openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ppod...@apache.org
Subject svn commit: r810212 [1/2] - in /openjpa/trunk: openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/ openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/
Date Tue, 01 Sep 2009 20:16:21 GMT
Author: ppoddar
Date: Tue Sep  1 20:16:19 2009
New Revision: 810212

URL: http://svn.apache.org/viewvc?rev=810212&view=rev
Log:
OPENJPA-1278,OPENJPA-1276,OPENJPA-1265: 
  Add new OpenJPACriteriaXYZ interface for extended features. 
  Draft version of conversion of Criteria Query to a JPQL-like string
  The getter methods return non-live, non-null, mutable lists/sets

Added:
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/OpenJPACriteriaQuery.java   (with props)
Modified:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/AbstractCriteriaTestCase.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/AliasContext.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpression.java
    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/CriteriaExpressionVisitor.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.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/OrderImpl.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/PredicateImpl.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/SelectionImpl.java
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/AbstractCriteriaTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/AbstractCriteriaTestCase.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/AbstractCriteriaTestCase.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/AbstractCriteriaTestCase.java Tue Sep  1 20:16:19 2009
@@ -100,6 +100,8 @@
      * Executes the given CriteriaQuery and JPQL string and compare their respective SQLs for equality.
      */
     void assertEquivalence(CriteriaQuery<?> c, String jpql) {
+        System.err.println("JPQL :" + jpql);
+        System.err.println("CJQL :" + ((CriteriaQueryImpl<?>)c).toCQL());
         assertEquivalence(c, jpql, null, null, null);
     }
 

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestQueryByExample.java Tue Sep  1 20:16:19 2009
@@ -40,7 +40,7 @@
         
         ComparisonStyle style = null;
         Attribute<?,?>[] excludes = null;
-        q.where(cb.example(q.from(Employee.class), example, style, excludes));
+        q.where(cb.qbe(q.from(Employee.class), example, style, excludes));
         
         assertEquivalence(q, jpql);
     }
@@ -56,7 +56,7 @@
         
         ComparisonStyle style = null;
         Attribute<?,?>[] excludes = {Employee_.rating};
-        q.where(cb.example(q.from(Employee.class), example, style, excludes));
+        q.where(cb.qbe(q.from(Employee.class), example, style, excludes));
         
         assertEquivalence(q, jpql);
     }
@@ -71,7 +71,7 @@
         
         ComparisonStyle style = null;
         Attribute<?,?>[] excludes = null;
-        q.where(cb.example(q.from(Employee.class), example, style, excludes));
+        q.where(cb.qbe(q.from(Employee.class), example, style, excludes));
         
         executeAndCompareSQL(q, "WHERE (t0.rating = ?)");        
         assertEquivalence(q, jpql);
@@ -85,9 +85,9 @@
         Employee example = new Employee();
         example.setRating(1);
         
-        ComparisonStyle style = cb.comparisonStyle();
+        ComparisonStyle style = cb.qbeStyle();
         Attribute<?,?>[] excludes = null;
-        q.where(cb.example(q.from(Employee.class), example, style.setExcludeDefault(false), excludes));
+        q.where(cb.qbe(q.from(Employee.class), example, style.setExcludeDefault(false), excludes));
         
         executeAndCompareSQL(q, "WHERE (t0.rating = ? AND t0.salary = ?)");
         assertEquivalence(q, jpql);
@@ -106,9 +106,9 @@
         example.setDepartment(dept);
         
         
-        ComparisonStyle style = cb.comparisonStyle();
+        ComparisonStyle style = cb.qbeStyle();
         Attribute<?,?>[] excludes = null;
-        q.where(cb.example(q.from(Employee.class), example, style, excludes));
+        q.where(cb.qbe(q.from(Employee.class), example, style, excludes));
         
         executeAndCompareSQL(q, "WHERE (t1.name = ? AND t0.rating = ? AND t0.salary = ?)");
     }
@@ -124,9 +124,9 @@
         example.setRating(1);
         example.setDepartment(null);
         
-        ComparisonStyle style = cb.comparisonStyle();
+        ComparisonStyle style = cb.qbeStyle();
         Attribute<?,?>[] excludes = {Employee_.frequentFlierPlan, Employee_.manager, Employee_.spouse};
-        q.where(cb.example(q.from(Employee.class), example, style.setExcludeNull(false).setExcludeDefault(false), 
+        q.where(cb.qbe(q.from(Employee.class), example, style.setExcludeNull(false).setExcludeDefault(false), 
                 excludes));
         
         executeAndCompareSQL(q, "WHERE (1 <> 1 AND t0.DEPARTMENT_DEPTNO IS NULL " 
@@ -150,10 +150,10 @@
         contact.setAddress(address);
         example.setContactInfo(contact);
         
-        ComparisonStyle style = cb.comparisonStyle();
+        ComparisonStyle style = cb.qbeStyle();
         Attribute<?,?>[] excludes = {Employee_.department, Employee_.frequentFlierPlan, 
                 Employee_.manager, Employee_.spouse};
-        q.where(cb.example(q.from(Employee.class), example, style, excludes));
+        q.where(cb.qbe(q.from(Employee.class), example, style, excludes));
         
         executeAndCompareSQL(q, "WHERE (t1.city = ? AND t1.country = ? AND t1.state = ? " 
                 + "AND t0.name = ? AND t0.rating = ? AND t0.salary = ?)");

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/AliasContext.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/AliasContext.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/AliasContext.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/AliasContext.java Tue Sep  1 20:16:19 2009
@@ -56,12 +56,12 @@
      * Gets the registered variable for the given node. 
      * Return null if the node is not registered.     
      */
-    Value getVariable(Selection<?> node);
+    Value getRegisteredVariable(Selection<?> node);
     
     /**
      * Gets the registered path value for the given node. 
      * Return null if the node is not registered.     
      */
-    Value getValue(Selection<?> node);
+    Value getRegisteredValue(Selection<?> node);
     
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CompoundSelections.java Tue Sep  1 20:16:19 2009
@@ -36,7 +36,7 @@
 import org.apache.openjpa.persistence.TupleImpl;
 
 /**
- * Implements slection terms that are composed of other selection terms.
+ * Implements selection terms that are composed of other selection terms.
  *  
  * @author Pinaki Poddar
  * 
@@ -81,7 +81,7 @@
          *           selection
          */
         public final List<Selection<?>> getCompoundSelectionItems() {
-            return _args == null ? Collections.EMPTY_LIST : new CopyOnWriteArrayList<Selection<?>>(_args);
+            return Expressions.returnCopy(_args);
         }
         
         void assertNoCompoundSelection(Selection<?>...args) {
@@ -94,7 +94,18 @@
             }
         }
 
-        public abstract FillStrategy<X> getFillStrategy();
+        abstract FillStrategy<X> getFillStrategy();
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            StringBuilder buffer = new StringBuilder();
+            for (int i = 0; i < _args.size(); i++) {
+                buffer.append((((CriteriaExpression)_args.get(i)).asValue(q)));
+                if (i+1 != _args.size())
+                    buffer.append(", ");
+            }
+            return buffer;
+        }
     }
     
     /**
@@ -145,6 +156,12 @@
                     types == null ? "[]" : Arrays.toString(types)).getMessage());
             }
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return new StringBuilder("NEW ").append(getJavaType().getName()).append("(")
+               .append(super.asValue(q)).append(")");
+        }
     }
     
     /**

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java Tue Sep  1 20:16:19 2009
@@ -62,7 +62,7 @@
  *
  */
 @SuppressWarnings("serial")
