[hibernate-commits] Hibernate SVN: r15919 - in core/branches/SQL_GEN_REDESIGN: src/main/java/org/hibernate/persister and 10 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Feb 9 14:32:49 EST 2009


Author: steve.ebersole at jboss.com
Date: 2009-02-09 14:32:49 -0500 (Mon, 09 Feb 2009)
New Revision: 15919

Added:
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/MappedTableMetadata.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Dot.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexCollectionElementReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexedCollectionElementAccessPersisterReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterJoin.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoin.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoinBuilder.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyPathTerminus.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/StatementStack.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/AbstractPathNormalizationStrategy.java
   core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/resolve/
   core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/resolve/ResolverTest.java
Removed:
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/AbstractPathNormalizationStrategy.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java
Modified:
   core/branches/SQL_GEN_REDESIGN/pom.xml
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/Queryable.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/ASTFactoryImpl.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/AbstractPersisterReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/CollectionPersisterReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/EntityPersisterReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/HqlNormalizer.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Join.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContext.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContextAwareNode.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterAliasReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceBuilder.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceContext.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyReference.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/RootPersisterReferenceContext.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathNormalizationStrategy.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathedPropertyReferenceSource.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/BasicPathNormalizationStrategySupport.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/FromClausePathNormalizationStrategy.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/SelectClausePathNormalizationStrategy.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/WithFragmentPathNormalizationStrategy.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/HqlParser.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/PathCollector.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorHandlerDelegateImpl.java
   core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java
   core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizerTest.java
   core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/parse/ParserTest.java
Log:
HHH-2407 : HQL translation rework ->
HHH-3687 : parse (phase1)
HHH-3688 : normalize (phase2)

Modified: core/branches/SQL_GEN_REDESIGN/pom.xml
===================================================================
--- core/branches/SQL_GEN_REDESIGN/pom.xml	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/pom.xml	2009-02-09 19:32:49 UTC (rev 15919)
@@ -197,6 +197,9 @@
                             <name>hql/normalize.g</name>
                         </grammar>
                         <grammar>
+                            <name>hql/resolve.g</name>
+                        </grammar>
+                        <grammar>
                             <name>order/parse.g</name>
                         </grammar>
                         <grammar>

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/MappedTableMetadata.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/MappedTableMetadata.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/MappedTableMetadata.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,108 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.persister;
+
+/**
+ * Provides access to information about the tables used to persist a collection or entity.
+ * <p/>
+ * Note that this includes all inheritence tables and secondary tables.  The "main" table is called the
+ * {@link #getDrivingTableName() driving} table.  This is the table from which all {@link #getJoinedTables joins}
+ * originate.
+ *
+ * @author Steve Ebersole
+ */
+public interface MappedTableMetadata {
+	/**
+	 * Provides information about a secondary or inheritence table to which we must join to define the entire
+	 * table space for this thing being persisted.
+	 */
+	public static class JoinedTable {
+		private final String name;
+		private final String[] keyColumns;
+		private final boolean useInnerJoin;
+
+		/**
+		 * Create a JoinedTable definition.  By default we are saying to not use inner joins.
+		 *
+		 * @param name The table name.
+		 * @param keyColumns The columns which make up the key to the {@link MappedTableMetadata#getDrivingTableName driving}
+		 * table.
+		 */
+		public JoinedTable(String name, String[] keyColumns) {
+			this( name, keyColumns, false );
+		}
+
+		/**
+		 * Create a JoinedTable definition.
+		 *
+		 * @param name The table name.
+		 * @param keyColumns The columns which make up the key to the {@link MappedTableMetadata#getDrivingTableName driving}
+		 * table.
+		 * @param useInnerJoin Should we use an inner join (faster, but restrictive) as the join type?
+		 */
+		public JoinedTable(String name, String[] keyColumns, boolean useInnerJoin) {
+			this.name = name;
+			this.keyColumns = keyColumns;
+			this.useInnerJoin = useInnerJoin;
+		}
+
+		public String getName() {
+			return name;
+		}
+
+		public String[] getKeyColumns() {
+			return keyColumns;
+		}
+
+		public boolean useInnerJoin() {
+			return useInnerJoin;
+		}
+	}
+
+
+	public String getSqlAliasRootBase();
+
+	/**
+	 * Get the name of the driving table.
+	 *
+	 * @return
+	 */
+	public String getDrivingTableName();
+
+	/**
+	 * Get the names of the identifier columns from the driving table.  The entity persisters
+	 * assume that all <i>key</i> mappings refer to the driving table's PK (this is true for both <i>join</i> and
+	 * <i>joined-subclass</i> mappings).
+	 *
+	 * @return The driving table columns used in all {@link #getJoinedTables joins}
+	 */
+	public String[] getIdentifierColumnNames();
+
+	/**
+	 * Tables to which we must join to provide the complete "table space" for the given persister.
+	 *
+	 * @return The joined table definitions.
+	 */
+	public JoinedTable[] getJoinedTables();
+}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -36,6 +36,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.Comparator;
+import java.util.LinkedHashMap;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -48,6 +49,7 @@
 import org.hibernate.QueryException;
 import org.hibernate.StaleObjectStateException;
 import org.hibernate.StaleStateException;
+import org.hibernate.persister.MappedTableMetadata;
 import org.hibernate.jdbc.Expectation;
 import org.hibernate.jdbc.Expectations;
 import org.hibernate.jdbc.TooManyRowsAffectedException;
@@ -2838,6 +2840,63 @@
 		return false;
 	}
 
