blob: 544f1a85f36ee15c7a27bb4fa139dfd512c72b28 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.persistence.criteria;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
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.CriteriaBuilder;
import javax.persistence.criteria.CriteriaBuilder.Trimspec;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Subquery;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
import org.apache.openjpa.kernel.exps.Literal;
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.Types;
/**
* Expressions according to JPA 2.0.
*
* A facade to OpenJPA kernel expressions to enforce stronger typing.
*
* @author Pinaki Poddar
* @author Fay Wang
*
* @since 2.0.0
*
*/
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.
* Handles null expression.
*/
static Value toValue(ExpressionImpl<?> e, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return (e == null) ? factory.getNull() : e.toValue(factory, q);
}
static void setImplicitTypes(Value v1, Value v2, Class<?> expected, CriteriaQueryImpl<?> q) {
JPQLExpressionBuilder.setImplicitTypes(v1, v2, expected, q.getMetamodel(),
q.getParameterTypes(), q.toString());
}
/**
* 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;
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(AliasContext 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(AliasContext 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<>() : 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 <X> Set<X> returnCopy(Set<X> set) {
return set == null ? new HashSet<>() : new CopyOnWriteArraySet<>(set);
}
static org.apache.openjpa.kernel.exps.Expression and(ExpressionFactory factory,
org.apache.openjpa.kernel.exps.Expression e1, org.apache.openjpa.kernel.exps.Expression e2) {
return e1 == null ? e2 : e2 == null ? e1 : factory.and(e1, e2);
}
/**
* Unary Functional Expression applies a unary function on a input operand Expression.
*
* @param <X> the type of the resultant expression
*/
public abstract static class UnaryFunctionalExpression<X> extends ExpressionImpl<X> {
protected final ExpressionImpl<?> e;
/**
* Supply the resultant type and input operand expression.
*/
public UnaryFunctionalExpression(Class<X> t, Expression<?> e) {
super(t);
this.e = (ExpressionImpl<?>)e;
}
public UnaryFunctionalExpression(Expression<X> e) {
this((Class<X>)e.getJavaType(), e);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, e);
}
}
/**
* Binary Functional Expression applies a binary function on a pair of input Expression.
*
* @param <X> the type of the resultant expression
*/
public abstract static class BinarayFunctionalExpression<X> extends ExpressionImpl<X>{
protected final ExpressionImpl<?> e1;
protected final ExpressionImpl<?> e2;
/**
* Supply the resultant type and pair of input operand expressions.
*/
public BinarayFunctionalExpression(Class<X> t, Expression<?> x, Expression<?> y) {
super(t);
e1 = (ExpressionImpl<?>)x;
e2 = (ExpressionImpl<?>)y;
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, e1, e2);
}
}
/**
* Functional Expression applies a function on a list of input Expressions.
*
* @param <X> the type of the resultant expression
*/
public abstract static class FunctionalExpression<X> extends ExpressionImpl<X> {
protected final ExpressionImpl<?>[] args;
/**
* Supply the resultant type and list of input operand expressions.
*/
public FunctionalExpression(Class<X> t, Expression<?>... args) {
super(t);
int len = args == null ? 0 : args.length;
this.args = new ExpressionImpl<?>[len];
for (int i = 0; args != null && i < args.length; i++) {
this.args[i] = (ExpressionImpl<?>)args[i];
}
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, args);
}
}
/**
* Binary Logical Expression applies a function on a pair of input Expression to generate a Predicate
* i.e. an expression whose resultant type is Boolean.
*
*/
public static abstract class BinaryLogicalExpression extends PredicateImpl {
protected final ExpressionImpl<?> e1;
protected final ExpressionImpl<?> e2;
public BinaryLogicalExpression(Expression<?> x, Expression<?> y) {
super();
e1 = (ExpressionImpl<?>)x;
e2 = (ExpressionImpl<?>)y;
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, e1, e2);
}
}
public static class Abs<X> extends UnaryFunctionalExpression<X> {
public Abs(Expression<X> x) {
super(x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.abs(Expressions.toValue(e, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "ABS", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Count extends UnaryFunctionalExpression<Long> {
private boolean _distinct;
public Count(Expression<?> x) {
this(x, false);
}
public Count(Expression<?> x, boolean distinct) {
super(Long.class, x);
_distinct = distinct;
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value v = Expressions.toValue(e, factory, q);
return _distinct ? factory.count(factory.distinct(v)) : factory.count(v);
}
@Override
public StringBuilder asValue(AliasContext 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> {
public Avg(Expression<?> x) {
super(Double.class, x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.avg(Expressions.toValue(e, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "AVG", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Sqrt extends UnaryFunctionalExpression<Double> {
public Sqrt(Expression<? extends Number> x) {
super(Double.class, x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.sqrt(Expressions.toValue(e, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "SQRT", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Max<X> extends UnaryFunctionalExpression<X> {
public Max(Expression<X> x) {
super(x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.max(Expressions.toValue(e, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "MAX", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Min<X> extends UnaryFunctionalExpression<X> {
public Min(Expression<X> x) {
super(x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.min(Expressions.toValue(e, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "MIN", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Size extends UnaryFunctionalExpression<Integer> {
public Size(Expression<? extends Collection<?>> x) {
super(Integer.class, x);
}
public Size(Collection<?> x) {
this(new Constant<Collection<?>>(x));
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value val = Expressions.toValue(e, factory, q);
Value result;
if (val instanceof Literal && ((Literal)val).getParseType() == Literal.TYPE_COLLECTION)
result = factory.newLiteral(((Collection)((Literal)val).getValue()).size(),
Literal.TYPE_NUMBER);
else
result = factory.size(val);
result.setImplicitType(Integer.class);
return result;
}
@Override
public StringBuilder asValue(AliasContext 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;
this.resultType = resultType;
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.newFunction(functionName, getJavaType(),
new Expressions.ListArgument(resultType, args).toValue(factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, functionName, OPEN_BRACE, Expressions.asValue(q, args, COMMA), CLOSE_BRACE);
}
}
public static class Type<X extends Class> extends UnaryFunctionalExpression<X> {
public Type(PathImpl<?, ?> path) {
super((Class)Class.class, path);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.type(Expressions.toValue(e, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "TYPE", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Cast<B> extends UnaryFunctionalExpression<B> {
public Cast(Expression<?> x, Class<B> b) {
super(b, x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.cast(Expressions.toValue(e, factory, q), getJavaType());
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, OPEN_BRACE, getJavaType().getSimpleName(), CLOSE_BRACE, e);
}
}
public static class Concat extends BinarayFunctionalExpression<String> {
public Concat(Expression<String> x, Expression<String> y) {
super(String.class, x, y);
}
public Concat(Expression<String> x, String y) {
this(x, new Constant<>(y));
}
public Concat(String x, Expression<String> y) {
this(new Constant<>(x), y);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.concat(
Expressions.toValue(e1, factory, q),
Expressions.toValue(e2, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "CONCAT", OPEN_BRACE, e1, COMMA, e2, CLOSE_BRACE);
}
}
public static class Substring extends UnaryFunctionalExpression<String> {
private ExpressionImpl<Integer> from;
private ExpressionImpl<Integer> len;
public Substring(Expression<String> s, Expression<Integer> from, Expression<Integer> len) {
super(String.class, s);
this.from = (ExpressionImpl<Integer>)from;
this.len = (ExpressionImpl<Integer>)len;
}
public Substring(Expression<String> s, Expression<Integer> from) {
this(s, (ExpressionImpl<Integer>)from, null);
}
public Substring(Expression<String> s) {
this(s, (Expression<Integer>)null, (Expression<Integer>)null);
}
public Substring(Expression<String> s, Integer from) {
this(s, new Constant<>(from), null);
}
public Substring(Expression<String> s, Integer from, Integer len) {
this(s, new Constant<>(from), new Constant<>(len));
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return JPQLExpressionBuilder.convertSubstringArguments(factory,
Expressions.toValue(e, factory, q),
from == null ? null : from.toValue(factory, q),
len == null ? null : len.toValue(factory, q));
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, from, len);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "SUBSTRING", OPEN_BRACE, e, COMMA, from, COMMA, len, CLOSE_BRACE);
}
}
public static class Locate extends ExpressionImpl<Integer> {
private ExpressionImpl<String> pattern;
private ExpressionImpl<Integer> from;
private ExpressionImpl<String> path;
public Locate(Expression<String> path, Expression<String> pattern, Expression<Integer> from) {
super(Integer.class);
this.path = (ExpressionImpl<String>)path;
this.pattern = (ExpressionImpl<String>)pattern;
this.from = (ExpressionImpl<Integer>)from;
}
public Locate(Expression<String> path, Expression<String> pattern) {
this(path, pattern, null);
}
public Locate(Expression<String> path, String pattern) {
this(path, new Constant<>(pattern), null);
}
public Locate(String path, Expression<String> pattern) {
this(new Constant<>(path), pattern, null);
}
public Locate(Expression<String> path, String pattern, int from) {
this(path, new Constant<>(pattern), new Constant<>(from));
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value locateSearch = path.toValue(factory, q);
Value locateFromIndex = (from == null ? null : Expressions.toValue(from, factory, q));
Value locatePath = Expressions.toValue(pattern, factory, q);
return factory.indexOf(locateSearch,
locateFromIndex == null ? locatePath
: factory.newArgumentList(locatePath, locateFromIndex));
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, pattern, from, path);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "LOCATE", OPEN_BRACE, pattern, COMMA, path, CLOSE_BRACE);
}
}
public static class Trim extends BinarayFunctionalExpression<String> {
static Expression<Character> defaultTrim = new Constant<>(Character.class, ' ');
static Trimspec defaultSpec = Trimspec.BOTH;
private Trimspec ts;
public Trim(Expression<String> x, Expression<Character> y, Trimspec ts) {
super(String.class, x, y);
this.ts = ts;
}
public Trim(Expression<String> x, Expression<Character> y) {
this(x, y, defaultSpec);
}
public Trim(Expression<String> x) {
this(x, defaultTrim, defaultSpec);
}
public Trim(Expression<String> x, Character t) {
this(x, new Constant<>(Character.class, t), defaultSpec);
}
public Trim(Expression<String> x, Character t, Trimspec ts) {
this(x, new Constant<>(Character.class, t), ts);
}
public Trim(Expression<String> x, Trimspec ts) {
this(x, defaultTrim, ts);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Boolean spec = null;
if (ts != null) {
switch (ts) {
case LEADING : spec = true; break;
case TRAILING : spec = false; break;
case BOTH : spec = null; break;
}
}
Character t = (Character)((Constant<Character>)e2).arg;
Constant<String> e2 = new Constant<>(String.class, t.toString());
return factory.trim(
Expressions.toValue(e1, factory, q),
Expressions.toValue(e2, factory, q), spec);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "TRIM", OPEN_BRACE, e1, COMMA, e2, CLOSE_BRACE);
}
}
public static class Sum<N extends Number> extends BinarayFunctionalExpression<N> {
public Sum(Expression<? extends Number> x, Expression<? extends Number> y) {
super((Class<N>)x.getJavaType(), x, y);
}
public Sum(Expression<? extends Number> x) {
this(x, (Expression<? extends Number>)null);
}
public Sum(Expression<? extends Number> x, Number y) {
this(x, new Constant<>(Number.class, y));
}
public Sum(Number x, Expression<? extends Number> y) {
this(new Constant<>(Number.class, x), y);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value= (e2 == null)
? factory.sum(Expressions.toValue(e1, factory, q))
: factory.add(
Expressions.toValue(e1, factory, q),
Expressions.toValue(e2, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext 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) {
super((Class<N>)x.getJavaType(), x, y);
}
public Product(Expression<? extends Number> x, Number y) {
this(x, new Constant<>(Number.class, y));
}
public Product(Number x, Expression<? extends Number> y) {
this(new Constant<>(Number.class, x), y);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.multiply(
Expressions.toValue(e1, factory, q),
Expressions.toValue(e2, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " * " ,e2);
}
}
public static class Diff<N extends Number> extends BinarayFunctionalExpression<N> {
public Diff(Expression<? extends Number> x, Expression<? extends Number> y) {
super((Class<N>)x.getJavaType(), x, y);
}
public Diff(Expression<? extends Number> x, Number y) {
this(x, new Constant<>(Number.class, y));
}
public Diff(Number x, Expression<? extends Number> y) {
this(new Constant<>(Number.class, x), y);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.subtract(
Expressions.toValue(e1, factory, q),
Expressions.toValue(e2, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " - " ,e2);
}
}
public static class Quotient<N extends Number> extends BinarayFunctionalExpression<N> {
public Quotient(Expression<? extends Number> x, Expression<? extends Number> y) {
super((Class<N>)x.getJavaType(), x, y);
}
public Quotient(Expression<? extends Number> x, Number y) {
this(x, new Constant<>(y));
}
public Quotient(Number x, Expression<? extends Number> y) {
this(new Constant<>(x), y);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.divide(
Expressions.toValue(e1, factory, q),
Expressions.toValue(e2, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, "%" ,e2);
}
}
public static class Mod extends BinarayFunctionalExpression<Integer> {
public Mod(Expression<Integer> x, Expression<Integer> y) {
super(Integer.class, x,y);
}
public Mod(Expression<Integer> x, Integer y) {
this(x,new Constant<>(Integer.class, y));
}
public Mod(Integer x, Expression<Integer> y) {
this(new Constant<>(Integer.class, x),y);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value = factory.mod(
Expressions.toValue(e1, factory, q),
Expressions.toValue(e2, factory, q));
value.setImplicitType(getJavaType());
return value;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "MOD", OPEN_BRACE, e1, COMMA, e2, CLOSE_BRACE);
}
}
public static class CurrentDate extends ExpressionImpl<java.sql.Date> {
public CurrentDate() {
super(java.sql.Date.class);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.getCurrentDate(getJavaType());
}
@Override
public StringBuilder asValue(AliasContext q) {
return new StringBuilder("CURRENT_DATE");
}
}
public static class CurrentTime extends ExpressionImpl<java.sql.Time> {
public CurrentTime() {
super(java.sql.Time.class);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.getCurrentTime(getJavaType());
}
@Override
public StringBuilder asValue(AliasContext q) {
return new StringBuilder("CURRENT_TIME");
}
}
public static class CurrentTimestamp extends ExpressionImpl<java.sql.Timestamp> {
public CurrentTimestamp() {
super(java.sql.Timestamp.class);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.getCurrentTimestamp(getJavaType());
}
@Override
public StringBuilder asValue(AliasContext q) {
return new StringBuilder("CURRENT_TIMESTAMP");
}
}
public static class Equal extends BinaryLogicalExpression {
public <X,Y> Equal(Expression<X> x, Expression<Y> y) {
super(x,y);
}
public <X> Equal(Expression<X> x, Object y) {
this(x, new Constant(y));
}
@Override
public PredicateImpl not() {
return new NotEqual(e1, e2).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val1 = Expressions.toValue(e1, factory, q);
Value val2 = Expressions.toValue(e2, factory, q);
Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
return factory.equal(val1, val2);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " = ", e2);
}
}
public static class NotEqual extends BinaryLogicalExpression {
public <X,Y> NotEqual(Expression<X> x, Expression<Y> y) {
super(x,y);
}
public <X> NotEqual(Expression<X> x, Object y) {
this(x, new Constant(y));
}
@Override
public PredicateImpl not() {
return new Equal(e1, e2).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val1 = Expressions.toValue(e1, factory, q);
Value val2 = Expressions.toValue(e2, factory, q);
Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
return factory.notEqual(val1, val2);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " <> ", e2);
}
}
public static class GreaterThan extends BinaryLogicalExpression {
public <X,Y> GreaterThan(Expression<X> x, Expression<Y> y) {
super(x,y);
}
public <X> GreaterThan(Expression<X> x, Object y) {
this(x, new Constant(y));
}
@Override
public PredicateImpl not() {
return new LessThanEqual(e1, e2).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val1 = Expressions.toValue(e1, factory, q);
Value val2 = Expressions.toValue(e2, factory, q);
Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
return factory.greaterThan(val1, val2);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " > ", e2);
}
}
public static class GreaterThanEqual extends BinaryLogicalExpression {
public <X,Y> GreaterThanEqual(Expression<X> x, Expression<Y> y) {
super(x,y);
}
public <X> GreaterThanEqual(Expression<X> x, Object y) {
this(x, new Constant(y));
}
@Override
public PredicateImpl not() {
return new LessThan(e1, e2).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val1 = Expressions.toValue(e1, factory, q);
Value val2 = Expressions.toValue(e2, factory, q);
Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
return factory.greaterThanEqual(val1, val2);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " >= ", e2);
}
}
public static class LessThan extends BinaryLogicalExpression {
public <X,Y> LessThan(Expression<X> x, Expression<Y> y) {
super(x,y);
}
public <X> LessThan(Expression<X> x, Object y) {
this(x, new Constant(y));
}
@Override
public PredicateImpl not() {
return new GreaterThanEqual(e1, e2).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val1 = Expressions.toValue(e1, factory, q);
Value val2 = Expressions.toValue(e2, factory, q);
Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
return factory.lessThan(val1, val2);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " < ", e2);
}
}
public static class LessThanEqual extends BinaryLogicalExpression {
public <X,Y> LessThanEqual(Expression<X> x, Expression<Y> y) {
super(x,y);
}
public <X> LessThanEqual(Expression<X> x, Object y) {
this(x, new Constant(y));
}
@Override
public PredicateImpl not() {
return new GreaterThan(e1, e2).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val1 = Expressions.toValue(e1, factory, q);
Value val2 = Expressions.toValue(e2, factory, q);
Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
return factory.lessThanEqual(val1, val2);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e1, " <= ", e2);
}
}
public static class Between<Y extends Comparable<Y>> extends PredicateImpl.And {
private final ExpressionImpl<? extends Y> e;
private final ExpressionImpl<? extends Y> v1;
private final ExpressionImpl<? extends Y> 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<? extends Y>)v;
v1 = (ExpressionImpl<? extends Y>)x;
v2 = (ExpressionImpl<? extends Y>)y;
}
public Between(Expression<? extends Y> v, Y x, Y y) {
this(v, new Constant<>(x), new Constant<>(y));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e, " BETWEEN ", v1, " AND ", v2);
}
}
public static class Constant<X> extends ExpressionImpl<X> {
public final Object arg;
public Constant(Class<X> t, X x) {
super(t);
this.arg = x;
}
public Constant(X x) {
this(x == null ? null : (Class<X>)x.getClass(), x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Object value = arg;
Class<?> literalClass = getJavaType();
if (arg instanceof ParameterExpressionImpl) {
return ((ParameterExpressionImpl)arg).toValue(factory, q);
}
int literalType = Literal.TYPE_UNKNOWN;
if (Number.class.isAssignableFrom(literalClass)) {
literalType = Literal.TYPE_NUMBER;
} else if (Boolean.class.isAssignableFrom(literalClass)) {
literalType = Literal.TYPE_BOOLEAN;
} else if (String.class.isAssignableFrom(literalClass)) {
literalType = Literal.TYPE_STRING;
} else if (Enum.class.isAssignableFrom(literalClass)) {
literalType = Literal.TYPE_ENUM;
} else if (Class.class.isAssignableFrom(literalClass)) {
literalType = Literal.TYPE_CLASS;
Literal lit = factory.newTypeLiteral(value, Literal.TYPE_CLASS);
ClassMetaData can = ((Types.Entity<X>)q.getRoot().getModel()).meta;
Class<?> candidate = can.getDescribedType();
if (candidate.isAssignableFrom((Class)value)) {
lit.setMetaData(q.getMetamodel().getRepository().getMetaData((Class<?>)value, null, true));
} else {
lit.setMetaData(can);
}
return lit;
} else if (Collection.class.isAssignableFrom(literalClass)) {
literalType = Literal.TYPE_COLLECTION;
}
return factory.newLiteral(value, literalType);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, arg instanceof Expression ? ((Expression)arg) : null);
}
@Override
public StringBuilder asValue(AliasContext 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());
}
}
public static class IsEmpty extends PredicateImpl {
final ExpressionImpl<?> collection;
public IsEmpty(Expression<?> collection) {
super();
this.collection = (ExpressionImpl<?>)collection;
}
@Override
public PredicateImpl not() {
return new IsNotEmpty(collection).markNegated();
}
@Override
Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return Expressions.toValue(collection, factory, q);
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val = Expressions.toValue(collection, factory, q);
return factory.isEmpty(val);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, collection);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, collection, " IS EMPTY");
}
}
public static class IsNotEmpty extends PredicateImpl {
final ExpressionImpl<?> collection;
public IsNotEmpty(Expression<?> collection) {
super();
this.collection = (ExpressionImpl<?>)collection;
}
@Override
public PredicateImpl not() {
return new IsEmpty(collection).markNegated();
}
@Override
Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return Expressions.toValue(collection, factory, q);
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(ExpressionFactory factory, CriteriaQueryImpl<?> q){
Value val = Expressions.toValue(collection, factory, q);
// factory.isNotEmpty() not used to match JPQL
return factory.not(factory.isEmpty(val));
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, collection);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, collection, " IS NOT EMPTY");
}
}
public static class Index extends UnaryFunctionalExpression<Integer> {
public Index(Joins.List<?,?> e) {
super(Integer.class, e);
}
@Override
public org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value v = Expressions.toValue(e, factory, q);
ClassMetaData meta = ((PathImpl<?,?>)e)._member.fmd.getElement().getTypeMetaData();
v.setMetaData(meta);
return factory.index(v);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "INDEX", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class IsMember<E> extends PredicateImpl {
final ExpressionImpl<E> element;
final ExpressionImpl<?> collection;
public IsMember(Expression<E> element, Expression<?> collection) {
super();
this.element = (ExpressionImpl<E>)element;
this.collection = (ExpressionImpl<?>)collection;
}
public IsMember(E element, Expression<?> collection) {
this(new Constant<>(element), collection);
}
@Override
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, CriteriaQueryImpl<?> q) {
org.apache.openjpa.kernel.exps.Expression contains = factory.contains(
Expressions.toValue(collection, factory, q),
Expressions.toValue(element, factory, q));
return contains;
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, collection, element);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, element, "MEMBER OF ", collection);
}
}
public static class Like extends PredicateImpl {
public static final String MATCH_MULTICHAR = "%";
public static final String MATCH_SINGLECHAR = "_";
final ExpressionImpl<String> str;
final ExpressionImpl<String> pattern;
final ExpressionImpl<Character> escapeChar;
public Like(Expression<String> x, Expression<String> pattern, Expression<Character> escapeChar) {
super();
this.str = (ExpressionImpl<String>)x;
this.pattern = (ExpressionImpl<String>)pattern;
this.escapeChar = (ExpressionImpl<Character>)escapeChar;
}
public Like(Expression<String> x, Expression<String> pat, char esc) {
this(x, pat, new Constant<>(Character.class, esc));
}
public Like(Expression<String> x, Expression<String> pattern) {
this(x, pattern, null);
}
public Like(Expression<String> x, String pattern) {
this(x, new Constant<>(pattern), null);
}
public Like(Expression<String> x, String pat,
Expression<Character> esc) {
this(x, new Constant<>(pat), esc);
}
public Like(Expression<String> x, String pat, Character esc) {
this(x, new Constant<>(pat), new Constant<>(esc));
}
@Override
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, CriteriaQueryImpl<?> q) {
String escapeStr = escapeChar == null ? null :
((Character)((Literal)Expressions.toValue(
escapeChar, factory, q)).getValue()).toString();
return factory.matches(
Expressions.toValue(str, factory, q),
Expressions.toValue(pattern, factory, q),
MATCH_SINGLECHAR, MATCH_MULTICHAR, escapeStr);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, str, pattern, escapeChar);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, str, " LIKE ", pattern);
}
}
public static class Coalesce<T> extends ExpressionImpl<T> implements CriteriaBuilder.Coalesce<T> {
private final List<Expression<? extends T>> values = new ArrayList<>();
public Coalesce(Class<T> cls) {
super(cls);
}
@Override
public Coalesce<T> value(T value) {
values.add(new Constant<>(value));
return this;
}
@Override
public Coalesce<T> value(Expression<? extends T> value) {
values.add(value);
return this;
}
@Override
public org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value[] vs = new Value[values.size()];
int i = 0;
for (Expression<?> e : values)
vs[i++] = Expressions.toValue((ExpressionImpl<?>)e, factory, q);
return factory.coalesceExpression(vs);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, values.toArray(new ExpressionImpl[values.size()]));
}
@Override
public StringBuilder asValue(AliasContext 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> {
private Expression<T> val1;
private Expression<?> val2;
public Nullif(Expression<T> x, Expression<?> y) {
super((Class<T>)x.getJavaType());
val1 = x;
val2 = y;
}
public Nullif(Expression<T> x, T y) {
this(x, new Constant<>(y));
}
@Override
public org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value value1 = Expressions.toValue((ExpressionImpl<?>)val1, factory, q);
Value value2 = Expressions.toValue((ExpressionImpl<?>)val2, factory, q);
return factory.nullIfExpression(value1, value2);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, val1, val2);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "NULLIF", OPEN_BRACE, val1, COMMA, val2, CLOSE_BRACE);
}
}
public static class IsNull extends PredicateImpl {
final ExpressionImpl<?> e;
public IsNull(ExpressionImpl<?> e) {
super();
this.e = e;
}
@Override
public PredicateImpl not() {
return new IsNotNull(e).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.equal(
Expressions.toValue(e, factory, q),
factory.getNull());
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e, " IS NULL");
}
}
public static class IsNotNull extends PredicateImpl {
final ExpressionImpl<?> e;
public IsNotNull(ExpressionImpl<?> e) {
super();
this.e = e;
}
@Override
public PredicateImpl not() {
return new IsNull(e).markNegated();
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.notEqual(
Expressions.toValue(e, factory, q),
factory.getNull());
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, e);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, e, " IS NOT NULL");
}
}
public static class In<T> extends PredicateImpl.Or implements CriteriaBuilder.In<T> {
final ExpressionImpl<T> e;
public In(Expression<?> e) {
super();
this.e = (ExpressionImpl<T>)e;
}
@Override
public Expression<T> getExpression() {
return e;
}
@Override
public In<T> value(T value) {
add(new Expressions.Equal(e,value));
return this;
}
@Override
public In<T> value(Expression<? extends T> value) {
add(new Expressions.Equal(e,value));
return this;
}
@Override
public PredicateImpl not() {
In<T> notIn = new In<>(e);
notIn.markNegated();
for (Predicate e : _exps) {
notIn.add(e);
}
return notIn;
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, CriteriaQueryImpl<?> q) {
org.apache.openjpa.kernel.exps.Expression inExpr = null;
if (_exps.size() == 1) {
Expressions.Equal e = (Expressions.Equal)_exps.get(0);
ExpressionImpl<?> e2 = e.e2;
ExpressionImpl<?> e1 = e.e1;
Class<?> e1JavaType = e1.getJavaType();
Class<?> e2JavaType = e2.getJavaType();
// array and Collection
if (BindableParameter.class.isInstance(e2) && BindableParameter.class.cast(e2).value() != null &&
((e2JavaType.isArray() && e2JavaType.getComponentType().equals(e1JavaType))
|| (Class.class.isInstance(e2JavaType) ||
(ParameterizedType.class.isInstance(e2JavaType)
&& ParameterizedType.class.cast(e2JavaType).getActualTypeArguments().length > 0
&& e1JavaType.equals(ParameterizedType.class.cast(e2JavaType).getActualTypeArguments()[0]))
))) {
final BindableParameter bp = BindableParameter.class.cast(e2);
final Object value = bp.value();
_exps.clear();
if (value == null) {
add(new Expressions.Equal(e1, null));
} else if (value.getClass().isArray()) {
final int len = Array.getLength(value);
for (int i = 0; i < len; i++) {
add(new Expressions.Equal(e1, Array.get(value, i)));
}
} else if (Collection.class.isInstance(value)) {
for (final Object item : Collection.class.cast(value)) {
add(new Expressions.Equal(e1, item));
}
}
} else {
// normal case
Value val2 = Expressions.toValue(e2, factory, q);
if (!(val2 instanceof Literal)) {
Value val1 = Expressions.toValue(e1, factory, q);
Expressions.setImplicitTypes(val1, val2, e1.getJavaType(), q);
inExpr = factory.contains(val2, val1);
return isNegated() ? factory.not(inExpr) : inExpr;
} else if (((Literal)val2).getParseType() == Literal.TYPE_COLLECTION) {
Collection coll = (Collection)((Literal)val2).getValue();
_exps.clear();
for (Object v : coll) {
add(new Expressions.Equal(e1,v));
}
}
}
}
inExpr = super.toKernelExpression(factory, q);
IsNotNull notNull = new Expressions.IsNotNull(e);
return factory.and(inExpr, notNull.toKernelExpression(factory, q));
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
super.acceptVisit(visitor);
Expressions.acceptVisit(visitor, this, e);
}
@Override
public StringBuilder asValue(AliasContext q) {
StringBuilder buffer = Expressions.asValue(q, e, " 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 CriteriaBuilder.Case<T> {
private final List<Expression<? extends T>> thens = new ArrayList<>();
private final List<Expression<Boolean>> whens = new ArrayList<>();
private Expression<? extends T> otherwise;
public Case(Class<T> cls) {
super(cls);
}
@Override
public Case<T> when(Expression<Boolean> when, Expression<? extends T> then) {
whens.add(when);
thens.add(then);
return this;
}
@Override
public Case<T> when(Expression<Boolean> when, T then) {
return when(when, new Expressions.Constant<>(then));
}
@Override
public Case<T> otherwise(Expression<? extends T> otherwise) {
this.otherwise = otherwise;
return this;
}
@Override
public Case<T> otherwise(T otherwise) {
return otherwise(new Expressions.Constant<>(otherwise));
}
@Override
public org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
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 =
((ExpressionImpl<?>)whens.get(i)).toKernelExpression(factory, q);
Value action = Expressions.toValue((ExpressionImpl<?>)thens.get(i), factory, q);
exps[i] = factory.whenCondition(expr, action);
}
Value other = Expressions.toValue((ExpressionImpl<?>)otherwise, factory, q);
return factory.generalCaseExpression(exps, other);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
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(AliasContext 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;
}
}
public static class SimpleCase<C,R> extends ExpressionImpl<R> implements CriteriaBuilder.SimpleCase<C,R> {
private final List<Expression<? extends R>> thens = new ArrayList<>();
private final List<Expression<C>> whens = new ArrayList<>();
private Expression<? extends R> otherwise;
private Expression<C> caseOperand;
public SimpleCase(Class<R> cls) {
super(cls);
}
public SimpleCase(Expression<C> expr) {
super(null);
this.caseOperand = expr;
}
@Override
public Expression<C> getExpression() {
return caseOperand;
}
public SimpleCase<C,R> when(Expression<C> when, Expression<? extends R> then) {
whens.add(when);
thens.add(then);
return this;
}
@Override
public SimpleCase<C,R> when(C when, Expression<? extends R> then) {
return when(new Constant<>(when), then);
}
@Override
public SimpleCase<C,R> when(C when, R then) {
return when(when, new Expressions.Constant<>(then));
}
@Override
public SimpleCase<C,R> otherwise(Expression<? extends R> otherwise) {
this.otherwise = otherwise;
return this;
}
@Override
public SimpleCase<C,R> otherwise(R otherwise) {
return otherwise(new Expressions.Constant<>(otherwise));
}
@Override
public org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
Value caseOperandExpr = Expressions.toValue((ExpressionImpl<?>)caseOperand, factory, q);
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++) {
Value when = Expressions.toValue((ExpressionImpl<C>)whens.get(i), factory, q);
Value action = Expressions.toValue((ExpressionImpl<?>)thens.get(i), factory, q);
exps[i] = factory.whenScalar(when, action);
}
Value other = Expressions.toValue((ExpressionImpl<?>)otherwise, factory, q);
return factory.simpleCaseExpression(caseOperandExpr, exps, other);
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
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(AliasContext 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;
}
}
public static class Lower extends UnaryFunctionalExpression<String> {
public Lower(Expression<String> x) {
super(String.class, x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.toLowerCase(Expressions.toValue(e, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "LOWER", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Upper extends UnaryFunctionalExpression<String> {
public Upper(Expression<String> x) {
super(String.class, x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.toUpperCase(Expressions.toValue(e, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "UPPER", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Length extends UnaryFunctionalExpression<Integer> {
public Length(Expression<String> x) {
super(Integer.class, x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.stringLength(Expressions.toValue(e, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "LENGTH", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static abstract class SubqueryPredicate<X> extends PredicateImpl {
final SubqueryImpl<X> e;
public SubqueryPredicate(Subquery<X> x) {
super();
e = (SubqueryImpl<X>)x;
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, e);
}
}
public static abstract class SubqueryExpression<X> extends ExpressionImpl<X> {
final SubqueryImpl<X> e;
public SubqueryExpression(Subquery<X> x) {
super((Class<X>)x.getJavaType());
e = (SubqueryImpl<X>)x;
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, e);
}
}
public static class Exists<X> extends SubqueryPredicate<X> {
public Exists(Subquery<X> x) {
super(x);
}
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, CriteriaQueryImpl<?> q) {
org.apache.openjpa.kernel.exps.Expression exists =
factory.isNotEmpty(Expressions.toValue(e, factory, q));
return exists;
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, " EXISTS", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class All<X> extends SubqueryExpression<X> {
public All(Subquery<X> x) {
super(x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.all(Expressions.toValue(e, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "ALL", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Any<X> extends SubqueryExpression<X> {
public Any(Subquery<X> x) {
super(x);
}
@Override
public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.any(Expressions.toValue(e, factory, q));
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "ANY", OPEN_BRACE, e, CLOSE_BRACE);
}
}
public static class Not extends PredicateImpl {
protected final ExpressionImpl<Boolean> e;
public Not(Expression<Boolean> ne) {
super();
e = (ExpressionImpl<Boolean>)ne;
}
@Override
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, CriteriaQueryImpl<?> q) {
return factory.not(e.toKernelExpression(factory, q));
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, e);
}
@Override
public StringBuilder asValue(AliasContext q) {
return Expressions.asValue(q, "NOT ", e);
}
}
public static class CastAs<Y> extends ExpressionImpl<Y> {
protected final ExpressionImpl<?> actual;
public CastAs(Class<Y> cast, ExpressionImpl<?> actual) {
super(cast);
this.actual = actual;
}
@Override
public org.apache.openjpa.kernel.exps.Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
org.apache.openjpa.kernel.exps.Value e = actual.toValue(factory, q);
e.setImplicitType(getJavaType());
return e;
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, actual);
}
@Override
public StringBuilder asValue(AliasContext q) {
return actual.asValue(q);
}
}
/**
* An expression that is composed of one or more expressions.
*
* @param <T>
*/
public static class ListArgument<T> extends ExpressionImpl<T> {
private final ExpressionImpl<?>[] _args;
public ListArgument(Class<T> cls, ExpressionImpl<?>... args) {
super(cls);
_args = args;
}
@Override
public org.apache.openjpa.kernel.exps.Arguments toValue(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
org.apache.openjpa.kernel.exps.Value[] kvs = new org.apache.openjpa.kernel.exps.Value[_args.length];
int i = 0;
for (ExpressionImpl<?> arg : _args) {
kvs[i++] = arg.toValue(factory, q);
}
org.apache.openjpa.kernel.exps.Arguments e = factory.newArgumentList(kvs);
e.setImplicitType(getJavaType());
return e;
}
@Override
public void acceptVisit(CriteriaExpressionVisitor visitor) {
Expressions.acceptVisit(visitor, this, _args);
}
}
}