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

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Jan 7 12:58:38 EST 2010


Author: steve.ebersole at jboss.com
Date: 2010-01-07 12:58:37 -0500 (Thu, 07 Jan 2010)
New Revision: 18436

Added:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/IllegalDereferenceException.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributeJoinSupport.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributePath.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java
   core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/
   core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/ImplicitJoinTest.java
   core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/AbstractMetamodelSpecificTest.java
Removed:
   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/BasicSetJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementors.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/PathImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/TableExpressionMapper.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java
Modified:
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.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/SizeOfCollectionExpression.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java
   core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java
Log:
HHH-4756 - javax.persistence.criteria.Path#get should result in *delayed* join rendering


Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/AbstractBasicPluralJoin.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,184 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.CollectionJoin;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.Fetch;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.ListJoin;
-import javax.persistence.criteria.MapJoin;
-import javax.persistence.criteria.Path;
-import javax.persistence.criteria.PluralJoin;
-import javax.persistence.criteria.SetJoin;
-import javax.persistence.metamodel.CollectionAttribute;
-import javax.persistence.metamodel.ListAttribute;
-import javax.persistence.metamodel.MapAttribute;
-import javax.persistence.metamodel.PluralAttribute;
-import javax.persistence.metamodel.SingularAttribute;
-
-/**
- * Convenience base class for all basic collection joins.  Mainly we handle the fact that
- * this path cannot be further de-referenced.
- *
- * @author Steve Ebersole
- */
-public abstract class AbstractBasicPluralJoin<O,C,E>
-		extends JoinImpl<O,E>
-		implements PluralJoin<O,C,E>, Fetch<O,E>, Serializable {
-
-	public AbstractBasicPluralJoin(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<E> javaType,
-			PathImpl<O> lhs,
-			PluralAttribute<? super O, ?, ?> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, 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 <E,Y> Join<E, Y> join(String attributeName, JoinType jt) {
-        throw illegalJoin();
-    }
-
-    @Override
-    public <E,Y> CollectionJoin<E, Y> joinCollection(String attributeName, JoinType jt) {
-        throw illegalJoin();
-    }
-
-    @Override
-    public <E,Y> ListJoin<E, Y> joinList(String attributeName, JoinType jt) {
-        throw illegalJoin();
-    }
-
-    @Override
-    public <E, L, W> MapJoin<E, L, W> joinMap(String attributeName, JoinType jt) {
-        throw illegalJoin();
-    }
-
-    @Override
-    public <E,Y> SetJoin<E, Y> joinSet(String attributeName, JoinType jt) {
-        throw illegalJoin();
-    }
-
-	@Override
-	public <Y> Fetch<E, Y> fetch(SingularAttribute<? super E, Y> singularAttribute) {
-		throw illegalFetch();
-	}
-
-	private BasicPathUsageException illegalFetch() {
-		return new BasicPathUsageException( "Basic collection cannot be source of a fetch", getAttribute() );
-	}
-
-	@Override
-	public <Y> Fetch<E, Y> fetch(SingularAttribute<? super E, Y> attribute, JoinType jt) {
-		throw illegalFetch();
-	}
-
-	@Override
-	public <Y> Fetch<E, Y> fetch(PluralAttribute<? super E, ?, Y> pluralAttribute) {
-		throw illegalFetch();
-	}
-
-	@Override
-	public <Y> Fetch<E, Y> fetch(PluralAttribute<? super E, ?, Y> pluralAttribute, JoinType jt) {
-		throw illegalFetch();
-	}
-
-	@Override
-	public <X, Y> Fetch<X, Y> fetch(String attributeName) {
-		throw illegalFetch();
-	}
-
-	@Override
-	public <X, Y> Fetch<X, Y> fetch(String attributeName, JoinType jt) {
-		throw illegalFetch();
-	}
-
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicCollectionJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,90 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.CollectionAttribute;
-import org.hibernate.ejb.criteria.JoinImplementors.CollectionJoinImplementor;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.Collection}, whose elements
- * are basic type.
- *
- * @author Steve Ebersole
- */
-public class BasicCollectionJoinImpl<O,E>
-		extends AbstractBasicPluralJoin<O,java.util.Collection<E>,E>
-		implements JoinImplementors.CollectionJoinImplementor<O,E>, Serializable {
-
-	public BasicCollectionJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<E> javaType,
-			PathImpl<O> lhs,
-			CollectionAttribute<? super O, E> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, javaType, lhs, joinProperty, joinType);
-	}
-
-	@Override
-	public CollectionAttribute<? super O, E> getAttribute() {
-		return (CollectionAttribute<? super O, E>) super.getAttribute();
-	}
-
-	@Override
-	public CollectionAttribute<? super O, E> getModel() {
-        return getAttribute();
-    }
-
-	@Override
-	public CollectionJoinImplementor<O, E> correlateTo(CriteriaSubqueryImpl subquery) {
-		BasicCollectionJoinImpl<O,E> correlation = new BasicCollectionJoinImpl<O,E>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getModel(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	private From<O, E> correlationParent;
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return false;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, E> getCorrelationParent() {
-		return null;
-	}
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicListJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,96 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.ListAttribute;
-import org.hibernate.ejb.criteria.JoinImplementors.ListJoinImplementor;
-import org.hibernate.ejb.criteria.expression.ListIndexExpression;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.List}, whose elements
- * are basic type.
- *
- * @author Steve Ebersole
- */
-public class BasicListJoinImpl<O,E>
-		extends AbstractBasicPluralJoin<O,java.util.List<E>,E> 
-		implements JoinImplementors.ListJoinImplementor<O,E>, Serializable {
-
-	public BasicListJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<E> javaType,
-			PathImpl<O> lhs,
-			ListAttribute<? super O, ?> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, 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(), this, getAttribute() );
-	}
-
-	@Override
-	public ListJoinImplementor<O, E> correlateTo(CriteriaSubqueryImpl subquery) {
-		BasicListJoinImpl<O,E> correlation = new BasicListJoinImpl<O,E>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	private From<O, E> correlationParent;
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return getCorrelationParent() != null;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, E> getCorrelationParent() {
-		return correlationParent;
-	}
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicMapJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,171 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import java.util.Map;
-import java.util.Map.Entry;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.Path;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.MapAttribute;
-import javax.persistence.metamodel.Type.PersistenceType;
-import org.hibernate.ejb.criteria.JoinImplementors.MapJoinImplementor;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.Map}, whose elements
- * are associations.
- *
- * @param <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 JoinImplementors.MapJoinImplementor<O,K,V>, Serializable {
-
-
-	public BasicMapJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<V> javaType,
-			PathImpl<O> lhs,
-			MapAttribute<? super O, K, V> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, 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}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	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() );
-		return new MapKeyHelpers.MapKeyJoin<K,V>(
-				queryBuilder(),
-				source,
-				attribute,
-				jt
-		);
-	}
-
-
-	/**
-	 * {@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}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public Expression<Entry<K, V>> entry() {
-		return new MapKeyHelpers.MapEntryExpression( queryBuilder(), Map.Entry.class, this, getAttribute() );
-	}
-
-	private From<O, V> correlationParent;
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public MapJoinImplementor<O, K, V> correlateTo(CriteriaSubqueryImpl subquery) {
-		BasicMapJoinImpl<O,K,V> correlation = new BasicMapJoinImpl<O,K,V>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return getCorrelationParent() != null;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, V> getCorrelationParent() {
-		return correlationParent;
-	}
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/BasicSetJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,90 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.SetAttribute;
-import org.hibernate.ejb.criteria.JoinImplementors.SetJoinImplementor;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.Set}, whose elements
- * are basic type.
- *
- * @author Steve Ebersole
- */
-public class BasicSetJoinImpl<O,E>
-		extends AbstractBasicPluralJoin<O,java.util.Set<E>,E> 
-		implements JoinImplementors.SetJoinImplementor<O,E>, Serializable {
-
-	public BasicSetJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<E> javaType,
-			PathImpl<O> lhs,
-			SetAttribute<? super O, ?> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, javaType, lhs, joinProperty, joinType );
-	}
-
-	@Override
-	public SetAttribute<? super O, E> getAttribute() {
-		return (SetAttribute<? super O, E>) super.getAttribute();
-	}
-
-	@Override
-	public SetAttribute<? super O, E> getModel() {
-        return getAttribute();
-    }
-
-	@Override
-	public SetJoinImplementor<O, E> correlateTo(CriteriaSubqueryImpl subquery) {
-		BasicSetJoinImpl<O,E> correlation = new BasicSetJoinImpl<O,E>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	private From<O, E> correlationParent;
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return getCorrelationParent() != null;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, E> getCorrelationParent() {
-		return correlationParent;
-	}
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,99 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.CollectionAttribute;
-import javax.persistence.metamodel.ManagedType;
-
-import org.hibernate.ejb.criteria.JoinImplementors.CollectionJoinImplementor;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.Collection}, whose elements
- * are associations.
- *
- * @author Steve Ebersole
- */
-public class CollectionJoinImpl<O,E>
-		extends JoinImpl<O,E>
-		implements JoinImplementors.CollectionJoinImplementor<O,E>, Serializable {
-
-	public CollectionJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<E> javaType,
-			PathImpl<O> lhs,
-			CollectionAttribute<? super O, ?> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, javaType, lhs, joinProperty, joinType);
-	}
-
-	@Override
-	public CollectionAttribute<? super O, E> getAttribute() {
-		return (CollectionAttribute<? super O, E>) super.getAttribute();
-	}
-
-	@Override
-	public CollectionAttribute<? super O, E> getModel() {
-        return getAttribute();
-    }
-
-	@Override
-	protected ManagedType<E> getManagedType() {
-		return ( ManagedType<E> ) getAttribute().getElementType();
-	}
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public CollectionJoinImplementor<O, E> correlateTo(CriteriaSubqueryImpl subquery) {
-		CollectionJoinImpl<O,E> correlation = new CollectionJoinImpl<O,E>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	private From<O, E> correlationParent;
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return false;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, E> getCorrelationParent() {
-		return null;
-	}
-
-}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImplementor.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CollectionJoinImplementor.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,40 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+import javax.persistence.criteria.CollectionJoin;
+
+/**
+ * Specialization of {@link JoinImplementor} for {@link java.util.Collection} typed attribute joins
+ *
+ * @author Steve Ebersole
+ */
+public interface CollectionJoinImplementor<Z,X> extends JoinImplementor<Z,X>, CollectionJoin<Z,X> {
+	/**
+	 * {@inheritDoc}
+	 * <p/>
+	 * Refined return type
+	 */
+	public CollectionJoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaBuilderImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -45,7 +45,6 @@
 import org.hibernate.ejb.EntityManagerFactoryImpl;
 import org.hibernate.ejb.criteria.expression.BinaryArithmeticOperation;
 import org.hibernate.ejb.criteria.expression.CoalesceExpression;
-import org.hibernate.ejb.criteria.expression.CollectionExpression;
 import org.hibernate.ejb.criteria.expression.CompoundSelectionImpl;
 import org.hibernate.ejb.criteria.expression.ConcatExpression;
 import org.hibernate.ejb.criteria.expression.ParameterExpressionImpl;
@@ -70,6 +69,7 @@
 import org.hibernate.ejb.criteria.expression.function.SubstringFunction;
 import org.hibernate.ejb.criteria.expression.function.TrimFunction;
 import org.hibernate.ejb.criteria.expression.function.UpperFunction;
+import org.hibernate.ejb.criteria.path.PluralAttributePath;
 import org.hibernate.ejb.criteria.predicate.BooleanAssertionPredicate;
 import org.hibernate.ejb.criteria.predicate.BooleanExpressionPredicate;
 import org.hibernate.ejb.criteria.predicate.NullnessPredicate;
@@ -1275,8 +1275,8 @@
 		if ( LiteralExpression.class.isInstance(exp) ) {
 			return size( ( (LiteralExpression<C>) exp ).getLiteral() );
 		}
-		else if ( CollectionExpression.class.isInstance(exp) ) {
-			return new SizeOfCollectionExpression<C>(this, (CollectionExpression<C>) exp );
+		else if ( PluralAttributePath.class.isInstance(exp) ) {
+			return new SizeOfCollectionExpression<C>(this, (PluralAttributePath<C>) exp );
 		}
 		// TODO : what other specific types?  any?
 		throw new IllegalArgumentException("unknown collection expression type [" + exp.getClass().getName() + "]" );
@@ -1302,11 +1302,8 @@
 	 */
 	@SuppressWarnings({ "unchecked" })
 	public <C extends Collection<?>> Predicate isEmpty(Expression<C> collectionExpression) {
-		if ( CollectionExpression.class.isInstance(collectionExpression) ) {
-			return new IsEmptyPredicate(
-					this,
-					(CollectionExpression<C>) collectionExpression
-			);
+		if ( PluralAttributePath.class.isInstance(collectionExpression) ) {
+			return new IsEmptyPredicate( this, (PluralAttributePath<C>) collectionExpression );
 		}
 		// TODO : what other specific types?  any?
 		throw new IllegalArgumentException(
@@ -1325,7 +1322,7 @@
 	 * {@inheritDoc}
 	 */
 	public <E, C extends Collection<E>> Predicate isMember(E e, Expression<C> collectionExpression) {
-		if ( ! CollectionExpression.class.isInstance(collectionExpression) ) {
+		if ( ! PluralAttributePath.class.isInstance( collectionExpression ) ) {
 			throw new IllegalArgumentException(
 					"unknown collection expression type [" + collectionExpression.getClass().getName() + "]"
 			);
@@ -1333,7 +1330,7 @@
 		return new MemberOfPredicate<E, C>(
 				this,
 				e, 
-				(CollectionExpression<C>)collectionExpression
+				(PluralAttributePath<C>)collectionExpression
 		);
 	}
 
@@ -1348,7 +1345,7 @@
 	 * {@inheritDoc}
 	 */
 	public <E, C extends Collection<E>> Predicate isMember(Expression<E> elementExpression, Expression<C> collectionExpression) {
-		if ( ! CollectionExpression.class.isInstance(collectionExpression) ) {
+		if ( ! PluralAttributePath.class.isInstance( collectionExpression ) ) {
 			throw new IllegalArgumentException(
 					"unknown collection expression type [" + collectionExpression.getClass().getName() + "]"
 			);
@@ -1356,7 +1353,7 @@
 		return new MemberOfPredicate<E, C>(
 				this,
 				elementExpression,
-				(CollectionExpression<C>)collectionExpression
+				(PluralAttributePath<C>)collectionExpression
 		);
 	}
 

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	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/CriteriaSubqueryImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -39,10 +39,9 @@
 import javax.persistence.criteria.Root;
 import javax.persistence.criteria.SetJoin;
 import javax.persistence.criteria.Subquery;
-import javax.persistence.criteria.From;
 import javax.persistence.metamodel.EntityType;
-import org.hibernate.ejb.criteria.FromImpl.JoinScope;
 import org.hibernate.ejb.criteria.expression.ExpressionImpl;
+import org.hibernate.ejb.criteria.path.RootImpl;
 
 /**
  * The Hibernate implementation of the JPA {@link Subquery} contract.  Mostlty a set of delegation to its internal
@@ -57,7 +56,7 @@
 	private Expression<T> selection;
 	private Set<Join<?, ?>> correlatedJoins = new HashSet<Join<?,?>>();
 
-	private final FromImpl.JoinScope joinScope = new FromImpl.JoinScope() {
+	private final FromImplementor.JoinScope joinScope = new FromImplementor.JoinScope() {
 		public void addJoin(Join join) {
 			correlatedJoins.add( join );
 		}
@@ -65,14 +64,6 @@
 		public void addFetch(Fetch fetch) {
 			throw new UnsupportedOperationException( "Cannot define fetch from a subquery correlation" );
 		}
-
-		public boolean isCorrelated() {
-			return true;
-		}
-
-		public From getCorrelationParent() {
-			return null;
-		}
 	};
 
 	public CriteriaSubqueryImpl(
@@ -89,7 +80,7 @@
 	 *
 	 * @return The subquery's join scope.
 	 */
-	public JoinScope getJoinScope() {
+	public FromImplementor.JoinScope getJoinScope() {
 		return joinScope;
 	}
 
@@ -260,35 +251,35 @@
 	 * {@inheritDoc}
 	 */
 	public <X, Y> Join<X, Y> correlate(Join<X, Y> source) {
-		return ( ( JoinImplementors.JoinImplementor<X,Y> ) source ).correlateTo( this );
+		return ( (JoinImplementor<X,Y>) source ).correlateTo( this );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	public <X, Y> CollectionJoin<X, Y> correlate(CollectionJoin<X, Y> source) {
-		return ( ( JoinImplementors.CollectionJoinImplementor<X,Y> ) source ).correlateTo( this );
+		return ( (CollectionJoinImplementor<X,Y>) source ).correlateTo( this );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	public <X, Y> SetJoin<X, Y> correlate(SetJoin<X, Y> source) {
-		return ( ( JoinImplementors.SetJoinImplementor<X,Y> ) source ).correlateTo( this );
+		return ( (SetJoinImplementor<X,Y>) source ).correlateTo( this );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	public <X, Y> ListJoin<X, Y> correlate(ListJoin<X, Y> source) {
-		return ( ( JoinImplementors.ListJoinImplementor<X,Y> ) source ).correlateTo( this );
+		return ( (ListJoinImplementor<X,Y>) source ).correlateTo( this );
 	}
 
 	/**
 	 * {@inheritDoc}
 	 */
 	public <X, K, V> MapJoin<X, K, V> correlate(MapJoin<X, K, V> source) {
-		return ( ( JoinImplementors.MapJoinImplementor<X, K, V> ) source ).correlateTo( this );
+		return ( (MapJoinImplementor<X, K, V>) source ).correlateTo( this );
 	}
 
 	/**

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,629 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import java.util.Set;
-import java.util.Collection;
-import java.util.Map;
-import java.util.LinkedHashSet;
-import javax.persistence.criteria.From;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.CollectionJoin;
-import javax.persistence.criteria.SetJoin;
-import javax.persistence.criteria.ListJoin;
-import javax.persistence.criteria.MapJoin;
-import javax.persistence.criteria.Path;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.Fetch;
-import javax.persistence.metamodel.Attribute;
-import javax.persistence.metamodel.Attribute.PersistentAttributeType;
-import javax.persistence.metamodel.SingularAttribute;
-import javax.persistence.metamodel.CollectionAttribute;
-import javax.persistence.metamodel.SetAttribute;
-import javax.persistence.metamodel.ListAttribute;
-import javax.persistence.metamodel.MapAttribute;
-import javax.persistence.metamodel.EntityType;
-import javax.persistence.metamodel.ManagedType;
-import javax.persistence.metamodel.PluralAttribute;
-import javax.persistence.metamodel.Bindable;
-
-import javax.persistence.metamodel.PluralAttribute.CollectionType;
-import javax.persistence.metamodel.Type.PersistenceType;
-import org.hibernate.ejb.criteria.expression.CollectionExpression;
-import org.hibernate.ejb.criteria.expression.EntityTypeExpression;
-
-/**
- * TODO : javadoc
- *
- * @author Steve Ebersole
- */
-public abstract class FromImpl<Z,X>
-		extends PathImpl<X>
-		implements From<Z,X>, TableExpressionMapper, Serializable {
-	public static final JoinType DEFAULT_JOIN_TYPE = JoinType.INNER;
-
-	private final Expression<Class<? extends X>> typeExpression;
-    private Set<Join<X, ?>> joins;
-    private Set<Fetch<X, ?>> fetches;
-
-	/**
-	 * Helper contract used to define who/what keeps track of joins and fetches made from this <tt>FROM</tt>.
-	 */
-	public static interface JoinScope<X> extends Serializable {
-		public void addJoin(Join<X, ?> join);
-		public void addFetch(Fetch<X,?> fetch);
-		public boolean isCorrelated();
-		public From<?, X> getCorrelationParent();
-	}
-
-	private JoinScope<X> joinScope = new JoinScope<X>() {
-		public void addJoin(Join<X, ?> join) {
-			if ( joins == null ) {
-				joins = new LinkedHashSet<Join<X,?>>();
-			}
-			joins.add( join );
-		}
-
-		public void addFetch(Fetch<X, ?> fetch) {
-			if ( fetches == null ) {
-				fetches = new LinkedHashSet<Fetch<X,?>>();
-			}
-			fetches.add( fetch );
-		}
-
-		public boolean isCorrelated() {
-			return false;
-		}
-
-		public From<?, X> getCorrelationParent() {
-			return null;
-		}
-	};
-
-	/**
-	 * Special constructor for {@link RootImpl}.
-	 *
-	 * @param criteriaBuilder The query build
-	 * @param entityType The entity defining this root
-	 */
-	@SuppressWarnings({ "unchecked" })
-    protected FromImpl(CriteriaBuilderImpl criteriaBuilder, EntityType<X> entityType) {
-		super( criteriaBuilder, entityType.getBindableJavaType(), null, null, entityType );
-		this.typeExpression = new EntityTypeExpression( criteriaBuilder, entityType.getBindableJavaType() );
-	}
-
-	/**
-	 * The general constructor for a {@link From} implementor.
-	 *
-	 * @param criteriaBuilder
-	 * @param javaType
-	 * @param origin
-	 * @param attribute
-	 * @param model
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public FromImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<X> javaType,
-			PathImpl<Z> origin,
-			Attribute<? super Z, ?> attribute,
-			Bindable<X> model) {
-		super( criteriaBuilder, javaType, origin, attribute, model );
-		this.typeExpression = new EntityTypeExpression( criteriaBuilder, model.getBindableJavaType() );
-	}
-
-	protected void defineJoinScope(JoinScope<X> joinScope) {
-		this.joinScope = joinScope;
-	}
-
-	@Override
-	public Expression<Class<? extends X>> type() {
-		return typeExpression;
-	}
-
-	/**
-	 * Get the attribute by name from the underlying model.  This alows subclasses to
-	 * define exactly how the attribute is derived.
-	 * 
-	 * @param name The attribute name
-	 * 
-	 * @return The attribute.
-	 * 
-	 * @throws IllegalArgumentException If no such attribute is found (follows exception type from {@link ManagedType}).
-	 */
-	protected abstract Attribute<X,?> getAttribute(String name);
-
-
-	// JOINS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Set<Join<X, ?>> getJoins() {
-		return joins;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> Join<X, Y> join(SingularAttribute<? super X, Y> singularAttribute) {
-		return join( singularAttribute, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> Join<X, Y> join(SingularAttribute<? super X, Y> attribute, JoinType jt) {
-		Join<X, Y> join = constructJoin( attribute, jt );
-		joinScope.addJoin( join );
-		return join;
-	}
-
-	private <Y> JoinImplementors.JoinImplementor<X, Y> constructJoin(SingularAttribute<? super X, Y> attribute, JoinType jt) {
-		if ( PersistenceType.BASIC.equals( attribute.getType().getPersistenceType() ) ) {
-			throw new BasicPathUsageException( "Cannot join to attribute of basic type", attribute );
-        }
-
-		// 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();
-        return new JoinImpl<X, Y>(
-				queryBuilder(),
-				attributeType,
-				this,
-				attribute,
-				jt
-		);
-	}
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> CollectionJoin<X, Y> join(CollectionAttribute<? super X, Y> collection) {
-		return join( collection, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> CollectionJoin<X, Y> join(CollectionAttribute<? super X, Y> collection, JoinType jt) {
-		final CollectionJoin<X, Y> join = constructJoin( collection, jt );
-		joinScope.addJoin( join );
-		return join;
-	}
-
-	private <Y> JoinImplementors.CollectionJoinImplementor<X, Y> constructJoin(CollectionAttribute<? super X, Y> collection, JoinType jt) {
-		if ( jt.equals( JoinType.RIGHT ) ) {
-			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
-		}
-
-		final Class<Y> attributeType = collection.getBindableJavaType();
-		final JoinImplementors.CollectionJoinImplementor<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
-			);
-		}
-		return join;
-	}
-
-	private boolean isBasicCollection(PluralAttribute collection) {
-		return PersistenceType.BASIC.equals( collection.getElementType().getPersistenceType() );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> SetJoin<X, Y> join(SetAttribute<? super X, Y> set) {
-		return join( set, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> SetJoin<X, Y> join(SetAttribute<? super X, Y> set, JoinType jt) {
-		final SetJoin<X, Y> join = constructJoin( set, jt );
-		joinScope.addJoin( join );
-		return join;
-	}
-
-	private <Y> JoinImplementors.SetJoinImplementor<X, Y> constructJoin(SetAttribute<? super X, Y> set, JoinType jt) {
-		if ( jt.equals( JoinType.RIGHT ) ) {
-			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
-		}
-
-		final Class<Y> attributeType = set.getBindableJavaType();
-		final JoinImplementors.SetJoinImplementor<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 );
-		}
-		return join;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list) {
-		return join( list, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list, JoinType jt) {
-		final ListJoin<X, Y> join = constructJoin( list, jt );
-		joinScope.addJoin( join );
-		return join;
-	}
-
-	private  <Y> JoinImplementors.ListJoinImplementor<X, Y> constructJoin(ListAttribute<? super X, Y> list, JoinType jt) {
-		if ( jt.equals( JoinType.RIGHT ) ) {
-			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
-		}
-
-		final Class<Y> attributeType = list.getBindableJavaType();
-		final JoinImplementors.ListJoinImplementor<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 );
-		}
-		return join;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <K, V> MapJoin<X, K, V> join(MapAttribute<? super X, K, V> map) {
-		return join( map, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <K, V> MapJoin<X, K, V> join(MapAttribute<? super X, K, V> map, JoinType jt) {
-		final MapJoin<X, K, V> join = constructJoin( map, jt );
-		joinScope.addJoin( join );
-		return join;
-	}
-
-	private <K, V> JoinImplementors.MapJoinImplementor<X, K, V> constructJoin(MapAttribute<? super X, K, V> map, JoinType jt) {
-		if ( jt.equals( JoinType.RIGHT ) ) {
-			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
-		}
-
-		final Class<V> attributeType = map.getBindableJavaType();
-		final JoinImplementors.MapJoinImplementor<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 );
-		}
-		return join;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <X,Y> Join<X, Y> join(String attributeName) {
-		return join( attributeName, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public <X,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<X,Y>) join( (CollectionAttribute) attribute, jt );
-			}
-			else if ( CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
-				return (Join<X,Y>) join( (ListAttribute) attribute, jt );
-			}
-			else if ( CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
-				return (Join<X,Y>) join( (SetAttribute) attribute, jt );
-			}
-			else {
-				return (Join<X,Y>) join( (MapAttribute) attribute, jt );
-			}
-		}
-		else {
-			return (Join<X,Y>) join( (SingularAttribute)attribute, jt );
-		}
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <X,Y> CollectionJoin<X, Y> joinCollection(String attributeName) {
-		return joinCollection( attributeName, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public <X,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 (CollectionJoin<X,Y>) join( (CollectionAttribute) attribute, jt );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <X,Y> SetJoin<X, Y> joinSet(String attributeName) {
-		return joinSet( attributeName, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public <X,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 (SetJoin<X,Y>) join( (SetAttribute) attribute, jt );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <X,Y> ListJoin<X, Y> joinList(String attributeName) {
-		return joinList( attributeName, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public <X,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 (ListJoin<X,Y>) join( (ListAttribute) attribute, jt );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public <X, K, V> MapJoin<X, K, V> joinMap(String attributeName) {
-		return joinMap( attributeName, DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public <X, 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 (MapJoin<X,K,V>) join( (MapAttribute) attribute, jt );
-	}
-
-
-	// FETCHES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Set<Fetch<X, ?>> getFetches() {
-		return fetches;
-	}
-
-	/**
-	 * Retrieve the collection of fetches, imnplementing delayed creations.  Calls on this method
-	 * assume the set is physically needed, and as a result the set is built if not already.
-	 *
-	 * @return The set of fetches.
-	 */
-	public Set<Fetch<X, ?>> internalGetFetches() {
-		return fetches;
-	}
-
-	public <Y> Fetch<X, Y> fetch(SingularAttribute<? super X, Y> singularAttribute) {
-		return fetch( singularAttribute, DEFAULT_JOIN_TYPE );
-	}
-
-	public <Y> Fetch<X, Y> fetch(SingularAttribute<? super X, Y> attribute, JoinType jt) {
-		Fetch<X, Y> fetch = constructJoin( attribute, jt );
-		joinScope.addFetch( fetch );
-		return fetch;
-	}
-
-	public <Y> Fetch<X, Y> fetch(PluralAttribute<? super X, ?, Y> pluralAttribute) {
-		return fetch( pluralAttribute, DEFAULT_JOIN_TYPE );
-	}
-
-	public <Y> Fetch<X, Y> fetch(PluralAttribute<? super X, ?, Y> pluralAttribute, JoinType jt) {
-		final Fetch<X, Y> fetch;
-		// TODO : combine Fetch and Join hierarchies (JoinImplementor extends Join,Fetch???)
-		if ( CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) {
-			fetch = constructJoin( (CollectionAttribute<X,Y>) pluralAttribute, jt );
-		}
-		else if ( CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
-			fetch = constructJoin( (ListAttribute<X,Y>) pluralAttribute, jt );
-		}
-		else if ( CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
-			fetch = constructJoin( (SetAttribute<X,Y>) pluralAttribute, jt );
-		}
-		else {
-			fetch = constructJoin( (MapAttribute<X,?,Y>) pluralAttribute, jt );
-		}
-		joinScope.addFetch( fetch );
-		return fetch;
-	}
-
-	public <X,Y> Fetch<X, Y> fetch(String attributeName) {
-		return fetch( attributeName, DEFAULT_JOIN_TYPE );
-	}
-
-	@SuppressWarnings({ "unchecked" })
-	public <X,Y> Fetch<X, Y> fetch(String attributeName, JoinType jt) {
-		Attribute<X,?> attribute = (Attribute<X, ?>) getAttribute( attributeName );
-		if ( attribute.isCollection() ) {
-			return (Fetch<X, Y>) fetch( (PluralAttribute) attribute, jt );
-		}
-		else {
-			return (Fetch<X, Y>) fetch( (SingularAttribute) attribute, jt );
-		}
-	}
-
-
-	// PATH HANDLING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-	@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) {
-		return new CollectionExpression<C>( queryBuilder(), collection.getJavaType(), this, collection );
-	}
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> map) {
-		return ( Expression<M> ) new CollectionExpression<Map<K, V>>( queryBuilder(), map.getJavaType(), this, map );
-	}
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public <Y> Path<Y> get(String attributeName) {
-		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 );
-		}
-	}
-
-	@Override
-	public String getPathIdentifier() {
-		return getAlias();
-	}
-
-	@Override
-	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		prepareAlias( renderingContext );
-		return getAlias();
-	}
-
-	@Override
-	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		prepareAlias( renderingContext );
-		return getAlias();
-	}
-
-	public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		prepareAlias( renderingContext );
-		return ( (EntityType) getModel() ).getName() + " as " + getAlias();
-	}
-	
-	public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		if ( getAlias() == null ) {
-			setAlias( renderingContext.generateAlias() );
-		}
-	}
-}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/FromImplementor.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,50 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+import java.io.Serializable;
+import javax.persistence.criteria.Fetch;
+import javax.persistence.criteria.From;
+import javax.persistence.criteria.Join;
+
+/**
+ * Implementation contract for the JPA {@link From} interface.
+ *
+ * @author Steve Ebersole
+ */
+public interface FromImplementor<Z,X> extends PathImplementor<X>, From<Z,X> {
+	public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext);
+	public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext);
+
+	/**
+	 * Helper contract used to define who/what keeps track of joins and fetches made from this <tt>FROM</tt>.
+	 */
+	public static interface JoinScope<X> extends Serializable {
+		public void addJoin(Join<X, ?> join);
+		public void addFetch(Fetch<X,?> fetch);
+	}
+
+	public FromImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
+	public void prepareCorrelationDelegate(JoinScope<X> joinScope, FromImplementor<Z,X> parent);
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/IllegalDereferenceException.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/IllegalDereferenceException.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/IllegalDereferenceException.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,43 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+/**
+ * Represents an illegal attempt to dereference from a {@link #getPathSource() path source} which
+ * cannot be dereferenced.
+ *
+ * @author Steve Ebersole
+ */
+public class IllegalDereferenceException extends RuntimeException {
+	private final PathSource pathSource;
+
+	public IllegalDereferenceException(PathSource pathSource) {
+		super( "Illegal attempt to dereference path source [" + pathSource.getPathIdentifier() + "]" );
+		this.pathSource = pathSource;
+	}
+
+	public PathSource getPathSource() {
+		return pathSource;
+	}
+}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,144 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.From;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.metamodel.Attribute;
-import javax.persistence.metamodel.ManagedType;
-import javax.persistence.metamodel.Bindable;
-import javax.persistence.metamodel.SingularAttribute;
-import javax.persistence.metamodel.EmbeddableType;
-
-/**
- * Models a non-collection property join.
- *
- * @author Steve Ebersole
- */
-public class JoinImpl<Z, X> 
-		extends FromImpl<Z, X>
-		implements JoinImplementors.JoinImplementor<Z,X>, Serializable {
-	// TODO : keep track or whether any non-identifier properties get dereferenced
-	// for join optimization like in HQL
-
-	// TODO : do we need (or is it easier with) a separate "component join impl"?
-
-	// TODO : cleanup these ctors, ugh...
-
-	private final ManagedType<X> managedType;
-	private final JoinType joinType;
-
-	@SuppressWarnings({ "unchecked" })
-	public JoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<X> javaType,
-			PathImpl<Z> lhs,
-			Attribute<? super Z, ?> joinProperty,
-			JoinType joinType) {
-		super(
-				criteriaBuilder,
-				javaType,
-				lhs,
-				joinProperty,
-				( Bindable<X> ) ( Attribute.PersistentAttributeType.EMBEDDED == joinProperty.getPersistentAttributeType()
-										? joinProperty
-										: criteriaBuilder.getEntityManagerFactory().getMetamodel().managedType( javaType ))
-		);
-		this.managedType = getManagedType();
-		this.joinType = joinType;
-	}
-
-	@SuppressWarnings({ "unchecked" })
-	protected ManagedType<X> getManagedType() {
-		Bindable<X> model = getModel();
-		return Bindable.BindableType.ENTITY_TYPE == model.getBindableType()
-				? (ManagedType<X>) model
-				: (EmbeddableType<X>) ( (SingularAttribute) model ).getType();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public From<?, Z> getParent() {
-		// AFAICT, only "froms" (specifically roots and joins) can be the parent of a join.
-		return ( From<?, Z> ) getParentPath();
-	}
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public Attribute<? super Z, ?> getAttribute() {
-		return (Attribute<? super Z, ?>) super.getAttribute();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public JoinType getJoinType() {
-		return joinType;
-	}
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	protected Attribute<X, ?> getAttribute(String name) {
-		return (Attribute<X, ?>) managedType.getAttribute( name );
-	}
-
-	@SuppressWarnings({ "unchecked" })
-	public JoinImplementors.JoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery) {
-		JoinImpl<Z,X> correlation = new JoinImpl<Z,X>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<Z>)getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	private From<Z,X> correlationParent;
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return false;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<Z,X> getCorrelationParent() {
-		return correlationParent;
-	}
-
-	public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		prepareAlias( renderingContext );
-		( (FromImpl) getParent() ).prepareAlias( renderingContext );
-		return getParent().getAlias() + '.' + getAttribute().getName() + " as " + getAlias();
-	}
-}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementor.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementor.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,42 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+import javax.persistence.criteria.Fetch;
+import javax.persistence.criteria.Join;
+
+/**
+ * Consolidates the {@link Join} and {@link Fetch} hierarchies since that is how we implement them.
+ * This allows us to treat them polymorphically.
+*
+* @author Steve Ebersole
+*/
+public interface JoinImplementor<Z,X> extends Join<Z,X>, Fetch<Z,X>, FromImplementor<Z,X> {
+	/**
+	 * {@inheritDoc}
+	 * <p/>
+	 * Refined return type
+	 */
+	public JoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
+}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementors.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementors.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/JoinImplementors.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,65 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import javax.persistence.criteria.CollectionJoin;
-import javax.persistence.criteria.Fetch;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.ListJoin;
-import javax.persistence.criteria.MapJoin;
-import javax.persistence.criteria.SetJoin;
-import javax.persistence.criteria.From;
-
-/**
- * Consolidates the {@link Join} and {@link Fetch} hierarchies since that is how we implement them.
- * This allows us to treat them polymorphically.
- *
- * @author Steve Ebersole
- */
-public interface JoinImplementors {
-	public static interface JoinImplementor<Z,X>
-			extends Join<Z,X>, Fetch<Z,X> {
-		public JoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
-	}
-
-	public static interface CollectionJoinImplementor<Z,X> 
-			extends JoinImplementor<Z,X>, CollectionJoin<Z,X>, Fetch<Z,X> {
-		public CollectionJoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
-	}
-
-	public static interface SetJoinImplementor<Z,X> 
-			extends JoinImplementor<Z,X>, SetJoin<Z,X>, Fetch<Z,X> {
-		public SetJoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
-	}
-
-	public static interface ListJoinImplementor<Z,X> 
-			extends JoinImplementor<Z,X>, ListJoin<Z,X>, Fetch<Z,X> {
-		public ListJoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
-	}
-
-	public static interface MapJoinImplementor<Z,K,V> 
-			extends JoinImplementor<Z,V>, MapJoin<Z,K,V>, Fetch<Z,V> {
-		public MapJoinImplementor<Z,K,V> correlateTo(CriteriaSubqueryImpl subquery);
-	}
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,106 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.ListAttribute;
-import javax.persistence.metamodel.ManagedType;
-
-import org.hibernate.ejb.criteria.JoinImplementors.ListJoinImplementor;
-import org.hibernate.ejb.criteria.expression.ListIndexExpression;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.List}, whose elements
- * are associations.
- *
- * @author Steve Ebersole
- */
-public class ListJoinImpl<O,E>
-		extends JoinImpl<O,E>
-		implements JoinImplementors.ListJoinImplementor<O,E>, Serializable {
-	public ListJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<E> javaType,
-			PathImpl<O> lhs,
-			ListAttribute<? super O, ?> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, 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();
-	}
-
-	@Override
-	protected ManagedType<E> getManagedType() {
-		return ( ManagedType<E> ) getAttribute().getElementType();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Expression<Integer> index() {
-		return new ListIndexExpression( queryBuilder(), this, getAttribute() );
-	}
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public ListJoinImplementor<O, E> correlateTo(CriteriaSubqueryImpl subquery) {
-		ListJoinImpl<O,E> correlation = new ListJoinImpl<O,E>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	private From<O, E> correlationParent;
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return getCorrelationParent() != null;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, E> getCorrelationParent() {
-		return correlationParent;
-	}
-}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImplementor.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/ListJoinImplementor.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,40 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+import javax.persistence.criteria.ListJoin;
+
+/**
+ * Specialization of {@link JoinImplementor} for {@link java.util.List} typed attribute joins
+ *
+ * @author Steve Ebersole
+ */
+public interface ListJoinImplementor<Z,X> extends JoinImplementor<Z,X>, ListJoin<Z,X> {
+	/**
+	 * {@inheritDoc}
+	 * <p/>
+	 * Refined return type
+	 */
+	public ListJoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
+}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,171 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import java.util.Map;
-import java.util.Map.Entry;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.Path;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.MapAttribute;
-import javax.persistence.metamodel.ManagedType;
-import javax.persistence.metamodel.Type.PersistenceType;
-import org.hibernate.ejb.criteria.JoinImplementors.MapJoinImplementor;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.Map}, whose elements
- * are associations.
- *
- * @author Steve Ebersole
- */
-public class MapJoinImpl<O,K,V>
-		extends JoinImpl<O,V>
-		implements JoinImplementors.MapJoinImplementor<O,K,V>, Serializable {
-
-	public MapJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<V> javaType,
-			PathImpl<O> lhs,
-			MapAttribute<? super O, K, V> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, 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();
-	}
-
-	@Override
-	protected ManagedType<V> getManagedType() {
-		return ( ManagedType<V> ) getAttribute().getElementType();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Join<Map<K, V>, K> joinKey() {
-		return joinKey( DEFAULT_JOIN_TYPE );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	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() );
-		return new MapKeyHelpers.MapKeyJoin<K,V>(
-				queryBuilder(),
-				mapKeySource,
-				mapKeyAttribute,
-				jt
-		);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	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}
-	 */
-	@SuppressWarnings({ "unchecked" })
-	public Expression<Entry<K, V>> entry() {
-		return new MapKeyHelpers.MapEntryExpression( queryBuilder(), Map.Entry.class, this, getAttribute() );
-	}
-
-
-	private From<O, V> correlationParent;
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public MapJoinImplementor<O, K, V> correlateTo(CriteriaSubqueryImpl subquery) {
-		MapJoinImpl<O, K, V> correlation = new MapJoinImpl<O, K, V>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return getCorrelationParent() != null;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, V> getCorrelationParent() {
-		return correlationParent;
-	}
-}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImplementor.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapJoinImplementor.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,40 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+import javax.persistence.criteria.MapJoin;
+
+/**
+ * Specialization of {@link JoinImplementor} for {@link java.util.Map} typed attribute joins
+ *
+ * @author Steve Ebersole
+ */
+public interface MapJoinImplementor<Z,K,V> extends JoinImplementor<Z,V>, MapJoin<Z,K,V> {
+	/**
+	 * {@inheritDoc}
+	 * <p/>
+	 * Refined return type
+	 */
+	public MapJoinImplementor<Z,K,V> correlateTo(CriteriaSubqueryImpl subquery);
+}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,314 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import java.lang.reflect.Member;
-import java.util.Map;
-import java.util.Map.Entry;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.From;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.MapJoin;
-import javax.persistence.criteria.Path;
-import javax.persistence.metamodel.Attribute;
-import javax.persistence.metamodel.ManagedType;
-import javax.persistence.metamodel.MapAttribute;
-import javax.persistence.metamodel.SingularAttribute;
-import javax.persistence.metamodel.Type.PersistenceType;
-
-import org.hibernate.ejb.criteria.JoinImplementors.JoinImplementor;
-import org.hibernate.ejb.criteria.expression.ExpressionImpl;
-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>, Serializable {
-
-		public MapKeyJoin(
-				CriteriaBuilderImpl criteriaBuilder,
-				MapPath<K,V> source,
-				MapKeyAttribute<K> attribute,
-				JoinType jt) {
-			super(
-					criteriaBuilder,
-					attribute.getJavaType(),
-					source,
-					attribute,
-					jt
-			);
-		}
-
-		@Override
-		public JoinImplementor<Map<K, V>, K> correlateTo(CriteriaSubqueryImpl subquery) {
-			throw new UnsupportedOperationException( "Map key join cannot be used as a correlation" );
-		}
-
-		public boolean isCorrelated() {
-			return false;
-		}
-
-		public From<Map<K, V>, K> getCorrelationParent() {
-			return null;
-		}
-	}
-
-	/**
-	 * 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>, Serializable {
-		public MapKeyPath(
-				CriteriaBuilderImpl criteriaBuilder,
-				MapPath<K,?> source,
-				MapKeyAttribute<K> attribute) {
-			super( criteriaBuilder, 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>>, Serializable {
-		private final MapJoin<?,K,V> mapJoin;
-
-		public MapPath(
-				CriteriaBuilderImpl criteriaBuilder,
-				Class<Map<K, V>> javaType,
-				MapJoin<?,K,V> mapJoin,
-				MapAttribute<?,K,V> attribute,
-				Object model) {
-			super( criteriaBuilder, 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>, Serializable {
-		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(CriteriaBuilderImpl criteriaBuilder, 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)
-					criteriaBuilder.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;
-		}
-	}
-
-	public static class MapEntryExpression<K,V>
-			extends ExpressionImpl<Map.Entry<K,V>>
-			implements Expression<Map.Entry<K,V>>, Serializable {
-		private final PathImpl origin;
-		private final MapAttribute<?, K, V> attribute;
-
-		public MapEntryExpression(
-				CriteriaBuilderImpl criteriaBuilder,
-				Class<Entry<K, V>> javaType,
-				PathImpl origin,
-				MapAttribute<?, K, V> attribute) {
-			super( criteriaBuilder, javaType);
-			this.origin = origin;
-			this.attribute = attribute;
-		}
-
-		public MapAttribute<?, K, V> getAttribute() {
-			return attribute;
-		}
-
-		public void registerParameters(ParameterRegistry registry) {
-			// none to register
-		}
-
-		public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
-			// i don't think this is valid outside of select clause...
-			throw new IllegalStateException( "illegal reference to map entry outside of select clause." );
-		}
-
-		public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
-			return "entry(" + path( renderingContext ) + ")";
-		}
-
-		private String path(CriteriaQueryCompiler.RenderingContext renderingContext) {
-			return origin.getPathIdentifier() 
-					+ '.'
-					+ ( (Renderable) getAttribute() ).renderProjection( renderingContext );
-		}
-	}
-
-	/**
-	 * Disallow instantiation
-	 */
-	private MapKeyHelpers() {
-	}
-
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,170 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.Map;
-import javax.persistence.criteria.Expression;
-import javax.persistence.criteria.Path;
-
-import javax.persistence.metamodel.Attribute;
-import javax.persistence.metamodel.Bindable;
-import javax.persistence.metamodel.MapAttribute;
-import javax.persistence.metamodel.PluralAttribute;
-import javax.persistence.metamodel.SingularAttribute;
-import org.hibernate.ejb.criteria.expression.ExpressionImpl;
-
-/**
- * A {@link Path} models an individual portion of a path expression.
- *
- * @author Steve Ebersole
- */
-public class PathImpl<X> extends ExpressionImpl<X> implements Path<X>, Serializable {
-	private final PathImpl<?> origin;
-	private final Attribute<?,?> attribute;
-	private Object model;
-
-	/**
-	 * Constructs a path.
-	 *
-	 * @param criteriaBuilder The delegate for building query components.
-	 * @param javaType The java type of this path,
-	 * @param origin The source ("lhs") of this path.
-	 * @param attribute The attribute defining this path element.
-	 * @param model The corresponding model of this path.
-	 */
-	protected PathImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<X> javaType,
-			PathImpl<?> origin,
-			Attribute<?,?> attribute,
-			Object model) {
-        super( criteriaBuilder, javaType );
-		this.origin = origin;
-		this.attribute = attribute;
-		this.model = model;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-    public PathImpl<?> getParentPath() {
-        return origin;
-    }
-
-	public Attribute<?, ?> getAttribute() {
-		return attribute;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-    @SuppressWarnings({ "unchecked" })
-	public Bindable<X> getModel() {
-        if ( model == null ) {
-            throw new IllegalStateException( this + " represents a basic path and not a bindable" );
-        }
-		return (Bindable<X>)model;
-    }
-
-	/**
-	 * {@inheritDoc}
-	 * <p/>
-	 * Subclasses override this appropriately, but here we simply throw
-	 * an {@link IllegalStateException}
-	 */
-	public Expression<Class<? extends X>> type() {
-		throw new BasicPathUsageException( "type() is not applicable to primitive paths.", getAttribute() );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 * <p/>
-	 * Subclasses override this appropriately, but here we simply throw
-	 * an {@link IllegalStateException}
-	 */
-	public <Y> Path<Y> get(SingularAttribute<? super X, Y> attribute) {
-		throw illegalDereference();
-	}
-
-	private BasicPathUsageException illegalDereference() {
-		return new BasicPathUsageException( "Primitive path cannot be de-referenced", getAttribute() );
-	}
-
-	/**
-	 * {@inheritDoc}
-	 * <p/>
-	 * Subclasses override this appropriately, but here we simply throw
-	 * an {@link IllegalStateException}
-	 */
-	public <E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> collection) {
-		throw illegalDereference();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 * <p/>
-	 * Subclasses override this appropriately, but here we simply throw
-	 * an {@link IllegalStateException}
-	 */
-	public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> map) {
-		throw illegalDereference();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 * <p/>
-	 * Subclasses override this appropriately, but here we simply throw
-	 * an {@link IllegalStateException}
-	 */
-	public <Y> Path<Y> get(String attributeName) {
-		throw illegalDereference();
-	}
-
-	public void registerParameters(ParameterRegistry registry) {
-		// none to register
-	}
-
-	/**
-	 * Get the string representation of this path as a navigation from one of the
-	 * queries <tt>identification variables</tt>
-	 *
-	 * @return The path's identifier.
-	 */
-	public String getPathIdentifier() {
-		return getParentPath().getPathIdentifier() + "." + getAttribute().getName();
-	}
-
-	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		( (TableExpressionMapper) getParentPath() ).prepareAlias( renderingContext );
-		return getParentPath().getAlias()
-				+ '.'
-				+ getAttribute().getName();
-	}
-
-	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		return render( renderingContext );
-	}
-}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathImplementor.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -31,16 +31,8 @@
  *
  * @author Steve Ebersole
  */
-public interface PathImplementor<X> extends ExpressionImplementor<X>, Path<X> {
+public interface PathImplementor<X> extends ExpressionImplementor<X>, Path<X>, PathSource<X>, Renderable {
 	/**
-	 * Get the string representation of this path as a navigation from one of the
-	 * queries <tt>identification variables</tt>
-	 *
-	 * @return The path's identifier.
-	 */
-	public String getPathIdentifier();
-
-	/**
 	 * Retrieve reference to the attribute this path represents.
 	 *
 	 * @return The metamodel attribute.

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/PathSource.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,43 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+import javax.persistence.criteria.Path;
+
+/**
+ * Implementation contract for things which can be the source (parent, left-hand-side, etc) of a path
+ *
+ * @author Steve Ebersole
+ */
+public interface PathSource<X> extends Path<X> {
+	public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext);
+
+	/**
+	 * Get the string representation of this path as a navigation from one of the
+	 * queries <tt>identification variables</tt>
+	 *
+	 * @return The path's identifier.
+	 */
+	public String getPathIdentifier();
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/QueryStructure.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -44,6 +44,8 @@
 import javax.persistence.criteria.JoinType;
 import javax.persistence.metamodel.EntityType;
 
+import org.hibernate.ejb.criteria.path.RootImpl;
+
 /**
  * Models basic query structure.  Used as a delegate in implementing both
  * {@link org.hibernate.criterion.CriteriaQuery} and
@@ -222,9 +224,9 @@
 		jpaqlQuery.append( " from " );
 		String sep = "";
 		for ( Root root : getRoots() ) {
-			( (TableExpressionMapper) root ).prepareAlias( renderingContext );
+			( (FromImplementor) root ).prepareAlias( renderingContext );
 			jpaqlQuery.append( sep );
-			jpaqlQuery.append( ( ( TableExpressionMapper ) root ).renderTableExpression( renderingContext ) );
+			jpaqlQuery.append( ( (FromImplementor) root ).renderTableExpression( renderingContext ) );
 			sep = ", ";
 		}
 
@@ -264,9 +266,9 @@
 		}
 
 		for ( Join join : joins ) {
-			( (TableExpressionMapper) join ).prepareAlias( renderingContext );
+			( (FromImplementor) join ).prepareAlias( renderingContext );
 			jpaqlQuery.append( renderJoinType( join.getJoinType() ) )
-					.append( ( ( TableExpressionMapper ) join ).renderTableExpression( renderingContext ) );
+					.append( ( (FromImplementor) join ).renderTableExpression( renderingContext ) );
 			renderJoins( jpaqlQuery, renderingContext, join.getJoins() );
 			renderFetches( jpaqlQuery, renderingContext, join.getFetches() );
 		}
@@ -297,10 +299,10 @@
 		}
 
 		for ( Fetch fetch : fetches ) {
-			( (TableExpressionMapper) fetch ).prepareAlias( renderingContext );
+			( (FromImplementor) fetch ).prepareAlias( renderingContext );
 			jpaqlQuery.append( renderJoinType( fetch.getJoinType() ) )
 					.append( "fetch " )
-					.append( ( ( TableExpressionMapper ) fetch ).renderTableExpression( renderingContext ) );
+					.append( ( (FromImplementor) fetch ).renderTableExpression( renderingContext ) );
 
 			renderFetches( jpaqlQuery, renderingContext, fetch.getFetches() );
 		}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/RootImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,70 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.Root;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.Attribute;
-import javax.persistence.metamodel.EntityType;
-
-/**
- * Defines a <tt>query root</tt>.
- *
- * @author Steve Ebersole
- */
-public class RootImpl<X> extends FromImpl<X,X> implements Root<X>, Serializable {
-	private RootImpl<X> correlationParent;
-
-	public RootImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			EntityType<X> model) {
-		super( criteriaBuilder, model );
-	}
-
-	@Override
-    public EntityType<X> getModel(){
-        return ( EntityType<X> ) super.getModel();
-    }
-
-	@Override
-	protected Attribute<X, ?> getAttribute(String name) {
-		return (Attribute<X, ?>) getModel().getAttribute( name );
-	}
-
-	public boolean isCorrelated() {
-		return getCorrelationParent() != null;
-	}
-
-	public From<X, X> getCorrelationParent() {
-		return correlationParent;
-	}
-
-	public RootImpl<X> correlateTo(CriteriaSubqueryImpl subquery) {
-		RootImpl<X> correlation = new RootImpl<X>( queryBuilder(), getModel() );
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,98 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-import java.io.Serializable;
-import javax.persistence.criteria.JoinType;
-import javax.persistence.criteria.From;
-import javax.persistence.metamodel.SetAttribute;
-import javax.persistence.metamodel.ManagedType;
-
-import org.hibernate.ejb.criteria.JoinImplementors.SetJoinImplementor;
-
-/**
- * Represents a join to a persistent collection, defined as type {@link java.util.Set}, whose elements
- * are associations.
- *
- * @author Steve Ebersole
- */
-public class SetJoinImpl<O,E>
-		extends JoinImpl<O,E>
-		implements JoinImplementors.SetJoinImplementor<O,E>, Serializable {
-
-	public SetJoinImpl(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<E> javaType, 
-			PathImpl<O> lhs,
-			SetAttribute<? super O, ?> joinProperty,
-			JoinType joinType) {
-		super( criteriaBuilder, javaType, lhs, joinProperty, joinType);
-	}
-
-	@Override
-	public SetAttribute<? super O, E> getAttribute() {
-		return (SetAttribute<? super O, E>) super.getAttribute();
-	}
-
-	@Override
-	public SetAttribute<? super O, E> getModel() {
-        return getAttribute();
-	}
-
-	@Override
-	protected ManagedType<E> getManagedType() {
-		return ( ManagedType<E> ) getAttribute().getElementType();
-	}
-
-	@Override
-	@SuppressWarnings({ "unchecked" })
-	public SetJoinImplementor<O, E> correlateTo(CriteriaSubqueryImpl subquery) {
-		SetJoinImpl<O,E> correlation = new SetJoinImpl<O,E>(
-				queryBuilder(),
-				getJavaType(),
-				(PathImpl<O>) getParentPath(),
-				getAttribute(),
-				getJoinType()
-		);
-		correlation.defineJoinScope( subquery.getJoinScope() );
-		correlation.correlationParent = this;
-		return correlation;
-	}
-
-	private From<O, E> correlationParent;
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isCorrelated() {
-		return getCorrelationParent() != null;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public From<O, E> getCorrelationParent() {
-		return correlationParent;
-	}
-}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImplementor.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImplementor.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/SetJoinImplementor.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,40 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria;
+
+import javax.persistence.criteria.SetJoin;
+
+/**
+ * Specialization of {@link JoinImplementor} for {@link java.util.Set} typed attribute joins
+ *
+ * @author Steve Ebersole
+ */
+public interface SetJoinImplementor<Z,X> extends JoinImplementor<Z,X>, SetJoin<Z,X> {
+	/**
+	 * {@inheritDoc}
+	 * <p/>
+	 * Refined return type
+	 */
+	public SetJoinImplementor<Z,X> correlateTo(CriteriaSubqueryImpl subquery);
+}

Deleted: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/TableExpressionMapper.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/TableExpressionMapper.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/TableExpressionMapper.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,34 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria;
-
-/**
- * Common contract for things which map to a table expression in a <tt>SQL FROM clause</tt>.
- *
- * @author Steve Ebersole
- */
-public interface TableExpressionMapper {
-	public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext);
-	public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext);
-}

Deleted: 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	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/CollectionExpression.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -1,95 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
- * third-party contributors as indicated by either @author tags or express
- * copyright attribution statements applied by the authors.  All
- * third-party contributions are distributed under license by Red Hat Inc.
- *
- * This copyrighted material is made available to anyone wishing to use, modify,
- * copy, or redistribute it subject to the terms and conditions of the GNU
- * Lesser General Public License, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this distribution; if not, write to:
- * Free Software Foundation, Inc.
- * 51 Franklin Street, Fifth Floor
- * Boston, MA  02110-1301  USA
- */
-package org.hibernate.ejb.criteria.expression;
-
-import java.io.Serializable;
-import javax.persistence.metamodel.PluralAttribute;
-import org.hibernate.ejb.criteria.ParameterRegistry;
-import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
-import org.hibernate.ejb.criteria.PathImpl;
-import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.persister.collection.CollectionPersister;
-
-/**
- * TODO : javadoc
- *
- * @author Steve Ebersole
- */
-public class CollectionExpression<C> extends ExpressionImpl<C> implements Serializable {
-	private final PathImpl origin;
-	private final CollectionPersister persister;
-	private final PluralAttribute<?, C, ?> attribute;
-
-	public CollectionExpression(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<C> javaType,
-			PathImpl origin,
-			PluralAttribute<?, C, ?> attribute) {
-		this( criteriaBuilder, javaType, resolvePersister( criteriaBuilder, attribute ), origin, attribute );
-	}
-
-	private static CollectionPersister resolvePersister(CriteriaBuilderImpl criteriaBuilder, PluralAttribute attribute) {
-		SessionFactoryImplementor sfi = (SessionFactoryImplementor)
-				criteriaBuilder.getEntityManagerFactory().getSessionFactory();
-		return sfi.getCollectionPersister( resolveRole( attribute ) );
-	}
-
-	private static String resolveRole(PluralAttribute attribute) {
-		return attribute.getDeclaringType().getJavaType().getName() +
-				'.' + attribute.getName();
-	}
-
-	public CollectionExpression(
-			CriteriaBuilderImpl criteriaBuilder,
-			Class<C> javaType,
-			CollectionPersister persister,
-			PathImpl origin,
-			PluralAttribute<?, C, ?> attribute) {
-		super( criteriaBuilder, javaType );
-		this.origin = origin;
-		this.persister = persister;
-		this.attribute = attribute;
-	}
-
-	public PluralAttribute<?, C, ?> getAttribute() {
-		return attribute;
-	}
-
-	public CollectionPersister getPersister() {
-		return persister;
-	}
-
-	public void registerParameters(ParameterRegistry registry) {
-		// none to register
-	}
-
-	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		return origin.getPathIdentifier() + '.' + getAttribute().getName();
-	}
-
-	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		return render( renderingContext );
-	}
-}

Modified: 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	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/ListIndexExpression.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -28,29 +28,33 @@
 import org.hibernate.ejb.criteria.ParameterRegistry;
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
 import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
-import org.hibernate.ejb.criteria.PathImpl;
+import org.hibernate.ejb.criteria.PathImplementor;
 
+
 /**
  * An expression for referring to the index of a list.
  *
  * @author Steve Ebersole
  */
 public class ListIndexExpression extends ExpressionImpl<Integer> implements Serializable {
-	private final PathImpl origin;
-	private final ListAttribute<?,?> listAttribute;
+	private final PathImplementor origin;
+	private final ListAttribute listAttribute;
 
-	public ListIndexExpression(CriteriaBuilderImpl criteriaBuilder, PathImpl origin, ListAttribute<?,?> listAttribute) {
+	public ListIndexExpression(
+			CriteriaBuilderImpl criteriaBuilder,
+			PathImplementor origin,
+			ListAttribute listAttribute) {
 		super( criteriaBuilder, Integer.class );
 		this.origin = origin;
 		this.listAttribute = listAttribute;
 	}
 
-	public ListAttribute<?,?> getListAttribute() {
+	public ListAttribute getListAttribute() {
 		return listAttribute;
 	}
 
 	public void registerParameters(ParameterRegistry registry) {
-		// nothign to do
+		// nothing to do
 	}
 
 	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/MapEntryExpression.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,81 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.expression;
+
+import java.io.Serializable;
+import java.util.Map;
+import javax.persistence.criteria.Expression;
+import javax.persistence.metamodel.MapAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.ParameterRegistry;
+import org.hibernate.ejb.criteria.PathImplementor;
+import org.hibernate.ejb.criteria.Renderable;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class MapEntryExpression<K,V>
+		extends ExpressionImpl<Map.Entry<K,V>>
+		implements Expression<Map.Entry<K,V>>, Serializable {
+
+	private final PathImplementor origin;
+	private final MapAttribute<?, K, V> attribute;
+
+	public MapEntryExpression(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<Map.Entry<K, V>> javaType,
+			PathImplementor origin,
+			MapAttribute<?, K, V> attribute) {
+		super( criteriaBuilder, javaType);
+		this.origin = origin;
+		this.attribute = attribute;
+	}
+
+	public MapAttribute<?, K, V> getAttribute() {
+		return attribute;
+	}
+
+	public void registerParameters(ParameterRegistry registry) {
+		// none to register
+	}
+
+	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		// don't think this is valid outside of select clause...
+		throw new IllegalStateException( "illegal reference to map entry outside of select clause." );
+	}
+
+	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		return "entry(" + path( renderingContext ) + ")";
+	}
+
+	private String path(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		return origin.getPathIdentifier()
+				+ '.'
+				+ ( (Renderable) getAttribute() ).renderProjection( renderingContext );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/PathTypeExpression.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,54 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.expression;
+
+import java.io.Serializable;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.ParameterRegistry;
+
+/**
+ * Used to construct the result of {@link javax.persistence.criteria.Path#type()}
+ *
+ * @author Steve Ebersole
+ */
+public class PathTypeExpression<T> extends ExpressionImpl<T> implements Serializable {
+	public PathTypeExpression(CriteriaBuilderImpl criteriaBuilder, Class<T> javaType) {
+		super( criteriaBuilder, javaType );
+	}
+
+	public void registerParameters(ParameterRegistry registry) {
+		// nothing to do
+	}
+
+	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		// todo : is it valid for this to get rendered into the query itself?
+		throw new IllegalArgumentException( "Unexpected call on EntityTypeExpression#render" );
+	}
+
+	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		return render( renderingContext );
+	}
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/expression/SizeOfCollectionExpression.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -28,6 +28,7 @@
 import org.hibernate.ejb.criteria.ParameterRegistry;
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
 import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.path.PluralAttributePath;
 
 /**
  * Represents a "size of" expression in regards to a persistent collection; the implication is
@@ -38,17 +39,17 @@
 public class SizeOfCollectionExpression<C extends Collection>
 		extends ExpressionImpl<Integer>
 		implements Serializable {
-	private final CollectionExpression<C> collectionExpression;
+	private final PluralAttributePath<C> collectionPath;
 
 	public SizeOfCollectionExpression(
 			CriteriaBuilderImpl criteriaBuilder,
-			CollectionExpression<C> collectionExpression) {
+			PluralAttributePath<C> collectionPath) {
 		super( criteriaBuilder, Integer.class);
-		this.collectionExpression = collectionExpression;
+		this.collectionPath = collectionPath;
 	}
 
-	public CollectionExpression<C> getCollectionExpression() {
-		return collectionExpression;
+	public PluralAttributePath<C> getCollectionPath() {
+		return collectionPath;
 	}
 
 	public void registerParameters(ParameterRegistry registry) {
@@ -56,7 +57,7 @@
 	}
 
 	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		return "size(" + getCollectionExpression().render( renderingContext ) + ")";
+		return "size(" + getCollectionPath().render( renderingContext ) + ")";
 	}
 
 	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractFromImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,597 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import javax.persistence.criteria.CollectionJoin;
+import javax.persistence.criteria.Fetch;
+import javax.persistence.criteria.From;
+import javax.persistence.criteria.Join;
+import javax.persistence.criteria.JoinType;
+import javax.persistence.criteria.ListJoin;
+import javax.persistence.criteria.MapJoin;
+import javax.persistence.criteria.SetJoin;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.CollectionAttribute;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type;
+
+import org.hibernate.ejb.criteria.BasicPathUsageException;
+import org.hibernate.ejb.criteria.CollectionJoinImplementor;
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+import org.hibernate.ejb.criteria.JoinImplementor;
+import org.hibernate.ejb.criteria.ListJoinImplementor;
+import org.hibernate.ejb.criteria.MapJoinImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+import org.hibernate.ejb.criteria.SetJoinImplementor;
+
+/**
+ * Convenience base class for various {@link javax.persistence.criteria.From} implementors.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractFromImpl<Z,X>
+		extends AbstractPathImpl<X>
+		implements From<Z,X>, FromImplementor<Z,X>, Serializable {
+
+	public static final JoinType DEFAULT_JOIN_TYPE = JoinType.INNER;
+
+    private Set<Join<X, ?>> joins;
+    private Set<Fetch<X, ?>> fetches;
+
+	public AbstractFromImpl(CriteriaBuilderImpl criteriaBuilder, Class<X> javaType) {
+		this( criteriaBuilder, javaType, null );
+	}
+
+	public AbstractFromImpl(CriteriaBuilderImpl criteriaBuilder, Class<X> javaType, PathSource pathSource) {
+		super( criteriaBuilder, javaType, pathSource );
+	}
+
+	@Override
+	@SuppressWarnings({ "unchecked" })
+	public PathSource<Z> getPathSource() {
+		return super.getPathSource();
+	}
+
+	@Override
+	public String getPathIdentifier() {
+		return getAlias();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected boolean canBeDereferenced() {
+		return true;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		if ( getAlias() == null ) {
+			setAlias( renderingContext.generateAlias() );
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Attribute<?, ?> getAttribute() {
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public From<?, Z> getParent() {
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	protected Attribute<X, ?> locateAttributeInternal(String name) {
+		return (Attribute<X, ?>) locateManagedType().getAttribute( name );
+	}
+
+	@SuppressWarnings({ "unchecked" })
+	protected ManagedType<? super X> locateManagedType() {
+		// by default, this should be the model
+		return (ManagedType<? super X>) getModel();
+	}
+
+
+	// CORRELATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	private From<Z,X> correlationParent;
+	private JoinScope<X> joinScope = new JoinScope<X>() {
+		public void addJoin(Join<X, ?> join) {
+			if ( joins == null ) {
+				joins = new LinkedHashSet<Join<X,?>>();
+			}
+			joins.add( join );
+		}
+
+		public void addFetch(Fetch<X, ?> fetch) {
+			if ( fetches == null ) {
+				fetches = new LinkedHashSet<Fetch<X,?>>();
+			}
+			fetches.add( fetch );
+		}
+	};
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isCorrelated() {
+		return getCorrelationParent() != null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public From<Z,X> getCorrelationParent() {
+		return correlationParent;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public FromImplementor<Z, X> correlateTo(CriteriaSubqueryImpl subquery) {
+		final FromImplementor<Z, X> correlationDelegate = createCorrelationDelegate();
+		correlationDelegate.prepareCorrelationDelegate( subquery.getJoinScope(), this );
+		return correlationDelegate;
+	}
+
+	protected abstract FromImplementor<Z, X> createCorrelationDelegate();
+
+	public void prepareCorrelationDelegate(JoinScope<X> joinScope, FromImplementor<Z, X> parent) {
+		this.joinScope = joinScope;
+		this.correlationParent = parent;
+	}
+
+
+	// JOINS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected abstract boolean canBeJoinSource();
+
+	private RuntimeException illegalJoin() {
+		return new IllegalArgumentException(
+				"Collection of values [" + getPathIdentifier() + "] cannot be source of a join"
+		);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Set<Join<X, ?>> getJoins() {
+		return joins;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> Join<X, Y> join(SingularAttribute<? super X, Y> singularAttribute) {
+		return join( singularAttribute, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> Join<X, Y> join(SingularAttribute<? super X, Y> attribute, JoinType jt) {
+		if ( ! canBeJoinSource() ) {
+			throw illegalJoin();
+		}
+
+		Join<X, Y> join = constructJoin( attribute, jt );
+		joinScope.addJoin( join );
+		return join;
+	}
+
+	private <Y> JoinImplementor<X, Y> constructJoin(SingularAttribute<? super X, Y> attribute, JoinType jt) {
+		if ( Type.PersistenceType.BASIC.equals( attribute.getType().getPersistenceType() ) ) {
+			throw new BasicPathUsageException( "Cannot join to attribute of basic type", attribute );
+        }
+
+		// 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();
+		return new SingularAttributeJoin<X,Y>(
+				queryBuilder(),
+				attributeType,
+				this,
+				attribute,
+				jt
+		);
+	}
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> CollectionJoin<X, Y> join(CollectionAttribute<? super X, Y> collection) {
+		return join( collection, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> CollectionJoin<X, Y> join(CollectionAttribute<? super X, Y> collection, JoinType jt) {
+		if ( ! canBeJoinSource() ) {
+			throw illegalJoin();
+		}
+
+		final CollectionJoin<X, Y> join = constructJoin( collection, jt );
+		joinScope.addJoin( join );
+		return join;
+	}
+
+	private <Y> CollectionJoinImplementor<X, Y> constructJoin(CollectionAttribute<? super X, Y> collection, JoinType jt) {
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
+		}
+
+		// TODO : runtime check that the attribute in fact belongs to this From's model/bindable
+
+		final Class<Y> attributeType = collection.getBindableJavaType();
+		return new CollectionAttributeJoin<X, Y>(
+				queryBuilder(),
+				attributeType,
+				this,
+				collection,
+				jt
+		);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> SetJoin<X, Y> join(SetAttribute<? super X, Y> set) {
+		return join( set, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> SetJoin<X, Y> join(SetAttribute<? super X, Y> set, JoinType jt) {
+		if ( ! canBeJoinSource() ) {
+			throw illegalJoin();
+		}
+
+		final SetJoin<X, Y> join = constructJoin( set, jt );
+		joinScope.addJoin( join );
+		return join;
+	}
+
+	private <Y> SetJoinImplementor<X, Y> constructJoin(SetAttribute<? super X, Y> set, JoinType jt) {
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
+		}
+
+		// TODO : runtime check that the attribute in fact belongs to this From's model/bindable
+
+		final Class<Y> attributeType = set.getBindableJavaType();
+		return new SetAttributeJoin<X,Y>( queryBuilder(), attributeType, this, set, jt );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list) {
+		return join( list, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list, JoinType jt) {
+		if ( ! canBeJoinSource() ) {
+			throw illegalJoin();
+		}
+
+		final ListJoin<X, Y> join = constructJoin( list, jt );
+		joinScope.addJoin( join );
+		return join;
+	}
+
+	private  <Y> ListJoinImplementor<X, Y> constructJoin(ListAttribute<? super X, Y> list, JoinType jt) {
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
+		}
+
+		// TODO : runtime check that the attribute in fact belongs to this From's model/bindable
+
+		final Class<Y> attributeType = list.getBindableJavaType();
+		return new ListAttributeJoin<X,Y>( queryBuilder(), attributeType, this, list, jt );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <K, V> MapJoin<X, K, V> join(MapAttribute<? super X, K, V> map) {
+		return join( map, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <K, V> MapJoin<X, K, V> join(MapAttribute<? super X, K, V> map, JoinType jt) {
+		if ( ! canBeJoinSource() ) {
+			throw illegalJoin();
+		}
+
+		final MapJoin<X, K, V> join = constructJoin( map, jt );
+		joinScope.addJoin( join );
+		return join;
+	}
+
+	private <K, V> MapJoinImplementor<X, K, V> constructJoin(MapAttribute<? super X, K, V> map, JoinType jt) {
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
+		}
+
+		// TODO : runtime check that the attribute in fact belongs to this From's model/bindable
+
+		final Class<V> attributeType = map.getBindableJavaType();
+		return new MapAttributeJoin<X, K, V>( queryBuilder(), attributeType, this, map, jt );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <X,Y> Join<X, Y> join(String attributeName) {
+		return join( attributeName, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <X,Y> Join<X, Y> join(String attributeName, JoinType jt) {
+		if ( ! canBeJoinSource() ) {
+			throw illegalJoin();
+		}
+
+		if ( jt.equals( JoinType.RIGHT ) ) {
+			throw new UnsupportedOperationException( "RIGHT JOIN not supported" );
+		}
+
+		final Attribute<X,?> attribute = (Attribute<X, ?>) locateAttribute( attributeName );
+		if ( attribute.isCollection() ) {
+			final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
+			if ( PluralAttribute.CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) {
+				return (Join<X,Y>) join( (CollectionAttribute) attribute, jt );
+			}
+			else if ( PluralAttribute.CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
+				return (Join<X,Y>) join( (ListAttribute) attribute, jt );
+			}
+			else if ( PluralAttribute.CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
+				return (Join<X,Y>) join( (SetAttribute) attribute, jt );
+			}
+			else {
+				return (Join<X,Y>) join( (MapAttribute) attribute, jt );
+			}
+		}
+		else {
+			return (Join<X,Y>) join( (SingularAttribute)attribute, jt );
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <X,Y> CollectionJoin<X, Y> joinCollection(String attributeName) {
+		return joinCollection( attributeName, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <X,Y> CollectionJoin<X, Y> joinCollection(String attributeName, JoinType jt) {
+		final Attribute<X,?> attribute = (Attribute<X, ?>) locateAttribute( attributeName );
+		if ( ! attribute.isCollection() ) {
+            throw new IllegalArgumentException( "Requested attribute was not a collection" );
+		}
+
+		final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
+		if ( ! PluralAttribute.CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) {
+            throw new IllegalArgumentException( "Requested attribute was not a collection" );
+		}
+
+		return (CollectionJoin<X,Y>) join( (CollectionAttribute) attribute, jt );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <X,Y> SetJoin<X, Y> joinSet(String attributeName) {
+		return joinSet( attributeName, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <X,Y> SetJoin<X, Y> joinSet(String attributeName, JoinType jt) {
+		final Attribute<X,?> attribute = (Attribute<X, ?>) locateAttribute( attributeName );
+		if ( ! attribute.isCollection() ) {
+            throw new IllegalArgumentException( "Requested attribute was not a set" );
+		}
+
+		final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
+		if ( ! PluralAttribute.CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
+            throw new IllegalArgumentException( "Requested attribute was not a set" );
+		}
+
+		return (SetJoin<X,Y>) join( (SetAttribute) attribute, jt );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <X,Y> ListJoin<X, Y> joinList(String attributeName) {
+		return joinList( attributeName, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <X,Y> ListJoin<X, Y> joinList(String attributeName, JoinType jt) {
+		final Attribute<X,?> attribute = (Attribute<X, ?>) locateAttribute( attributeName );
+		if ( ! attribute.isCollection() ) {
+            throw new IllegalArgumentException( "Requested attribute was not a list" );
+		}
+
+		final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
+		if ( ! PluralAttribute.CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
+            throw new IllegalArgumentException( "Requested attribute was not a list" );
+		}
+
+		return (ListJoin<X,Y>) join( (ListAttribute) attribute, jt );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public <X, K, V> MapJoin<X, K, V> joinMap(String attributeName) {
+		return joinMap( attributeName, DEFAULT_JOIN_TYPE );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <X, K, V> MapJoin<X, K, V> joinMap(String attributeName, JoinType jt) {
+		final Attribute<X,?> attribute = (Attribute<X, ?>) locateAttribute( attributeName );
+		if ( ! attribute.isCollection() ) {
+            throw new IllegalArgumentException( "Requested attribute was not a map" );
+		}
+
+		final PluralAttribute pluralAttribute = ( PluralAttribute ) attribute;
+		if ( ! PluralAttribute.CollectionType.MAP.equals( pluralAttribute.getCollectionType() ) ) {
+            throw new IllegalArgumentException( "Requested attribute was not a map" );
+		}
+
+		return (MapJoin<X,K,V>) join( (MapAttribute) attribute, jt );
+	}
+
+
+	// FETCHES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+	protected boolean canBeFetchSource() {
+		// the conditions should be the same...
+		return canBeJoinSource();
+	}
+
+	private RuntimeException illegalFetch() {
+		return new IllegalArgumentException(
+				"Collection of values [" + getPathIdentifier() + "] cannot be source of a fetch"
+		);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Set<Fetch<X, ?>> getFetches() {
+		return fetches;
+	}
+
+	public <Y> Fetch<X, Y> fetch(SingularAttribute<? super X, Y> singularAttribute) {
+		return fetch( singularAttribute, DEFAULT_JOIN_TYPE );
+	}
+
+	public <Y> Fetch<X, Y> fetch(SingularAttribute<? super X, Y> attribute, JoinType jt) {
+		if ( ! canBeFetchSource() ) {
+			throw illegalFetch();
+		}
+
+		Fetch<X, Y> fetch = constructJoin( attribute, jt );
+		joinScope.addFetch( fetch );
+		return fetch;
+	}
+
+	public <Y> Fetch<X, Y> fetch(PluralAttribute<? super X, ?, Y> pluralAttribute) {
+		return fetch( pluralAttribute, DEFAULT_JOIN_TYPE );
+	}
+
+	public <Y> Fetch<X, Y> fetch(PluralAttribute<? super X, ?, Y> pluralAttribute, JoinType jt) {
+		if ( ! canBeFetchSource() ) {
+			throw illegalFetch();
+		}
+
+		final Fetch<X, Y> fetch;
+		// TODO : combine Fetch and Join hierarchies (JoinImplementor extends Join,Fetch???)
+		if ( PluralAttribute.CollectionType.COLLECTION.equals( pluralAttribute.getCollectionType() ) ) {
+			fetch = constructJoin( (CollectionAttribute<X,Y>) pluralAttribute, jt );
+		}
+		else if ( PluralAttribute.CollectionType.LIST.equals( pluralAttribute.getCollectionType() ) ) {
+			fetch = constructJoin( (ListAttribute<X,Y>) pluralAttribute, jt );
+		}
+		else if ( PluralAttribute.CollectionType.SET.equals( pluralAttribute.getCollectionType() ) ) {
+			fetch = constructJoin( (SetAttribute<X,Y>) pluralAttribute, jt );
+		}
+		else {
+			fetch = constructJoin( (MapAttribute<X,?,Y>) pluralAttribute, jt );
+		}
+		joinScope.addFetch( fetch );
+		return fetch;
+	}
+
+	public <X,Y> Fetch<X, Y> fetch(String attributeName) {
+		return fetch( attributeName, DEFAULT_JOIN_TYPE );
+	}
+
+	@SuppressWarnings({ "unchecked" })
+	public <X,Y> Fetch<X, Y> fetch(String attributeName, JoinType jt) {
+		if ( ! canBeFetchSource() ) {
+			throw illegalFetch();
+		}
+
+		Attribute<X,?> attribute = (Attribute<X, ?>) locateAttribute( attributeName );
+		if ( attribute.isCollection() ) {
+			return (Fetch<X, Y>) fetch( (PluralAttribute) attribute, jt );
+		}
+		else {
+			return (Fetch<X, Y>) fetch( (SingularAttribute) attribute, jt );
+		}
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractJoinImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,103 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+
+import javax.persistence.criteria.From;
+import javax.persistence.criteria.JoinType;
+import javax.persistence.metamodel.Attribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+import org.hibernate.ejb.criteria.JoinImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractJoinImpl<Z, X>
+		extends AbstractFromImpl<Z, X>
+		implements JoinImplementor<Z,X>, Serializable {
+
+	private final Attribute<? super Z, ?> joinAttribute;
+	private final JoinType joinType;
+
+	public AbstractJoinImpl(
+			CriteriaBuilderImpl criteriaBuilder,
+			PathSource<Z> pathSource,
+			Attribute<? super Z, X> joinAttribute,
+			JoinType joinType) {
+		this( criteriaBuilder, joinAttribute.getJavaType(), pathSource, joinAttribute, joinType );
+	}
+
+	public AbstractJoinImpl(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<X> javaType,
+			PathSource<Z> pathSource,
+			Attribute<? super Z, ?> joinAttribute,
+			JoinType joinType) {
+		super( criteriaBuilder, javaType, pathSource );
+		this.joinAttribute = joinAttribute;
+		this.joinType = joinType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Attribute<? super Z, ?> getAttribute() {
+		return joinAttribute;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public JoinType getJoinType() {
+		return joinType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public From<?, Z> getParent() {
+		// this cast should be ok by virtue of our constructors...
+		return (From<?, Z>) getPathSource();
+	}
+
+	public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		prepareAlias( renderingContext );
+		( (FromImplementor) getParent() ).prepareAlias( renderingContext );
+		return getParent().getAlias() + '.' + getAttribute().getName() + " as " + getAlias();
+	}
+
+
+	public JoinImplementor<Z, X> correlateTo(CriteriaSubqueryImpl subquery) {
+		return (JoinImplementor<Z, X>) super.correlateTo( subquery );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/AbstractPathImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,263 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Path;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.ParameterRegistry;
+import org.hibernate.ejb.criteria.PathImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+import org.hibernate.ejb.criteria.expression.ExpressionImpl;
+import org.hibernate.ejb.criteria.expression.PathTypeExpression;
+
+/**
+ * Convenience base class for various {@link Path} implementors.
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractPathImpl<X>
+		extends ExpressionImpl<X>
+		implements Path<X>, PathImplementor<X>, Serializable {
+
+	private final PathSource pathSource;
+	private final Expression<Class<? extends X>> typeExpression;
+	private Map<String,Path> attributePathRegistry;
+
+	/**
+	 * Constructs a basic path instance.
+	 *
+	 * @param criteriaBuilder The criteria builder
+	 * @param javaType The java type of this path
+	 * @param pathSource The source (or origin) from which this path originates
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public AbstractPathImpl(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<X> javaType,
+			PathSource pathSource) {
+		super( criteriaBuilder, javaType );
+		this.pathSource = pathSource;
+		this.typeExpression =  new PathTypeExpression( queryBuilder(), getJavaType() );
+	}
+
+	public PathSource getPathSource() {
+		return pathSource;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public PathSource<?> getParentPath() {
+        return getPathSource();
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public Expression<Class<? extends X>> type() {
+		return typeExpression;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getPathIdentifier() {
+		return getPathSource().getPathIdentifier() + "." + getAttribute().getName();
+	}
+
+	protected abstract boolean canBeDereferenced();
+
+	protected final RuntimeException illegalDereference() {
+		return new IllegalArgumentException(
+				"Illegal attempt to dereference path source [" + getPathSource().getPathIdentifier() + "]"
+		);
+	}
+
+	protected final RuntimeException unknownAttribute(String attributeName) {
+		return new IllegalArgumentException(
+				"Unable to resolve attribute [" + attributeName + "] against path [" +
+						getPathSource().getPathIdentifier() + "]"
+		);
+	}
+
+	protected final Path resolveCachedAttributePath(String attributeName) {
+		return attributePathRegistry == null
+				? null
+				: attributePathRegistry.get( attributeName );
+	}
+
+	protected final void registerAttributePath(String attributeName, Path path) {
+		if ( attributePathRegistry == null ) {
+			attributePathRegistry = new HashMap<String,Path>();
+		}
+		attributePathRegistry.put( attributeName, path );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <Y> Path<Y> get(SingularAttribute<? super X, Y> attribute) {
+		if ( ! canBeDereferenced() ) {
+			throw illegalDereference();
+		}
+
+		SingularAttributePath<Y> path = (SingularAttributePath<Y>) resolveCachedAttributePath( attribute.getName() );
+		if ( path == null ) {
+			path = new SingularAttributePath<Y>( queryBuilder(), attribute.getJavaType(), this, attribute );
+			registerAttributePath( attribute.getName(), path );
+		}
+		return path;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <E, C extends Collection<E>> Expression<C> get(PluralAttribute<X, C, E> attribute) {
+		if ( ! canBeDereferenced() ) {
+			throw illegalDereference();
+		}
+
+		PluralAttributePath<C> path = (PluralAttributePath<C>) resolveCachedAttributePath( attribute.getName() );
+		if ( path == null ) {
+			path = new PluralAttributePath<C>( queryBuilder(), this, attribute );
+			registerAttributePath( attribute.getName(), path );
+		}
+		return path;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <K, V, M extends Map<K, V>> Expression<M> get(MapAttribute<X, K, V> attribute) {
+		if ( ! canBeDereferenced() ) {
+			throw illegalDereference();
+		}
+
+		PluralAttributePath path = (PluralAttributePath) resolveCachedAttributePath( attribute.getName() );
+		if ( path == null ) {
+			path = new PluralAttributePath( queryBuilder(), this, attribute );
+			registerAttributePath( attribute.getName(), path );
+		}
+		return path;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public <Y> Path<Y> get(String attributeName) {
+		if ( ! canBeDereferenced() ) {
+			throw illegalDereference();
+		}
+
+		final Attribute attribute = locateAttribute( attributeName );
+
+		if ( attribute.isCollection() ) {
+			final PluralAttribute<X,Y,?> pluralAttribute = (PluralAttribute<X,Y,?>) attribute;
+			if ( PluralAttribute.CollectionType.MAP.equals( pluralAttribute.getCollectionType() ) ) {
+				return (PluralAttributePath<Y>) get( (MapAttribute<X,?,?>) pluralAttribute );
+			}
+			else {
+				return (PluralAttributePath<Y>) get( (PluralAttribute) pluralAttribute );
+			}
+		}
+		else {
+			return get( (SingularAttribute<X,Y>) attribute );
+		}
+	}
+
+	/**
+	 * Get the attribute by name from the underlying model.  This allows subclasses to
+	 * define exactly how the attribute is derived.
+	 *
+	 * @param attributeName The name of the attribute to locate
+	 *
+	 * @return The attribute; should never return null.
+	 *
+	 * @throws IllegalArgumentException If no such attribute exists
+	 */
+	protected  final Attribute locateAttribute(String attributeName) {
+		final Attribute attribute = locateAttributeInternal( attributeName );
+		if ( attribute == null ) {
+			throw unknownAttribute( attributeName );
+		}
+		return attribute;
+	}
+
+	/**
+	 * Get the attribute by name from the underlying model.  This allows subclasses to
+	 * define exactly how the attribute is derived.  Called from {@link #locateAttribute}
+	 * which also applies nullness checking for proper error reporting.
+	 *
+	 * @param attributeName The name of the attribute to locate
+	 *
+	 * @return The attribute; may be null.
+	 *
+	 * @throws IllegalArgumentException If no such attribute exists
+	 */
+	protected abstract Attribute locateAttributeInternal(String attributeName);
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void registerParameters(ParameterRegistry registry) {
+		// none to register
+	}
+
+	public void prepareAlias(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		// Make sure we delegate up to our source (eventually up to the path root) to
+		// prepare the path properly.
+		getPathSource().prepareAlias( renderingContext );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		getPathSource().prepareAlias( renderingContext );
+		return getPathSource().getPathIdentifier() + "." + getAttribute().getName();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		return render( renderingContext );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/CollectionAttributeJoin.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,80 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+import javax.persistence.criteria.JoinType;
+import javax.persistence.metamodel.CollectionAttribute;
+
+import org.hibernate.ejb.criteria.CollectionJoinImplementor;
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+import org.hibernate.ejb.criteria.PathImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class CollectionAttributeJoin<O,E>
+		extends PluralAttributeJoinSupport<O,Collection<E>,E>
+		implements CollectionJoinImplementor<O,E>, Serializable {
+	public CollectionAttributeJoin(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<E> javaType,
+			PathSource<O> pathSource,
+			CollectionAttribute<? super O, E> joinAttribute,
+			JoinType joinType) {
+		super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType );
+	}
+
+	public final CollectionAttributeJoin<O,E> correlateTo(CriteriaSubqueryImpl subquery) {
+		return (CollectionAttributeJoin<O,E>) super.correlateTo( subquery );
+	}
+
+	@Override
+	public CollectionAttribute<? super O, E> getAttribute() {
+		return (CollectionAttribute<? super O, E>) super.getAttribute();
+	}
+
+	@Override
+	public CollectionAttribute<? super O, E> getModel() {
+		return getAttribute();
+	}
+
+	@Override
+	protected FromImplementor<O, E> createCorrelationDelegate() {
+		return new CollectionAttributeJoin<O,E>(
+				queryBuilder(),
+				getJavaType(),
+				(PathImplementor<O>) getParentPath(),
+				getAttribute(),
+				getJoinType()
+		);
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/ListAttributeJoin.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,91 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.JoinType;
+import javax.persistence.metamodel.ListAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+import org.hibernate.ejb.criteria.ListJoinImplementor;
+import org.hibernate.ejb.criteria.PathImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+import org.hibernate.ejb.criteria.expression.ListIndexExpression;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class ListAttributeJoin<O,E>
+		extends PluralAttributeJoinSupport<O, List<E>,E>
+		implements ListJoinImplementor<O,E>, Serializable {
+
+	public ListAttributeJoin(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<E> javaType,
+			PathSource<O> pathSource,
+			ListAttribute<? super O, E> joinAttribute,
+			JoinType joinType) {
+		super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Expression<Integer> index() {
+		return new ListIndexExpression( queryBuilder(), this, getAttribute() );
+	}
+
+	@Override
+	public ListAttribute<? super O, E> getAttribute() {
+		return (ListAttribute<? super O, E>) super.getAttribute();
+	}
+
+	@Override
+	public ListAttribute<? super O, E> getModel() {
+		return getAttribute();
+	}
+
+	@Override
+	public final ListAttributeJoin<O,E> correlateTo(CriteriaSubqueryImpl subquery) {
+		return (ListAttributeJoin<O,E>) super.correlateTo( subquery );
+	}
+
+	@Override
+	protected FromImplementor<O, E> createCorrelationDelegate() {
+		return new ListAttributeJoin<O,E>(
+				queryBuilder(),
+				getJavaType(),
+				(PathImplementor<O>) getParentPath(),
+				getAttribute(),
+				getJoinType()
+		);
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapAttributeJoin.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,117 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import java.util.Map;
+
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.JoinType;
+import javax.persistence.criteria.Path;
+import javax.persistence.metamodel.MapAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+import org.hibernate.ejb.criteria.MapJoinImplementor;
+import org.hibernate.ejb.criteria.PathImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+import org.hibernate.ejb.criteria.expression.MapEntryExpression;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class MapAttributeJoin<O,K,V>
+		extends PluralAttributeJoinSupport<O, Map<K,V>, V>
+		implements MapJoinImplementor<O,K,V>, Serializable {
+
+	public MapAttributeJoin(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<V> javaType,
+			PathSource<O> pathSource,
+			MapAttribute<? super O, K, V> joinAttribute,
+			JoinType joinType) {
+		super( criteriaBuilder, javaType, pathSource, joinAttribute, 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();
+	}
+
+	@Override
+	public final MapAttributeJoin<O,K,V> correlateTo(CriteriaSubqueryImpl subquery) {
+		return (MapAttributeJoin<O,K,V>) super.correlateTo( subquery );
+	}
+
+	@Override
+	protected FromImplementor<O, V> createCorrelationDelegate() {
+		return new MapAttributeJoin<O,K,V>(
+				queryBuilder(),
+				getJavaType(),
+				(PathImplementor<O>) getParentPath(),
+				getAttribute(),
+				getJoinType()
+		);
+	}
+
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Path<V> value() {
+		return this;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public Expression<Map.Entry<K, V>> entry() {
+		return new MapEntryExpression( queryBuilder(), Map.Entry.class, this, getAttribute() );
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@SuppressWarnings({ "unchecked" })
+	public Path<K> key() {
+		final MapKeyHelpers.MapKeySource<K,V> mapKeySource = new MapKeyHelpers.MapKeySource<K,V>(
+				queryBuilder(),
+				getAttribute().getJavaType(),
+				this,
+				getAttribute()
+		);
+		final MapKeyHelpers.MapKeyAttribute mapKeyAttribute = new MapKeyHelpers.MapKeyAttribute( queryBuilder(), getAttribute() );
+		return new MapKeyHelpers.MapKeyPath( queryBuilder(), mapKeySource, mapKeyAttribute );
+	}
+
+}

Copied: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java (from rev 18403, core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/MapKeyHelpers.java)
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/MapKeyHelpers.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,288 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009 by Red Hat Inc and/or its affiliates or by
+ * third-party contributors as indicated by either @author tags or express
+ * copyright attribution statements applied by the authors.  All
+ * third-party contributions are distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import java.lang.reflect.Member;
+import java.util.Map;
+import javax.persistence.criteria.Join;
+import javax.persistence.criteria.MapJoin;
+import javax.persistence.criteria.Path;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Bindable;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.MapJoinImplementor;
+import org.hibernate.ejb.criteria.PathImplementor;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * {@link MapJoin#key} poses a number of implementation difficulties in terms of the type signatures
+ * amongst the {@link Path}, {@link Join} and {@link Attribute} reference at play.  The implementations found here
+ * provide that bridge.
+ *
+ * @author Steve Ebersole
+ */
+public class MapKeyHelpers {
+
+	/**
+	 * Models a path to a map key.  This is the actual return used from {@link MapJoin#key}
+	 *
+	 * @param <K> The type of the map key.
+	 */
+	public static class MapKeyPath<K>
+			extends AbstractPathImpl<K>
+			implements PathImplementor<K>, Serializable {
+
+		private final MapKeyAttribute<K> mapKeyAttribute;
+
+		public MapKeyPath(
+				CriteriaBuilderImpl criteriaBuilder,
+				MapKeySource<K,?> source,
+				MapKeyAttribute<K> mapKeyAttribute) {
+			super( criteriaBuilder, mapKeyAttribute.getJavaType(), source );
+			this.mapKeyAttribute = mapKeyAttribute;
+		}
+
+		@Override
+		public MapKeySource getPathSource() {
+			return (MapKeySource) super.getPathSource();
+		}
+
+		public MapKeyAttribute<K> getAttribute() {
+			return mapKeyAttribute;
+		}
+
+		private boolean isBasicTypeKey() {
+			return Attribute.PersistentAttributeType.BASIC ==
+					mapKeyAttribute.getPersistentAttributeType();
+		}
+
+		@Override
+		protected boolean canBeDereferenced() {
+			return ! isBasicTypeKey();
+		}
+
+		@Override
+		protected Attribute locateAttributeInternal(String attributeName) {
+			if ( ! canBeDereferenced() ) {
+				throw new IllegalArgumentException(
+						"Map key [" + getPathSource().getPathIdentifier() + "] cannot be dereferenced"
+				);
+			}
+			throw new UnsupportedOperationException( "Not yet supported!" );
+		}
+
+		public Bindable<K> getModel() {
+			return mapKeyAttribute;
+		}
+	}
+
+	/**
+	 * Defines a {@link Path} for the map which can then be used to represent the source of the
+	 * map key "attribute".
+	 *
+	 * @param <K> The map key type
+	 * @param <V> The map value type
+	 */
+	public static class MapKeySource<K,V>
+			extends AbstractPathImpl<Map<K, V>>
+			implements PathImplementor<Map<K, V>>, Serializable {
+
+		private final MapAttribute<?,K,V> mapAttribute;
+		private final MapJoinImplementor<?,K,V> mapJoin;
+
+		public MapKeySource(
+				CriteriaBuilderImpl criteriaBuilder,
+				Class<Map<K, V>> javaType,
+				MapJoinImplementor<?,K,V> mapJoin,
+				MapAttribute<?,K,V> attribute) {
+			super( criteriaBuilder, javaType, null );
+			this.mapJoin = mapJoin;
+			this.mapAttribute = attribute;
+		}
+
+		public MapAttribute<?,K,V> getAttribute() {
+			return mapAttribute;
+		}
+
+		@SuppressWarnings({ "unchecked" })
+		public Bindable<Map<K, V>> getModel() {
+			// TODO : ok???  the attribute is in fact bindable, but its type signature is different
+			return (Bindable<Map<K, V>>) mapAttribute;
+		}
+
+		@Override
+		public PathImplementor<?> getParentPath() {
+			return (PathImplementor<?>) mapJoin.getParentPath();
+		}
+
+		@Override
+		protected boolean canBeDereferenced() {
+			return false;
+		}
+
+		@Override
+		protected Attribute locateAttributeInternal(String attributeName) {
+			throw new IllegalArgumentException( "Map [" + mapJoin.getPathIdentifier() + "] cannot be dereferenced" );
+		}
+
+	}
+
+	/**
+	 * Disallow instantiation
+	 */
+	private MapKeyHelpers() {
+	}
+
+	/**
+	 * Defines an {@link javax.persistence.metamodel.Attribute} modelling of a map-key.
+	 *
+	 * @param <K> The type of the map key
+	 */
+	public static class MapKeyAttribute<K>
+			implements SingularAttribute<Map<K,?>,K>, Bindable<K>, Serializable {
+		private final MapAttribute<?,K,?> attribute;
+		private final CollectionPersister mapPersister;
+		private final org.hibernate.type.Type mapKeyType;
+		private final Type<K> jpaType;
+		private final BindableType jpaBindableType;
+		private final Class<K> jpaBinableJavaType;
+		private final PersistentAttributeType persistentAttributeType;
+
+		public MapKeyAttribute(CriteriaBuilderImpl criteriaBuilder, MapAttribute<?, K, ?> attribute) {
+			this.attribute = attribute;
+			this.jpaType = attribute.getKeyType();
+			this.jpaBinableJavaType = attribute.getKeyJavaType();
+			this.jpaBindableType = Type.PersistenceType
+					.ENTITY.equals( jpaType.getPersistenceType() )
+					? BindableType.ENTITY_TYPE
+					: BindableType.SINGULAR_ATTRIBUTE;
+
+			String guessedRoleName = determineRole( attribute );
+			SessionFactoryImplementor sfi = (SessionFactoryImplementor)
+					criteriaBuilder.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 + "]" );
+			}
+
+			this.persistentAttributeType = mapKeyType.isEntityType()
+					? PersistentAttributeType.MANY_TO_ONE
+					: mapKeyType.isComponentType()
+							? PersistentAttributeType.EMBEDDED
+							: PersistentAttributeType.BASIC;
+		}
+
+		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() {
+			return persistentAttributeType;
+		}
+
+		/**
+		 * {@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 Type<K> getType() {
+			return jpaType;
+		}
+
+		public BindableType getBindableType() {
+			return jpaBindableType;
+		}
+
+		public Class<K> getBindableJavaType() {
+			return jpaBinableJavaType;
+		}
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributeJoinSupport.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributeJoinSupport.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributeJoinSupport.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,86 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import javax.persistence.criteria.JoinType;
+import javax.persistence.criteria.PluralJoin;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Bindable;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.Type;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.PathSource;
+
+/**
+ * Support for defining joins to plural attributes (JPA requires typing based on
+ * the specific collection type so we cannot really implement all support in a
+ * single class)
+ *
+ * @author Steve Ebersole
+ */
+public abstract class PluralAttributeJoinSupport<O,C,E>
+		extends AbstractJoinImpl<O,E>
+		implements PluralJoin<O,C,E> {
+
+	public PluralAttributeJoinSupport(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<E> javaType,
+			PathSource<O> pathSource,
+			Attribute<? super O,?> joinAttribute,
+			JoinType joinType) {
+		super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType );
+	}
+
+	@Override
+	public PluralAttribute<? super O, C, E> getAttribute() {
+		return (PluralAttribute<? super O, C, E>) super.getAttribute();
+	}
+
+	public PluralAttribute<? super O, C, E> getModel() {
+		return getAttribute();
+	}
+
+	@Override
+	protected ManagedType<E> locateManagedType() {
+		return isBasicCollection()
+				? null
+				: (ManagedType<E>) getAttribute().getElementType();
+	}
+
+	public boolean isBasicCollection() {
+		return Type.PersistenceType.BASIC.equals( getAttribute().getElementType().getPersistenceType() );
+	}
+
+	@Override
+	protected boolean canBeDereferenced() {
+		return !isBasicCollection();
+	}
+
+	@Override
+	protected boolean canBeJoinSource() {
+		return !isBasicCollection();
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributePath.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributePath.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/PluralAttributePath.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,94 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Bindable;
+import javax.persistence.metamodel.PluralAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.PathSource;
+import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.persister.collection.CollectionPersister;
+
+/**
+ * Models a path for a {@link PluralAttribute} generally obtained from a
+ * {@link javax.persistence.criteria.Path#get} call
+ *
+ * @author Steve Ebersole
+ */
+public class PluralAttributePath<X> extends AbstractPathImpl<X> implements Serializable {
+	private final PluralAttribute<?,X,?> attribute;
+	private final CollectionPersister persister;
+
+	public PluralAttributePath(
+			CriteriaBuilderImpl criteriaBuilder,
+			PathSource source,
+			PluralAttribute<?,X,?> attribute) {
+		super( criteriaBuilder, attribute.getJavaType(), source );
+		this.attribute = attribute;
+		this.persister = resolvePersister( criteriaBuilder, attribute );
+	}
+
+	private static CollectionPersister resolvePersister(CriteriaBuilderImpl criteriaBuilder, PluralAttribute attribute) {
+		SessionFactoryImplementor sfi = (SessionFactoryImplementor)
+				criteriaBuilder.getEntityManagerFactory().getSessionFactory();
+		return sfi.getCollectionPersister( resolveRole( attribute ) );
+	}
+
+	private static String resolveRole(PluralAttribute attribute) {
+		return attribute.getDeclaringType().getJavaType().getName() +
+				'.' + attribute.getName();
+	}
+
+	public PluralAttribute<?,X,?> getAttribute() {
+		return attribute;
+	}
+
+	@SuppressWarnings({ "UnusedDeclaration" })
+	public CollectionPersister getPersister() {
+		return persister;
+	}
+
+	@Override
+	protected boolean canBeDereferenced() {
+		// cannot be dereferenced
+		return false;
+	}
+
+	@Override
+	protected Attribute locateAttributeInternal(String attributeName) {
+		throw new IllegalArgumentException( "Plural attribute paths cannot be further dereferenced" );
+	}
+
+	public Bindable<X> getModel() {
+		// the issue here is the parameterized type; X is the collection
+		// type (Map, Set, etc) while the "bindable" for a collection is the
+		// elements.
+		//
+		// TODO : throw exception instead?
+		return null;
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/RootImpl.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,93 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.EntityType;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class RootImpl<X> extends AbstractFromImpl<X,X> implements Root<X>, Serializable {
+	private final EntityType<X> entityType;
+
+	public RootImpl(
+			CriteriaBuilderImpl criteriaBuilder,
+			EntityType<X> entityType) {
+		super( criteriaBuilder, entityType.getJavaType() );
+		this.entityType = entityType;
+	}
+
+	public EntityType<X> getEntityType() {
+		return entityType;
+	}
+
+	public EntityType<X> getModel() {
+		return getEntityType();
+	}
+
+	@Override
+	protected FromImplementor<X, X> createCorrelationDelegate() {
+		return new RootImpl<X>( queryBuilder(), getEntityType() );
+	}
+
+	@Override
+	public RootImpl<X> correlateTo(CriteriaSubqueryImpl subquery) {
+		return (RootImpl<X>) super.correlateTo( subquery );
+	}
+
+	@Override
+	protected boolean canBeJoinSource() {
+		return true;
+	}
+
+	public String renderTableExpression(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		prepareAlias( renderingContext );
+		return getModel().getName() + " as " + getAlias();
+	}
+
+	@Override
+	public String getPathIdentifier() {
+		return getAlias();
+	}
+
+	@Override
+	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		prepareAlias( renderingContext );
+		return getAlias();
+	}
+
+	@Override
+	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {
+		return render( renderingContext );
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SetAttributeJoin.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,82 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.criteria.JoinType;
+import javax.persistence.metamodel.SetAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+import org.hibernate.ejb.criteria.PathImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+import org.hibernate.ejb.criteria.SetJoinImplementor;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class SetAttributeJoin<O,E>
+		extends PluralAttributeJoinSupport<O, Set<E>,E>
+		implements SetJoinImplementor<O,E>, Serializable {
+
+	public SetAttributeJoin(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<E> javaType,
+			PathSource<O> pathSource,
+			SetAttribute<? super O, E> joinAttribute,
+			JoinType joinType) {
+		super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType );
+	}
+
+	@Override
+	public SetAttribute<? super O, E> getAttribute() {
+		return (SetAttribute<? super O, E>) super.getAttribute();
+	}
+
+	@Override
+	public SetAttribute<? super O, E> getModel() {
+		return getAttribute();
+	}
+
+	@Override
+	public final SetAttributeJoin<O,E> correlateTo(CriteriaSubqueryImpl subquery) {
+		return (SetAttributeJoin<O,E>) super.correlateTo( subquery );
+	}
+
+	@Override
+	protected FromImplementor<O, E> createCorrelationDelegate() {
+		return new SetAttributeJoin<O,E>(
+				queryBuilder(),
+				getJavaType(),
+				(PathImplementor<O>) getParentPath(),
+				getAttribute(),
+				getJoinType()
+		);
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributeJoin.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,88 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import javax.persistence.criteria.JoinType;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Bindable;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.CriteriaSubqueryImpl;
+import org.hibernate.ejb.criteria.FromImplementor;
+import org.hibernate.ejb.criteria.PathSource;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class SingularAttributeJoin<Z,X> extends AbstractJoinImpl<Z,X> {
+	private final Bindable<X> model;
+
+	@SuppressWarnings({ "unchecked" })
+	public SingularAttributeJoin(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<X> javaType,
+			PathSource<Z> pathSource, 
+			SingularAttribute<? super Z, ?> joinAttribute,
+			JoinType joinType) {
+		super( criteriaBuilder, javaType, pathSource, joinAttribute, joinType );
+		this.model = (Bindable<X>) (
+				Attribute.PersistentAttributeType.EMBEDDED == joinAttribute.getPersistentAttributeType()
+						? joinAttribute
+						: criteriaBuilder.getEntityManagerFactory().getMetamodel().managedType( javaType )
+		);
+	}
+
+	@Override
+	public SingularAttribute<? super Z, ?> getAttribute() {
+		return (SingularAttribute<? super Z, ?>) super.getAttribute();
+	}
+
+	@Override
+	public SingularAttributeJoin<Z, X> correlateTo(CriteriaSubqueryImpl subquery) {
+		return (SingularAttributeJoin<Z, X>) super.correlateTo( subquery );
+	}
+
+	@Override
+	protected FromImplementor<Z, X> createCorrelationDelegate() {
+		return new SingularAttributeJoin<Z,X>(
+				queryBuilder(),
+				getJavaType(),
+				getPathSource(),
+				getAttribute(),
+				getJoinType()
+		);
+	}
+
+	@Override
+	protected boolean canBeJoinSource() {
+		return true;
+	}
+
+	public Bindable<X> getModel() {
+		return model;
+	}
+}

Added: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java	                        (rev 0)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/path/SingularAttributePath.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,105 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.path;
+
+import java.io.Serializable;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Bindable;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.IdentifiableType;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
+import org.hibernate.ejb.criteria.PathSource;
+
+/**
+ * Models a path for a {@link SingularAttribute} generally obtained from a
+ * {@link javax.persistence.criteria.Path#get(SingularAttribute)} call
+ *
+ * @author Steve Ebersole
+ */
+public class SingularAttributePath<X> extends AbstractPathImpl<X> implements Serializable {
+	private final SingularAttribute<?,X> attribute;
+	private final ManagedType<X> managedType;
+
+	@SuppressWarnings({ "unchecked" })
+	public SingularAttributePath(
+			CriteriaBuilderImpl criteriaBuilder,
+			Class<X> javaType,
+			PathSource pathSource,
+			SingularAttribute<?, X> attribute) {
+		super( criteriaBuilder, javaType, pathSource );
+		this.attribute = attribute;
+		this.managedType = resolveManagedType( attribute );
+	}
+
+	private ManagedType<X> resolveManagedType(SingularAttribute<?, X> attribute) {
+		if ( Attribute.PersistentAttributeType.BASIC == attribute.getPersistentAttributeType() ) {
+			return null;
+		}
+		else if ( Attribute.PersistentAttributeType.EMBEDDED == attribute.getPersistentAttributeType() ) {
+			return (EmbeddableType<X>) attribute.getType();
+		}
+		else {
+			return (IdentifiableType<X>) attribute.getType();
+//			return criteriaBuilder.getEntityManagerFactory()
+//					.getMetamodel()
+//					.managedType( javaType );
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public SingularAttribute<?, X> getAttribute() {
+		return attribute;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Bindable<X> getModel() {
+		return getAttribute();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected boolean canBeDereferenced() {
+		return managedType != null;
+	}
+
+	@Override
+	protected Attribute locateAttributeInternal(String attributeName) {
+		final Attribute attribute = managedType.getAttribute( attributeName );
+		// ManagedType.getAttribute should throw exception rather than return
+		// null, but just to be safe...
+		if ( attribute == null ) {
+			throw new IllegalArgumentException( "Could not resolve attribute named " + attributeName );
+		}
+		return attribute;
+	}
+}

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/BooleanAssertionPredicate.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -75,7 +75,7 @@
 	 * {@inheritDoc}
 	 */
 	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
-		final String operator = isNegated() ? " = " : " <> ";
+		final String operator = isNegated() ? " <> " : " = ";
 		final String assertionLiteral = assertedValue ? "true" : "false";
 
 		return ( (Renderable) expression ).render( renderingContext )

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/IsEmptyPredicate.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -28,8 +28,8 @@
 import org.hibernate.ejb.criteria.ParameterRegistry;
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
 import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
-import org.hibernate.ejb.criteria.expression.CollectionExpression;
 import org.hibernate.ejb.criteria.expression.UnaryOperatorExpression;
+import org.hibernate.ejb.criteria.path.PluralAttributePath;
 
 /**
  * Models an <tt>IS [NOT] EMPTY</tt> restriction
@@ -40,17 +40,17 @@
 		extends AbstractSimplePredicate
 		implements UnaryOperatorExpression<Boolean>, Serializable {
 
-	private final CollectionExpression<C> collectionExpression;
+	private final PluralAttributePath<C> collectionPath;
 
 	public IsEmptyPredicate(
 			CriteriaBuilderImpl criteriaBuilder,
-			CollectionExpression<C> collectionExpression) {
+			PluralAttributePath<C> collectionPath) {
 		super( criteriaBuilder );
-		this.collectionExpression = collectionExpression;
+		this.collectionPath = collectionPath;
 	}
 
-	public CollectionExpression<C> getOperand() {
-		return collectionExpression;
+	public PluralAttributePath<C> getOperand() {
+		return collectionPath;
 	}
 
 	public void registerParameters(ParameterRegistry registry) {

Modified: core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java
===================================================================
--- core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java	2010-01-07 17:45:29 UTC (rev 18435)
+++ core/trunk/entitymanager/src/main/java/org/hibernate/ejb/criteria/predicate/MemberOfPredicate.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -30,8 +30,8 @@
 import org.hibernate.ejb.criteria.CriteriaBuilderImpl;
 import org.hibernate.ejb.criteria.CriteriaQueryCompiler;
 import org.hibernate.ejb.criteria.Renderable;
-import org.hibernate.ejb.criteria.expression.CollectionExpression;
 import org.hibernate.ejb.criteria.expression.LiteralExpression;
+import org.hibernate.ejb.criteria.path.PluralAttributePath;
 
 /**
  * Models an <tt>[NOT] MEMBER OF</tt> restriction
@@ -43,30 +43,30 @@
 		implements Serializable {
 
 	private final Expression<E> elementExpression;
-	private final CollectionExpression<C> collectionExpression;
+	private final PluralAttributePath<C> collectionPath;
 
 	public MemberOfPredicate(
 			CriteriaBuilderImpl criteriaBuilder,
 			Expression<E> elementExpression,
-			CollectionExpression<C> collectionExpression) {
+			PluralAttributePath<C> collectionPath) {
 		super( criteriaBuilder );
 		this.elementExpression = elementExpression;
-		this.collectionExpression = collectionExpression;
+		this.collectionPath = collectionPath;
 	}
 
 	public MemberOfPredicate(
 			CriteriaBuilderImpl criteriaBuilder,
 			E element,
-			CollectionExpression<C> collectionExpression) {
+			PluralAttributePath<C> collectionPath) {
 		this(
 				criteriaBuilder,
 				new LiteralExpression<E>( criteriaBuilder, element ),
-				collectionExpression
+				collectionPath
 		);
 	}
 
-	public CollectionExpression<C> getCollectionExpression() {
-		return collectionExpression;
+	public PluralAttributePath<C> getCollectionPath() {
+		return collectionPath;
 	}
 
 	public Expression<E> getElementExpression() {
@@ -74,14 +74,14 @@
 	}
 
 	public void registerParameters(ParameterRegistry registry) {
-		Helper.possibleParameter( getCollectionExpression(), registry );
+		Helper.possibleParameter( getCollectionPath(), registry );
 		Helper.possibleParameter( getElementExpression(), registry );
 	}
 
 	public String render(CriteriaQueryCompiler.RenderingContext renderingContext) {
 		return ( (Renderable) elementExpression ).render( renderingContext )
 				+ ( isNegated() ? " not" : "" ) + " member of "
-				+ collectionExpression.render( renderingContext );
+				+ getCollectionPath().render( renderingContext );
 	}
 
 	public String renderProjection(CriteriaQueryCompiler.RenderingContext renderingContext) {

Added: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/ImplicitJoinTest.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/ImplicitJoinTest.java	                        (rev 0)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/criteria/paths/ImplicitJoinTest.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,62 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.criteria.paths;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Join;
+import javax.persistence.criteria.Root;
+
+import org.hibernate.ejb.metamodel.AbstractMetamodelSpecificTest;
+import org.hibernate.ejb.metamodel.LineItem;
+import org.hibernate.ejb.metamodel.LineItem_;
+import org.hibernate.ejb.metamodel.Order;
+import org.hibernate.ejb.metamodel.Order_;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public class ImplicitJoinTest extends AbstractMetamodelSpecificTest {
+
+	public void testImplicitJoinFromExplicitCollectionJoin() {
+		EntityManager em = getOrCreateEntityManager();
+		em.getTransaction().begin();
+
+		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
+		CriteriaQuery<Order> criteria = criteriaBuilder.createQuery( Order.class );
+		Root<Order> orderRoot = criteria.from( Order.class );
+		Join<Order, LineItem> lineItemsJoin = orderRoot.join( Order_.lineItems );
+		criteria.where( criteriaBuilder.lt( lineItemsJoin.get( LineItem_.quantity ), 2 ) );
+		criteria.select( orderRoot ).distinct( true );
+		TypedQuery<Order> query = em.createQuery( criteria );
+		query.getResultList();
+
+		em.getTransaction().commit();
+		em.close();
+	}
+}

Added: core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/AbstractMetamodelSpecificTest.java
===================================================================
--- core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/AbstractMetamodelSpecificTest.java	                        (rev 0)
+++ core/trunk/entitymanager/src/test/java/org/hibernate/ejb/metamodel/AbstractMetamodelSpecificTest.java	2010-01-07 17:58:37 UTC (rev 18436)
@@ -0,0 +1,42 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.ejb.metamodel;
+
+import org.hibernate.ejb.test.TestCase;
+
+/**
+ * TODO : javadoc
+ *
+ * @author Steve Ebersole
+ */
+public abstract class AbstractMetamodelSpecificTest extends TestCase {
+	@Override
+	public Class[] getAnnotatedClasses() {
+		return new Class[] {
+				Address.class, Alias.class, Country.class, CreditCard.class, Customer.class,
+				Info.class, LineItem.class, Order.class, Phone.class, Product.class,
+				ShelfLife.class, Spouse.class
+		};
+	}
+}



More information about the hibernate-commits mailing list