[hibernate-commits] Hibernate SVN: r17227 - in core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria: expression and 2 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Aug 4 14:01:46 EDT 2009


Author: steve.ebersole at jboss.com
Date: 2009-08-04 14:01:45 -0400 (Tue, 04 Aug 2009)
New Revision: 17227

Added:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicPathUsageException.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ExpressionImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AverageAggregrateFunction.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SumAggregateFunction.java
Removed:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/AbstractExpression.java
Modified:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryBuilderImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/FunctionExpressionImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/AbstractPredicateImpl.java
Log:
EJB-447 : Implement JPA 2.0 criteria apis

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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();
+    }
+
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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();
+    }
+
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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() );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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.");
+	}
+
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicPathUsageException.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicPathUsageException.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicPathUsageException.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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;
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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();
+    }
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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();
+    }
+
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -34,14 +34,14 @@
 import javax.persistence.criteria.SetJoin;
 import javax.persistence.criteria.Subquery;
 import javax.persistence.metamodel.EntityType;
-import org.hibernate.ejb.criteria.expression.AbstractExpression;
+import org.hibernate.ejb.criteria.expression.ExpressionImpl;
 
 /**
  * TODO : javadoc
  *
  * @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 QueryStructure<T> queryStructure;
 

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -36,18 +36,19 @@
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Fetch;
 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.Bindable;
 import javax.persistence.metamodel.EntityType;
 import javax.persistence.metamodel.ManagedType;
 import javax.persistence.metamodel.PluralAttribute;
 
+import javax.persistence.metamodel.PluralAttribute.CollectionType;
 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;
 
 /**
@@ -69,7 +70,7 @@
 	 * @param 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() );
 	}
 
@@ -77,10 +78,10 @@
 			QueryBuilderImpl queryBuilder,
 			Class<X> javaType,
 			PathImpl<Z> origin,
-			Bindable<X> model,
-			Expression<Class<? extends X>> type) {
-		super( queryBuilder, javaType, origin, model );
-		this.type = type;
+			Attribute<? super Z, ?> attribute,
+			ManagedType<X> model) {
+		super( queryBuilder, javaType, origin, attribute, model );
+		this.type = new EntityTypeExpression( queryBuilder, model.getJavaType() );
 	}
 
 	@Override
@@ -88,7 +89,19 @@
 		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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 	/**
@@ -111,6 +124,10 @@
 		return joins;
 	}
 
+	protected void addJoin(Join<X,?> join) {
+		getJoinsInternal().add( join );
+	}
+
 	/**
 	 * {@inheritDoc}
 	 */
@@ -123,9 +140,25 @@
 	 */
 	public <Y> Join<X, Y> join(SingularAttribute<? super X, Y> attribute, JoinType jt) {
 		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,10 +172,38 @@
 	 * {@inheritDoc}
 	 */
 	public <Y> CollectionJoin<X, Y> join(CollectionAttribute<? super X, Y> collection, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			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() );
+	}
+
 	/**
 	 * {@inheritDoc}
 	 */
