Return-Path: Delivered-To: apmail-openjpa-commits-archive@www.apache.org Received: (qmail 7678 invoked from network); 1 Sep 2009 20:16:45 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 1 Sep 2009 20:16:45 -0000 Received: (qmail 11706 invoked by uid 500); 1 Sep 2009 20:16:45 -0000 Delivered-To: apmail-openjpa-commits-archive@openjpa.apache.org Received: (qmail 11669 invoked by uid 500); 1 Sep 2009 20:16:45 -0000 Mailing-List: contact commits-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list commits@openjpa.apache.org Received: (qmail 11660 invoked by uid 99); 1 Sep 2009 20:16:45 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 01 Sep 2009 20:16:45 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 01 Sep 2009 20:16:42 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0AD0923888E9; Tue, 1 Sep 2009 20:16:22 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commits@openjpa.apache.org From: ppoddar@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090901201622.0AD0923888E9@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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> getCompoundSelectionItems() { - return _args == null ? Collections.EMPTY_LIST : new CopyOnWriteArrayList>(_args); + return Expressions.returnCopy(_args); } void assertNoCompoundSelection(Selection...args) { @@ -94,7 +94,18 @@ } } - public abstract FillStrategy getFillStrategy(); + abstract FillStrategy 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 Predicate example(From from, T example, ComparisonStyle style, Attribute... excludes) { + public Predicate qbe(From from, T example, ComparisonStyle style, Attribute... excludes) { if (from == null) throw new NullPointerException(); if (example == null) { @@ -733,13 +733,25 @@ } ManagedType type = (ManagedType)_model.type(example.getClass()); return new CompareByExample(this, type, from, example, - style == null ? comparisonStyle() : style, excludes); + style == null ? qbeStyle() : style, excludes); + } + + public Predicate qbe(From from, T example, ComparisonStyle style) { + return qbe(from, example, style, null); + } + + public Predicate qbe(From from, T example, Attribute... excludes) { + return qbe(from, example, qbeStyle(), excludes); + } + + public Predicate qbe(From 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 + * @since 2.0.0 */ -public interface CriteriaExpression extends Expression { +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> 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> _visited = new HashSet>(); + protected final Set _visited = new HashSet(); /** - * 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 implements CriteriaQuery, AliasContext { +public class CriteriaQueryImpl implements OpenJPACriteriaQuery, AliasContext { private static final Localizer _loc = Localizer.forPackage(CriteriaQueryImpl.class); private final MetamodelImpl _model; @@ -71,13 +73,13 @@ private PredicateImpl _where; private List _orders; private LinkedMap/*, Class>*/ _params; - private Selection _selection; + private Selection _selection; private List> _selections; private List> _groups; private PredicateImpl _having; private List> _subqueries; private Boolean _distinct; - private SubqueryImpl _delegator; + private final SubqueryImpl _delegator; private final Class _resultClass; private boolean _compiled; @@ -96,39 +98,60 @@ public CriteriaQueryImpl(MetamodelImpl model, Class resultClass) { this._model = model; this._resultClass = resultClass; + this._delegator = null; _aliases = new HashMap, String>(); } - public CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl 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 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 getContexts() { + /** + * Gets the stack of contexts used by this query. + */ + Stack getContexts() { return _contexts; } + /** + * Sets whether this query as distinct. + */ public CriteriaQuery 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 getOrderList() { - return _orders == null ? Collections.EMPTY_LIST : new CopyOnWriteArrayList(_orders); + return Expressions.returnCopy(_orders); } /** @@ -136,7 +159,7 @@ * @return the item to be returned in the query result */ public Selection getSelection() { - return _selection; + return (Selection)_selection; } /** @@ -209,9 +232,7 @@ * @return the selection items of the query as a list */ public List> getSelectionList() { - if (_selections == null) - return Collections.EMPTY_LIST; - return Collections.unmodifiableList(_selections); + return Expressions.returnCopy(_selections); } public CriteriaQuery groupBy(Expression... grouping) { @@ -246,7 +267,7 @@ * @return the modified query */ public CriteriaQuery select(Selection selection) { - _selection = (Selection)selection; + _selection = selection; _selections = new ArrayList>(); _selections.add(selection); return this; @@ -289,7 +310,7 @@ } public List> getGroupList() { - return _groups == null ? Collections.EMPTY_LIST : new CopyOnWriteArrayList>(_groups); + return Expressions.returnCopy(_groups); } public PredicateImpl getGroupRestriction() { @@ -301,7 +322,7 @@ } public Set> 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>(); @@ -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 = 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 contexts) { + void setContexts(Stack 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 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> roots, List> 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 orderBys = getOrderList(); + for (int i = 0; i < orderBys.size(); i++) { + buffer.append(((CriteriaExpression)orderBys.get(i)).asValue(this)); + } + } + } + + private void renderJoins(StringBuilder buffer, Collection> 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> 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 the type of the value this expression represents. + * + * @author Pinaki Poddar + * @since 2.0.0 */ -public abstract class ExpressionImpl extends SelectionImpl - implements CriteriaExpression { - 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 extends SelectionImpl implements Expression { /** * @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 List returnCopy(List list) { + return list == null ? new ArrayList() : new CopyOnWriteArrayList(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 Set returnCopy(Set set) { + return set == null ? new HashSet() : new CopyOnWriteArraySet(set); + } + + + + /** * Unary Functional Expression applies a unary function on a input operand Expression. * * @param 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 { @@ -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 { @@ -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 { @@ -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 extends UnaryFunctionalExpression { @@ -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 extends UnaryFunctionalExpression { @@ -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 { @@ -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 extends FunctionalExpression { private final String functionName; private final Class resultType; + public DatabaseFunction(String name, Class 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 extends UnaryFunctionalExpression { @@ -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 { @@ -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 { @@ -334,7 +485,7 @@ private ExpressionImpl len; public Substring(Expression s, Expression from, Expression len) { - super(s); + super(String.class, s); this.from = (ExpressionImpl)from; this.len = (ExpressionImpl)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 { @@ -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 x, Expression y, - Trimspec ts) { + public Trim(Expression x, Expression 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 extends BinarayFunctionalExpression { @@ -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 extends BinarayFunctionalExpression { public Product(Expression x, Expression 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 extends BinarayFunctionalExpression { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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> extends PredicateImpl.And { + private final ExpressionImpl e; + private final ExpressionImpl v1; + private final ExpressionImpl v2; + public Between(Expression v, Expression x, Expression y) { super(new GreaterThanEqual(v,x), new LessThanEqual(v,y)); + e = (ExpressionImpl)v; + v1 = (ExpressionImpl)x; + v2 = (ExpressionImpl)y; } public Between(Expression v, Y x, Y y) { this(v, new Constant(x), new Constant(y)); } + + @Override + public StringBuilder asValue(CriteriaQueryImpl q) { + return Expressions.asValue(q, e, " BETWEEN ", v1, " AND ", v2); + } } public static class Constant extends ExpressionImpl { @@ -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 extends PredicateImpl { @@ -840,6 +1118,7 @@ final ExpressionImpl collection; public IsMember(Class t, Expression element, Expression collection) { + super(); this.element = (ExpressionImpl)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 extends ExpressionImpl implements QueryBuilder.Coalesce { @@ -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 extends ExpressionImpl { @@ -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 e; private boolean negate; public In(Expression e) { - super((Predicate[])null); + super(); this.e = (ExpressionImpl)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 extends ExpressionImpl implements QueryBuilder.Case { private final List> thens = new ArrayList>(); - private final List> whens = new ArrayList>(); + private final List> whens = new ArrayList>(); private Expression otherwise; public Case(Class 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 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 extends SubqueryExpression { @@ -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 extends SubqueryExpression { @@ -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 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 extends ExpressionImpl { + final ExpressionImpl _delegate; + public DelegatingExpression(ExpressionImpl del) { + super((Class)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> getJoins() { - return _joins; + return Expressions.returnCopy(_joins); } /** @@ -272,7 +269,7 @@ } public java.util.Set> getFetches() { - return _fetches; + return Expressions.returnCopy(_fetches); } private Fetch addFetch(Members.Member 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> 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 getParent() { - return (FromImpl) _parent; - } - - @Override - public FromImpl getParentPath() { + /** + * Gets the parent of this join. + */ + public final FromImpl getParent() { return (FromImpl) _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 extends AbstractCollection,E> implements CollectionJoin{ - public Collection(FromImpl parent, - Members.CollectionAttributeImpl member, JoinType jt) { + public Collection(FromImpl parent, Members.CollectionAttributeImpl member, JoinType jt) { super(parent, member, jt); } public CollectionAttribute getModel() { - return (CollectionAttribute)_member.getType(); + return (CollectionAttribute)_member; } } @@ -450,7 +461,7 @@ * @param the type of the the set attribute elements */ public static class Set extends AbstractCollection,E> - implements SetJoin{ + implements SetJoin { public Set(FromImpl parent, Members.SetAttributeImpl member, JoinType jt) { super(parent, member, jt); } @@ -470,13 +481,12 @@ public static class List extends AbstractCollection,E> implements ListJoin { - public List(FromImpl parent, - Members.ListAttributeImpl member, JoinType jt) { + public List(FromImpl parent, Members.ListAttributeImpl member, JoinType jt) { super(parent, member, jt); } public ListAttribute getModel() { - return (ListAttribute)_member.getType(); + return (ListAttribute)_member; } public Expression index() { @@ -509,8 +519,8 @@ } /** - * Create a pseudo-attribute of a pseudo-managed type for java.util.Map<K,V> to represent its keys as - * a pseudo-attribute of type java.util.Set<V>. + * Create a pseudo-attribute of a pseudo-managed type for java.util.Map<K,V> + * to represent its keys of type java.util.Set<V>. */ public Join, K> joinKey(JoinType jt) { AbstractManagedType> pseudoOwner = (AbstractManagedType>) @@ -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 extends ExpressionImpl> { @@ -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; + } } /**