OPENJPA-1013: Visitor pattern for collecting declared parameters. Editing with parameters. Search within result usage.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@809036 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2009-08-28 21:32:29 +00:00
parent fe44661dc2
commit 0795778d3d
6 changed files with 219 additions and 42 deletions

View File

@ -118,6 +118,7 @@ public abstract class AbstractPersistenceTestCase extends TestCase {
protected Map<String, Object> getPropertiesMap(Object... props) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("openjpa.DynamicEnhancementAgent", "false");
List<Class<?>> types = new ArrayList<Class<?>>();
boolean prop = false;

View File

@ -174,7 +174,7 @@ public class CriteriaExpressionBuilder {
exps.grouping[i] = Expressions.toValue((ExpressionImpl<?>)groupBy, factory, model, q);;
}
exps.having = having == null ? factory.emptyExpression() : having.toKernelExpression(factory, model, q);
exps.having = having == null ? null : having.toKernelExpression(factory, model, q);
}
protected void evalDistinct(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {

View File

@ -28,7 +28,6 @@ import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.persistence.criteria.AbstractQuery;
import javax.persistence.criteria.CriteriaQuery;
@ -80,7 +79,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
private Boolean _distinct;
private SubqueryImpl<?> _delegator;
private final Class<T> _resultClass;
private boolean _compiled;
// AliasContext
private int aliasCount = 0;
@ -190,21 +189,8 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
/**
* Registers the given parameter.
* On registration, an unnamed parameter is assigned an auto-generated
* name.
*
*/
public void registerParameter(ParameterExpressionImpl<?> p) {
if (_delegator != null) {
CriteriaQueryImpl<?> owner = _delegator.getInnermostParent();
if (owner != this) {
owner.registerParameter(p);
}
}
registerParameterInternal(p);
}
private void registerParameterInternal(ParameterExpressionImpl<?> p) {
void registerParameter(ParameterExpressionImpl<?> p) {
if (_params == null)
_params = new LinkedMap/*<ParameterExpression<?>, Class<?>*/();
if (!_params.containsKey(p)) {
@ -214,6 +200,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
}
public Set<ParameterExpression<?>> getParameters() {
collectParameters(new CriteriaExpressionVisitor.ParameterVisitor(this));
return _params == null ? Collections.EMPTY_SET : _params.keySet();
}
@ -266,11 +253,21 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
}
public CriteriaQuery<T> where(Expression<Boolean> restriction) {
invalidateCompilation();
if (restriction == null) {
_where = null;
return this;
}
_where = new PredicateImpl().add(restriction);
return this;
}
public CriteriaQuery<T> where(Predicate... restrictions) {
invalidateCompilation();
if (restrictions == null) {
_where = null;
return this;
}
_where = new PredicateImpl();
for (Predicate p : restrictions)
_where.add(p);
@ -340,6 +337,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
* Empty map if no parameter has been declared.
*/
public LinkedMap getParameterTypes() {
collectParameters(new CriteriaExpressionVisitor.ParameterVisitor(this));
return _params == null ? StoreQuery.EMPTY_PARAMS : _params;
}
@ -562,5 +560,37 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
}
return false;
}
void invalidateCompilation() {
_compiled = false;
_params = null;
}
/**
* Compiles to verify that at least one root is defined, a selection term is present
* and, most importantly, collects all the parameters so that they can be bound to
* the executable query.
*/
public void compile() {
if (_compiled)
return;
assertRoot();
assertSelection();
collectParameters(new CriteriaExpressionVisitor.ParameterVisitor(this));
_compiled = true;
}
private void collectParameters(CriteriaExpressionVisitor visitor) {
if (_compiled)
return;
if (_where != null) {
_where.acceptVisit(visitor);
}
if (_subqueries != null) {
for (Subquery<?> subq : _subqueries) {
((SubqueryImpl<?>)subq).getDelegate().collectParameters(visitor);
}
}
}
}

View File

@ -37,15 +37,22 @@ import org.apache.openjpa.persistence.meta.MetamodelImpl;
* @param <X> the type of the value this expression represents.
*/
public abstract class ExpressionImpl<X> extends SelectionImpl<X>
implements Expression<X> {
abstract Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q);
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);
}
}
/**
* @param cls the type of the evaluated result of the expression

View File

@ -63,6 +63,15 @@ public class Expressions {
JPQLExpressionBuilder.setImplicitTypes(v1, v2, expected, q.getMetamodel(),
q.getParameterTypes(), q.toString());
}
static void acceptVisit(CriteriaExpressionVisitor visitor, Expression<?>...exprs) {
if (exprs == null)
return;
for (Expression<?> e : exprs) {
if (e != null)
((ExpressionImpl<?>)e).acceptVisit(visitor);
}
}
/**
* Unary Functional Expression applies a unary function on a input operand Expression.
@ -82,6 +91,11 @@ public class Expressions {
public UnaryFunctionalExpression(Expression<X> e) {
this(e.getJavaType(), e);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
}
/**
@ -101,6 +115,11 @@ public class Expressions {
e1 = (ExpressionImpl<?>)x;
e2 = (ExpressionImpl<?>)y;
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e1, e2);
}
}
/**
@ -122,6 +141,11 @@ public class Expressions {
this.args[i] = (ExpressionImpl<?>)args[i];
}
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, args);
}
}
/**
@ -143,6 +167,11 @@ public class Expressions {
public PredicateImpl clone() {
return new BinaryLogicalExpression(e1, e2);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e1, e2);
}
}
@ -333,6 +362,11 @@ public class Expressions {
from == null ? null : from.toValue(factory, model, q),
len == null ? null : len.toValue(factory, model, q));
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, from, len);
}
}
public static class Locate extends ExpressionImpl<Integer> {
@ -376,6 +410,11 @@ public class Expressions {
factory.newLiteral(Integer.valueOf(1), Literal.TYPE_NUMBER)))),
factory.newLiteral(Integer.valueOf(1), Literal.TYPE_NUMBER));
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, pattern, from, path);
}
}
public static class Trim extends BinarayFunctionalExpression<String> {
@ -721,19 +760,15 @@ public class Expressions {
}
return factory.newLiteral(value, literalType);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
if (arg instanceof CriteriaExpression) {
((CriteriaExpression<?>)arg).acceptVisit(visitor);
}
}
}
// public static class TypeConstant<X> extends Constant<X> {
// public TypeConstant(X x) {
// super((Class<X>)x.getClass(),x);
// }
//
// @Override
// public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
// return factory.newTypeLiteral(arg, Literal.TYPE_CLASS);
// }
// }
public static class IsEmpty extends PredicateImpl {
final ExpressionImpl<?> collection;
public IsEmpty(Expression<?> collection) {
@ -752,6 +787,11 @@ public class Expressions {
Value val = Expressions.toValue(collection, factory, model, q);
return (isNegated()) ? factory.not(factory.isEmpty(val)) : factory.isEmpty(val);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, collection);
}
}
public static class IsNotEmpty extends PredicateImpl {
@ -772,6 +812,11 @@ public class Expressions {
Value val = Expressions.toValue(collection, factory, model, q);
return (isNegated()) ? factory.isEmpty(val) : factory.isNotEmpty(val);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, collection);
}
}
@ -820,6 +865,11 @@ public class Expressions {
Expressions.toValue(element, factory, model, q));
return _negated ? factory.not(contains) : contains;
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, collection, element);
}
}
public static class Like extends PredicateImpl {
@ -875,6 +925,11 @@ public class Expressions {
Expressions.toValue(pattern, factory, model, q),
MATCH_SINGLECHAR, MATCH_MULTICHAR, escapeStr);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, str, pattern, escapeChar);
}
}
public static class Coalesce<T> extends ExpressionImpl<T> implements QueryBuilder.Coalesce<T> {
@ -903,6 +958,11 @@ public class Expressions {
vs[i++] = Expressions.toValue((ExpressionImpl<?>)e, factory, model, q);
return factory.coalesceExpression(vs);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, values.toArray(new ExpressionImpl[values.size()]));
}
}
public static class Nullif<T> extends ExpressionImpl<T> {
@ -928,6 +988,11 @@ public class Expressions {
Value value2 = Expressions.toValue((ExpressionImpl<?>)val2, factory, model, q);
return factory.nullIfExpression(value1, value2);
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, val1, val2);
}
}
public static class IsNull extends PredicateImpl {
@ -949,6 +1014,11 @@ public class Expressions {
Expressions.toValue(e, factory, model, q),
factory.getNull());
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
}
public static class IsNotNull extends PredicateImpl {
@ -970,6 +1040,11 @@ public class Expressions {
Expressions.toValue(e, factory, model, q),
factory.getNull());
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
}
@ -1030,6 +1105,11 @@ public class Expressions {
return factory.and(inExpr, notNull.toKernelExpression(factory, model, q));
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
}
public static class Case<T> extends ExpressionImpl<T> implements QueryBuilder.Case<T> {
@ -1075,6 +1155,13 @@ public class Expressions {
Value other = Expressions.toValue((ExpressionImpl<?>)otherwise, factory, model, q);
return factory.generalCaseExpression(exps, other);
}
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);
}
}
public static class SimpleCase<C,R> extends ExpressionImpl<R> implements QueryBuilder.SimpleCase<C,R> {
@ -1130,6 +1217,13 @@ public class Expressions {
Value other = Expressions.toValue((ExpressionImpl<?>)otherwise, factory, model, q);
return factory.simpleCaseExpression(caseOperandExpr, exps, other);
}
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);
}
}
public static class Lower extends UnaryFunctionalExpression<String> {
@ -1167,13 +1261,39 @@ public class Expressions {
return factory.stringLength(Expressions.toValue(e, factory, model, q));
}
}
public static class Exists<X> extends PredicateImpl {
public static abstract class SubqueryPredicate<X> extends PredicateImpl {
final SubqueryImpl<X> e;
public Exists(Subquery<X> x) {
public SubqueryPredicate(Subquery<X> x) {
super();
e = (SubqueryImpl<X>)x;
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
}
public static abstract class SubqueryExpression<X> extends ExpressionImpl<X> {
final SubqueryImpl<X> e;
public SubqueryExpression(Subquery<X> x) {
super(x.getJavaType());
e = (SubqueryImpl<X>)x;
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
if (e != null) e.acceptVisit(visitor);
}
}
public static class Exists<X> extends SubqueryPredicate<X> {
public Exists(Subquery<X> x) {
super(x);
}
@Override
public PredicateImpl clone() {
@ -1189,11 +1309,9 @@ public class Expressions {
}
}
public static class All<X> extends ExpressionImpl<X> {
final SubqueryImpl<X> e;
public static class All<X> extends SubqueryExpression<X> {
public All(Subquery<X> x) {
super(x.getJavaType());
e = (SubqueryImpl<X>)x;
super(x);
}
@Override
@ -1203,11 +1321,9 @@ public class Expressions {
}
}
public static class Any<X> extends ExpressionImpl<X> {
final SubqueryImpl<X> e;
public static class Any<X> extends SubqueryExpression<X> {
public Any(Subquery<X> x) {
super(x.getJavaType());
e = (SubqueryImpl<X>)x;
super(x);
}
@Override
@ -1233,6 +1349,11 @@ public class Expressions {
ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
return factory.not(super.toKernelExpression(factory, model, q));
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
}
public static class CastAs<Y> extends ExpressionImpl<Y> {
@ -1249,6 +1370,11 @@ public class Expressions {
e.setImplicitType(getJavaType());
return e;
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, actual);
}
}
/**
@ -1275,6 +1401,11 @@ public class Expressions {
e.setImplicitType(getJavaType());
return e;
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, _args);
}
}
}

View File

@ -124,6 +124,14 @@ public class PredicateImpl extends ExpressionImpl<Boolean> implements Predicate
return _negated ? factory.not(result) : result;
}
public void acceptVisit(CriteriaExpressionVisitor visitor) {
if (_exps == null)
return;
for (Expression<?> e : _exps) {
((ExpressionImpl<?>)e).acceptVisit(visitor);
}
}
public static class And extends PredicateImpl {
public And(Expression<Boolean> x, Expression<Boolean> y) {
super(BooleanOperator.AND);