[hibernate-commits] Hibernate SVN: r16388 - in core/branches/antlr3/src/main/java/org/hibernate: sql/ast/phase/hql/resolve and 3 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Tue Apr 21 14:29:41 EDT 2009
Author: steve.ebersole at jboss.com
Date: 2009-04-21 14:29:41 -0400 (Tue, 21 Apr 2009)
New Revision: 16388
Added:
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategyStack.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractPathResolutionStrategy.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractUnexpectedPropertyTypeException.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/BasicPathResolutionStrategySupport.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/CollectionExpectedException.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/IndexedCollectionExectedException.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/InvalidPropertyJoinException.java
Modified:
core/branches/antlr3/src/main/java/org/hibernate/QueryException.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterSpace.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterTableExpressionGenerator.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/ResolutionContext.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategy.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathedPropertyReferenceSource.java
core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java
Log:
initial path resolution
Modified: core/branches/antlr3/src/main/java/org/hibernate/QueryException.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/QueryException.java 2009-04-21 18:19:38 UTC (rev 16387)
+++ core/branches/antlr3/src/main/java/org/hibernate/QueryException.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -32,9 +32,14 @@
private String queryString;
+ protected QueryException() {
+ super( "<expecting override of message building>" );
+ }
+
public QueryException(String message) {
super(message);
}
+
public QueryException(String message, Throwable e) {
super(message, e);
}
@@ -47,6 +52,7 @@
public QueryException(Exception e) {
super(e);
}
+
public String getQueryString() {
return queryString;
}
@@ -56,11 +62,16 @@
}
public String getMessage() {
- String msg = super.getMessage();
- if ( queryString!=null ) msg += " [" + queryString + ']';
+ String msg = internalGetMessage();
+ if ( queryString != null ) {
+ msg += " [" + queryString + ']';
+ }
return msg;
}
+ protected String internalGetMessage() {
+ return super.getMessage();
+ }
}
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterSpace.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterSpace.java 2009-04-21 18:19:38 UTC (rev 16387)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterSpace.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -28,19 +28,41 @@
*/
package org.hibernate.sql.ast.phase.hql.resolve;
-import java.util.List;
-
-import org.antlr.runtime.tree.Tree;
-
import org.hibernate.type.Type;
+import org.hibernate.sql.ast.tree.Table;
/**
*
* @author Steve Ebersole
*/
public interface PersisterSpace {
- public String getAlias();
- public List<Tree> getTables();
+ /**
+ * Retrieve the corresponding alias from the input (HQL, etc).
+ *
+ * @return The source alias.
+ */
+ public String getSourceAlias();
+ /**
+ * Retrieve the name of the underlying persister.
+ *
+ * @return The persister name.
+ */
+ public String getName();
+
+ /**
+ * Retrieve the short (unqualified) version of the persister name.
+ * <p/>
+ * Useful for alias basing.
+ *
+ * @return The persister short name.
+ */
+ public String getShortName();
+
+ public Table.TableSpace getTableSpace();
+
public Type getPropertyType(String propertyName);
+
+ public Table locateReusablePropertyJoinedTable(String propertyName);
+ public void registerReusablePropertyJoinedTable(String propertyName, Table table);
}
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterTableExpressionGenerator.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterTableExpressionGenerator.java 2009-04-21 18:19:38 UTC (rev 16387)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/PersisterTableExpressionGenerator.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -30,6 +30,7 @@
package org.hibernate.sql.ast.phase.hql.resolve;
import org.hibernate.persister.MappedTableMetadata;
+import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.ast.alias.TableAliasGenerator;
import org.hibernate.sql.ast.common.HibernateTree;
@@ -44,6 +45,7 @@
* @author Steve Ebersole
*/
public class PersisterTableExpressionGenerator {
+
public static Table generateTableExpression(
Queryable persister,
TableAliasGenerator.TableAliasRoot aliasRoot,
@@ -57,14 +59,13 @@
int suffix = 0;
- MappedTableMetadata.JoinedTable[] tables = tableMetadata.getJoinedTables();
- for ( int i = 0; i < tables.length; i++ ) {
+ for ( MappedTableMetadata.JoinedTable joinedTable : tableMetadata.getJoinedTables() ) {
final String joinTableAlias = aliasRoot.generate( ++suffix );
- final Table table = generateTableReference( tables[i].getName(), joinTableAlias, tableSpace );
+ final Table table = generateTableReference( joinedTable.getName(), joinTableAlias, tableSpace );
final HibernateTree join = new HibernateTree( HQLParser.JOIN, "join" );
drivingTable.addChild( join );
- if ( tables[i].useInnerJoin() ) {
+ if ( joinedTable.useInnerJoin() ) {
join.addChild( new HibernateTree( HQLParser.INNER, "inner" ) );
}
else {
@@ -78,7 +79,7 @@
drivingTableAlias,
drivingTableJoinColumns,
joinTableAlias,
- tables[i].getKeyColumns()
+ joinedTable.getKeyColumns()
);
on.addChild( joinCondition );
}
@@ -86,6 +87,57 @@
return drivingTable;
}
+ public static Table generateTableExpression(
+ QueryableCollection collectionPersister,
+ TableAliasGenerator.TableAliasRoot aliasRoot,
+ Table.CollectionTableSpace tableSpace) {
+ if ( collectionPersister.isOneToMany() ) {
+ Table table = generateTableExpression(
+ ( Queryable ) collectionPersister.getElementPersister(),
+ aliasRoot,
+ tableSpace.getEntityElementTableSpace()
+ );
+ tableSpace.setCollectionTable( table );
+ return table;
+ }
+ else {
+ Table associationTable = generateTableReference(
+ collectionPersister.getTableName(),
+ aliasRoot.generateCollectionTableAlias(),
+ tableSpace
+ );
+ tableSpace.setCollectionTable( associationTable );
+
+ if ( collectionPersister.isManyToMany() ) {
+ Queryable elementPersister = ( Queryable ) collectionPersister.getElementPersister();
+ Table drivingTable = generateTableExpression(
+ elementPersister,
+ aliasRoot,
+ tableSpace.getEntityElementTableSpace()
+ );
+
+ final HibernateTree join = new HibernateTree( HQLParser.JOIN );
+ associationTable.addChild( join );
+ join.addChild( new HibernateTree( HQLParser.LEFT, "left outer" ) );
+ join.addChild( drivingTable );
+
+ String[] entityFkColumnNames = collectionPersister.getElementColumnNames();
+ String[] entityPkColumnNames = elementPersister.getKeyColumnNames();
+
+ final HibernateTree on = new HibernateTree( HQLParser.ON );
+ join.addChild( on );
+ final HibernateTree joinCondition = generateJoinCorrelation(
+ associationTable.getAliasText(),
+ entityFkColumnNames,
+ drivingTable.getAliasText(),
+ entityPkColumnNames
+ );
+ on.addChild( joinCondition );
+ }
+ return associationTable;
+ }
+ }
+
private static Table generateTableReference(String tableName, String tableAlias, Table.TableSpace tableSpace) {
Table table = new Table( HQLParser.TABLE, tableSpace );
table.addChild( new HibernateTree( HQLParser.IDENTIFIER, tableName ) );
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/ResolutionContext.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/ResolutionContext.java 2009-04-21 18:19:38 UTC (rev 16387)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/ResolutionContext.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -32,7 +32,7 @@
import org.antlr.runtime.tree.TreeAdaptor;
import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.sql.ast.alias.ImplicitAliasGenerator;
+import org.hibernate.sql.ast.alias.TableAliasGenerator;
import org.hibernate.sql.ast.util.TreePrinter;
import org.hibernate.sql.ast.phase.hql.resolve.path.PathResolutionStrategy;
@@ -52,13 +52,6 @@
public TreeAdaptor getTreeAdaptor();
-// /**
-// * The alias builder available in this context.
-// *
-// * @return The alias builder.
-// */
-// public ImplicitAliasGenerator getAliasBuilder();
-
/**
* The current {@link PersisterSpaceContext} for this context. The {@link PersisterSpaceContext}
* can change in relation to subqueries and such. See {@link PersisterSpaceContext} docs for more info.
@@ -88,6 +81,8 @@
*/
public TreePrinter getTreePrinter();
+ public TableAliasGenerator getTableAliasGenerator();
+
/**
* Is this context currently processing a function?
*
@@ -97,7 +92,7 @@
public PathResolutionStrategy getCurrentPathResolutionStrategy();
-// public void registerAssociationFetch(Join join);
-//
-// public void registerPropertyFetch(PersisterReference persisterReference);
+ public void registerAssociationFetch(PersisterSpace persisterSpace);
+
+ public void registerPropertyFetch(PersisterSpace persisterSpace);
}
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategy.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategy.java 2009-04-21 18:19:38 UTC (rev 16387)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategy.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -30,7 +30,6 @@
package org.hibernate.sql.ast.phase.hql.resolve.path;
import org.hibernate.sql.ast.phase.hql.resolve.PersisterSpace;
-import org.hibernate.sql.ast.phase.hql.resolve.PropertyPathTerminus;
import org.hibernate.sql.ast.common.HibernateTree;
/**
@@ -67,7 +66,7 @@
*
* @return The terminal property reference indicated by the overall path.
*/
- public PropertyPathTerminus handleTerminalPathPart(PathedPropertyReferenceSource source, String pathPart);
+ public HibernateTree handleTerminalPathPart(PathedPropertyReferenceSource source, String pathPart);
/**
* Handle an index access operation (a.b[selector] for example). In this particular case the index access
@@ -91,5 +90,5 @@
*
* @return The terminal property reference indicated by the overall path.
*/
- public PropertyPathTerminus handleTerminalIndexAccess(PathedPropertyReferenceSource source, String pathPart, HibernateTree selector);
+ public HibernateTree handleTerminalIndexAccess(PathedPropertyReferenceSource source, String pathPart, HibernateTree selector);
}
Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategyStack.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategyStack.java (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathResolutionStrategyStack.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -0,0 +1,53 @@
+/*
+ * 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.path;
+
+import java.util.LinkedList;
+
+/**
+ * Provides a stack of {@link PathResolutionStrategy} instances.
+ *
+ * @author Steve Ebersole
+ */
+public class PathResolutionStrategyStack {
+ private LinkedList<PathResolutionStrategy> stack = new LinkedList<PathResolutionStrategy>();
+
+ public void push(PathResolutionStrategy handler) {
+ stack.addFirst( handler );
+ }
+
+ public PathResolutionStrategy pop() {
+ return stack.removeFirst();
+ }
+
+ public PathResolutionStrategy getCurrent() {
+ return stack.getFirst();
+ }
+}
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathedPropertyReferenceSource.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathedPropertyReferenceSource.java 2009-04-21 18:19:38 UTC (rev 16387)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/PathedPropertyReferenceSource.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -26,13 +26,11 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-
package org.hibernate.sql.ast.phase.hql.resolve.path;
import org.antlr.runtime.tree.Tree;
import org.hibernate.sql.ast.common.HibernateTree;
-import org.hibernate.sql.ast.phase.hql.resolve.PropertyPathTerminus;
/**
* The contract for representing the non-terminal parts of a property path expression
@@ -66,7 +64,7 @@
*
* @return The property reference terminus.
*/
- public PropertyPathTerminus handleTerminalPathPart(String name);
+ public HibernateTree handleTerminalPathPart(String name);
/**
* Handle an index access operation (a.b[selector] for example). In this particular case the index access
@@ -88,5 +86,5 @@
*
* @return The property reference terminus.
*/
- public PropertyPathTerminus handleTerminalIndexAccess(String collectionPropertyName, HibernateTree selector);
+ public HibernateTree handleTerminalIndexAccess(String collectionPropertyName, HibernateTree selector);
}
Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractPathResolutionStrategy.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractPathResolutionStrategy.java (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractPathResolutionStrategy.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -0,0 +1,595 @@
+/*
+ * 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.path.impl;
+
+import org.antlr.runtime.Token;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.QueryException;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.persister.collection.QueryableCollection;
+import org.hibernate.persister.entity.Queryable;
+import org.hibernate.sql.ast.alias.TableAliasGenerator;
+import org.hibernate.sql.ast.common.HibernateToken;
+import org.hibernate.sql.ast.common.HibernateTree;
+import org.hibernate.sql.ast.phase.hql.parse.HQLParser;
+import org.hibernate.sql.ast.phase.hql.resolve.PersisterSpace;
+import org.hibernate.sql.ast.phase.hql.resolve.PersisterTableExpressionGenerator;
+import org.hibernate.sql.ast.phase.hql.resolve.ResolutionContext;
+import org.hibernate.sql.ast.phase.hql.resolve.path.PathResolutionStrategy;
+import org.hibernate.sql.ast.phase.hql.resolve.path.PathedPropertyReferenceSource;
+import org.hibernate.sql.ast.tree.Table;
+import org.hibernate.sql.ast.util.DisplayableNode;
+import org.hibernate.sql.ast.util.TreePrinter;
+import org.hibernate.type.CollectionType;
+import org.hibernate.type.ComponentType;
+import org.hibernate.type.EntityType;
+import org.hibernate.type.Type;
+
+/**
+ * Abstract implementation of {@link PathResolutionStrategy} providing convenience methods to actual
+ * {@link PathResolutionStrategy} implementors.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractPathResolutionStrategy implements PathResolutionStrategy {
+ private static final Logger log = LoggerFactory.getLogger( AbstractPathResolutionStrategy.class );
+
+ private final ResolutionContext resolutionContext;
+ private String pathThusFar = null;
+
+ protected AbstractPathResolutionStrategy(ResolutionContext resolutionContext) {
+ this.resolutionContext = resolutionContext;
+ }
+
+ // reolution context ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ /**
+ * Getter for property 'resolutionContext'.
+ *
+ * @return Value for property 'resolutionContext'.
+ */
+ protected ResolutionContext resolutionContext() {
+ return resolutionContext;
+ }
+
+ protected final HibernateTree createNode(int type, String text) {
+ return ( HibernateTree ) resolutionContext().getTreeAdaptor().create( type, text );
+ }
+
+ /**
+ * Getter for property 'sessionFactoryImplementor'.
+ *
+ * @return Value for property 'sessionFactoryImplementor'.
+ */
+ protected final SessionFactoryImplementor getSessionFactoryImplementor() {
+ return resolutionContext().getSessionFactoryImplementor();
+ }
+
+ /**
+ * Getter for property 'ASTPrinter'.
+ *
+ * @return Value for property 'ASTPrinter'.
+ */
+ protected final TreePrinter getTreePrinter() {
+ return resolutionContext().getTreePrinter();
+ }
+
+
+ // 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(PersisterSpace persisterSpace) {
+ initializePathSoFar( persisterSpace.getSourceAlias() );
+ log.trace( "handling root path source [" + pathThusFar + "]" );
+ return internalHandleRoot( persisterSpace );
+ }
+
+ /**
+ * Hook for subclasses to process the path root.
+ *
+ * @param persisterSpace The persister defining the source root.
+ * @return The appropriate property path source implementation.
+ */
+ protected abstract PathedPropertyReferenceSource internalHandleRoot(PersisterSpace persisterSpace);
+
+ /**
+ * {@inheritDoc}
+ */
+ public final PathedPropertyReferenceSource handleIntermediatePathPart(PathedPropertyReferenceSource source, String pathPart) {
+ pathThusFar = ( pathThusFar == null ) ? pathPart : pathThusFar + "." + pathPart;
+ 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, String pathPart) {
+ return source.handleIntermediatePathPart( pathPart );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final HibernateTree handleTerminalPathPart(PathedPropertyReferenceSource source, String pathPart) {
+ pathThusFar = ( pathThusFar == null ) ? pathPart : pathThusFar + "." + pathPart;
+ 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 HibernateTree internalResolveTerminalPathPart(PathedPropertyReferenceSource source, String pathPart) {
+ return source.handleTerminalPathPart( pathPart );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final PathedPropertyReferenceSource handleIntermediateIndexAccess(PathedPropertyReferenceSource source, String pathPart, HibernateTree selector) {
+ pathThusFar = ( ( pathThusFar == null ) ? pathPart : pathThusFar + "." + pathPart ) + "[]";
+ 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, String pathPart, HibernateTree selector) {
+ return source.handleIntermediateIndexAccess( pathPart, selector );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final HibernateTree handleTerminalIndexAccess(PathedPropertyReferenceSource source, String pathPart, HibernateTree selector) {
+ pathThusFar = ( ( pathThusFar == null ) ? pathPart : pathThusFar + "." + pathPart ) + "[]";
+ 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 HibernateTree internalHandleTerminalIndexAccess(PathedPropertyReferenceSource source, String pathPart, HibernateTree 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 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 + "]" );
+ }
+
+ /**
+ * 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(PersisterSpace origin, String property) {
+ log.debug( "creating path expression implied join [" + origin.getSourceAlias() + "].[" + 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 HQLParser#INNER} join.
+ *
+ * @return The join type node.
+ */
+ protected HibernateTree buildJoinTypeNode() {
+ return createNode( HQLParser.INNER, "inner" );
+ }
+
+ /**
+ * Does this strategy allows property joins to be reused?
+ *
+ * @return True/false.
+ */
+ protected boolean areJoinsReusable() {
+ return true;
+ }
+
+ /**
+ * Locate (if property joins are reusable) or build an appropriate joined table.
+ *
+ * @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 Table locateOrBuildPropertyJoinedTable(
+ PersisterSpace lhs,
+ String propertyName,
+ String alias,
+ boolean propertyFetching,
+ boolean associationFetching) {
+ Table joinedTable = null;
+ if ( areJoinsReusable() ) {
+ joinedTable = lhs.locateReusablePropertyJoinedTable( propertyName );
+ }
+
+ if ( joinedTable == null ) {
+ joinedTable = buildPropertyJoinedTable( lhs, propertyName, alias, propertyFetching, associationFetching );
+ if ( areJoinsReusable() ) {
+ lhs.registerReusablePropertyJoinedTable( propertyName, joinedTable );
+ }
+ }
+
+ return joinedTable;
+ }
+
+ /**
+ * Build a property joined table
+ *
+ * @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 Table buildPropertyJoinedTable(
+ PersisterSpace lhs,
+ String propertyName,
+ String alias,
+ boolean propertyFetching,
+ boolean associationFetching) {
+ validateJoinCreation( lhs, propertyName );
+ Table joinedTable;
+ Type propertyType = lhs.getPropertyType( propertyName );
+ if ( propertyType.isEntityType() ) {
+ EntityType entityType = ( EntityType ) propertyType;
+ Queryable entityPersister = ( Queryable ) getSessionFactoryImplementor()
+ .getEntityPersister( entityType.getAssociatedEntityName( getSessionFactoryImplementor() ) );
+ joinedTable = createJoin( lhs, entityPersister, alias );
+ }
+ else if ( propertyType.isCollectionType() ) {
+ CollectionType collectionType = ( CollectionType ) propertyType;
+ QueryableCollection collectionPersister = ( QueryableCollection ) getSessionFactoryImplementor()
+ .getCollectionPersister( collectionType.getRole() );
+ joinedTable = createJoin( lhs, collectionPersister, alias, null );
+ }
+ else {
+ throw new InvalidPropertyJoinException( getPathThusFar(), lhs.getName(), propertyName );
+ }
+
+ if ( propertyFetching ) {
+ resolutionContext().registerPropertyFetch( joinedTable.getTableSpace().getPersisterSpace() );
+ }
+ if ( associationFetching ) {
+ resolutionContext.registerAssociationFetch( joinedTable.getTableSpace().getPersisterSpace() );
+ }
+
+ return joinedTable;
+ }
+
+ /**
+ * Generate a column list (tree w/ token type {@link HQLParser#COLUMN_LIST} for the columns making up the given
+ * property.
+ *
+ * @param origin The persister-space from which the property originates.
+ * @param propertyName The name of the property being referenced.
+ *
+ * @return The column list.
+ */
+ protected final HibernateTree generatePropertyColumnList(PersisterSpace origin, String propertyName) {
+ HibernateTree columnList = new HibernateTree( HQLParser.COLUMN_LIST );
+ Table containingTable = origin.getTableSpace().getContainingTable( propertyName );
+ for ( String columnName : origin.getTableSpace().getPropertyColumnNames( propertyName ) ) {
+ final HibernateTree column = new HibernateTree( HQLParser.COLUMN );
+ columnList.addChild( column );
+ column.addChild( new HibernateTree( HQLParser.ALIAS_REF, containingTable.getAliasText() ) );
+ column.addChild( new HibernateTree( HQLParser.IDENTIFIER, columnName ) );
+ }
+ return columnList;
+ }
+
+
+ // source impl support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ public abstract class AbstractPathedPropertyReferenceSource
+ extends HibernateTree
+ 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) {
+ super( new HibernateToken( HQLParser.IDENTIFIER, originationPath ) );
+ this.originationPath = originationPath;
+ }
+
+ protected AbstractPathedPropertyReferenceSource(Token token, String originationPath) {
+ super( token );
+ this.originationPath = originationPath;
+ }
+
+ public HibernateTree handleTerminalIndexAccess(PersisterSpace lhs, String collectionPropertyName, HibernateTree selector) {
+ Table joinedCollectionTable = createIndexAccessJoin( lhs, collectionPropertyName, selector );
+
+ // in general we need the collection element column list
+ QueryableCollection collectionPersister = resolveCollectionPersister( lhs, collectionPropertyName );
+ HibernateTree columnList = new HibernateTree( HQLParser.COLUMN_LIST );
+ for ( String columnName : collectionPersister.getElementColumnNames() ) {
+ final HibernateTree column = new HibernateTree( HQLParser.COLUMN );
+ column.addChild( new HibernateTree( HQLParser.ALIAS_REF, joinedCollectionTable.getAliasText() ) );
+ column.addChild( new HibernateTree( HQLParser.IDENTIFIER, columnName ) );
+ }
+ return columnList;
+ }
+
+ protected Table createIndexAccessJoin(PersisterSpace lhs, String collectionPropertyName, HibernateTree selector) {
+ validateIndexedCollectionReference( lhs, collectionPropertyName );
+
+ QueryableCollection collectionPersister = resolveCollectionPersister( lhs, collectionPropertyName );
+ HibernateTree join = createJoin( lhs, collectionPersister, null, selector );
+
+ if ( log.isTraceEnabled() ) {
+ log.trace(
+ resolutionContext().getTreePrinter().renderAsString(
+ join,
+ "implicit join : " + lhs.getSourceAlias() + "." + collectionPropertyName + "[]"
+ )
+ );
+ }
+
+ return ( Table ) join.getChild( 1 );
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getOriginationPath() {
+ return originationPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final String getDisplayText() {
+ return " ADPATER : SHOULD NEVER END UP IN TREE!";
+ }
+ }
+
+ protected Table createJoin(PersisterSpace lhs, Queryable entityPersister, String alias) {
+ EntityType entityType = entityPersister.getEntityMetamodel().getEntityType();
+
+ Table.EntityTableSpace tableSpace = new Table.EntityTableSpace( entityPersister, alias );
+ TableAliasGenerator.TableAliasRoot tableAliasRoot = resolutionContext().getTableAliasGenerator()
+ .generateSqlAliasRoot( entityPersister, alias );
+
+ Table joinedTableExpression = PersisterTableExpressionGenerator.generateTableExpression(
+ entityPersister,
+ tableAliasRoot,
+ tableSpace
+ );
+
+ HibernateTree join = new HibernateTree( HQLParser.JOIN );
+ join.addChild( buildJoinTypeNode() );
+ join.addChild( joinedTableExpression );
+
+ HibernateTree joinCondition;
+ final String lhsJoinProperty = entityType.getLHSPropertyName();
+ if ( lhsJoinProperty == null ) {
+ // join using the lhs PK
+ joinCondition = PersisterTableExpressionGenerator.generateJoinCorrelation(
+ lhs.getTableSpace().getJoinIntoTable().getAliasText(),
+ lhs.getTableSpace().getJoinIntoColumns(),
+ joinedTableExpression.getAliasText(),
+ entityPersister.getKeyColumnNames()
+ );
+ }
+ else {
+ // join using the columns to which the given lhs property is mapped
+ joinCondition = PersisterTableExpressionGenerator.generateJoinCorrelation(
+ lhs.getTableSpace().getContainingTable( lhsJoinProperty ).getAliasText(),
+ lhs.getTableSpace().getPropertyColumnNames( lhsJoinProperty ),
+ joinedTableExpression.getAliasText(),
+ entityPersister.getKeyColumnNames()
+ );
+ }
+
+ HibernateTree on = new HibernateTree( HQLParser.ON );
+ join.addChild( on );
+ on.addChild( joinCondition );
+
+ return joinedTableExpression;
+ }
+
+ protected Table createJoin(PersisterSpace lhs, QueryableCollection collectionPersister, String sourceAlias, HibernateTree extraJoinConditions) {
+ CollectionType collectionType = collectionPersister.getCollectionType();
+
+ Table.CollectionTableSpace tableSpace = new Table.CollectionTableSpace( collectionPersister, sourceAlias );
+ TableAliasGenerator.TableAliasRoot tableAliasRoot = resolutionContext().getTableAliasGenerator()
+ .generateSqlAliasRoot( collectionPersister, sourceAlias );
+
+ Table collectionTableExpression = PersisterTableExpressionGenerator.generateTableExpression(
+ collectionPersister,
+ tableAliasRoot,
+ tableSpace
+ );
+
+ HibernateTree joinNode = new HibernateTree( HQLParser.JOIN );
+ joinNode.addChild( buildJoinTypeNode() );
+ joinNode.addChild( collectionTableExpression );
+
+ HibernateTree joinCondition;
+ final String lhsJoinProperty = collectionType.getLHSPropertyName();
+ if ( lhsJoinProperty == null ) {
+ // join using the lhs PK
+ joinCondition = PersisterTableExpressionGenerator.generateJoinCorrelation(
+ lhs.getTableSpace().getJoinIntoTable().getAliasText(),
+ lhs.getTableSpace().getJoinIntoColumns(),
+ collectionTableExpression.getAliasText(),
+ collectionPersister.getKeyColumnNames()
+ );
+ }
+ else {
+ // join using the columns to which the given lhs property is mapped
+ joinCondition = PersisterTableExpressionGenerator.generateJoinCorrelation(
+ lhs.getTableSpace().getContainingTable( lhsJoinProperty ).getAliasText(),
+ lhs.getTableSpace().getPropertyColumnNames( lhsJoinProperty ),
+ collectionTableExpression.getAliasText(),
+ collectionPersister.getKeyColumnNames()
+ );
+ }
+
+ if ( extraJoinConditions != null ) {
+ HibernateTree mappedJoinCondition = joinCondition;
+ joinCondition = new HibernateTree( HQLParser.AND );
+ joinCondition.addChild( mappedJoinCondition );
+ joinCondition.addChild( extraJoinConditions );
+ }
+
+ HibernateTree on = new HibernateTree( HQLParser.ON );
+ joinNode.addChild( on );
+ on.addChild( joinCondition );
+
+ return collectionTableExpression;
+ }
+
+ protected void validateCollectionReference(PersisterSpace lhs, String propertyName) {
+ if ( ! isCollectionReference( lhs.getPropertyType( propertyName ) ) ) {
+ throw new CollectionExpectedException( getPathThusFar(), lhs.getName(), propertyName );
+ }
+ }
+
+ private boolean isCollectionReference(Type propertyType) {
+ return propertyType.isCollectionType();
+ }
+
+ protected void validateIndexedCollectionReference(PersisterSpace lhs, String propertyName) {
+ if ( ! isIndexedCollectionReference( lhs.getPropertyType( propertyName ) ) ) {
+ throw new IndexedCollectionExectedException( getPathThusFar(), lhs.getName(), propertyName );
+ }
+ }
+
+ private boolean isIndexedCollectionReference(Type propertyType) {
+ return isCollectionReference( propertyType )
+ && resolveCollectionPersister( ( CollectionType ) propertyType ).hasIndex();
+ }
+
+ protected QueryableCollection resolveCollectionPersister(PersisterSpace lhs, String propertyName) {
+ return resolveCollectionPersister( ( CollectionType ) lhs.getPropertyType( propertyName ) );
+ }
+
+ protected QueryableCollection resolveCollectionPersister(CollectionType collectionType) {
+ return ( QueryableCollection ) getSessionFactoryImplementor().getCollectionPersister( collectionType.getRole() );
+ }
+
+ protected Queryable resolveEntityPersister(PersisterSpace lhs, String propertyName) {
+ return resolveEntityPersister( ( EntityType ) lhs.getPropertyType( propertyName ) );
+ }
+
+ protected Queryable resolveEntityPersister(EntityType entityType) {
+ return ( Queryable ) getSessionFactoryImplementor().getEntityPersister(
+ entityType.getAssociatedEntityName( getSessionFactoryImplementor() )
+ );
+ }
+}
Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractUnexpectedPropertyTypeException.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractUnexpectedPropertyTypeException.java (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/AbstractUnexpectedPropertyTypeException.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -0,0 +1,71 @@
+/*
+ * 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.path.impl;
+
+import org.hibernate.QueryException;
+
+/**
+ * todo : javadocs
+ *
+ * @author Steve Ebersole
+ */
+public class AbstractUnexpectedPropertyTypeException extends QueryException {
+ private final String path;
+ private final String persisterName;
+ private final String propertyName;
+
+ public AbstractUnexpectedPropertyTypeException(String path, String persisterName, String propertyName) {
+ super();
+ this.path = path;
+ this.persisterName = persisterName;
+ this.propertyName = propertyName;
+ }
+
+ @Override
+ protected String internalGetMessage() {
+ return "Referenced property [" + buildPropertyReferenceFragment() + "] was not of expected type";
+ }
+
+ protected String buildPropertyReferenceFragment() {
+ return path + " (" + persisterName + ")." + propertyName;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public String getPersisterName() {
+ return persisterName;
+ }
+
+ public String getPropertyName() {
+ return propertyName;
+ }
+}
Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/BasicPathResolutionStrategySupport.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/BasicPathResolutionStrategySupport.java (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/BasicPathResolutionStrategySupport.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -0,0 +1,334 @@
+/*
+ * 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.path.impl;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.hibernate.HibernateException;
+import org.hibernate.hql.CollectionProperties;
+import org.hibernate.persister.collection.QueryableCollection;
+import org.hibernate.persister.entity.EntityPersister;
+import org.hibernate.sql.ast.common.HibernateTree;
+import org.hibernate.sql.ast.phase.hql.resolve.PersisterSpace;
+import org.hibernate.sql.ast.phase.hql.resolve.PropertyPathTerminus;
+import org.hibernate.sql.ast.phase.hql.resolve.ResolutionContext;
+import org.hibernate.sql.ast.phase.hql.resolve.path.PathedPropertyReferenceSource;
+import org.hibernate.sql.ast.tree.Table;
+import org.hibernate.type.ComponentType;
+import org.hibernate.type.EntityType;
+import org.hibernate.type.Type;
+
+/**
+ * todo : javadocs
+ *
+ * @author Steve Ebersole
+ */
+public class BasicPathResolutionStrategySupport extends AbstractPathResolutionStrategy {
+ private static final Logger log = LoggerFactory.getLogger( BasicPathResolutionStrategySupport.class );
+
+
+ public BasicPathResolutionStrategySupport(ResolutionContext resolutionContext) {
+ super( resolutionContext );
+ }
+
+ protected PathedPropertyReferenceSource internalHandleRoot(PersisterSpace persisterSpace) {
+ return new RootSourceImpl( persisterSpace );
+ }
+
+ private PathedPropertyReferenceSource determineAppropriateIntermediateSourceType(PersisterSpace origin, String propertyName) {
+ final Type propertyType = origin.getPropertyType( propertyName );
+ if ( propertyType.isComponentType() ) {
+ return new ComponentIntermediatePathSource( origin, propertyName, ( ComponentType ) propertyType );
+ }
+ else if ( propertyType.isEntityType() ) {
+ return new EntityIntermediatePathSource( origin, propertyName );
+ }
+ else if ( propertyType.isCollectionType() ) {
+ return new CollectionIntermediatePathSource( origin, propertyName );
+ }
+ else {
+ return new SimpleIntermediatePathSource();
+ }
+ }
+
+ /**
+ * Is the given property name a reference to the primary key of the associated
+ * entity construed by the given entity type?
+ * <p/>
+ * For example, consider a fragment like order.customer.id
+ * (where order is a from-element alias). Here, we'd have:
+ * propertyName = "id" AND
+ * owningType = ManyToOneType(Customer)
+ * and are being asked to determine whether "customer.id" is a reference
+ * to customer's PK...
+ *
+ * @param propertyName The name of the property to check.
+ * @param owningType The type represeting the entity "owning" the property
+ * @return True if propertyName references the enti ty's (owningType->associatedEntity)
+ * primary key; false otherwise.
+ */
+ private boolean isReferenceToPrimaryKey(EntityType owningType, String propertyName) {
+ EntityPersister persister = getSessionFactoryImplementor().getEntityPersister(
+ owningType.getAssociatedEntityName( getSessionFactoryImplementor() )
+ );
+ if ( persister.getEntityMetamodel().hasNonIdentifierPropertyNamedId() ) {
+ // only the identifier property field name can be a reference to the associated entity's PK...
+ return propertyName.equals( persister.getIdentifierPropertyName() ) && owningType.isReferenceToPrimaryKey();
+ }
+ else {
+ // here, we have two possibilities:
+ // 1) the property-name matches the explicitly identifier property name
+ // 2) the property-name matches the implicit 'id' property name
+ if ( EntityPersister.ENTITY_ID.equals( propertyName ) ) {
+ // the referenced node text is the special 'id'
+ return owningType.isReferenceToPrimaryKey();
+ }
+ else {
+ String keyPropertyName = owningType.getIdentifierOrUniqueKeyPropertyName( getSessionFactoryImplementor() );
+ return keyPropertyName != null && keyPropertyName.equals( propertyName ) && owningType.isReferenceToPrimaryKey();
+ }
+ }
+ }
+
+
+
+ // source impls ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ private class RootSourceImpl extends AbstractPathedPropertyReferenceSource {
+ private final PersisterSpace lhs;
+
+ public RootSourceImpl(PersisterSpace lhs) {
+ this.lhs = lhs;
+ }
+
+ public PathedPropertyReferenceSource handleIntermediatePathPart(String name) {
+ return determineAppropriateIntermediateSourceType( lhs, name );
+ }
+
+ public HibernateTree handleTerminalPathPart(String name) {
+ if ( lhs.getPropertyType( name ).isEntityType() ) {
+ if ( shouldTerminalEntityPropertyForceJoin() ) {
+ locateOrBuildPropertyJoinedTable( lhs, name, null, false, false );
+ }
+ }
+ return generatePropertyColumnList( lhs, name );
+ }
+
+ public PathedPropertyReferenceSource handleIntermediateIndexAccess(String collectionPropertyName, HibernateTree selector) {
+ validateIndexedCollectionReference( lhs, collectionPropertyName );
+ QueryableCollection collectionPersister = resolveCollectionPersister( lhs, collectionPropertyName );
+
+ Table joinedCollectionTable = createJoin( lhs, collectionPersister, null, selector );
+ return new IndexAccessIntermediatePathSource(joinedCollectionTable.getTableSpace().getPersisterSpace() );
+ }
+
+ public HibernateTree handleTerminalIndexAccess(String collectionPropertyName, HibernateTree selector) {
+ return handleTerminalIndexAccess( lhs, collectionPropertyName, selector );
+ }
+
+ public String getText() {
+ return "root-source {" + lhs.getSourceAlias() + "}";
+ }
+ }
+
+ protected class SimpleIntermediatePathSource extends AbstractPathedPropertyReferenceSource {
+ public PathedPropertyReferenceSource handleIntermediatePathPart(String name) {
+ throw new HibernateException( "cannot dereference simple value as part of path expression" );
+ }
+
+ public HibernateTree handleTerminalPathPart(String name) {
+ throw new HibernateException( "cannot dereference simple value as part of path expression" );
+ }
+
+ public PathedPropertyReferenceSource handleIntermediateIndexAccess(String name, HibernateTree selector) {
+ throw new HibernateException( "cannot apply index operation to simple value" );
+ }
+
+ public HibernateTree handleTerminalIndexAccess(String name, HibernateTree selector) {
+ throw new HibernateException( "cannot apply index operation to simple value" );
+ }
+ }
+
+ private class ComponentIntermediatePathSource extends AbstractPathedPropertyReferenceSource {
+ private final PersisterSpace lhs;
+ private final String propertyPath;
+ private final ComponentType componentType;
+
+ public ComponentIntermediatePathSource(PersisterSpace lhs, String propertyPath) {
+ this( lhs, propertyPath, ( ComponentType ) lhs.getPropertyType( propertyPath ) );
+ }
+
+ private ComponentIntermediatePathSource(PersisterSpace lhs, String propertyPath, ComponentType componentType) {
+ this.lhs = lhs;
+ this.propertyPath = propertyPath;
+ this.componentType = componentType;
+ }
+
+ public PathedPropertyReferenceSource handleIntermediatePathPart(String propertyName) {
+ final int index = locateComponentPropertyIndex( componentType, propertyName );
+ final String path = buildComponentDereferencePath( propertyName );
+ final Type propertyType = componentType.getSubtypes()[index];
+ if ( propertyType.isComponentType() ) {
+ return new ComponentIntermediatePathSource( lhs, path, ( ComponentType ) propertyType );
+ }
+ else if ( propertyType.isEntityType() ) {
+ return new EntityIntermediatePathSource( lhs, path );
+ }
+ else {
+ return new SimpleIntermediatePathSource();
+ }
+ }
+
+ public HibernateTree handleTerminalPathPart(String name) {
+ return generatePropertyColumnList( lhs, buildComponentDereferencePath( name ) );
+ }
+
+ public PathedPropertyReferenceSource handleIntermediateIndexAccess(String name, HibernateTree selector) {
+ throw new HibernateException( "cannot apply index operation to component value" );
+ }
+
+ public PropertyPathTerminus handleTerminalIndexAccess(String name, HibernateTree selector) {
+ throw new HibernateException( "cannot apply index operation to component value" );
+ }
+
+ private String buildComponentDereferencePath(String subPropertyName) {
+ return propertyPath + "." + subPropertyName;
+ }
+ }
+
+ protected class EntityIntermediatePathSource extends AbstractPathedPropertyReferenceSource {
+ private final PersisterSpace lhs;
+ private final String lhsPropertyName;
+
+ public EntityIntermediatePathSource(PersisterSpace lhs, String lhsPropertyName) {
+ this.lhs = lhs;
+ this.lhsPropertyName = lhsPropertyName;
+ }
+
+ public PathedPropertyReferenceSource handleIntermediatePathPart(String name) {
+ Table joinedTable = locateOrBuildPropertyJoinedTable( lhs, lhsPropertyName, null, false, false );
+ return determineAppropriateIntermediateSourceType( joinedTable.getTableSpace().getPersisterSpace(), name );
+ }
+
+ public HibernateTree handleTerminalPathPart(String name) {
+ final EntityType type = ( EntityType ) lhs.getPropertyType( lhsPropertyName );
+ if ( isReferenceToPrimaryKey( type, lhsPropertyName ) ) {
+ // todo : create a column-list based on the FKs...
+ return null;
+ }
+ else {
+ Table joinedTable = locateOrBuildPropertyJoinedTable( lhs, lhsPropertyName, null, false, false );
+ PersisterSpace rhs = joinedTable.getTableSpace().getPersisterSpace();
+ if ( type.isEntityType() ) {
+ if ( shouldTerminalEntityPropertyForceJoin() ) {
+ locateOrBuildPropertyJoinedTable( rhs, name, null, false, false );
+ }
+ }
+ return generatePropertyColumnList( rhs, name );
+ }
+
+ }
+
+ public PathedPropertyReferenceSource handleIntermediateIndexAccess(String name, HibernateTree selector) {
+ Table lhsJoinedTable = locateOrBuildPropertyJoinedTable( lhs, lhsPropertyName, null, false, false );
+ PersisterSpace lhsJoinedPersisterSpace = lhsJoinedTable.getTableSpace().getPersisterSpace();
+
+ validateIndexedCollectionReference( lhs, name );
+ QueryableCollection collectionPersister = resolveCollectionPersister( lhsJoinedPersisterSpace, name );
+ Table joinedTable = createJoin( lhsJoinedPersisterSpace, collectionPersister, null, selector );
+
+ return new IndexAccessIntermediatePathSource( joinedTable.getTableSpace().getPersisterSpace() );
+ }
+
+ public HibernateTree handleTerminalIndexAccess(String collectionPropertyName, HibernateTree selector) {
+ return handleTerminalIndexAccess( lhs, collectionPropertyName, selector );
+ }
+ }
+
+ protected boolean shouldTerminalEntityPropertyForceJoin() {
+ return false;
+ }
+
+ protected class CollectionIntermediatePathSource extends AbstractPathedPropertyReferenceSource {
+ private final PersisterSpace lhs;
+ private final String propertyName;
+
+ public CollectionIntermediatePathSource(PersisterSpace lhs, String propertyName) {
+ this.lhs = lhs;
+ this.propertyName = propertyName;
+ }
+
+ public PathedPropertyReferenceSource handleIntermediatePathPart(String name) {
+ throw new HibernateException( "cannot implicit join across a collection association" );
+ }
+
+ public HibernateTree handleTerminalPathPart(String name) {
+ // TODO : what are the circusmstances under which we need to *join* to the collection, as opposed to say munge it into a subquery???
+ if ( CollectionProperties.isAnyCollectionProperty( name ) ) {
+ Table joinedTable = locateOrBuildPropertyJoinedTable( lhs, propertyName, null, false, false );
+ return generatePropertyColumnList( joinedTable.getTableSpace().getPersisterSpace(), name );
+ }
+ throw new HibernateException( "cannot implicit join across a collection association" );
+ }
+
+ public PathedPropertyReferenceSource handleIntermediateIndexAccess(String name, HibernateTree selector) {
+ throw new HibernateException( "cannot implicit join across a collection association" );
+ }
+
+ public HibernateTree handleTerminalIndexAccess(String name, HibernateTree selector) {
+ throw new HibernateException( "cannot implicit join across a collection association" );
+ }
+ }
+
+ protected class IndexAccessIntermediatePathSource extends AbstractPathedPropertyReferenceSource {
+ private final PersisterSpace persisterSpace;
+
+ public IndexAccessIntermediatePathSource(PersisterSpace persisterSpace) {
+ this.persisterSpace = persisterSpace;
+ }
+
+ public PathedPropertyReferenceSource handleIntermediatePathPart(String name) {
+ return determineAppropriateIntermediateSourceType( persisterSpace, name );
+ }
+
+ public HibernateTree handleTerminalPathPart(String name) {
+ return generatePropertyColumnList( persisterSpace, name );
+ }
+
+ public PathedPropertyReferenceSource handleIntermediateIndexAccess(String name, HibernateTree selector) {
+ throw new IllegalStateException( "doubled up index operators" );
+ }
+
+ public HibernateTree handleTerminalIndexAccess(String name, HibernateTree selector) {
+ throw new IllegalStateException( "doubled up index operators" );
+ }
+ }
+}
Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/CollectionExpectedException.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/CollectionExpectedException.java (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/CollectionExpectedException.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -0,0 +1,46 @@
+/*
+ * 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.path.impl;
+
+/**
+ * Indicates that we were expecting a property reference to identify a collection, but it did not.
+ *
+ * @author Steve Ebersole
+ */
+public class CollectionExpectedException extends AbstractUnexpectedPropertyTypeException {
+ public CollectionExpectedException(String path, String persisterName, String propertyName) {
+ super( path, persisterName, propertyName );
+ }
+
+ @Override
+ protected String internalGetMessage() {
+ return "Expected property reference [" + buildPropertyReferenceFragment() + "] to identify collection";
+ }
+}
Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/IndexedCollectionExectedException.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/IndexedCollectionExectedException.java (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/IndexedCollectionExectedException.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -0,0 +1,46 @@
+/*
+ * 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.path.impl;
+
+/**
+ * Indicates that we were expecting a property reference to identify an indexed collection, but it did not.
+ *
+ * @author Steve Ebersole
+ */
+public class IndexedCollectionExectedException extends AbstractUnexpectedPropertyTypeException {
+ public IndexedCollectionExectedException(String path, String persisterName, String propertyName) {
+ super( path, persisterName, propertyName );
+ }
+
+ @Override
+ protected String internalGetMessage() {
+ return "Expected property reference [" + buildPropertyReferenceFragment() + "] to identify indexed collection";
+ }
+}
Added: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/InvalidPropertyJoinException.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/InvalidPropertyJoinException.java (rev 0)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/phase/hql/resolve/path/impl/InvalidPropertyJoinException.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -0,0 +1,46 @@
+/*
+ * 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.path.impl;
+
+/**
+ * Indicates an attempt to define an implicit or explicit property join based on a non-association property.
+ *
+ * @author Steve Ebersole
+ */
+public class InvalidPropertyJoinException extends AbstractUnexpectedPropertyTypeException {
+ public InvalidPropertyJoinException(String path, String persisterName, String propertyName) {
+ super( path, persisterName, propertyName );
+ }
+
+ @Override
+ protected String internalGetMessage() {
+ return "Referenced property [" + buildPropertyReferenceFragment() + "] not valid for join";
+ }
+}
Modified: core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java
===================================================================
--- core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java 2009-04-21 18:19:38 UTC (rev 16387)
+++ core/branches/antlr3/src/main/java/org/hibernate/sql/ast/tree/Table.java 2009-04-21 18:29:41 UTC (rev 16388)
@@ -26,12 +26,11 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
-
package org.hibernate.sql.ast.tree;
-import java.util.List;
import java.util.ArrayList;
import java.util.LinkedHashSet;
+import java.util.HashMap;
import org.antlr.runtime.Token;
@@ -41,6 +40,7 @@
import org.hibernate.sql.ast.common.HibernateToken;
import org.hibernate.sql.ast.util.DisplayableNode;
import org.hibernate.sql.ast.phase.hql.parse.HQLParser;
+import org.hibernate.sql.ast.phase.hql.resolve.PersisterSpace;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.util.StringHelper;
@@ -95,7 +95,13 @@
return "[source-alias=" + tableSpace.getSourceAlias() + "]";
}
+ /**
+ * Represents a grouping of related tables (i.e. all tables for a given persister).
+ */
public static interface TableSpace {
+
+ public void addTable(Table table);
+
/**
* Used as a unique identification since each table space originates from a single source alias (persister reference).
*
@@ -104,6 +110,13 @@
public String getSourceAlias();
/**
+ * PersisterSpace and TableSpace are related one-to-one...
+ *
+ * @return The persister space corresponding to this table space.
+ */
+ public PersisterSpace getPersisterSpace();
+
+ /**
* Get the table reference that should act as the RHS for this table space whenever we join to into it.
*
* @return The RHS table for joining into this table space structure.
@@ -112,9 +125,8 @@
public String[] getJoinIntoColumns();
- public void addTable(Table table);
+ public Type getPropertyType(String propertyName);
-
/**
* Get the table reference that contains the columns to which the given property is mapped.
*
@@ -124,23 +136,23 @@
*/
public Table getContainingTable(String propertyName);
- public Type getPropertyType(String propertyName);
-
public String[] getPropertyColumnNames(String propertyName);
- public List buildIdentifierColumnReferences();
+ public HibernateTree buildIdentifierColumnReferences();
- public List buildCompleteColumnReferences();
+ public HibernateTree buildCompleteColumnReferences();
}
public static abstract class AbstractTableSpace implements Table.TableSpace {
private final String sourceAlias;
- private final String sqlAliasBaseRoot;
+ private final boolean implicitSourceAlias;
protected final LinkedHashSet<Table> tables = new LinkedHashSet<Table>();
+ protected final HashMap<String,Table> aliasToTableMap = new HashMap<String,Table>();
+ protected final HashMap<String,Table> nameToTableMap = new HashMap<String,Table>();
- private AbstractTableSpace(String sourceAlias, String persisterName) {
+ private AbstractTableSpace(String sourceAlias) {
this.sourceAlias = sourceAlias;
- this.sqlAliasBaseRoot = ImplicitAliasGenerator.isImplicitAlias( sourceAlias ) ? persisterName : sourceAlias;
+ this.implicitSourceAlias = ImplicitAliasGenerator.isImplicitAlias( sourceAlias );
}
public String getSourceAlias() {
@@ -148,32 +160,46 @@
}
public String getSqlAliasBaseRoot() {
- return sqlAliasBaseRoot;
+ return implicitSourceAlias ? getPersisterSpace().getShortName() : sourceAlias;
}
public void addTable(Table table) {
tables.add( table );
+ aliasToTableMap.put( table.getAliasText(), table );
+ nameToTableMap.put( table.getTableNameText(), table );
}
}
+ public static abstract class AbstractPersisterSpace implements PersisterSpace {
+ private final HashMap<String,Table> propertyToJoinedTableMap = new HashMap<String,Table>();
+
+ public Table locateReusablePropertyJoinedTable(String propertyName) {
+ return propertyToJoinedTableMap.get( propertyName );
+ }
+
+ public void registerReusablePropertyJoinedTable(String propertyName, Table table) {
+ propertyToJoinedTableMap.put( propertyName, table );
+ }
+ }
+
public static class EntityTableSpace extends AbstractTableSpace {
- private final Queryable entityPersister;
+ private final EntityPersisterSpace persisterSpace;
private final ArrayList tables;
public EntityTableSpace(Queryable entityPersister, String sourecAlias) {
- super( sourecAlias, StringHelper.unqualifyEntityName( entityPersister.getEntityName() ) );
- this.entityPersister = entityPersister;
+ super( sourecAlias );
+ this.persisterSpace = new EntityPersisterSpace( this, entityPersister );
int numberOfTables = entityPersister.getMappedTableMetadata().getJoinedTables().length + 1;
int listSize = numberOfTables + (int) ( numberOfTables * .75 ) + 1;
this.tables = new ArrayList( listSize );
}
- public Queryable getEntityPersister() {
- return entityPersister;
+ public PersisterSpace getPersisterSpace() {
+ return persisterSpace;
}
- public void addTable(Table table) {
- tables.add( table );
+ public Queryable getEntityPersister() {
+ return persisterSpace.getEntityPersister();
}
public Table getDrivingTable() {
@@ -185,69 +211,98 @@
}
public String[] getJoinIntoColumns() {
- return entityPersister.getIdentifierColumnNames();
+ return getEntityPersister().getIdentifierColumnNames();
}
public Table getContainingTable(String propertyName) {
- return ( Table ) tables.get( entityPersister.getSubclassPropertyTableNumber( propertyName ) );
+ // todo : probably a better solution here is to iterate the internal collection of tables...
+ return ( Table ) tables.get( getEntityPersister().getSubclassPropertyTableNumber( propertyName ) );
}
public Type getPropertyType(String propertyName) {
- return entityPersister.getPropertyType( propertyName );
+ return getEntityPersister().getPropertyType( propertyName );
}
public String[] getPropertyColumnNames(String propertyName) {
- int index = entityPersister.getEntityMetamodel().getPropertyIndex( propertyName );
- return entityPersister.getPropertyColumnNames( index );
+ int index = getEntityPersister().getEntityMetamodel().getPropertyIndex( propertyName );
+ return getEntityPersister().getPropertyColumnNames( index );
}
- public List buildIdentifierColumnReferences() {
- String[] identifierColumnsNames = entityPersister.getIdentifierColumnNames();
- ArrayList columnsReferences = new ArrayList( collectionSizeWithoutRehashing( identifierColumnsNames.length ) );
- for ( int i = 0; i < identifierColumnsNames.length; i++ ) {
+ public HibernateTree buildIdentifierColumnReferences() {
+ HibernateTree columnList = new HibernateTree( HQLParser.COLUMN_LIST );
+ for ( String columnName : getEntityPersister().getIdentifierColumnNames() ) {
HibernateTree columnNode = new HibernateTree( HQLParser.COLUMN );
columnNode.addChild( new HibernateTree( HQLParser.ALIAS_REF, getDrivingTable().getAliasText() ) );
- columnNode.addChild( new HibernateTree( HQLParser.IDENTIFIER, identifierColumnsNames[i] ) );
- columnsReferences.add( columnNode );
+ columnNode.addChild( new HibernateTree( HQLParser.IDENTIFIER, columnName ) );
+ columnList.addChild( columnNode );
}
- return columnsReferences;
+ return columnList;
}
- public List buildCompleteColumnReferences() {
+ public HibernateTree buildCompleteColumnReferences() {
// todo : implement
return null;
}
}
- private static int collectionSizeWithoutRehashing(int elements) {
- // usually collection load factors are .75
- return collectionSizeWithoutRehashing( elements, .75 );
- }
+ private static class EntityPersisterSpace extends AbstractPersisterSpace {
+ private final EntityTableSpace correspondingTableSpace;
+ private final Queryable entityPersister;
+ private final String shortName;
- private static int collectionSizeWithoutRehashing(int elements, double factor) {
- return elements + ( (int) ( elements * factor ) + 1 );
+ private EntityPersisterSpace(EntityTableSpace correspondingTableSpace, Queryable entityPersister) {
+ this.correspondingTableSpace = correspondingTableSpace;
+ this.entityPersister = entityPersister;
+ this.shortName = StringHelper.unqualifyEntityName( entityPersister.getEntityName() );
+ }
+
+ public Queryable getEntityPersister() {
+ return entityPersister;
+ }
+
+ public String getSourceAlias() {
+ return correspondingTableSpace.getSourceAlias();
+ }
+
+ public String getName() {
+ return entityPersister.getName();
+ }
+
+ public String getShortName() {
+ return shortName;
+ }
+
+ public TableSpace getTableSpace() {
+ return correspondingTableSpace;
+ }
+
+ public Type getPropertyType(String propertyName) {
+ return entityPersister.getPropertyType( propertyName );
+ }
}
public static class CollectionTableSpace extends AbstractTableSpace {
- private final QueryableCollection persister;
- private final boolean areElementsEntities;
+ private final CollectionPersisterSpace persisterSpace;
private Table collectionTable;
private EntityTableSpace entityElementTableSpace;
public CollectionTableSpace(QueryableCollection persister, String sourceAlias) {
- super( sourceAlias, StringHelper.unqualify( persister.getRole() ) );
- this.persister = persister;
- this.areElementsEntities = persister.getElementType().isEntityType();
- if ( areElementsEntities ) {
+ super( sourceAlias );
+ this.persisterSpace = new CollectionPersisterSpace( this, persister );
+ if ( persisterSpace.areElementsEntities ) {
entityElementTableSpace = new EntityTableSpace( ( Queryable ) persister.getElementPersister(), sourceAlias );
}
}
- public QueryableCollection getPersister() {
- return persister;
+ public QueryableCollection getCollectionPersister() {
+ return persisterSpace.getCollectionPersister();
}
+ public PersisterSpace getPersisterSpace() {
+ return persisterSpace;
+ }
+
public void setCollectionTable(Table collectionTable) {
this.collectionTable = collectionTable;
}
@@ -261,7 +316,7 @@
}
public String[] getJoinIntoColumns() {
- return persister.getKeyColumnNames();
+ return getCollectionPersister().getKeyColumnNames();
}
public Table getContainingTable(String propertyName) {
@@ -277,14 +332,55 @@
return getEntityElementTableSpace().getPropertyColumnNames( propertyName );
}
- public List buildIdentifierColumnReferences() {
+ public HibernateTree buildIdentifierColumnReferences() {
// todo : implement
return null;
}
- public List buildCompleteColumnReferences() {
+ public HibernateTree buildCompleteColumnReferences() {
// todo : implement
return null;
}
}
+
+ public static class CollectionPersisterSpace extends AbstractPersisterSpace {
+ private final CollectionTableSpace correspondingTableSpace;
+ private final QueryableCollection collectionPersister;
+
+ private final String shortName;
+ private final boolean areElementsEntities;
+
+ public CollectionPersisterSpace(CollectionTableSpace correspondingTableSpace, QueryableCollection collectionPersister) {
+ this.correspondingTableSpace = correspondingTableSpace;
+ this.collectionPersister = collectionPersister;
+ this.shortName = StringHelper.unqualify( collectionPersister.getRole() );
+ this.areElementsEntities = collectionPersister.getElementType().isEntityType();
+ }
+
+ public String getSourceAlias() {
+ return correspondingTableSpace.getSourceAlias();
+ }
+
+ public QueryableCollection getCollectionPersister() {
+ return collectionPersister;
+ }
+
+ public String getName() {
+ return collectionPersister.getRole();
+ }
+
+ public String getShortName() {
+ return shortName;
+ }
+
+ public TableSpace getTableSpace() {
+ return correspondingTableSpace;
+ }
+
+ public Type getPropertyType(String propertyName) {
+ return areElementsEntities
+ ? correspondingTableSpace.entityElementTableSpace.getPersisterSpace().getPropertyType( propertyName )
+ : null;
+ }
+ }
}
More information about the hibernate-commits
mailing list