[hibernate-commits] Hibernate SVN: r16500 - in core/branches/antlr3: src/main/antlr3/org/hibernate/sql/ast/origin/ordering and 7 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri May 1 16:26:16 EDT 2009


Author: steve.ebersole at jboss.com
Date: 2009-05-01 16:26:15 -0400 (Fri, 01 May 2009)
New Revision: 16500

Added:
   core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java
   core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java
   core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
Removed:
   core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java
   core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
Modified:
   core/branches/antlr3/pom.xml
   core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g
   core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g
   core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java
   core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java
   core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg
   core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java
   core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java
Log:
Initial working versions of order-by processing using antlr3+stringtemplate

Modified: core/branches/antlr3/pom.xml
===================================================================
--- core/branches/antlr3/pom.xml	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/pom.xml	2009-05-01 20:26:15 UTC (rev 16500)
@@ -186,17 +186,18 @@
             <plugin>
                 <groupId>org.antlr</groupId>
                 <artifactId>antlr3-maven-plugin</artifactId>
-                <version>3.1.3-steve</version>
+                <version>3.1.4-SNAPSHOT</version>
                 <configuration>
                 </configuration>
                 <executions>
                     <execution>
+                        <!-- execution to generate "source grammars" -->
                         <goals>
                             <goal>antlr</goal>
-                            <goal>gunit</goal>
                         </goals>
                     </execution>
                     <execution>
+                        <!-- execution to generate "test grammars" -->
                         <id>test-grammar-processing</id>
                         <phase>generate-test-sources</phase>
                         <goals>
@@ -211,6 +212,12 @@
                 </executions>
             </plugin>
 
+            <plugin>
+                <groupId>org.antlr</groupId>
+                <artifactId>maven-gunit-plugin</artifactId>
+                <version>3.1.4-SNAPSHOT</version>
+            </plugin>
+
         </plugins>
     </build>
 

Modified: core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g
===================================================================
--- core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/origin/ordering/OrderByParser.g	2009-05-01 20:26:15 UTC (rev 16500)
@@ -1,9 +1,10 @@
 parser grammar OrderByParser;
 
 options {
-	tokenVocab=HQLLexer;
-	output=AST;
-	ASTLabelType=CommonTree;
+	tokenVocab = HQLLexer;
+	output = AST;
+	TokenLabelType = CommonToken;
+	ASTLabelType = CommonTree;
 }
 
 @parser::header {
@@ -82,7 +83,7 @@
         throw new UnsupportedOperationException( "must be overridden!" );
     }
 
-	private boolean validateSoftKeyword(String text) {
+    private boolean validateSoftKeyword(String text) {
 		return validateLT(1, text);
 	}
 
@@ -107,37 +108,38 @@
 /**
  * Main recognition rule for this grammar
  */
-orderByFragment :
-    sortSpecification ( COMMA sortSpecification )*
+orderByFragment
+    : sortSpecification ( COMMA sortSpecification )*
         -> ^( ORDER_BY sortSpecification+ )
-;
+    ;
 
 
 /**
  * Reconition rule for what ANSI SQL terms the <tt>sort specification</tt>.  These are the atomic elements of the
  * <tt>ORDER BY</tt> list pieces.
  */
-sortSpecification :
-    sortKey collationSpecification? orderingSpecification?
+sortSpecification
+    : sortKey collationSpecification? orderingSpecification?
         -> ^( SORT_SPEC sortKey collationSpecification? orderingSpecification? )
-;
+    ;
 
 
 /**
  * Reconition rule for what ANSI SQL terms the <tt>sort key</tt> which is the expression (column, function, etc) upon
  * which to base the sorting.
  */
-sortKey :
-    expression
-;
+sortKey
+    : expression
+    ;
 
 /**
  * Reconition rule what this grammar recognizes as valid <tt>sort key</tt>.
  */
 expression
-    : QUOTED_IDENTIFIER -> ^( COLUMN[$QUOTED_IDENTIFIER] ALIAS_REF[Template.TEMPLATE] QUOTED_IDENTIFIER[$QUOTED_IDENTIFIER] )
+    : QUOTED_IDENTIFIER -> ^( COLUMN ALIAS_REF[Template.TEMPLATE] QUOTED_IDENTIFIER[$QUOTED_IDENTIFIER] )
     // we treat the so-called standard functions differently because they are handled differently by the HQL lexer which we also use here...
     | standardFunction
+    | literal
     // not identDotIdentStructure because we dont want QUOTED_IDENTIFIERs is here
     | ( IDENTIFIER ( DOT IDENTIFIER )* LEFT_PAREN ) => generalFunction
     // otherwise we fully expect a dot-identifier series, and then we just need to decode the semantic of that structure
@@ -191,7 +193,7 @@
 
 castFunction
 	: cast_keyword LEFT_PAREN expression as_keyword dataType RIGHT_PAREN
-	    -> ^( FUNCTION[$cast_keyword.start,$cast_keyword.text] expression as_keyword dataType )
+	    -> ^( cast_keyword expression dataType )
 	;
 
 fragment
@@ -201,17 +203,18 @@
 
 concatFunction
 	: concat_keyword LEFT_PAREN expression ( COMMA expression )+ RIGHT_PAREN
-	    -> ^( FUNCTION[$concat_keyword.start,$concat_keyword.text] expression+ )
+	    -> ^( concat_keyword expression+ )
 	;
 
 substringFunction
 	: substring_keyword LEFT_PAREN expression COMMA expression ( COMMA expression)? RIGHT_PAREN
-	    -> ^( FUNCTION[$substring_keyword.start,$substring_keyword.text] expression+ )
+	    -> ^( substring_keyword expression+ )
 	;
 
 trimFunction
+    // todo : dont like the creation of subtree(s) for the operands in the trimOperands rule
 	: trim_keyword LEFT_PAREN trimOperands RIGHT_PAREN
-	    -> ^( FUNCTION[$trim_keyword.start,$trim_keyword.text] trimOperands )
+	    -> ^( trim_keyword trimOperands )
 	;
 
 fragment
@@ -220,106 +223,117 @@
 k=2;
 }
 @init {boolean hasSecondExpression = false;}
-	:	trimSpecification from_keyword expression -> ^(trimSpecification STRING_LITERAL[" "] expression)
-	|	trimSpecification expression from_keyword expression -> ^(trimSpecification expression+)
-	|	from_keyword expression -> ^(BOTH STRING_LITERAL[" "] expression)
-	|	cn=expression ( from_keyword expression {hasSecondExpression = true;} )?
-		-> {hasSecondExpression}? ^(BOTH expression+)
-		-> ^(BOTH STRING_LITERAL[" "] $cn)
+	: trimSpecification from_keyword expression
+	    -> ^( trimSpecification STRING_LITERAL["' '"] expression)
+	| trimSpecification expression from_keyword expression
+	    -> ^(trimSpecification expression+)
+	| from_keyword expression
+	    -> ^(BOTH STRING_LITERAL["' '"] expression)
+	| cn=expression ( from_keyword expression {hasSecondExpression = true;} )?
+	    -> {hasSecondExpression}? ^(BOTH expression+)
+		-> ^(BOTH STRING_LITERAL["' '"] $cn)
 	;
 
 fragment
 trimSpecification
-	:	leading_keyword
-	|	trailing_keyword
-	|	both_keyword
+	: leading_keyword
+	| trailing_keyword
+	| both_keyword
 	;
 
 upperFunction
 	: upper_keyword LEFT_PAREN expression RIGHT_PAREN
-	    -> ^( FUNCTION[$upper_keyword.start,$upper_keyword.text] expression )
+	    -> ^( upper_keyword expression )
 	;
 
 lowerFunction
 	: lower_keyword LEFT_PAREN expression RIGHT_PAREN
-	    -> ^( FUNCTION[$lower_keyword.start,$lower_keyword.text] expression )
+	    -> ^( lower_keyword expression )
 	;
 
 lengthFunction
 	: length_keyword LEFT_PAREN expression RIGHT_PAREN
-	    -> ^( FUNCTION[$length_keyword.start,$length_keyword.text] expression )
+	    -> ^( length_keyword expression )
 	;
 
 locateFunction
 	: locate_keyword LEFT_PAREN expression COMMA expression ( COMMA expression )? RIGHT_PAREN
-	    -> ^( FUNCTION[$locate_keyword.start,$locate_keyword.text] expression+ )
+	    -> ^( locate_keyword expression+ )
 	;
 
 absFunction
-	:	abs_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+	: abs_keyword LEFT_PAREN expression RIGHT_PAREN
+	    -> ^( abs_keyword expression )
 	;
 
 sqrtFunction
-	:	sqrt_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+	: sqrt_keyword LEFT_PAREN expression RIGHT_PAREN
+	    -> ^( sqrt_keyword expression )
 	;
 
 modFunction
-	:	mod_keyword^ LEFT_PAREN! expression COMMA! expression RIGHT_PAREN!
+	: mod_keyword LEFT_PAREN expression COMMA expression RIGHT_PAREN
+	    -> ^( mod_keyword expression+ )
 	;
 
 currentDateFunction
-	:	current_date_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+	: current_date_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
 	;
 
 currentTimeFunction
