| /* |
| * 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); |
| } |
| } |
| } |