@@ -154,8 +215,20 @@
 	 * {@inheritDoc}
 	 */
 	public <Y> SetJoin<X, Y> join(SetAttribute<? super X, Y> set, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			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 @@
 	 * {@inheritDoc}
 	 */
 	public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			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 @@
 	 * {@inheritDoc}
 	 */
 	public <K, V> MapJoin<X, K, V> join(MapAttribute<? super X, K, V> map, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			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}
 	 */
-	public <X, Y> Join<X, Y> join(String attributeName) {
+	public <Y> Join<X, Y> join(String attributeName) {
 		return join( attributeName, DEFAULT_JOIN_TYPE );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
-	public <X, Y> Join<X, Y> join(String attributeName, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+	public <Y> Join<X, Y> join(String attributeName, JoinType jt) {
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			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}
 	 */
-	public <X, Y> CollectionJoin<X, Y> joinCollection(String attributeName) {
+	public <Y> CollectionJoin<X, Y> joinCollection(String attributeName) {
 		return joinCollection( attributeName, DEFAULT_JOIN_TYPE );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
-	public <X, Y> CollectionJoin<X, Y> joinCollection(String attributeName, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+	public <Y> CollectionJoin<X, Y> joinCollection(String attributeName, JoinType jt) {
+		final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
+		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}
 	 */
-	public <X, Y> SetJoin<X, Y> joinSet(String attributeName) {
+	public <Y> SetJoin<X, Y> joinSet(String attributeName) {
 		return joinSet( attributeName, DEFAULT_JOIN_TYPE );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
-	public <X, Y> SetJoin<X, Y> joinSet(String attributeName, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+	public <Y> SetJoin<X, Y> joinSet(String attributeName, JoinType jt) {
+		final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
+		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}
 	 */
-	public <X, Y> ListJoin<X, Y> joinList(String attributeName) {
+	public <Y> ListJoin<X, Y> joinList(String attributeName) {
 		return joinList( attributeName, DEFAULT_JOIN_TYPE );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
-	public <X, Y> ListJoin<X, Y> joinList(String attributeName, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+	public <Y> ListJoin<X, Y> joinList(String attributeName, JoinType jt) {	
+		final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
+		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}
 	 */
-	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 );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
-	public <X, K, V> MapJoin<X, K, V> joinMap(String attributeName, JoinType jt) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+	public <K, V> MapJoin<X, K, V> joinMap(String attributeName, JoinType jt) {
+		final Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
+		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 @@
 
 	// PATH HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-	public <Y> Path<Y> get(SingularAttribute<? super X, Y> ySingularAttribute) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+	@Override
+	public <Y> Path<Y> get(SingularAttribute<? super X, Y> attribute) {
+		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) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+		return new CollectionExpression<C>( queryBuilder(), collection.getJavaType(), collection );
 	}
 
+	@Override
 	public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> map) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+		return ( Expression<M> ) new CollectionExpression<Map<K, V>>( queryBuilder(), map.getJavaType(), map );
 	}
 
+	@Override
 	public <Y> Path<Y> get(String attributeName) {
-		// TODO : implement
-		throw new UnsupportedOperationException( "Not yet implemented!" );
+		Attribute attribute = getAttribute( attributeName );
+		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 );
+		}
 	}
 }

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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 );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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() );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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.");
+	}
+
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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() {
+	}
+
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -26,29 +26,41 @@
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Path;
 
+import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.Bindable;
-import javax.persistence.metamodel.EntityType;
 import javax.persistence.metamodel.MapAttribute;
 import javax.persistence.metamodel.PluralAttribute;
 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
  */
-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 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(
 			QueryBuilderImpl queryBuilder,
 			Class<X> javaType,
 			PathImpl<?> origin,
-			Bindable<X> model) {
+			Attribute<?,?> attribute,
+			Object model) {
         super( queryBuilder, javaType );
 		this.origin = origin;
+		this.attribute = attribute;
 		this.model = model;
 	}
 
@@ -59,6 +71,10 @@
         return origin;
     }
 
+	public Attribute<?, ?> getAttribute() {
+		return attribute;
+	}
+
 	/**
 	 * {@inheritDoc}
 	 */
@@ -66,7 +82,7 @@
         if ( model == null ) {
             throw new IllegalStateException( this + " represents a basic path and not a bindable" );
         }
-		return model;
+		return (Bindable<X>)model;
     }
 
 	/**
@@ -76,7 +92,8 @@
 	 * an {@link IllegalStateException}
 	 */
 	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}
@@ -85,9 +102,13 @@
 	 * an {@link IllegalStateException}
 	 */
 	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() );
+	}
+
 	/**
 	 * {@inheritDoc}
 	 * <p/>
@@ -95,7 +116,7 @@
 	 * an {@link IllegalStateException}
 	 */
 	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 @@
 	 * an {@link IllegalStateException}
 	 */
 	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 @@
 	 * an {@link IllegalStateException}
 	 */
 	public <Y> Path<Y> get(String attributeName) {
-		throw new IllegalStateException( this + " is a primitive path node." );
+		throw illegalDereference();
 	}
 
 }

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryBuilderImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryBuilderImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryBuilderImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -73,7 +73,7 @@
 	 *
 	 * @return The underlying {@link EntityManagerFactoryImpl}
 	 */
