You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2009/06/26 08:34:35 UTC

svn commit: r788604 - in /openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria: CriteriaExpressionBuilder.java Joins.java PathImpl.java RootImpl.java SubqueryImpl.java

Author: faywang
Date: Fri Jun 26 06:34:34 2009
New Revision: 788604

URL: http://svn.apache.org/viewvc?rev=788604&view=rev
Log:
OPENJPA-1143: correlation join support

Modified:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java?rev=788604&r1=788603&r2=788604&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java Fri Jun 26 06:34:34 2009
@@ -49,8 +49,7 @@
  */
 public class CriteriaExpressionBuilder {
     
-    public QueryExpressions getQueryExpressions(ExpressionFactory factory, 
-        CriteriaQueryImpl q) {
+    public QueryExpressions getQueryExpressions(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         QueryExpressions exps = new QueryExpressions();
         //exps.setContexts(q.getContexts());
 
@@ -76,8 +75,7 @@
         return exps;
     }
 
-    protected void evalAccessPaths(QueryExpressions exps, 
-        ExpressionFactory factory, CriteriaQueryImpl q) {
+    protected void evalAccessPaths(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         Set<ClassMetaData> metas = new HashSet<ClassMetaData>();
         Set<Root<?>> roots = q.getRoots();
         if (roots != null) {
@@ -88,17 +86,14 @@
                     for (Join<?,?> join : root.getJoins()) {
                         Class<?> cls = join.getAttribute().getJavaType();
                         if (join.getAttribute().isAssociation()) {
-                            ClassMetaData meta = metamodel.repos.
-                                getMetaData(cls, null, true);
-                            PersistenceType type = metamodel.
-                                getPersistenceType(meta);
-                            if (type == PersistenceType.ENTITY ||
-                                type == PersistenceType.EMBEDDABLE) 
+                            ClassMetaData meta = metamodel.repos.getMetaData(cls, null, true);
+                            PersistenceType type = metamodel.getPersistenceType(meta);
+                            if (type == PersistenceType.ENTITY || type == PersistenceType.EMBEDDABLE) 
                                 metas.add(meta);
                         }
                     }
                     if (root.getFetches() != null) {
-                        for (Fetch fetch : root.getFetches()) {
+                        for (Fetch<?,?> fetch : root.getFetches()) {
                             metas.add(metamodel.repos.getMetaData(
                             fetch.getAttribute().getJavaType(), 
                             null, false));
@@ -110,8 +105,7 @@
         exps.accessPath = metas.toArray(new ClassMetaData[metas.size()]);
     }
     
-    protected void evalOrdering(QueryExpressions exps, 
-        ExpressionFactory factory, CriteriaQueryImpl q) {
+    protected void evalOrdering(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         List<Order> orders = q.getOrderList();
         MetamodelImpl model = q.getMetamodel(); 
         if (orders == null) 
@@ -124,7 +118,7 @@
         for (int i = 0; i < ordercount; i++) {
             OrderImpl order = (OrderImpl)orders.get(i);
             //Expression<? extends Comparable> expr = order.getExpression();
-            Expression expr = order.getExpression5();
+            Expression<?> expr = order.getExpression5();
             exps.ordering[i] = Expressions.toValue(
                     (ExpressionImpl<?>)expr, factory, model, q);
 
@@ -134,8 +128,7 @@
         }
     }
 
-    protected void evalGrouping(QueryExpressions exps, 
-        ExpressionFactory factory, CriteriaQueryImpl q) {
+    protected void evalGrouping(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         //    exps.grouping = null; // Value[]
         //    exps.groupingClauses = null; // String[]
         List<Expression<?>> groups = q.getGroupList();
@@ -155,8 +148,7 @@
                 : having.toKernelExpression(factory, model, q);
     }
 
-    protected void evalDistinct(QueryExpressions exps, 
-        ExpressionFactory factory, CriteriaQueryImpl q) {
+    protected void evalDistinct(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         Boolean distinct = q.getDistinct();
         if (distinct == null) {
             exps.distinct = QueryExpressions.DISTINCT_FALSE;
@@ -167,22 +159,33 @@
         //exps.distinct &= ~QueryExpressions.DISTINCT_AUTO;
     }
 
-    protected void evalFilter(QueryExpressions exps, ExpressionFactory factory,
-        CriteriaQueryImpl q) {
+    protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         Set<Root<?>> roots = q.getRoots();
         MetamodelImpl model = q.getMetamodel();
         PredicateImpl where = q.getRestriction();
-        q.assertRoot();
+        SubqueryImpl<?> subQuery = q.getDelegator();
         org.apache.openjpa.kernel.exps.Expression filter = null;
-        for (Root<?> root : roots) {
-            if (root.getJoins() != null) {
-                for (Join<?, ?> join : root.getJoins()) {
-                    filter = and(factory, ((ExpressionImpl<?>)join)
-                        .toKernelExpression(factory, model, q), filter);
+        if (subQuery == null || subQuery.getCorrelatedJoins() == null) {
+            q.assertRoot();
+            for (Root<?> root : roots) {
+                if (root.getJoins() != null) {
+                    for (Join<?, ?> join : root.getJoins()) {
+                        filter = and(factory, ((ExpressionImpl<?>)join)
+                                .toKernelExpression(factory, model, q), filter);
+                    }
                 }
+                ((RootImpl<?>)root).addToContext(factory, model, q);
+            }
+        }
+        if (subQuery != null) {
+            List<Join<?,?>> corrJoins = subQuery.getCorrelatedJoins();
+            if (corrJoins != null) {
+                for (int i = 0; i < corrJoins.size(); i++) 
+                    filter = and(factory, ((ExpressionImpl<?>)corrJoins.get(i))
+                            .toKernelExpression(factory, model, q), filter);
             }
-            ((RootImpl)root).addToContext(factory, model, q);
         }
+        
         if (where != null) {
             filter = and(factory, where.toKernelExpression
                     (factory, model, q), filter);
@@ -192,8 +195,7 @@
         exps.filter = filter;
     }
 
-    protected void evalProjections(QueryExpressions exps, 
-        ExpressionFactory factory, CriteriaQueryImpl q) {
+    protected void evalProjections(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         List<Selection<?>> selections = q.getSelectionList();
         MetamodelImpl model = q.getMetamodel();
         // TODO: fill in projection clauses
@@ -212,8 +214,8 @@
     }
 
     private void getProjections(QueryExpressions exps, 
-        List<Selection<?>> selections, List projections, List aliases, 
-        ExpressionFactory factory, CriteriaQueryImpl q, MetamodelImpl model) {
+        List<Selection<?>> selections, List projections, List<String> aliases, 
+        ExpressionFactory factory, CriteriaQueryImpl<?> q, MetamodelImpl model) {
         for (Selection<?> s : selections) {
             List<Selection<?>> sels = ((SelectionImpl)s).getSelections();
             if (sels == null) {
@@ -229,14 +231,20 @@
         }
     }
 
-    protected boolean isDefaultProjection(List<Selection<?>> selections, 
-        CriteriaQueryImpl q) {
-        return selections == null 
-        || (selections.size() == 1 && selections.get(0) == q.getRoot());
+    protected boolean isDefaultProjection(List<Selection<?>> selections, CriteriaQueryImpl<?> q) {
+        if (selections == null)
+            return true;
+        if (selections.size() != 1)
+            return false;
+        Selection<?> sel = selections.get(0);
+        if (q.getRoots() != null && sel == q.getRoot())
+            return true;
+        if ((sel instanceof PathImpl<?,?>) && ((PathImpl<?,?>)sel)._correlatedPath != null)
+            return true;
+        return false;
     }
 
-    protected void evalFetchJoin(QueryExpressions exps, 
-        ExpressionFactory factory, CriteriaQueryImpl q) {
+    protected void evalFetchJoin(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         List<String> iPaths = new ArrayList<String>();
         List<String> oPaths = new ArrayList<String>();
         Set<Root<?>> roots = q.getRoots();

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java?rev=788604&r1=788603&r2=788604&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java Fri Jun 26 06:34:34 2009
@@ -18,6 +18,7 @@
  */
 package org.apache.openjpa.persistence.criteria;
 
+import javax.persistence.criteria.AbstractQuery;
 import javax.persistence.criteria.CollectionJoin;
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Join;
@@ -73,6 +74,10 @@
             return (FromImpl<?, Z>) _parent;
         }
         
+        public Member<? extends Z, X> getMember() {
+            return (Member<? extends Z, X>) _member;
+        }
+        
         /**
          * Return the metamodel attribute corresponding to the join.
          * @return metamodel attribute type corresponding to the join
@@ -111,32 +116,37 @@
             SubqueryImpl<?> subquery = c.getDelegator();
             PathImpl<?,?> parent = getInnermostParentPath();
             org.apache.openjpa.kernel.exps.Expression filter = null;
-            PathImpl<?,?> correlatedParent = null;
+            PathImpl<?,?> correlatedParentPath = null;
             boolean bind = true;
-            if (parent.inSubquery(subquery)) {
-                org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
-                path = factory.newPath(subQ);
-                correlatedParent = _parent.getCorrelatedParent();
-                if (correlatedParent == null) {
-                    path.setMetaData(subQ.getMetaData());
-                    path.get(_member.fmd, allowNull);
-                    //path.setSchemaAlias(c.getAlias(_parent));
-                } else {
-                    bind = false;
-                }
-            } else if (c.isRegistered(_parent)) {
-               Value var = c.getVariable(_parent);
-               path = factory.newPath(var);
-               path.setMetaData(meta);
-               path.get(_member.fmd, false);
-            } else {
-               path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
-            }
+            java.util.List<Join<?,?>> corrJoins = null;
             org.apache.openjpa.kernel.exps.Expression join = null;
-            if (bind) {
-                Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
-                join = factory.bindVariable(var, path);
-                c.registerVariable(this, var, path);
+            if (_correlatedPath == null) {
+                if (subquery != null) {
+                    corrJoins = subquery.getCorrelatedJoins();
+                    org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
+                    path = factory.newPath(subQ);
+                    if ((corrJoins != null && corrJoins.contains(_parent)) || 
+                            (corrJoins == null && parent.inSubquery(subquery))) { 
+                        correlatedParentPath = _parent.getCorrelatedPath();
+                        bind = false;
+                    } else {    
+                        path.setMetaData(subQ.getMetaData());
+                        path.get(_member.fmd, allowNull);
+                        //path.setSchemaAlias(c.getAlias(_parent));
+                    } 
+                } else if (c.isRegistered(_parent)) {
+                    Value var = c.getVariable(_parent);
+                    path = factory.newPath(var);
+                    path.setMetaData(meta);
+                    path.get(_member.fmd, false);
+                } else            
+                    path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
+
+                if (bind) {
+                    Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
+                    join = factory.bindVariable(var, path);
+                    c.registerVariable(this, var, path);
+                }
             }
             if (getJoins() != null) {
                 for (Join<?, ?> join1 : getJoins()) {
@@ -146,11 +156,16 @@
             }
             org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter);
             
-            if (correlatedParent == null) {
+            if (correlatedParentPath == null) {
                 return expr;
             } else {
-                org.apache.openjpa.kernel.exps.Path parentPath = (org.apache.openjpa.kernel.exps.Path)
-                    correlatedParent.toValue(factory, model, c);
+                org.apache.openjpa.kernel.exps.Path parentPath = null;
+                if (corrJoins != null && corrJoins.contains(_parent)) {
+                    Value var = getVariableForCorrPath(subquery, correlatedParentPath);
+                    parentPath = factory.newPath(var);
+                } else 
+                    parentPath = (org.apache.openjpa.kernel.exps.Path)
+                        correlatedParentPath.toValue(factory, model, c);
                 parentPath.get(_member.fmd, allowNull);
                 //parentPath.setSchemaAlias(c.getAlias(correlatedParent));
                 path.setMetaData(meta);
@@ -159,6 +174,18 @@
                 return CriteriaExpressionBuilder.and(factory, expr, filter);
             }
         }
+        
+        private Value getVariableForCorrPath(SubqueryImpl<?> subquery, PathImpl<?,?> path) {
+            AbstractQuery<?> parent = subquery.getParent();
+            if (parent instanceof CriteriaQueryImpl) {
+                return ((CriteriaQueryImpl<?>)parent).getVariable(path);
+            }
+            Value var = ((SubqueryImpl<?>)parent).getDelegate().getVariable(path); 
+            if (var != null)
+                return var;
+            return getVariableForCorrPath((SubqueryImpl<?>)parent, path);
+        }
+        
     }
     
     /**
@@ -214,7 +241,6 @@
         @Override
         public Value toValue(ExpressionFactory factory, MetamodelImpl model,
             CriteriaQueryImpl<?> c) {
-            ClassMetaData meta = getMemberClassMetaData(); 
             org.apache.openjpa.kernel.exps.Path path = null;
             SubqueryImpl<?> subquery = c.getDelegator();
             PathImpl<?,?> parent = getInnermostParentPath();
@@ -245,34 +271,40 @@
             ClassMetaData meta = getMemberClassMetaData(); 
             org.apache.openjpa.kernel.exps.Path path = null;
             SubqueryImpl<?> subquery = c.getDelegator();
-            PathImpl<?,?> parent = getInnermostParentPath();
             org.apache.openjpa.kernel.exps.Expression filter = null;
-            PathImpl correlatedParent = null;
+            java.util.List<Join<?,?>> corrJoins = null;
             boolean bind = true;
-            if (parent.inSubquery(subquery)) {
-                org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
-                path = factory.newPath(subQ);
-                correlatedParent = _parent.getCorrelatedParent();
-                if (correlatedParent == null) {
-                    path.setMetaData(subQ.getMetaData());
-                    path.get(_member.fmd, allowNull);
-                    //path.setSchemaAlias(c.getAlias(_parent));
-                } else {
-                    bind = false;
-                }
-            } else if (c.isRegistered(_parent)) {
-                Value var = c.getVariable(_parent);
-                path = factory.newPath(var);
-                path.setMetaData(meta);
-                path.get(_member.fmd, false);
-            } else {           
-                path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
-            }
             org.apache.openjpa.kernel.exps.Expression join = null;
-            if (bind) {
-                Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
-                join = factory.bindVariable(var, path);
-                c.registerVariable(this, var, path);
+            PathImpl<?,?> corrJoin = getCorrelatedJoin(this);
+            PathImpl<?,?> corrRoot = getCorrelatedRoot(subquery);
+
+            PathImpl<?,?> correlatedParentPath = null;
+            if (_correlatedPath == null) {
+                if (subquery != null) {
+                    corrJoins = subquery.getCorrelatedJoins();
+                    org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
+                    path = factory.newPath(subQ); 
+                    if (corrJoin != null || corrRoot != null) { 
+                        correlatedParentPath = _parent.getCorrelatedPath();
+                        bind = false;
+                    } else {    
+                        path.setMetaData(subQ.getMetaData());
+                        path.get(_member.fmd, allowNull);
+                        //path.setSchemaAlias(c.getAlias(_parent));
+                    } 
+                } else if (c.isRegistered(_parent)) {
+                    Value var = c.getVariable(_parent);
+                    path = factory.newPath(var);
+                    path.setMetaData(meta);
+                    path.get(_member.fmd, false);
+                } else            
+                    path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
+
+                if (bind) {
+                    Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
+                    join = factory.bindVariable(var, path);
+                    c.registerVariable(this, var, path);
+                }
             }
             if (getJoins() != null) {
                 for (Join<?, ?> join1 : getJoins()) {
@@ -281,19 +313,36 @@
                 }
             }
             org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter);
-            if (correlatedParent == null) {
+            if (correlatedParentPath == null) {
                 return expr;
             } else {
-                org.apache.openjpa.kernel.exps.Path parentPath = (org.apache.openjpa.kernel.exps.Path)
-                    correlatedParent.toValue(factory, model, c);
+                org.apache.openjpa.kernel.exps.Path parentPath = null;
+                if (corrJoins != null && corrJoins.contains(_parent)) {
+                    Value var = getVariableForCorrPath(subquery, correlatedParentPath);
+                    parentPath = factory.newPath(var);
+                } else 
+                    parentPath = (org.apache.openjpa.kernel.exps.Path)
+                        correlatedParentPath.toValue(factory, model, c);
+                
                 parentPath.get(_member.fmd, allowNull);
-                //parentPath.setSchemaAlias(c.getAlias(correlatedParent));
+                //parentPath.setSchemaAlias(c.getAlias(correlatedParentPath));
                 path.setMetaData(meta);
                 //filter = bindVariableForKeyPath(path, alias, filter);
                 filter = factory.equal(parentPath, path);
                 return CriteriaExpressionBuilder.and(factory, expr, filter);
             }
         }
+        
+        private Value getVariableForCorrPath(SubqueryImpl<?> subquery, PathImpl<?,?> path) {
+            AbstractQuery<?> parent = subquery.getParent();
+            if (parent instanceof CriteriaQueryImpl) {
+                return ((CriteriaQueryImpl<?>)parent).getVariable(path);
+            }
+            Value var = ((SubqueryImpl<?>)parent).getDelegate().getVariable(path); 
+            if (var != null)
+                return var;
+            return getVariableForCorrPath((SubqueryImpl<?>)parent, path);
+        }
     }
     
     /**

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java?rev=788604&r1=788603&r2=788604&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java Fri Jun 26 06:34:34 2009
@@ -56,8 +56,8 @@
     protected final PathImpl<?,Z> _parent;
     protected final Members.Member<? super Z,?> _member;
     private boolean isEmbedded = false;
-    private PathImpl<?,?> _correlatedParent;
-
+    protected PathImpl<?,?> _correlatedPath;
+    
     /**
      * Protected. use by root path which neither represent a member nor has a
      * parent. 
@@ -119,12 +119,11 @@
             parent._member); 
     }
     
-    public void setCorrelatedParent(PathImpl<?,?> correlatedParent) {
-        _correlatedParent = correlatedParent;
+    public void setCorrelatedPath(PathImpl<?,?> correlatedPath) {
+        _correlatedPath = correlatedPath;
     }
-    
-    public PathImpl<?,?> getCorrelatedParent() {
-        return _correlatedParent;
+    public PathImpl<?,?> getCorrelatedPath() {
+        return _correlatedPath;
     }
     
     /**
@@ -137,15 +136,15 @@
             return q.getValue(this);
         org.apache.openjpa.kernel.exps.Path path = null;
         SubqueryImpl<?> subquery = q.getDelegator();
-        PathImpl<?,?> parent = getInnermostParentPath();
         boolean allowNull = _parent == null ? false : _parent instanceof Join 
             && ((Join<?,?>)_parent).getJoinType() != JoinType.INNER;
-        
+        PathImpl<?,?> corrJoin = getCorrelatedJoin(this);
+        PathImpl<?,?> corrRoot = getCorrelatedRoot(subquery);
         if (_parent != null && q.isRegistered(_parent)) {
             path = factory.newPath(q.getVariable(_parent));
             //path.setSchemaAlias(q.getAlias(_parent));
             path.get(_member.fmd, allowNull);
-        } else if (parent.inSubquery(subquery)) {
+        } else if (corrJoin != null || corrRoot != null) {
             org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
             path = factory.newPath(subQ);
             path.setMetaData(subQ.getMetaData());
@@ -166,11 +165,29 @@
         return path;
     }
     
+    public PathImpl<?,?> getCorrelatedRoot(SubqueryImpl<?> subquery) {
+        if (subquery == null)
+            return null;
+        PathImpl<?,?> root = getInnermostParentPath();
+        if (subquery.getRoots() != null && subquery.getRoots().contains(this))
+            return root;
+        return null;
+    }
+    
+    
+    public PathImpl<?,?> getCorrelatedJoin(PathImpl<?,?> path) {
+        if (path._correlatedPath != null)
+            return path._correlatedPath;
+        if (path._parent == null)
+            return null;
+        return getCorrelatedJoin(path._parent);
+    }
+    
     /**
      * Affirms if this receiver occurs in the roots of the given subquery.
      */
     public boolean inSubquery(SubqueryImpl<?> subquery) {
-        return subquery != null && subquery.getRoots().contains(this);
+        return subquery != null && (subquery.getRoots() == null ? false : subquery.getRoots().contains(this));
     }
     
     protected void traversePath(PathImpl<?,?> parent,  org.apache.openjpa.kernel.exps.Path path, FieldMetaData fmd) {
@@ -178,7 +195,7 @@
             && ((Join<?,?>)parent).getJoinType() != JoinType.INNER;
         FieldMetaData fmd1 = parent._member == null ? null : parent._member.fmd;
         PathImpl<?,?> parent1 = parent._parent;
-        if (parent1 == null || parent1.getCorrelatedParent() != null) {
+        if (parent1 == null || parent1.getCorrelatedPath() != null) {
             if (fmd != null) 
                 path.get(fmd, allowNull);
             return;

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java?rev=788604&r1=788603&r2=788604&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java Fri Jun 26 06:34:34 2009
@@ -50,7 +50,7 @@
     }
     
     public void  addToContext(ExpressionFactory factory, MetamodelImpl model, 
-        CriteriaQueryImpl q) {
+        CriteriaQueryImpl<?> q) {
         String alias = q.getAlias(this);
         Value var = factory.newBoundVariable(alias, 
             AbstractExpressionBuilder.TYPE_OBJECT);
@@ -71,11 +71,13 @@
         CriteriaQueryImpl<?> c) {
         SubqueryImpl<?> subquery = c.getDelegator();
         Path var = null;
+        //String alias = c.getAlias(this);
         if (inSubquery(subquery)) {
             Subquery subQ = subquery.getSubQ();
             var = factory.newPath(subQ);
         } else {
             var = factory.newPath();
+            //var.setSchemaAlias(alias);
         }
         var.setMetaData(_entity.meta);
         return var;

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java?rev=788604&r1=788603&r2=788604&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java Fri Jun 26 06:34:34 2009
@@ -18,6 +18,7 @@
  */
 package org.apache.openjpa.persistence.criteria;
 
+import java.util.ArrayList;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
@@ -26,6 +27,7 @@
 import javax.persistence.criteria.CollectionJoin;
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Join;
+import javax.persistence.criteria.JoinType;
 import javax.persistence.criteria.ListJoin;
 import javax.persistence.criteria.MapJoin;
 import javax.persistence.criteria.Predicate;
@@ -62,6 +64,7 @@
     private java.util.Set<Join<?,?>> _joins;
     private Expression<T> _select;
     private org.apache.openjpa.kernel.exps.Subquery _subq;
+    private List<Join<?,?>> _corrJoins = null;
     
     public SubqueryImpl(Class<T> cls, AbstractQuery<?> parent) {
         super(cls);
@@ -176,7 +179,7 @@
     public <Y> Root<Y> correlate(Root<Y> root) {
         Types.Entity<Y> entity = (Types.Entity<Y>)root.getModel();
         RootImpl<Y> corrRoot = new RootImpl<Y>(entity);
-        corrRoot.setCorrelatedParent((RootImpl<Y>)root);
+        corrRoot.setCorrelatedPath((RootImpl<Y>)root);
         Set<Root<?>> roots = getRoots();
         if (roots == null) {
             roots = new LinkedHashSet<Root<?>>();
@@ -186,9 +189,54 @@
         return corrRoot;
     }
     
+    public List<Join<?,?>> getCorrelatedJoins() {
+        return _corrJoins;
+    }
+    
     public <X,Y> Join<X,Y> correlate(Join<X,Y> join) {
-        _delegate.from(join.getModel().getBindableJavaType());
-        return join;
+        Join corrJoin = clone(join);
+        ((PathImpl<?,?>)corrJoin).setCorrelatedPath((PathImpl<?,?>)join);
+        if (_corrJoins == null)
+            _corrJoins = new ArrayList<Join<?,?>>();
+        _corrJoins.add(corrJoin);
+        return corrJoin;
+    }
+    
+    private Join<?,?> clone(Join<?,?> join) {
+        List<Members.SingularAttributeImpl<?,?>> members = 
+            new ArrayList<Members.SingularAttributeImpl<?,?>>();
+        List<JoinType> jts = new ArrayList<JoinType>();
+        FromImpl<?,?> root = getMembers(join, members, jts);
+        Members.SingularAttributeImpl<?,?> member = members.get(0);
+        JoinType jt = jts.get(0);
+        Join<?,?> join1 = makeJoin(root, member, jt);
+        for (int i = 1; i < members.size(); i++) {
+            join1 = makeJoin((FromImpl<?,?>)join1, members.get(i), jts.get(i));
+        }
+        return join1;
+    }
+    
+    private Join<?,?> makeJoin(FromImpl<?,?> parent, Members.SingularAttributeImpl<?,?> member, JoinType jt) {
+        return new Joins.SingularJoin(parent, member, jt);
+    }
+    
+    private FromImpl<?,?> getMembers(Join<?,?> join, List<Members.SingularAttributeImpl<?,?>> members, 
+        List<JoinType> jts) {
+        PathImpl<?,?> parent = (PathImpl<?,?>)join.getParentPath();
+        Members.SingularAttributeImpl<?,?> member = 
+            (Members.SingularAttributeImpl<?,?>)((Joins.SingularJoin<?,?>)join).getMember();
+        JoinType jt = join.getJoinType();
+        FromImpl<?,?> root = null;
+        if (parent instanceof RootImpl<?>) {
+            members.add(member);
+            jts.add(jt);
+            return (FromImpl<?,?>)parent;
+        } else {
+            root = getMembers((Join<?,?>)parent, members, jts);
+        }
+        members.add(member);
+        jts.add(jt);
+        return root;
     }
     public <X,Y> CollectionJoin<X,Y> correlate(CollectionJoin<X,Y> join) {
         _delegate.from(join.getModel().getBindableJavaType());
@@ -225,7 +273,7 @@
     public Value toValue(ExpressionFactory factory, MetamodelImpl model,
         CriteriaQueryImpl<?> q) {
         final boolean subclasses = true;
-        CriteriaExpressionBuilder queryEval = new CriteriaExpressionBuilder();
+        CriteriaExpressionBuilder exprBuilder = new CriteriaExpressionBuilder();
         String alias = q.getAlias(this);
         ClassMetaData candidate = getCandidate(); 
         _subq = factory.newSubquery(candidate, subclasses, alias);
@@ -235,7 +283,7 @@
         //Context context = new Context(null, _subq, contexts.peek());
         //contexts.push(context);
         //_delegate.setContexts(contexts);
-        QueryExpressions subexp = queryEval.getQueryExpressions(factory, 
+        QueryExpressions subexp = exprBuilder.getQueryExpressions(factory, 
                 _delegate);
         _subq.setQueryExpressions(subexp);
         if (subexp.projections.length > 0)
@@ -248,18 +296,42 @@
     // correlated parent, the candidate of the subquery
     // should be the class metadata of the collection element 
     private ClassMetaData getCandidate() {
+        if (_delegate.getRoots() == null && _corrJoins != null) {
+            FromImpl<?,?> corrJoin = (FromImpl<?,?>) _corrJoins.get(0);
+            if (corrJoin.getJoins() != null) {
+                FromImpl<?,?> join = (FromImpl<?,?>)corrJoin.getJoins().iterator().next();
+                return getInnermostCandidate(join);
+            }
+        }
+         
         RootImpl<?> root = (RootImpl<?>)getRoot();
-        PathImpl<?, ?> correlatedRoot = root.getCorrelatedParent();
-        if (correlatedRoot != null && root.getJoins() != null) {
-           Join<?,?> join = root.getJoins().iterator().next();
-           FieldMetaData fmd = ((Members.Member<?, ?>)join.getAttribute()).fmd;
-           if (join.getAttribute().isCollection()) {
-               return fmd.isElementCollection() ? fmd.getEmbeddedMetaData(): fmd.getElement().getDeclaredTypeMetaData();
-           } else {
-               return fmd.getDeclaredTypeMetaData();
-           }
+        RootImpl<?> corrRoot = (RootImpl<?>)root.getCorrelatedPath();
+        if (corrRoot != null && root.getJoins() != null) {
+            FromImpl<?,?> join = (FromImpl<?,?>) root.getJoins().iterator().next();
+            return getInnermostCandidate(join);
         }
+
         return ((AbstractManagedType<?>)root.getModel()).meta;
     }
     
+    private ClassMetaData getInnermostCandidate(FromImpl<?,?> from) {
+        if (from.getJoins() != null) {
+            from = (FromImpl<?,?>) from.getJoins().iterator().next();
+            return getInnermostCandidate(from);
+        }
+        return getCandidate(from);
+    }
+    
+    
+    private ClassMetaData getCandidate(FromImpl<?,?> from) {
+        if (from._member.fmd.getDeclaredTypeCode() == 
+            JavaTypes.COLLECTION || 
+            from._member.fmd.getDeclaredTypeCode() == 
+            JavaTypes.MAP)
+            return from._member.fmd.isElementCollection()
+                ? from._member.fmd.getEmbeddedMetaData()
+                : from._member.fmd.getElement().getDeclaredTypeMetaData();
+        return from._member.fmd.getDeclaredTypeMetaData();
+        
+    }    
 }