EJB-447 : Implement JPA 2.0 criteria apis

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17227 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-08-04 18:01:45 +00:00
parent 9fc25c8c8a
commit 152dc5abf9
27 changed files with 1584 additions and 69 deletions

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.Expression;
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<O,C,E> extends JoinImpl<O,E> implements PluralJoin<O,C,E> {
public AbstractBasicPluralJoin(
QueryBuilderImpl queryBuilder,
Class<E> javaType,
PathImpl<O> lhs,
PluralAttribute<? super O, ?, ?> joinProperty,
JoinType joinType) {
super(queryBuilder, javaType, lhs, joinProperty, joinType);
}
@Override
public PluralAttribute<? super O, C, E> getModel() {
return ( PluralAttribute<? super O, C, E> ) super.getAttribute();
}
@Override
public Expression<Class<? extends E>> type(){
throw new BasicPathUsageException( "type() is not applicable to primitive paths.", getAttribute() );
}
@Override
public <Y> Path<Y> get(SingularAttribute<? super E, Y> attribute){
throw illegalDereference();
}
private BasicPathUsageException illegalDereference() {
return new BasicPathUsageException( "Basic collection elements cannot be de-referenced", getAttribute() );
}
@Override
public <Y, C extends java.util.Collection<Y>> Expression<C> get(PluralAttribute<E, C, Y> collection){
throw illegalDereference();
}
@Override
public <L, W, M extends java.util.Map<L, W>> Expression<M> get(MapAttribute<E, L, W> map){
throw illegalDereference();
}
@Override
public <Y> Path<Y> get(String attName) {
throw illegalDereference();
}
@Override
public <Y> Join<E, Y> join(SingularAttribute<? super E, Y> attribute, JoinType jt) {
throw illegalJoin();
}
private BasicPathUsageException illegalJoin() {
return new BasicPathUsageException( "Basic collection cannot be source of a join", getAttribute() );
}
@Override
public <Y> CollectionJoin<E, Y> join(CollectionAttribute<? super E, Y> collection, JoinType jt) {
throw illegalJoin();
}
@Override
public <Y> SetJoin<E, Y> join(javax.persistence.metamodel.SetAttribute<? super E, Y> set, JoinType jt) {
throw illegalJoin();
}
@Override
public <Y> ListJoin<E, Y> join(ListAttribute<? super E, Y> list, JoinType jt) {
throw illegalJoin();
}
@Override
public <L, W> MapJoin<E, L, W> join(MapAttribute<? super E, L, W> map, JoinType jt) {
throw illegalJoin();
}
@Override
public <Y> Join<E, Y> join(String attributeName, JoinType jt) {
throw illegalJoin();
}
@Override
public <Y> CollectionJoin<E, Y> joinCollection(String attributeName, JoinType jt) {
throw illegalJoin();
}
@Override
public <Y> ListJoin<E, Y> joinList(String attributeName, JoinType jt) {
throw illegalJoin();
}
@Override
public <L, W> MapJoin<E, L, W> joinMap(String attributeName, JoinType jt) {
throw illegalJoin();
}
@Override
public <Y> SetJoin<E, Y> joinSet(String attributeName, JoinType jt) {
throw illegalJoin();
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.JoinType;
import javax.persistence.metamodel.CollectionAttribute;
/**
* 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<O,E>
extends AbstractBasicPluralJoin<O,java.util.Collection<E>,E>
implements CollectionJoin<O,E> {
public BasicCollectionJoinImpl(
QueryBuilderImpl queryBuilder,
Class<E> javaType,
PathImpl<O> lhs,
CollectionAttribute<? super O, E> joinProperty,
JoinType joinType) {
super(queryBuilder, javaType, lhs, joinProperty, joinType);
}
@Override
public CollectionAttribute<? super O, E> getModel() {
return (CollectionAttribute<? super O, E>) super.getAttribute();
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ListJoin;
import javax.persistence.metamodel.ListAttribute;
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.
*
* @author Steve Ebersole
*/
public class BasicListJoinImpl<O,E>
extends AbstractBasicPluralJoin<O,java.util.List<E>,E>
implements ListJoin<O,E> {
public BasicListJoinImpl(
QueryBuilderImpl queryBuilder,
Class<E> javaType,
PathImpl<O> lhs,
ListAttribute<? super O, ?> joinProperty,
JoinType joinType) {
super(queryBuilder, javaType, lhs, joinProperty, joinType);
}
@Override
public ListAttribute<? super O, E> getAttribute() {
return (ListAttribute<? super O, E>) super.getAttribute();
}
@Override
public ListAttribute<? super O, E> getModel() {
return getAttribute();
}
public Expression<Integer> index() {
return new ListIndexExpression( queryBuilder(), getAttribute() );
}
}

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
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.MapJoin;
import javax.persistence.criteria.Path;
import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.Type.PersistenceType;
/**
* Represents a join to a persistent collection, defined as type {@link java.util.Map}, whose elements
* are associations.
*
* @param <O> The map owner
* @param <K> The map key
* @param <V> The map value
*
* @author Steve Ebersole
*/
public class BasicMapJoinImpl<O,K,V>
extends AbstractBasicPluralJoin<O,java.util.Map<K,V>,V>
implements MapJoin<O,K,V> {
public BasicMapJoinImpl(
QueryBuilderImpl queryBuilder,
Class<V> javaType,
PathImpl<O> lhs,
MapAttribute<? super O, K, V> joinProperty,
JoinType joinType) {
super( queryBuilder, javaType, lhs, joinProperty, joinType );
}
@Override
public MapAttribute<? super O, K, V> getAttribute() {
return (MapAttribute<? super O, K, V>) super.getAttribute();
}
@Override
public MapAttribute<? super O, K, V> getModel() {
return getAttribute();
}
/**
* {@inheritDoc}
*/
public Join<Map<K, V>, K> joinKey() {
return joinKey( DEFAULT_JOIN_TYPE );
}
/**
* {@inheritDoc}
*/
public Join<Map<K, V>, 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<K,V> source = new MapKeyHelpers.MapPath<K,V>(
queryBuilder(),
getAttribute().getJavaType(),
this,
getAttribute(),
getParentPath().getModel()
);
final MapKeyHelpers.MapKeyAttribute attribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() );
final Join<Map<K, V>, K> join = new MapKeyHelpers.MapKeyJoin<K,V>(
queryBuilder(),
source,
attribute,
jt
);
return join;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked" })
public Path<K> key() {
final MapKeyHelpers.MapPath<K,V> source = new MapKeyHelpers.MapPath<K,V>(
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<V> value() {
// API docs explicitly say value() should simply return this;
return this;
}
/**
* {@inheritDoc}
*/
public Expression<Entry<K, V>> entry() {
// TODO : ???
throw new UnsupportedOperationException("Not supported yet.");
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.metamodel.Attribute;
/**
* Represents an incorrect usage of a basic path. Generally this means an attempt to
* de-reference a basic attribute path.
*
* @author Steve Ebersole
*/
public class BasicPathUsageException extends RuntimeException {
private final Attribute<?,?> attribute;
/**
* Construct the usage exception.
*
* @param message An error message describing the incorrect usage.
* @param attribute The basic attribute involved.
*/
public BasicPathUsageException(String message, Attribute<?,?> attribute) {
super( message );
this.attribute = attribute;
}
/**
* Construct the usage exception.
*
* @param message An error message describing the incorrect usage.
* @param cause An underlying cause.
* @param attribute The basic attribute involved.
*/
public BasicPathUsageException(String message, Throwable cause, Attribute<?,?> attribute) {
super( message, cause );
this.attribute = attribute;
}
public Attribute<?,?> getAttribute() {
return attribute;
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.SetJoin;
import javax.persistence.metamodel.SetAttribute;
/**
* 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<O,E>
extends AbstractBasicPluralJoin<O,java.util.Set<E>,E>
implements SetJoin<O,E> {
public BasicSetJoinImpl(
QueryBuilderImpl queryBuilder,
Class<E> javaType,
PathImpl<O> lhs,
SetAttribute<? super O, ?> joinProperty,
JoinType joinType) {
super( queryBuilder, javaType, lhs, joinProperty, joinType );
}
@Override
public SetAttribute<? super O, E> getModel() {
return (SetAttribute<? super O, E>) super.getAttribute();
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.JoinType;
import javax.persistence.metamodel.CollectionAttribute;
/**
* Represents a join to a persistent collection, defined as type {@link java.util.Collection}, whose elements
* are associations.
*
* @author Steve Ebersole
*/
public class CollectionJoinImpl<O,E> extends JoinImpl<O,E> implements CollectionJoin<O,E> {
public CollectionJoinImpl(
QueryBuilderImpl queryBuilder,
Class<E> javaType,
PathImpl<O> lhs,
CollectionAttribute<? super O, ?> joinProperty,
JoinType joinType) {
super(queryBuilder, javaType, lhs, joinProperty, joinType);
}
@Override
public CollectionAttribute<? super O, E> getModel() {
return (CollectionAttribute<? super O, E>) super.getAttribute();
}
}

View File

@ -34,14 +34,14 @@ import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery; import javax.persistence.criteria.Subquery;
import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.EntityType;
import org.hibernate.ejb.criteria.expression.AbstractExpression; import org.hibernate.ejb.criteria.expression.ExpressionImpl;
/** /**
* TODO : javadoc * TODO : javadoc
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CriteriaSubqueryImpl<T> extends AbstractExpression<T> implements Subquery<T> { public class CriteriaSubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
private final AbstractQuery<?> parent; private final AbstractQuery<?> parent;
private final QueryStructure<T> queryStructure; private final QueryStructure<T> queryStructure;

View File

@ -36,18 +36,19 @@ import javax.persistence.criteria.Path;
import javax.persistence.criteria.Expression; import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Fetch; import javax.persistence.criteria.Fetch;
import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.CollectionAttribute; import javax.persistence.metamodel.CollectionAttribute;
import javax.persistence.metamodel.SetAttribute; import javax.persistence.metamodel.SetAttribute;
import javax.persistence.metamodel.ListAttribute; import javax.persistence.metamodel.ListAttribute;
import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.Bindable;
import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.PluralAttribute.CollectionType;
import javax.persistence.metamodel.Type.PersistenceType; import javax.persistence.metamodel.Type.PersistenceType;
import org.hibernate.ejb.criteria.expression.AbstractExpression; import org.hibernate.ejb.criteria.expression.CollectionExpression;
import org.hibernate.ejb.criteria.expression.EntityTypeExpression; import org.hibernate.ejb.criteria.expression.EntityTypeExpression;
/** /**
@ -69,7 +70,7 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
* @param entityType * @param entityType
*/ */
protected FromImpl(QueryBuilderImpl queryBuilder, EntityType<X> entityType) { protected FromImpl(QueryBuilderImpl queryBuilder, EntityType<X> entityType) {
super( queryBuilder, entityType.getBindableJavaType(), null, entityType ); super( queryBuilder, entityType.getBindableJavaType(), null, null, entityType );
this.type = new EntityTypeExpression( queryBuilder, entityType.getBindableJavaType() ); this.type = new EntityTypeExpression( queryBuilder, entityType.getBindableJavaType() );
} }
@ -77,10 +78,10 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
QueryBuilderImpl queryBuilder, QueryBuilderImpl queryBuilder,
Class<X> javaType, Class<X> javaType,
PathImpl<Z> origin, PathImpl<Z> origin,
Bindable<X> model, Attribute<? super Z, ?> attribute,
Expression<Class<? extends X>> type) { ManagedType<X> model) {
super( queryBuilder, javaType, origin, model ); super( queryBuilder, javaType, origin, attribute, model );
this.type = type; this.type = new EntityTypeExpression( queryBuilder, model.getJavaType() );
} }
@Override @Override
@ -88,6 +89,18 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
return type; return type;
} }
/**
* 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<X,?> getAttribute(String name);
// JOINS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // JOINS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -111,6 +124,10 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
return joins; return joins;
} }
protected void addJoin(Join<X,?> join) {
getJoinsInternal().add( join );
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -123,9 +140,25 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
*/ */
public <Y> Join<X, Y> join(SingularAttribute<? super X, Y> attribute, JoinType jt) { public <Y> Join<X, Y> join(SingularAttribute<? super X, Y> attribute, JoinType jt) {
if ( PersistenceType.BASIC.equals( attribute.getType().getPersistenceType() ) ) { if ( PersistenceType.BASIC.equals( attribute.getType().getPersistenceType() ) ) {
throw new IllegalStateException( "Cannot join to basic type" ); throw new BasicPathUsageException( "Cannot join to attribute of basic type", attribute );
} }
throw new UnsupportedOperationException( "Not yet implemented!" );
// TODO : runtime check that the attribute in fact belongs to this From's model/bindable
if ( jt.equals( JoinType.RIGHT ) ) {
throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
}
final Class<Y> attributeType = attribute.getBindableJavaType();
final JoinImpl<X, Y> join = new JoinImpl<X, Y>(
queryBuilder(),
attributeType,
this,
attribute,
jt
);
joins.add( join );
return join;
} }
/** /**
@ -139,8 +172,36 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
* {@inheritDoc} * {@inheritDoc}
*/ */
public <Y> CollectionJoin<X, Y> join(CollectionAttribute<? super X, Y> collection, JoinType jt) { public <Y> CollectionJoin<X, Y> join(CollectionAttribute<? super X, Y> collection, JoinType jt) {
// TODO : implement if ( jt.equals( JoinType.RIGHT ) ) {
throw new UnsupportedOperationException( "Not yet implemented!" ); throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
}
final Class<Y> attributeType = collection.getBindableJavaType();
final CollectionJoin<X, Y> join;
if ( isBasicCollection( collection ) ) {
join = new BasicCollectionJoinImpl<X, Y>(
queryBuilder(),
attributeType,
this,
collection,
jt
);
}
else {
join = new CollectionJoinImpl<X, Y>(
queryBuilder(),
attributeType,
this,
collection,
jt
);
}
joins.add( join );
return join;
}
private boolean isBasicCollection(PluralAttribute collection) {
return PersistenceType.BASIC.equals( collection.getElementType().getPersistenceType() );
} }
/** /**
@ -154,8 +215,20 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
* {@inheritDoc} * {@inheritDoc}
*/ */
public <Y> SetJoin<X, Y> join(SetAttribute<? super X, Y> set, JoinType jt) { public <Y> SetJoin<X, Y> join(SetAttribute<? super X, Y> set, JoinType jt) {
// TODO : implement if ( jt.equals( JoinType.RIGHT ) ) {
throw new UnsupportedOperationException( "Not yet implemented!" ); throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
}
final Class<Y> attributeType = set.getBindableJavaType();
final SetJoin<X, Y> join;
if ( isBasicCollection( set ) ) {
join = new BasicSetJoinImpl<X, Y>( queryBuilder(), attributeType, this, set, jt );
}
else {
join = new SetJoinImpl<X, Y>( queryBuilder(), attributeType, this, set, jt );
}
joins.add( join );
return join;
} }
/** /**
@ -169,8 +242,20 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
* {@inheritDoc} * {@inheritDoc}
*/ */
public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list, JoinType jt) { public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list, JoinType jt) {
// TODO : implement if ( jt.equals( JoinType.RIGHT ) ) {
throw new UnsupportedOperationException( "Not yet implemented!" ); throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
}
final Class<Y> attributeType = list.getBindableJavaType();
final ListJoin<X, Y> join;
if ( isBasicCollection( list ) ) {
join = new BasicListJoinImpl<X, Y>( queryBuilder(), attributeType, this, list, jt );
}
else {
join = new ListJoinImpl<X, Y>( queryBuilder(), attributeType, this, list, jt );
}
joins.add( join );
return join;
} }
/** /**
@ -184,83 +269,152 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
* {@inheritDoc} * {@inheritDoc}
*/ */
public <K, V> MapJoin<X, K, V> join(MapAttribute<? super X, K, V> map, JoinType jt) { public <K, V> MapJoin<X, K, V> join(MapAttribute<? super X, K, V> map, JoinType jt) {
// TODO : implement if ( jt.equals( JoinType.RIGHT ) ) {
throw new UnsupportedOperationException( "Not yet implemented!" ); throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
}
final Class<V> attributeType = map.getBindableJavaType();
final MapJoin<X, K, V> join;
if ( isBasicCollection( map ) ) {
join = new BasicMapJoinImpl<X,K,V>( queryBuilder(), attributeType, this, map, jt );
}
else {
join = new MapJoinImpl<X,K,V>( queryBuilder(), attributeType, this, map, jt );
}
joins.add( join );
return join;
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> Join<X, Y> join(String attributeName) { public <Y> Join<X, Y> join(String attributeName) {
return join( attributeName, DEFAULT_JOIN_TYPE ); return join( attributeName, DEFAULT_JOIN_TYPE );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> Join<X, Y> join(String attributeName, JoinType jt) { public <Y> Join<X, Y> join(String attributeName, JoinType jt) {
// TODO : implement if ( jt.equals( JoinType.RIGHT ) ) {
throw new UnsupportedOperationException( "Not yet implemented!" ); throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
}
final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
if ( attribute.isCollection() ) {
final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
if ( CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) {
return join( (CollectionAttribute<X,Y>) attribute, jt );
}
else if ( CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
return join( (ListAttribute<X,Y>) attribute, jt );
}
else if ( CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
return join( (SetAttribute<X,Y>) attribute, jt );
}
else {
return join( (MapAttribute<X,?,Y>) attribute, jt );
}
}
else {
return join( (SingularAttribute)attribute, jt );
}
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> CollectionJoin<X, Y> joinCollection(String attributeName) { public <Y> CollectionJoin<X, Y> joinCollection(String attributeName) {
return joinCollection( attributeName, DEFAULT_JOIN_TYPE ); return joinCollection( attributeName, DEFAULT_JOIN_TYPE );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> CollectionJoin<X, Y> joinCollection(String attributeName, JoinType jt) { public <Y> CollectionJoin<X, Y> joinCollection(String attributeName, JoinType jt) {
// TODO : implement final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
throw new UnsupportedOperationException( "Not yet implemented!" ); if ( ! attribute.isCollection() ) {
throw new IllegalArgumentException( "Requested attribute was not a collection" );
}
final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
if ( ! CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) {
throw new IllegalArgumentException( "Requested attribute was not a collection" );
}
return join( (CollectionAttribute<X,Y>) attribute, jt );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> SetJoin<X, Y> joinSet(String attributeName) { public <Y> SetJoin<X, Y> joinSet(String attributeName) {
return joinSet( attributeName, DEFAULT_JOIN_TYPE ); return joinSet( attributeName, DEFAULT_JOIN_TYPE );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> SetJoin<X, Y> joinSet(String attributeName, JoinType jt) { public <Y> SetJoin<X, Y> joinSet(String attributeName, JoinType jt) {
// TODO : implement final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
throw new UnsupportedOperationException( "Not yet implemented!" ); if ( ! attribute.isCollection() ) {
throw new IllegalArgumentException( "Requested attribute was not a set" );
}
final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
if ( ! CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
throw new IllegalArgumentException( "Requested attribute was not a set" );
}
return join( (SetAttribute<X,Y>) attribute, jt );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> ListJoin<X, Y> joinList(String attributeName) { public <Y> ListJoin<X, Y> joinList(String attributeName) {
return joinList( attributeName, DEFAULT_JOIN_TYPE ); return joinList( attributeName, DEFAULT_JOIN_TYPE );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, Y> ListJoin<X, Y> joinList(String attributeName, JoinType jt) { public <Y> ListJoin<X, Y> joinList(String attributeName, JoinType jt) {
// TODO : implement final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
throw new UnsupportedOperationException( "Not yet implemented!" ); if ( ! attribute.isCollection() ) {
throw new IllegalArgumentException( "Requested attribute was not a list" );
}
final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
if ( ! CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
throw new IllegalArgumentException( "Requested attribute was not a list" );
}
return join( (ListAttribute<X,Y>) attribute, jt );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, K, V> MapJoin<X, K, V> joinMap(String attributeName) { public <K, V> MapJoin<X, K, V> joinMap(String attributeName) {
return joinMap( attributeName, DEFAULT_JOIN_TYPE ); return joinMap( attributeName, DEFAULT_JOIN_TYPE );
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public <X, K, V> MapJoin<X, K, V> joinMap(String attributeName, JoinType jt) { public <K, V> MapJoin<X, K, V> joinMap(String attributeName, JoinType jt) {
// TODO : implement final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
throw new UnsupportedOperationException( "Not yet implemented!" ); if ( ! attribute.isCollection() ) {
throw new IllegalArgumentException( "Requested attribute was not a map" );
}
final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
if ( ! CollectionType.MAP.equals( pluralAttribute.getCollectionType() ) ) {
throw new IllegalArgumentException( "Requested attribute was not a map" );
}
return join( (MapAttribute<X,K,V>) attribute, jt );
} }
@ -316,23 +470,46 @@ public abstract class FromImpl<Z,X> extends PathImpl<X> implements From<Z,X> {
// PATH HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PATH HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public <Y> Path<Y> get(SingularAttribute<? super X, Y> ySingularAttribute) { @Override
// TODO : implement public <Y> Path<Y> get(SingularAttribute<? super X, Y> attribute) {
throw new UnsupportedOperationException( "Not yet implemented!" ); if ( PersistentAttributeType.BASIC.equals( attribute.getPersistentAttributeType() ) ) {
return new PathImpl<Y>( queryBuilder(), attribute.getJavaType(), this, attribute, attribute.getBindableType() );
}
else {
return join( attribute );
}
} }
@Override
public <E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection) { public <E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection) {
// TODO : implement return new CollectionExpression<C>( queryBuilder(), collection.getJavaType(), collection );
throw new UnsupportedOperationException( "Not yet implemented!" );
} }
@Override
public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> map) { public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> map) {
// TODO : implement return ( Expression<M> ) new CollectionExpression<Map<K, V>>( queryBuilder(), map.getJavaType(), map );
throw new UnsupportedOperationException( "Not yet implemented!" );
} }
@Override
public <Y> Path<Y> get(String attributeName) { public <Y> Path<Y> get(String attributeName) {
// TODO : implement Attribute attribute = getAttribute( attributeName );
throw new UnsupportedOperationException( "Not yet implemented!" ); if ( attribute.isCollection() ) {
final PluralAttribute<X,?,Y> pluralAttribute = (PluralAttribute<X, ?, Y>) attribute;
if ( CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) {
return join( (CollectionAttribute<X,Y>) attribute );
}
else if ( CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
return join( (ListAttribute<X,Y>) attribute );
}
else if ( CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
return join( (SetAttribute<X,Y>) attribute );
}
else {
return join( (MapAttribute<X,?,Y>) attribute );
}
}
else {
return get( (SingularAttribute<X,Y>) attribute );
}
} }
} }

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.From;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.ManagedType;
/**
* Models a non-collection property join.
*
* @author Steve Ebersole
*/
public class JoinImpl<Z, X> extends FromImpl<Z, X> implements Join<Z, X> {
// 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<X> managedType;
private final JoinType joinType;
public JoinImpl(
QueryBuilderImpl queryBuilder,
Class<X> javaType,
PathImpl<Z> lhs,
Attribute<? super Z, ?> joinProperty,
JoinType joinType) {
super(
queryBuilder,
javaType,
lhs,
joinProperty,
(ManagedType<X>)queryBuilder.getEntityManagerFactory().getMetamodel().type( javaType )
);
this.managedType = (ManagedType<X>) getModel();
this.joinType = joinType;
}
/**
* {@inheritDoc}
*/
public From<?, Z> getParent() {
// AFAICT, only "froms" (specifically roots and joins) can be the parent of a join.
return ( From<?, Z> ) getParentPath();
}
@Override
public Attribute<? super Z, ?> getAttribute() {
return (Attribute<? super Z, ?>) super.getAttribute();
}
/**
* {@inheritDoc}
*/
public JoinType getJoinType() {
return joinType;
}
@Override
protected Attribute<X, ?> getAttribute(String name) {
return (Attribute<X, ?>) managedType.getAttribute( name );
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ListJoin;
import javax.persistence.metamodel.ListAttribute;
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<O,E> extends JoinImpl<O,E> implements ListJoin<O,E> {
public ListJoinImpl(
QueryBuilderImpl queryBuilder,
Class<E> javaType,
PathImpl<O> lhs,
ListAttribute<? super O, ?> joinProperty,
JoinType joinType) {
super( queryBuilder, javaType, lhs, joinProperty, joinType );
}
@Override
public ListAttribute<? super O, E> getAttribute() {
return (ListAttribute<? super O, E>) super.getAttribute();
}
@Override
public ListAttribute<? super O, E> getModel() {
return (ListAttribute<? super O, E>) getAttribute();
}
public Expression<Integer> index() {
return new ListIndexExpression( queryBuilder(), getAttribute() );
}
}

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
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.MapJoin;
import javax.persistence.criteria.Path;
import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.Type.PersistenceType;
/**
* Represents a join to a persistent collection, defined as type {@link java.util.Map}, whose elements
* are associations.
*
* @author Steve Ebersole
*/
public class MapJoinImpl<O,K,V>
extends JoinImpl<O,V>
implements MapJoin<O,K,V> {
public MapJoinImpl(
QueryBuilderImpl queryBuilder,
Class<V> javaType,
PathImpl<O> lhs,
MapAttribute<? super O, K, V> joinProperty,
JoinType joinType) {
super(queryBuilder, javaType, lhs, joinProperty, joinType);
}
@Override
public MapAttribute<? super O, K, V> getAttribute() {
return (MapAttribute<? super O, K, V>) super.getAttribute();
}
@Override
public MapAttribute<? super O, K, V> getModel() {
return getAttribute();
}
/**
* {@inheritDoc}
*/
public Join<Map<K, V>, K> joinKey() {
return joinKey( DEFAULT_JOIN_TYPE );
}
/**
* {@inheritDoc}
*/
public Join<Map<K, V>, 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<K,V> mapKeySource = new MapKeyHelpers.MapPath<K,V>(
queryBuilder(),
getAttribute().getJavaType(),
this,
getAttribute(),
getParentPath().getModel()
);
final MapKeyHelpers.MapKeyAttribute mapKeyAttribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() );
final Join<Map<K, V>, K> join = new MapKeyHelpers.MapKeyJoin<K,V>(
queryBuilder(),
mapKeySource,
mapKeyAttribute,
jt
);
return join;
}
/**
* {@inheritDoc}
*/
public Path<K> key() {
final MapKeyHelpers.MapPath<K,V> mapKeySource = new MapKeyHelpers.MapPath<K,V>(
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<V> value() {
return this;
}
/**
* {@inheritDoc}
*/
public Expression<Entry<K, V>> entry() {
// TODO : ???
throw new UnsupportedOperationException("Not supported yet.");
}
}

View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import java.lang.reflect.Member;
import java.util.Map;
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.BindableType;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.Type.PersistenceType;
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.
*
* @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 <K> The type of the map key
* @param <V> The type of the map value
*/
public static class MapKeyJoin<K,V> extends JoinImpl<Map<K, V>, K> implements Join<Map<K, V>, K> {
public MapKeyJoin(QueryBuilderImpl queryBuilder, MapPath<K,V> source, MapKeyAttribute<K> attribute, JoinType jt) {
super(
queryBuilder,
attribute.getJavaType(),
source,
attribute,
jt
);
}
}
/**
* Models a path to a map key.
*
* @param <K> The type of the map key.
*/
public static class MapKeyPath<K> extends PathImpl<K> implements Path<K> {
public MapKeyPath(
QueryBuilderImpl queryBuilder,
MapPath<K,?> source,
MapKeyAttribute<K> attribute) {
super( queryBuilder, attribute.getJavaType(), source, attribute, attribute.getType() );
}
}
/**
* Defines a {@link Path} resulting in a map attribute. This can then be used as the
* parent/origin/source for referencing the map-key.
*
* @param <K> The map key type
* @param <V> The map value type
*/
public static class MapPath<K,V> extends PathImpl<Map<K, V>> implements Path<Map<K, V>> {
private final MapJoin<?,K,V> mapJoin;
public MapPath(
QueryBuilderImpl queryBuilder,
Class<Map<K, V>> javaType,
MapJoin<?,K,V> mapJoin,
MapAttribute<?,K,V> attribute,
Object model) {
super(queryBuilder, javaType, null, attribute, model);
this.mapJoin = mapJoin;
}
@Override
public MapAttribute<?,K,V> getAttribute() {
return (MapAttribute<?,K,V>) super.getAttribute();
}
@Override
public PathImpl<?> getParentPath() {
return (PathImpl<?>) mapJoin;
}
}
/**
* Defines an {@link Attribute} modelling of a map-key.
* <p/>
* TODO : Ideally something like this needs to be part of the metamodel package
*
* @param <K> The type of the map key
*/
public static class MapKeyAttribute<K> implements SingularAttribute<Map<K,?>,K> {
private final MapAttribute<?,K,?> attribute;
private final CollectionPersister mapPersister;
private final Type mapKeyType;
private final javax.persistence.metamodel.Type<K> jpaType;
private final BindableType jpaBindableType;
private final Class<K> jpaBinableJavaType;
public MapKeyAttribute(QueryBuilderImpl queryBuilder, MapAttribute<?, K, ?> attribute) {
this.attribute = attribute;
this.jpaType = attribute.getKeyType();
this.jpaBinableJavaType = attribute.getKeyJavaType();
this.jpaBindableType = PersistenceType.ENTITY.equals( jpaType.getPersistenceType() )
? BindableType.ENTITY_TYPE
: BindableType.SINGULAR_ATTRIBUTE;
String guessedRoleName = determineRole( attribute );
SessionFactoryImplementor sfi = (SessionFactoryImplementor)
queryBuilder.getEntityManagerFactory().getSessionFactory();
mapPersister = sfi.getCollectionPersister( guessedRoleName );
if ( mapPersister == null ) {
throw new IllegalStateException( "Could not locate collection persister [" + guessedRoleName + "]" );
}
mapKeyType = mapPersister.getIndexType();
if ( mapKeyType == null ) {
throw new IllegalStateException( "Could not determine map-key type [" + guessedRoleName + "]" );
}
}
private String determineRole(MapAttribute<?,K,?> attribute) {
return attribute.getDeclaringType().getJavaType().getName() +
'.' + attribute.getName();
}
/**
* {@inheritDoc}
*/
public String getName() {
// TODO : ???
return "map-key";
}
/**
* {@inheritDoc}
*/
public PersistentAttributeType getPersistentAttributeType() {
if ( mapKeyType.isEntityType() ) {
return PersistentAttributeType.MANY_TO_ONE;
}
else if ( mapKeyType.isComponentType() ) {
return PersistentAttributeType.EMBEDDED;
}
else {
return PersistentAttributeType.BASIC;
}
}
/**
* {@inheritDoc}
*/
public ManagedType<Map<K, ?>> getDeclaringType() {
// TODO : ???
return null;
}
/**
* {@inheritDoc}
*/
public Class<K> getJavaType() {
return attribute.getKeyJavaType();
}
/**
* {@inheritDoc}
*/
public Member getJavaMember() {
// TODO : ???
return null;
}
/**
* {@inheritDoc}
*/
public boolean isAssociation() {
return mapKeyType.isEntityType();
}
/**
* {@inheritDoc}
*/
public boolean isCollection() {
return false;
}
public boolean isId() {
return false;
}
public boolean isVersion() {
return false;
}
public boolean isOptional() {
return false;
}
public javax.persistence.metamodel.Type<K> getType() {
return jpaType;
}
public BindableType getBindableType() {
return jpaBindableType;
}
public Class<K> getBindableJavaType() {
return jpaBinableJavaType;
}
}
/**
* Disallow instantiation
*/
private MapKeyHelpers() {
}
}

View File

@ -26,29 +26,41 @@ import java.util.Map;
import javax.persistence.criteria.Expression; import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Path; import javax.persistence.criteria.Path;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.Bindable; import javax.persistence.metamodel.Bindable;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.PluralAttribute;
import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.SingularAttribute;
import org.hibernate.ejb.criteria.expression.AbstractExpression; import org.hibernate.ejb.criteria.expression.ExpressionImpl;
/** /**
* A {@link Path} models an individual portion of a join expression. * A {@link Path} models an individual portion of a path expression.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class PathImpl<X> extends AbstractExpression<X> implements Path<X> { public class PathImpl<X> extends ExpressionImpl<X> implements Path<X> {
private final PathImpl<?> origin; private final PathImpl<?> origin;
private Bindable<X> model; private final Attribute<?,?> attribute;
private Object model;
/**
* Constructs a path.
*
* @param queryBuilder 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( protected PathImpl(
QueryBuilderImpl queryBuilder, QueryBuilderImpl queryBuilder,
Class<X> javaType, Class<X> javaType,
PathImpl<?> origin, PathImpl<?> origin,
Bindable<X> model) { Attribute<?,?> attribute,
Object model) {
super( queryBuilder, javaType ); super( queryBuilder, javaType );
this.origin = origin; this.origin = origin;
this.attribute = attribute;
this.model = model; this.model = model;
} }
@ -59,6 +71,10 @@ public class PathImpl<X> extends AbstractExpression<X> implements Path<X> {
return origin; return origin;
} }
public Attribute<?, ?> getAttribute() {
return attribute;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -66,7 +82,7 @@ public class PathImpl<X> extends AbstractExpression<X> implements Path<X> {
if ( model == null ) { if ( model == null ) {
throw new IllegalStateException( this + " represents a basic path and not a bindable" ); throw new IllegalStateException( this + " represents a basic path and not a bindable" );
} }
return model; return (Bindable<X>)model;
} }
/** /**
@ -76,7 +92,8 @@ public class PathImpl<X> extends AbstractExpression<X> implements Path<X> {
* an {@link IllegalStateException} * an {@link IllegalStateException}
*/ */
public Expression<Class<? extends X>> type() { public Expression<Class<? extends X>> type() {
throw new IllegalStateException( "type() is not applicable to a primitive path node." ); } throw new BasicPathUsageException( "type() is not applicable to primitive paths.", getAttribute() );
}
/** /**
* {@inheritDoc} * {@inheritDoc}
@ -85,7 +102,11 @@ public class PathImpl<X> extends AbstractExpression<X> implements Path<X> {
* an {@link IllegalStateException} * an {@link IllegalStateException}
*/ */
public <Y> Path<Y> get(SingularAttribute<? super X, Y> attribute) { public <Y> Path<Y> get(SingularAttribute<? super X, Y> attribute) {
throw new IllegalStateException( this + " is a primitive path node." ); throw illegalDereference();
}
private BasicPathUsageException illegalDereference() {
return new BasicPathUsageException( "Primitive path cannot be de-referenced", getAttribute() );
} }
/** /**
@ -95,7 +116,7 @@ public class PathImpl<X> extends AbstractExpression<X> implements Path<X> {
* an {@link IllegalStateException} * an {@link IllegalStateException}
*/ */
public <E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection) { public <E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection) {
throw new IllegalStateException( this + " is a primitive path node." ); throw illegalDereference();
} }
/** /**
@ -105,7 +126,7 @@ public class PathImpl<X> extends AbstractExpression<X> implements Path<X> {
* an {@link IllegalStateException} * an {@link IllegalStateException}
*/ */
public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> map) { public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> map) {
throw new IllegalStateException( this + " is a primitive path node." ); throw illegalDereference();
} }
/** /**
@ -115,7 +136,7 @@ public class PathImpl<X> extends AbstractExpression<X> implements Path<X> {
* an {@link IllegalStateException} * an {@link IllegalStateException}
*/ */
public <Y> Path<Y> get(String attributeName) { public <Y> Path<Y> get(String attributeName) {
throw new IllegalStateException( this + " is a primitive path node." ); throw illegalDereference();
} }
} }

View File

@ -73,7 +73,7 @@ public class QueryBuilderImpl implements QueryBuilder, Serializable {
* *
* @return The underlying {@link EntityManagerFactoryImpl} * @return The underlying {@link EntityManagerFactoryImpl}
*/ */
protected EntityManagerFactoryImpl getEntityManagerFactory() { public EntityManagerFactoryImpl getEntityManagerFactory() {
return entityManagerFactory; return entityManagerFactory;
} }

View File

@ -22,6 +22,7 @@
package org.hibernate.ejb.criteria; package org.hibernate.ejb.criteria;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.EntityType;
/** /**
@ -41,4 +42,9 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
return ( EntityType<X> ) super.getModel(); return ( EntityType<X> ) super.getModel();
} }
@Override
protected Attribute<X, ?> getAttribute(String name) {
return (Attribute<X, ?>) getModel().getAttribute( name );
}
} }

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.SetJoin;
import javax.persistence.metamodel.SetAttribute;
/**
* Represents a join to a persistent collection, defined as type {@link java.util.Set}, whose elements
* are associations.
*
* @author Steve Ebersole
*/
public class SetJoinImpl<O,E> extends JoinImpl<O,E> implements SetJoin<O,E> {
public SetJoinImpl(
QueryBuilderImpl queryBuilder,
Class<E> javaType,
PathImpl<O> lhs,
SetAttribute<? super O, ?> joinProperty,
JoinType joinType) {
super(queryBuilder, javaType, lhs, joinProperty, joinType);
}
@Override
public SetAttribute<? super O, E> getModel() {
return (SetAttribute<? super O, E>) super.getAttribute();
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria.expression;
import javax.persistence.metamodel.PluralAttribute;
import org.hibernate.ejb.criteria.QueryBuilderImpl;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.persister.collection.CollectionPersister;
/**
* TODO : javadoc
*
* @author Steve Ebersole
*/
public class CollectionExpression<C> extends ExpressionImpl<C> {
private final CollectionPersister persister;
private final PluralAttribute<?, C, ?> attribute;
public CollectionExpression(
QueryBuilderImpl queryBuilder,
Class<C> javaType,
PluralAttribute<?, C, ?> attribute) {
this( queryBuilder, javaType, resolvePersister( queryBuilder, attribute ), attribute );
}
private static CollectionPersister resolvePersister(QueryBuilderImpl queryBuilder, PluralAttribute attribute) {
SessionFactoryImplementor sfi = (SessionFactoryImplementor)
queryBuilder.getEntityManagerFactory().getSessionFactory();
return sfi.getCollectionPersister( resolveRole( attribute ) );
}
private static String resolveRole(PluralAttribute attribute) {
return attribute.getDeclaringType().getJavaType().getName() +
'.' + attribute.getName();
}
public CollectionExpression(
QueryBuilderImpl queryBuilder,
Class<C> javaType,
CollectionPersister persister,
PluralAttribute<?, C, ?> attribute) {
super(queryBuilder, javaType);
this.persister = persister;
this.attribute = attribute;
}
public PluralAttribute<?, C, ?> getAttribute() {
return attribute;
}
public CollectionPersister getPersister() {
return persister;
}
}

View File

@ -28,7 +28,7 @@ import org.hibernate.ejb.criteria.QueryBuilderImpl;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityTypeExpression<T> extends AbstractExpression<T> { public class EntityTypeExpression<T> extends ExpressionImpl<T> {
public EntityTypeExpression(QueryBuilderImpl queryBuilder, Class<T> javaType) { public EntityTypeExpression(QueryBuilderImpl queryBuilder, Class<T> javaType) {
super( queryBuilder, javaType ); super( queryBuilder, javaType );
} }

View File

@ -32,8 +32,8 @@ import org.hibernate.ejb.criteria.QueryBuilderImpl;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class AbstractExpression<T> extends SelectionImpl<T> implements Expression<T> { public class ExpressionImpl<T> extends SelectionImpl<T> implements Expression<T> {
protected AbstractExpression(QueryBuilderImpl queryBuilder, Class<T> javaType) { public ExpressionImpl(QueryBuilderImpl queryBuilder, Class<T> javaType) {
super( queryBuilder, javaType ); super( queryBuilder, javaType );
} }

View File

@ -32,7 +32,7 @@ import org.hibernate.ejb.criteria.QueryBuilderImpl;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class FunctionExpressionImpl<X> extends AbstractExpression<X> implements Expression<X> { public class FunctionExpressionImpl<X> extends ExpressionImpl<X> implements Expression<X> {
private final String functionName; private final String functionName;
private final List<Expression<?>> argumentExpressions; private final List<Expression<?>> argumentExpressions;

View File

@ -0,0 +1,23 @@
package org.hibernate.ejb.criteria.expression;
import javax.persistence.metamodel.ListAttribute;
import org.hibernate.ejb.criteria.QueryBuilderImpl;
/**
* An expression for referring to the index of a list.
*
* @author Steve Ebersole
*/
public class ListIndexExpression extends ExpressionImpl<Integer> {
private final ListAttribute<?,?> listAttribute;
public ListIndexExpression(QueryBuilderImpl queryBuilder, ListAttribute<?,?> listAttribute) {
super( queryBuilder, Integer.class );
this.listAttribute = listAttribute;
}
public ListAttribute<?,?> getListAttribute() {
return listAttribute;
}
}

View File

@ -28,7 +28,7 @@ import org.hibernate.ejb.criteria.QueryBuilderImpl;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class LiteralExpression<T> extends AbstractExpression<T> { public class LiteralExpression<T> extends ExpressionImpl<T> {
private final T literal; private final T literal;
public LiteralExpression( public LiteralExpression(

View File

@ -31,7 +31,7 @@ import org.hibernate.ejb.criteria.QueryBuilderImpl;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ParameterExpressionImpl<T> extends AbstractExpression<T> implements ParameterExpression<T> { public class ParameterExpressionImpl<T> extends ExpressionImpl<T> implements ParameterExpression<T> {
private final String name; private final String name;
private final Integer position; private final Integer position;

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria.expression.function;
import javax.persistence.criteria.Expression;
import org.hibernate.ejb.criteria.expression.FunctionExpressionImpl;
import org.hibernate.ejb.criteria.QueryBuilderImpl;
/**
* Implementation of a <tt>AVG</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Double} because thats what JPA states that the return
* from <tt>AVG</tt> should be.
*
* @author Steve Ebersole
*/
public class AverageAggregrateFunction extends FunctionExpressionImpl<Double> {
public AverageAggregrateFunction(
QueryBuilderImpl queryBuilder,
Expression<? extends Number> expression) {
super( queryBuilder, Double.class, "avg", expression );
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.criteria.expression.function;
import javax.persistence.criteria.Expression;
import org.hibernate.ejb.criteria.expression.FunctionExpressionImpl;
import org.hibernate.ejb.criteria.QueryBuilderImpl;
/**
* Implementation of a <tt>SUM</tt> function providing convenience in construction.
* <p/>
* Parameterized as {@link Number N extends Number} because thats what JPA states
* that the return from <tt>SUM</tt> should be.
*
* @author Steve Ebersole
*/
public class SumAggregateFunction<N extends Number> extends FunctionExpressionImpl<N> {
public SumAggregateFunction(
QueryBuilderImpl queryBuilder,
Expression<N> expression) {
super( queryBuilder, expression.getJavaType(), "sum", expression );
}
}

View File

@ -25,7 +25,7 @@ import java.util.List;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Selection; import javax.persistence.criteria.Selection;
import org.hibernate.ejb.criteria.expression.AbstractExpression; import org.hibernate.ejb.criteria.expression.ExpressionImpl;
import org.hibernate.ejb.criteria.QueryBuilderImpl; import org.hibernate.ejb.criteria.QueryBuilderImpl;
/** /**
@ -34,7 +34,7 @@ import org.hibernate.ejb.criteria.QueryBuilderImpl;
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractPredicateImpl extends AbstractExpression<Boolean> implements Predicate { public abstract class AbstractPredicateImpl extends ExpressionImpl<Boolean> implements Predicate {
private boolean negated; private boolean negated;
protected AbstractPredicateImpl(QueryBuilderImpl queryBuilder) { protected AbstractPredicateImpl(QueryBuilderImpl queryBuilder) {