-	:	current_time_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+	: current_time_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
 	;
 
 currentTimestampFunction
-	:	current_timestamp_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
+	: current_timestamp_keyword ( LEFT_PAREN! RIGHT_PAREN! )?
 	;
 
 extractFunction
-	:	extract_keyword^ LEFT_PAREN! extractField from_keyword! expression RIGHT_PAREN!
+	: extract_keyword LEFT_PAREN extractField from_keyword expression RIGHT_PAREN
+	    -> ^( extract_keyword extractField expression )
 	;
 
 extractField
-	:	datetimeField
-	|	timeZoneField
+	: datetimeField
+	| timeZoneField
 	;
 
 datetimeField
-	:	nonSecondDatetimeField
-	|	second_keyword
+	: nonSecondDatetimeField
+	| second_keyword
 	;
 
 nonSecondDatetimeField
-	:	year_keyword
-	|	month_keyword
-	|	day_keyword
-	|	hour_keyword
-	|	minute_keyword
+	: year_keyword
+	| month_keyword
+	| day_keyword
+	| hour_keyword
+	| minute_keyword
 	;
 
 timeZoneField
-	:	timezone_hour_keyword
-	|	timezone_minute_keyword
+	: timezone_hour_keyword
+	| timezone_minute_keyword
 	;
 
 positionFunction
-	:	position_keyword^ LEFT_PAREN! expression in_keyword! expression RIGHT_PAREN!
+	: position_keyword LEFT_PAREN expression in_keyword expression RIGHT_PAREN
+	    -> ^( position_keyword expression+ )
 	;
 
 charLengthFunction
-	:	character_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+	: character_length_keyword LEFT_PAREN expression RIGHT_PAREN
+	    -> ^( character_length_keyword expression )
 	;
 
 octetLengthFunction
-	:	octet_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+	: octet_length_keyword LEFT_PAREN expression RIGHT_PAREN
+	    -> ^( octet_length_keyword expression )
 	;
 
 bitLengthFunction
-	:	bit_length_keyword^ LEFT_PAREN! expression RIGHT_PAREN!
+	: bit_length_keyword LEFT_PAREN expression RIGHT_PAREN
+	    -> ^( bit_length_keyword expression )
 	;
 
 
@@ -335,10 +349,9 @@
 /**
  * Recognized function parameters.
  */
-functionArgument :
-    expression
-    | literal
-;
+functionArgument
+    : expression
+    ;
 
 literal
 	:	numeric_literal
@@ -361,30 +374,30 @@
 collationSpecification!
     : collateKeyword collationName
         -> COLLATE[$collateKeyword.start,$collationName.text]
-;
+    ;
 
-collateKeyword :
-    {(validateSoftKeyword("collate"))}?=>  id=IDENTIFIER
-		->	COLLATE[$id]
-;
+collateKeyword
+    : {(validateSoftKeyword("collate"))}?=>  id=IDENTIFIER
+        -> COLLATE[$id]
+    ;
 
 /**
  * The collation name wrt {@link #collationSpecification}.  Namely, the character-set.
  */
-collationName :
-    IDENTIFIER
-;
+collationName
+    : IDENTIFIER
+    ;
 
 /**
  * Reconition rule for what ANSI SQL terms the <tt>ordering specification</tt>; <tt>ASCENDING</tt> or
  * <tt>DESCENDING</tt>.
  */
-orderingSpecification! :
-    ascending_keyword
+orderingSpecification!
+    : ascending_keyword
         -> ORDER_SPEC[$ascending_keyword.start,$ascending_keyword.text]
     | descending_keyword
         -> ORDER_SPEC[$descending_keyword.start,$descending_keyword.text]
-;
+    ;
 
 
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Modified: core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g
===================================================================
--- core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/main/antlr3/org/hibernate/sql/ast/render/OrderByRenderer.g	2009-05-01 20:26:15 UTC (rev 16500)
@@ -38,143 +38,237 @@
  * entirety.
  */
 package org.hibernate.sql.ast.render;
+
+import org.antlr.stringtemplate.StringTemplate;
 }
 
+ at members {
+    protected StringTemplate quotedIdentifier(CommonToken recognizedIdentifierToken) {
+        return new StringTemplate( getTemplateLib(), recognizedIdentifierToken.getText() );
+    }
+
+    protected StringTemplate basicFunctionTemplate(String functionName, List arguments) {
+        return new StringTemplate(
+                getTemplateLib(),
+                "<name>(<arguments; separator=\", \">)",
+                new STAttrMap().put( "name", functionName ).put( "arguments", arguments )
+        );
+    }
+
+    protected StringTemplate castFunctionTemplate(StringTemplate expression, String  datatype) {
+        return new StringTemplate(
+                getTemplateLib(),
+                "cast(<expression> as <datatype>)",
+                new STAttrMap().put( "expression", expression )
+                        .put( "datatype", datatype )
+        );
+    }
+
+    protected StringTemplate trimFunctionTemplate(StringTemplate trimSpec, StringTemplate trimCharacter, StringTemplate trimSource) {
+        return new StringTemplate(
+                getTemplateLib(),
+                "trim(<trimSpec> <trimCharacter> from <trimSource>)",
+                new STAttrMap().put( "trimSpec", trimSpec )
+                        .put( "trimCharacter", trimCharacter )
+                        .put( "trimSource", trimSource )
+        );
+    }
+
+    protected StringTemplate extractFunctionTemplate(StringTemplate extractField, StringTemplate expression) {
+        return new StringTemplate(
+                getTemplateLib(),
+                "extract(<extractField> from <expression>)",
+                new STAttrMap().put( "extractField", extractField )
+                        .put( "expression", expression )
+        );
+    }
+
+    protected StringTemplate positionFunctionTemplate(StringTemplate searchString, StringTemplate sourceString) {
+        return new StringTemplate(
+                getTemplateLib(),
+                "position(<searchString> in <sourceString>)",
+                new STAttrMap().put( "searchString", searchString )
+                        .put( "sourceString", sourceString )
+        );
+    }
+}
+
 // todo : merge with 'full sql rendering' grammar
 //    this is currently just a temporary subset grammar limited to the needs of mapping-defined order-by fragments
 
-orderByClause
+orderByFragment
     : ^( ORDER_BY sortSpecs+=sortSpecification+ )
-        ->  orderByClause( sortSpecifications={$sortSpecs} )
+        ->  orderByFragment( sortSpecifications={$sortSpecs} )
     ;
 
 sortSpecification
-    : ^( SORT_SPEC sortKey COLLATE? ORDER_SPEC? )
+    : ^( SORT_SPEC sortKey collationSpecification? ORDER_SPEC? )
         ->  sortSpecification(
                     sortKey={$sortKey.st},
-                    collationSpecification={$COLLATE.text},
+                    collationSpecification={$collationSpecification.st},
                     orderingSpecification={$ORDER_SPEC.text}
             )
     ;
 
+collationSpecification
+    : COLLATE -> {%{"collate " + $COLLATE.text}}
+    ;
+
 sortKey
-    : expression
+    : expression -> {$expression.st}
     ;
 
 expression
-    : column
-    | function
+    : valueExpression -> {$valueExpression.st}
     ;
 
+valueExpression
+    : column -> {$column.st}
+    | function -> {$function.st}
+    | literal -> {$literal.st}
+    | rowValueConstructor -> {$rowValueConstructor.st}
+    ;
+
+characterValueExpression
+    : valueExpression -> {$valueExpression.st}
+    ;
+
+numericValueExpression
+    : valueExpression -> {$valueExpression.st}
+    ;
+
 column
     : ^( COLUMN ALIAS_REF identifier )
-        -> column( qualifier={$ALIAS_REF.text}, name={$identifier.text} )
+        -> column( qualifier={$ALIAS_REF.text}, name={$identifier.st} )
     ;
 
 identifier
-    : IDENTIFIER
-    | QUOTED_IDENTIFIER
+    : IDENTIFIER -> {%{$IDENTIFIER.text}}
+    | QUOTED_IDENTIFIER -> { quotedIdentifier( (CommonToken) $QUOTED_IDENTIFIER.getToken() ) }
     ;
 
+rowValueConstructor
+    : ^( VECTOR_EXPR expressions+=expression+ )
+        -> template( expressions={$expressions} ) "(<expressions; separator=\", \">)"
+    ;
+
 function
-    : functionFunction
-//	| castFunction
-//	| concatFunction
-//	| substringFunction
-//	| trimFunction
-//	| upperFunction
-//	| lowerFunction
-//	| lengthFunction
-//	| locateFunction
-	| absFunction
-	| sqrtFunction
-	| modFunction
-	| currentDateFunction
-	| currentTimeFunction
-	| currentTimestampFunction
-	| extractFunction
-	| positionFunction
-	| charLengthFunction
-	| octetLengthFunction
-	| bitLengthFunction
+    : functionFunction -> {$functionFunction.st}
+	| castFunction -> {$castFunction.st}
+	| concatFunction -> {$concatFunction.st}
+	| substringFunction -> {$substringFunction.st}
+	| trimFunction -> {$trimFunction.st}
+	| upperFunction -> {$upperFunction.st}
+	| lowerFunction -> {$lowerFunction.st}
+	| lengthFunction -> {$lengthFunction.st}
+	| locateFunction -> {$locateFunction.st}
+	| absFunction -> {$absFunction.st}
+	| sqrtFunction -> {$sqrtFunction.st}
+	| modFunction -> {$modFunction.st}
+	| currentDateFunction -> {$currentDateFunction.st}
+	| currentTimeFunction -> {$currentTimeFunction.st}
+	| currentTimestampFunction -> {$currentTimestampFunction.st}
+	| extractFunction -> {$extractFunction.st}
+	| positionFunction -> {$positionFunction.st}
+	| charLengthFunction -> {$charLengthFunction.st}
+	| octetLengthFunction -> {$octetLengthFunction.st}
+	| bitLengthFunction -> {$bitLengthFunction.st}
     ;
 
 functionFunction
     : ^( FUNCTION args+=functionArgument* )