-	protected EntityManagerFactoryImpl getEntityManagerFactory() {
+	public  EntityManagerFactoryImpl getEntityManagerFactory() {
 		return entityManagerFactory;
 	}
 

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -22,6 +22,7 @@
 package org.hibernate.ejb.criteria;
 
 import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.EntityType;
 
 /**
@@ -41,4 +42,9 @@
         return ( EntityType<X> ) super.getModel();
     }
 
+	@Override
+	protected Attribute<X, ?> getAttribute(String name) {
+		return (Attribute<X, ?>) getModel().getAttribute( name );
+	}
+
 }

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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();
+	}
+
+}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/AbstractExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/AbstractExpression.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/AbstractExpression.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2009, Red Hat Middleware LLC or third-party contributors as
- * indicated by the @author tags or express copyright attribution
- * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria.expression;
-
-import java.util.Collection;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.Predicate;
-
-import org.hibernate.ejb.criteria.QueryBuilderImpl;
-
-/**
- * TODO : javadoc
- *
- * @author Steve Ebersole
- */
-public class AbstractExpression<T> extends SelectionImpl<T> implements Expression<T> {
-	protected AbstractExpression(QueryBuilderImpl queryBuilder, Class<T> javaType) {
-		super( queryBuilder, javaType );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <X> Expression<X> as(Class<X> type) {
-		// TODO-STEVE : implement - needs a cast expression
-		throw new UnsupportedOperationException( "Not yet implemented!" );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Predicate isNull() {
-		return queryBuilder().isNull( this );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Predicate isNotNull() {
-		return queryBuilder().isNotNull( this );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-    public Predicate in(Object... values) {
-		return queryBuilder().in( this, values );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Predicate in(Expression<?>... values) {
-		return queryBuilder().in( this, values );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Predicate in(Collection<?> values) {
-		return queryBuilder().in( this, values );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Predicate in(Expression<Collection<?>> values) {
-		return queryBuilder().in( this, values );
-	}
-}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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;
+	}
+
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/EntityTypeExpression.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -28,7 +28,7 @@
  *
  * @author Steve Ebersole
  */
-public class EntityTypeExpression<T> extends AbstractExpression<T> {
+public class EntityTypeExpression<T> extends ExpressionImpl<T> {
 	public EntityTypeExpression(QueryBuilderImpl queryBuilder, Class<T> javaType) {
 		super( queryBuilder, javaType );
 	}

Copied: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ExpressionImpl.java (from rev 17222, core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/AbstractExpression.java)
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ExpressionImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ExpressionImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -0,0 +1,89 @@
+/*
+ * 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 java.util.Collection;
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Predicate;
+
+import org.hibernate.ejb.criteria.QueryBuilderImpl;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class ExpressionImpl<T> extends SelectionImpl<T> implements Expression<T> {
+	public ExpressionImpl(QueryBuilderImpl queryBuilder, Class<T> javaType) {
+		super( queryBuilder, javaType );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <X> Expression<X> as(Class<X> type) {
+		// TODO-STEVE : implement - needs a cast expression
+		throw new UnsupportedOperationException( "Not yet implemented!" );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Predicate isNull() {
+		return queryBuilder().isNull( this );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Predicate isNotNull() {
+		return queryBuilder().isNotNull( this );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public Predicate in(Object... values) {
+		return queryBuilder().in( this, values );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Predicate in(Expression<?>... values) {
+		return queryBuilder().in( this, values );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Predicate in(Collection<?> values) {
+		return queryBuilder().in( this, values );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Predicate in(Expression<Collection<?>> values) {
+		return queryBuilder().in( this, values );
+	}
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/FunctionExpressionImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/FunctionExpressionImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/FunctionExpressionImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -32,7 +32,7 @@
  *
  * @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 List<Expression<?>> argumentExpressions;
 

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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;
+	}
+
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/LiteralExpression.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -28,7 +28,7 @@
  *
  * @author Steve Ebersole
  */
-public class LiteralExpression<T> extends AbstractExpression<T> {
+public class LiteralExpression<T> extends ExpressionImpl<T> {
 	private final T literal;
 
 	public LiteralExpression(

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ParameterExpressionImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -31,7 +31,7 @@
  *
  * @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 Integer position;
 

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AverageAggregrateFunction.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AverageAggregrateFunction.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/AverageAggregrateFunction.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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 );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SumAggregateFunction.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SumAggregateFunction.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/function/SumAggregateFunction.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -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 );
+	}
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/AbstractPredicateImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/AbstractPredicateImpl.java	2009-08-04 17:07:20 UTC (rev 17226)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/AbstractPredicateImpl.java	2009-08-04 18:01:45 UTC (rev 17227)
@@ -25,7 +25,7 @@
 import javax.persistence.criteria.Predicate;
 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;
 
 /**
@@ -34,7 +34,7 @@
  *
  * @author Steve Ebersole
  */
-public abstract class AbstractPredicateImpl extends AbstractExpression<Boolean> implements Predicate {
+public abstract class AbstractPredicateImpl extends ExpressionImpl<Boolean> implements Predicate {
 	private boolean negated;
 
 	protected AbstractPredicateImpl(QueryBuilderImpl queryBuilder) {



More information about the hibernate-commits mailing list