+
+	public class MappedTableMetadataImpl implements MappedTableMetadata {
+		private final JoinedTable[] joinedTables;
+
+		public MappedTableMetadataImpl() {
+			LinkedHashMap joinedTableMap = new LinkedHashMap();
+
+			int sublassTableCount = getSubclassTableSpan();
+			for ( int i = 1; i < sublassTableCount; i++ ) {
+				final String tableName = getSubclassTableName( i );
+				JoinedTable joinedTable = ( JoinedTable ) joinedTableMap.get( tableName );
+				if ( joinedTable == null && !getTableName().equals( tableName ) ) {
+					joinedTable = new JoinedTable( tableName, getSubclassTableKeyColumns( i ), isClassOrSuperclassTable( i ) );
+					joinedTableMap.put( tableName, joinedTable );
+				}
+			}
+
+			int tableCount = getTableSpan();
+			for ( int i = 1; i < tableCount; i++ ) {
+				final String tableName = getTableName( i );
+				JoinedTable joinedTable = ( JoinedTable ) joinedTableMap.get( tableName );
+				if ( joinedTable == null && !getTableName().equals( tableName ) ) {
+					joinedTable = new JoinedTable( tableName, getKeyColumns( i ) );
+					joinedTableMap.put( tableName, joinedTable );
+				}
+			}
+
+			this.joinedTables = ( JoinedTable[] ) joinedTableMap.values().toArray( new JoinedTable[ joinedTableMap.size() ] );
+		}
+
+		public String getSqlAliasRootBase() {
+			return StringHelper.unqualifyEntityName( entityMetamodel.getName() ).toLowerCase();
+		}
+
+		public String getDrivingTableName() {
+			return getTableName();
+		}
+
+		public String[] getIdentifierColumnNames() {
+			return AbstractEntityPersister.this.getIdentifierColumnNames();
+		}
+
+		public JoinedTable[] getJoinedTables() {
+			return joinedTables;
+		}
+	}
+
+
+	private MappedTableMetadata mappedTableMetadata;
+
+	public MappedTableMetadata getMappedTableMetadata() {
+		if ( mappedTableMetadata == null) {
+			mappedTableMetadata = new MappedTableMetadataImpl();
+		}
+		return mappedTableMetadata;
+	}
+
 	protected JoinFragment createJoin(String name, boolean innerJoin, boolean includeSubclasses) {
 		final String[] idCols = StringHelper.qualify( name, getIdentifierColumnNames() ); //all joins join to the pk of the driving table
 		final JoinFragment join = getFactory().getDialect().createOuterJoinFragment();

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/Queryable.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/Queryable.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/persister/entity/Queryable.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -24,6 +24,8 @@
  */
 package org.hibernate.persister.entity;
 
+import org.hibernate.persister.MappedTableMetadata;
+
 /**
  * Extends the generic <tt>EntityPersister</tt> contract to add
  * operations required by the Hibernate Query Language
@@ -174,4 +176,11 @@
 			return name;
 		}
 	}
+
+	/**
+	 * Get access to the persister's mapped table metadata.
+	 *
+	 * @return The mapped table metadata
+	 */
+	public MappedTableMetadata getMappedTableMetadata();
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/ASTFactoryImpl.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/ASTFactoryImpl.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/ASTFactoryImpl.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -44,16 +44,24 @@
 		switch ( tokenType ) {
 			case IDENT :
 				return Ident.class;
+			case DOT :
+				return Dot.class;
 			case ENTITY_PERSISTER_REF :
 				return EntityPersisterReference.class;
 			case COLLECTION_PERSISTER_REF :
 				return CollectionPersisterReference.class;
-			case JOIN :
-				return Join.class;
+			case INDEXED_COLLECTION_ACCESS_PERSISTER_REF :
+				return IndexedCollectionElementAccessPersisterReference.class;
+			case PROPERTY_JOIN :
+				return PropertyJoin.class;
+			case PERSISTER_JOIN :
+				return PersisterJoin.class;
 			case ALIAS_REF :
 				return PersisterAliasReference.class;
 			case PROPERTY_REF :
 				return PropertyReference.class;
+			case INDEXED_COLLECTION_ELEMENT_REF :
+				return IndexCollectionElementReference.class;
 			case INSERT :
 				return InsertStatement.class;
 			case UPDATE :
@@ -97,7 +105,7 @@
 	 */
 	protected void initialize(AST ast) {
 		if ( ast instanceof NormalizationContextAwareNode ) {
-			( ( NormalizationContextAwareNode ) ast ).injectResolutionContext( resolutionContext );
+			( ( NormalizationContextAwareNode ) ast ).injectNormalizationContext( resolutionContext );
 		}
 	}
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/AbstractPersisterReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/AbstractPersisterReference.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/AbstractPersisterReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -30,11 +30,12 @@
 
 /**
  * Base class for {@link PersisterReference} implementations.  Mainly it centralizes handling
- * of reusable proerty joins.
+ * of reusable property joins.
  *
  * @author Steve Ebersole
  */
-public abstract class AbstractPersisterReference extends Node implements PersisterReference {
+public abstract class AbstractPersisterReference extends Node implements PersisterReference, NormalizationContextAwareNode {
+	private NormalizationContext normalizationContext;
 	private Map reusablePropertyJoins = new HashMap();
 
 	/**
@@ -57,4 +58,31 @@
 	public PersisterReference locatePersisterReference() {
 		return this;
 	}
+
+	/**
+	 * Getter for property 'aliasNode'.
+	 *
+	 * @return Value for property 'aliasNode'.
+	 */
+	protected Node getAliasNode() {
+		return ( Node ) getFirstChild().getNextSibling();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getAlias() {
+		return getAliasNode().getText();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void injectNormalizationContext(NormalizationContext normalizationContext) {
+		this.normalizationContext = normalizationContext;
+	}
+
+	protected NormalizationContext normalizationContext() {
+		return normalizationContext;
+	}
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/CollectionPersisterReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/CollectionPersisterReference.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/CollectionPersisterReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -38,8 +38,7 @@
  *
  * @author Steve Ebersole
  */
-public class CollectionPersisterReference extends AbstractPersisterReference implements PersisterReference, NormalizationContextAwareNode, DisplayableNode {
-	private NormalizationContext resolutionContext;
+public class CollectionPersisterReference extends AbstractPersisterReference implements DisplayableNode {
 	private transient QueryableCollection persister;
 
 	/**
@@ -113,18 +112,11 @@
 		return getPropertyType( propertyName ) != null;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public void injectResolutionContext(NormalizationContext resolutionContext) {
-		this.resolutionContext = resolutionContext;
-	}
-
 	private SessionFactoryImplementor getSessionFactory() {
-		if ( resolutionContext == null ) {
+		if ( normalizationContext() == null ) {
 			throw new AssertionFailure( "resolution context was null on attempt to retrieve session factory reference" );
 		}
-		return resolutionContext.getSessionFactoryImplementor();
+		return normalizationContext().getSessionFactoryImplementor();
 	}
 
 	/**

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Dot.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Dot.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Dot.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,37 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import org.hibernate.sql.ast.common.Node;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class Dot extends Node {
+	public String getText() {
+		return getFirstChild().getText() + '.' + getFirstChild().getNextSibling().getText();
+	}
+}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/EntityPersisterReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/EntityPersisterReference.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/EntityPersisterReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -41,9 +41,7 @@
  *
  * @author Steve Ebersole
  */
-public class EntityPersisterReference extends AbstractPersisterReference
-		implements NormalizationContextAwareNode, DisplayableNode {
-	private NormalizationContext resolutionContext;
+public class EntityPersisterReference extends AbstractPersisterReference implements DisplayableNode {
 	private transient Queryable persister;
 
 	/**
@@ -111,18 +109,11 @@
 		return getPropertyType( propertyName ) != null;
 	}
 
-	/**
-	 * {@inheritDoc}
-	 */
-	public void injectResolutionContext(NormalizationContext resolutionContext) {
-		this.resolutionContext = resolutionContext;
-	}
-
 	private SessionFactoryImplementor getSessionFactory() {
-		if ( resolutionContext == null ) {
-			throw new AssertionFailure( "resolution context was null on attempt to retrieve session factory reference" );
+		if ( normalizationContext() == null ) {
+			throw new AssertionFailure( "normalizatioon context was null on attempt to retrieve session factory reference" );
 		}
-		return resolutionContext.getSessionFactoryImplementor();
+		return normalizationContext().getSessionFactoryImplementor();
 	}
 
 	/**

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/HqlNormalizer.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/HqlNormalizer.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/HqlNormalizer.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -25,14 +25,18 @@
 
 import java.io.PrintStream;
 import java.io.PrintWriter;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.hibernate.sql.ast.util.ParseErrorHandler;
-import org.hibernate.sql.ast.util.ErrorCounter;
+import org.hibernate.sql.ast.util.ErrorHandlerDelegate;
+import org.hibernate.sql.ast.util.ErrorHandlerDelegateImpl;
 import org.hibernate.sql.ast.util.ASTPrinter;
 import org.hibernate.sql.ast.common.JoinType;
+import org.hibernate.sql.ast.common.Node;
 import org.hibernate.sql.ast.phase.hql.normalize.path.impl.FromClausePathNormalizationStrategy;
 import org.hibernate.sql.ast.phase.hql.normalize.path.impl.BasicPathNormalizationStrategySupport;
 import org.hibernate.sql.ast.phase.hql.normalize.path.impl.SelectClausePathNormalizationStrategy;
@@ -40,8 +44,13 @@
 import org.hibernate.sql.ast.phase.hql.normalize.path.impl.WithFragmentPathNormalizationStrategy;
 import org.hibernate.QueryException;
 import org.hibernate.MappingException;
+import org.hibernate.persister.collection.QueryableCollection;
+import org.hibernate.type.Type;
 import org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategyStack;
 import org.hibernate.sql.ast.phase.hql.normalize.path.PathedPropertyReferenceSource;
+import org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategy;
+import org.hibernate.sql.ast.DetailedSemanticException;
+import org.hibernate.sql.ast.alias.ImplicitAliasGenerator;
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.util.StringHelper;
 
@@ -60,9 +69,11 @@
 
 	private final SessionFactoryImplementor sessionFactory;
 	private final PersisterReferenceBuilder persisterReferenceBuilder;
-	private final ParseErrorHandler parseErrorHandler = new ErrorCounter();
+	private final PropertyJoinBuilder propertyJoinBuilder;
+	private final ErrorHandlerDelegate parseErrorHandler = new ErrorHandlerDelegateImpl();
 	private final ASTPrinter printer = new ASTPrinter( HqlNormalizeTokenTypes.class );
-	private final AliasBuilder aliasBuilder = new AliasBuilder();
+	private final ImplicitAliasGenerator aliasBuilder = new ImplicitAliasGenerator();
+	private final StatementStack statementStack = new StatementStack();
 	private final PathNormalizationStrategyStack pathNormalizationStrategyStack = new PathNormalizationStrategyStack();
 
 	private int traceDepth = 0;
@@ -71,6 +82,7 @@
 		super();
 		this.sessionFactory = sessionFactory;
 		this.persisterReferenceBuilder = new PersisterReferenceBuilder( this );
+		this.propertyJoinBuilder = new PropertyJoinBuilder( this );
 		super.setASTFactory( new ASTFactoryImpl( this ) );
 	}
 
@@ -79,6 +91,37 @@
 	}
 
 
+	// handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public void traceIn(String ruleName, AST tree) {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = StringHelper.repeat( '-', (traceDepth++ * 2) ) + "-> ";
+		String traceText = ruleName + " (" + buildTraceNodeName(tree) + ")";
+		trace( prefix + traceText );
+	}
+
+	private String buildTraceNodeName(AST tree) {
+		return tree == null
+				? "???"
+				: tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]";
+	}
+
+	public void traceOut(String ruleName, AST tree) {
+		if ( inputState.guessing > 0 ) {
+			return;
+		}
+		String prefix = "<-" + StringHelper.repeat( '-', (--traceDepth * 2) ) + " ";
+		trace( prefix + ruleName );
+	}
+
+	private void trace(String msg) {
+		System.out.println( msg );
+//		log.trace( msg );
+	}
+
+
 	// overrides of Antlr infastructure methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 	public void reportError(RecognitionException e) {
@@ -93,7 +136,7 @@
 		getParseErrorHandler().reportWarning( s );
 	}
 
-	public ParseErrorHandler getParseErrorHandler() {
+	public ErrorHandlerDelegate getParseErrorHandler() {
 		return parseErrorHandler;
 	}
 
@@ -107,7 +150,7 @@
 	}
 
 
-	// Resolution state ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+	// Normalization context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 	private PersisterReferenceContext currentPersisterReferenceContext;
 
@@ -115,6 +158,10 @@
 		return currentPersisterReferenceContext;
 	}
 
+	public PathNormalizationStrategy getCurrentPathNormalizationStrategy() {
+		return pathNormalizationStrategyStack.getCurrent();
+	}
+
 	protected void pushStatement(AST statementNode) {
 		if ( currentPersisterReferenceContext == null ) {
 			currentPersisterReferenceContext = new RootPersisterReferenceContext();
@@ -124,9 +171,11 @@
 		}
 
 		pathNormalizationStrategyStack.push( new BasicPathNormalizationStrategySupport( this ) );
+		statementStack.push( ( Statement ) statementNode );
 	}
 
 	protected void popStatement() {
+		statementStack.pop();
 		pathNormalizationStrategyStack.pop();
 		if ( currentPersisterReferenceContext instanceof HierarchicalPersisterReferenceContext ) {
 			currentPersisterReferenceContext = ( ( HierarchicalPersisterReferenceContext ) currentPersisterReferenceContext ).getParent();
@@ -136,10 +185,7 @@
 		}
 	}
 
-
-	// ResolutionContext impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	public AliasBuilder getAliasBuilder() {
+	public ImplicitAliasGenerator getAliasBuilder() {
 		return aliasBuilder;
 	}
 
@@ -155,64 +201,74 @@
 		return persisterReferenceBuilder;
 	}
 
+	public PropertyJoinBuilder getPropertyJoinBuilder() {
+		return propertyJoinBuilder;
+	}
 
-	// handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	public void traceIn(String ruleName, AST tree) {
-		if ( inputState.guessing > 0 ) {
-			return;
-		}
-		String prefix = StringHelper.repeat( '-', (traceDepth++ * 2) ) + "-> ";
-		String traceText = ruleName + " (" + buildTraceNodeName(tree) + ")";
-		trace( prefix + traceText );
+	public void registerAssociationFetch(Join join) {
+		// todo : implement
 	}
 
-	private String buildTraceNodeName(AST tree) {
-		return tree == null
-				? "???"
-				: tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]";
+	public void registerPropertyFetch(PersisterReference persisterReference) {
+		// todo : implement
 	}
 
-	public void traceOut(String ruleName, AST tree) {
-		if ( inputState.guessing > 0 ) {
+
+	// semantic action overrides ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected void applyCollectionFilter(AST querySpecIn) {
+		if ( isSubquery() ) {
 			return;
 		}
-		String prefix = "<-" + StringHelper.repeat( '-', (--traceDepth * 2) ) + " ";
-		trace( prefix + ruleName );
-	}
 
-	private void trace(String msg) {
-		System.out.println( msg );
-//		log.trace( msg );
-	}
+		AST potentialFilterRole = querySpecIn.getFirstChild();
+		if ( potentialFilterRole == null || potentialFilterRole.getType() != FILTER ) {
+			return;
+		}
 
+		final String collectionRole = potentialFilterRole.getText();
+		trace( "applying collection filter for role [" + collectionRole + "]" );
 
-	// AST output methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+		// Remove the FILTER node from the tree as we are about to expand it...
+		querySpecIn.setFirstChild( potentialFilterRole.getNextSibling() );
 
-	public void dumpAst(AST ast) {
-		dumpAst( ast, "DUMP" );
-	}
+		QueryableCollection persister = ( QueryableCollection ) getSessionFactoryImplementor().getCollectionPersister( collectionRole );
 
-	public void dumpAst(AST ast, String header) {
-		log.info( printer.showAsString( ast, header ) );
-	}
+		if ( !persister.getElementType().isEntityType() ) {
+			throw new QueryException( "cannot filter collection of values" );
+		}
 
-	public void showAst(AST ast, PrintStream out) {
-		showAst( ast, new PrintWriter( out ) );
-	}
+		String collectionElementEntityName = persister.getElementPersister().getEntityName();
 
-	private void showAst(AST ast, PrintWriter pw) {
-		printer.showAst( ast, pw );
-	}
+		AST persisterSpace = astFactory.create( PERSISTER_SPACE, "filter-persister-space" );
+		AST persisterRef = astFactory.create( ENTITY_PERSISTER_REF, "filter-persister-ref" );
+		persisterSpace.setFirstChild( persisterRef );
+		persisterRef.addChild( astFactory.create( ENTITY_NAME, collectionElementEntityName ) );
+		persisterRef.addChild( astFactory.create( ALIAS, "this" ) );
+		persisterRef.addChild( astFactory.create( FILTER, collectionRole ) );
 
+		registerPersisterReference( persisterRef );
 
-	private String textOrNull(AST ast) {
-		return ast == null ? null : ast.getText();
+		AST selectFromNode = querySpecIn.getFirstChild();
+		assert selectFromNode.getType() == SELECT_FROM : "mis-structured AST";
+
+		AST fromClauseNode = selectFromNode.getFirstChild();
+		if ( fromClauseNode == null ) {
+			fromClauseNode = astFactory.create( FROM, "from" );
+			selectFromNode.setFirstChild( fromClauseNode );
+		}
+		else if ( fromClauseNode.getType() == SELECT ) {
+			AST tmp = astFactory.create( FROM, "from" );
+			tmp.setFirstChild( fromClauseNode );	// really the SELECT clause
+			fromClauseNode = tmp;
+			selectFromNode.setFirstChild( fromClauseNode );
+		}
+
+		assert fromClauseNode.getType() == FROM : "mis-structured AST";
+		fromClauseNode.addChild( persisterSpace );  // make it the first child???
 	}
 
 
-	// function processing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
 	private boolean processingFunction;
 
 	protected void startingFunction() {
@@ -227,10 +283,7 @@
 		return processingFunction;
 	}
 
-
-	// persister-related semntic action overrides ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	protected AST normalizeEntityName(AST node) throws SemanticException {
+ 	protected AST normalizeEntityName(AST node) throws SemanticException {
 		String entityName = node.getText();
 		if ( !isEntityName( entityName ) ) {
 			final String importedName = getSessionFactoryImplementor().getImportedClassName( entityName );
@@ -265,8 +318,6 @@
 	}
 
 
-	// property-related semntic action overrides ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
     protected String locateOwningPersisterAlias(AST property) {
 		PersisterReference persisterReference = getCurrentPersisterReferenceContext()
 				.locatePersisterReferenceExposingProperty( property.getText() );
@@ -274,8 +325,6 @@
 	}
 
 
-	// path normalization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
 	protected AST normalizeQualifiedRoot(AST alias) {
 		log.debug( "normalizing path expression root as alias [" + alias.getText() + "]" );
 		return pathNormalizationStrategyStack.getCurrent().handleRoot( getCurrentPersisterReferenceContext().locatePersisterReferenceByAlias( alias.getText() ) );
@@ -287,6 +336,10 @@
 		return root.handleIntermediatePathPart( ( Ident ) propertyName );
 	}
 
+	protected AST normalizeUnqualifiedPropertyReferenceSource(AST propertyName) {
+		return pathNormalizationStrategyStack.getCurrent().handleRoot( getCurrentPersisterReferenceContext().locatePersisterReferenceExposingProperty( propertyName.getText() ) );
+	}
+
 	protected AST normalizePropertyPathIntermediary(AST source, AST propertyNameNode) {
 		log.trace( "normalizing intermediate path expression [" + textOrNull( propertyNameNode ) + "]" );
 		return pathNormalizationStrategyStack.getCurrent().handleIntermediatePathPart( ( PathedPropertyReferenceSource ) source, ( Ident ) propertyNameNode );
@@ -297,9 +350,45 @@
 		return pathNormalizationStrategyStack.getCurrent().handleTerminalPathPart( ( PathedPropertyReferenceSource ) source, ( Ident ) propertyNameNode );
     }
 
+    protected AST normalizeIntermediateIndexOperation(AST collectionPath, AST selector) throws SemanticException {
+		log.trace( "normalizing intermediate index access [" + textOrNull( collectionPath ) + "]" );
+		PathedPropertyReferenceSource collectionSource = ( PathedPropertyReferenceSource ) collectionPath.getFirstChild();
+		Ident collectionProperty = ( Ident ) collectionSource.getNextSibling();
+		return pathNormalizationStrategyStack.getCurrent().handleIntermediateIndexAccess( collectionSource, collectionProperty, ( Node ) selector );
+    }
 
-	// property path normalization strategies ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    protected AST normalizeTerminalIndexOperation(AST collectionPath, AST selector) throws SemanticException {
+		log.trace( "normalizing terminal index access [" + textOrNull( collectionPath ) + "]" );
+		PathedPropertyReferenceSource collectionSource = ( PathedPropertyReferenceSource ) collectionPath.getFirstChild();
+		Ident collectionProperty = ( Ident ) collectionSource.getNextSibling();
+		return pathNormalizationStrategyStack.getCurrent().handleTerminalIndexAccess( collectionSource, collectionProperty, ( Node ) selector );
+    }
 
+	protected AST normalizeIndexOperation(AST collectionPropertyReference, AST selector) throws SemanticException {
+		PropertyReference propertyReference = ( PropertyReference ) collectionPropertyReference;
+		Type type = propertyReference.getSource().getPropertyType( propertyReference.getPropertyName() );
+		if ( !type.isCollectionType() ) {
+			throw new DetailedSemanticException( "Not a collection property reference", collectionPropertyReference );
+		}
+
+		// todo : validate the selector type against the indexed collection's key type?
+
+		Join join = getPropertyJoinBuilder().buildIndexOperationJoin(
+				propertyReference.getSource().locatePersisterReference(),
+				propertyReference.getPropertyName(),
+				null,
+				( Node ) getASTFactory().create( INNER, "inner" ),
+				( Node ) selector
+		);
+
+		return join.locateRhs();
+	}
+
+	protected AST normalizeIndexedRoot(AST root) {
+//		return super.normalizeIndexedRoot( alias );
+		return root;
+	}
+
 	protected void pushFromClausePropertyPathContext(AST joinTypeNode, AST fetch, AST alias, AST propertyFetch) {
 		pathNormalizationStrategyStack.push(
 				new FromClausePathNormalizationStrategy(
@@ -332,8 +421,8 @@
 		popPathNormalizationContext();
 	}
 
-	private void popPathNormalizationContext() {
-		pathNormalizationStrategyStack.pop();
+	private PathNormalizationStrategy popPathNormalizationContext() {
+		return pathNormalizationStrategyStack.pop();
 	}
 
 	protected void pushSelectClausePropertyPathContext() {
@@ -350,8 +439,9 @@
 		);
 	}
 
-	protected void popOnFragmentPropertyPathContext() {
-		popPathNormalizationContext();
+	protected AST popOnFragmentPropertyPathContext() {
+		OnFragmentPathNormalizationStrategy strategy = ( OnFragmentPathNormalizationStrategy ) popPathNormalizationContext();
+		return strategy.getDiscoveredLHS();
 	}
 
 	protected void pushWithFragmentPropertyPathContext(AST rhsPropertyReference) {
@@ -371,4 +461,115 @@
 	protected void applyWithFragment(AST withFragment) {
 		( ( WithFragmentPathNormalizationStrategy ) pathNormalizationStrategyStack.getCurrent() ).applyWithFragment( withFragment );
 	}
+
+	protected void postProcessQuery(AST querySpec) {
+		AST selectFrom = querySpec.getFirstChild();
+		assert selectFrom.getType() == SELECT_FROM;
+
+		AST fromClause = selectFrom.getFirstChild();
+		assert fromClause.getType() == FROM;
+
+		AST selectClause = fromClause.getNextSibling();
+		assert selectClause == null || selectClause.getType() == SELECT;
+
+		if ( selectClause == null || selectClause.getNumberOfChildren() == 0 ) {
+			selectClause = generateDerivedSelectClause( fromClause );
+			fromClause.setNextSibling( selectClause );
+		}
+
+		if ( propertyFetchAliases != null && !propertyFetchAliases.isEmpty() ) {
+			AST fetches = astFactory.create( FETCH, "fetch-aliases" );
+			Iterator aliases = propertyFetchAliases.iterator();
+			while ( aliases.hasNext() ) {
+				final String alias = ( String ) aliases.next();
+				fetches.addChild( astFactory.create( ALIAS_REF, alias ) );
+			}
+			selectClause.addChild( fetches );
+			propertyFetchAliases.clear();
+		}
+
+		// todo : attach mapping-defined order-by fragments
+		//		an issue here is that order-by fragments are attached "above" the "query spec" level according to ANSI SQL
+		//		for example, an order by is a function of the combined result in the case of a UNION, INTERSECT, etc...
+
+	}
+
+	private AST generateDerivedSelectClause(AST fromClause) {
+		AST selectClause = astFactory.create( SELECT, "derived-select-clause" );
+		AST selectList = astFactory.create( SELECT_LIST, "derived-select-list" );
+		selectClause.setFirstChild( selectList );
+
+		List implicitlySelectedPersisterReferenceAliases =
+				getCurrentPersisterReferenceContext().getPersisterReferencesImplicitInDerivedSelectClause();
+		assert implicitlySelectedPersisterReferenceAliases != null : "Found no registered implied select references";
+
+
+		Iterator itr = implicitlySelectedPersisterReferenceAliases.iterator();
+		while ( itr.hasNext() ) {
+			final PersisterReference persisterReference = ( PersisterReference ) itr.next();
+			final String alias = persisterReference.getAlias();
+			AST aliasReference = astFactory.create( ALIAS_REF, alias );
+			AST selectItem = astFactory.create( SELECT_ITEM, "derived-select-item" );
+			selectItem.setFirstChild( aliasReference );
+			selectList.addChild( selectItem );
+		}
+
+		return selectClause;
+	}
+
+	protected void registerSelectItem(AST selectItem) {
+		// todo : this was intended to allow for reusing select elements in other clauses, like say an order by
+		trace( "registering select item" );
+	}
+
+	protected AST buildRootEntityPersisterReference(AST persisterReferenceNode, AST entityName, AST alias, AST filter, AST propertyFetch) {
+		PersisterReference ref = ( PersisterReference ) super.buildRootEntityPersisterReference(
+				persisterReferenceNode,
+				entityName,
+				alias,
+				filter,
+				propertyFetch
+		);
+
+		if ( filter != null ) {
+			log.trace( "applying filter [" + filter.getText() + ", " + entityName + "]" );
+		}
+
+		getCurrentPersisterReferenceContext().registerPersisterReferenceImplicitInDerivedSelectClause( ref );
+
+		return ref;
+	}
+
+	private List propertyFetchAliases;
+
+	protected void registerPropertyFetchNode(AST persisterReference) {
+		if ( propertyFetchAliases == null ) {
+			propertyFetchAliases = new ArrayList();
+		}
+		propertyFetchAliases.add( ( ( PersisterReference ) persisterReference ).getAlias() );
+	}
+
+
+	// AST output methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public void dumpAst(AST ast) {
+		dumpAst( ast, "DUMP" );
+	}
+
+	public void dumpAst(AST ast, String header) {
+		log.info( printer.showAsString( ast, header ) );
+	}
+
+	public void showAst(AST ast, PrintStream out) {
+		showAst( ast, new PrintWriter( out ) );
+	}
+
+	private void showAst(AST ast, PrintWriter pw) {
+		printer.showAst( ast, pw );
+	}
+
+
+	private String textOrNull(AST ast) {
+		return ast == null ? null : ast.getText();
+	}
 }

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexCollectionElementReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexCollectionElementReference.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexCollectionElementReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,34 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import org.hibernate.sql.ast.common.Node;
+
+/**
+ *  Models the terminal reference to an index operator.
+ *
+ * @author Steve Ebersole
+ */
+public class IndexCollectionElementReference extends Node implements PropertyPathTerminus {
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexedCollectionElementAccessPersisterReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexedCollectionElementAccessPersisterReference.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/IndexedCollectionElementAccessPersisterReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,101 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import org.hibernate.type.AssociationType;
+import org.hibernate.type.Type;
+import org.hibernate.persister.collection.QueryableCollection;
+import org.hibernate.persister.entity.Queryable;
+import org.hibernate.AssertionFailure;
+
+/**
+ * Models the concept of a reference to the element persister of an indexed collection (map, list) which has been
+ * accessed or restricted by an index operation.
+ *
+ * @author Steve Ebersole
+ */
+public class IndexedCollectionElementAccessPersisterReference extends AbstractPersisterReference {
+	private transient QueryableCollection collectionPersister;
+	private transient Queryable elementPersister;
+
+	/**
+	 * Retrieve the collection "role" identifying the underlying {@link org.hibernate.persister.collection.CollectionPersister}
+	 *
+	 * @return The collection role
+	 */
+	public String getCollectionRole() {
+		return getFirstChild().getText();
+	}
+
+	public String getName() {
+		return getCollectionRole() + "[]";
+	}
+
+	public boolean isCollection() {
+		return false;
+	}
+
+	public AssociationType getPersisterType() {
+		return elementPersister() == null
+				? null
+				: ( AssociationType ) elementPersister().getType();
+	}
+
+	public QueryableCollection collectionPersister() {
+		if ( collectionPersister == null ) {
+			collectionPersister = ( QueryableCollection ) normalizationContext().getSessionFactoryImplementor()
+					.getCollectionPersister( getCollectionRole() );
+		}
+		return collectionPersister;
+	}
+
+	public Queryable elementPersister() {
+		if ( elementPersister == null ) {
+			try {
+				elementPersister = ( Queryable ) collectionPersister().getElementPersister();
+			}
+			catch ( AssertionFailure ignore ) {
+				// leave it null
+			}
+		}
+		return elementPersister;
+	}
+
+	public Type getPropertyType(String propertyName) {
+		try {
+			return elementPersister().getPropertyType( propertyName );
+		}
+		catch( Throwable ignore ) {
+			return null;
+		}
+	}
+
+	public boolean containsProperty(String propertyName) {
+		return getPropertyType( propertyName ) != null;
+	}
+
+	public Type getCollectionIndexType() {
+		return collectionPersister().getIndexType();
+	}
+}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Join.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Join.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/Join.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -33,26 +33,12 @@
  *
  * @author Steve Ebersole
  */
-public class Join extends Node {
-	private boolean forced = false;
+public interface Join extends AST {
+	public Node locateJoinType();
 
-	public void force() {
-		forced = true;
-	}
+	public JoinType getEnumeratedJoinType();
 
-	public boolean isForced() {
-		return forced;
-	}
+	public Node locateJoinedProperty();
 
-	public Node getJoinType() {
-		return ( Node ) getFirstChild();
-	}
-
-	public JoinType getEnumeratedJoinType() {
-		return JoinType.resolve( getJoinType() );
-	}
-
-	public PersisterReference getRhs() {
-		return ( PersisterReference ) getFirstChild().getNextSibling();
-	}
+	public PersisterReference locateRhs();
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContext.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContext.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContext.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -27,6 +27,8 @@
 
 import org.hibernate.engine.SessionFactoryImplementor;
 import org.hibernate.sql.ast.util.ASTPrinter;
+import org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategy;
+import org.hibernate.sql.ast.alias.ImplicitAliasGenerator;
 
 /**
  * Defines the environment or context in which normalization is occuring, more specifically
@@ -54,7 +56,7 @@
 	 *
 	 * @return The alias builder.
 	 */
-	public AliasBuilder getAliasBuilder();
+	public ImplicitAliasGenerator getAliasBuilder();
 
 	/**
 	 * The current {@link PersisterReferenceContext} for this context.  The {@link PersisterReferenceContext}
@@ -72,6 +74,13 @@
 	public PersisterReferenceBuilder getPersisterReferenceBuilder();
 
 	/**
+	 * The builder of {@link Join} instances pertaining to property joins for this context.
+	 *
+	 * @return The property {@link Join} builder.
+	 */
+	public PropertyJoinBuilder getPropertyJoinBuilder();
+
+	/**
 	 * The AST printer available for this context.
 	 *
 	 * @return The AST printer.
@@ -84,4 +93,10 @@
 	 * @return True or false.
 	 */
 	public boolean isCurrentlyProcessingFunction();
+
+	public PathNormalizationStrategy getCurrentPathNormalizationStrategy();
+
+	public void registerAssociationFetch(Join join);
+
+	public void registerPropertyFetch(PersisterReference persisterReference);
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContextAwareNode.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContextAwareNode.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizationContextAwareNode.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -35,5 +35,5 @@
 	 *
 	 * @param resolutionContext The resolution context.
 	 */
-	public void injectResolutionContext(NormalizationContext resolutionContext);
+	public void injectNormalizationContext(NormalizationContext resolutionContext);
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterAliasReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterAliasReference.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterAliasReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -27,26 +27,40 @@
 import org.hibernate.type.Type;
 
 /**
- * TODO : javadoc
+ * Represents a reference to a persister-reference alias.
  *
  * @author Steve Ebersole
  */
 public class PersisterAliasReference extends Node implements PropertyReferenceSource, NormalizationContextAwareNode {
 	private NormalizationContext resolutionContext;
 
+	/**
+	 * Retrieves the alias.
+	 *
+	 * @return The alias.
+	 */
 	public String getPersisterAlias() {
 		return getText();
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public PersisterReference locatePersisterReference() {
 		return resolutionContext.getCurrentPersisterReferenceContext()
 				.locatePersisterReferenceByAlias( getPersisterAlias() );
 	}
 
-	public void injectResolutionContext(NormalizationContext resolutionContext) {
+	/**
+	 * {@inheritDoc}
+	 */
+	public void injectNormalizationContext(NormalizationContext resolutionContext) {
 		this.resolutionContext = resolutionContext;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public Type getPropertyType(String property) {
 		return locatePersisterReference().getPropertyType( property );
 	}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterJoin.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterJoin.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterJoin.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import org.hibernate.sql.ast.common.Node;
+import org.hibernate.sql.ast.common.JoinType;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class PersisterJoin extends Node implements Join {
+	public Node locateJoinType() {
+		return ( Node ) getFirstChild();
+	}
+
+	public JoinType getEnumeratedJoinType() {
+		return JoinType.resolve( locateJoinType() );
+	}
+
+	public Node locateJoinedProperty() {
+		return null;
+	}
+
+	public PersisterReference locateRhs() {
+		return ( PersisterReference ) locateJoinType().getNextSibling();
+	}
+}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReference.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -36,14 +36,15 @@
 public interface PersisterReference extends AST, PropertyReferenceSource {
 	/**
 	 * Get the alias assigned to this persister reference.  May be explcitly defined by the query author or
-	 * supplied by {@link AliasBuilder#buildUniqueImplicitAlias()}, but all persister references will have an alias.
+	 * supplied by {@link org.hibernate.sql.ast.alias.ImplicitAliasGenerator#buildUniqueImplicitAlias()}, but all persister references will have an alias.
 	 *
 	 * @return This persister reference's alias.
 	 */
 	public String getAlias();
 
 	/**
-	 * Get the name of this persister reference.
+	 * Get the name of this persister reference.  This is just some descriptive text.
+	 * 
 	 * @return The name.
 	 */
 	public String getName();

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceBuilder.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceBuilder.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceBuilder.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -23,23 +23,23 @@
  */
 package org.hibernate.sql.ast.phase.hql.normalize;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import antlr.ASTFactory;
+import antlr.collections.AST;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import org.hibernate.persister.entity.EntityPersister;
 import org.hibernate.MappingException;
 import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.sql.ast.alias.ImplicitAliasGenerator;
 
-import antlr.collections.AST;
-import antlr.ASTFactory;
-
 /**
  * Centralization of code needed to build a {@link PersisterReference}
  *
  * @author Steve Ebersole
  */
 public class PersisterReferenceBuilder implements HqlNormalizeTokenTypes {
-	public static final Log log = LogFactory.getLog( PersisterReferenceBuilder.class );
+	private static final Logger log = LoggerFactory.getLogger( PersisterReferenceBuilder.class );
 
 	private final NormalizationContext normalizationContext;
 
@@ -55,7 +55,7 @@
 		return normalizationContext.getCurrentPersisterReferenceContext();
 	}
 
-	private AliasBuilder aliasBuilder() {
+	private ImplicitAliasGenerator aliasBuilder() {
 		return normalizationContext.getAliasBuilder();
 	}
 
@@ -70,13 +70,11 @@
 	 *
 	 * @param entityName The entity name to which to build a PersisterReference.
 	 * @param alias The alias (or null) to apply to the built PersisterReference.
-	 * @param propertyFetching Whether lazy property fetching should be enabled.
 	 * @return The built PersisterReference
 	 */
 	public EntityPersisterReference buildEntityPersisterReference(
 			String entityName,
-			String alias,
-			boolean propertyFetching) {
+			String alias) {
 		EntityPersister persister = lookupEntityPersister( entityName );
 		String aliasText = determineAlias( alias );
 
@@ -85,9 +83,6 @@
 		AST persisterReference = astFactory().create( ENTITY_PERSISTER_REF );
 		persisterReference.setFirstChild( entityNameNode );
 		persisterReference.addChild( aliasNode );
-		if ( propertyFetching ) {
-			persisterReference.addChild( astFactory().create( PROP_FETCH ) );
-		}
 
 		EntityPersisterReference entityPersisterReference = ( EntityPersisterReference ) persisterReference;
 		persisterReferenceContext().registerPersisterReference( entityPersisterReference );
@@ -100,13 +95,11 @@
 	 * @param collectionRole The {@link org.hibernate.persister.collection.CollectionPersister#getRole() collection role}
 	 * for which to build a PersisterReference.
 	 * @param alias The alias (or null) to apply to the built PersisterReference.
-	 * @param propertyFetching Whether lazy property fetching should be enabled.
 	 * @return The built PersisterReference
 	 */
 	public CollectionPersisterReference buildCollectionPersisterReference(
 			String collectionRole, 
-			String alias,
-			boolean propertyFetching) {
+			String alias) {
 		// todo : is this the structure we want here?
 		String aliasText = determineAlias( alias );
 
@@ -115,16 +108,35 @@
 		AST persisterReference = astFactory().create( COLLECTION_PERSISTER_REF );
 		persisterReference.setFirstChild( collectionRoleNode );
 		persisterReference.addChild( aliasNode );
-		if ( propertyFetching ) {
-			persisterReference.addChild( astFactory().create( PROP_FETCH ) );
-		}
 
-
 		CollectionPersisterReference collectionPersisterReference = ( CollectionPersisterReference ) persisterReference;
 		persisterReferenceContext().registerPersisterReference( collectionPersisterReference );
 		return collectionPersisterReference;
 	}
 
+	public IndexedCollectionElementAccessPersisterReference buildIndexedCollectionElementAccessPersisterReference(
+			String collectionRole,
+			String alias,
+			AST selector) {
+		String aliasText = determineAlias( alias );
+
+		AST collectionRoleNode = astFactory().create( COLLECTION_ROLE, collectionRole );
+		AST aliasNode = astFactory().create( ALIAS, aliasText );
+
+		AST indexValueCondition = astFactory().create( INDEX_VALUE_CORRELATION, "index-correlation" );
+		indexValueCondition.addChild( selector );
+
+		AST persisterReference = astFactory().create( INDEXED_COLLECTION_ACCESS_PERSISTER_REF );
+		persisterReference.setFirstChild( collectionRoleNode );
+		persisterReference.addChild( aliasNode );
+		persisterReference.addChild( indexValueCondition );
+
+		IndexedCollectionElementAccessPersisterReference pr = ( IndexedCollectionElementAccessPersisterReference ) persisterReference;
+		persisterReferenceContext().registerPersisterReference( pr );
+
+		return pr;
+	}
+
 	private EntityPersister lookupEntityPersister(String name) {
 		// NOTE : the parser should have already normalized the entity name...
 		try {
@@ -156,7 +168,7 @@
 	}
 
 	public static boolean isImplicitAlias(String alias) {
-		return AliasBuilder.isImplicitAlias( alias );
+		return ImplicitAliasGenerator.isImplicitAlias( alias );
 	}
 
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceContext.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceContext.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PersisterReferenceContext.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -23,6 +23,8 @@
  */
 package org.hibernate.sql.ast.phase.hql.normalize;
 
+import java.util.List;
+
 /**
  * TODO : javadoc
  *
@@ -78,4 +80,8 @@
 	 */
 	public void registerPersisterReference(PersisterReference persisterReference);
 
+	public void registerPersisterReferenceImplicitInDerivedSelectClause(PersisterReference persisterReference);
+
+	public List getPersisterReferencesImplicitInDerivedSelectClause();
+
 }

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoin.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoin.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoin.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import org.hibernate.sql.ast.common.Node;
+import org.hibernate.sql.ast.common.JoinType;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class PropertyJoin extends Node implements Join {
+	public Node locateJoinType() {
+		return ( Node ) getFirstChild();
+	}
+
+	public JoinType getEnumeratedJoinType() {
+		return JoinType.resolve( locateJoinType() );
+	}
+
+	public Node locateJoinedProperty() {
+		return ( Node ) locateJoinType().getNextSibling();
+	}
+
+	public PersisterReference locateRhs() {
+		return ( PersisterReference ) locateJoinedProperty().getNextSibling();
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoinBuilder.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoinBuilder.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyJoinBuilder.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,217 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import org.hibernate.type.Type;
+import org.hibernate.type.CollectionType;
+import org.hibernate.type.EntityType;
+import org.hibernate.HibernateException;
+import org.hibernate.sql.ast.util.ASTPrinter;
+import org.hibernate.sql.ast.common.Node;
+import org.hibernate.sql.ast.alias.ImplicitAliasGenerator;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class PropertyJoinBuilder implements HqlNormalizeTokenTypes {
+	private static final Logger log = LoggerFactory.getLogger( PropertyJoinBuilder.class );
+
+	private final NormalizationContext normalizationContext;
+
+	public PropertyJoinBuilder(NormalizationContext normalizationContext) {
+		this.normalizationContext = normalizationContext;
+	}
+
+	/**
+	 * Build a property join node.
+	 *
+	 * @param lhs The join's left-hand-side persister-reference
+	 * @param propertyName The property name.
+	 * @param alias The alias to apply to the rhs of the join
+	 * @param joinType The type of join (INNER, etc) to produce.
+	 * @param propertyFetching should property fetching be applied to the joined persister?
+	 * @param associationFetching Should the association making up the property join also be fetched?
+	 *
+	 * @return The right-hand-side persister-reference.
+	 */
+	public Join buildPropertyJoin(
+			PersisterReference lhs,
+			String propertyName,
+			String alias,
+			Node joinType,
+			boolean propertyFetching,
+			boolean associationFetching) {
+		PersisterReference rhs;
+		final Type associationType = lhs.getPropertyType( propertyName );
+		if ( associationType.isCollectionType() ) {
+			CollectionType collectionType = ( CollectionType ) associationType;
+			rhs = persisterReferenceBuilder().buildCollectionPersisterReference(
+					collectionType.getRole(),
+					alias
+			);
+		}
+		else if ( associationType.isEntityType() ) {
+			EntityType entityType = ( EntityType ) associationType;
+			String entityName = entityType.getAssociatedEntityName( sessionFactoryImplementor() );
+			rhs = persisterReferenceBuilder().buildEntityPersisterReference( entityName, alias );
+		}
+		else {
+			throw new HibernateException(
+					"cannot create join on non-association [root=" + lhs.getAlias()
+							+ ", name=" + propertyName
+							+ ", type=" + associationType.getName() + "]"
+			);
+		}
+
+		if ( propertyFetching ) {
+			normalizationContext.registerPropertyFetch( rhs );
+		}
+
+		Join joinNode = buildJoinNode( lhs, rhs, propertyName, joinType, associationFetching );
+
+
+		if ( log.isTraceEnabled() ) {
+			log.trace(
+					printer().showAsString(
+							joinNode,
+							"implicit join : " + lhs.getAlias() + "." + propertyName
+					)
+			);
+		}
+
+		return joinNode;
+	}
+
+	public Join buildIndexOperationJoin(
+			PersisterReference lhs,
+			String collectionPropertyName,
+			String alias,
+			Node joinType,
+			Node selector) {
+		final Type associationType = lhs.getPropertyType( collectionPropertyName );
+		if ( !associationType.isCollectionType() ) {
+			throw new HibernateException(
+					"Cannot process index operation against a non-collection property [root=" + lhs.getAlias() +
+							", name=" + collectionPropertyName +
+							", type=" + associationType.getName()
+			);
+		}
+
+		CollectionType collectionType = ( CollectionType ) associationType;
+		IndexedCollectionElementAccessPersisterReference rhs = persisterReferenceBuilder().buildIndexedCollectionElementAccessPersisterReference(
+				collectionType.getRole(),
+				alias,
+				selector
+		);
+		if ( rhs.getCollectionIndexType() == null ) {
+			throw new HibernateException(
+					"Cannot process index operation against a non-indexed collection property [root=" + lhs.getAlias() +
+							", name=" + collectionPropertyName +
+							", type=" + associationType.getName()
+			);
+		}
+
+		Join joinNode = buildJoinNode( lhs, rhs, collectionPropertyName, joinType, false );
+
+		if ( log.isTraceEnabled() ) {
+			log.trace(
+					printer().showAsString(
+							joinNode,
+							"implicit join : " + lhs.getAlias() + "." + collectionPropertyName + "[]"
+					)
+			);
+		}
+
+		return joinNode;
+	}
+
+
+	private Join buildJoinNode(
+			PersisterReference lhs,
+			PersisterReference rhs,
+			String propertyName,
+			Node joinType,
+			boolean associationFetching) {
+		Join joinNode = ( Join ) createNode( PROPERTY_JOIN, "join" );
+		joinNode.setFirstChild( joinType );
+		joinNode.addChild( createNode( ASSOCIATION_NAME, propertyName ) );
+		joinNode.addChild( rhs );
+
+		if ( associationFetching ) {
+			normalizationContext.registerAssociationFetch( joinNode );
+		}
+
+		lhs.addChild( joinNode );
+
+		return joinNode;
+	}
+
+	// normalization context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected final Node createNode(int type, String text) {
+		return ( Node ) normalizationContext.getASTFactory().create( type, text );
+	}
+
+	/**
+	 * Getter for property 'aliasBuilder'.
+	 *
+	 * @return Value for property 'aliasBuilder'.
+	 */
+	protected final ImplicitAliasGenerator aliasBuilder() {
+		return normalizationContext.getAliasBuilder();
+	}
+
+	/**
+	 * Getter for property 'persisterReferenceBuilder'.
+	 *
+	 * @return Value for property 'persisterReferenceBuilder'.
+	 */
+	protected final PersisterReferenceBuilder persisterReferenceBuilder() {
+		return normalizationContext.getPersisterReferenceBuilder();
+	}
+
+	/**
+	 * Getter for property 'sessionFactoryImplementor'.
+	 *
+	 * @return Value for property 'sessionFactoryImplementor'.
+	 */
+	protected final SessionFactoryImplementor sessionFactoryImplementor() {
+		return normalizationContext.getSessionFactoryImplementor();
+	}
+
+	/**
+	 * Getter for property 'ASTPrinter'.
+	 *
+	 * @return Value for property 'ASTPrinter'.
+	 */
+	protected final ASTPrinter printer() {
+		return normalizationContext.getPrinter();
+	}
+}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyPathTerminus.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyPathTerminus.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyPathTerminus.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,34 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import antlr.collections.AST;
+
+/**
+ * Represents the terminal part of a property path.
+ *
+ * @author Steve Ebersole
+ */
+public interface PropertyPathTerminus extends AST {
+}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyReference.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyReference.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/PropertyReference.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -31,7 +31,7 @@
  *
  * @author Steve Ebersole
  */
-public class PropertyReference extends Node {
+public class PropertyReference extends Node implements PropertyPathTerminus {
 	private String originalPath;
 
 	public String getOriginalPath() {

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/RootPersisterReferenceContext.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/RootPersisterReferenceContext.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/RootPersisterReferenceContext.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -47,6 +47,7 @@
 	private static final Logger log = LoggerFactory.getLogger( RootPersisterReferenceContext.class );
 
 	private List persisterReferences = new ArrayList();
+	private List persisterReferencesImplicitInDerivedSelectClause;
 	private Map aliasXref = new HashMap();
 
 	/**
@@ -63,6 +64,23 @@
 	/**
 	 * {@inheritDoc}
 	 */
+	public void registerPersisterReferenceImplicitInDerivedSelectClause(PersisterReference persisterReference) {
+		if ( persisterReferencesImplicitInDerivedSelectClause == null ) {
+			persisterReferencesImplicitInDerivedSelectClause = new ArrayList();
+		}
+		persisterReferencesImplicitInDerivedSelectClause.add( persisterReference );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List getPersisterReferencesImplicitInDerivedSelectClause() {
+		return persisterReferencesImplicitInDerivedSelectClause;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
 	public boolean isContainedAlias(String alias) {
 		return aliasXref.containsKey( alias );
 	}

Added: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/StatementStack.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/StatementStack.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/StatementStack.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,47 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.normalize;
+
+import java.util.LinkedList;
+
+/**
+ * Provides a stack of {@link Statement} nodes
+ *
+ * @author Steve Ebersole
+ */
+public class StatementStack {
+	private LinkedList stack = new LinkedList();
+
+	public void push(Statement statement) {
+		stack.addFirst( statement );
+	}
+
+	public Statement pop() {
+		return ( Statement ) stack.removeFirst();
+	}
+
+	public Statement getCurrent() {
+		return ( Statement ) stack.getFirst();
+	}
+}

Deleted: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/AbstractPathNormalizationStrategy.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/AbstractPathNormalizationStrategy.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/AbstractPathNormalizationStrategy.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -1,422 +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.phase.hql.normalize.path;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.hibernate.sql.ast.phase.hql.normalize.PropertyReference;
-import org.hibernate.sql.ast.phase.hql.normalize.Ident;
-import org.hibernate.sql.ast.phase.hql.normalize.NormalizationContext;
-import org.hibernate.sql.ast.phase.hql.normalize.AliasBuilder;
-import org.hibernate.sql.ast.phase.hql.normalize.PersisterReferenceBuilder;
-import org.hibernate.sql.ast.phase.hql.normalize.PersisterReference;
-import org.hibernate.sql.ast.phase.hql.normalize.HqlNormalizeTokenTypes;
-import org.hibernate.sql.ast.phase.hql.normalize.Join;
-import org.hibernate.sql.ast.phase.hql.normalize.DuplicateAliasException;
-import org.hibernate.sql.ast.util.ASTPrinter;
-import org.hibernate.sql.ast.util.DisplayableNode;
-import org.hibernate.type.ComponentType;
-import org.hibernate.type.Type;
-import org.hibernate.type.CollectionType;
-import org.hibernate.type.EntityType;
-import org.hibernate.QueryException;
-import org.hibernate.HibernateException;
-import org.hibernate.engine.SessionFactoryImplementor;
-
-import antlr.collections.AST;
-import antlr.CommonAST;
-import antlr.Token;
-
-/**
- * Abstract implementation of {@link PathNormalizationStrategy} providing convenience methods to actual
- * {@link PathNormalizationStrategy} implementors.
- *
- * @author Steve Ebersole
- */
-public abstract class AbstractPathNormalizationStrategy implements PathNormalizationStrategy, HqlNormalizeTokenTypes {
-	private static final Logger log = LoggerFactory.getLogger( AbstractPathNormalizationStrategy.class );
-
-	protected final NormalizationContext normalizationContext;
-	private PersisterReference root;  // todo whether we need this depends on how we deciode to structure the prop-joins...
-	private String pathThusFar = null;
-
-	protected AbstractPathNormalizationStrategy(NormalizationContext normalizationContext) {
-		this.normalizationContext = normalizationContext;
-	}
-
-	/**
-	 * Getter for property 'root'.
-	 *
-	 * @return Value for property 'root'.
-	 */
-	protected PersisterReference getRoot() {
-		return root;
-	}
-
-
-	// normalization context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	/**
-	 * Getter for property 'normalizationContext'.
-	 *
-	 * @return Value for property 'normalizationContext'.
-	 */
-	protected NormalizationContext getNormalizationContext() {
-		return normalizationContext;
-	}
-
-	protected final AST createNode(int type, String text) {
-		return getNormalizationContext().getASTFactory().create( type, text );
-	}
-
-	/**
-	 * Getter for property 'aliasBuilder'.
-	 *
-	 * @return Value for property 'aliasBuilder'.
-	 */
-	protected final AliasBuilder getAliasBuilder() {
-		return getNormalizationContext().getAliasBuilder();
-	}
-
-	/**
-	 * Getter for property 'persisterReferenceBuilder'.
-	 *
-	 * @return Value for property 'persisterReferenceBuilder'.
-	 */
-	protected final PersisterReferenceBuilder getPersisterReferenceBuilder() {
-		return getNormalizationContext().getPersisterReferenceBuilder();
-	}
-
-	/**
-	 * Getter for property 'sessionFactoryImplementor'.
-	 *
-	 * @return Value for property 'sessionFactoryImplementor'.
-	 */
-	protected final SessionFactoryImplementor getSessionFactoryImplementor() {
-		return getNormalizationContext().getSessionFactoryImplementor();
-	}
-
-	/**
-	 * Getter for property 'ASTPrinter'.
-	 *
-	 * @return Value for property 'ASTPrinter'.
-	 */
-	protected final ASTPrinter getASTPrinter() {
-		return getNormalizationContext().getPrinter();
-	}
-
-
-	// path ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	protected void initializePathSoFar(String root) {
-		pathThusFar = root;
-	}
-
-	/**
-	 * Getter for property 'pathThusFar'.
-	 *
-	 * @return Value for property 'pathThusFar'.
-	 */
-	public String getPathThusFar() {
-		return pathThusFar;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public final PathedPropertyReferenceSource handleRoot(PersisterReference persisterReference) {
-		initializePathSoFar( persisterReference.getAlias() );
-		root = persisterReference;
-		log.trace( "handling root path source [" + pathThusFar + "]" );
-		return internalHandleRoot( persisterReference );
-	}
-
-	/**
-	 * Hook for subclasses to process the path root.
-	 *
-	 * @param persisterReference The persister defining the source root.
-	 * @return The appropriate property path source implementation.
-	 */
-	protected abstract PathedPropertyReferenceSource internalHandleRoot(PersisterReference persisterReference);
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public final PathedPropertyReferenceSource handleIntermediatePathPart(PathedPropertyReferenceSource source, Ident pathPart) {
-		pathThusFar = ( pathThusFar == null ) ? pathPart.getText() : pathThusFar + "." + pathPart.getText();
-		log.trace( "handling intermediate path source [" + pathThusFar + "]" );
-		return internalResolveIntermediatePathPart( source, pathPart );
-	}
-
-	/**
-	 * Hook for subclasses to process an intermediate part of the path.
-	 *
-	 * @param source The source from which pathPart originates.
-	 * @param pathPart The name of the path part to be processed.
-	 * @return The appropriate property path source implementation.
-	 */
-	protected PathedPropertyReferenceSource internalResolveIntermediatePathPart(PathedPropertyReferenceSource source, Ident pathPart) {
-		return source.handleIntermediatePathPart( pathPart );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public final PropertyReference handleTerminalPathPart(PathedPropertyReferenceSource source, Ident pathPart) {
-		pathThusFar = ( pathThusFar == null ) ? pathPart.getText() : pathThusFar + "." + pathPart.getText();
-		log.trace( "handling terminal path part [" + pathThusFar + "]" );
-		try {
-			return internalResolveTerminalPathPart( source, pathPart );
-		}
-		finally {
-			pathThusFar = null;
-		}
-	}
-
-	/**
-	 * Hook for subclasses to process the terminal (or ending) part of a path.
-	 *
-	 * @param source The source from which pathPart originates.
-	 * @param pathPart The name of the path part to be processed.
-	 * @return a {@link #PROPERTY_REF} node representing the normalized property path.
-	 */
-	protected PropertyReference internalResolveTerminalPathPart(PathedPropertyReferenceSource source, Ident pathPart) {
-		return source.handleTerminalPathPart( pathPart );
-	}
-
-	/**
-	 * Convenience method to locate the index of a component sub-property.  The returned index is relative to
-	 * {@link ComponentType#getPropertyNames}.
-	 *
-	 * @param componentType The component type mapping.
-	 * @param subPropertyName The sub-property name.
-	 * @return The index.
-	 */
-	protected final int locateComponentPropertyIndex(ComponentType componentType, Ident subPropertyName) {
-		return locateComponentPropertyIndex( componentType, subPropertyName.getText() );
-	}
-
-	/**
-	 * Convenience method to locate the index of a component sub-property.  The returned index is relative to
-	 * {@link ComponentType#getPropertyNames}.
-	 *
-	 * @param componentType The component type mapping.
-	 * @param subPropertyName The sub-property name.
-	 * @return The index.
-	 */
-	protected static int locateComponentPropertyIndex(ComponentType componentType, String subPropertyName) {
-		String[] componentPropertyNames = componentType.getPropertyNames();
-		for ( int i = 0; i < componentPropertyNames.length; i++ ) {
-			if ( componentPropertyNames[i].equals( subPropertyName ) ) {
-				return i;
-			}
-		}
-		throw new QueryException( "could not locate component property [" + subPropertyName + "]" );
-	}
-
-	/**
-	 * Generate a {@link #PROPERTY_REF} node.
-	 *
-	 * @param origin The persister from which the property originates.
-	 * @param propertyName The name of the property being referenced.
-	 * @return The {@link #PROPERTY_REF} node.
-	 */
-	protected final PropertyReference generatePropertyReference(PersisterReference origin, String propertyName) {
-		AST propertyReference = createNode( PROPERTY_REF, "property-reference" );
-		propertyReference.addChild( createNode( ALIAS_REF, origin.getAlias() ) );
-		propertyReference.addChild( createNode( IDENT, propertyName ) );
-		return ( PropertyReference ) propertyReference;
-	}
-
-	/**
-	 * Locate (if property joins are reusable) or build an appropriate join.
-	 *
-	 * @param lhs The join lhs, which is the origin of the property.
-	 * @param propertyName The name of the property
-	 * @param alias The alias, if any, to apply to the generated RHS persister reference.
-	 * @param propertyFetching Should property fetching be applied to the generated RHS?
-	 * @param associationFetch Did this property join specify association fetching (join fetch)?
-	 * @return The appropriate join.
-	 */
-	protected final Join locateOrBuildPropertyJoin(
-			PersisterReference lhs,
-			String propertyName,
-			String alias,
-			boolean propertyFetching,
-			boolean associationFetch) {
-		Join join = null;
-
-		if ( areJoinsReusable() ) {
-			join = lhs.locateReusablePropertyJoin( propertyName );
-		}
-
-		if ( join == null ) {
-			join = buildPropertyJoin( lhs, propertyName, alias, propertyFetching, associationFetch );
-			if ( areJoinsReusable() ) {
-				lhs.registerReusablePropertyJoin( propertyName, join );
-			}
-		}
-
-		return join;
-	}
-
-	/**
-	 * Build a property join node.
-	 *
-	 * @param lhs The join's left-hand-side persister-reference
-	 * @param propertyName The property name.
-	 * @param alias The alias to apply to the rhs of the join
-	 * @param propertyFetching should property fetching be applied to the joined persister?
-	 * @param associationFetch Should the association making up the property join also be fetched?
-	 *
-	 * @return The right-hand-side persister-reference.
-	 */
-	protected Join buildPropertyJoin(
-			PersisterReference lhs,
-			String propertyName,
-			String alias,
-			boolean propertyFetching,
-			boolean associationFetch) {
-		validateJoinCreation( lhs, propertyName );
-
-		PersisterReference rhs = null;
-		final Type associationType = lhs.getPropertyType( propertyName );
-		if ( associationType.isCollectionType() ) {
-			CollectionType collectionType = ( CollectionType ) associationType;
-			rhs = getPersisterReferenceBuilder().buildCollectionPersisterReference(
-					collectionType.getRole(),
-					alias,
-					propertyFetching
-			);
-		}
-		else if ( associationType.isEntityType() ) {
-			EntityType entityType = ( EntityType ) associationType;
-			String entityName = entityType.getAssociatedEntityName( getSessionFactoryImplementor() );
-			rhs = getPersisterReferenceBuilder().buildEntityPersisterReference( entityName, alias, propertyFetching );
-		}
-		else {
-			throw new HibernateException( "cannot create join on non-association [name=" + propertyName + ", type=" + associationType + "]" );
-		}
-
-		Join propertyJoinNode = ( Join ) createNode( JOIN, "join" );
-		propertyJoinNode.setFirstChild( buildJoinTypeNode() );
-		propertyJoinNode.addChild( rhs );
-
-		// todo : handle mapped join conditions, adding them to the tree
-
-		if ( associationFetch ) {
-			registerAssociationFetch( propertyJoinNode );
-		}
-
-		if ( log.isTraceEnabled() ) {
-			log.trace(
-					getASTPrinter().showAsString(
-							propertyJoinNode,
-							"implicit join [" + lhs.getAlias() + "." + propertyName + "]"
-					)
-			);
-		}
-
-		lhs.addChild( propertyJoinNode );
-
-		return propertyJoinNode;
-	}
-
-	/**
-	 * Hook to allow subclasses to disallow implicit join.
-	 *
-	 * @param origin The persister-reference which is the origin of the property
-	 * @param property The property resulting in a join.
-	 */
-	protected void validateJoinCreation(PersisterReference origin, String property) {
-		log.debug( "creating path expression implied join [" + origin.getAlias() + "].[" + property + "]" );
-	}
-
-	private void registerAssociationFetch(Join propertyJoinNode) {
-		// todo : implement
-	}
-
-	/**
-	 * Hook to allow subclasses to define the type of join to use for an implciit join.
-	 * <p/>
-	 * The default is to use an {@link #INNER} join.
-	 *
-	 * @return The join type node.
-	 */
-	protected AST buildJoinTypeNode() {
-		return createNode( INNER, "inner" );
-	}
-
-	/**
-	 * Does this strategy allows property joins to be reused?
-	 *
-	 * @return True/false.
-	 */
-	protected boolean areJoinsReusable() {
-		return true;
-	}
-
-
-	// source impl support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	public abstract class AbstractPathedPropertyReferenceSource extends CommonAST
-			implements PathedPropertyReferenceSource, DisplayableNode {
-		private final String originationPath;
-
-		/**
-		 * Constructs a new AbstractPathedPropertyReferenceSource.
-		 */
-		protected AbstractPathedPropertyReferenceSource() {
-			this( getPathThusFar() );
-		}
-
-		protected AbstractPathedPropertyReferenceSource(Token token) {
-			this( token, getPathThusFar() );
-		}
-
-		protected AbstractPathedPropertyReferenceSource(String originationPath) {
-			this.originationPath = originationPath;
-		}
-
-		protected AbstractPathedPropertyReferenceSource(Token token, String originationPath) {
-			super( token );
-			this.originationPath = originationPath;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		public String getOriginationPath() {
-			return originationPath;
-		}
-
-		/**
-		 * {@inheritDoc}
-		 */
-		public final String getDisplayText() {
-				return " ADPATER : SHOULD NEVER END UP IN TREE!";
-		}
-	}
-}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathNormalizationStrategy.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathNormalizationStrategy.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathNormalizationStrategy.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -24,12 +24,13 @@
 package org.hibernate.sql.ast.phase.hql.normalize.path;
 
 import org.hibernate.sql.ast.phase.hql.normalize.PersisterReference;
-import org.hibernate.sql.ast.phase.hql.normalize.PropertyReference;
 import org.hibernate.sql.ast.phase.hql.normalize.Ident;
+import org.hibernate.sql.ast.phase.hql.normalize.PropertyPathTerminus;
+import org.hibernate.sql.ast.common.Node;
 
 /**
  * Applies a strategy pattern to the manner in which path expressions are normalized, allowing contextual pluggability
- * of the implicit-join handling rules...
+ * of the implicit-join and index-access handling rules...
  *
  * @author Steve Ebersole
  */
@@ -61,5 +62,9 @@
 	 *
 	 * @return The terminal property reference indicated by the overall path.
 	 */
-	public PropertyReference handleTerminalPathPart(PathedPropertyReferenceSource source, Ident pathPart);
+	public PropertyPathTerminus handleTerminalPathPart(PathedPropertyReferenceSource source, Ident pathPart);
+	
+	public PathedPropertyReferenceSource handleIntermediateIndexAccess(PathedPropertyReferenceSource source, Ident name, Node selector);
+
+	public PropertyPathTerminus handleTerminalIndexAccess(PathedPropertyReferenceSource source, Ident name, Node selector);
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathedPropertyReferenceSource.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathedPropertyReferenceSource.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/PathedPropertyReferenceSource.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -25,8 +25,9 @@
 
 import antlr.collections.AST;
 
-import org.hibernate.sql.ast.phase.hql.normalize.PropertyReference;
 import org.hibernate.sql.ast.phase.hql.normalize.Ident;
+import org.hibernate.sql.ast.phase.hql.normalize.PropertyPathTerminus;
+import org.hibernate.sql.ast.common.Node;
 
 /**
  * The contract for representing the non-terminal parts of a property path expression
@@ -60,5 +61,9 @@
 	 *
 	 * @return The property reference.
 	 */
-	public PropertyReference handleTerminalPathPart(Ident name);
+	public PropertyPathTerminus handleTerminalPathPart(Ident name);
+
+	public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector);
+
+	public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector);
 }

Copied: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/AbstractPathNormalizationStrategy.java (from rev 15747, core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/AbstractPathNormalizationStrategy.java)
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/AbstractPathNormalizationStrategy.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/AbstractPathNormalizationStrategy.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,448 @@
+/*
+ * 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.phase.hql.normalize.path.impl;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.sql.ast.phase.hql.normalize.PropertyReference;
+import org.hibernate.sql.ast.phase.hql.normalize.Ident;
+import org.hibernate.sql.ast.phase.hql.normalize.NormalizationContext;
+import org.hibernate.sql.ast.alias.ImplicitAliasGenerator;
+import org.hibernate.sql.ast.phase.hql.normalize.PersisterReferenceBuilder;
+import org.hibernate.sql.ast.phase.hql.normalize.PersisterReference;
+import org.hibernate.sql.ast.phase.hql.normalize.HqlNormalizeTokenTypes;
+import org.hibernate.sql.ast.phase.hql.normalize.Join;
+import org.hibernate.sql.ast.phase.hql.normalize.PropertyPathTerminus;
+import org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategy;
+import org.hibernate.sql.ast.phase.hql.normalize.path.PathedPropertyReferenceSource;
+import org.hibernate.sql.ast.util.ASTPrinter;
+import org.hibernate.sql.ast.util.DisplayableNode;
+import org.hibernate.sql.ast.common.Node;
+import org.hibernate.type.ComponentType;
+import org.hibernate.QueryException;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+import antlr.collections.AST;
+import antlr.CommonAST;
+import antlr.Token;
+
+/**
+ * Abstract implementation of {@link org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategy} providing convenience methods to actual
+ * {@link org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategy} implementors.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractPathNormalizationStrategy implements PathNormalizationStrategy, HqlNormalizeTokenTypes {
+	private static final Logger log = LoggerFactory.getLogger( AbstractPathNormalizationStrategy.class );
+
+	private final NormalizationContext normalizationContext;
+	private PersisterReference root;  // todo whether we need this depends on how we deciode to structure the prop-joins...
+	private String pathThusFar = null;
+
+	protected AbstractPathNormalizationStrategy(NormalizationContext normalizationContext) {
+		this.normalizationContext = normalizationContext;
+	}
+
+	/**
+	 * Getter for property 'root'.
+	 *
+	 * @return Value for property 'root'.
+	 */
+	protected PersisterReference getRoot() {
+		return root;
+	}
+
+
+	// normalization context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	/**
+	 * Getter for property 'normalizationContext'.
+	 *
+	 * @return Value for property 'normalizationContext'.
+	 */
+	protected NormalizationContext normalizationContext() {
+		return normalizationContext;
+	}
+
+	protected final Node createNode(int type, String text) {
+		return ( Node ) normalizationContext().getASTFactory().create( type, text );
+	}
+
+	/**
+	 * Getter for property 'aliasBuilder'.
+	 *
+	 * @return Value for property 'aliasBuilder'.
+	 */
+	protected final ImplicitAliasGenerator getAliasBuilder() {
+		return normalizationContext().getAliasBuilder();
+	}
+
+	/**
+	 * Getter for property 'persisterReferenceBuilder'.
+	 *
+	 * @return Value for property 'persisterReferenceBuilder'.
+	 */
+	protected final PersisterReferenceBuilder getPersisterReferenceBuilder() {
+		return normalizationContext().getPersisterReferenceBuilder();
+	}
+
+	/**
+	 * Getter for property 'sessionFactoryImplementor'.
+	 *
+	 * @return Value for property 'sessionFactoryImplementor'.
+	 */
+	protected final SessionFactoryImplementor getSessionFactoryImplementor() {
+		return normalizationContext().getSessionFactoryImplementor();
+	}
+
+	/**
+	 * Getter for property 'ASTPrinter'.
+	 *
+	 * @return Value for property 'ASTPrinter'.
+	 */
+	protected final ASTPrinter getASTPrinter() {
+		return normalizationContext().getPrinter();
+	}
+
+
+	// path ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected void initializePathSoFar(String root) {
+		pathThusFar = root;
+	}
+
+	/**
+	 * Getter for property 'pathThusFar'.
+	 *
+	 * @return Value for property 'pathThusFar'.
+	 */
+	public String getPathThusFar() {
+		return pathThusFar;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final PathedPropertyReferenceSource handleRoot(PersisterReference persisterReference) {
+		initializePathSoFar( persisterReference.getAlias() );
+		root = persisterReference;
+		log.trace( "handling root path source [" + pathThusFar + "]" );
+		return internalHandleRoot( persisterReference );
+	}
+
+	/**
+	 * Hook for subclasses to process the path root.
+	 *
+	 * @param persisterReference The persister defining the source root.
+	 * @return The appropriate property path source implementation.
+	 */
+	protected abstract PathedPropertyReferenceSource internalHandleRoot(PersisterReference persisterReference);
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final PathedPropertyReferenceSource handleIntermediatePathPart(PathedPropertyReferenceSource source, Ident pathPart) {
+		pathThusFar = ( pathThusFar == null ) ? pathPart.getText() : pathThusFar + "." + pathPart.getText();
+		log.trace( "handling intermediate path source [" + pathThusFar + "]" );
+		return internalResolveIntermediatePathPart( source, pathPart );
+	}
+
+	/**
+	 * Hook for subclasses to process an intermediate part of the path.
+	 *
+	 * @param source The source from which pathPart originates.
+	 * @param pathPart The name of the path part to be processed.
+	 * @return The appropriate property path source implementation.
+	 */
+	protected PathedPropertyReferenceSource internalResolveIntermediatePathPart(PathedPropertyReferenceSource source, Ident pathPart) {
+		return source.handleIntermediatePathPart( pathPart );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final PropertyPathTerminus handleTerminalPathPart(PathedPropertyReferenceSource source, Ident pathPart) {
+		pathThusFar = ( pathThusFar == null ) ? pathPart.getText() : pathThusFar + "." + pathPart.getText();
+		log.trace( "handling terminal path part [" + pathThusFar + "]" );
+		try {
+			return internalResolveTerminalPathPart( source, pathPart );
+		}
+		finally {
+			pathThusFar = null;
+		}
+	}
+
+	/**
+	 * Hook for subclasses to process the terminal (or ending) part of a path.
+	 *
+	 * @param source The source from which pathPart originates.
+	 * @param pathPart The name of the path part to be processed.
+	 * @return a node representing the normalized property path.
+	 */
+	protected PropertyPathTerminus internalResolveTerminalPathPart(PathedPropertyReferenceSource source, Ident pathPart) {
+		return source.handleTerminalPathPart( pathPart );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final PathedPropertyReferenceSource handleIntermediateIndexAccess(PathedPropertyReferenceSource source, Ident pathPart, Node selector) {
+		pathThusFar = ( ( pathThusFar == null ) ? pathPart.getText() : pathThusFar + "." + pathPart.getText() ) + "[]";
+		log.trace( "handling intermediate index access [" + pathThusFar + "]" );
+		try {
+			return internalHandleIntermediateIndexAccess( source, pathPart, selector );
+		}
+		finally {
+			pathThusFar = null;
+		}
+	}
+
+	/**
+	 * Hook for subclasses to process an index access as an intermediate property path.
+	 *
+	 * @param source The source from which pathPart originates.
+	 * @param pathPart The name of the path part to be processed.
+	 * @param selector The index selector to be appliedto the indexed collection
+	 *
+	 * @return The appropriate property path source implementation.
+	 */
+	protected PathedPropertyReferenceSource internalHandleIntermediateIndexAccess(PathedPropertyReferenceSource source, Ident pathPart, Node selector) {
+		return source.handleIntermediateIndexAccess( pathPart, selector );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final PropertyPathTerminus handleTerminalIndexAccess(PathedPropertyReferenceSource source, Ident pathPart, Node selector) {
+		pathThusFar = ( ( pathThusFar == null ) ? pathPart.getText() : pathThusFar + "." + pathPart.getText() ) + "[]";
+		log.trace( "handling terminal index access [" + pathThusFar + "]" );
+		try {
+			return internalHandleTerminalIndexAccess( source, pathPart, selector );
+		}
+		finally {
+			pathThusFar = null;
+		}
+	}
+
+	/**
+	 * Hook for subclasses to process an index access as the terminus of a property path.
+	 *
+	 * @param source The source from which pathPart originates.
+	 * @param pathPart The name of the path part to be processed.
+	 * @param selector The index selector to be appliedto the indexed collection
+	 *
+	 * @return a node representing the normalized property path.
+	 */
+	protected PropertyPathTerminus internalHandleTerminalIndexAccess(PathedPropertyReferenceSource source, Ident pathPart, Node selector) {
+		return source.handleTerminalIndexAccess( pathPart, selector );
+	}
+
+	/**
+	 * Convenience method to locate the index of a component sub-property.  The returned index is relative to
+	 * {@link ComponentType#getPropertyNames}.
+	 *
+	 * @param componentType The component type mapping.
+	 * @param subPropertyName The sub-property name.
+	 * @return The index.
+	 */
+	protected final int locateComponentPropertyIndex(ComponentType componentType, Ident subPropertyName) {
+		return locateComponentPropertyIndex( componentType, subPropertyName.getText() );
+	}
+
+	/**
+	 * Convenience method to locate the index of a component sub-property.  The returned index is relative to
+	 * {@link ComponentType#getPropertyNames}.
+	 *
+	 * @param componentType The component type mapping.
+	 * @param subPropertyName The sub-property name.
+	 * @return The index.
+	 */
+	protected static int locateComponentPropertyIndex(ComponentType componentType, String subPropertyName) {
+		String[] componentPropertyNames = componentType.getPropertyNames();
+		for ( int i = 0; i < componentPropertyNames.length; i++ ) {
+			if ( componentPropertyNames[i].equals( subPropertyName ) ) {
+				return i;
+			}
+		}
+		throw new QueryException( "could not locate component property [" + subPropertyName + "]" );
+	}
+
+	/**
+	 * Generate a {@link #PROPERTY_REF} node.
+	 *
+	 * @param origin The persister from which the property originates.
+	 * @param propertyName The name of the property being referenced.
+	 * @return The {@link #PROPERTY_REF} node.
+	 */
+	protected final PropertyReference generatePropertyReference(PersisterReference origin, String propertyName) {
+		AST propertyReference = createNode( PROPERTY_REF, "property-reference" );
+		propertyReference.addChild( createNode( ALIAS_REF, origin.getAlias() ) );
+		propertyReference.addChild( createNode( IDENT, propertyName ) );
+		return ( PropertyReference ) propertyReference;
+	}
+
+	/**
+	 * Locate (if property joins are reusable) or build an appropriate join.
+	 *
+	 * @param lhs The join lhs, which is the origin of the property.
+	 * @param propertyName The name of the property
+	 * @param alias The alias, if any, to apply to the generated RHS persister reference.
+	 * @param propertyFetching Should property fetching be applied to the generated RHS?
+	 * @param associationFetching Did this property join specify association fetching (join fetch)?
+	 * @return The appropriate join.
+	 */
+	protected final Join locateOrBuildPropertyJoin(
+			PersisterReference lhs,
+			String propertyName,
+			String alias,
+			boolean propertyFetching,
+			boolean associationFetching) {
+		Join join = null;
+
+		if ( areJoinsReusable() ) {
+			join = lhs.locateReusablePropertyJoin( propertyName );
+		}
+
+		if ( join == null ) {
+			join = buildPropertyJoin( lhs, propertyName, alias, propertyFetching, associationFetching );
+			if ( areJoinsReusable() ) {
+				lhs.registerReusablePropertyJoin( propertyName, join );
+			}
+		}
+
+		return join;
+	}
+
+	/**
+	 * Build a property join node.
+	 *
+	 * @param lhs The join's left-hand-side persister-reference
+	 * @param propertyName The property name.
+	 * @param alias The alias to apply to the rhs of the join
+	 * @param propertyFetching should property fetching be applied to the joined persister?
+	 * @param associationFetching Should the association making up the property join also be fetched?
+	 *
+	 * @return The right-hand-side persister-reference.
+	 */
+	protected Join buildPropertyJoin(
+			PersisterReference lhs,
+			String propertyName,
+			String alias,
+			boolean propertyFetching,
+			boolean associationFetching) {
+		validateJoinCreation( lhs, propertyName );
+		return normalizationContext().getPropertyJoinBuilder().buildPropertyJoin(
+				lhs,
+				propertyName,
+				alias,
+				buildJoinTypeNode(),
+				propertyFetching,
+				associationFetching
+		);
+	}
+
+	/**
+	 * Hook to allow subclasses to disallow implicit join.
+	 *
+	 * @param origin The persister-reference which is the origin of the property
+	 * @param property The property resulting in a join.
+	 */
+	protected void validateJoinCreation(PersisterReference origin, String property) {
+		log.debug( "creating path expression implied join [" + origin.getAlias() + "].[" + property + "]" );
+	}
+
+	/**
+	 * Hook to allow subclasses to define the type of join to use for an implciit join.
+	 * <p/>
+	 * The default is to use an {@link #INNER} join.
+	 *
+	 * @return The join type node.
+	 */
+	protected Node buildJoinTypeNode() {
+		return createNode( INNER, "inner" );
+	}
+
+	/**
+	 * Does this strategy allows property joins to be reused?
+	 *
+	 * @return True/false.
+	 */
+	protected boolean areJoinsReusable() {
+		return true;
+	}
+
+
+	// source impl support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	public abstract class AbstractPathedPropertyReferenceSource extends CommonAST
+			implements PathedPropertyReferenceSource, DisplayableNode {
+		private final String originationPath;
+
+		/**
+		 * Constructs a new AbstractPathedPropertyReferenceSource.
+		 */
+		protected AbstractPathedPropertyReferenceSource() {
+			this( getPathThusFar() );
+		}
+
+		protected AbstractPathedPropertyReferenceSource(Token token) {
+			this( token, getPathThusFar() );
+		}
+
+		protected AbstractPathedPropertyReferenceSource(String originationPath) {
+			this.originationPath = originationPath;
+		}
+
+		protected AbstractPathedPropertyReferenceSource(Token token, String originationPath) {
+			super( token );
+			this.originationPath = originationPath;
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(PersisterReference lhs, Ident name, Node selector) {
+			Join join = normalizationContext().getPropertyJoinBuilder().buildIndexOperationJoin(
+					lhs,
+					name.getText(),
+					null,
+					buildJoinTypeNode(),
+					selector
+			);
+			return ( PropertyPathTerminus ) createNode( INDEXED_COLLECTION_ELEMENT_REF, join.locateRhs().getAlias() );
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public String getOriginationPath() {
+			return originationPath;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public final String getDisplayText() {
+				return " ADPATER : SHOULD NEVER END UP IN TREE!";
+		}
+	}
+}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/BasicPathNormalizationStrategySupport.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/BasicPathNormalizationStrategySupport.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/BasicPathNormalizationStrategySupport.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -29,10 +29,12 @@
 import org.hibernate.sql.ast.phase.hql.normalize.PersisterReference;
 import org.hibernate.sql.ast.phase.hql.normalize.NormalizationContext;
 import org.hibernate.sql.ast.phase.hql.normalize.Ident;
-import org.hibernate.sql.ast.phase.hql.normalize.PropertyReference;
 import org.hibernate.sql.ast.phase.hql.normalize.Join;
-import org.hibernate.sql.ast.phase.hql.normalize.path.AbstractPathNormalizationStrategy;
+import org.hibernate.sql.ast.phase.hql.normalize.IndexedCollectionElementAccessPersisterReference;
+import org.hibernate.sql.ast.phase.hql.normalize.PropertyPathTerminus;
+import org.hibernate.sql.ast.phase.hql.normalize.path.impl.AbstractPathNormalizationStrategy;
 import org.hibernate.sql.ast.phase.hql.normalize.path.PathedPropertyReferenceSource;
+import org.hibernate.sql.ast.common.Node;
 import org.hibernate.type.Type;
 import org.hibernate.type.ComponentType;
 import org.hibernate.type.EntityType;
@@ -128,7 +130,7 @@
 			return determineAppropriateIntermediateSourceType( lhs, name );
 		}
 
-		public PropertyReference handleTerminalPathPart(Ident name) {
+		public PropertyPathTerminus handleTerminalPathPart(Ident name) {
 			final String nameText = name.getText();
 			if ( lhs.getPropertyType( nameText ).isEntityType() ) {
 				if ( shouldTerminalEntityPropertyForceJoin() ) {
@@ -138,6 +140,21 @@
 			return generatePropertyReference( lhs, name.getText() );
 		}
 
+		public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector) {
+			Join join = normalizationContext().getPropertyJoinBuilder().buildIndexOperationJoin(
+					lhs,
+					name.getText(),
+					null,
+					buildJoinTypeNode(),
+					selector
+			);
+			return new IndexAccessIntermediatePathSource( join.locateRhs() );
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector) {
+			return super.handleTerminalIndexAccess( lhs, name, selector );
+		}
+
 		public String getText() {
 			return "root-source {" + lhs.getAlias() + "}";
 		}
@@ -148,9 +165,17 @@
 			throw new HibernateException( "cannot dereference simple value as part of path expression" );
 		}
 
-		public PropertyReference handleTerminalPathPart(Ident name) {
+		public PropertyPathTerminus handleTerminalPathPart(Ident name) {
 			throw new HibernateException( "cannot dereference simple value as part of path expression" );
 		}
+
+		public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector) {
+			throw new HibernateException( "cannot apply index operation to simple value" );
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector) {
+			throw new HibernateException( "cannot apply index operation to simple value" );
+		}
 	}
 
 	private class ComponentIntermediatePathSource extends AbstractPathedPropertyReferenceSource {
@@ -184,10 +209,18 @@
 			}
 		}
 
-		public PropertyReference handleTerminalPathPart(Ident name) {
+		public PropertyPathTerminus handleTerminalPathPart(Ident name) {
 			return generatePropertyReference( lhs, buildComponentDereferencePath( name.getText() ) );
 		}
 
+		public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector) {
+			throw new HibernateException( "cannot apply index operation to component value" );
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector) {
+			throw new HibernateException( "cannot apply index operation to component value" );
+		}
+
 		private String buildComponentDereferencePath(String subPropertyName) {
 			return propertyPath + "." + subPropertyName;
 		}
@@ -204,10 +237,10 @@
 
 		public PathedPropertyReferenceSource handleIntermediatePathPart(Ident name) {
 			Join join = locateOrBuildPropertyJoin( lhs, lhsPropertyName, null, false, false );
-			return determineAppropriateIntermediateSourceType( join.getRhs(), name );
+			return determineAppropriateIntermediateSourceType( join.locateRhs(), name );
 		}
 
-		public PropertyReference handleTerminalPathPart(Ident name) {
+		public PropertyPathTerminus handleTerminalPathPart(Ident name) {
 			final EntityType type = ( EntityType ) lhs.getPropertyType( lhsPropertyName );
 			if ( isReferenceToPrimaryKey( type, lhsPropertyName ) ) {
 				return generatePropertyReference( lhs, lhsPropertyName + "." + name.getText() );
@@ -217,12 +250,27 @@
 				final String propertyName = name.getText();
 				if ( type.isEntityType() ) {
 					if ( shouldTerminalEntityPropertyForceJoin() ) {
-						locateOrBuildPropertyJoin( join.getRhs(), propertyName, null, false, false );
+						locateOrBuildPropertyJoin( join.locateRhs(), propertyName, null, false, false );
 					}
 				}
-				return generatePropertyReference( join.getRhs(), propertyName );
+				return generatePropertyReference( join.locateRhs(), propertyName );
 			}
 		}
+
+		public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector) {
+			Join join = normalizationContext().getPropertyJoinBuilder().buildIndexOperationJoin(
+					lhs,
+					name.getText(),
+					null,
+					buildJoinTypeNode(),
+					selector
+			);
+			return new IndexAccessIntermediatePathSource( join.locateRhs() );
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector) {
+			return super.handleTerminalIndexAccess( lhs, name, selector );
+		}
 	}
 
 	protected boolean shouldTerminalEntityPropertyForceJoin() {
@@ -242,14 +290,51 @@
 			throw new HibernateException( "cannot implicit join across a collection association" );
 		}
 
-		public PropertyReference handleTerminalPathPart(Ident name) {
+		public PropertyPathTerminus handleTerminalPathPart(Ident name) {
 			// TODO : what are the circusmstances under which we need to *join* to the collection, as opposed to say munge it into a subquery???
 			final String nameText = name.getText();
 			if ( CollectionProperties.isAnyCollectionProperty( nameText ) ) {
 				Join join = locateOrBuildPropertyJoin( lhs, propertyName, null, false, false );
-				return generatePropertyReference( join.getRhs(), nameText );
+				return generatePropertyReference( join.locateRhs(), nameText );
 			}
 			throw new HibernateException( "cannot implicit join across a collection association" );
 		}
+
+		public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector) {
+			throw new HibernateException( "cannot implicit join across a collection association" );
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector) {
+			throw new HibernateException( "cannot implicit join across a collection association" );
+		}
 	}
+
+	protected class IndexAccessIntermediatePathSource extends AbstractPathedPropertyReferenceSource {
+		private final IndexedCollectionElementAccessPersisterReference persisterReference;
+
+		public IndexAccessIntermediatePathSource(PersisterReference persisterReference) {
+			if ( persisterReference instanceof IndexedCollectionElementAccessPersisterReference ) {
+				this.persisterReference = ( IndexedCollectionElementAccessPersisterReference ) persisterReference;
+			}
+			else {
+				throw new HibernateException( "Expecting IndexedCollectionElementAccessPersisterReference, found " + persisterReference.getClass().getName() );
+			}
+		}
+
+		public PathedPropertyReferenceSource handleIntermediatePathPart(Ident name) {
+			return determineAppropriateIntermediateSourceType( persisterReference, name );
+		}
+
+		public PropertyPathTerminus handleTerminalPathPart(Ident name) {
+			return generatePropertyReference( persisterReference, name.getText() );
+		}
+
+		public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector) {
+			throw new IllegalStateException( "doubled up index operators" );
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector) {
+			throw new IllegalStateException( "doubled up index operators" );
+		}
+	}
 }
\ No newline at end of file

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/FromClausePathNormalizationStrategy.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/FromClausePathNormalizationStrategy.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/FromClausePathNormalizationStrategy.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -23,17 +23,18 @@
  */
 package org.hibernate.sql.ast.phase.hql.normalize.path.impl;
 
-import antlr.collections.AST;
-
 import org.hibernate.sql.ast.phase.hql.normalize.PersisterReference;
 import org.hibernate.sql.ast.phase.hql.normalize.PropertyReference;
 import org.hibernate.sql.ast.phase.hql.normalize.Ident;
 import org.hibernate.sql.ast.phase.hql.normalize.NormalizationContext;
 import org.hibernate.sql.ast.phase.hql.normalize.HqlNormalizeTokenTypes;
-import org.hibernate.sql.ast.phase.hql.normalize.path.AbstractPathNormalizationStrategy;
+import org.hibernate.sql.ast.phase.hql.normalize.PropertyPathTerminus;
+import org.hibernate.sql.ast.phase.hql.normalize.Join;
+import org.hibernate.sql.ast.phase.hql.normalize.path.impl.AbstractPathNormalizationStrategy;
 import org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategy;
 import org.hibernate.sql.ast.phase.hql.normalize.path.PathedPropertyReferenceSource;
 import org.hibernate.sql.ast.common.JoinType;
+import org.hibernate.sql.ast.common.Node;
 import org.hibernate.type.Type;
 import org.hibernate.HibernateException;
 import org.hibernate.QueryException;
@@ -80,6 +81,18 @@
 		return new SourceImpl( persisterReference );
 	}
 
+	protected Join buildPropertyJoin(
+			PersisterReference lhs,
+			String propertyName,
+			String alias,
+			boolean propertyFetching,
+			boolean associationFetching) {
+		Join join = super.buildPropertyJoin( lhs, propertyName, alias, propertyFetching, associationFetching );
+		normalizationContext().getCurrentPersisterReferenceContext()
+				.registerPersisterReferenceImplicitInDerivedSelectClause( join.locateRhs() );
+		return join;
+	}
+
 	private class SourceImpl extends AbstractPathedPropertyReferenceSource {
 		private final PersisterReference lhs;
 
@@ -89,10 +102,10 @@
 
 		public PathedPropertyReferenceSource handleIntermediatePathPart(Ident name) {
 			// TODO : still need to account for paths including component dereferences...
-			return new SourceImpl( locateOrBuildPropertyJoin( lhs, name.getText(), null, false, associationFetch ).getRhs() );
+			return new SourceImpl( locateOrBuildPropertyJoin( lhs, name.getText(), null, false, associationFetch ).locateRhs() );
 		}
 
-		public PropertyReference handleTerminalPathPart(Ident name) {
+		public PropertyPathTerminus handleTerminalPathPart(Ident name) {
 			final String propertyName = name.getText();
 			Type terminalPropertyType = lhs.getPropertyType( propertyName );
 			if ( !terminalPropertyType.isAssociationType() ) {
@@ -106,9 +119,17 @@
 
 			return propertyReference;
 		}
+
+		public PathedPropertyReferenceSource handleIntermediateIndexAccess(Ident name, Node selector) {
+			throw new UnsupportedOperationException( "index operation not supported in from clause" );
+		}
+
+		public PropertyPathTerminus handleTerminalIndexAccess(Ident name, Node selector) {
+			throw new UnsupportedOperationException( "index operation not supported in from clause" );
+		}
 	}
 
-	protected AST buildJoinTypeNode() {
+	protected Node buildJoinTypeNode() {
 		if ( joinType == JoinType.INNER ) {
 			return createNode( INNER, "inner" );
 		}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/SelectClausePathNormalizationStrategy.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/SelectClausePathNormalizationStrategy.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/SelectClausePathNormalizationStrategy.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -41,6 +41,6 @@
 
 	protected boolean shouldTerminalEntityPropertyForceJoin() {
 		// here we should *as long as* we are not part of a function processing
-		return ! getNormalizationContext().isCurrentlyProcessingFunction();
+		return ! normalizationContext().isCurrentlyProcessingFunction();
 	}
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/WithFragmentPathNormalizationStrategy.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/WithFragmentPathNormalizationStrategy.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/normalize/path/impl/WithFragmentPathNormalizationStrategy.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -23,9 +23,6 @@
  */
 package org.hibernate.sql.ast.phase.hql.normalize.path.impl;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
 import org.hibernate.sql.ast.phase.hql.normalize.PersisterReference;
 import org.hibernate.sql.ast.phase.hql.normalize.NormalizationContext;
 import org.hibernate.sql.ast.phase.hql.normalize.Join;
@@ -33,6 +30,8 @@
 import org.hibernate.QueryException;
 
 import antlr.collections.AST;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * {@link org.hibernate.sql.ast.phase.hql.normalize.path.PathNormalizationStrategy} for dealing with <tt>WITH</tt>
@@ -41,7 +40,7 @@
  * @author Steve Ebersole
  */
 public class WithFragmentPathNormalizationStrategy extends BasicPathNormalizationStrategySupport {
-	public static final Log log = LogFactory.getLog( WithFragmentPathNormalizationStrategy.class );
+	private static final Logger log = LoggerFactory.getLogger( WithFragmentPathNormalizationStrategy.class );
 
 	private final PersisterReference lhs;
 
@@ -57,7 +56,7 @@
 		AST nextPossible = lhs.getFirstChild();
 		while ( nextPossible != null ) {
 			if ( nextPossible instanceof Join ) {
-				if ( ( ( Join ) nextPossible ).getRhs() == rhs ) {
+				if ( ( ( Join ) nextPossible ).locateRhs() == rhs ) {
 					join = ( Join ) nextPossible;
 					break;
 				}

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/HqlParser.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/HqlParser.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/HqlParser.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -25,8 +25,8 @@
 
 import org.hibernate.sql.ast.util.ASTUtil;
 import org.hibernate.sql.ast.util.ASTPrinter;
-import org.hibernate.sql.ast.util.ErrorCounter;
-import org.hibernate.sql.ast.util.ParseErrorHandler;
+import org.hibernate.sql.ast.util.ErrorHandlerDelegateImpl;
+import org.hibernate.sql.ast.util.ErrorHandlerDelegate;
 import org.hibernate.QueryException;
 import org.hibernate.MappingException;
 import org.hibernate.persister.entity.EntityPersister;
@@ -65,7 +65,7 @@
 	private static final Logger log = LoggerFactory.getLogger( HqlParser.class );
 
 	private final Context context;
-	private final ParseErrorHandler parseErrorHandler = new ErrorCounter();
+	private final ErrorHandlerDelegate parseErrorHandler = new ErrorHandlerDelegateImpl();
 	private final ASTPrinter printer = new ASTPrinter( HqlParseTokenTypes.class );
 	private int traceDepth = 0;
 
@@ -93,7 +93,7 @@
 		parseErrorHandler.reportWarning( s );
 	}
 
-	public ParseErrorHandler getParseErrorHandler() {
+	public ErrorHandlerDelegate getParseErrorHandler() {
 		return parseErrorHandler;
 	}
 

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/PathCollector.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/PathCollector.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/phase/hql/parse/PathCollector.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -40,22 +40,23 @@
 	}
 
 	public static String getPath(AST dotStructure) {
-		if ( dotStructure.getType() == IDENT ) {
+		if ( dotStructure.getType() == DOT ) {
+			return extractText( dotStructure );
+		}
+		else {
 			return dotStructure.getText();
 		}
-
-		return extractText( dotStructure );
 	}
 
 	private static String extractText(AST node) {
 		AST lhs = node.getFirstChild();
 		AST rhs = lhs.getNextSibling();
 
-		if ( lhs.getType() == IDENT ) {
-			return lhs.getText() + node.getText() + rhs.getText();
+		if ( lhs.getType() == DOT ) {
+			return extractText( lhs ) + node.getText() + rhs.getText();
 		}
 		else {
-			return extractText( lhs ) + node.getText() + rhs.getText();
+			return lhs.getText() + node.getText() + rhs.getText();
 		}
 	}
 }

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTPrinter.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -131,10 +131,15 @@
 	 *         or just the integer as a string if none exists.
 	 */
 	public String getTokenTypeName(int type) {
-		if ( tokenTypeNameCache == null ) {
-			return Integer.toString( type );
+		final Integer typeInteger = new Integer( type );
+		String value = null;
+		if ( tokenTypeNameCache != null ) {
+			value = ( String ) tokenTypeNameCache.get( typeInteger );
 		}
-		return ( String ) tokenTypeNameCache.get( new Integer( type ) );
+		if ( value == null ) {
+			value = typeInteger.toString();
+		}
+		return value;
 	}
 
 	private void showAst(ArrayList parents, PrintWriter pw, AST ast) {

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ASTUtil.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -383,14 +383,31 @@
 	 * @param value The value of the constant.
 	 *
 	 * @return The token type name, *or* the integer value if the name could not be found.
+	 *
+	 * @deprecated Use #getTokenTypeName instead
 	 */
 	public static String getConstantName(Class owner, int value) {
-		String tokenTypeName = Integer.toString( value );
-		if ( owner != null ) {
-			Field[] fields = owner.getFields();
+		return getTokenTypeName( owner, value );
+	}
+
+	/**
+	 * Intended to retrieve the name of an AST token type based on the token type interface.  However, this
+	 * method can be used to look up the name of any constant defined on a class/interface based on the constant value.
+	 * Note that if multiple constants have this value, the first will be returned which is known to be different
+	 * on different JVM implementations.
+	 *
+	 * @param tokenTypeInterface The *TokenTypes interface (or one of its implementors).
+	 * @param tokenType The token type value.
+	 * 
+	 * @return The corresponding name.
+	 */
+	public static String getTokenTypeName(Class tokenTypeInterface, int tokenType) {
+		String tokenTypeName = Integer.toString( tokenType );
+		if ( tokenTypeInterface != null ) {
+			Field[] fields = tokenTypeInterface.getFields();
 			for ( int i = 0; i < fields.length; i++ ) {
 				final Integer fieldValue = extractIntegerValue( fields[i] );
-				if ( fieldValue != null && fieldValue.intValue() == value ) {
+				if ( fieldValue != null && fieldValue.intValue() == tokenType ) {
 					tokenTypeName = fields[i].getName();
 					break;
 				}
@@ -419,17 +436,4 @@
 		}
 		return rtn;
 	}
-
-	/**
-	 * Just a friendly renaming of {@link #getConstantName}; in fact this method just simply delegates to that one.
-	 *
-	 * @param tokenTypeInterface The *TokenTypes interface (or one of its implementors).
-	 * @param tokenType The token type value.
-	 * @return The corresponding name.
-	 *
-	 * @see #getConstantName
-	 */
-	public static String getTokenTypeName(Class tokenTypeInterface, int tokenType) {
-		return getConstantName( tokenTypeInterface, tokenType );
-	}
 }

Deleted: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorCounter.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -1,95 +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.util;
-
-import antlr.RecognitionException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.QueryException;
-import org.hibernate.sql.ast.QuerySyntaxException;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * An error handler that counts parsing errors and warnings.
- */
-public class ErrorCounter implements ParseErrorHandler {
-	private Log log = LogFactory.getLog( ErrorCounter.class );
-
-	private List errorList = new ArrayList();
-	private List warningList = new ArrayList();
-	private List recognitionExceptions = new ArrayList();
-
-	public void reportError(RecognitionException e) {
-		String msg = e.toString();
-		reportError( msg );
-		recognitionExceptions.add( e );
-		if ( log.isTraceEnabled() ) {
-			log.trace( msg, e );
-		}
-	}
-
-	public void reportError(String message) {
-		log.error( message );
-		errorList.add( message );
-	}
-
-	public void reportWarning(String message) {
-		log.debug( message );
-		warningList.add( message );
-	}
-
-	public int getErrorCount() {
-		return errorList.size();
-	}
-
-	private String getErrorString() {
-		StringBuffer buf = new StringBuffer();
-		for ( Iterator iterator = errorList.iterator(); iterator.hasNext(); ) {
-			buf.append( ( String ) iterator.next() );
-			if ( iterator.hasNext() ) buf.append( "\n" );
-
-		}
-		return buf.toString();
-	}
-
-	public void throwQueryException() throws QueryException {
-		if ( getErrorCount() > 0 ) {
-			if ( recognitionExceptions.size() > 0 ) {
-				throw QuerySyntaxException.convert( ( RecognitionException ) recognitionExceptions.get( 0 ) );
-			}
-			else {
-				throw new QueryException( getErrorString() );
-			}
-		}
-		else {
-			// all clear
-			if ( log.isDebugEnabled() ) {
-				log.debug( "throwQueryException() : no errors" );
-			}
-		}
-	}
-}
\ No newline at end of file

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorHandlerDelegateImpl.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorHandlerDelegateImpl.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorHandlerDelegateImpl.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -23,16 +23,17 @@
  */
 package org.hibernate.sql.ast.util;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
 import antlr.RecognitionException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import org.hibernate.QueryException;
 import org.hibernate.sql.ast.QuerySyntaxException;
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
 /**
  * An implementation of the {@link ErrorHandlerDelegate} contract.
  *
@@ -40,7 +41,7 @@
  * @author Steve Ebersole
  */
 public class ErrorHandlerDelegateImpl implements ErrorHandlerDelegate {
-	private static final Log log = LogFactory.getLog( ErrorHandlerDelegateImpl.class );
+	private static final Logger log = LoggerFactory.getLogger( ErrorHandlerDelegateImpl.class );
 
 	private List errorList = new ArrayList();
 	private List recognitionExceptions = new ArrayList();

Deleted: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ErrorReporter.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -1,39 +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.util;
-
-import antlr.RecognitionException;
-
-/**
- * Implementations will report or handle errors invoked by an ANTLR base parser.
- *
- * @author Joshua Davis
- */
-public interface ErrorReporter {
-	void reportError(RecognitionException e);
-
-	void reportError(String s);
-
-	void reportWarning(String s);
-}
\ No newline at end of file

Deleted: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/ParseErrorHandler.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -1,39 +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.util;
-
-import org.hibernate.QueryException;
-
-
-/**
- * Defines the behavior of an error handler for the Hibernate parsers.
- *
- * @author Joshua Davis
- */
-public interface ParseErrorHandler extends ErrorReporter {
-
-	int getErrorCount();
-
-	void throwQueryException() throws QueryException;
-}
\ No newline at end of file

Modified: core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/main/java/org/hibernate/sql/ast/util/PathHelper.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -28,10 +28,9 @@
 
 import antlr.ASTFactory;
 import antlr.collections.AST;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
 /**
  * Provides utility methods for dealing with path expressions.
  * <p/>
@@ -41,7 +40,7 @@
  * @author Steve Ebersole
  */
 public final class PathHelper implements Sql92TokenTypes {
-	private static final Log log = LogFactory.getLog( PathHelper.class );
+	private static final Logger log = LoggerFactory.getLogger( PathHelper.class );
 
 	/**
 	 * Direct instantiation of PathHelper disallowed.

Modified: core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizerTest.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizerTest.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/normalize/NormalizerTest.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -34,10 +34,6 @@
 import org.hibernate.cfg.Environment;
 import org.hibernate.dialect.HSQLDialect;
 import org.hibernate.sql.ast.util.NodeTraverser;
-import org.hibernate.sql.ast.phase.hql.normalize.HqlNormalizer;
-import org.hibernate.sql.ast.phase.hql.normalize.QuerySpec;
-import org.hibernate.sql.ast.phase.hql.normalize.SelectItem;
-import org.hibernate.sql.ast.phase.hql.normalize.SelectStatement;
 import org.hibernate.sql.ast.phase.hql.parse.ParserTest;
 import org.hibernate.sql.ast.phase.hql.domain.Animal;
 import org.hibernate.sql.ast.common.JoinType;
@@ -72,7 +68,7 @@
 	}
 
 	public void testBasicStructure() throws Throwable {
-		AST query = resolve( "select a from Animal a order by a.name" );
+		AST query = normalize( "select a from Animal a order by a.name" );
 		assertEquals( query.getType(), QUERY );
 
 		AST querySpec = query.getFirstChild();
@@ -99,26 +95,26 @@
 
 	public void testSimpleHql() throws Exception {
 		// First, get an AST by parsing some HQL text.
-		AST ast = resolve( "from Animal" );
+		AST ast = normalize( "from Animal" );
 		// Assert:
 		assertEquals( ast.getType(), QUERY );
 	}
 
 	public void testSimpleExplicitJoins() throws Throwable {
-		AST ast = resolve( "from Animal as a inner join a.mother as m" );
+		AST ast = normalize( "from Animal as a inner join a.mother as m" );
 		JoinCounter.assertJoinCount( 1, ast );
 
-		ast = resolve( "from Animal as a inner join a.offspring as c inner join a.mother as m" );
+		ast = normalize( "from Animal as a inner join a.offspring as c inner join a.mother as m" );
 		JoinCounter.assertJoinCount( 2, ast );
 	}
 
 	public void testPathedExplicitJoins() throws Throwable {
-		AST ast = resolve( "from Animal as a inner join a.mother.father.offspring as auntsanduncles" );
+		AST ast = normalize( "from Animal as a inner join a.mother.father.offspring as auntsanduncles" );
 		JoinCounter.assertJoinCount( 3, ast );
 	}
 
 	public void testSelectPersisterReference() throws Throwable {
-		AST query = resolve( "select a from Animal a" );
+		AST query = normalize( "select a from Animal a" );
 		JoinCounter.assertJoinCount( 0, query );
 		SelectItemCounter.assertSelectItemCount( 1, query );
 
@@ -135,7 +131,7 @@
 
 	public void testSelectAssociationPropertyReference() throws Throwable {
 		// todo : implicit joins...
-		AST query = resolve( "select a.mother as m from Animal as a" );
+		AST query = normalize( "select a.mother as m from Animal as a" );
 		JoinCounter.assertJoinCount( 1, query );
 
 		assertTrue( query instanceof SelectStatement );
@@ -148,7 +144,7 @@
 		Join join = ( Join ) itr.next();
 		assertFalse( itr.hasNext() );
 		assertEquals( JoinType.INNER, join.getEnumeratedJoinType() );
-		PersisterReference rhs = join.getRhs();
+		PersisterReference rhs = join.locateRhs();
 		assertEquals( Animal.class.getName(), rhs.getName() );
 		// this should work since there is only one non-explicit persister alias...
 		assertEquals( "<gen:0>", rhs.getAlias() );
@@ -166,7 +162,7 @@
 	}
 
 	public void testSimpleSimplePropertyReference() throws Throwable {
-		AST query = resolve( "select a.name as m from Animal as a" );
+		AST query = normalize( "select a.name as m from Animal as a" );
 		JoinCounter.assertJoinCount( 0, query );
 		SelectItemCounter.assertSelectItemCount( 1, query );
 		assertTrue( query instanceof SelectStatement );
@@ -187,7 +183,7 @@
 	}
 
 	public void testSelectPropertyRefCount() throws Throwable {
-		AST query = resolve( "select count(a.mother) from Animal as a" );
+		AST query = normalize( "select count(a.mother) from Animal as a" );
 		JoinCounter.assertJoinCount( 0, query );
 		SelectItemCounter.assertSelectItemCount( 1, query );
 		assertTrue( query instanceof SelectStatement );
@@ -206,110 +202,135 @@
 	}
 
 	public void testExplicitImplicitJoin() throws Exception {
-		AST ast = resolve( "from Animal a left join fetch a.mother.mother.mother as ggm where ggm.name like '%weeble%'" );
+		AST ast = normalize( "from Animal a left join fetch a.mother.mother.mother as ggm where ggm.name like '%weeble%'" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 3, ast );
 
-		ast = resolve( "from Animal as a inner join a.mother.mother as gm" );
+		ast = normalize( "from Animal as a inner join a.mother.mother as gm" );
 		JoinCounter.assertJoinCount( 2, ast );
 
-		ast = resolve( "from Animal as a inner join a.mother.father as gf" );
+		ast = normalize( "from Animal as a inner join a.mother.father as gf" );
 		JoinCounter.assertJoinCount( 2, ast );
 
-		ast = resolve( "from Animal as a inner join a.offspring as c inner join a.mother.father as mgf inner join fetch a.father" );
+		ast = normalize( "from Animal as a inner join a.offspring as c inner join a.mother.father as mgf inner join fetch a.father" );
 		JoinCounter.assertJoinCount( 4, ast );
 	}
 
 	public void testExplicitCollectionJoin() throws Throwable {
-		AST ast = resolve( "from Animal as a inner join a.offspring as o where o.name like '%boots%'" );
+		normalize( "from Animal as a inner join a.offspring as o where o.name like '%boots%'" );
 	}
 
 	public void testSimpleImplicitJoin() throws Exception {
-		AST ast = resolve( "from Animal a where a.mother.name like '%mary%'" );
+		AST ast = normalize( "from Animal a where a.mother.name like '%mary%'" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 1, ast );
 
-		ast = resolve( "from Animal a where a.mother.father.name like '%weeble%'" );
+		ast = normalize( "from Animal a where a.mother.father.name like '%weeble%'" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 2, ast );
 
-		ast = resolve( "from Animal a where a.mother.mother.name like '%weeble%'" );
+		ast = normalize( "from Animal a where a.mother.mother.name like '%weeble%'" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 2, ast );
 
-		ast = resolve( "from Animal a where a.mother.mother = ?" );
+		ast = normalize( "from Animal a where a.mother.mother = ?" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 1, ast );
 	}
 
 	public void testWithClause() throws Throwable {
-		resolve( "from Zoo z inner join z.mammals as m with m.name = ?" );
+		normalize( "from Zoo z inner join z.mammals as m with m.name = ?" );
 	}
 
 	public void testUnqualifiedPropertyReference() throws Exception {
-		AST ast = resolve( "from Animal where name like '%mary%'" );
+		AST ast = normalize( "from Animal where name like '%mary%'" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 0, ast );
 
-		ast = resolve( "from Animal where mother.name like '%mary%'" );
+		ast = normalize( "from Animal where mother.name like '%mary%'" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 1, ast );
 	}
 
 	public void testThetaJoins() throws Exception {
-		AST ast = resolve( "from Animal a, Animal b where a.mother.id = b.id and b.name like '%mary%'" );
+		AST ast = normalize( "from Animal a, Animal b where a.mother.id = b.id and b.name like '%mary%'" );
 		assertTrue( ast instanceof SelectStatement );
 //		JoinCounter.assertJoinCount( 1, ast );
 
-		ast = resolve( "from Animal a, Animal b inner join b.mother as c where a.mother.id = b.id and b.name like '%mary%'" );
+		ast = normalize( "from Animal a, Animal b inner join b.mother as c where a.mother.id = b.id and b.name like '%mary%'" );
 		assertTrue( ast instanceof SelectStatement );
 //		JoinCounter.assertJoinCount( 2, ast );
 	}
 
 	public void testAdHocJoins() throws Exception {
-		resolve( "from Animal a inner join Zoo z on a.id = z.id" );
-		resolve( "from Animal a inner join Zoo z on a.id = z.id inner join z.mammals as m with m.name = ?" );
+		normalize( "from Animal a inner join Zoo z on a.id = z.id" );
+		normalize( "from Animal a inner join Zoo z on a.id = z.id inner join z.mammals as m with m.name = ?" );
 	}
 
 	public void testReusingImplcitJoins() throws Throwable {
-		AST ast = resolve( "from Animal a where a.mother.father.name = 'abc' and a.mother.father.description = 'xyz'" );
+		AST ast = normalize( "from Animal a where a.mother.father.name = 'abc' and a.mother.father.description = 'xyz'" );
 		assertTrue( ast instanceof SelectStatement );
 		JoinCounter.assertJoinCount( 2, ast );
 	}
 
-	public void testIndexOperations() throws Throwable {
-//		resolve( "select o from IndexedCollectionOwner as o where o.simpleMap['test'] = 'xyz'" );
-		resolve( "select o from IndexedCollectionOwner as o inner join o.simpleMap as s where o.simpleMap[ index(s) ] = 'xyz'" );
-	}
+// these entities were not copied over...
+//	public void testIndexOperations() throws Throwable {
+//		normalize( "select o from IndexedCollectionOwner as o where o.simpleMap['test'] = 'xyz'" );
+//		normalize( "select o from IndexedCollectionOwner as o inner join o.simpleMap as s where o.simpleMap[ index(s) ] = 'xyz'" );
+//	}
 
 	public void testIndexOperations2() throws Throwable {
-		resolve( "from Zoo zoo join zoo.animals an where zoo.mammals[ index(an) ] = an" );
-		resolve( "from Zoo where mammals['dog'] = ?" );
-		resolve( "from Zoo zoo where zoo.mammals['dog'].father.description like '%black%'" );
+		normalize( "select zoo from Zoo as zoo where zoo.mammals['dog'] = maxelement(zoo.mammals)" );
+		normalize( "select zoo from Zoo as zoo where zoo.mammals['dog'].description = 'abc'" );
+		normalize( "from Zoo zoo join zoo.animals an where zoo.mammals[ index(an) ] = an" );
+		normalize( "from Zoo where mammals['dog'] = ?" );
+		normalize( "from Zoo zoo where zoo.mammals['dog'].father.description like '%black%'" );
 	}
 
+	public void testFilters() throws Exception {
+		String role = Animal.class.getName() + ".offspring";
+		normalizeFilter( "", role );
+		normalizeFilter( "order by this.id", role );
+		normalizeFilter( "where this.name = ?", role );
+	}
 
+
 	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-	private AST resolve(String hql) throws RecognitionException, TokenStreamException {
-		// to be completely accurate, the incoming hql string should be run through
-		// QuerySplitter as that is what happens prior to translation and results in
-		// a different string to actually translate...
-		String[] queries = QuerySplitter.concreteQueries( hql, getSessionFactoryImplementor() );
-		assertEquals( "polymorhpic queries not allowed here", 1, queries.length );
-		hql = queries[0];
+	private AST normalize(String hql) throws RecognitionException, TokenStreamException {
+		return normalize( hql, getSessionFactoryImplementor() );
+	}
 
-		AST hqlAst = ParserTest.doParse( hql, false );
+	private AST normalizeFilter(String hql, String role) throws RecognitionException, TokenStreamException {
+		return normalizeFilter( hql, role, getSessionFactoryImplementor() );
+	}
 
-		// Now, pass it though the resolver phase, which yeilds
-		// a processed HQL AST.
-		HqlNormalizer resolver = new HqlNormalizer( sessionFactory );
-		resolver.statement( hqlAst );
-		AST resolvedHql = resolver.getAST();
-		System.out.println( resolver.getPrinter().showAsString( resolvedHql, "Resolved AST  :  " + resolvedHql.toStringTree() + "" ) );
-		return resolvedHql;
+	public static AST normalize(String hql, SessionFactoryImplementor sessionFactory) throws TokenStreamException, RecognitionException {
+		AST hqlAst = ParserTest.parse( splitQuery( hql, sessionFactory ) );
+
+		HqlNormalizer normalizer = new HqlNormalizer( sessionFactory );
+		normalizer.statement( hqlAst );
+		AST normalizedAST = normalizer.getAST();
+		System.out.println( normalizer.getPrinter().showAsString( normalizedAST, "Normalized query AST" ) );
+		return normalizedAST;
 	}
 
+	public static AST normalizeFilter(String hql, String role, SessionFactoryImplementor sessionFactory) throws TokenStreamException, RecognitionException {
+		AST hqlAst = ParserTest.parseFilter( splitQuery( hql, sessionFactory ), role );
+
+		HqlNormalizer normalizer = new HqlNormalizer( sessionFactory );
+		normalizer.statement( hqlAst );
+		AST normalizedAST = normalizer.getAST();
+		System.out.println( normalizer.getPrinter().showAsString( normalizedAST, "Normalized filter AST" ) );
+		return normalizedAST;
+	}
+
+	private static String splitQuery(String hql, SessionFactoryImplementor sessionFactory) {
+		String[] queries = QuerySplitter.concreteQueries( hql, sessionFactory );
+		assertEquals( "polymorhpic queries not allowed here", 1, queries.length );
+		return queries[0];
+	}
+
 	protected SessionFactoryImplementor getSessionFactoryImplementor() {
 		return sessionFactory;
 	}

Modified: core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/parse/ParserTest.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/parse/ParserTest.java	2009-02-09 19:27:30 UTC (rev 15918)
+++ core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/parse/ParserTest.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -4,7 +4,6 @@
 import org.hibernate.sql.ast.util.ASTIterator;
 import org.hibernate.sql.ast.common.Node;
 import org.hibernate.sql.ast.util.ASTPrinter;
-import org.hibernate.sql.ast.phase.hql.parse.HqlParser;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -1013,15 +1012,15 @@
 	}
 
 	public void testEmptyFilter() throws Exception {
-		parseFilter( "" );  //  Blank is a legitimate filter.
+		parseFilter( "", "Owner.collection" );  //  Blank is a legitimate filter.
 	}
 
 	public void testOrderByFilter() throws Exception {
-		parseFilter( "order by this.id" );
+		parseFilter( "order by this.id", "Owner.collection" );
 	}
 
 	public void testRestrictionFilter() throws Exception {
-		parseFilter( "where this.name = ?" );
+		parseFilter( "where this.name = ?", "Owner.collection" );
 	}
 
 	public void testNoFrom() throws Exception {
@@ -1099,7 +1098,7 @@
 		parse("select distinct user.party from com.itf.iceclaims.domain.party.user.UserImpl user inner join user.party.$RelatedWorkgroups relatedWorkgroups where relatedWorkgroups.workgroup.id = :workgroup and relatedWorkgroups.effectiveTime.start <= :datesnow and relatedWorkgroups.effectiveTime.end > :dateenow ");
 	}
 	public void testLineAndColumnNumber() throws Exception {
-		AST ast = doParse("from Foo f\nwhere f.name = 'fred'",false);
+		AST ast = parse("from Foo f\nwhere f.name = 'fred'" );
 		// Find some of the nodes and check line and column values.
 		ASTIterator iter = new ASTIterator(ast);
 		boolean foundFoo = false;
@@ -1131,30 +1130,27 @@
 	}
 
 
-	private void parse(String input) throws RecognitionException, TokenStreamException {
-		doParse( input, false );
+	public static AST parse(String input) throws RecognitionException, TokenStreamException {
+		HqlParser parser = buildHqlParser( input );
+		parser.statement();
+		return extractAST( parser );
 	}
 
-	private void parseFilter(String input) throws TokenStreamException, RecognitionException {
-		doParse( input, true );
+	public static AST parseFilter(String input, String collectionRole) throws TokenStreamException, RecognitionException {
+		HqlParser parser = buildHqlParser( input );
+		parser.filterStatement( collectionRole );
+		return extractAST( parser );
 	}
 
-	public static AST doParse(String input, boolean isFilter) throws RecognitionException, TokenStreamException {
-		System.out.println( "input: ->" + ASTPrinter.escapeMultibyteChars(input) + "<-" );
-		HqlParser parser = buildHqlParser( input );
-		if ( isFilter ) {
-			parser.filterStatement();
-		}
-		else {
-			parser.statement();
-		}
+	private static AST extractAST(HqlParser parser) {
 		AST ast = parser.getAST();
-		show( ast, "AST [" + ast.toStringTree() + "]" );
+		show( ast, "Parsed AST" );
 		assertEquals( "At least one error occurred during parsing!", 0, parser.getParseErrorHandler().getErrorCount() );
 		return ast;
 	}
 
 	private static HqlParser buildHqlParser(String hql) {
+		System.out.println( "input: ->" + ASTPrinter.escapeMultibyteChars( hql ) + "<-" );
 		return new HqlParser(
 				hql,
 				new HqlParser.Context() {

Added: core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/resolve/ResolverTest.java
===================================================================
--- core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/resolve/ResolverTest.java	                        (rev 0)
+++ core/branches/SQL_GEN_REDESIGN/src/test/java/org/hibernate/sql/ast/phase/hql/resolve/ResolverTest.java	2009-02-09 19:32:49 UTC (rev 15919)
@@ -0,0 +1,117 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * 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.phase.hql.resolve;
+
+import junit.framework.TestCase;
+
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.sql.ast.util.ASTPrinter;
+import org.hibernate.sql.ast.util.NodeDeepCopier;
+import org.hibernate.sql.ast.phase.hql.domain.Animal;
+import org.hibernate.sql.ast.phase.hql.domain.Human;
+import org.hibernate.sql.ast.phase.hql.normalize.NormalizerTest;
+import org.hibernate.persister.entity.AbstractEntityPersister;
+
+import antlr.ASTFactory;
+import antlr.TokenStreamException;
+import antlr.RecognitionException;
+import antlr.collections.AST;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class ResolverTest extends TestCase {
+	private static ASTPrinter printer = new ASTPrinter( HqlResolveTokenTypes.class );
+	private SessionFactoryImplementor sessionFactory;
+
+	protected void setUp() throws Exception {
+		super.setUp();
+		sessionFactory = ( SessionFactoryImplementor ) new Configuration()
+				.setProperty( Environment.HBM2DDL_AUTO, "none" )
+				.setProperty( Environment.DIALECT, HSQLDialect.class.getName() )
+				.addResource( "org/hibernate/sql/ast/phase/hql/domain/Mappings.hbm.xml" )
+				.buildSessionFactory();
+	}
+
+	protected void tearDown() throws Exception {
+		if ( sessionFactory != null ) {
+			sessionFactory.close();
+		}
+		super.tearDown();
+	}
+
+	public void testResolve() throws Throwable {
+//		resolve( "from Animal a" );
+//		resolve( "select a.description from Animal a" );
+		resolve( "select a from Animal a" );
+	}
+
+	public void testFilters() throws Exception {
+		String role = Animal.class.getName() + ".offspring";
+		AST ast = resolveFilter( "", role );
+		resolveFilter( "order by this.id", role );
+		resolveFilter( "where this.name = ?", role );
+	}
+
+	public void testPropertyJoins() throws Throwable {
+		resolve( "from Animal a inner join a.father as f" );
+	}
+
+	public void testPersisterJoins() throws Throwable {
+//		resolve( "from Animal a, Animal b" );
+		resolve( "from Animal a cross join Animal b" );
+//		resolve( "from Animal a inner join Animal b on a.mother = b.father" );
+	}
+
+	private AST resolve(String hql) throws TokenStreamException, RecognitionException {
+		return resolve( hql, sessionFactory );
+	}
+
+	private AST resolveFilter(String hql, String role) throws TokenStreamException, RecognitionException {
+		return resolveFilter( hql, role, sessionFactory );
+	}
+
+	public static AST resolve(String hql, SessionFactoryImplementor sessionFactory) throws TokenStreamException, RecognitionException {
+		AST normalizedAST = NormalizerTest.normalize( hql, sessionFactory );
+		return resolve( normalizedAST, sessionFactory );
+	}
+
+	public static AST resolveFilter(String hql, String role, SessionFactoryImplementor sessionFactory) throws TokenStreamException, RecognitionException {
+		AST normalizedAST = NormalizerTest.normalizeFilter( hql, role, sessionFactory );
+		return resolve( normalizedAST, sessionFactory );
+	}
+
+	private static AST resolve(AST normalizedAST, SessionFactoryImplementor sessionFactory) throws RecognitionException {
+		HqlResolver resolver = new HqlResolver( sessionFactory );
+		resolver.statement( normalizedAST );
+		AST resolvedAST = resolver.getAST();
+		System.out.println( printer.showAsString( resolvedAST, "Resolved AST" ) );
+		return resolvedAST;
+	}
+}




More information about the hibernate-commits mailing list