-public class CriteriaBuilder implements QueryBuilder, ExpressionParser {
+public class CriteriaBuilder implements OpenJPACriteriaBuilder, ExpressionParser {
     public static final String LANG_CRITERIA = "javax.persistence.criteria";
 
     private MetamodelImpl _model;
@@ -724,7 +724,7 @@
      *  
      * @return a predicate 
      */
-    public <T> Predicate example(From<?, T> from, T example, ComparisonStyle style, Attribute<?,?>... excludes) {
+    public <T> Predicate qbe(From<?, T> from, T example, ComparisonStyle style, Attribute<?,?>... excludes) {
         if (from == null)
             throw new NullPointerException();
         if (example == null) {
@@ -733,13 +733,25 @@
         }
         ManagedType<T> type = (ManagedType<T>)_model.type(example.getClass());
         return new CompareByExample<T>(this, type, from, example, 
-            style == null ? comparisonStyle() : style, excludes);
+            style == null ? qbeStyle() : style, excludes);
+    }
+    
+    public <T> Predicate qbe(From<?, T> from, T example, ComparisonStyle style) {
+        return qbe(from, example, style, null);
+    }
+    
+    public <T> Predicate qbe(From<?, T> from, T example, Attribute<?,?>... excludes) {
+        return qbe(from, example, qbeStyle(), excludes);
+    }
+    
+    public <T> Predicate qbe(From<?, T> from, T example) {
+        return qbe(from, example, qbeStyle(), null);
     }
     
     /**
      * Create a style to tune different aspects of comparison by example. 
      */
-    public ComparisonStyle comparisonStyle() {
+    public ComparisonStyle qbeStyle() {
         return new ComparisonStyle.Default();
     }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpression.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpression.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpression.java Tue Sep  1 20:16:19 2009
@@ -18,16 +18,13 @@
  */
 package org.apache.openjpa.persistence.criteria;
 
-import javax.persistence.criteria.Expression;
-
 /**
- * Extends specification interface to define contract for Visitor pattern.
+ * Interface to support Visitor pattern on Criteria Query nodes.
  * 
  * @author Pinaki Poddar
- *
- * @param <X>
+ * @since 2.0.0
  */
-public interface CriteriaExpression<X> extends Expression<X> {
+public interface CriteriaExpression  {
     /**
      * Accept visit from the given visitor. The receiver is responsible 
      * to propagate the visitor to the constituent sub-nodes if any.
@@ -35,5 +32,14 @@
      * @param visitor a processor to walk the nodes of a tree.
      */
     void acceptVisit(CriteriaExpressionVisitor visitor);
-
+    
+    /**
+     * Get a string representation of this node as a value in the context of the given query.
+     */
+    StringBuilder asValue(CriteriaQueryImpl<?> q);
+    
+    /**
+     * Get a string representation of this node as a variable in the context of the given query.
+     */
+    StringBuilder asVariable(CriteriaQueryImpl<?> q);
 }

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=810212&r1=810211&r2=810212&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 Tue Sep  1 20:16:19 2009
@@ -190,7 +190,6 @@
 
     protected void evalCrossJoinRoots(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
         Set<Root<?>> roots = q.getRoots();
-        MetamodelImpl model = q.getMetamodel();
         SubqueryImpl<?> subQuery = q.getDelegator();
         if (subQuery == null || subQuery.getCorrelatedJoins() == null) {
             q.assertRoot();
@@ -201,8 +200,7 @@
                     var.setMetaData(((Types.Entity)root.getModel()).meta);
                     q.registerRoot(root, var);
                 }
-            }
-        }
+            }         }
     }
     
     protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionVisitor.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionVisitor.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionVisitor.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionVisitor.java Tue Sep  1 20:16:19 2009
@@ -19,7 +19,6 @@
 package org.apache.openjpa.persistence.criteria;
 
 import java.util.HashSet;