-        -> basicFunction( name={$FUNCTION.text}, args={$args} )
+        -> { basicFunctionTemplate( $FUNCTION.text, $args ) }
     ;
 
 functionArgument
-    : expression
-    | literal
+    : expression -> {$expression.st}
 ;
 
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// rewritten in parser as ^( FUNCTION ... ) structures
-//castFunction
-//	: ^( CAST valueExpression IDENTIFIER )
-//	;
-//
-//concatFunction
-//	: ^( CONCAT valueExpression+ )
-//	;
-//
-//substringFunction
-//	:	^(SUBSTRING characterValueExpression numericValueExpression numericValueExpression?)
-//	;
-//
-//trimFunction
-//	:	^(TRIM trimOperands)
-//	;
-//
-//trimOperands
-//	:	^((LEADING|TRAILING|BOTH) characterValueExpression characterValueExpression)
-//	;
-//
-//upperFunction
-//	:	^(UPPER characterValueExpression)
-//	;
-//
-//lowerFunction
-//	:	^(LOWER characterValueExpression)
-//	;
-//
-//lengthFunction
-//	:	^(LENGTH characterValueExpression)
-//	;
-//
-//locateFunction
-//	:	^(LOCATE characterValueExpression characterValueExpression numericValueExpression?)
-//	;
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+castFunction
+    : ^( CAST valueExpression IDENTIFIER )
+        -> { castFunctionTemplate( $valueExpression.st, $IDENTIFIER.text ) }
+    ;
 
-absFunction
-	:	^( ABS expression )
+concatFunction
+	: ^( CONCAT args+=valueExpression+ )
+        -> { basicFunctionTemplate( $CONCAT.text, $args ) }
 	;
 
+substringFunction
+    : ^( SUBSTRING args+=characterValueExpression args+=numericValueExpression args+=numericValueExpression? )
+        -> { basicFunctionTemplate( $SUBSTRING.text, $args ) }
+    ;
+
+trimFunction
+    : ^( TRIM ^( trimSpec trimChar trimSource ) )
+        -> { trimFunctionTemplate( $trimSpec.st, $trimChar.st, $trimSource.st ) }
+    ;
+
+trimSpec
+    : LEADING   -> {%{"leading"}}
+    | TRAILING  -> {%{"trailing"}}
+    | BOTH      -> {%{"both"}}
+    ;
+
+trimChar
+    : characterValueExpression -> { $characterValueExpression.st }
+    ;
+
+trimSource
+    : characterValueExpression -> { $characterValueExpression.st }
+    ;
+
+upperFunction
+    : ^( UPPER args+=characterValueExpression )
+        -> { basicFunctionTemplate( $UPPER.text, $args ) }
+    ;
+
+lowerFunction
+    : ^( LOWER args+=characterValueExpression )
+        -> { basicFunctionTemplate( $LOWER.text, $args ) }
+    ;
+
+lengthFunction
+    : ^( LENGTH args+=characterValueExpression )
+        -> { basicFunctionTemplate( $LENGTH.text, $args ) }
+    ;
+
+locateFunction
+    : ^( LOCATE args+=characterValueExpression args+=characterValueExpression args+=numericValueExpression? )
+        -> { basicFunctionTemplate( $LOCATE.text, $args ) }
+    ;
+
+absFunction
+    : ^( ABS args+=expression )
+        -> { basicFunctionTemplate( $ABS.text, $args ) }
+    ;
+
 sqrtFunction
-	:	^(SQRT expression)
-	;
+    : ^( SQRT args+=expression )
+        -> { basicFunctionTemplate( $SQRT.text, $args ) }
+    ;
 
 modFunction
-	:	^(MOD expression expression)
-	;
+    : ^( MOD args+=expression args+=expression )
+        -> { basicFunctionTemplate( $MOD.text, $args ) }
+    ;
 
 currentDateFunction
-	:	CURRENT_DATE
-	;
+    : CURRENT_DATE -> { basicFunctionTemplate( $CURRENT_DATE.text, null ) }
+    ;
 
 currentTimeFunction
-	:	CURRENT_TIME
-	;
+    : CURRENT_TIME -> { basicFunctionTemplate( $CURRENT_TIME.text, null ) }
+    ;
 
 currentTimestampFunction
-	:	CURRENT_TIMESTAMP
-	;
+    : CURRENT_TIMESTAMP -> { basicFunctionTemplate( $CURRENT_TIMESTAMP.text, null ) }
+    ;
 
 extractFunction
-	:	^(EXTRACT extractField expression)
-	;
+    : ^( EXTRACT extractField expression )
+        -> { extractFunctionTemplate( $extractField.st, $expression.st ) }
+    ;
 
 extractField
 	:	datetimeField
@@ -182,46 +276,50 @@
 	;
 
 datetimeField
-	:	YEAR
-	|	MONTH
-	|	DAY
-	|	HOUR
-	|	MINUTE
-	|	SECOND
+	:	YEAR    -> {%{"year"}}
+	|	MONTH   -> {%{"month"}}
+	|	DAY     -> {%{"day"}}
+	|	HOUR    -> {%{"hour"}}
+	|	MINUTE  -> {%{"minute"}}
+	|	SECOND  -> {%{"second"}}
 	;
 
 timeZoneField
-	:	TIMEZONE_HOUR
-	|	TIMEZONE_MINUTE
+	:	TIMEZONE_HOUR   -> {%{"timezone_hour"}}
+	|	TIMEZONE_MINUTE -> {%{"timezone_minute"}}
 	;
 
 positionFunction
-	:	^(POSITION expression expression)
-	;
+    : ^( POSITION s1=expression s2=expression )
+        -> { positionFunctionTemplate( $s1.st, $s2.st ) }
+    ;
 
 charLengthFunction
-	:	^(CHARACTER_LENGTH expression)
-	;
+    : ^( CHARACTER_LENGTH args+=expression )
+         -> { basicFunctionTemplate( $CHARACTER_LENGTH.text, $args ) }
+    ;
 
 octetLengthFunction
-	:	^(OCTET_LENGTH expression)
-	;
+    : ^( OCTET_LENGTH args+=expression )
+         -> { basicFunctionTemplate( $OCTET_LENGTH.text, $args ) }
+    ;
 
 bitLengthFunction
-	:	^(BIT_LENGTH expression)
-	;
+    : ^( BIT_LENGTH args+=expression )
+         -> { basicFunctionTemplate( $BIT_LENGTH.text, $args ) }
+    ;
 
 literal
-	:	numeric_literal
-	|	HEX_LITERAL
-	|	OCTAL_LITERAL
-	|	CHARACTER_LITERAL
-	|	STRING_LITERAL
+	:	numeric_literal -> {$numeric_literal.st}
+	|	HEX_LITERAL -> {%{$HEX_LITERAL.text}}
+	|	OCTAL_LITERAL -> {%{$OCTAL_LITERAL.text}}
+	|	CHARACTER_LITERAL -> {%{$CHARACTER_LITERAL.text}}
+	|	STRING_LITERAL -> {%{$STRING_LITERAL.text}}
 	;
 
 numeric_literal
-	:	INTEGER_LITERAL
-	|	DECIMAL_LITERAL
-	|	FLOATING_POINT_LITERAL
+	:	INTEGER_LITERAL -> {%{$INTEGER_LITERAL.text}}
+	|	DECIMAL_LITERAL -> {%{$DECIMAL_LITERAL.text}}
+	|	FLOATING_POINT_LITERAL -> {%{$FLOATING_POINT_LITERAL.text}}
 	;
 

Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/common/HibernateToken.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -58,12 +58,23 @@
 	 */
 	public HibernateToken(Token oldToken) {
 		super( oldToken );
-		if ( null != oldToken
-				&& ( oldToken.getClass().equals( CommonToken.class ) || oldToken
-				.getClass().equals( HibernateToken.class ) ) ) {
-			start = ( ( CommonToken ) oldToken ).getStartIndex();
-			stop = ( ( CommonToken ) oldToken ).getStopIndex();
+		if ( null != oldToken && CommonToken.class.isInstance( oldToken ) ) {
+			setStartIndex( ( ( CommonToken ) oldToken ).getStartIndex() );
+			setStopIndex( ( ( CommonToken ) oldToken ).getStopIndex() );
 		}
 	}
 
+	/**
+	 * Constructor form used to track origination position information via the passed
+	 * 'oldToken' param, but to utilize a new token type and text.
+	 *
+	 * @param oldToken The original token type (used for position tracking info).
+	 * @param type The type of the new (this) token
+	 * @param text The test of the new (this) token.
+	 */
+	public HibernateToken(Token oldToken, int type, String text) {
+		this( oldToken );
+		setType( type );
+		setText( text );
+	}
 }

