diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java deleted file mode 100644 index 4eca6d144f..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.CollectionJoin; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Fetch; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.ListJoin; -import javax.persistence.criteria.MapJoin; -import javax.persistence.criteria.Path; -import javax.persistence.criteria.PluralJoin; -import javax.persistence.criteria.SetJoin; -import javax.persistence.metamodel.CollectionAttribute; -import javax.persistence.metamodel.ListAttribute; -import javax.persistence.metamodel.MapAttribute; -import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.SingularAttribute; - -/** - * Convenience base class for all basic collection joins. Mainly we handle the fact that - * this path cannot be further de-referenced. - * - * @author Steve Ebersole - */ -public abstract class AbstractBasicPluralJoin - extends JoinImpl - implements PluralJoin, Fetch, Serializable { - - public AbstractBasicPluralJoin( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - PluralAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType); - } - - @Override - public PluralAttribute getModel() { - return ( PluralAttribute ) super.getAttribute(); - } - - @Override - public Expression> type(){ - throw new BasicPathUsageException( "type() is not applicable to primitive paths.", getAttribute() ); - } - - @Override - public Path get(SingularAttribute attribute){ - throw illegalDereference(); - } - - private BasicPathUsageException illegalDereference() { - return new BasicPathUsageException( "Basic collection elements cannot be de-referenced", getAttribute() ); - } - - @Override - public > Expression get(PluralAttribute collection){ - throw illegalDereference(); - } - - @Override - public > Expression get(MapAttribute map){ - throw illegalDereference(); - } - - @Override - public Path get(String attName) { - throw illegalDereference(); - } - - @Override - public Join join(SingularAttribute attribute, JoinType jt) { - throw illegalJoin(); - } - - private BasicPathUsageException illegalJoin() { - return new BasicPathUsageException( "Basic collection cannot be source of a join", getAttribute() ); - } - - @Override - public CollectionJoin join(CollectionAttribute collection, JoinType jt) { - throw illegalJoin(); - } - - @Override - public SetJoin join(javax.persistence.metamodel.SetAttribute set, JoinType jt) { - throw illegalJoin(); - } - - @Override - public ListJoin join(ListAttribute list, JoinType jt) { - throw illegalJoin(); - } - - @Override - public MapJoin join(MapAttribute map, JoinType jt) { - throw illegalJoin(); - } - - @Override - public Join join(String attributeName, JoinType jt) { - throw illegalJoin(); - } - - @Override - public CollectionJoin joinCollection(String attributeName, JoinType jt) { - throw illegalJoin(); - } - - @Override - public ListJoin joinList(String attributeName, JoinType jt) { - throw illegalJoin(); - } - - @Override - public MapJoin joinMap(String attributeName, JoinType jt) { - throw illegalJoin(); - } - - @Override - public SetJoin joinSet(String attributeName, JoinType jt) { - throw illegalJoin(); - } - - @Override - public Fetch fetch(SingularAttribute singularAttribute) { - throw illegalFetch(); - } - - private BasicPathUsageException illegalFetch() { - return new BasicPathUsageException( "Basic collection cannot be source of a fetch", getAttribute() ); - } - - @Override - public Fetch fetch(SingularAttribute attribute, JoinType jt) { - throw illegalFetch(); - } - - @Override - public Fetch fetch(PluralAttribute pluralAttribute) { - throw illegalFetch(); - } - - @Override - public Fetch fetch(PluralAttribute pluralAttribute, JoinType jt) { - throw illegalFetch(); - } - - @Override - public Fetch fetch(String attributeName) { - throw illegalFetch(); - } - - @Override - public Fetch fetch(String attributeName, JoinType jt) { - throw illegalFetch(); - } - -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java deleted file mode 100644 index c2436ea55e..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.CollectionAttribute; -import org.hibernate.ejb.criteria.JoinImplementors.CollectionJoinImplementor; - -/** - * Represents a join to a persistent collection, defined as type {@link java.util.Collection}, whose elements - * are basic type. - * - * @author Steve Ebersole - */ -public class BasicCollectionJoinImpl - extends AbstractBasicPluralJoin,E> - implements JoinImplementors.CollectionJoinImplementor, Serializable { - - public BasicCollectionJoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - CollectionAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType); - } - - @Override - public CollectionAttribute getAttribute() { - return (CollectionAttribute) super.getAttribute(); - } - - @Override - public CollectionAttribute getModel() { - return getAttribute(); - } - - @Override - public CollectionJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - BasicCollectionJoinImpl correlation = new BasicCollectionJoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl) getParentPath(), - getModel(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - private From correlationParent; - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return false; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return null; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java deleted file mode 100644 index 30c76fe73f..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import java.util.Map; -import java.util.Map.Entry; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.Path; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.MapAttribute; -import javax.persistence.metamodel.Type.PersistenceType; -import org.hibernate.ejb.criteria.JoinImplementors.MapJoinImplementor; - -/** - * Represents a join to a persistent collection, defined as type {@link java.util.Map}, whose elements - * are associations. - * - * @param The map owner - * @param The map key - * @param The map value - * - * @author Steve Ebersole - */ -public class BasicMapJoinImpl - extends AbstractBasicPluralJoin,V> - implements JoinImplementors.MapJoinImplementor, Serializable { - - - public BasicMapJoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - MapAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType ); - } - - @Override - public MapAttribute getAttribute() { - return (MapAttribute) super.getAttribute(); - } - - @Override - public MapAttribute getModel() { - return getAttribute(); - } - - /** - * {@inheritDoc} - */ - public Join, K> joinKey() { - return joinKey( DEFAULT_JOIN_TYPE ); - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public Join, K> joinKey(JoinType jt) { - if ( PersistenceType.BASIC.equals( getAttribute().getKeyType().getPersistenceType() ) ) { - throw new BasicPathUsageException( "Cannot join to map key of basic type", getAttribute() ); - } - - if ( jt.equals( JoinType.RIGHT ) ) { - throw new UnsupportedOperationException( "RIGHT JOIN not supported" ); - } - - final MapKeyHelpers.MapPath source = new MapKeyHelpers.MapPath( - queryBuilder(), - getAttribute().getJavaType(), - this, - getAttribute(), - getParentPath().getModel() - ); - final MapKeyHelpers.MapKeyAttribute attribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() ); - return new MapKeyHelpers.MapKeyJoin( - queryBuilder(), - source, - attribute, - jt - ); - } - - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public Path key() { - final MapKeyHelpers.MapPath source = new MapKeyHelpers.MapPath( - queryBuilder(), - getAttribute().getJavaType(), - this, - getAttribute(), - getParentPath().getModel() - ); - final MapKeyHelpers.MapKeyAttribute attribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() ); - return new MapKeyHelpers.MapKeyPath( queryBuilder(), source, attribute ); - } - - /** - * {@inheritDoc} - */ - public Path value() { - // API docs explicitly say value() should simply return this; - return this; - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public Expression> entry() { - return new MapKeyHelpers.MapEntryExpression( queryBuilder(), Map.Entry.class, this, getAttribute() ); - } - - private From correlationParent; - - @Override - @SuppressWarnings({ "unchecked" }) - public MapJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - BasicMapJoinImpl correlation = new BasicMapJoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl) getParentPath(), - getAttribute(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return getCorrelationParent() != null; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return correlationParent; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java deleted file mode 100644 index 54dc2a4428..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.SetAttribute; -import org.hibernate.ejb.criteria.JoinImplementors.SetJoinImplementor; - -/** - * Represents a join to a persistent collection, defined as type {@link java.util.Set}, whose elements - * are basic type. - * - * @author Steve Ebersole - */ -public class BasicSetJoinImpl - extends AbstractBasicPluralJoin,E> - implements JoinImplementors.SetJoinImplementor, Serializable { - - public BasicSetJoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - SetAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType ); - } - - @Override - public SetAttribute getAttribute() { - return (SetAttribute) super.getAttribute(); - } - - @Override - public SetAttribute getModel() { - return getAttribute(); - } - - @Override - public SetJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - BasicSetJoinImpl correlation = new BasicSetJoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl) getParentPath(), - getAttribute(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - private From correlationParent; - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return getCorrelationParent() != null; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return correlationParent; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java deleted file mode 100644 index 973611c1d8..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.CollectionAttribute; -import javax.persistence.metamodel.ManagedType; - -import org.hibernate.ejb.criteria.JoinImplementors.CollectionJoinImplementor; - -/** - * Represents a join to a persistent collection, defined as type {@link java.util.Collection}, whose elements - * are associations. - * - * @author Steve Ebersole - */ -public class CollectionJoinImpl - extends JoinImpl - implements JoinImplementors.CollectionJoinImplementor, Serializable { - - public CollectionJoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - CollectionAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType); - } - - @Override - public CollectionAttribute getAttribute() { - return (CollectionAttribute) super.getAttribute(); - } - - @Override - public CollectionAttribute getModel() { - return getAttribute(); - } - - @Override - protected ManagedType getManagedType() { - return ( ManagedType ) getAttribute().getElementType(); - } - - @Override - @SuppressWarnings({ "unchecked" }) - public CollectionJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - CollectionJoinImpl correlation = new CollectionJoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl) getParentPath(), - getAttribute(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - private From correlationParent; - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return false; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return null; - } - -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImplementor.java new file mode 100644 index 0000000000..7c7266284a --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImplementor.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria; + +import javax.persistence.criteria.CollectionJoin; + +/** + * Specialization of {@link JoinImplementor} for {@link java.util.Collection} typed attribute joins + * + * @author Steve Ebersole + */ +public interface CollectionJoinImplementor extends JoinImplementor, CollectionJoin { + /** + * {@inheritDoc} + *

+ * Refined return type + */ + public CollectionJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java index 80ad17bf57..3ac9d0dbd1 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java @@ -45,7 +45,6 @@ import javax.persistence.Tuple; import org.hibernate.ejb.EntityManagerFactoryImpl; import org.hibernate.ejb.criteria.expression.BinaryArithmeticOperation; import org.hibernate.ejb.criteria.expression.CoalesceExpression; -import org.hibernate.ejb.criteria.expression.CollectionExpression; import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl; import org.hibernate.ejb.criteria.expression.ConcatExpression; import org.hibernate.ejb.criteria.expression.ParameterExpressionImpl; @@ -70,6 +69,7 @@ import org.hibernate.ejb.criteria.expression.function.SqrtFunction; import org.hibernate.ejb.criteria.expression.function.SubstringFunction; import org.hibernate.ejb.criteria.expression.function.TrimFunction; import org.hibernate.ejb.criteria.expression.function.UpperFunction; +import org.hibernate.ejb.criteria.path.PluralAttributePath; import org.hibernate.ejb.criteria.predicate.BooleanAssertionPredicate; import org.hibernate.ejb.criteria.predicate.BooleanExpressionPredicate; import org.hibernate.ejb.criteria.predicate.NullnessPredicate; @@ -1275,8 +1275,8 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { if ( LiteralExpression.class.isInstance(exp) ) { return size( ( (LiteralExpression) exp ).getLiteral() ); } - else if ( CollectionExpression.class.isInstance(exp) ) { - return new SizeOfCollectionExpression(this, (CollectionExpression) exp ); + else if ( PluralAttributePath.class.isInstance(exp) ) { + return new SizeOfCollectionExpression(this, (PluralAttributePath) exp ); } // TODO : what other specific types? any? throw new IllegalArgumentException("unknown collection expression type [" + exp.getClass().getName() + "]" ); @@ -1302,11 +1302,8 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { */ @SuppressWarnings({ "unchecked" }) public > Predicate isEmpty(Expression collectionExpression) { - if ( CollectionExpression.class.isInstance(collectionExpression) ) { - return new IsEmptyPredicate( - this, - (CollectionExpression) collectionExpression - ); + if ( PluralAttributePath.class.isInstance(collectionExpression) ) { + return new IsEmptyPredicate( this, (PluralAttributePath) collectionExpression ); } // TODO : what other specific types? any? throw new IllegalArgumentException( @@ -1325,7 +1322,7 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { * {@inheritDoc} */ public > Predicate isMember(E e, Expression collectionExpression) { - if ( ! CollectionExpression.class.isInstance(collectionExpression) ) { + if ( ! PluralAttributePath.class.isInstance( collectionExpression ) ) { throw new IllegalArgumentException( "unknown collection expression type [" + collectionExpression.getClass().getName() + "]" ); @@ -1333,7 +1330,7 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { return new MemberOfPredicate( this, e, - (CollectionExpression)collectionExpression + (PluralAttributePath)collectionExpression ); } @@ -1348,7 +1345,7 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { * {@inheritDoc} */ public > Predicate isMember(Expression elementExpression, Expression collectionExpression) { - if ( ! CollectionExpression.class.isInstance(collectionExpression) ) { + if ( ! PluralAttributePath.class.isInstance( collectionExpression ) ) { throw new IllegalArgumentException( "unknown collection expression type [" + collectionExpression.getClass().getName() + "]" ); @@ -1356,7 +1353,7 @@ public class CriteriaBuilderImpl implements CriteriaBuilder, Serializable { return new MemberOfPredicate( this, elementExpression, - (CollectionExpression)collectionExpression + (PluralAttributePath)collectionExpression ); } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java index 6001f04076..400b920d1c 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java @@ -39,10 +39,9 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.Subquery; -import javax.persistence.criteria.From; import javax.persistence.metamodel.EntityType; -import org.hibernate.ejb.criteria.FromImpl.JoinScope; import org.hibernate.ejb.criteria.expression.ExpressionImpl; +import org.hibernate.ejb.criteria.path.RootImpl; /** * The Hibernate implementation of the JPA {@link Subquery} contract. Mostlty a set of delegation to its internal @@ -57,7 +56,7 @@ public class CriteriaSubqueryImpl extends ExpressionImpl implements Subque private Expression selection; private Set> correlatedJoins = new HashSet>(); - private final FromImpl.JoinScope joinScope = new FromImpl.JoinScope() { + private final FromImplementor.JoinScope joinScope = new FromImplementor.JoinScope() { public void addJoin(Join join) { correlatedJoins.add( join ); } @@ -65,14 +64,6 @@ public class CriteriaSubqueryImpl extends ExpressionImpl implements Subque public void addFetch(Fetch fetch) { throw new UnsupportedOperationException( "Cannot define fetch from a subquery correlation" ); } - - public boolean isCorrelated() { - return true; - } - - public From getCorrelationParent() { - return null; - } }; public CriteriaSubqueryImpl( @@ -89,7 +80,7 @@ public class CriteriaSubqueryImpl extends ExpressionImpl implements Subque * * @return The subquery's join scope. */ - public JoinScope getJoinScope() { + public FromImplementor.JoinScope getJoinScope() { return joinScope; } @@ -260,35 +251,35 @@ public class CriteriaSubqueryImpl extends ExpressionImpl implements Subque * {@inheritDoc} */ public Join correlate(Join source) { - return ( ( JoinImplementors.JoinImplementor ) source ).correlateTo( this ); + return ( (JoinImplementor) source ).correlateTo( this ); } /** * {@inheritDoc} */ public CollectionJoin correlate(CollectionJoin source) { - return ( ( JoinImplementors.CollectionJoinImplementor ) source ).correlateTo( this ); + return ( (CollectionJoinImplementor) source ).correlateTo( this ); } /** * {@inheritDoc} */ public SetJoin correlate(SetJoin source) { - return ( ( JoinImplementors.SetJoinImplementor ) source ).correlateTo( this ); + return ( (SetJoinImplementor) source ).correlateTo( this ); } /** * {@inheritDoc} */ public ListJoin correlate(ListJoin source) { - return ( ( JoinImplementors.ListJoinImplementor ) source ).correlateTo( this ); + return ( (ListJoinImplementor) source ).correlateTo( this ); } /** * {@inheritDoc} */ public MapJoin correlate(MapJoin source) { - return ( ( JoinImplementors.MapJoinImplementor ) source ).correlateTo( this ); + return ( (MapJoinImplementor) source ).correlateTo( this ); } /** diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java new file mode 100644 index 0000000000..8c40e87ffe --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java @@ -0,0 +1,50 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria; + +import java.io.Serializable; +import javax.persistence.criteria.Fetch; +import javax.persistence.criteria.From; +import javax.persistence.criteria.Join; + +/** + * Implementation contract for the JPA {@link From} interface. + * + * @author Steve Ebersole + */ +public interface FromImplementor extends PathImplementor, From { + public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext); + public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext); + + /** + * Helper contract used to define who/what keeps track of joins and fetches made from this FROM. + */ + public static interface JoinScope extends Serializable { + public void addJoin(Join join); + public void addFetch(Fetch fetch); + } + + public FromImplementor correlateTo(CriteriaSubqueryImpl subquery); + public void prepareCorrelationDelegate(JoinScope joinScope, FromImplementor parent); +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/IllegalDereferenceException.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/IllegalDereferenceException.java new file mode 100644 index 0000000000..c5eed4af42 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/IllegalDereferenceException.java @@ -0,0 +1,43 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria; + +/** + * Represents an illegal attempt to dereference from a {@link #getPathSource() path source} which + * cannot be dereferenced. + * + * @author Steve Ebersole + */ +public class IllegalDereferenceException extends RuntimeException { + private final PathSource pathSource; + + public IllegalDereferenceException(PathSource pathSource) { + super( "Illegal attempt to dereference path source [" + pathSource.getPathIdentifier() + "]" ); + this.pathSource = pathSource; + } + + public PathSource getPathSource() { + return pathSource; + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java deleted file mode 100644 index 1a530e45a5..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.From; -import javax.persistence.criteria.JoinType; -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.ManagedType; -import javax.persistence.metamodel.Bindable; -import javax.persistence.metamodel.SingularAttribute; -import javax.persistence.metamodel.EmbeddableType; - -/** - * Models a non-collection property join. - * - * @author Steve Ebersole - */ -public class JoinImpl - extends FromImpl - implements JoinImplementors.JoinImplementor, Serializable { - // TODO : keep track or whether any non-identifier properties get dereferenced - // for join optimization like in HQL - - // TODO : do we need (or is it easier with) a separate "component join impl"? - - // TODO : cleanup these ctors, ugh... - - private final ManagedType managedType; - private final JoinType joinType; - - @SuppressWarnings({ "unchecked" }) - public JoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - Attribute joinProperty, - JoinType joinType) { - super( - criteriaBuilder, - javaType, - lhs, - joinProperty, - ( Bindable ) ( Attribute.PersistentAttributeType.EMBEDDED == joinProperty.getPersistentAttributeType() - ? joinProperty - : criteriaBuilder.getEntityManagerFactory().getMetamodel().managedType( javaType )) - ); - this.managedType = getManagedType(); - this.joinType = joinType; - } - - @SuppressWarnings({ "unchecked" }) - protected ManagedType getManagedType() { - Bindable model = getModel(); - return Bindable.BindableType.ENTITY_TYPE == model.getBindableType() - ? (ManagedType) model - : (EmbeddableType) ( (SingularAttribute) model ).getType(); - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public From getParent() { - // AFAICT, only "froms" (specifically roots and joins) can be the parent of a join. - return ( From ) getParentPath(); - } - - @Override - @SuppressWarnings({ "unchecked" }) - public Attribute getAttribute() { - return (Attribute) super.getAttribute(); - } - - /** - * {@inheritDoc} - */ - public JoinType getJoinType() { - return joinType; - } - - @Override - @SuppressWarnings({ "unchecked" }) - protected Attribute getAttribute(String name) { - return (Attribute) managedType.getAttribute( name ); - } - - @SuppressWarnings({ "unchecked" }) - public JoinImplementors.JoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - JoinImpl correlation = new JoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl)getParentPath(), - getAttribute(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - private From correlationParent; - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return false; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return correlationParent; - } - - public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) { - prepareAlias( renderingContext ); - ( (FromImpl) getParent() ).prepareAlias( renderingContext ); - return getParent().getAlias() + '.' + getAttribute().getName() + " as " + getAlias(); - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementor.java new file mode 100644 index 0000000000..33b859f4bb --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementor.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria; + +import javax.persistence.criteria.Fetch; +import javax.persistence.criteria.Join; + +/** + * Consolidates the {@link Join} and {@link Fetch} hierarchies since that is how we implement them. + * This allows us to treat them polymorphically. +* +* @author Steve Ebersole +*/ +public interface JoinImplementor extends Join, Fetch, FromImplementor { + /** + * {@inheritDoc} + *

+ * Refined return type + */ + public JoinImplementor correlateTo(CriteriaSubqueryImpl subquery); +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementors.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementors.java deleted file mode 100644 index 88a68cd935..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementors.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import javax.persistence.criteria.CollectionJoin; -import javax.persistence.criteria.Fetch; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.ListJoin; -import javax.persistence.criteria.MapJoin; -import javax.persistence.criteria.SetJoin; -import javax.persistence.criteria.From; - -/** - * Consolidates the {@link Join} and {@link Fetch} hierarchies since that is how we implement them. - * This allows us to treat them polymorphically. - * - * @author Steve Ebersole - */ -public interface JoinImplementors { - public static interface JoinImplementor - extends Join, Fetch { - public JoinImplementor correlateTo(CriteriaSubqueryImpl subquery); - } - - public static interface CollectionJoinImplementor - extends JoinImplementor, CollectionJoin, Fetch { - public CollectionJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); - } - - public static interface SetJoinImplementor - extends JoinImplementor, SetJoin, Fetch { - public SetJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); - } - - public static interface ListJoinImplementor - extends JoinImplementor, ListJoin, Fetch { - public ListJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); - } - - public static interface MapJoinImplementor - extends JoinImplementor, MapJoin, Fetch { - public MapJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java deleted file mode 100644 index fc6554c0ff..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.ListAttribute; -import javax.persistence.metamodel.ManagedType; - -import org.hibernate.ejb.criteria.JoinImplementors.ListJoinImplementor; -import org.hibernate.ejb.criteria.expression.ListIndexExpression; - -/** - * Represents a join to a persistent collection, defined as type {@link java.util.List}, whose elements - * are associations. - * - * @author Steve Ebersole - */ -public class ListJoinImpl - extends JoinImpl - implements JoinImplementors.ListJoinImplementor, Serializable { - public ListJoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - ListAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType ); - } - - @Override - public ListAttribute getAttribute() { - return (ListAttribute) super.getAttribute(); - } - - @Override - public ListAttribute getModel() { - return getAttribute(); - } - - @Override - protected ManagedType getManagedType() { - return ( ManagedType ) getAttribute().getElementType(); - } - - /** - * {@inheritDoc} - */ - public Expression index() { - return new ListIndexExpression( queryBuilder(), this, getAttribute() ); - } - - @Override - @SuppressWarnings({ "unchecked" }) - public ListJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - ListJoinImpl correlation = new ListJoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl) getParentPath(), - getAttribute(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - private From correlationParent; - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return getCorrelationParent() != null; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return correlationParent; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImplementor.java new file mode 100644 index 0000000000..fa554512b9 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImplementor.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria; + +import javax.persistence.criteria.ListJoin; + +/** + * Specialization of {@link JoinImplementor} for {@link java.util.List} typed attribute joins + * + * @author Steve Ebersole + */ +public interface ListJoinImplementor extends JoinImplementor, ListJoin { + /** + * {@inheritDoc} + *

+ * Refined return type + */ + public ListJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java deleted file mode 100644 index cc312ba2e2..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import java.util.Map; -import java.util.Map.Entry; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.Path; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.MapAttribute; -import javax.persistence.metamodel.ManagedType; -import javax.persistence.metamodel.Type.PersistenceType; -import org.hibernate.ejb.criteria.JoinImplementors.MapJoinImplementor; - -/** - * Represents a join to a persistent collection, defined as type {@link java.util.Map}, whose elements - * are associations. - * - * @author Steve Ebersole - */ -public class MapJoinImpl - extends JoinImpl - implements JoinImplementors.MapJoinImplementor, Serializable { - - public MapJoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - MapAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType); - } - - @Override - public MapAttribute getAttribute() { - return (MapAttribute) super.getAttribute(); - } - - @Override - public MapAttribute getModel() { - return getAttribute(); - } - - @Override - protected ManagedType getManagedType() { - return ( ManagedType ) getAttribute().getElementType(); - } - - /** - * {@inheritDoc} - */ - public Join, K> joinKey() { - return joinKey( DEFAULT_JOIN_TYPE ); - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public Join, K> joinKey(JoinType jt) { - if ( PersistenceType.BASIC.equals( getAttribute().getKeyType().getPersistenceType() ) ) { - throw new BasicPathUsageException( "Cannot join to map key of basic type", getAttribute() ); - } - - if ( jt.equals( JoinType.RIGHT ) ) { - throw new UnsupportedOperationException( "RIGHT JOIN not supported" ); - } - - final MapKeyHelpers.MapPath mapKeySource = new MapKeyHelpers.MapPath( - queryBuilder(), - getAttribute().getJavaType(), - this, - getAttribute(), - getParentPath().getModel() - ); - final MapKeyHelpers.MapKeyAttribute mapKeyAttribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() ); - return new MapKeyHelpers.MapKeyJoin( - queryBuilder(), - mapKeySource, - mapKeyAttribute, - jt - ); - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public Path key() { - final MapKeyHelpers.MapPath mapKeySource = new MapKeyHelpers.MapPath( - queryBuilder(), - getAttribute().getJavaType(), - this, - getAttribute(), - getParentPath().getModel() - ); - final MapKeyHelpers.MapKeyAttribute mapKeyAttribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() ); - return new MapKeyHelpers.MapKeyPath( queryBuilder(), mapKeySource, mapKeyAttribute ); - } - - /** - * {@inheritDoc} - */ - public Path value() { - return this; - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public Expression> entry() { - return new MapKeyHelpers.MapEntryExpression( queryBuilder(), Map.Entry.class, this, getAttribute() ); - } - - - private From correlationParent; - - @Override - @SuppressWarnings({ "unchecked" }) - public MapJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - MapJoinImpl correlation = new MapJoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl) getParentPath(), - getAttribute(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return getCorrelationParent() != null; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return correlationParent; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImplementor.java new file mode 100644 index 0000000000..8d61c95d1e --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImplementor.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria; + +import javax.persistence.criteria.MapJoin; + +/** + * Specialization of {@link JoinImplementor} for {@link java.util.Map} typed attribute joins + * + * @author Steve Ebersole + */ +public interface MapJoinImplementor extends JoinImplementor, MapJoin { + /** + * {@inheritDoc} + *

+ * Refined return type + */ + public MapJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java deleted file mode 100644 index aafef0e907..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import java.util.Collection; -import java.util.Map; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Path; - -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.Bindable; -import javax.persistence.metamodel.MapAttribute; -import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.SingularAttribute; -import org.hibernate.ejb.criteria.expression.ExpressionImpl; - -/** - * A {@link Path} models an individual portion of a path expression. - * - * @author Steve Ebersole - */ -public class PathImpl extends ExpressionImpl implements Path, Serializable { - private final PathImpl origin; - private final Attribute attribute; - private Object model; - - /** - * Constructs a path. - * - * @param criteriaBuilder The delegate for building query components. - * @param javaType The java type of this path, - * @param origin The source ("lhs") of this path. - * @param attribute The attribute defining this path element. - * @param model The corresponding model of this path. - */ - protected PathImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl origin, - Attribute attribute, - Object model) { - super( criteriaBuilder, javaType ); - this.origin = origin; - this.attribute = attribute; - this.model = model; - } - - /** - * {@inheritDoc} - */ - public PathImpl getParentPath() { - return origin; - } - - public Attribute getAttribute() { - return attribute; - } - - /** - * {@inheritDoc} - */ - @SuppressWarnings({ "unchecked" }) - public Bindable getModel() { - if ( model == null ) { - throw new IllegalStateException( this + " represents a basic path and not a bindable" ); - } - return (Bindable)model; - } - - /** - * {@inheritDoc} - *

- * Subclasses override this appropriately, but here we simply throw - * an {@link IllegalStateException} - */ - public Expression> type() { - throw new BasicPathUsageException( "type() is not applicable to primitive paths.", getAttribute() ); - } - - /** - * {@inheritDoc} - *

- * Subclasses override this appropriately, but here we simply throw - * an {@link IllegalStateException} - */ - public Path get(SingularAttribute attribute) { - throw illegalDereference(); - } - - private BasicPathUsageException illegalDereference() { - return new BasicPathUsageException( "Primitive path cannot be de-referenced", getAttribute() ); - } - - /** - * {@inheritDoc} - *

- * Subclasses override this appropriately, but here we simply throw - * an {@link IllegalStateException} - */ - public > Expression get(PluralAttribute collection) { - throw illegalDereference(); - } - - /** - * {@inheritDoc} - *

- * Subclasses override this appropriately, but here we simply throw - * an {@link IllegalStateException} - */ - public > Expression get(MapAttribute map) { - throw illegalDereference(); - } - - /** - * {@inheritDoc} - *

- * Subclasses override this appropriately, but here we simply throw - * an {@link IllegalStateException} - */ - public Path get(String attributeName) { - throw illegalDereference(); - } - - public void registerParameters(ParameterRegistry registry) { - // none to register - } - - /** - * Get the string representation of this path as a navigation from one of the - * queries identification variables - * - * @return The path's identifier. - */ - public String getPathIdentifier() { - return getParentPath().getPathIdentifier() + "." + getAttribute().getName(); - } - - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { - ( (TableExpressionMapper) getParentPath() ).prepareAlias( renderingContext ); - return getParentPath().getAlias() - + '.' - + getAttribute().getName(); - } - - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { - return render( renderingContext ); - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java index 6e38fb00fd..27b5f751d0 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java @@ -31,15 +31,7 @@ import javax.persistence.metamodel.Attribute; * * @author Steve Ebersole */ -public interface PathImplementor extends ExpressionImplementor, Path { - /** - * Get the string representation of this path as a navigation from one of the - * queries identification variables - * - * @return The path's identifier. - */ - public String getPathIdentifier(); - +public interface PathImplementor extends ExpressionImplementor, Path, PathSource, Renderable { /** * Retrieve reference to the attribute this path represents. * diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/TableExpressionMapper.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java similarity index 59% rename from entitymanager/src/main/java/org/hibernate/ejb/criteria/TableExpressionMapper.java rename to entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java index f93a7dd1a3..1fe20c688f 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/TableExpressionMapper.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. + * Copyright (c) 2010, Red Hat Inc. 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 Inc. * * 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 @@ -23,12 +23,21 @@ */ package org.hibernate.ejb.criteria; +import javax.persistence.criteria.Path; + /** - * Common contract for things which map to a table expression in a SQL FROM clause. + * Implementation contract for things which can be the source (parent, left-hand-side, etc) of a path * * @author Steve Ebersole */ -public interface TableExpressionMapper { +public interface PathSource extends Path { public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext); - public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext); + + /** + * Get the string representation of this path as a navigation from one of the + * queries identification variables + * + * @return The path's identifier. + */ + public String getPathIdentifier(); } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java index 99c5ab8ed4..ebfe5517fd 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java @@ -44,6 +44,8 @@ import javax.persistence.criteria.Fetch; import javax.persistence.criteria.JoinType; import javax.persistence.metamodel.EntityType; +import org.hibernate.ejb.criteria.path.RootImpl; + /** * Models basic query structure. Used as a delegate in implementing both * {@link org.hibernate.criterion.CriteriaQuery} and @@ -222,9 +224,9 @@ public class QueryStructure implements Serializable { jpaqlQuery.append( " from " ); String sep = ""; for ( Root root : getRoots() ) { - ( (TableExpressionMapper) root ).prepareAlias( renderingContext ); + ( (FromImplementor) root ).prepareAlias( renderingContext ); jpaqlQuery.append( sep ); - jpaqlQuery.append( ( ( TableExpressionMapper ) root ).renderTableExpression( renderingContext ) ); + jpaqlQuery.append( ( (FromImplementor) root ).renderTableExpression( renderingContext ) ); sep = ", "; } @@ -264,9 +266,9 @@ public class QueryStructure implements Serializable { } for ( Join join : joins ) { - ( (TableExpressionMapper) join ).prepareAlias( renderingContext ); + ( (FromImplementor) join ).prepareAlias( renderingContext ); jpaqlQuery.append( renderJoinType( join.getJoinType() ) ) - .append( ( ( TableExpressionMapper ) join ).renderTableExpression( renderingContext ) ); + .append( ( (FromImplementor) join ).renderTableExpression( renderingContext ) ); renderJoins( jpaqlQuery, renderingContext, join.getJoins() ); renderFetches( jpaqlQuery, renderingContext, join.getFetches() ); } @@ -297,10 +299,10 @@ public class QueryStructure implements Serializable { } for ( Fetch fetch : fetches ) { - ( (TableExpressionMapper) fetch ).prepareAlias( renderingContext ); + ( (FromImplementor) fetch ).prepareAlias( renderingContext ); jpaqlQuery.append( renderJoinType( fetch.getJoinType() ) ) .append( "fetch " ) - .append( ( ( TableExpressionMapper ) fetch ).renderTableExpression( renderingContext ) ); + .append( ( (FromImplementor) fetch ).renderTableExpression( renderingContext ) ); renderFetches( jpaqlQuery, renderingContext, fetch.getFetches() ); } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java deleted file mode 100644 index f35a05e1f0..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.Root; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.EntityType; - -/** - * Defines a query root. - * - * @author Steve Ebersole - */ -public class RootImpl extends FromImpl implements Root, Serializable { - private RootImpl correlationParent; - - public RootImpl( - CriteriaBuilderImpl criteriaBuilder, - EntityType model) { - super( criteriaBuilder, model ); - } - - @Override - public EntityType getModel(){ - return ( EntityType ) super.getModel(); - } - - @Override - protected Attribute getAttribute(String name) { - return (Attribute) getModel().getAttribute( name ); - } - - public boolean isCorrelated() { - return getCorrelationParent() != null; - } - - public From getCorrelationParent() { - return correlationParent; - } - - public RootImpl correlateTo(CriteriaSubqueryImpl subquery) { - RootImpl correlation = new RootImpl( queryBuilder(), getModel() ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java deleted file mode 100644 index ce0e216f4d..0000000000 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. - * - * 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.ejb.criteria; - -import java.io.Serializable; -import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.From; -import javax.persistence.metamodel.SetAttribute; -import javax.persistence.metamodel.ManagedType; - -import org.hibernate.ejb.criteria.JoinImplementors.SetJoinImplementor; - -/** - * Represents a join to a persistent collection, defined as type {@link java.util.Set}, whose elements - * are associations. - * - * @author Steve Ebersole - */ -public class SetJoinImpl - extends JoinImpl - implements JoinImplementors.SetJoinImplementor, Serializable { - - public SetJoinImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl lhs, - SetAttribute joinProperty, - JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType); - } - - @Override - public SetAttribute getAttribute() { - return (SetAttribute) super.getAttribute(); - } - - @Override - public SetAttribute getModel() { - return getAttribute(); - } - - @Override - protected ManagedType getManagedType() { - return ( ManagedType ) getAttribute().getElementType(); - } - - @Override - @SuppressWarnings({ "unchecked" }) - public SetJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - SetJoinImpl correlation = new SetJoinImpl( - queryBuilder(), - getJavaType(), - (PathImpl) getParentPath(), - getAttribute(), - getJoinType() - ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - private From correlationParent; - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return getCorrelationParent() != null; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return correlationParent; - } -} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImplementor.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImplementor.java new file mode 100644 index 0000000000..33e6727f10 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImplementor.java @@ -0,0 +1,40 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria; + +import javax.persistence.criteria.SetJoin; + +/** + * Specialization of {@link JoinImplementor} for {@link java.util.Set} typed attribute joins + * + * @author Steve Ebersole + */ +public interface SetJoinImplementor extends JoinImplementor, SetJoin { + /** + * {@inheritDoc} + *

+ * Refined return type + */ + public SetJoinImplementor correlateTo(CriteriaSubqueryImpl subquery); +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java index 0839e6ee4a..a7f2458750 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java @@ -28,7 +28,8 @@ import javax.persistence.metamodel.ListAttribute; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; import org.hibernate.ejb.criteria.CriteriaQueryCompiler; -import org.hibernate.ejb.criteria.PathImpl; +import org.hibernate.ejb.criteria.PathImplementor; + /** * An expression for referring to the index of a list. @@ -36,21 +37,24 @@ import org.hibernate.ejb.criteria.PathImpl; * @author Steve Ebersole */ public class ListIndexExpression extends ExpressionImpl implements Serializable { - private final PathImpl origin; - private final ListAttribute listAttribute; + private final PathImplementor origin; + private final ListAttribute listAttribute; - public ListIndexExpression(CriteriaBuilderImpl criteriaBuilder, PathImpl origin, ListAttribute listAttribute) { + public ListIndexExpression( + CriteriaBuilderImpl criteriaBuilder, + PathImplementor origin, + ListAttribute listAttribute) { super( criteriaBuilder, Integer.class ); this.origin = origin; this.listAttribute = listAttribute; } - public ListAttribute getListAttribute() { + public ListAttribute getListAttribute() { return listAttribute; } public void registerParameters(ParameterRegistry registry) { - // nothign to do + // nothing to do } public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java new file mode 100644 index 0000000000..20da99aae1 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java @@ -0,0 +1,81 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.expression; + +import java.io.Serializable; +import java.util.Map; +import javax.persistence.criteria.Expression; +import javax.persistence.metamodel.MapAttribute; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.Renderable; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class MapEntryExpression + extends ExpressionImpl> + implements Expression>, Serializable { + + private final PathImplementor origin; + private final MapAttribute attribute; + + public MapEntryExpression( + CriteriaBuilderImpl criteriaBuilder, + Class> javaType, + PathImplementor origin, + MapAttribute attribute) { + super( criteriaBuilder, javaType); + this.origin = origin; + this.attribute = attribute; + } + + public MapAttribute getAttribute() { + return attribute; + } + + public void registerParameters(ParameterRegistry registry) { + // none to register + } + + public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + // don't think this is valid outside of select clause... + throw new IllegalStateException( "illegal reference to map entry outside of select clause." ); + } + + public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + return "entry(" + path( renderingContext ) + ")"; + } + + private String path(CriteriaQueryCompiler.RenderingContext renderingContext) { + return origin.getPathIdentifier() + + '.' + + ( (Renderable) getAttribute() ).renderProjection( renderingContext ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java new file mode 100644 index 0000000000..b076308cba --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java @@ -0,0 +1,54 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.expression; + +import java.io.Serializable; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.ParameterRegistry; + +/** + * Used to construct the result of {@link javax.persistence.criteria.Path#type()} + * + * @author Steve Ebersole + */ +public class PathTypeExpression extends ExpressionImpl implements Serializable { + public PathTypeExpression(CriteriaBuilderImpl criteriaBuilder, Class javaType) { + super( criteriaBuilder, javaType ); + } + + public void registerParameters(ParameterRegistry registry) { + // nothing to do + } + + public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + // todo : is it valid for this to get rendered into the query itself? + throw new IllegalArgumentException( "Unexpected call on EntityTypeExpression#render" ); + } + + public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + return render( renderingContext ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java index 8af1d71fbf..cd2cd18a99 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java @@ -28,6 +28,7 @@ import java.util.Collection; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.path.PluralAttributePath; /** * Represents a "size of" expression in regards to a persistent collection; the implication is @@ -38,17 +39,17 @@ import org.hibernate.ejb.criteria.CriteriaQueryCompiler; public class SizeOfCollectionExpression extends ExpressionImpl implements Serializable { - private final CollectionExpression collectionExpression; + private final PluralAttributePath collectionPath; public SizeOfCollectionExpression( CriteriaBuilderImpl criteriaBuilder, - CollectionExpression collectionExpression) { + PluralAttributePath collectionPath) { super( criteriaBuilder, Integer.class); - this.collectionExpression = collectionExpression; + this.collectionPath = collectionPath; } - public CollectionExpression getCollectionExpression() { - return collectionExpression; + public PluralAttributePath getCollectionPath() { + return collectionPath; } public void registerParameters(ParameterRegistry registry) { @@ -56,7 +57,7 @@ public class SizeOfCollectionExpression } public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { - return "size(" + getCollectionExpression().render( renderingContext ) + ")"; + return "size(" + getCollectionPath().render( renderingContext ) + ")"; } public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java similarity index 56% rename from entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java rename to entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java index d3fc2389b3..f4440d0b9e 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. + * Copyright (c) 2010, Red Hat Inc. 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 Inc. * * 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 @@ -21,64 +21,123 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.ejb.criteria; +package org.hibernate.ejb.criteria.path; import java.io.Serializable; -import java.util.Set; -import java.util.Collection; -import java.util.Map; import java.util.LinkedHashSet; +import java.util.Set; +import javax.persistence.criteria.CollectionJoin; +import javax.persistence.criteria.Fetch; import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.CollectionJoin; -import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.ListJoin; import javax.persistence.criteria.MapJoin; -import javax.persistence.criteria.Path; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Fetch; +import javax.persistence.criteria.SetJoin; import javax.persistence.metamodel.Attribute; -import javax.persistence.metamodel.Attribute.PersistentAttributeType; -import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.CollectionAttribute; -import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.ListAttribute; -import javax.persistence.metamodel.MapAttribute; -import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.PluralAttribute; -import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.SetAttribute; +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.Type; -import javax.persistence.metamodel.PluralAttribute.CollectionType; -import javax.persistence.metamodel.Type.PersistenceType; -import org.hibernate.ejb.criteria.expression.CollectionExpression; -import org.hibernate.ejb.criteria.expression.EntityTypeExpression; +import org.hibernate.ejb.criteria.BasicPathUsageException; +import org.hibernate.ejb.criteria.CollectionJoinImplementor; +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.JoinImplementor; +import org.hibernate.ejb.criteria.ListJoinImplementor; +import org.hibernate.ejb.criteria.MapJoinImplementor; +import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.SetJoinImplementor; /** - * TODO : javadoc + * Convenience base class for various {@link javax.persistence.criteria.From} implementors. * * @author Steve Ebersole */ -public abstract class FromImpl - extends PathImpl - implements From, TableExpressionMapper, Serializable { +public abstract class AbstractFromImpl + extends AbstractPathImpl + implements From, FromImplementor, Serializable { + public static final JoinType DEFAULT_JOIN_TYPE = JoinType.INNER; - private final Expression> typeExpression; private Set> joins; private Set> fetches; - /** - * Helper contract used to define who/what keeps track of joins and fetches made from this FROM. - */ - public static interface JoinScope extends Serializable { - public void addJoin(Join join); - public void addFetch(Fetch fetch); - public boolean isCorrelated(); - public From getCorrelationParent(); + public AbstractFromImpl(CriteriaBuilderImpl criteriaBuilder, Class javaType) { + this( criteriaBuilder, javaType, null ); } + public AbstractFromImpl(CriteriaBuilderImpl criteriaBuilder, Class javaType, PathSource pathSource) { + super( criteriaBuilder, javaType, pathSource ); + } + + @Override + @SuppressWarnings({ "unchecked" }) + public PathSource getPathSource() { + return super.getPathSource(); + } + + @Override + public String getPathIdentifier() { + return getAlias(); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean canBeDereferenced() { + return true; + } + + /** + * {@inheritDoc} + */ + public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + if ( getAlias() == null ) { + setAlias( renderingContext.generateAlias() ); + } + } + + /** + * {@inheritDoc} + */ + public Attribute getAttribute() { + return null; + } + + /** + * {@inheritDoc} + */ + public From getParent() { + return null; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + protected Attribute locateAttributeInternal(String name) { + return (Attribute) locateManagedType().getAttribute( name ); + } + + @SuppressWarnings({ "unchecked" }) + protected ManagedType locateManagedType() { + // by default, this should be the model + return (ManagedType) getModel(); + } + + + // CORRELATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private From correlationParent; private JoinScope joinScope = new JoinScope() { public void addJoin(Join join) { if ( joins == null ) { @@ -93,72 +152,50 @@ public abstract class FromImpl } fetches.add( fetch ); } - - public boolean isCorrelated() { - return false; - } - - public From getCorrelationParent() { - return null; - } }; /** - * Special constructor for {@link RootImpl}. - * - * @param criteriaBuilder The query build - * @param entityType The entity defining this root + * {@inheritDoc} */ - @SuppressWarnings({ "unchecked" }) - protected FromImpl(CriteriaBuilderImpl criteriaBuilder, EntityType entityType) { - super( criteriaBuilder, entityType.getBindableJavaType(), null, null, entityType ); - this.typeExpression = new EntityTypeExpression( criteriaBuilder, entityType.getBindableJavaType() ); + public boolean isCorrelated() { + return getCorrelationParent() != null; } /** - * The general constructor for a {@link From} implementor. - * - * @param criteriaBuilder - * @param javaType - * @param origin - * @param attribute - * @param model + * {@inheritDoc} */ - @SuppressWarnings({ "unchecked" }) - public FromImpl( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl origin, - Attribute attribute, - Bindable model) { - super( criteriaBuilder, javaType, origin, attribute, model ); - this.typeExpression = new EntityTypeExpression( criteriaBuilder, model.getBindableJavaType() ); + public From getCorrelationParent() { + return correlationParent; } - protected void defineJoinScope(JoinScope joinScope) { + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public FromImplementor correlateTo(CriteriaSubqueryImpl subquery) { + final FromImplementor correlationDelegate = createCorrelationDelegate(); + correlationDelegate.prepareCorrelationDelegate( subquery.getJoinScope(), this ); + return correlationDelegate; + } + + protected abstract FromImplementor createCorrelationDelegate(); + + public void prepareCorrelationDelegate(JoinScope joinScope, FromImplementor parent) { this.joinScope = joinScope; + this.correlationParent = parent; } - @Override - public Expression> type() { - return typeExpression; - } - - /** - * Get the attribute by name from the underlying model. This alows subclasses to - * define exactly how the attribute is derived. - * - * @param name The attribute name - * - * @return The attribute. - * - * @throws IllegalArgumentException If no such attribute is found (follows exception type from {@link ManagedType}). - */ - protected abstract Attribute getAttribute(String name); - // JOINS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + protected abstract boolean canBeJoinSource(); + + private RuntimeException illegalJoin() { + return new IllegalArgumentException( + "Collection of values [" + getPathIdentifier() + "] cannot be source of a join" + ); + } + /** * {@inheritDoc} */ @@ -177,13 +214,17 @@ public abstract class FromImpl * {@inheritDoc} */ public Join join(SingularAttribute attribute, JoinType jt) { + if ( ! canBeJoinSource() ) { + throw illegalJoin(); + } + Join join = constructJoin( attribute, jt ); joinScope.addJoin( join ); return join; } - private JoinImplementors.JoinImplementor constructJoin(SingularAttribute attribute, JoinType jt) { - if ( PersistenceType.BASIC.equals( attribute.getType().getPersistenceType() ) ) { + private JoinImplementor constructJoin(SingularAttribute attribute, JoinType jt) { + if ( Type.PersistenceType.BASIC.equals( attribute.getType().getPersistenceType() ) ) { throw new BasicPathUsageException( "Cannot join to attribute of basic type", attribute ); } @@ -194,7 +235,7 @@ public abstract class FromImpl } final Class attributeType = attribute.getBindableJavaType(); - return new JoinImpl( + return new SingularAttributeJoin( queryBuilder(), attributeType, this, @@ -213,41 +254,30 @@ public abstract class FromImpl * {@inheritDoc} */ public CollectionJoin join(CollectionAttribute collection, JoinType jt) { + if ( ! canBeJoinSource() ) { + throw illegalJoin(); + } + final CollectionJoin join = constructJoin( collection, jt ); joinScope.addJoin( join ); return join; } - private JoinImplementors.CollectionJoinImplementor constructJoin(CollectionAttribute collection, JoinType jt) { + private CollectionJoinImplementor constructJoin(CollectionAttribute collection, JoinType jt) { if ( jt.equals( JoinType.RIGHT ) ) { throw new UnsupportedOperationException( "RIGHT JOIN not supported" ); } - final Class attributeType = collection.getBindableJavaType(); - final JoinImplementors.CollectionJoinImplementor join; - if ( isBasicCollection( collection ) ) { - join = new BasicCollectionJoinImpl( - queryBuilder(), - attributeType, - this, - collection, - jt - ); - } - else { - join = new CollectionJoinImpl( - queryBuilder(), - attributeType, - this, - collection, - jt - ); - } - return join; - } + // TODO : runtime check that the attribute in fact belongs to this From's model/bindable - private boolean isBasicCollection(PluralAttribute collection) { - return PersistenceType.BASIC.equals( collection.getElementType().getPersistenceType() ); + final Class attributeType = collection.getBindableJavaType(); + return new CollectionAttributeJoin( + queryBuilder(), + attributeType, + this, + collection, + jt + ); } /** @@ -261,25 +291,24 @@ public abstract class FromImpl * {@inheritDoc} */ public SetJoin join(SetAttribute set, JoinType jt) { + if ( ! canBeJoinSource() ) { + throw illegalJoin(); + } + final SetJoin join = constructJoin( set, jt ); joinScope.addJoin( join ); return join; } - private JoinImplementors.SetJoinImplementor constructJoin(SetAttribute set, JoinType jt) { + private SetJoinImplementor constructJoin(SetAttribute set, JoinType jt) { if ( jt.equals( JoinType.RIGHT ) ) { throw new UnsupportedOperationException( "RIGHT JOIN not supported" ); } + // TODO : runtime check that the attribute in fact belongs to this From's model/bindable + final Class attributeType = set.getBindableJavaType(); - final JoinImplementors.SetJoinImplementor join; - if ( isBasicCollection( set ) ) { - join = new BasicSetJoinImpl( queryBuilder(), attributeType, this, set, jt ); - } - else { - join = new SetJoinImpl( queryBuilder(), attributeType, this, set, jt ); - } - return join; + return new SetAttributeJoin( queryBuilder(), attributeType, this, set, jt ); } /** @@ -293,25 +322,24 @@ public abstract class FromImpl * {@inheritDoc} */ public ListJoin join(ListAttribute list, JoinType jt) { + if ( ! canBeJoinSource() ) { + throw illegalJoin(); + } + final ListJoin join = constructJoin( list, jt ); joinScope.addJoin( join ); return join; } - private JoinImplementors.ListJoinImplementor constructJoin(ListAttribute list, JoinType jt) { + private ListJoinImplementor constructJoin(ListAttribute list, JoinType jt) { if ( jt.equals( JoinType.RIGHT ) ) { throw new UnsupportedOperationException( "RIGHT JOIN not supported" ); } + // TODO : runtime check that the attribute in fact belongs to this From's model/bindable + final Class attributeType = list.getBindableJavaType(); - final JoinImplementors.ListJoinImplementor join; - if ( isBasicCollection( list ) ) { - join = new BasicListJoinImpl( queryBuilder(), attributeType, this, list, jt ); - } - else { - join = new ListJoinImpl( queryBuilder(), attributeType, this, list, jt ); - } - return join; + return new ListAttributeJoin( queryBuilder(), attributeType, this, list, jt ); } /** @@ -325,25 +353,24 @@ public abstract class FromImpl * {@inheritDoc} */ public MapJoin join(MapAttribute map, JoinType jt) { + if ( ! canBeJoinSource() ) { + throw illegalJoin(); + } + final MapJoin join = constructJoin( map, jt ); joinScope.addJoin( join ); return join; } - private JoinImplementors.MapJoinImplementor constructJoin(MapAttribute map, JoinType jt) { + private MapJoinImplementor constructJoin(MapAttribute map, JoinType jt) { if ( jt.equals( JoinType.RIGHT ) ) { throw new UnsupportedOperationException( "RIGHT JOIN not supported" ); } + // TODO : runtime check that the attribute in fact belongs to this From's model/bindable + final Class attributeType = map.getBindableJavaType(); - final JoinImplementors.MapJoinImplementor join; - if ( isBasicCollection( map ) ) { - join = new BasicMapJoinImpl( queryBuilder(), attributeType, this, map, jt ); - } - else { - join = new MapJoinImpl( queryBuilder(), attributeType, this, map, jt ); - } - return join; + return new MapAttributeJoin( queryBuilder(), attributeType, this, map, jt ); } /** @@ -358,20 +385,24 @@ public abstract class FromImpl */ @SuppressWarnings({ "unchecked" }) public Join join(String attributeName, JoinType jt) { + if ( ! canBeJoinSource() ) { + throw illegalJoin(); + } + if ( jt.equals( JoinType.RIGHT ) ) { throw new UnsupportedOperationException( "RIGHT JOIN not supported" ); } - final Attribute attribute = (Attribute) getAttribute( attributeName ); + final Attribute attribute = (Attribute) locateAttribute( attributeName ); if ( attribute.isCollection() ) { final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute; - if ( CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) { + if ( PluralAttribute.CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) { return (Join) join( (CollectionAttribute) attribute, jt ); } - else if ( CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) { + else if ( PluralAttribute.CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) { return (Join) join( (ListAttribute) attribute, jt ); } - else if ( CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) { + else if ( PluralAttribute.CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) { return (Join) join( (SetAttribute) attribute, jt ); } else { @@ -395,13 +426,13 @@ public abstract class FromImpl */ @SuppressWarnings({ "unchecked" }) public CollectionJoin joinCollection(String attributeName, JoinType jt) { - final Attribute attribute = (Attribute) getAttribute( attributeName ); + final Attribute attribute = (Attribute) locateAttribute( attributeName ); if ( ! attribute.isCollection() ) { throw new IllegalArgumentException( "Requested attribute was not a collection" ); } final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute; - if ( ! CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) { + if ( ! PluralAttribute.CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) { throw new IllegalArgumentException( "Requested attribute was not a collection" ); } @@ -420,13 +451,13 @@ public abstract class FromImpl */ @SuppressWarnings({ "unchecked" }) public SetJoin joinSet(String attributeName, JoinType jt) { - final Attribute attribute = (Attribute) getAttribute( attributeName ); + final Attribute attribute = (Attribute) locateAttribute( attributeName ); if ( ! attribute.isCollection() ) { throw new IllegalArgumentException( "Requested attribute was not a set" ); } final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute; - if ( ! CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) { + if ( ! PluralAttribute.CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) { throw new IllegalArgumentException( "Requested attribute was not a set" ); } @@ -445,13 +476,13 @@ public abstract class FromImpl */ @SuppressWarnings({ "unchecked" }) public ListJoin joinList(String attributeName, JoinType jt) { - final Attribute attribute = (Attribute) getAttribute( attributeName ); + final Attribute attribute = (Attribute) locateAttribute( attributeName ); if ( ! attribute.isCollection() ) { throw new IllegalArgumentException( "Requested attribute was not a list" ); } final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute; - if ( ! CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) { + if ( ! PluralAttribute.CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) { throw new IllegalArgumentException( "Requested attribute was not a list" ); } @@ -470,13 +501,13 @@ public abstract class FromImpl */ @SuppressWarnings({ "unchecked" }) public MapJoin joinMap(String attributeName, JoinType jt) { - final Attribute attribute = (Attribute) getAttribute( attributeName ); + final Attribute attribute = (Attribute) locateAttribute( attributeName ); if ( ! attribute.isCollection() ) { throw new IllegalArgumentException( "Requested attribute was not a map" ); } final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute; - if ( ! CollectionType.MAP.equals( pluralAttribute.getCollectionType() ) ) { + if ( ! PluralAttribute.CollectionType.MAP.equals( pluralAttribute.getCollectionType() ) ) { throw new IllegalArgumentException( "Requested attribute was not a map" ); } @@ -486,6 +517,17 @@ public abstract class FromImpl // FETCHES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + protected boolean canBeFetchSource() { + // the conditions should be the same... + return canBeJoinSource(); + } + + private RuntimeException illegalFetch() { + return new IllegalArgumentException( + "Collection of values [" + getPathIdentifier() + "] cannot be source of a fetch" + ); + } + /** * {@inheritDoc} */ @@ -493,21 +535,15 @@ public abstract class FromImpl return fetches; } - /** - * Retrieve the collection of fetches, imnplementing delayed creations. Calls on this method - * assume the set is physically needed, and as a result the set is built if not already. - * - * @return The set of fetches. - */ - public Set> internalGetFetches() { - return fetches; - } - public Fetch fetch(SingularAttribute singularAttribute) { return fetch( singularAttribute, DEFAULT_JOIN_TYPE ); } public Fetch fetch(SingularAttribute attribute, JoinType jt) { + if ( ! canBeFetchSource() ) { + throw illegalFetch(); + } + Fetch fetch = constructJoin( attribute, jt ); joinScope.addFetch( fetch ); return fetch; @@ -518,15 +554,19 @@ public abstract class FromImpl } public Fetch fetch(PluralAttribute pluralAttribute, JoinType jt) { + if ( ! canBeFetchSource() ) { + throw illegalFetch(); + } + final Fetch fetch; // TODO : combine Fetch and Join hierarchies (JoinImplementor extends Join,Fetch???) - if ( CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) { + if ( PluralAttribute.CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) { fetch = constructJoin( (CollectionAttribute) pluralAttribute, jt ); } - else if ( CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) { + else if ( PluralAttribute.CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) { fetch = constructJoin( (ListAttribute) pluralAttribute, jt ); } - else if ( CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) { + else if ( PluralAttribute.CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) { fetch = constructJoin( (SetAttribute) pluralAttribute, jt ); } else { @@ -542,7 +582,11 @@ public abstract class FromImpl @SuppressWarnings({ "unchecked" }) public Fetch fetch(String attributeName, JoinType jt) { - Attribute attribute = (Attribute) getAttribute( attributeName ); + if ( ! canBeFetchSource() ) { + throw illegalFetch(); + } + + Attribute attribute = (Attribute) locateAttribute( attributeName ); if ( attribute.isCollection() ) { return (Fetch) fetch( (PluralAttribute) attribute, jt ); } @@ -550,80 +594,4 @@ public abstract class FromImpl return (Fetch) fetch( (SingularAttribute) attribute, jt ); } } - - - // PATH HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - @Override - public Path get(SingularAttribute attribute) { - if ( PersistentAttributeType.BASIC.equals( attribute.getPersistentAttributeType() ) ) { - return new PathImpl( queryBuilder(), attribute.getJavaType(), this, attribute, attribute.getBindableType() ); - } - else { - return join( attribute ); - } - } - - @Override - public > Expression get(PluralAttribute collection) { - return new CollectionExpression( queryBuilder(), collection.getJavaType(), this, collection ); - } - - @Override - @SuppressWarnings({ "unchecked" }) - public > Expression get(MapAttribute map) { - return ( Expression ) new CollectionExpression>( queryBuilder(), map.getJavaType(), this, map ); - } - - @Override - @SuppressWarnings({ "unchecked" }) - public Path get(String attributeName) { - Attribute attribute = getAttribute( attributeName ); - if ( attribute.isCollection() ) { - final PluralAttribute pluralAttribute = (PluralAttribute) attribute; - if ( CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) { - return join( (CollectionAttribute) attribute ); - } - else if ( CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) { - return join( (ListAttribute) attribute ); - } - else if ( CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) { - return join( (SetAttribute) attribute ); - } - else { - return join( (MapAttribute) attribute ); - } - } - else { - return get( (SingularAttribute) attribute ); - } - } - - @Override - public String getPathIdentifier() { - return getAlias(); - } - - @Override - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { - prepareAlias( renderingContext ); - return getAlias(); - } - - @Override - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { - prepareAlias( renderingContext ); - return getAlias(); - } - - public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) { - prepareAlias( renderingContext ); - return ( (EntityType) getModel() ).getName() + " as " + getAlias(); - } - - public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { - if ( getAlias() == null ) { - setAlias( renderingContext.generateAlias() ); - } - } } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java new file mode 100644 index 0000000000..d91eed8dc7 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java @@ -0,0 +1,103 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import java.io.Serializable; + +import javax.persistence.criteria.From; +import javax.persistence.criteria.JoinType; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.JoinImplementor; +import org.hibernate.ejb.criteria.PathSource; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public abstract class AbstractJoinImpl + extends AbstractFromImpl + implements JoinImplementor, Serializable { + + private final Attribute joinAttribute; + private final JoinType joinType; + + public AbstractJoinImpl( + CriteriaBuilderImpl criteriaBuilder, + PathSource pathSource, + Attribute joinAttribute, + JoinType joinType) { + this( criteriaBuilder, joinAttribute.getJavaType(), pathSource, joinAttribute, joinType ); + } + + public AbstractJoinImpl( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource, + Attribute joinAttribute, + JoinType joinType) { + super( criteriaBuilder, javaType, pathSource ); + this.joinAttribute = joinAttribute; + this.joinType = joinType; + } + + /** + * {@inheritDoc} + */ + public Attribute getAttribute() { + return joinAttribute; + } + + /** + * {@inheritDoc} + */ + public JoinType getJoinType() { + return joinType; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public From getParent() { + // this cast should be ok by virtue of our constructors... + return (From) getPathSource(); + } + + public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) { + prepareAlias( renderingContext ); + ( (FromImplementor) getParent() ).prepareAlias( renderingContext ); + return getParent().getAlias() + '.' + getAttribute().getName() + " as " + getAlias(); + } + + + public JoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { + return (JoinImplementor) super.correlateTo( subquery ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java new file mode 100644 index 0000000000..55e12d151e --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java @@ -0,0 +1,263 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Path; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.MapAttribute; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.SingularAttribute; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.ParameterRegistry; +import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.expression.ExpressionImpl; +import org.hibernate.ejb.criteria.expression.PathTypeExpression; + +/** + * Convenience base class for various {@link Path} implementors. + * + * @author Steve Ebersole + */ +public abstract class AbstractPathImpl + extends ExpressionImpl + implements Path, PathImplementor, Serializable { + + private final PathSource pathSource; + private final Expression> typeExpression; + private Map attributePathRegistry; + + /** + * Constructs a basic path instance. + * + * @param criteriaBuilder The criteria builder + * @param javaType The java type of this path + * @param pathSource The source (or origin) from which this path originates + */ + @SuppressWarnings({ "unchecked" }) + public AbstractPathImpl( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource) { + super( criteriaBuilder, javaType ); + this.pathSource = pathSource; + this.typeExpression = new PathTypeExpression( queryBuilder(), getJavaType() ); + } + + public PathSource getPathSource() { + return pathSource; + } + + /** + * {@inheritDoc} + */ + public PathSource getParentPath() { + return getPathSource(); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Expression> type() { + return typeExpression; + } + + /** + * {@inheritDoc} + */ + public String getPathIdentifier() { + return getPathSource().getPathIdentifier() + "." + getAttribute().getName(); + } + + protected abstract boolean canBeDereferenced(); + + protected final RuntimeException illegalDereference() { + return new IllegalArgumentException( + "Illegal attempt to dereference path source [" + getPathSource().getPathIdentifier() + "]" + ); + } + + protected final RuntimeException unknownAttribute(String attributeName) { + return new IllegalArgumentException( + "Unable to resolve attribute [" + attributeName + "] against path [" + + getPathSource().getPathIdentifier() + "]" + ); + } + + protected final Path resolveCachedAttributePath(String attributeName) { + return attributePathRegistry == null + ? null + : attributePathRegistry.get( attributeName ); + } + + protected final void registerAttributePath(String attributeName, Path path) { + if ( attributePathRegistry == null ) { + attributePathRegistry = new HashMap(); + } + attributePathRegistry.put( attributeName, path ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Path get(SingularAttribute attribute) { + if ( ! canBeDereferenced() ) { + throw illegalDereference(); + } + + SingularAttributePath path = (SingularAttributePath) resolveCachedAttributePath( attribute.getName() ); + if ( path == null ) { + path = new SingularAttributePath( queryBuilder(), attribute.getJavaType(), this, attribute ); + registerAttributePath( attribute.getName(), path ); + } + return path; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public > Expression get(PluralAttribute attribute) { + if ( ! canBeDereferenced() ) { + throw illegalDereference(); + } + + PluralAttributePath path = (PluralAttributePath) resolveCachedAttributePath( attribute.getName() ); + if ( path == null ) { + path = new PluralAttributePath( queryBuilder(), this, attribute ); + registerAttributePath( attribute.getName(), path ); + } + return path; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public > Expression get(MapAttribute attribute) { + if ( ! canBeDereferenced() ) { + throw illegalDereference(); + } + + PluralAttributePath path = (PluralAttributePath) resolveCachedAttributePath( attribute.getName() ); + if ( path == null ) { + path = new PluralAttributePath( queryBuilder(), this, attribute ); + registerAttributePath( attribute.getName(), path ); + } + return path; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Path get(String attributeName) { + if ( ! canBeDereferenced() ) { + throw illegalDereference(); + } + + final Attribute attribute = locateAttribute( attributeName ); + + if ( attribute.isCollection() ) { + final PluralAttribute pluralAttribute = (PluralAttribute) attribute; + if ( PluralAttribute.CollectionType.MAP.equals( pluralAttribute.getCollectionType() ) ) { + return (PluralAttributePath) get( (MapAttribute) pluralAttribute ); + } + else { + return (PluralAttributePath) get( (PluralAttribute) pluralAttribute ); + } + } + else { + return get( (SingularAttribute) attribute ); + } + } + + /** + * Get the attribute by name from the underlying model. This allows subclasses to + * define exactly how the attribute is derived. + * + * @param attributeName The name of the attribute to locate + * + * @return The attribute; should never return null. + * + * @throws IllegalArgumentException If no such attribute exists + */ + protected final Attribute locateAttribute(String attributeName) { + final Attribute attribute = locateAttributeInternal( attributeName ); + if ( attribute == null ) { + throw unknownAttribute( attributeName ); + } + return attribute; + } + + /** + * Get the attribute by name from the underlying model. This allows subclasses to + * define exactly how the attribute is derived. Called from {@link #locateAttribute} + * which also applies nullness checking for proper error reporting. + * + * @param attributeName The name of the attribute to locate + * + * @return The attribute; may be null. + * + * @throws IllegalArgumentException If no such attribute exists + */ + protected abstract Attribute locateAttributeInternal(String attributeName); + + /** + * {@inheritDoc} + */ + public void registerParameters(ParameterRegistry registry) { + // none to register + } + + public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) { + // Make sure we delegate up to our source (eventually up to the path root) to + // prepare the path properly. + getPathSource().prepareAlias( renderingContext ); + } + + /** + * {@inheritDoc} + */ + public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + getPathSource().prepareAlias( renderingContext ); + return getPathSource().getPathIdentifier() + "." + getAttribute().getName(); + } + + /** + * {@inheritDoc} + */ + public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + return render( renderingContext ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java new file mode 100644 index 0000000000..d775db44ec --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java @@ -0,0 +1,80 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import java.io.Serializable; +import java.util.Collection; + +import javax.persistence.criteria.JoinType; +import javax.persistence.metamodel.CollectionAttribute; + +import org.hibernate.ejb.criteria.CollectionJoinImplementor; +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.PathSource; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class CollectionAttributeJoin + extends PluralAttributeJoinSupport,E> + implements CollectionJoinImplementor, Serializable { + public CollectionAttributeJoin( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource, + CollectionAttribute joinAttribute, + JoinType joinType) { + super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType ); + } + + public final CollectionAttributeJoin correlateTo(CriteriaSubqueryImpl subquery) { + return (CollectionAttributeJoin) super.correlateTo( subquery ); + } + + @Override + public CollectionAttribute getAttribute() { + return (CollectionAttribute) super.getAttribute(); + } + + @Override + public CollectionAttribute getModel() { + return getAttribute(); + } + + @Override + protected FromImplementor createCorrelationDelegate() { + return new CollectionAttributeJoin( + queryBuilder(), + getJavaType(), + (PathImplementor) getParentPath(), + getAttribute(), + getJoinType() + ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java similarity index 52% rename from entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java rename to entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java index 4b24de6da2..7a179cd5a7 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. + * Copyright (c) 2010, Red Hat Inc. 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 Inc. * * 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 @@ -21,33 +21,46 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.ejb.criteria; +package org.hibernate.ejb.criteria.path; import java.io.Serializable; +import java.util.List; + import javax.persistence.criteria.Expression; import javax.persistence.criteria.JoinType; -import javax.persistence.criteria.From; import javax.persistence.metamodel.ListAttribute; -import org.hibernate.ejb.criteria.JoinImplementors.ListJoinImplementor; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.ListJoinImplementor; +import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.PathSource; import org.hibernate.ejb.criteria.expression.ListIndexExpression; /** - * Represents a join to a persistent collection, defined as type {@link java.util.List}, whose elements - * are basic type. + * TODO : javadoc * * @author Steve Ebersole */ -public class BasicListJoinImpl - extends AbstractBasicPluralJoin,E> - implements JoinImplementors.ListJoinImplementor, Serializable { +public class ListAttributeJoin + extends PluralAttributeJoinSupport,E> + implements ListJoinImplementor, Serializable { - public BasicListJoinImpl( + public ListAttributeJoin( CriteriaBuilderImpl criteriaBuilder, Class javaType, - PathImpl lhs, - ListAttribute joinProperty, + PathSource pathSource, + ListAttribute joinAttribute, JoinType joinType) { - super( criteriaBuilder, javaType, lhs, joinProperty, joinType); + super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType ); + } + + /** + * {@inheritDoc} + */ + public Expression index() { + return new ListIndexExpression( queryBuilder(), this, getAttribute() ); } @Override @@ -57,40 +70,22 @@ public class BasicListJoinImpl @Override public ListAttribute getModel() { - return getAttribute(); - } - - public Expression index() { - return new ListIndexExpression( queryBuilder(), this, getAttribute() ); + return getAttribute(); } @Override - public ListJoinImplementor correlateTo(CriteriaSubqueryImpl subquery) { - BasicListJoinImpl correlation = new BasicListJoinImpl( + public final ListAttributeJoin correlateTo(CriteriaSubqueryImpl subquery) { + return (ListAttributeJoin) super.correlateTo( subquery ); + } + + @Override + protected FromImplementor createCorrelationDelegate() { + return new ListAttributeJoin( queryBuilder(), getJavaType(), - (PathImpl) getParentPath(), + (PathImplementor) getParentPath(), getAttribute(), getJoinType() ); - correlation.defineJoinScope( subquery.getJoinScope() ); - correlation.correlationParent = this; - return correlation; - } - - private From correlationParent; - - /** - * {@inheritDoc} - */ - public boolean isCorrelated() { - return getCorrelationParent() != null; - } - - /** - * {@inheritDoc} - */ - public From getCorrelationParent() { - return correlationParent; } } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java new file mode 100644 index 0000000000..5dade3174c --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java @@ -0,0 +1,117 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import java.io.Serializable; +import java.util.Map; + +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.JoinType; +import javax.persistence.criteria.Path; +import javax.persistence.metamodel.MapAttribute; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.MapJoinImplementor; +import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.expression.MapEntryExpression; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class MapAttributeJoin + extends PluralAttributeJoinSupport, V> + implements MapJoinImplementor, Serializable { + + public MapAttributeJoin( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource, + MapAttribute joinAttribute, + JoinType joinType) { + super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType ); + } + + @Override + public MapAttribute getAttribute() { + return (MapAttribute) super.getAttribute(); + } + + @Override + public MapAttribute getModel() { + return getAttribute(); + } + + @Override + public final MapAttributeJoin correlateTo(CriteriaSubqueryImpl subquery) { + return (MapAttributeJoin) super.correlateTo( subquery ); + } + + @Override + protected FromImplementor createCorrelationDelegate() { + return new MapAttributeJoin( + queryBuilder(), + getJavaType(), + (PathImplementor) getParentPath(), + getAttribute(), + getJoinType() + ); + } + + + /** + * {@inheritDoc} + */ + public Path value() { + return this; + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Expression> entry() { + return new MapEntryExpression( queryBuilder(), Map.Entry.class, this, getAttribute() ); + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "unchecked" }) + public Path key() { + final MapKeyHelpers.MapKeySource mapKeySource = new MapKeyHelpers.MapKeySource( + queryBuilder(), + getAttribute().getJavaType(), + this, + getAttribute() + ); + final MapKeyHelpers.MapKeyAttribute mapKeyAttribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() ); + return new MapKeyHelpers.MapKeyPath( queryBuilder(), mapKeySource, mapKeyAttribute ); + } + +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java similarity index 50% rename from entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java rename to entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java index 65bcfa23f2..4a91ca7ef1 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java @@ -21,144 +21,167 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.ejb.criteria; +package org.hibernate.ejb.criteria.path; import java.io.Serializable; import java.lang.reflect.Member; import java.util.Map; -import java.util.Map.Entry; -import javax.persistence.criteria.Expression; -import javax.persistence.criteria.From; import javax.persistence.criteria.Join; -import javax.persistence.criteria.JoinType; import javax.persistence.criteria.MapJoin; import javax.persistence.criteria.Path; import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Bindable; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.SingularAttribute; -import javax.persistence.metamodel.Type.PersistenceType; +import javax.persistence.metamodel.Type; -import org.hibernate.ejb.criteria.JoinImplementors.JoinImplementor; -import org.hibernate.ejb.criteria.expression.ExpressionImpl; +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.MapJoinImplementor; +import org.hibernate.ejb.criteria.PathImplementor; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.persister.collection.CollectionPersister; -import org.hibernate.type.Type; /** - * {@link MapJoin} defines a number of methods which require {@link Path}, {@link Join} and {@link Attribute} - * implementations which do not fit nicely into the generic signatures it defines for everything else (mainly - * in terms of dealing with the map key). The implementations found here provide that bridge. + * {@link MapJoin#key} poses a number of implementation difficulties in terms of the type signatures + * amongst the {@link Path}, {@link Join} and {@link Attribute} reference at play. The implementations found here + * provide that bridge. * * @author Steve Ebersole */ public class MapKeyHelpers { /** - * Represents a join to the key of a map attribute. Obviously the map key must be an - * entity or component type. - * - * @param The type of the map key - * @param The type of the map value - */ - public static class MapKeyJoin - extends JoinImpl, K> - implements Join, K>, Serializable { - - public MapKeyJoin( - CriteriaBuilderImpl criteriaBuilder, - MapPath source, - MapKeyAttribute attribute, - JoinType jt) { - super( - criteriaBuilder, - attribute.getJavaType(), - source, - attribute, - jt - ); - } - - @Override - public JoinImplementor, K> correlateTo(CriteriaSubqueryImpl subquery) { - throw new UnsupportedOperationException( "Map key join cannot be used as a correlation" ); - } - - public boolean isCorrelated() { - return false; - } - - public From, K> getCorrelationParent() { - return null; - } - } - - /** - * Models a path to a map key. + * Models a path to a map key. This is the actual return used from {@link MapJoin#key} * * @param The type of the map key. */ - public static class MapKeyPath extends PathImpl implements Path, Serializable { + public static class MapKeyPath + extends AbstractPathImpl + implements PathImplementor, Serializable { + + private final MapKeyAttribute mapKeyAttribute; + public MapKeyPath( CriteriaBuilderImpl criteriaBuilder, - MapPath source, - MapKeyAttribute attribute) { - super( criteriaBuilder, attribute.getJavaType(), source, attribute, attribute.getType() ); + MapKeySource source, + MapKeyAttribute mapKeyAttribute) { + super( criteriaBuilder, mapKeyAttribute.getJavaType(), source ); + this.mapKeyAttribute = mapKeyAttribute; + } + + @Override + public MapKeySource getPathSource() { + return (MapKeySource) super.getPathSource(); + } + + public MapKeyAttribute getAttribute() { + return mapKeyAttribute; + } + + private boolean isBasicTypeKey() { + return Attribute.PersistentAttributeType.BASIC == + mapKeyAttribute.getPersistentAttributeType(); + } + + @Override + protected boolean canBeDereferenced() { + return ! isBasicTypeKey(); + } + + @Override + protected Attribute locateAttributeInternal(String attributeName) { + if ( ! canBeDereferenced() ) { + throw new IllegalArgumentException( + "Map key [" + getPathSource().getPathIdentifier() + "] cannot be dereferenced" + ); + } + throw new UnsupportedOperationException( "Not yet supported!" ); + } + + public Bindable getModel() { + return mapKeyAttribute; } } /** - * Defines a {@link Path} resulting in a map attribute. This can then be used as the - * parent/origin/source for referencing the map-key. + * Defines a {@link Path} for the map which can then be used to represent the source of the + * map key "attribute". * * @param The map key type * @param The map value type */ - public static class MapPath extends PathImpl> implements Path>, Serializable { - private final MapJoin mapJoin; + public static class MapKeySource + extends AbstractPathImpl> + implements PathImplementor>, Serializable { - public MapPath( + private final MapAttribute mapAttribute; + private final MapJoinImplementor mapJoin; + + public MapKeySource( CriteriaBuilderImpl criteriaBuilder, Class> javaType, - MapJoin mapJoin, - MapAttribute attribute, - Object model) { - super( criteriaBuilder, javaType, null, attribute, model); + MapJoinImplementor mapJoin, + MapAttribute attribute) { + super( criteriaBuilder, javaType, null ); this.mapJoin = mapJoin; + this.mapAttribute = attribute; } - @Override public MapAttribute getAttribute() { - return (MapAttribute) super.getAttribute(); + return mapAttribute; + } + + @SuppressWarnings({ "unchecked" }) + public Bindable> getModel() { + // TODO : ok??? the attribute is in fact bindable, but its type signature is different + return (Bindable>) mapAttribute; } @Override - public PathImpl getParentPath() { - return (PathImpl) mapJoin; + public PathImplementor getParentPath() { + return (PathImplementor) mapJoin.getParentPath(); + } + + @Override + protected boolean canBeDereferenced() { + return false; + } + + @Override + protected Attribute locateAttributeInternal(String attributeName) { + throw new IllegalArgumentException( "Map [" + mapJoin.getPathIdentifier() + "] cannot be dereferenced" ); } } /** - * Defines an {@link Attribute} modelling of a map-key. - *

- * TODO : Ideally something like this needs to be part of the metamodel package + * Disallow instantiation + */ + private MapKeyHelpers() { + } + + /** + * Defines an {@link javax.persistence.metamodel.Attribute} modelling of a map-key. * * @param The type of the map key */ - public static class MapKeyAttribute implements SingularAttribute,K>, Serializable { + public static class MapKeyAttribute + implements SingularAttribute,K>, Bindable, Serializable { private final MapAttribute attribute; private final CollectionPersister mapPersister; - private final Type mapKeyType; - private final javax.persistence.metamodel.Type jpaType; + private final org.hibernate.type.Type mapKeyType; + private final Type jpaType; private final BindableType jpaBindableType; private final Class jpaBinableJavaType; + private final PersistentAttributeType persistentAttributeType; public MapKeyAttribute(CriteriaBuilderImpl criteriaBuilder, MapAttribute attribute) { this.attribute = attribute; this.jpaType = attribute.getKeyType(); this.jpaBinableJavaType = attribute.getKeyJavaType(); - this.jpaBindableType = PersistenceType.ENTITY.equals( jpaType.getPersistenceType() ) + this.jpaBindableType = Type.PersistenceType + .ENTITY.equals( jpaType.getPersistenceType() ) ? BindableType.ENTITY_TYPE : BindableType.SINGULAR_ATTRIBUTE; @@ -173,6 +196,12 @@ public class MapKeyHelpers { if ( mapKeyType == null ) { throw new IllegalStateException( "Could not determine map-key type [" + guessedRoleName + "]" ); } + + this.persistentAttributeType = mapKeyType.isEntityType() + ? PersistentAttributeType.MANY_TO_ONE + : mapKeyType.isComponentType() + ? PersistentAttributeType.EMBEDDED + : PersistentAttributeType.BASIC; } private String determineRole(MapAttribute attribute) { @@ -192,15 +221,7 @@ public class MapKeyHelpers { * {@inheritDoc} */ public PersistentAttributeType getPersistentAttributeType() { - if ( mapKeyType.isEntityType() ) { - return PersistentAttributeType.MANY_TO_ONE; - } - else if ( mapKeyType.isComponentType() ) { - return PersistentAttributeType.EMBEDDED; - } - else { - return PersistentAttributeType.BASIC; - } + return persistentAttributeType; } /** @@ -252,7 +273,7 @@ public class MapKeyHelpers { return false; } - public javax.persistence.metamodel.Type getType() { + public Type getType() { return jpaType; } @@ -264,51 +285,4 @@ public class MapKeyHelpers { return jpaBinableJavaType; } } - - public static class MapEntryExpression - extends ExpressionImpl> - implements Expression>, Serializable { - private final PathImpl origin; - private final MapAttribute attribute; - - public MapEntryExpression( - CriteriaBuilderImpl criteriaBuilder, - Class> javaType, - PathImpl origin, - MapAttribute attribute) { - super( criteriaBuilder, javaType); - this.origin = origin; - this.attribute = attribute; - } - - public MapAttribute getAttribute() { - return attribute; - } - - public void registerParameters(ParameterRegistry registry) { - // none to register - } - - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { - // i don't think this is valid outside of select clause... - throw new IllegalStateException( "illegal reference to map entry outside of select clause." ); - } - - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { - return "entry(" + path( renderingContext ) + ")"; - } - - private String path(CriteriaQueryCompiler.RenderingContext renderingContext) { - return origin.getPathIdentifier() - + '.' - + ( (Renderable) getAttribute() ).renderProjection( renderingContext ); - } - } - - /** - * Disallow instantiation - */ - private MapKeyHelpers() { - } - } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributeJoinSupport.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributeJoinSupport.java new file mode 100644 index 0000000000..44519ed8ea --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributeJoinSupport.java @@ -0,0 +1,86 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import javax.persistence.criteria.JoinType; +import javax.persistence.criteria.PluralJoin; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.Type; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.PathSource; + +/** + * Support for defining joins to plural attributes (JPA requires typing based on + * the specific collection type so we cannot really implement all support in a + * single class) + * + * @author Steve Ebersole + */ +public abstract class PluralAttributeJoinSupport + extends AbstractJoinImpl + implements PluralJoin { + + public PluralAttributeJoinSupport( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource, + Attribute joinAttribute, + JoinType joinType) { + super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType ); + } + + @Override + public PluralAttribute getAttribute() { + return (PluralAttribute) super.getAttribute(); + } + + public PluralAttribute getModel() { + return getAttribute(); + } + + @Override + protected ManagedType locateManagedType() { + return isBasicCollection() + ? null + : (ManagedType) getAttribute().getElementType(); + } + + public boolean isBasicCollection() { + return Type.PersistenceType.BASIC.equals( getAttribute().getElementType().getPersistenceType() ); + } + + @Override + protected boolean canBeDereferenced() { + return !isBasicCollection(); + } + + @Override + protected boolean canBeJoinSource() { + return !isBasicCollection(); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributePath.java similarity index 53% rename from entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java rename to entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributePath.java index 96e828bbb9..0cd2a8e928 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributePath.java @@ -1,10 +1,10 @@ /* * Hibernate, Relational Persistence for Idiomatic Java * - * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by - * third-party contributors as indicated by either @author tags or express - * copyright attribution statements applied by the authors. All - * third-party contributions are distributed under license by Red Hat Inc. + * Copyright (c) 2010, Red Hat Inc. 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 Inc. * * 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 @@ -21,33 +21,35 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.ejb.criteria.expression; +package org.hibernate.ejb.criteria.path; import java.io.Serializable; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Bindable; import javax.persistence.metamodel.PluralAttribute; -import org.hibernate.ejb.criteria.ParameterRegistry; + import org.hibernate.ejb.criteria.CriteriaBuilderImpl; -import org.hibernate.ejb.criteria.PathImpl; -import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.PathSource; import org.hibernate.engine.SessionFactoryImplementor; import org.hibernate.persister.collection.CollectionPersister; /** - * TODO : javadoc + * Models a path for a {@link PluralAttribute} generally obtained from a + * {@link javax.persistence.criteria.Path#get} call * * @author Steve Ebersole */ -public class CollectionExpression extends ExpressionImpl implements Serializable { - private final PathImpl origin; +public class PluralAttributePath extends AbstractPathImpl implements Serializable { + private final PluralAttribute attribute; private final CollectionPersister persister; - private final PluralAttribute attribute; - public CollectionExpression( + public PluralAttributePath( CriteriaBuilderImpl criteriaBuilder, - Class javaType, - PathImpl origin, - PluralAttribute attribute) { - this( criteriaBuilder, javaType, resolvePersister( criteriaBuilder, attribute ), origin, attribute ); + PathSource source, + PluralAttribute attribute) { + super( criteriaBuilder, attribute.getJavaType(), source ); + this.attribute = attribute; + this.persister = resolvePersister( criteriaBuilder, attribute ); } private static CollectionPersister resolvePersister(CriteriaBuilderImpl criteriaBuilder, PluralAttribute attribute) { @@ -61,35 +63,32 @@ public class CollectionExpression extends ExpressionImpl implements Serial '.' + attribute.getName(); } - public CollectionExpression( - CriteriaBuilderImpl criteriaBuilder, - Class javaType, - CollectionPersister persister, - PathImpl origin, - PluralAttribute attribute) { - super( criteriaBuilder, javaType ); - this.origin = origin; - this.persister = persister; - this.attribute = attribute; - } - - public PluralAttribute getAttribute() { + public PluralAttribute getAttribute() { return attribute; } + @SuppressWarnings({ "UnusedDeclaration" }) public CollectionPersister getPersister() { return persister; } - public void registerParameters(ParameterRegistry registry) { - // none to register + @Override + protected boolean canBeDereferenced() { + // cannot be dereferenced + return false; } - public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { - return origin.getPathIdentifier() + '.' + getAttribute().getName(); + @Override + protected Attribute locateAttributeInternal(String attributeName) { + throw new IllegalArgumentException( "Plural attribute paths cannot be further dereferenced" ); } - public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { - return render( renderingContext ); + public Bindable getModel() { + // the issue here is the parameterized type; X is the collection + // type (Map, Set, etc) while the "bindable" for a collection is the + // elements. + // + // TODO : throw exception instead? + return null; } } diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java new file mode 100644 index 0000000000..3e64a4e316 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java @@ -0,0 +1,93 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import java.io.Serializable; +import javax.persistence.criteria.Root; +import javax.persistence.metamodel.EntityType; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaQueryCompiler; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class RootImpl extends AbstractFromImpl implements Root, Serializable { + private final EntityType entityType; + + public RootImpl( + CriteriaBuilderImpl criteriaBuilder, + EntityType entityType) { + super( criteriaBuilder, entityType.getJavaType() ); + this.entityType = entityType; + } + + public EntityType getEntityType() { + return entityType; + } + + public EntityType getModel() { + return getEntityType(); + } + + @Override + protected FromImplementor createCorrelationDelegate() { + return new RootImpl( queryBuilder(), getEntityType() ); + } + + @Override + public RootImpl correlateTo(CriteriaSubqueryImpl subquery) { + return (RootImpl) super.correlateTo( subquery ); + } + + @Override + protected boolean canBeJoinSource() { + return true; + } + + public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) { + prepareAlias( renderingContext ); + return getModel().getName() + " as " + getAlias(); + } + + @Override + public String getPathIdentifier() { + return getAlias(); + } + + @Override + public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { + prepareAlias( renderingContext ); + return getAlias(); + } + + @Override + public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { + return render( renderingContext ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java new file mode 100644 index 0000000000..6360b0fa4c --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java @@ -0,0 +1,82 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import java.io.Serializable; +import java.util.Set; + +import javax.persistence.criteria.JoinType; +import javax.persistence.metamodel.SetAttribute; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.PathImplementor; +import org.hibernate.ejb.criteria.PathSource; +import org.hibernate.ejb.criteria.SetJoinImplementor; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class SetAttributeJoin + extends PluralAttributeJoinSupport,E> + implements SetJoinImplementor, Serializable { + + public SetAttributeJoin( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource, + SetAttribute joinAttribute, + JoinType joinType) { + super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType ); + } + + @Override + public SetAttribute getAttribute() { + return (SetAttribute) super.getAttribute(); + } + + @Override + public SetAttribute getModel() { + return getAttribute(); + } + + @Override + public final SetAttributeJoin correlateTo(CriteriaSubqueryImpl subquery) { + return (SetAttributeJoin) super.correlateTo( subquery ); + } + + @Override + protected FromImplementor createCorrelationDelegate() { + return new SetAttributeJoin( + queryBuilder(), + getJavaType(), + (PathImplementor) getParentPath(), + getAttribute(), + getJoinType() + ); + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java new file mode 100644 index 0000000000..1380fb0da9 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java @@ -0,0 +1,88 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import javax.persistence.criteria.JoinType; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.SingularAttribute; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.CriteriaSubqueryImpl; +import org.hibernate.ejb.criteria.FromImplementor; +import org.hibernate.ejb.criteria.PathSource; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class SingularAttributeJoin extends AbstractJoinImpl { + private final Bindable model; + + @SuppressWarnings({ "unchecked" }) + public SingularAttributeJoin( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource, + SingularAttribute joinAttribute, + JoinType joinType) { + super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType ); + this.model = (Bindable) ( + Attribute.PersistentAttributeType.EMBEDDED == joinAttribute.getPersistentAttributeType() + ? joinAttribute + : criteriaBuilder.getEntityManagerFactory().getMetamodel().managedType( javaType ) + ); + } + + @Override + public SingularAttribute getAttribute() { + return (SingularAttribute) super.getAttribute(); + } + + @Override + public SingularAttributeJoin correlateTo(CriteriaSubqueryImpl subquery) { + return (SingularAttributeJoin) super.correlateTo( subquery ); + } + + @Override + protected FromImplementor createCorrelationDelegate() { + return new SingularAttributeJoin( + queryBuilder(), + getJavaType(), + getPathSource(), + getAttribute(), + getJoinType() + ); + } + + @Override + protected boolean canBeJoinSource() { + return true; + } + + public Bindable getModel() { + return model; + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java new file mode 100644 index 0000000000..38aeedb5e5 --- /dev/null +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java @@ -0,0 +1,105 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.path; + +import java.io.Serializable; +import javax.persistence.metamodel.Attribute; +import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.EmbeddableType; +import javax.persistence.metamodel.IdentifiableType; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.SingularAttribute; + +import org.hibernate.ejb.criteria.CriteriaBuilderImpl; +import org.hibernate.ejb.criteria.PathSource; + +/** + * Models a path for a {@link SingularAttribute} generally obtained from a + * {@link javax.persistence.criteria.Path#get(SingularAttribute)} call + * + * @author Steve Ebersole + */ +public class SingularAttributePath extends AbstractPathImpl implements Serializable { + private final SingularAttribute attribute; + private final ManagedType managedType; + + @SuppressWarnings({ "unchecked" }) + public SingularAttributePath( + CriteriaBuilderImpl criteriaBuilder, + Class javaType, + PathSource pathSource, + SingularAttribute attribute) { + super( criteriaBuilder, javaType, pathSource ); + this.attribute = attribute; + this.managedType = resolveManagedType( attribute ); + } + + private ManagedType resolveManagedType(SingularAttribute attribute) { + if ( Attribute.PersistentAttributeType.BASIC == attribute.getPersistentAttributeType() ) { + return null; + } + else if ( Attribute.PersistentAttributeType.EMBEDDED == attribute.getPersistentAttributeType() ) { + return (EmbeddableType) attribute.getType(); + } + else { + return (IdentifiableType) attribute.getType(); +// return criteriaBuilder.getEntityManagerFactory() +// .getMetamodel() +// .managedType( javaType ); + } + } + + /** + * {@inheritDoc} + */ + public SingularAttribute getAttribute() { + return attribute; + } + + /** + * {@inheritDoc} + */ + public Bindable getModel() { + return getAttribute(); + } + + /** + * {@inheritDoc} + */ + @Override + protected boolean canBeDereferenced() { + return managedType != null; + } + + @Override + protected Attribute locateAttributeInternal(String attributeName) { + final Attribute attribute = managedType.getAttribute( attributeName ); + // ManagedType.getAttribute should throw exception rather than return + // null, but just to be safe... + if ( attribute == null ) { + throw new IllegalArgumentException( "Could not resolve attribute named " + attributeName ); + } + return attribute; + } +} diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java index 2c56b0aaf8..a0842ff782 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java @@ -75,7 +75,7 @@ public class BooleanAssertionPredicate * {@inheritDoc} */ public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { - final String operator = isNegated() ? " = " : " <> "; + final String operator = isNegated() ? " <> " : " = "; final String assertionLiteral = assertedValue ? "true" : "false"; return ( (Renderable) expression ).render( renderingContext ) diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java index 344ae61f6f..c3e26584b7 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java @@ -28,8 +28,8 @@ import java.util.Collection; import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; import org.hibernate.ejb.criteria.CriteriaQueryCompiler; -import org.hibernate.ejb.criteria.expression.CollectionExpression; import org.hibernate.ejb.criteria.expression.UnaryOperatorExpression; +import org.hibernate.ejb.criteria.path.PluralAttributePath; /** * Models an IS [NOT] EMPTY restriction @@ -40,17 +40,17 @@ public class IsEmptyPredicate extends AbstractSimplePredicate implements UnaryOperatorExpression, Serializable { - private final CollectionExpression collectionExpression; + private final PluralAttributePath collectionPath; public IsEmptyPredicate( CriteriaBuilderImpl criteriaBuilder, - CollectionExpression collectionExpression) { + PluralAttributePath collectionPath) { super( criteriaBuilder ); - this.collectionExpression = collectionExpression; + this.collectionPath = collectionPath; } - public CollectionExpression getOperand() { - return collectionExpression; + public PluralAttributePath getOperand() { + return collectionPath; } public void registerParameters(ParameterRegistry registry) { diff --git a/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java b/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java index 35d6770d56..95734f9985 100644 --- a/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java +++ b/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java @@ -30,8 +30,8 @@ import org.hibernate.ejb.criteria.ParameterRegistry; import org.hibernate.ejb.criteria.CriteriaBuilderImpl; import org.hibernate.ejb.criteria.CriteriaQueryCompiler; import org.hibernate.ejb.criteria.Renderable; -import org.hibernate.ejb.criteria.expression.CollectionExpression; import org.hibernate.ejb.criteria.expression.LiteralExpression; +import org.hibernate.ejb.criteria.path.PluralAttributePath; /** * Models an [NOT] MEMBER OF restriction @@ -43,30 +43,30 @@ public class MemberOfPredicate> implements Serializable { private final Expression elementExpression; - private final CollectionExpression collectionExpression; + private final PluralAttributePath collectionPath; public MemberOfPredicate( CriteriaBuilderImpl criteriaBuilder, Expression elementExpression, - CollectionExpression collectionExpression) { + PluralAttributePath collectionPath) { super( criteriaBuilder ); this.elementExpression = elementExpression; - this.collectionExpression = collectionExpression; + this.collectionPath = collectionPath; } public MemberOfPredicate( CriteriaBuilderImpl criteriaBuilder, E element, - CollectionExpression collectionExpression) { + PluralAttributePath collectionPath) { this( criteriaBuilder, new LiteralExpression( criteriaBuilder, element ), - collectionExpression + collectionPath ); } - public CollectionExpression getCollectionExpression() { - return collectionExpression; + public PluralAttributePath getCollectionPath() { + return collectionPath; } public Expression getElementExpression() { @@ -74,14 +74,14 @@ public class MemberOfPredicate> } public void registerParameters(ParameterRegistry registry) { - Helper.possibleParameter( getCollectionExpression(), registry ); + Helper.possibleParameter( getCollectionPath(), registry ); Helper.possibleParameter( getElementExpression(), registry ); } public String render(CriteriaQueryCompiler.RenderingContext renderingContext) { return ( (Renderable) elementExpression ).render( renderingContext ) + ( isNegated() ? " not" : "" ) + " member of " - + collectionExpression.render( renderingContext ); + + getCollectionPath().render( renderingContext ); } public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) { diff --git a/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/ImplicitJoinTest.java b/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/ImplicitJoinTest.java new file mode 100644 index 0000000000..dfd00956a7 --- /dev/null +++ b/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/ImplicitJoinTest.java @@ -0,0 +1,62 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.criteria.paths; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Root; + +import org.hibernate.ejb.metamodel.AbstractMetamodelSpecificTest; +import org.hibernate.ejb.metamodel.LineItem; +import org.hibernate.ejb.metamodel.LineItem_; +import org.hibernate.ejb.metamodel.Order; +import org.hibernate.ejb.metamodel.Order_; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class ImplicitJoinTest extends AbstractMetamodelSpecificTest { + + public void testImplicitJoinFromExplicitCollectionJoin() { + EntityManager em = getOrCreateEntityManager(); + em.getTransaction().begin(); + + CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); + CriteriaQuery criteria = criteriaBuilder.createQuery( Order.class ); + Root orderRoot = criteria.from( Order.class ); + Join lineItemsJoin = orderRoot.join( Order_.lineItems ); + criteria.where( criteriaBuilder.lt( lineItemsJoin.get( LineItem_.quantity ), 2 ) ); + criteria.select( orderRoot ).distinct( true ); + TypedQuery query = em.createQuery( criteria ); + query.getResultList(); + + em.getTransaction().commit(); + em.close(); + } +} diff --git a/entitymanager/src/test/java/org/hibernate/ejb/metamodel/AbstractMetamodelSpecificTest.java b/entitymanager/src/test/java/org/hibernate/ejb/metamodel/AbstractMetamodelSpecificTest.java new file mode 100644 index 0000000000..a7b30baffe --- /dev/null +++ b/entitymanager/src/test/java/org/hibernate/ejb/metamodel/AbstractMetamodelSpecificTest.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat Inc. 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 Inc. + * + * 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.ejb.metamodel; + +import org.hibernate.ejb.test.TestCase; + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public abstract class AbstractMetamodelSpecificTest extends TestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { + Address.class, Alias.class, Country.class, CreditCard.class, Customer.class, + Info.class, LineItem.class, Order.class, Phone.class, Product.class, + ShelfLife.class, Spouse.class + }; + } +}