-import java.util.IdentityHashMap;
 import java.util.Set;
 
 /**
@@ -30,31 +29,60 @@
  *
  */
 public interface CriteriaExpressionVisitor {
+    // Enumerates order of traversal of nodes
+    public static enum TraversalStyle {
+        INFIX,    // operand1 operator operand2   e.g. a + b
+        POSTFIX,  // operand1 operand2 operator   e.g. a b +
+        PREFIX,   // operator operand1 operand2   e.g. + a b
+        FUNCTION  // operator(operand1, operand2) e.g. f(a,b)
+    }
+    
     /**
-     * Enter the given expression.
+     * Enter the given node.
      */
-    void enter(CriteriaExpression<?> expr);
+    void enter(CriteriaExpression node);
     
     /**
-     * Exit the given expression.
+     * Exit the given node.
      */
-    void exit(CriteriaExpression<?> expr);
+    void exit(CriteriaExpression node);
     
-    boolean isVisited(CriteriaExpression<?> expr);
+    /**
+     * Affirms if this node has been visited.
+     */
+    boolean isVisited(CriteriaExpression node);
+    
+    /**
+     * Get the traversal style of the children of the given node.
+     */
+    TraversalStyle getTraversalStyle(CriteriaExpression node);
     
     /**
      * An abstract implementation that can detect cycles during traversal.
      *  
      */
     public static abstract class AbstractVisitor implements CriteriaExpressionVisitor {
-        protected final Set<CriteriaExpression<?>> _visited = new HashSet<CriteriaExpression<?>>();
+        protected final Set<CriteriaExpression> _visited = new HashSet<CriteriaExpression>();
         
         /**
-         * Affirms if this expression has been visited before.
-         * Remembers the given node as visited.
+         * Remembers the node being visited.
          */
-        public boolean isVisited(CriteriaExpression<?> expr) {
-            return _visited.contains(expr);
+        public void exit(CriteriaExpression node) {
+            _visited.add(node);
+        }
+        
+        /**
+         * Affirms if this node has been visited before.
+         */
+        public boolean isVisited(CriteriaExpression node) {
+            return _visited.contains(node);
+        }
+        
+        /**
+         * Returns PREFIX as the default traversal style.
+         */
+        public TraversalStyle getTraversalStyle(CriteriaExpression node) {
+            return TraversalStyle.PREFIX;
         }
     }
     
@@ -69,15 +97,11 @@
             query = q;
         }
         
-        public void enter(CriteriaExpression<?> expr) {
-            if (expr != null && expr instanceof ParameterExpressionImpl) {
+        public void enter(CriteriaExpression expr) {
+            if (expr instanceof ParameterExpressionImpl) {
                 query.registerParameter((ParameterExpressionImpl<?>)expr);
             }
         }
 
-        public void exit(CriteriaExpression<?> expr) {
-            _visited.add(expr);
-        }
-        
     }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java Tue Sep  1 20:16:19 2009
@@ -20,6 +20,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
@@ -32,6 +33,7 @@
 import javax.persistence.criteria.AbstractQuery;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Join;
 import javax.persistence.criteria.Order;
 import javax.persistence.criteria.ParameterExpression;
 import javax.persistence.criteria.Predicate;
@@ -63,7 +65,7 @@
  *
  * @since 2.0.0
  */
-public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
+public class CriteriaQueryImpl<T> implements OpenJPACriteriaQuery<T>, AliasContext {
     private static final Localizer _loc = Localizer.forPackage(CriteriaQueryImpl.class);
     
     private final MetamodelImpl  _model;
@@ -71,13 +73,13 @@
     private PredicateImpl       _where;
     private List<Order>         _orders;
     private LinkedMap/*<ParameterExpression<?>, Class<?>>*/ _params;
-    private Selection<T>        _selection;
+    private Selection<? extends T>        _selection;
     private List<Selection<?>>  _selections;
     private List<Expression<?>> _groups;
     private PredicateImpl       _having;
     private List<Subquery<?>>   _subqueries;
     private Boolean             _distinct;
-    private SubqueryImpl<?>     _delegator;
+    private final SubqueryImpl<?> _delegator;
     private final Class<T>      _resultClass;
     private boolean             _compiled;
 
@@ -96,39 +98,60 @@
     public CriteriaQueryImpl(MetamodelImpl model, Class<T> resultClass) {
         this._model = model;
         this._resultClass = resultClass;
+        this._delegator = null;
         _aliases = new HashMap<Selection<?>, String>(); 
     }
     
-    public CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<T> delegator) {
+    /**
+     * Used by a subquery to delegate to this receiver.
+     * 
+     * @param model the metamodel defines the scope of all persistent entity references.
+     * @param delegator the subquery which will delegate to this receiver.
+     */
+    CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<T> delegator) {
         this._model = model;
         this._resultClass = delegator.getJavaType();
         _delegator = delegator;
         _aliases = getAliases();
     }
-
-    public void setDelegator(SubqueryImpl<?> delegator) {
-        _delegator = delegator;
-    }
     
-    public SubqueryImpl<?> getDelegator() {
+    /**
+     * Gets the subquery, if any, which is delegating to this receiver.
+     */
+    SubqueryImpl<?> getDelegator() {
         return _delegator;
     }
     
+    /**
+     * Gets the metamodel which defines the scope of all persistent entity references.
+     */
     public MetamodelImpl getMetamodel() {
         return _model;
     }
     
-    public Stack<Context> getContexts() {
+    /**
+     * Gets the stack of contexts used by this query.
+     */
+    Stack<Context> getContexts() {
         return _contexts;
     }
     
+    /**
+     * Sets whether this query as distinct.
+     */
     public CriteriaQuery<T> distinct(boolean distinct) {
         _distinct = distinct;
         return this;
     }
 
+    /**
+     * Gets the list of ordering elements.
+     * 
+     * @return Empty list if there is no ordering elements.
+     * The returned list if mutable but mutation has no impact on this query.
+     */
     public List<Order> getOrderList() {
-        return _orders == null ? Collections.EMPTY_LIST : new CopyOnWriteArrayList<Order>(_orders);
+        return Expressions.returnCopy(_orders);
     }
     
     /**
@@ -136,7 +159,7 @@
      * @return the item to be returned in the query result
      */
     public Selection<T> getSelection() {
-        return _selection;
+        return (Selection<T>)_selection;
     }
     
     /**
@@ -209,9 +232,7 @@
      * @return the selection items of the query as a list
      */
     public List<Selection<?>> getSelectionList() {
-        if (_selections == null)
-            return Collections.EMPTY_LIST;
-        return Collections.unmodifiableList(_selections);
+        return Expressions.returnCopy(_selections);
     }
 
     public CriteriaQuery<T> groupBy(Expression<?>... grouping) {
@@ -246,7 +267,7 @@
      * @return the modified query
      */
     public CriteriaQuery<T> select(Selection<? extends T> selection) {
-        _selection = (Selection<T>)selection;
+        _selection = selection;
         _selections = new ArrayList<Selection<?>>();
         _selections.add(selection);
         return this;
@@ -289,7 +310,7 @@
     }
 
     public List<Expression<?>> getGroupList() {
-        return _groups == null ? Collections.EMPTY_LIST : new CopyOnWriteArrayList<Expression<?>>(_groups);
+        return Expressions.returnCopy(_groups);
     }
 
     public PredicateImpl getGroupRestriction() {
@@ -301,7 +322,7 @@
     }
 
     public Set<Root<?>> getRoots() {
-        return _roots;
+        return Expressions.returnCopy(_roots);
     }
 
     public Root<?> getRoot() {
@@ -309,6 +330,13 @@
         return _roots.iterator().next();
     }
     
+    Root<?> getRoot(boolean mustExist) {
+        if (mustExist) {
+            return getRoot();
+        }
+        return _roots == null || _roots.isEmpty() ? null : _roots.iterator().next();
+    }
+    
     void addRoot(RootImpl<?> root) {
         if (_roots == null) {
             _roots = new LinkedHashSet<Root<?>>();
@@ -317,10 +345,10 @@
     }
     
     public boolean isDistinct() {
-        return _distinct;
+        return _distinct == null ? false : _distinct.booleanValue();
     }
 
-    public Boolean getDistinct() {
+    Boolean getDistinct() {
         return _distinct;
     }
 
@@ -348,9 +376,8 @@
     QueryExpressions getQueryExpressions(ExpressionFactory factory) {
         _contexts = new Stack<Context>();
         Context context = new Context(null, null, null);
-            _contexts.push(context);
-        return new CriteriaExpressionBuilder()
-             .getQueryExpressions(factory, this);
+        _contexts.push(context);
+        return new CriteriaExpressionBuilder().getQueryExpressions(factory, this);
     }    
     
     public void assertRoot() {
@@ -366,11 +393,16 @@
     //
     // SubqueryContext
     //
-    public void setContexts(Stack<Context> contexts) {
+    void setContexts(Stack<Context> contexts) {
         _contexts = contexts;
     }
     
-    public CriteriaQueryImpl<?> getAncestor() {
+    /**
+     * Gets either this query itself if this is not a captive query for
+     * a subquery. Otherwise gets the parent query of the delegating
+     * subquery.
+     */
+    CriteriaQueryImpl<?> getAncestor() {
         if (_delegator == null)
             return this;
         AbstractQuery<?> parent = _delegator.getParent();
@@ -387,7 +419,10 @@
         return c._aliases;
     }
     
-    public Context ctx() {
+    /**
+     * Gets the current context.
+     */
+    Context ctx() {
         return _contexts.peek();
     }
     
@@ -412,14 +447,6 @@
         return _aliases.get(selection);
     }
     
-    public Value getVariable(Selection<?> selection) {
-        return _variables.get(selection);
-    }
-    
-    public Value getValue(Selection<?> selection) {
-        return _values.get(selection);
-    }
-    
     /**
      * Register the given variable of given path value against the given node.
      * If the given node has no alias then an alias is set to the given node.
@@ -434,7 +461,7 @@
         if (!var.isVariable())
             throw new RuntimeException(var.getClass() + " is not a variable");
         if (var.getPath() != path)
-            throw new RuntimeException(var + " and " + path);
+            throw new RuntimeException(var + " does not match given " + path + " Variable path is " + var.getPath());
         String alias = getAlias(node);
         
         if (!alias.equals(var.getAlias())) {
@@ -454,82 +481,69 @@
         _variables.put(node, var);
         _values.put(node, path);
         _aliases.put(node, alias);
+        // add to context
         ctx().addSchema(alias, var.getMetaData());
         ctx().addVariable(alias, var);
     }
     
     public boolean isRegistered(Selection<?> selection) {
-        boolean found = _variables.containsKey(selection);
-        if (found) 
+        if (_variables.containsKey(selection))
             return true;
         SubqueryImpl<?> delegator = getDelegator();
-        if (delegator == null)
-            return false;
-        
-        AbstractQuery<?> parent = delegator.getParent();
-        if (parent instanceof CriteriaQueryImpl) 
-            return ((CriteriaQueryImpl)parent).isRegistered(selection);
-        // parent is a SubqueryImpl    
-        return ((SubqueryImpl<?>)parent).getDelegate().isRegistered(selection);
-        
+        return (delegator == null) ? false : getDelegatorParent().isRegistered(selection);
     }
 
-    Value getRegisteredVariable(Selection<?> selection) {
-        Value var = getVariable(selection);
+    public Value getRegisteredVariable(Selection<?> selection) {
+        Value var = _variables.get(selection);
         if (var != null)
             return var;
         SubqueryImpl<?> delegator = getDelegator();
-        if (delegator == null)
-            return null;
-        
-        AbstractQuery<?> parent = delegator.getParent();
-        if (parent instanceof CriteriaQueryImpl) 
-            return ((CriteriaQueryImpl)parent).getRegisteredVariable(selection);
-        // parent is a SubqueryImpl    
-        return ((SubqueryImpl<?>)parent).getDelegate().getRegisteredVariable(selection);
-
+        return (delegator == null) ? null : getDelegatorParent().getRegisteredVariable(selection);
     }
 
-    Value getRegisteredValue(Selection<?> selection) {
-        Value var = getValue(selection);
-        if (var != null)
-            return var;
+    public Value getRegisteredValue(Selection<?> selection) {
+        Value val = _values.get(selection);
+        if (val != null)
+            return val;
         SubqueryImpl<?> delegator = getDelegator();
-        if (delegator == null)
-            return null;
-        
-        AbstractQuery<?> parent = delegator.getParent();
-        if (parent instanceof CriteriaQueryImpl) 
-            return ((CriteriaQueryImpl)parent).getRegisteredValue(selection);
-        // parent is a SubqueryImpl    
-        return ((SubqueryImpl<?>)parent).getDelegate().getRegisteredValue(selection);
-
+        return (delegator == null) ? null : getDelegatorParent().getRegisteredValue(selection);
     }
 
+    /**
+     * Registers a variable for the given root expression.
+     * A root expression is registered only for cross join.  
+     * @param root
+     * @param var
+     */
     void registerRoot(Root<?> root, Value var) {
+        if (var == null || !var.isVariable())
+            throw new IllegalArgumentException("Attempt to register non-variable " + var);
         _rootVariables.put(root, var);
         String alias = var.getName();
         ctx().addSchema(alias, var.getMetaData());
         ctx().addVariable(alias, var);
     }
     
-    Value getRootVariable(Root<?> root) {
-        return _rootVariables.get(root);
-    }
-    
+    /**
+     * Gets the registered variable for the given root. 
+     * 
+     * @param root
+     * @return
+     */
     Value getRegisteredRootVariable(Root<?> root) {
-        Value var = getRootVariable(root);
+        Value var = _rootVariables.get(root);
         if (var != null)
             return var;
         SubqueryImpl<?> delegator = getDelegator();
-        if (delegator == null)
-            return null;
-        
-        AbstractQuery<?> parent = delegator.getParent();
+        return (delegator == null) ? null : getDelegatorParent().getRegisteredRootVariable(root);
+    }
+    
+    CriteriaQueryImpl<?> getDelegatorParent() {
+        AbstractQuery<?> parent = _delegator.getParent();
         if (parent instanceof CriteriaQueryImpl) 
-            return ((CriteriaQueryImpl)parent).getRegisteredRootVariable(root);
+            return ((CriteriaQueryImpl<?>)parent);
         // parent is a SubqueryImpl    
-        return ((SubqueryImpl<?>)parent).getDelegate().getRegisteredRootVariable(root);
+        return ((SubqueryImpl<?>)parent).getDelegate();
     }
     
     public Class<T> getResultType() {
@@ -546,16 +560,16 @@
     
     protected boolean isDefaultProjection() {
         if (_selections == null) {
-            return _roots != null && _roots.size() == 1 && getRoot().getModel().getJavaType() == _resultClass;
+            return getRoots().size() == 1 && getRoot().getModel().getJavaType() == _resultClass;
         } 
         if (_selections.size() != 1) {
             return false;
         }
         Selection<?> sel = _selections.get(0);
-        if (getRoots() != null && sel == getRoot()) {
+        if (!getRoots().isEmpty() && sel == getRoot()) {
             return true;
         }
-        if ((sel instanceof PathImpl<?,?>) && ((PathImpl<?,?>)sel)._correlatedPath != null) {
+        if ((sel instanceof PathImpl<?,?>) && ((PathImpl<?,?>)sel).isCorrelated()) {
             return true;
         }
         return false;
@@ -593,4 +607,49 @@
         }
     }
 
+    /**
+     * Gets the string representation of the query.
+     */
+    public String toCQL() {
+        StringBuilder buffer = new StringBuilder();
+        render(buffer, _roots, null);
+        return buffer.toString();
+    }
+    
+    void render(StringBuilder buffer, Set<Root<?>> roots, List<Join<?,?>> correlatedJoins) {
+        buffer.append("SELECT ");
+        if (isDistinct()) buffer.append(" DISTINCT ");
+        buffer.append(_selection != null ? ((CriteriaExpression)_selection).asValue(this) : "*");
+        buffer.append(" FROM ");
+        renderRoots(buffer, roots);
+        renderJoins(buffer, correlatedJoins);
+        if (_where != null) {
+            buffer.append(" WHERE ").append(_where.asValue(this));
+        }
+        if (_orders != null) {
+            buffer.append(" ORDER BY ");
+            List<Order> orderBys = getOrderList();
+            for (int i = 0; i < orderBys.size(); i++) {
+                buffer.append(((CriteriaExpression)orderBys.get(i)).asValue(this));
+            }
+        }
+    }
+    
+    private void renderJoins(StringBuilder buffer, Collection<Join<?,?>> joins) {
+        if (joins == null) return;
+        for (Join j : joins) {
+            buffer.append(((ExpressionImpl<?>)j).asVariable(this)).append(" ");
+            renderJoins(buffer, j.getJoins());
+        }
+    }
+    
+    private void renderRoots(StringBuilder buffer, Collection<Root<?>> roots) {
+        if (roots == null) return;
+        int i = 0;
+        for (Root r : roots) {
+            buffer.append(((ExpressionImpl<?>)r).asVariable(this));
+            if (++i != roots.size()) buffer.append(", ");
+            renderJoins(buffer, r.getJoins());
+        }
+    }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java Tue Sep  1 20:16:19 2009
@@ -26,34 +26,17 @@
 import javax.persistence.criteria.QueryBuilder.In;
 
 import org.apache.openjpa.kernel.exps.ExpressionFactory;
-import org.apache.openjpa.kernel.exps.Value;
 import org.apache.openjpa.persistence.meta.MetamodelImpl;
 
 /**
  * Expression for Criteria query.
  * 
- * @author Pinaki Poddar
- *
  * @param <X> the type of the value this expression represents.
+ * 
+ * @author Pinaki Poddar
+ * @since 2.0.0
  */
-public abstract class ExpressionImpl<X> extends SelectionImpl<X> 
-    implements CriteriaExpression<X> {
-    abstract org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, MetamodelImpl model,
-            CriteriaQueryImpl<?> q);
-    
-    org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, MetamodelImpl model,
-        CriteriaQueryImpl<?> q) {
-        return factory.asExpression(toValue(factory, model, q));
-    }
-    
-    public void acceptVisit(CriteriaExpressionVisitor visitor) {
-        if (!visitor.isVisited(this)) {
-            visitor.enter(this);
-            visitor.exit(this);
-        }
-    }
-    
-
+public abstract class ExpressionImpl<X> extends SelectionImpl<X> implements Expression<X> {
     /**
      * @param cls the type of the evaluated result of the expression
      */
@@ -137,4 +120,12 @@
     public Predicate isNull() {
     	return new Expressions.IsNull(this);
     }
+    
+    abstract org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, MetamodelImpl model,
+            CriteriaQueryImpl<?> q);
+    
+    org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, MetamodelImpl model,
+        CriteriaQueryImpl<?> q) {
+        return factory.asExpression(toValue(factory, model, q));
+    }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java Tue Sep  1 20:16:19 2009
@@ -21,7 +21,11 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
 
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Predicate;
@@ -34,6 +38,7 @@
 import org.apache.openjpa.kernel.exps.Value;
 import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder;
 import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.persistence.criteria.CriteriaExpressionVisitor.TraversalStyle;
 import org.apache.openjpa.persistence.meta.MetamodelImpl;
 import org.apache.openjpa.persistence.meta.Types;
 
@@ -49,7 +54,10 @@
  *
  */
 public class Expressions {
-	
+    static final String OPEN_BRACE = "(";
+    static final String CLOSE_BRACE = ")";
+    static final String COMMA = ",";
+    
     /**
      * Convert the given Criteria expression to a corresponding kernel value 
      * using the given ExpressionFactory.
@@ -64,16 +72,112 @@
              q.getParameterTypes(), q.toString());
      }
      
-     static void acceptVisit(CriteriaExpressionVisitor visitor, Expression<?>...exprs) {
-         if (exprs == null)
+     /**
+      * Visits the given expression and the given children recursively.
+      * The order of traversal depends on the parent and is determined by the visitor.
+      */
+     static void acceptVisit(CriteriaExpressionVisitor visitor, CriteriaExpression parent, Expression<?>...exprs) {
+         if (parent == null)
              return;
-         for (Expression<?> e : exprs) {
-             if (e != null)
-                 ((ExpressionImpl<?>)e).acceptVisit(visitor);
+         TraversalStyle traversal = visitor.getTraversalStyle(parent);
+         switch (traversal) {
+         case INFIX : 
+             if (exprs == null || exprs.length == 0) {
+                 visitor.enter(parent);
+                 visitor.exit(parent);
+                 return;
+             }
+             for (int i = 0; i < exprs.length; i++) {
+                 ExpressionImpl<?> e = (ExpressionImpl<?>)exprs[i];
+                 if (e != null) e.acceptVisit(visitor);
+                 if (i + 1 != exprs.length) {
+                     visitor.enter(parent);
+                     visitor.exit(parent);
+                 }
+             }
+             break;
+         case POSTFIX:
+             visitChildren(visitor,exprs);
+             visitor.enter(parent);
+             visitor.exit(parent);
+             break;
+         case PREFIX :
+             visitor.enter(parent);
+             visitor.exit(parent);
+             visitChildren(visitor,exprs);
+             break;
+         case FUNCTION:
+             visitor.enter(parent);
+             visitChildren(visitor, exprs);
+             visitor.exit(parent);
+             break;
          }
      }
-    
-    /**
+     
+     static void visitChildren(CriteriaExpressionVisitor visitor, Expression<?>...exprs) {
+         for (int i = 0; exprs != null && i < exprs.length; i++) {
+             ExpressionImpl<?> e = (ExpressionImpl<?>)exprs[i];
+             if (e != null) e.acceptVisit(visitor);
+         }
+     }
+     
+     /**
+      * Renders the given expressions as a list of values separated by the given connector.
+      */
+     static StringBuilder asValue(CriteriaQueryImpl<?> q, Expression<?>[] exps, String connector) {
+         StringBuilder buffer = new StringBuilder();
+         if (exps == null) return buffer;
+         for (int i = 0; i < exps.length; i++) {
+             buffer.append(((ExpressionImpl<?>)exps[i]).asValue(q));
+             if (i+1 != exps.length) {
+                 buffer.append(connector);
+             }
+         }
+         return buffer;
+     }
+     
+     /**
+      * Renders the given arguments as a list of values separated by the given connector.
+      */
+     static StringBuilder asValue(CriteriaQueryImpl<?> q, Object...params) {
+         StringBuilder buffer = new StringBuilder();
+         if (params == null) return buffer;
+         for (int i = 0; i < params.length; i++) {
+             Object o = params[i];
+             if (o == null) {
+                 if (i+1 < params.length && params[i+1].equals(COMMA)) {
+                     i++;
+                 }
+                 continue;
+             }
+             if (o instanceof CriteriaExpression) {
+                 buffer.append(((CriteriaExpression)o).asValue(q));
+             } else {
+                 buffer.append(o);
+             }
+         }
+         return buffer;
+     }
+     
+     /**
+      * Return a list that is either empty (if the given list is null) or a list
+      * whose mutation do not impact the original list.
+      */
+     static <X> List<X> returnCopy(List<X> list) {
+         return list == null ? new ArrayList<X>() : new CopyOnWriteArrayList<X>(list);
+     }
+     
+     /**
+      * Return a set that is either empty (if the given set is null) or a set
+      * whose mutation do not impact the original list.
+      */
+     static <X> Set<X> returnCopy(Set<X> set) {
+         return set == null ? new HashSet<X>() : new CopyOnWriteArraySet<X>(set);
+     }
+     
+
+
+     /**
      * Unary Functional Expression applies a unary function on a input operand Expression.
      *
      * @param <X> the type of the resultant expression
@@ -93,8 +197,7 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, e);
+            Expressions.acceptVisit(visitor, this, e);
         }
     }
     
@@ -117,8 +220,7 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, e1, e2);
+            Expressions.acceptVisit(visitor, this, e1, e2);
         }
     }
     
@@ -143,8 +245,7 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, args);
+            Expressions.acceptVisit(visitor, this, args);
         }
     }
    
@@ -169,8 +270,7 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, e1, e2);
+            Expressions.acceptVisit(visitor, this, e1, e2);
         }
     }
     
@@ -184,6 +284,10 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.abs(Expressions.toValue(e, factory, model, q));
         }
+        
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "ABS", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static class Count extends UnaryFunctionalExpression<Long> {
@@ -203,6 +307,12 @@
             Value v = factory.count(Expressions.toValue(e, factory, model, q));
             return _distinct ? factory.distinct(v) : v;
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "COUNT", OPEN_BRACE, _distinct ? "DISTINCT"+OPEN_BRACE : "", 
+                e, _distinct ? CLOSE_BRACE : "", CLOSE_BRACE);
+        }
     }
 
     public static class Avg extends UnaryFunctionalExpression<Double> {
@@ -214,6 +324,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.avg(Expressions.toValue(e, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "AVG", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static class Sqrt extends UnaryFunctionalExpression<Double> {
@@ -225,6 +340,10 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.sqrt(Expressions.toValue(e, factory, model, q));
         }
+        
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "SQRT", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static class Max<X> extends UnaryFunctionalExpression<X> {
@@ -236,6 +355,10 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.max(Expressions.toValue(e, factory, model, q));
         }
+        
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "MAX", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
 
     public static class Min<X> extends UnaryFunctionalExpression<X> {
@@ -247,6 +370,10 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.min(Expressions.toValue(e, factory, model, q));
         }
+        
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "MIN", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static class Size extends UnaryFunctionalExpression<Integer> {
@@ -267,11 +394,16 @@
                 
             return factory.size(val);
         }
+        
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "SIZE", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static class DatabaseFunction<T> extends FunctionalExpression<T> {
         private final String functionName;
         private final Class<T> resultType;
+       
         public  DatabaseFunction(String name, Class<T> resultType, Expression<?>... exps) {
             super(resultType, exps);
             functionName = name;
@@ -283,6 +415,10 @@
             return factory.newFunction(functionName, getJavaType(), 
                 new Expressions.ListArgument(resultType, args).toValue(factory, model, q));
         }
+        
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, functionName, OPEN_BRACE, Expressions.asValue(q, args, COMMA), CLOSE_BRACE);
+        }
     }
 
     
@@ -295,6 +431,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.type(Expressions.toValue(e, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "TYPE", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
 
     public static class Cast<B> extends UnaryFunctionalExpression<B> {
@@ -306,6 +447,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.cast(Expressions.toValue(e, factory, model, q), getJavaType());
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, OPEN_BRACE, getJavaType().getSimpleName(), CLOSE_BRACE, e);
+        }
     }
     
     public static class Concat extends BinarayFunctionalExpression<String> {
@@ -327,6 +473,11 @@
                 Expressions.toValue(e1, factory, model, q), 
                 Expressions.toValue(e2, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "CONCAT", OPEN_BRACE, e1, COMMA, e2, CLOSE_BRACE);
+        }
     }
     
     public static class Substring extends UnaryFunctionalExpression<String> {
@@ -334,7 +485,7 @@
         private ExpressionImpl<Integer> len;
         
         public Substring(Expression<String> s, Expression<Integer> from, Expression<Integer> len) {
-            super(s);
+            super(String.class, s);
             this.from = (ExpressionImpl<Integer>)from;
             this.len  = (ExpressionImpl<Integer>)len;
         }
@@ -367,6 +518,11 @@
             super.acceptVisit(visitor);
             Expressions.acceptVisit(visitor, from, len);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "SUBSTRING", OPEN_BRACE, e, COMMA, from, COMMA, len, CLOSE_BRACE);
+        }
     }
 
     public static class Locate extends ExpressionImpl<Integer> {
@@ -412,8 +568,12 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, pattern, from, path);
+            Expressions.acceptVisit(visitor, this, pattern, from, path);
+        }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "LOCATE", OPEN_BRACE, pattern, COMMA, path, CLOSE_BRACE);
         }
     }
     
@@ -422,8 +582,7 @@
         static Trimspec defaultSpec = Trimspec.BOTH;
         private Trimspec ts;
         
-        public Trim(Expression<String> x, Expression<Character> y, 
-            Trimspec ts) {
+        public Trim(Expression<String> x, Expression<Character> y, Trimspec ts) {
             super(String.class, x, y);
             this.ts = ts;
         }
@@ -462,6 +621,11 @@
                 Expressions.toValue(e1, factory, model, q), 
                 Expressions.toValue(e2, factory, model, q), spec);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "TRIM", OPEN_BRACE, e1, COMMA, e2, CLOSE_BRACE);
+        }        
     }
     
     public static class Sum<N extends Number> extends BinarayFunctionalExpression<N> {
@@ -489,7 +653,14 @@
                    Expressions.toValue(e1, factory, model, q), 
                    Expressions.toValue(e2, factory, model, q));
         }
-    }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return e2 == null 
+               ? Expressions.asValue(q, "SUM", OPEN_BRACE, e1, CLOSE_BRACE)
+               : Expressions.asValue(q, e1, " + ", e2);
+        }        
+     }
     
     public static class Product<N extends Number> extends BinarayFunctionalExpression<N> {
         public Product(Expression<? extends Number> x, Expression<? extends Number> y) {
@@ -510,6 +681,11 @@
                 Expressions.toValue(e1, factory, model, q), 
                 Expressions.toValue(e2, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, " * " ,e2);
+        }        
     }
     
     public static class Diff<N extends Number> extends BinarayFunctionalExpression<N> {
@@ -531,6 +707,11 @@
                 Expressions.toValue(e1, factory, model, q), 
                 Expressions.toValue(e2, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, " - " ,e2);
+        }        
     }
 
     
@@ -553,6 +734,11 @@
                 Expressions.toValue(e1, factory, model, q), 
                 Expressions.toValue(e2, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, "%" ,e2);
+        }        
     }
 
     public static class Mod extends BinarayFunctionalExpression<Integer> {
@@ -572,6 +758,11 @@
                 Expressions.toValue(e1, factory, model, q), 
                 Expressions.toValue(e2, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "MOD", OPEN_BRACE, e1, COMMA, e2, CLOSE_BRACE);
+        }        
     }
 
     public static class CurrentDate extends ExpressionImpl<java.sql.Date> {
@@ -583,6 +774,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.getCurrentDate();
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return new StringBuilder("CURRENT_DATE");
+        }
     }
     
     public static class CurrentTime extends ExpressionImpl<java.sql.Time> {
@@ -594,6 +790,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.getCurrentTime();
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return new StringBuilder("CURRENT_TIME");
+        }
     }
     
     public static class CurrentTimestamp extends ExpressionImpl<java.sql.Timestamp> {
@@ -605,6 +806,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.getCurrentTimestamp();
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return new StringBuilder("CURRENT_TIMESTAMP");
+        }
     }
 
     public static class Equal extends BinaryLogicalExpression {
@@ -629,6 +835,11 @@
             Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
             return isNegated() ? factory.notEqual(val1, val2) : factory.equal(val1, val2);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, " = ", e2);
+        }        
     }
     
     public static class GreaterThan extends BinaryLogicalExpression {
@@ -648,6 +859,11 @@
             Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q); 
             return factory.greaterThan(val1, val2);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, " > ", e2);
+        }        
     }
     
     public static class GreaterThanEqual extends BinaryLogicalExpression {
@@ -667,6 +883,11 @@
             Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q); 
             return factory.greaterThanEqual(val1, val2);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, " >= ", e2);
+        }        
     }
    
     public static class LessThan extends BinaryLogicalExpression {
@@ -686,6 +907,11 @@
             Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q); 
             return factory.lessThan(val1, val2);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, " < ", e2);
+        }        
     }
     
     public static class LessThanEqual extends BinaryLogicalExpression {
@@ -705,16 +931,34 @@
             Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q); 
             return factory.lessThanEqual(val1, val2);
         }
+        
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e1, " <= ", e2);
+        }        
     }
 
     public static class Between<Y extends Comparable<Y>> extends PredicateImpl.And {
+        private final ExpressionImpl<?> e;
+        private final ExpressionImpl<?> v1;
+        private final ExpressionImpl<?> v2;
+        
         public Between(Expression<? extends Y> v, Expression<? extends Y> x, Expression<? extends Y> y) {
             super(new GreaterThanEqual(v,x), new LessThanEqual(v,y));
+            e = (ExpressionImpl<?>)v;
+            v1 = (ExpressionImpl<?>)x;
+            v2 = (ExpressionImpl<?>)y;
         }
         
         public Between(Expression<? extends Y> v, Y x, Y y) {
             this(v, new Constant<Y>(x), new Constant<Y>(y));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e, " BETWEEN ", v1, " AND ", v2);
+        }
     }
     
     public static class Constant<X> extends ExpressionImpl<X> {
@@ -762,10 +1006,29 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            if (arg instanceof CriteriaExpression) {
-                ((CriteriaExpression<?>)arg).acceptVisit(visitor);
+            Expressions.acceptVisit(visitor, this, arg instanceof Expression ? ((Expression)arg) : null);
+        }
+        
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            if (arg == null)
+                return new StringBuilder("NULL");
+            Class<?> literalClass = getJavaType();
+            if (arg instanceof ParameterExpressionImpl) {
+                return ((ParameterExpressionImpl<?>)arg).asValue(q);
+            } else if (Number.class.isAssignableFrom(literalClass)) {
+                return new StringBuilder(arg.toString());
+            } else if (Boolean.class.isAssignableFrom(literalClass)) {
+                return new StringBuilder(arg.toString());
+            } else if (String.class.isAssignableFrom(literalClass)) {
+                return new StringBuilder("'").append(arg.toString()).append("'");
+            } else if (Enum.class.isAssignableFrom(literalClass)) {
+                return new StringBuilder(arg.toString());
+            } else if (Class.class.isAssignableFrom(literalClass)) {
+                return new StringBuilder(((Class)arg).getSimpleName());
+            } else if (Collection.class.isAssignableFrom(literalClass)) {
+                return new StringBuilder(((Collection)arg).toString());
             }
+            return new StringBuilder(arg.toString());
         }
     }
     
@@ -792,6 +1055,11 @@
             super.acceptVisit(visitor);
             Expressions.acceptVisit(visitor, collection);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, collection, " IS EMPTY");
+        }
     }
     
     public static class IsNotEmpty extends PredicateImpl {
@@ -817,6 +1085,11 @@
             super.acceptVisit(visitor);
             Expressions.acceptVisit(visitor, collection);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, collection, " IS NOT EMPTY");
+        }
     }
 
     
@@ -833,6 +1106,11 @@
             v.setMetaData(meta);
             return factory.index(v);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "INDEX", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static class IsMember<E> extends PredicateImpl {
@@ -840,6 +1118,7 @@
         final ExpressionImpl<?> collection;
         
         public IsMember(Class<E> t, Expression<E> element, Expression<?> collection) {
+            super();
             this.element = (ExpressionImpl<E>)element;
             this.collection = (ExpressionImpl<?>)collection;
         }
@@ -863,13 +1142,18 @@
             org.apache.openjpa.kernel.exps.Expression contains = factory.contains(
                 Expressions.toValue(collection, factory, model, q), 
                 Expressions.toValue(element, factory, model, q));
-            return _negated ? factory.not(contains) : contains;
+            return isNegated() ? factory.not(contains) : contains;
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
             super.acceptVisit(visitor);
             Expressions.acceptVisit(visitor, collection, element);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, element, isNegated() ? "NOT " : "", "MEMBER OF ", collection);
+        }
     }
     
     public static class Like extends PredicateImpl {
@@ -927,9 +1211,13 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, str, pattern, escapeChar);
+            Expressions.acceptVisit(visitor, this, str, pattern, escapeChar);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, str, " LIKE ", pattern);
+        }        
     }
     
     public static class Coalesce<T> extends ExpressionImpl<T> implements QueryBuilder.Coalesce<T> {
@@ -960,9 +1248,14 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, values.toArray(new ExpressionImpl[values.size()]));
+            Expressions.acceptVisit(visitor, this, values.toArray(new ExpressionImpl[values.size()]));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "COALESCE", OPEN_BRACE, Expressions.asValue(q, values == null 
+                    ? null : values.toArray(new Expression<?>[values.size()]), COMMA), CLOSE_BRACE);
+        }        
     }
     
     public static class Nullif<T> extends ExpressionImpl<T> {
@@ -990,9 +1283,13 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, val1, val2);
+            Expressions.acceptVisit(visitor, this, val1, val2);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "NULLIF", OPEN_BRACE, val1, COMMA, val2, CLOSE_BRACE);
+        }        
     }
 
     public static class IsNull extends PredicateImpl {
@@ -1019,6 +1316,11 @@
             super.acceptVisit(visitor);
             Expressions.acceptVisit(visitor, e);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e, " IS NULL");
+        }
     }
     
     public static class IsNotNull extends PredicateImpl {
@@ -1045,6 +1347,11 @@
             super.acceptVisit(visitor);
             Expressions.acceptVisit(visitor, e);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, e, " IS NOT NULL");
+        }
     }
     
     
@@ -1052,7 +1359,7 @@
         final ExpressionImpl<T> e;
         private boolean negate;
         public In(Expression<?> e) {
-            super((Predicate[])null);
+            super();
             this.e = (ExpressionImpl<T>)e;
         }
         
@@ -1083,7 +1390,7 @@
                 Expressions.Equal e = (Expressions.Equal)_exps.get(0);
                 ExpressionImpl<?> e2 = e.e2;
                 ExpressionImpl<?> e1 = e.e1;
-               Value val2 = Expressions.toValue(e2, factory, model, q);
+                Value val2 = Expressions.toValue(e2, factory, model, q);
                 if (!(val2 instanceof Literal)) {
                      Value val1 = Expressions.toValue(e1, factory, model, q);
                     Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
@@ -1108,13 +1415,22 @@
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
             super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, e);
+            Expressions.acceptVisit(visitor, this, e);
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            StringBuilder buffer = Expressions.asValue(q, e, negate ? " NOT IN " : " IN ", OPEN_BRACE);
+            for (int i = 0; i < _exps.size(); i++) {
+                buffer.append(((Equal)_exps.get(i)).e2.asValue(q)).append(i+1 == _exps.size() ? CLOSE_BRACE : COMMA);
+            }
+            return buffer;
+        }        
     }
     
     public static class Case<T> extends ExpressionImpl<T> implements QueryBuilder.Case<T> {
         private final List<Expression<? extends T>> thens = new ArrayList<Expression<? extends T>>();
-        private final List<Expression<Boolean>> whens     = new ArrayList<Expression<Boolean>>();
+        private final List<Expression<Boolean>> whens = new ArrayList<Expression<Boolean>>();
         private Expression<? extends T> otherwise;
 
         public Case(Class<T> cls) {
@@ -1146,8 +1462,8 @@
             int size = whens.size();
             org.apache.openjpa.kernel.exps.Expression[] exps = new org.apache.openjpa.kernel.exps.Expression[size];
             for (int i = 0; i < size; i++) {
-                org.apache.openjpa.kernel.exps.Expression expr = ((Expressions.BinaryLogicalExpression)whens.get(i)).
-                    toKernelExpression(factory, model, q);
+                org.apache.openjpa.kernel.exps.Expression expr = 
+                    ((ExpressionImpl<?>)whens.get(i)).toKernelExpression(factory, model, q);
                 Value action = Expressions.toValue((ExpressionImpl<?>)thens.get(i), factory, model, q);
                 exps[i] = factory.whenCondition(expr, action);
             }
@@ -1157,10 +1473,24 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, thens.toArray(new ExpressionImpl[thens.size()]));
-            Expressions.acceptVisit(visitor, whens.toArray(new ExpressionImpl[whens.size()]));
-            Expressions.acceptVisit(visitor, otherwise);
+            visitor.enter(this);
+            for (int i = 0; i < whens.size(); i++) {
+                Expressions.visitChildren(visitor, whens.get(i));
+                Expressions.visitChildren(visitor, thens.get(i));
+            }
+            Expressions.visitChildren(visitor, otherwise);
+            visitor.exit(this);
+        }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            StringBuilder buffer = new StringBuilder("CASE ");
+            int size = whens.size();
+            for (int i = 0; i < size; i++) {
+                buffer.append(Expressions.asValue(q, " WHEN ", whens.get(i), " THEN ", thens.get(i)));
+            }
+            buffer.append(Expressions.asValue(q, " ELSE ", otherwise, " END"));
+            return buffer;
         }
     }
 
@@ -1219,10 +1549,25 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, thens.toArray(new ExpressionImpl[thens.size()]));
-            Expressions.acceptVisit(visitor, whens.toArray(new ExpressionImpl[whens.size()]));
-            Expressions.acceptVisit(visitor, otherwise, caseOperand);
+            visitor.enter(this);
+            Expressions.visitChildren(visitor, caseOperand);
+            for (int i = 0; i < whens.size(); i++) {
+                Expressions.visitChildren(visitor, whens.get(i));
+                Expressions.visitChildren(visitor, thens.get(i));
+            }
+            Expressions.visitChildren(visitor, otherwise);
+            visitor.exit(this);
+        }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            StringBuilder buffer = new StringBuilder("CASE ");
+            int size = whens.size();
+            for (int i = 0; i < size; i++) {
+                buffer.append(Expressions.asValue(q, " WHEN ", whens.get(i), " THEN ", thens.get(i)));
+            }
+            buffer.append(Expressions.asValue(q, " ELSE ", otherwise, " END"));
+            return buffer;
         }
     }
 
@@ -1233,8 +1578,12 @@
         
         @Override
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
-            return factory.toLowerCase(
-                Expressions.toValue(e, factory, model, q));
+            return factory.toLowerCase(Expressions.toValue(e, factory, model, q));
+        }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "LOWER", OPEN_BRACE, e, CLOSE_BRACE);
         }
     }
 
@@ -1244,10 +1593,13 @@
         }
         
         @Override
-        public Value toValue(ExpressionFactory factory, MetamodelImpl model,
-            CriteriaQueryImpl<?> q) {
-            return factory.toUpperCase(
-                Expressions.toValue(e, factory, model, q));
+        public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
+            return factory.toUpperCase(Expressions.toValue(e, factory, model, q));
+        }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "UPPER", OPEN_BRACE, e, CLOSE_BRACE);
         }
     }
 
@@ -1260,6 +1612,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.stringLength(Expressions.toValue(e, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "LENGTH", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static abstract class SubqueryPredicate<X> extends PredicateImpl {
@@ -1271,8 +1628,7 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, e);
+            Expressions.acceptVisit(visitor, this, e);
         }
     }
      
@@ -1285,8 +1641,7 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            if (e != null) e.acceptVisit(visitor);
+            Expressions.acceptVisit(visitor, this, e);
         }
     }
 
@@ -1307,6 +1662,11 @@
                 factory.isNotEmpty(Expressions.toValue(e, factory, model, q));
             return isNegated() ? factory.not(exists) : exists;
         }        
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, isNegated() ? "NOT" : "", " EXISTS", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
     
     public static class All<X> extends SubqueryExpression<X> {
@@ -1319,6 +1679,11 @@
             CriteriaQueryImpl<?> q) {
             return factory.all(Expressions.toValue(e, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "ALL", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
 
     public static class Any<X> extends SubqueryExpression<X> {
@@ -1330,6 +1695,11 @@
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
             return factory.any(Expressions.toValue(e, factory, model, q));
         }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "ANY", OPEN_BRACE, e, CLOSE_BRACE);
+        }
     }
 
     public static class Not<X> extends PredicateImpl {
@@ -1351,8 +1721,12 @@
         }        
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, e);
+            Expressions.acceptVisit(visitor, this, e);
+        }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return Expressions.asValue(q, "NOT", OPEN_BRACE, e, CLOSE_BRACE);
         }
     }
     
@@ -1372,8 +1746,12 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, actual);
+            Expressions.acceptVisit(visitor, this, actual);
+        }
+        
+        @Override
+        public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+            return actual.asValue(q);
         }
     }
     
@@ -1403,9 +1781,30 @@
         }
         
         public void acceptVisit(CriteriaExpressionVisitor visitor) {
-            super.acceptVisit(visitor);
-            Expressions.acceptVisit(visitor, _args);
+            Expressions.acceptVisit(visitor, this, _args);
         }
     }
 
+    public static class DelegatingExpression<X> extends ExpressionImpl<X> {
+        final ExpressionImpl<? extends X> _delegate;
+        public DelegatingExpression(ExpressionImpl<? extends X> del) {
+            super((Class<X>)del.getJavaType());
+            _delegate = del;
+        }
+        
+        @Override
+        Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
+            return _delegate.toValue(factory, model, q);
+        }
+        
+        @Override
+        public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
+            ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
+            return _delegate.toKernelExpression(factory, model, q);
+        }
+        
+        public void acceptVisit(CriteriaExpressionVisitor visitor) {
+            Expressions.acceptVisit(visitor, this, _delegate);
+        }
+    }
 }

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java?rev=810212&r1=810211&r2=810212&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java Tue Sep  1 20:16:19 2009
@@ -28,7 +28,6 @@
 import javax.persistence.criteria.JoinType;
 import javax.persistence.criteria.ListJoin;
 import javax.persistence.criteria.MapJoin;
-import javax.persistence.criteria.Path;
 import javax.persistence.criteria.SetJoin;
 import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.CollectionAttribute;
@@ -39,12 +38,10 @@
 import javax.persistence.metamodel.SetAttribute;
 import javax.persistence.metamodel.SingularAttribute;
 import javax.persistence.metamodel.Type;
-import javax.persistence.metamodel.PluralAttribute.CollectionType;
 import javax.persistence.metamodel.Type.PersistenceType;
 
 import org.apache.openjpa.persistence.meta.AbstractManagedType;
 import org.apache.openjpa.persistence.meta.Members;
-import org.apache.openjpa.persistence.meta.Members.Member;
 
 /**
  * Represents a bound type, usually an entity that appears in the from clause, 
@@ -83,7 +80,7 @@
      *  Return the joins that have been made from this receiver.
      */
     public java.util.Set<Join<X, ?>> getJoins() {
-        return _joins;
+        return Expressions.returnCopy(_joins);
     }
 
     /**
@@ -272,7 +269,7 @@
     }
 
     public java.util.Set<Fetch<X, ?>> getFetches() {
-        return _fetches;
+        return Expressions.returnCopy(_fetches);
     }
     
     private <Y> Fetch<X,Y> addFetch(Members.Member<? super X, Y> member, 
@@ -283,4 +280,9 @@
         _fetches.add(fetch);
         return fetch;
     }
+    
+    public void acceptVisit(CriteriaExpressionVisitor visitor) {
+        Expressions.acceptVisit(visitor, this, 
+                _joins == null ? null : _joins.toArray(new ExpressionImpl<?>[_joins.size()]));
+    }
 }

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=810212&r1=810211&r2=810212&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 Tue Sep  1 20:16:19 2009
@@ -133,7 +133,7 @@
             boolean bind = true;
             java.util.List<Join<?,?>> corrJoins = null;
             org.apache.openjpa.kernel.exps.Expression join = null;
-            if (_correlatedPath == null) {
+            if (!isCorrelated()) {
                 if (subquery != null) {
                     corrJoins = subquery.getCorrelatedJoins();
                     org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
@@ -247,6 +247,19 @@
                 }
             }
         }
+        
+        @Override
+        public StringBuilder asVariable(CriteriaQueryImpl<?> q) {
+            String varName = "?";
+            Value var = q.getRegisteredVariable(this);
+            if (var == null) {
+                varName = ""+_member.fmd.getName().charAt(0);
+            } else {
+                varName = var.getName();
+            }
+            return new StringBuilder(joinType.toString()).append(" JOIN ")
+                .append(super.asVariable(q)).append(" " + varName);
+        }
     }
     
     /**
@@ -268,16 +281,14 @@
             allowNull = joinType != JoinType.INNER;
         }
         
-        public JoinType getJoinType() {
+        public final JoinType getJoinType() {
             return joinType;
         }
 
-        public FromImpl<?, Z> getParent() {
-            return (FromImpl<?, Z>) _parent;
-        }
-        
-        @Override
-        public FromImpl<?, Z> getParentPath() {
+        /**
+         * Gets the parent of this join.
+         */
+        public final FromImpl<?, Z> getParent() {
             return (FromImpl<?, Z>) _parent;
         }
         
@@ -337,7 +348,7 @@
             PathImpl<?,?> corrRoot = getCorrelatedRoot(subquery);
 
             PathImpl<?,?> correlatedParentPath = null;
-            if (_correlatedPath == null) {
+            if (!isCorrelated()) {
                 if (subquery != null) {
                     corrJoins = subquery.getCorrelatedJoins();
                     org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
@@ -351,8 +362,9 @@
                         if (c.isRegistered(_parent)) { 
                             Value var = c.getRegisteredVariable(_parent);
                             path = factory.newPath(var);
-                        } else 
+                        } else {
                             path = factory.newPath(subQ);
+                        }
                         path.setMetaData(meta);
                         path.get(_member.fmd, false);
                         path.setSchemaAlias(c.getAlias(_parent));
@@ -362,9 +374,9 @@
                     path = factory.newPath(var);
                     path.setMetaData(meta);
                     path.get(_member.fmd, false);
-                } else            
+                } else {           
                     path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
-
+                }
                 Class<?> type = meta == null ? AbstractExpressionBuilder.TYPE_OBJECT : meta.getDescribedType(); 
                 if (bind) {
                     Value var = factory.newBoundVariable(c.getAlias(this), type);
@@ -386,10 +398,10 @@
                 if (corrJoins != null && corrJoins.contains(_parent)) {
                     Value var = getVariableForCorrPath(subquery, correlatedParentPath);
                     parentPath = factory.newPath(var);
-                } else 
+                } else {
                     parentPath = (org.apache.openjpa.kernel.exps.Path)
                         correlatedParentPath.toValue(factory, model, c);
-                
+                }
                 parentPath.get(_member.fmd, allowNull);
                 parentPath.setSchemaAlias(c.getAlias(correlatedParentPath));
                 if (c.ctx().getParent() != null && c.ctx().getVariable(parentPath.getSchemaAlias()) == null) 
@@ -404,11 +416,11 @@
                 if (_member.fmd.getDeclaredTypeCode() == JavaTypes.MAP)
                     c.registerVariable(this, var, parentPath);
                 
-                if (_member.fmd.isElementCollection()) 
+                if (_member.fmd.isElementCollection()) {
                     filter = CriteriaExpressionBuilder.and(factory, join, filter);
-                else 
+                } else { 
                     filter = factory.equal(parentPath, path);
-                
+                }
                 return CriteriaExpressionBuilder.and(factory, expr, filter);
             }
         }
@@ -433,13 +445,12 @@
      */
     public static class Collection<Z,E> extends AbstractCollection<Z,java.util.Collection<E>,E> 
         implements CollectionJoin<Z,E>{
-        public Collection(FromImpl<?,Z> parent, 
-            Members.CollectionAttributeImpl<? super Z, E> member, JoinType jt) {
+        public Collection(FromImpl<?,Z> parent, Members.CollectionAttributeImpl<? super Z, E> member, JoinType jt) {
             super(parent, member, jt);
         }
         
         public CollectionAttribute<? super Z, E> getModel() {
-            return (CollectionAttribute<? super Z, E>)_member.getType();
+            return (CollectionAttribute<? super Z, E>)_member;
         }
     }
     
@@ -450,7 +461,7 @@
      * @param <E> the type of the the set attribute elements
      */
     public static class Set<Z,E> extends AbstractCollection<Z,java.util.Set<E>,E> 
-        implements SetJoin<Z,E>{
+        implements SetJoin<Z,E> {
         public Set(FromImpl<?,Z> parent, Members.SetAttributeImpl<? super Z, E> member, JoinType jt) {
             super(parent, member, jt);
         }
@@ -470,13 +481,12 @@
     public static class List<Z,E> extends AbstractCollection<Z,java.util.List<E>,E> 
         implements ListJoin<Z,E> {
         
-        public List(FromImpl<?,Z> parent, 
-            Members.ListAttributeImpl<? super Z, E> member, JoinType jt) {
+        public List(FromImpl<?,Z> parent, Members.ListAttributeImpl<? super Z, E> member, JoinType jt) {
             super(parent, member, jt);
         }
         
         public ListAttribute<? super Z, E> getModel() {
-            return (ListAttribute<? super Z, E>)_member.getType();
+            return (ListAttribute<? super Z, E>)_member;
         }
         
         public Expression<Integer> index() {
@@ -509,8 +519,8 @@
         }
         
         /**
-         * Create a pseudo-attribute of a pseudo-managed type for java.util.Map&lt;K,V&gt; to represent its keys as 
-         * a pseudo-attribute of type java.util.Set&lt;V&gt;.
+         * Create a pseudo-attribute of a pseudo-managed type for java.util.Map&lt;K,V&gt; 
+         * to represent its keys of type java.util.Set&lt;V&gt;.
          */
         public Join<java.util.Map<K, V>, K> joinKey(JoinType jt) {
             AbstractManagedType<java.util.Map<K,V>> pseudoOwner = (AbstractManagedType<java.util.Map<K,V>>)
@@ -564,12 +574,18 @@
         */
        @Override
        public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> c) {
-           SubqueryImpl<?> subquery = c.getDelegator();
-           PathImpl<?,?> parent = map.getInnermostParentPath();
            Value val = c.getRegisteredVariable(map);
            org.apache.openjpa.kernel.exps.Path path = factory.newPath(val);
            return factory.getKey(path);
        }
+       
+       @Override
+       public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+           StringBuilder buffer = new StringBuilder("KEY(");
+           Value var = q.getRegisteredVariable(map);
+           buffer.append(var != null ? var.getName() : map.asValue(q)).append(")");
+           return buffer;
+       }
    }
        
    public static class MapEntry<K,V> extends ExpressionImpl<java.util.Map.Entry<K,V>> {
@@ -591,6 +607,14 @@
            org.apache.openjpa.kernel.exps.Path var = factory.newPath(val);
            return factory.mapEntry(path, var);
        }
+       
+       @Override
+       public StringBuilder asValue(CriteriaQueryImpl<?> q) {
+           StringBuilder buffer = new StringBuilder("ENTRY(");
+           Value var = q.getRegisteredVariable(map);
+           buffer.append(var != null ? var.getName() : map.asValue(q)).append(")");
+           return buffer;
+       }
    }
    
    /**



Mime
View raw message