Copied: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java (from rev 16468, core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java)
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java	                        (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByParser.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -0,0 +1,117 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ *
+ */
+package org.hibernate.sql.ast.origin.ordering;
+
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.tree.CommonTree;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.sql.ast.common.HibernateTree;
+import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
+import org.hibernate.sql.Template;
+
+/**
+ * Extension of the Antlr-generated parser for the purpose of adding our custom parsing behavior.
+ *
+ * @author Steve Ebersole
+ */
+public class ContextualOrderByParser extends OrderByParser {
+	private static final Logger log = LoggerFactory.getLogger( ContextualOrderByParser.class );
+	private final TranslationContext context;
+
+	private final String openQuoteChar;
+	private final String closeQuoteChar;
+
+	public ContextualOrderByParser(TokenStream lexer, TranslationContext context) {
+		super( lexer );
+		this.context = context;
+
+		this.openQuoteChar = Character.toString( context.getDialect().openQuote() );
+		this.closeQuoteChar = Character.toString( context.getDialect().closeQuote() );
+	}
+
+	@Override
+	protected boolean isFunctionName(String text) {
+		log.trace( "Checking function name [" + text + "]" );
+		return context.getSqlFunctionRegistry().hasFunction( text );
+	}
+
+	@Override
+	protected boolean isPropertyName(String text) {
+		log.trace( "Checking property name [" + text + "]" );
+		try {
+			return context.getColumnMapper().map( text ) != null;
+		}
+		catch ( Throwable t ) {
+			return false;
+		}
+	}
+
+	@Override
+	protected CommonTree buildPropertyColumns(CommonTree propertyTree) {
+		final String text = extractPropertyName( propertyTree );
+		String[] columns = context.getColumnMapper().map( text );
+		if ( columns.length == 1 ) {
+			return buildColumn( columns[0] );
+		}
+		else {
+			HibernateTree vector = new HibernateTree( VECTOR_EXPR );
+			for ( String column : columns ) {
+				vector.addChild( buildColumn( column ) );
+			}
+			return vector;
+		}
+	}
+
+	private CommonTree buildColumn(String columnName) {
+		// ugh
+		HibernateTree columnNameNode;
+		if ( columnName.startsWith( openQuoteChar ) && columnName.endsWith( closeQuoteChar ) ) {
+			columnName = columnName.substring( 1, columnName.length() - 1 );
+			columnNameNode = new HibernateTree( QUOTED_IDENTIFIER, columnName );
+		}
+		else {
+			columnNameNode = new HibernateTree( IDENTIFIER, columnName );
+		}
+
+		HibernateTree tree = new HibernateTree( COLUMN );
+		tree.addChild( new HibernateTree( ALIAS_REF, Template.TEMPLATE ) );
+		tree.addChild( columnNameNode );
+
+		return tree;
+	}
+
+	private String extractPropertyName(CommonTree propertyTree) {
+		if ( HQLLexer.DOT == propertyTree.getType() ) {
+			return extractPropertyName( ( CommonTree ) propertyTree.getChild( 0 ) ) + "." +
+					extractPropertyName( ( CommonTree ) propertyTree.getChild( 1 ) );
+		}
+		else {
+			// assume IDENTIFIER... assertion?
+			return propertyTree.getText();
+		}
+	}
+}

Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java	                        (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/ContextualOrderByRenderer.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.origin.ordering;
+
+import java.util.List;
+
+import org.antlr.runtime.CommonToken;
+import org.antlr.runtime.tree.TreeNodeStream;
+import org.antlr.stringtemplate.StringTemplate;
+import org.antlr.stringtemplate.StringTemplateGroup;
+
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.sql.ast.render.OrderByRenderer;
+
+/**
+ * Subclassing of the Antlr-generated renderer to apply contextual semantics.
+ *
+ * @author Steve Ebersole
+ */
+public class ContextualOrderByRenderer extends OrderByRenderer {
+	private final TranslationContext translationContext;
+
+	private final StringTemplate quotedIdentifierTemplate;
+
+	private final StringTemplate basicFunctionNoArgsWithoutParens;
+	private final StringTemplate basicFunctionNoArgsWithParens;
+	private final StringTemplate basicFunctionWithArgs;
+
+	private final StringTemplate castFunction;
+	private final StringTemplate trimfunction;
+
+	public ContextualOrderByRenderer(
+			TreeNodeStream input,
+			TranslationContext translationContext,
+			StringTemplateGroup stringTemplateGroup) {
+		super( input );
+		setTemplateLib( stringTemplateGroup );
+		this.translationContext = translationContext;
+
+		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        // todo : eventually get these directly from the Dialect
+		quotedIdentifierTemplate = buildQuotedIdentiferTemplate();
+
+		basicFunctionNoArgsWithoutParens = new StringTemplate( getTemplateLib(), "<name>" );
+		basicFunctionNoArgsWithoutParens.defineFormalArgument( "name" );
+
+		basicFunctionNoArgsWithParens = new StringTemplate( getTemplateLib(), "<name>()" );
+		basicFunctionNoArgsWithParens.defineFormalArgument( "name" );
+
+		basicFunctionWithArgs = new StringTemplate( getTemplateLib(), "<name>(<arguments; separator=\", \">)" );
+		basicFunctionWithArgs.defineFormalArgument( "name" );
+		basicFunctionWithArgs.defineFormalArgument( "arguments" );
+
+		castFunction = new StringTemplate( getTemplateLib(), "cast(<expression> as <datatype>)" );
+		castFunction.defineFormalArgument( "expression" );
+		castFunction.defineFormalArgument( "datatype" );
+
+		trimfunction = new StringTemplate( getTemplateLib(), "trim(<trimSpec> <trimCharacter> from <trimSource >)" );
+		trimfunction.defineFormalArgument( "trimSpec" );
+		trimfunction.defineFormalArgument( "trimCharacter" );
+		trimfunction.defineFormalArgument( "trimSource" );
+		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+	}
+
+	@Override
+    protected StringTemplate quotedIdentifier(CommonToken recognizedIdentifierToken) {
+        String identifierText = recognizedIdentifierToken.getText();
+        if ( identifierText.startsWith( "`" ) ) {
+            identifierText = identifierText.substring( 1, identifierText.length() - 1 );
+            StringTemplate template = quotedIdentifierTemplate.getInstanceOf();
+            template.setAttribute( "identifier", identifierText );
+			return template;
+        }
+        else {
+            return super.quotedIdentifier( recognizedIdentifierToken );
+        }
+    }
+
+    private StringTemplate buildQuotedIdentiferTemplate() {
+		String templateContent = translationContext.getDialect().openQuote() +
+				"<identifier>" +
+				translationContext.getDialect().closeQuote();
+        StringTemplate template = new StringTemplate( getTemplateLib(), templateContent );
+        template.defineFormalArgument( "identifier" );
+        return template;
+    }
+
+	@Override
+	protected StringTemplate basicFunctionTemplate(String functionName, List arguments) {
+		if ( arguments == null || arguments.isEmpty() ) {
+			SQLFunction sqlFunction = translationContext.getSqlFunctionRegistry().findSQLFunction( "functionName" );
+			StringTemplate template = sqlFunction.hasParenthesesIfNoArguments()
+					? basicFunctionNoArgsWithParens
+					: basicFunctionNoArgsWithoutParens;
+			template.setAttribute( "name", functionName );
+			return template;
+		}
+		else {
+			StringTemplate template = basicFunctionWithArgs.getInstanceOf();
+			template.setAttribute( "name", functionName );
+			template.setAttribute( "arguments", arguments );
+			return template;
+		}
+	}
+
+	@Override
+	protected StringTemplate castFunctionTemplate(StringTemplate expression, String datatype) {
+		StringTemplate template = castFunction.getInstanceOf();
+		template.setAttribute( "expression", expression );
+		template.setAttribute( "datatype", datatype );
+		return template;
+	}
+
+	@Override
+    protected StringTemplate trimFunctionTemplate(StringTemplate trimSpec, StringTemplate trimCharacter, StringTemplate trimSource) {
+		StringTemplate template = trimfunction.getInstanceOf();
+		template.setAttribute( "trimSpec", trimSpec );
+		template.setAttribute( "trimCharacter", trimCharacter );
+		template.setAttribute( "trimSource", trimSource );
+		return template;
+    }
+}

Deleted: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentParser.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -1,109 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- *
- */
-package org.hibernate.sql.ast.origin.ordering;
-
-import org.antlr.runtime.TokenStream;
-import org.antlr.runtime.tree.CommonTree;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.sql.ast.common.HibernateTree;
-import org.hibernate.sql.Template;
-
-/**
- * Extension of the Antlr-generated parser for the purpose of adding our custom parsing behavior.
- *
- * @author Steve Ebersole
- */
-public class OrderByFragmentParser extends OrderByParser {
-	private static final Logger log = LoggerFactory.getLogger( OrderByFragmentParser.class );
-	private final TranslationContext context;
-
-	private final String openQuoteChar;
-	private final String closeQuoteChar;
-
-	public OrderByFragmentParser(TokenStream lexer, TranslationContext context) {
-		super( lexer );
-		this.context = context;
-
-		this.openQuoteChar = Character.toString( context.getDialect().openQuote() );
-		this.closeQuoteChar = Character.toString( context.getDialect().closeQuote() );
-	}
-
-	@Override
-	protected boolean isFunctionName(String text) {
-		log.trace( "Checking function name [" + text + "]" );
-		return context.getSqlFunctionRegistry().hasFunction( text );
-	}
-
-	@Override
-	protected boolean isPropertyName(String text) {
-		log.trace( "Checking property name [" + text + "]" );
-		try {
-			return context.getColumnMapper().map( text ) != null;
-		}
-		catch ( Throwable t ) {
-			return false;
-		}
-	}
-
-	@Override
-	protected CommonTree buildPropertyColumns(CommonTree propertyTree) {
-		final String text = extractPropertyName( propertyTree );
-		String[] columns = context.getColumnMapper().map( text );
-		if ( columns.length == 1 ) {
-			return buildColumn( columns[0] );
-		}
-		else {
-			HibernateTree vector = new HibernateTree( VECTOR_EXPR );
-			for ( String column : columns ) {
-				vector.addChild( buildColumn( column ) );
-			}
-			return vector;
-		}
-	}
-
-	private CommonTree buildColumn(String columnName) {
-		// ugh
-		HibernateTree columnNameNode;
-		if ( columnName.startsWith( openQuoteChar ) && columnName.endsWith( closeQuoteChar ) ) {
-			columnName = columnName.substring( 1, columnName.length() - 1 );
-			columnNameNode = new HibernateTree( QUOTED_IDENTIFIER, columnName );
-		}
-		else {
-			columnNameNode = new HibernateTree( IDENTIFIER, columnName );
-		}
-
-		HibernateTree tree = new HibernateTree( COLUMN );
-		tree.addChild( new HibernateTree( ALIAS_REF, Template.TEMPLATE ) );
-		tree.addChild( columnNameNode );
-
-		return tree;
-	}
-
-	private String extractPropertyName(CommonTree propertyTree) {
-		return propertyTree.getText();
-	}
-}

Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/origin/ordering/OrderByFragmentTranslator.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -33,7 +33,12 @@
 
 import org.antlr.runtime.ANTLRStringStream;
 import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.RecognitionException;
 import org.antlr.runtime.tree.Tree;
+import org.antlr.runtime.tree.CommonTreeNodeStream;
+import org.antlr.stringtemplate.StringTemplateGroup;
+import org.antlr.stringtemplate.CommonGroupLoader;
+import org.antlr.stringtemplate.StringTemplateErrorListener;
 
 /**
  * A translator which coordinates translation of an <tt>order-by</tt> mapping.
@@ -58,13 +63,14 @@
 	 */
 	public String render(String fragment) {
 		HQLLexer lexer = new HQLLexer( new ANTLRStringStream( fragment ) );
-		OrderByFragmentParser parser = new OrderByFragmentParser( new CommonTokenStream( lexer ), context );
+		ContextualOrderByParser parser = new ContextualOrderByParser( new CommonTokenStream( lexer ), context );
+		Tree orderByTree;
 		try {
-            Tree tree = ( Tree ) parser.orderByFragment().getTree();
+            orderByTree = ( Tree ) parser.orderByFragment().getTree();
 
             if ( log.isTraceEnabled() ) {
                 TreePrinter printer = new TreePrinter( OrderByParser.class );
-                log.trace( printer.renderAsString( tree, "--- {order-by fragment} ---" ) );
+                log.trace( printer.renderAsString( orderByTree, "--- {order-by fragment} ---" ) );
             }
 		}
 		catch ( HibernateException e ) {
@@ -74,18 +80,29 @@
 			throw new HibernateException( "Unable to parse order-by fragment", t );
 		}
 
-//		OrderByFragmentRenderer renderer = new OrderByFragmentRenderer();
-//		try {
-//			renderer.orderByFragment( parser.getAST() );
-//		}
-//		catch ( HibernateException e ) {
-//			throw e;
-//		}
-//		catch ( Throwable t ) {
-//			throw new HibernateException( "Unable to render parsed order-by fragment", t );
-//		}
-//
-//		return renderer.getRenderedFragment();
-        return null;
+		// Load the string templates...
+		CommonGroupLoader groupLoader = new CommonGroupLoader(
+				"org/hibernate/sql/ast/template/",
+				new StringTemplateErrorListener() {
+					public void error(String s, Throwable throwable) {
+						throw new RuntimeException( s, throwable );
+					}
+
+					public void warning(String s) {
+						System.out.println( "GROUP-LOADER : " + s );
+					}
+				}
+		);
+		StringTemplateGroup.registerGroupLoader( groupLoader );
+		StringTemplateGroup stringTemplateGroup = groupLoader.loadGroup( "OrderBy" );
+		ContextualOrderByRenderer renderer = new ContextualOrderByRenderer( new CommonTreeNodeStream( orderByTree ), context, stringTemplateGroup );
+
+		try {
+			return renderer.orderByFragment().st.toString();
+		}
+		catch ( RecognitionException e ) {
+			throw new HibernateException( "Unable to render order-by fragment", e );
+		}
+
 	}
 }

Modified: core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg
===================================================================
--- core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/main/resources/org/hibernate/sql/ast/template/OrderBy.stg	2009-05-01 20:26:15 UTC (rev 16500)
@@ -1,26 +1,13 @@
 group OrderBy;
 
-
-orderByClause(sortSpecifications) ::= <<
-order by <orderByFragment(sortSpecifications)>
->>
-
 orderByFragment(sortSpecifications) ::= <<
 <sortSpecifications; separator=", ">
 >>
 
 sortSpecification(sortKey,collationSpecification,orderingSpecification) ::= <<
-<sortKey> <collationSpecification> <orderingSpecification>
+<[sortKey, collationSpecification, orderingSpecification]; separator=" ">
 >>
 
 column(qualifier,name) ::= <<
 <qualifier>.<name>
 >>
-
-function(name,arguments) ::= <<
-<name>(<arguments; separator=", ">)
->>
-
-noArgumentFunction(name) ::= <<
-<name>
->>
\ No newline at end of file

Modified: core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java
===================================================================
--- core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/test/java/org/hibernate/sql/TemplateTest.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -44,10 +44,7 @@
 public class TemplateTest extends TestCase {
 	private static final PropertyMapping PROPERTY_MAPPING = new PropertyMapping() {
 		public String[] toColumns(String propertyName) throws QueryException, UnsupportedOperationException {
-			if ( "sql".equals( propertyName ) ) {
-				return new String[] { "sql" };
-			}
-			else if ( "component".equals( propertyName ) ) {
+			if ( "component".equals( propertyName ) ) {
 				return new String[] { "comp_1", "comp_2" };
 			}
 			else if ( "component.prop1".equals( propertyName ) ) {
@@ -85,104 +82,152 @@
 
 	private static final SQLFunctionRegistry FUNCTION_REGISTRY = new SQLFunctionRegistry( DIALECT, Collections.EMPTY_MAP );
 
-    public void testParsing() {
+    public void testSQLReferences() {
         String fragment = "sql asc, sql desc";
         String template = doStandardRendering( fragment );
+
+        assertEquals( Template.TEMPLATE + ".sql asc, " + Template.TEMPLATE + ".sql desc", template );
     }
 
-//    public void testSQLReferences() {
-//        String fragment = "sql asc, sql desc";
-//        String template = doStandardRendering( fragment );
-//
-//        assertEquals( Template.TEMPLATE + ".sql asc, " + Template.TEMPLATE + ".sql desc", template );
-//    }
-//
-//    public void testQuotedSQLReferences() {
-//        String fragment = "`sql` asc, `sql` desc";
-//        String template = doStandardRendering( fragment );
-//
-//        assertEquals( Template.TEMPLATE + ".\"sql\" asc, " + Template.TEMPLATE + ".\"sql\" desc", template );
-//    }
-//
-//    public void testPropertyReference() {
-//		String fragment = "property asc, property desc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( Template.TEMPLATE + ".prop asc, " + Template.TEMPLATE + ".prop desc", template );
-//	}
-//
-//    public void testFunctionReference() {
-//		String fragment = "upper(sql) asc, lower(sql) desc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( "upper(" + Template.TEMPLATE + ".sql) asc, lower(" + Template.TEMPLATE + ".sql) desc", template );
-//	}
-//
-//	public void testQualifiedFunctionReference() {
-//		String fragment = "qual.upper(property) asc, qual.lower(property) desc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( "qual.upper(" + Template.TEMPLATE + ".prop) asc, qual.lower(" + Template.TEMPLATE + ".prop) desc", template );
-//	}
-//
-//	public void testDoubleQualifiedFunctionReference() {
-//		String fragment = "qual1.qual2.upper(property) asc, qual1.qual2.lower(property) desc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( "qual1.qual2.upper(" + Template.TEMPLATE + ".prop) asc, qual1.qual2.lower(" + Template.TEMPLATE + ".prop) desc", template );
-//	}
-//
-//	public void testFunctionWithPropertyReferenceAsParam() {
-//		String fragment = "upper(property) asc, lower(property) desc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( "upper(" + Template.TEMPLATE + ".prop) asc, lower(" + Template.TEMPLATE + ".prop) desc", template );
-//	}
-//
-//	public void testNestedFunctionReferences() {
-//		String fragment = "upper(lower(sql)) asc, lower(upper(sql)) desc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( "upper(lower(" + Template.TEMPLATE + ".sql)) asc, lower(upper(" + Template.TEMPLATE + ".sql)) desc", template );
-//	}
-//
-//	public void testComplexNestedFunctionReferences() {
-//		String fragment = "mod(mod(sql,2),3) asc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( "mod(mod(" + Template.TEMPLATE + ".sql, 2), 3) asc", template );
-//	}
-//
-//	public void testCollation() {
-//		String fragment = "`sql` COLLATE my_collation, `sql` COLLATE your_collation";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( Template.TEMPLATE + ".\"sql\" collate my_collation, " + Template.TEMPLATE + ".\"sql\" collate your_collation", template );
-//	}
-//
-//	public void testCollationAndOrdering() {
-//		String fragment = "sql COLLATE my_collation, upper(prop) COLLATE your_collation asc, `sql` desc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( Template.TEMPLATE + ".sql collate my_collation, upper(" + Template.TEMPLATE + ".prop) collate your_collation asc, " + Template.TEMPLATE + ".\"sql\" desc", template );
-//
-//	}
-//
-//	public void testComponentReferences() {
-//		String fragment = "component asc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( Template.TEMPLATE + ".comp_1 asc, " + Template.TEMPLATE + ".comp_2 asc", template );
-//
-//	}
-//
-//	public void testComponentDerefReferences() {
-//		String fragment = "component.prop1 asc";
-//		String template = doStandardRendering( fragment );
-//
-//		assertEquals( Template.TEMPLATE + ".comp_1 asc", template );
-//	}
+    public void testQuotedSQLReferences() {
+        String fragment = "`sql` asc, `sql` desc";
+        String template = doStandardRendering( fragment );
 
+        assertEquals( Template.TEMPLATE + ".\"sql\" asc, " + Template.TEMPLATE + ".\"sql\" desc", template );
+    }
+
+    public void testPropertyReference() {
+		String fragment = "property asc, property desc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( Template.TEMPLATE + ".prop asc, " + Template.TEMPLATE + ".prop desc", template );
+	}
+
+    public void testFunctionReference() {
+		String fragment = "upper(sql) asc, lower(sql) desc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( "upper(" + Template.TEMPLATE + ".sql) asc, lower(" + Template.TEMPLATE + ".sql) desc", template );
+	}
+
+	public void testQualifiedFunctionReference() {
+		String fragment = "qual.upper(property) asc, qual.lower(property) desc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( "qual.upper(" + Template.TEMPLATE + ".prop) asc, qual.lower(" + Template.TEMPLATE + ".prop) desc", template );
+	}
+
+	public void testDoubleQualifiedFunctionReference() {
+		String fragment = "qual1.qual2.upper(property) asc, qual1.qual2.lower(property) desc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( "qual1.qual2.upper(" + Template.TEMPLATE + ".prop) asc, qual1.qual2.lower(" + Template.TEMPLATE + ".prop) desc", template );
+	}
+
+	public void testFunctionWithPropertyReferenceAsParam() {
+		String fragment = "upper(property) asc, lower(property) desc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( "upper(" + Template.TEMPLATE + ".prop) asc, lower(" + Template.TEMPLATE + ".prop) desc", template );
+	}
+
+	public void testNestedFunctionReferences() {
+		String fragment = "upper(lower(sql)) asc, lower(upper(sql)) desc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( "upper(lower(" + Template.TEMPLATE + ".sql)) asc, lower(upper(" + Template.TEMPLATE + ".sql)) desc", template );
+	}
+
+	public void testComplexNestedFunctionReferences() {
+		String fragment = "mod(mod(sql,2),3) asc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( "mod(mod(" + Template.TEMPLATE + ".sql, 2), 3) asc", template );
+	}
+
+	public void testCollation() {
+		String fragment = "`sql` COLLATE my_collation, `sql` COLLATE your_collation";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( Template.TEMPLATE + ".\"sql\" collate my_collation, " + Template.TEMPLATE + ".\"sql\" collate your_collation", template );
+	}
+
+	public void testCollationAndOrdering() {
+		String fragment = "sql COLLATE my_collation, upper(prop) COLLATE your_collation asc, `sql` desc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( Template.TEMPLATE + ".sql collate my_collation, upper(" + Template.TEMPLATE + ".prop) collate your_collation asc, " + Template.TEMPLATE + ".\"sql\" desc", template );
+
+	}
+
+	public void testComponentReferences() {
+		// todo : inline the row value constructor expressions [(e1, e2) asc] -> [e1 asc, e2 asc]
+		String fragment = "component asc";
+		String template = doStandardRendering( fragment );
+		assertEquals( Template.TEMPLATE + ".comp_1 asc, " + Template.TEMPLATE + ".comp_2 asc", template );
+	}
+
+	public void testComponentDerefReferences() {
+		String fragment = "component.prop1 asc";
+		String template = doStandardRendering( fragment );
+
+		assertEquals( Template.TEMPLATE + ".comp_1 asc", template );
+	}
+
+
+	// test the various 'standard function' handlings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public void testCastFunction() {
+		String template = doStandardRendering( "cast( sql as varchar )" );
+		assertEquals( "cast(" + Template.TEMPLATE + ".sql as varchar)", template );
+	}
+
+	public void testConcatFunction() {
+		String template = doStandardRendering( "concat(sql, sql)" );
+		assertEquals( "concat(" + Template.TEMPLATE + ".sql, " + Template.TEMPLATE + ".sql)", template );
+	}
+
+	public void testConcatExpression2Function() {
+		// todo : pull the concatenation-op rules over from the hql parser...
+		String template = doStandardRendering( "sql || sql" );
+		assertEquals( "concat(" + Template.TEMPLATE + ".sql, " + Template.TEMPLATE + ".sql)", template );
+	}
+
+	public void testSubstringFunction() {
+		String template = doStandardRendering( "substring(sql,1)" );
+		assertEquals( "substring(" + Template.TEMPLATE + ".sql, 1)", template );
+
+		template = doStandardRendering( "substring(sql,1,2)" );
+		assertEquals( "substring(" + Template.TEMPLATE + ".sql, 1, 2)", template );
+	}
+
+	public void testTrimFunction() {
+		String template = doStandardRendering( "trim( both ' ' from sql )" );
+		assertEquals( "trim(both ' ' from " + Template.TEMPLATE + ".sql)", template );
+
+		template = doStandardRendering( "trim( ' ' from sql )" );
+		assertEquals( "trim(both ' ' from " + Template.TEMPLATE + ".sql)", template );
+
+		template = doStandardRendering( "trim( sql )" );
+		assertEquals( "trim(both ' ' from " + Template.TEMPLATE + ".sql)", template );
+
+		template = doStandardRendering( "trim( leading from sql )" );
+		assertEquals( "trim(leading ' ' from " + Template.TEMPLATE + ".sql)", template );
+	}
+
+	public void testLengthFunction() {
+		String template = doStandardRendering( "length(sql)" );
+		assertEquals( "length(" + Template.TEMPLATE + ".sql)", template );
+	}
+
+	public void testLocateFunction() {
+		String template = doStandardRendering( "locate('abc', sql)" );
+		assertEquals( "locate('abc', " + Template.TEMPLATE + ".sql)", template );
+
+		template = doStandardRendering( "locate('abc', sql, 2)" );
+		assertEquals( "locate('abc', " + Template.TEMPLATE + ".sql, 2)", template );
+	}
+
 	public String doStandardRendering(String fragment) {
 		return Template.renderOrderByStringTemplate( fragment, MAPPER, null, DIALECT, FUNCTION_REGISTRY );
 	}

Modified: core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java
===================================================================
--- core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/hql/resolve/TestHQLResolver.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -1,20 +1,40 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.sql.ast.origin.hql.resolve;
 
 import junit.framework.TestCase;
-
 import org.antlr.runtime.ANTLRStringStream;
 import org.antlr.runtime.CommonTokenStream;
 import org.antlr.runtime.RecognitionException;
 import org.antlr.runtime.tree.CommonTreeNodeStream;
 import org.antlr.runtime.tree.Tree;
+
 import org.hibernate.cfg.Configuration;
 import org.hibernate.cfg.Environment;
 import org.hibernate.dialect.HSQLDialect;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.hql.classic.ClassicQueryTranslatorFactory;
-import org.hibernate.sql.ast.origin.hql.resolve.HQLResolver;
+import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
 import org.hibernate.sql.ast.origin.hql.parse.HQLParser;
-import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
 
 public class TestHQLResolver extends TestCase {
 
@@ -41,11 +61,11 @@
 	}
 
 	public void testBasicStructure() throws RecognitionException {
-		Tree queryTree = normalize( "from Animal" );
+		normalize( "from Animal" );
 	}
 
 	public void testBasicSelectStructure() throws Throwable {
-		Tree queryTree = normalize( "from Zoo z where z.mammals['dog'].id = ?" );
+		normalize( "from Zoo z where z.mammals['dog'].id = ?" );
 	}
 
 	public Tree normalize( String hql ) throws RecognitionException {
@@ -84,7 +104,6 @@
 		ANTLRStringStream charStream = new ANTLRStringStream( input );
 		HQLLexer hqlLexer = new HQLLexer( charStream );
 		tokens = new CommonTokenStream( hqlLexer );
-		HQLParser parser = new HQLParser( tokens );
-		return parser;
+		return new HQLParser( tokens );
 	}
 }

Deleted: core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
===================================================================
--- core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java	2009-05-01 11:59:08 UTC (rev 16499)
+++ core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.sql.ast.origin.ordering;
-
-import java.util.Collections;
-import java.util.Map;
-
-import junit.framework.TestCase;
-import junit.framework.AssertionFailedError;
-
-import org.hibernate.persister.entity.PropertyMapping;
-import org.hibernate.QueryException;
-import org.hibernate.Hibernate;
-import org.hibernate.HibernateException;
-import org.hibernate.dialect.Dialect;
-import org.hibernate.dialect.HSQLDialect;
-import org.hibernate.dialect.function.SQLFunctionRegistry;
-import org.hibernate.dialect.function.SQLFunction;
-import org.hibernate.dialect.function.SQLFunctionTemplate;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.sql.ast.util.ASTUtil;
-import org.hibernate.sql.ast.util.TreePrinter;
-import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
-import org.hibernate.sql.Template;
-import org.hibernate.type.Type;
-
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.tree.Tree;
-import org.antlr.runtime.tree.CommonTree;
-
-/**
- * Assertions against the structures generated by various paths of the "order-by" mapping fragment parser.
- *
- * @author Steve Ebersole
- */
-public class OrderByParserTest extends TestCase {
-	public static final PropertyMapping STANDARD_PROPERTY_MAPPING = new PropertyMapping() {
-		public String[] toColumns(String propertyName) throws QueryException, UnsupportedOperationException {
-			if ( "component".equals( propertyName ) ) {
-				return new String[] { "comp_1", "comp_2" };
-			}
-			else if ( "component.prop1".equals( propertyName ) ) {
-				return new String[] { "comp_1" };
-			}
-			else if ( "component.prop2".equals( propertyName ) ) {
-				return new String[] { "comp_2" };
-			}
-			else if ( "property".equals( propertyName ) ) {
-				return new String[] { "prop" };
-			}
-			throw new QueryException( "could not resolve property: " + propertyName );
-		}
-
-		public Type toType(String propertyName) throws QueryException {
-			throw new UnsupportedOperationException( "toType(propertyName) not supported here" );
-		}
-
-		public String[] toColumns(String alias, String propertyName) throws QueryException {
-			throw new UnsupportedOperationException( "toColumns(alias,propertyName) not supported here" );
-		}
-
-		public Type getType() {
-			throw new UnsupportedOperationException( "getType() not supported here" );
-		}
-	};
-
-	public static final ColumnMapper STANDARD_MAPPER = new ColumnMapper() {
-		public String[] map(String reference) {
-			return STANDARD_PROPERTY_MAPPING.toColumns( reference );
-		}
-	};
-
-	public OrderByParserTest() {
-	}
-
-	public OrderByParserTest(String name) {
-		super( name );
-	}
-
-    public void testSQLReferences() {
-        String fragment = "sql asc, sql desc";
-        CommonTree tree = parse( fragment );
-
-		assertRootStructure( tree, 2 );
-
-		Tree firstSortSpec = tree.getChild( 0 );
-		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec );
-		assertEquals( 2, firstSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
-		assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
-		assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
-		assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
-		assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
-		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
-		Tree secondSortSpec = tree.getChild( 1 );
-		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
-		assertEquals( 2, secondSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
-		assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
-		assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
-		assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
-		assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
-		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
-    }
-
-    public void testQuotedSQLReferences() {
-        String fragment = "`sql` asc, `sql` desc";
-        CommonTree tree = parse( fragment );
-
-		assertRootStructure( tree, 2 );
-
-		Tree firstSortSpec = tree.getChild( 0 );
-		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
-		assertEquals( 2, firstSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
-		assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
-		assertTokenType( HQLLexer.QUOTED_IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
-		assertEquals( "`sql`", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
-		assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
-		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
-		Tree secondSortSpec = tree.getChild( 1 );
-		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
-		assertEquals( 2, secondSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
-		assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
-		assertTokenType( HQLLexer.QUOTED_IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
-		assertEquals( "`sql`", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
-		assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
-		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
-    }
-
-    public void testPropertyReference() {
-		String fragment = "property asc, property desc";
-        CommonTree tree = parse( fragment );
-
-		assertRootStructure( tree, 2 );
-
-		Tree firstSortSpec = tree.getChild( 0 );
-		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
-		assertEquals( 2, firstSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
-		assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
-		assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
-		assertEquals( "prop", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
-		assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
-		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
-		Tree secondSortSpec = tree.getChild( 1 );
-		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
-		assertEquals( 2, secondSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
-		assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
-		assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
-		assertEquals( "prop", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
-		assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
-		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
-	}
-
-    public void testFunctionReference() {
-		String fragment = "upper(sql) asc, lower(sql) desc";
-		CommonTree tree = parse( fragment );
-
-		assertRootStructure( tree, 2 );
-
-		Tree firstSortSpec = tree.getChild( 0 );
-		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
-		assertEquals( 2, firstSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.UPPER, firstSortSpec.getChild( 0 ) );
-		assertEquals( 1, firstSortSpec.getChild( 0 ).getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ) );
-		assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ).getText() );
-		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
-
-		Tree secondSortSpec = tree.getChild( 1 );
-		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
-		assertEquals( 2, secondSortSpec.getChildCount() );
-		assertTokenType( HQLLexer.LOWER, secondSortSpec.getChild( 0 ) );
-		assertEquals( 1, secondSortSpec.getChild( 0 ).getChildCount() );
-		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ).getChild( 0 ) );
-		assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ) );
-		assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ).getText() );
-		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
-	}
-
-	protected CommonTree parse(String orderByFragment) {
-		final Dialect dialect = new HSQLDialect();
-		final SQLFunction myFunction = new SQLFunctionTemplate( Hibernate.STRING, "myFunction($1)" );
-		final SQLFunctionRegistry functionRegistry = new SQLFunctionRegistry( dialect, Collections.singletonMap( "myFunction", myFunction ) );
-		return parse(
-				orderByFragment,
-				new TranslationContext() {
-					public SessionFactoryImplementor getSessionFactory() {
-						return null;
-					}
-
-					public Dialect getDialect() {
-						return dialect;
-					}
-
-					public SQLFunctionRegistry getSqlFunctionRegistry() {
-						return functionRegistry;
-					}
-
-					public ColumnMapper getColumnMapper() {
-						return STANDARD_MAPPER;
-					}
-				}
-		);
-	}
-
-	private static final TreePrinter TREE_PRINTER = new TreePrinter( HQLLexer.class );
-
-	protected CommonTree parse(String orderByFragment, TranslationContext context) {
-		try {
-			HQLLexer lexer = new HQLLexer( new ANTLRStringStream( orderByFragment ) );
-			OrderByFragmentParser parser = new OrderByFragmentParser( new CommonTokenStream( lexer ), context );
-			CommonTree rtn = parser.orderByFragment().tree;
-			// temp
-			System.out.println(
-					TREE_PRINTER.renderAsString( rtn, "fragment" )
-			);
-			return rtn;
-		}
-		catch ( HibernateException e ) {
-			throw e;
-		}
-		catch ( Throwable t ) {
-			throw new HibernateException( "Unable to parse order-by fragment", t );
-		}
-	}
-
-	private static final Map<Integer,String> tokenNameMap = ( Map<Integer,String> ) ASTUtil.generateTokenNameCache( HQLLexer.class );
-
-	public void assertTokenType(int expected, int actual) {
-		if ( expected != actual ) {
-			throw new AssertionFailedError(
-					"expected:<"+ tokenNameMap.get( expected ) +"> but was:<"+ tokenNameMap.get( actual ) +">"
-			);
-		}
-	}
-
-	public void assertTokenType(int expected, Tree tree) {
-		if ( tree == null ) {
-			throw new AssertionFailedError(
-					"expected:<"+ tokenNameMap.get( expected ) +"> but was:<null>"
-			);
-		}
-		assertTokenType( expected, tree.getType() );
-	}
-
-	public void assertRootStructure(Tree tree, int expectedSortSpecCount) {
-		assertTokenType( HQLLexer.ORDER_BY, tree.getType() );
-		assertEquals( expectedSortSpecCount, tree.getChildCount() );
-	}
-}

Added: core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java
===================================================================
--- core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java	                        (rev 0)
+++ core/branches/antlr3/src/test/java/org/hibernate/sql/ast/origin/ordering/OrderByParserTest.java	2009-05-01 20:26:15 UTC (rev 16500)
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.sql.ast.origin.ordering;
+
+import java.util.Collections;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import junit.framework.AssertionFailedError;
+
+import org.hibernate.persister.entity.PropertyMapping;
+import org.hibernate.QueryException;
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.dialect.Dialect;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.dialect.function.SQLFunctionRegistry;
+import org.hibernate.dialect.function.SQLFunction;
+import org.hibernate.dialect.function.SQLFunctionTemplate;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.sql.ast.util.ASTUtil;
+import org.hibernate.sql.ast.util.TreePrinter;
+import org.hibernate.sql.ast.origin.hql.parse.HQLLexer;
+import org.hibernate.sql.Template;
+import org.hibernate.type.Type;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.tree.Tree;
+import org.antlr.runtime.tree.CommonTree;
+
+/**
+ * Assertions against the structures generated by various paths of the "order-by" mapping fragment parser.
+ *
+ * @author Steve Ebersole
+ */
+public class OrderByParserTest extends TestCase {
+	public static final PropertyMapping STANDARD_PROPERTY_MAPPING = new PropertyMapping() {
+		public String[] toColumns(String propertyName) throws QueryException, UnsupportedOperationException {
+			if ( "component".equals( propertyName ) ) {
+				return new String[] { "comp_1", "comp_2" };
+			}
+			else if ( "component.prop1".equals( propertyName ) ) {
+				return new String[] { "comp_1" };
+			}
+			else if ( "component.prop2".equals( propertyName ) ) {
+				return new String[] { "comp_2" };
+			}
+			else if ( "property".equals( propertyName ) ) {
+				return new String[] { "prop" };
+			}
+			throw new QueryException( "could not resolve property: " + propertyName );
+		}
+
+		public Type toType(String propertyName) throws QueryException {
+			throw new UnsupportedOperationException( "toType(propertyName) not supported here" );
+		}
+
+		public String[] toColumns(String alias, String propertyName) throws QueryException {
+			throw new UnsupportedOperationException( "toColumns(alias,propertyName) not supported here" );
+		}
+
+		public Type getType() {
+			throw new UnsupportedOperationException( "getType() not supported here" );
+		}
+	};
+
+	public static final ColumnMapper STANDARD_MAPPER = new ColumnMapper() {
+		public String[] map(String reference) {
+			return STANDARD_PROPERTY_MAPPING.toColumns( reference );
+		}
+	};
+
+	public OrderByParserTest() {
+	}
+
+	public OrderByParserTest(String name) {
+		super( name );
+	}
+
+    public void testSQLReferences() {
+        String fragment = "sql asc, sql desc";
+        CommonTree tree = parse( fragment );
+
+		assertRootStructure( tree, 2 );
+
+		Tree firstSortSpec = tree.getChild( 0 );
+		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec );
+		assertEquals( 2, firstSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+		assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+		assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+		assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+		assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+		Tree secondSortSpec = tree.getChild( 1 );
+		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+		assertEquals( 2, secondSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+		assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+		assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
+		assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+		assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+    }
+
+    public void testQuotedSQLReferences() {
+        String fragment = "`sql` asc, `sql` desc";
+        CommonTree tree = parse( fragment );
+
+		assertRootStructure( tree, 2 );
+
+		Tree firstSortSpec = tree.getChild( 0 );
+		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+		assertEquals( 2, firstSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+		assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+		assertTokenType( HQLLexer.QUOTED_IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+		assertEquals( "`sql`", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+		assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+		Tree secondSortSpec = tree.getChild( 1 );
+		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+		assertEquals( 2, secondSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+		assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+		assertTokenType( HQLLexer.QUOTED_IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
+		assertEquals( "`sql`", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+		assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+    }
+
+    public void testPropertyReference() {
+		String fragment = "property asc, property desc";
+        CommonTree tree = parse( fragment );
+
+		assertRootStructure( tree, 2 );
+
+		Tree firstSortSpec = tree.getChild( 0 );
+		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+		assertEquals( 2, firstSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ) );
+		assertTokenType( HQLLexer.ALIAS_REF, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertEquals( Template.TEMPLATE, firstSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+		assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 1 ) );
+		assertEquals( "prop", firstSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+		assertTokenType( HQLLexer.ORDER_SPEC, firstSortSpec.getChild( 1 ) );
+		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+		Tree secondSortSpec = tree.getChild( 1 );
+		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+		assertEquals( 2, secondSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ) );
+		assertTokenType( HQLLexer.ALIAS_REF, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertEquals( Template.TEMPLATE, secondSortSpec.getChild( 0 ).getChild( 0 ).getText() );
+		assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 1 ) );
+		assertEquals( "prop", secondSortSpec.getChild( 0 ).getChild( 1 ).getText() );
+		assertTokenType( HQLLexer.ORDER_SPEC, secondSortSpec.getChild( 1 ) );
+		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+	}
+
+    public void testFunctionReference() {
+		String fragment = "upper(sql) asc, lower(sql) desc";
+		CommonTree tree = parse( fragment );
+
+		assertRootStructure( tree, 2 );
+
+		Tree firstSortSpec = tree.getChild( 0 );
+		assertTokenType( HQLLexer.SORT_SPEC, firstSortSpec.getType() );
+		assertEquals( 2, firstSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.UPPER, firstSortSpec.getChild( 0 ) );
+		assertEquals( 1, firstSortSpec.getChild( 0 ).getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, firstSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertTokenType( HQLLexer.IDENTIFIER, firstSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ) );
+		assertEquals( "sql", firstSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ).getText() );
+		assertEquals( "asc", firstSortSpec.getChild( 1 ).getText() );
+
+		Tree secondSortSpec = tree.getChild( 1 );
+		assertTokenType( HQLLexer.SORT_SPEC, secondSortSpec.getType() );
+		assertEquals( 2, secondSortSpec.getChildCount() );
+		assertTokenType( HQLLexer.LOWER, secondSortSpec.getChild( 0 ) );
+		assertEquals( 1, secondSortSpec.getChild( 0 ).getChildCount() );
+		assertTokenType( HQLLexer.COLUMN, secondSortSpec.getChild( 0 ).getChild( 0 ) );
+		assertTokenType( HQLLexer.IDENTIFIER, secondSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ) );
+		assertEquals( "sql", secondSortSpec.getChild( 0 ).getChild( 0 ).getChild( 1 ).getText() );
+		assertEquals( "desc", secondSortSpec.getChild( 1 ).getText() );
+	}
+
+	protected CommonTree parse(String orderByFragment) {
+		final Dialect dialect = new HSQLDialect();
+		final SQLFunction myFunction = new SQLFunctionTemplate( Hibernate.STRING, "myFunction($1)" );
+		final SQLFunctionRegistry functionRegistry = new SQLFunctionRegistry( dialect, Collections.singletonMap( "myFunction", myFunction ) );
+		return parse(
+				orderByFragment,
+				new TranslationContext() {
+					public SessionFactoryImplementor getSessionFactory() {
+						return null;
+					}
+
+					public Dialect getDialect() {
+						return dialect;
+					}
+
+					public SQLFunctionRegistry getSqlFunctionRegistry() {
+						return functionRegistry;
+					}
+
+					public ColumnMapper getColumnMapper() {
+						return STANDARD_MAPPER;
+					}
+				}
+		);
+	}
+
+	private static final TreePrinter TREE_PRINTER = new TreePrinter( HQLLexer.class );
+
+	protected CommonTree parse(String orderByFragment, TranslationContext context) {
+		try {
+			HQLLexer lexer = new HQLLexer( new ANTLRStringStream( orderByFragment ) );
+			ContextualOrderByParser parser = new ContextualOrderByParser( new CommonTokenStream( lexer ), context );
+			CommonTree rtn = parser.orderByFragment().tree;
+			// temp
+			System.out.println(
+					TREE_PRINTER.renderAsString( rtn, "fragment" )
+			);
+			return rtn;
+		}
+		catch ( HibernateException e ) {
+			throw e;
+		}
+		catch ( Throwable t ) {
+			throw new HibernateException( "Unable to parse order-by fragment", t );
+		}
+	}
+
+	private static final Map<Integer,String> tokenNameMap = ( Map<Integer,String> ) ASTUtil.generateTokenNameCache( HQLLexer.class );
+
+	public void assertTokenType(int expected, int actual) {
+		if ( expected != actual ) {
+			throw new AssertionFailedError(
+					"expected:<"+ tokenNameMap.get( expected ) +"> but was:<"+ tokenNameMap.get( actual ) +">"
+			);
+		}
+	}
+
+	public void assertTokenType(int expected, Tree tree) {
+		if ( tree == null ) {
+			throw new AssertionFailedError(
+					"expected:<"+ tokenNameMap.get( expected ) +"> but was:<null>"
+			);
+		}
+		assertTokenType( expected, tree.getType() );
+	}
+
+	public void assertRootStructure(Tree tree, int expectedSortSpecCount) {
+		assertTokenType( HQLLexer.ORDER_BY, tree.getType() );
+		assertEquals( expectedSortSpecCount, tree.getChildCount() );
+	}
+}




More information about the hibernate-commits mailing list