Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.eclipse.persistence.internal.jpa.querydef.CriteriaBuilderImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2009, 2024 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Gordon Yorke - Initial development
// 02/01/2022: Tomas Kraus
// - Issue 1442: Implement New Jakarta Persistence 3.1 Features
// 04/19/2022: Jody Grassel
// - Issue 579726: CriteriaBuilder neg() only returns Integer type, instead of it's argument expression type.
// 08/22/2023: Tomas Kraus
// - New Jakarta Persistence 3.2 Features
package org.eclipse.persistence.internal.jpa.querydef;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.temporal.Temporal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.CollectionJoin;
import jakarta.persistence.criteria.CompoundSelection;
import jakarta.persistence.criteria.CriteriaDelete;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.CriteriaSelect;
import jakarta.persistence.criteria.CriteriaUpdate;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.ListJoin;
import jakarta.persistence.criteria.MapJoin;
import jakarta.persistence.criteria.Nulls;
import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.ParameterExpression;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Predicate.BooleanOperator;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Selection;
import jakarta.persistence.criteria.SetJoin;
import jakarta.persistence.criteria.Subquery;
import jakarta.persistence.criteria.TemporalField;
import jakarta.persistence.metamodel.EntityType;
import jakarta.persistence.metamodel.Metamodel;
import jakarta.persistence.metamodel.Type.PersistenceType;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.expressions.ExpressionMath;
import org.eclipse.persistence.expressions.ExpressionOperator;
import org.eclipse.persistence.internal.expressions.ArgumentListFunctionExpression;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.expressions.FunctionExpression;
import org.eclipse.persistence.internal.expressions.SubSelectExpression;
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl;
import org.eclipse.persistence.internal.jpa.metamodel.TypeImpl;
import org.eclipse.persistence.internal.jpa.querydef.AbstractQueryImpl.ResultType;
import org.eclipse.persistence.internal.jpa.querydef.CriteriaMultiSelectImpl.Union;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.jpa.JpaCriteriaBuilder;
import org.eclipse.persistence.queries.ReportQuery;
import static org.eclipse.persistence.internal.jpa.querydef.ExpressionImpl.currentNode;
public class CriteriaBuilderImpl implements JpaCriteriaBuilder, Serializable {
public static final String CONCAT = "concat";
public static final String SIZE = "size";
protected Metamodel metamodel;
public CriteriaBuilderImpl(Metamodel metamodel){
this.metamodel = metamodel;
}
/**
* Create a Criteria query object.
* @return query object
*/
@Override
public CriteriaQuery createQuery(){
return new CriteriaQueryImpl<>(this.metamodel, ResultType.UNKNOWN, ClassConstants.OBJECT, this);
}
/**
* Create a Criteria query object.
* @return query object
*/
@Override
@SuppressWarnings("unchecked")
public CriteriaQuery createQuery(Class resultClass) {
if (resultClass == null) {
return (CriteriaQuery) this.createQuery();
}
if (resultClass.equals(Tuple.class)) {
return new CriteriaQueryImpl<>(this.metamodel, ResultType.TUPLE, resultClass, this);
} else if (resultClass.equals(ClassConstants.AOBJECT)) {
return new CriteriaQueryImpl<>(this.metamodel, ResultType.OBJECT_ARRAY, resultClass, this);
} else if (resultClass.isArray()) {
return new CriteriaQueryImpl<>(this.metamodel, ResultType.OBJECT_ARRAY, resultClass, this);
} else {
if (resultClass.equals(ClassConstants.OBJECT)) {
return (CriteriaQuery) this.createQuery();
} else {
if (resultClass.isPrimitive() || resultClass.equals(ClassConstants.STRING)|| BasicTypeHelperImpl.getInstance().isWrapperClass(resultClass) || BasicTypeHelperImpl.getInstance().isDateClass(resultClass)) {
return new CriteriaQueryImpl<>(metamodel, ResultType.OTHER, resultClass, this);
} else {
TypeImpl type = ((MetamodelImpl)this.metamodel).getType(resultClass);
if (type != null && type.getPersistenceType().equals(PersistenceType.ENTITY)) {
return new CriteriaQueryImpl<>(this.metamodel, ResultType.ENTITY, resultClass, this);
} else {
return new CriteriaQueryImpl<>(this.metamodel, ResultType.CONSTRUCTOR, resultClass, this);
}
}
}
}
}
/**
* Create a Criteria query object that returns a tuple of
* objects as its result.
* @return query object
*/
@Override
public CriteriaQuery createTupleQuery(){
return new CriteriaQueryImpl<>(this.metamodel, ResultType.TUPLE, Tuple.class, this);
}
/**
* Define a select list item corresponding to a constructor.
*
* @param result
* class whose instance is to be constructed
* @param selections
* arguments to the constructor
* @return selection item
*/
@Override
public CompoundSelection construct(Class result, Selection>... selections){
return new ConstructorSelectionImpl<>(result, selections);
}
@Override
public CompoundSelection tuple(Selection>... selections){
return new CompoundSelectionImpl<>(Tuple.class, selections, true);
}
@Override
public CompoundSelection tuple(List> selections) {
return tuple(selections != null
? selections.toArray(new Selection>[0])
: null);
}
/**
* Create an array-valued selection item
* @param selections selection items
* @return array-valued compound selection
* @throws IllegalArgumentException if an argument is a tuple- or
* array-valued selection item
*/
@Override
public CompoundSelection array(Selection>... selections){
return new CompoundSelectionImpl<>((Class extends Object[]>) ClassConstants.AOBJECT, selections, true);
}
@Override
public CompoundSelection array(List> selections) {
return array(selections != null
? selections.toArray(new Selection>[0])
: null);
}
@Override
public Order asc(Expression> expression) {
return asc(expression, Nulls.NONE);
}
// TODO-API-3.2 - Nulls added to OrderImpl and ObjectLevelReadQuery in CriteriaQueryImpl, but no tests exist
@Override
public Order asc(Expression> expression, Nulls nullPrecedence) {
if (currentNode(expression) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new OrderImpl(expression, true, nullPrecedence);
}
@Override
public Order desc(Expression> expression){
return desc(expression, Nulls.NONE);
}
// TODO-API-3.2 - Nulls added to OrderImpl and ObjectLevelReadQuery in CriteriaQueryImpl, but no tests exist
@Override
public Order desc(Expression> expression, Nulls nullPrecedence) {
if (currentNode(expression) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new OrderImpl(expression, false, nullPrecedence);
}
// aggregate functions:
/**
* Create an expression applying the avg operation.
*
* @param x
* expression representing input value to avg operation
* @return avg expression
*/
@Override
public Expression avg(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.DOUBLE, currentNode(x).average(), buildList(x), "AVG");
}
/**
* Create an expression applying the sum operation.
*
* @param x
* expression representing input value to sum operation
* @return sum expression
*/
@Override
public Expression sum(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(), currentNode(x).sum(), buildList(x), "SUM");
}
/**
* Create an expression applying the numerical max operation.
*
* @param x
* expression representing input value to max operation
* @return max expression
*/
@Override
public Expression max(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(), currentNode(x).maximum(), buildList(x), "MAX");
}
/**
* Create an expression applying the numerical min operation.
*
* @param x
* expression representing input value to min operation
* @return min expression
*/
@Override
public Expression min(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(), currentNode(x).minimum(), buildList(x), "MIN");
}
/**
* Create an aggregate expression for finding the greatest of the values
* (strings, dates, etc).
*
* @param x
* expression representing input value to greatest operation
* @return greatest expression
*/
@Override
public > Expression greatest(Expression x){
if (currentNode(x) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new ExpressionImpl<>(this.metamodel, x.getJavaType(), currentNode(x).maximum());
}
/**
* Create an aggregate expression for finding the least of the values
* (strings, dates, etc).
*
* @param x
* expression representing input value to least operation
* @return least expression
*/
@Override
public > Expression least(Expression x){
if (currentNode(x) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new ExpressionImpl<>(this.metamodel, x.getJavaType(),currentNode(x).minimum());
}
/**
* Create an expression applying the count operation.
*
* @param x
* expression representing input value to count operation
* @return count expression
*/
@Override
public Expression count(Expression> x){
if (currentNode(x) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.LONG, currentNode(x).count(), buildList(x),"COUNT");
}
/**
* Create an expression applying the count distinct operation.
*
* @param x
* expression representing input value to count distinct
* operation
* @return count distinct expression
*/
@Override
public Expression countDistinct(Expression> x){
if (currentNode(x) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.LONG, currentNode(x).distinct().count(), buildList(x),"COUNT");
}
// subqueries:
/**
* Create a predicate testing the existence of a subquery result.
*
* @param subquery
* subquery whose result is to be tested
* @return exists predicate
*/
@Override
public Predicate exists(Subquery> subquery){
// Setting SubQuery's SubSelectExpression as a base for the expression created by operator allows setting a new ExpressionBuilder later in the SubSelectExpression (see integrateRoot method in SubQueryImpl).
return new CompoundExpressionImpl(
metamodel,
org.eclipse.persistence.expressions.Expression.getOperator(ExpressionOperator.Exists)
.expressionFor(((SubQueryImpl>)subquery).getCurrentNode()),
buildList(subquery),
"exists");
}
/**
* Create a predicate corresponding to an all expression over the subquery
* results.
*
* @return all expression
*/
@Override
public Expression all(Subquery subquery){
return new FunctionExpressionImpl<>(metamodel, subquery.getJavaType(), new ExpressionBuilder().all(currentNode(subquery)), buildList(subquery), "all");
}
/**
* Create a predicate corresponding to a some expression over the subquery
* results. This is equivalent to an any expression.
*
* @return all expression
*/
@Override
public Expression some(Subquery subquery){
return new FunctionExpressionImpl<>(metamodel, subquery.getJavaType(), new ExpressionBuilder().some(currentNode(subquery)), buildList(subquery), "some");
}
/**
* Create a predicate corresponding to an any expression over the subquery
* results. This is equivalent to a some expression.
*
* @return any expression
*/
@Override
public Expression any(Subquery subquery){
return new FunctionExpressionImpl<>(metamodel, subquery.getJavaType(), new ExpressionBuilder().any(currentNode(subquery)), buildList(subquery), "any");
}
// boolean functions:
/**
* Create a conjunction of the given boolean expressions.
*
* @param x
* boolean expression
* @param y
* boolean expression
* @return and predicate
*/
@Override
public Predicate and(Expression x, Expression y){
CompoundExpressionImpl xp = null;
CompoundExpressionImpl yp = null;
if (((InternalExpression)x).isExpression()){
xp = (CompoundExpressionImpl)this.isTrue(x);
}else{
xp = (CompoundExpressionImpl)x;
}
if (((InternalExpression)y).isExpression()){
yp = (CompoundExpressionImpl)this.isTrue(y);
}else{
yp = (CompoundExpressionImpl)y;
}
//bug 413084
if (yp.isJunction()){
if ( ((PredicateImpl)yp).getJunctionValue()){
return xp;//yp is true and so can be ignored/extracted
}else{
return yp;//yp is false so the statement is false
}
}
if (xp.isJunction()){
if (((PredicateImpl)xp).getJunctionValue()){
return yp;
}else{
return xp;
}
}
org.eclipse.persistence.expressions.Expression currentNode = xp.getCurrentNode().and(yp.getCurrentNode());
xp.setParentNode(currentNode);
yp.setParentNode(currentNode);
return new PredicateImpl(this.metamodel, currentNode, buildList(xp,yp), BooleanOperator.AND);
}
/**
* Create a disjunction of the given boolean expressions.
*
* @param x
* boolean expression
* @param y
* boolean expression
* @return or predicate
*/
@Override
public Predicate or(Expression x, Expression y){
CompoundExpressionImpl xp = null;
CompoundExpressionImpl yp = null;
if (((InternalExpression)x).isExpression()){
xp = (CompoundExpressionImpl)this.isTrue(x);
}else{
xp = (CompoundExpressionImpl)x;
}
if (((InternalExpression)y).isExpression()){
yp = (CompoundExpressionImpl)this.isTrue(y);
}else{
yp = (CompoundExpressionImpl)y;
}
//bug 413084
if (yp.isJunction()){
if (((PredicateImpl)yp).getJunctionValue()){
return yp;//yp is true so the statement is true
}
return xp;//yp is false so can be extracted.
}
if (xp.isJunction()){
if (((PredicateImpl)xp).getJunctionValue()){
return xp;
}
return yp;
}
org.eclipse.persistence.expressions.Expression parentNode = xp.getCurrentNode().or(yp.getCurrentNode());
xp.setParentNode(parentNode);
yp.setParentNode(parentNode);
return new PredicateImpl(this.metamodel, parentNode, buildList(xp,yp), BooleanOperator.OR);
}
/**
* Create a conjunction of the given restriction predicates.
* A conjunction of {@code null} or zero predicates is {@code true}.
*
* @param restrictions zero or more restriction predicates
* @return and predicate
*/
@Override
public Predicate and(Predicate... restrictions) {
return and(restrictions != null ? List.of(restrictions) : null);
}
@Override
public Predicate and(List restrictions) {
// PERF: Build simple cases directly
switch (restrictions != null ? restrictions.size() : 0) {
case 0:
return this.conjunction();
case 1:
return restrictions.get(0);
case 2:
return and(restrictions.get(0), restrictions.get(1));
default:
Predicate predicate = restrictions.get(0);
for (int i = 1; i < restrictions.size(); i++) {
predicate = and(predicate, restrictions.get(i));
}
return predicate;
}
}
/**
* Create a disjunction of the given restriction predicates.
* A disjunction of {@code null} or zero predicates is {@code false}.
*
* @param restrictions zero or more restriction predicates
* @return and predicate
*/
@Override
public Predicate or(Predicate... restrictions) {
return or(restrictions != null ? List.of(restrictions) : null);
}
@Override
public Predicate or(List restrictions) {
// PERF: Build simple cases directly
switch (restrictions != null ? restrictions.size() : 0) {
case 0:
return this.disjunction();
case 1:
return restrictions.get(0);
case 2:
return or(restrictions.get(0), restrictions.get(1));
default:
Predicate predicate = restrictions.get(0);
for (int i = 1; i < restrictions.size(); i++) {
predicate = or(predicate, restrictions.get(i));
}
return predicate;
}
}
/**
* Create a negation of the given restriction.
*
* @param restriction
* restriction expression
* @return not predicate
*/
@Override
public Predicate not(Expression restriction){
if (((InternalExpression)restriction).isPredicate()){
return ((Predicate)restriction).not();
}
org.eclipse.persistence.expressions.Expression parentNode = null;
List> compoundExpressions = null;
String name = "not";
if (((InternalExpression)restriction).isCompoundExpression() && ((CompoundExpressionImpl)restriction).getOperation().equals("exists")){
FunctionExpression exp = (FunctionExpression) currentNode(restriction);
SubSelectExpression sub = (SubSelectExpression) exp.getChildren().get(0);
parentNode = org.eclipse.persistence.expressions.Expression.getOperator(ExpressionOperator.NotExists).expressionFor(sub);
name = "notExists";
compoundExpressions = ((CompoundExpressionImpl)restriction).getChildExpressions();
}else{
parentNode = currentNode(restriction).not();
compoundExpressions = buildList(restriction);
}
CompoundExpressionImpl expr = new CompoundExpressionImpl(this.metamodel, parentNode, compoundExpressions, name);
expr.setIsNegated(true);
return expr;
}
/**
* Create a conjunction (with zero conjuncts). A conjunction with zero
* conjuncts is true.
*
* @return and predicate
*/
@Override
public Predicate conjunction(){
return new PredicateImpl(this.metamodel, null, null, BooleanOperator.AND);
}
/**
* Create a disjunction (with zero disjuncts). A disjunction with zero
* disjuncts is false.
*
* @return or predicate
*/
@Override
public Predicate disjunction(){
return new PredicateImpl(this.metamodel, null, null, BooleanOperator.OR);
}
// turn Expression into a Predicate
// useful for use with varargs methods
/**
* Create a predicate testing for a true value.
*
* @param x
* expression to be tested if true
* @return predicate
*/
@Override
public Predicate isTrue(Expression x){
if (((InternalExpression)x).isPredicate()){
if (currentNode(x) == null){
return (Predicate)x;
}else{
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("PREDICATE_PASSED_TO_EVALUATION"));
}
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).equal(true), buildList(x), "equals");
}
/**
* Create a predicate testing for a false value.
*
* @param x
* expression to be tested if false
* @return predicate
*/
@Override
public Predicate isFalse(Expression x){
if (((InternalExpression)x).isPredicate()){
if (currentNode(x) == null){
if (((Predicate)x).getOperator() == BooleanOperator.AND){
return (Predicate)x;
}else{
return this.conjunction();
}
}else{
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("PREDICATE_PASSED_TO_EVALUATION"));
}
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).equal(false), buildList(x), "equals");
}
//null tests:
/**
* Create a predicate to test whether the expression is null.
* @param x expression
* @return predicate
*/
@Override
public Predicate isNull(Expression> x){
return new PredicateImpl(this.metamodel, currentNode(x).isNull(), buildList(x), BooleanOperator.AND);
}
/**
* Create a predicate to test whether the expression is not null.
* @param x expression
* @return predicate
*/
@Override
public Predicate isNotNull(Expression> x){
return new PredicateImpl(this.metamodel, currentNode(x).notNull(), buildList(x), BooleanOperator.AND);
}
// equality:
/**
* Create a predicate for testing the arguments for equality.
*
* @param x
* expression
* @param y
* expression
* @return equality predicate
*/
@Override
public Predicate equal(Expression> x, Expression> y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).equal(currentNode(y)), buildList(x, y), "equals");
}
/**
* Create a predicate for testing the arguments for inequality.
*
* @param x
* expression
* @param y
* expression
* @return inequality predicate
*/
@Override
public Predicate notEqual(Expression> x, Expression> y){
if (currentNode(x) == null || currentNode(y) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).notEqual(currentNode(y)), buildList(x, y), "not equal");
}
/**
* Create a predicate for testing the arguments for equality.
*
* @param x
* expression
* @param y
* object
* @return equality predicate
*/
@Override
public Predicate equal(Expression> x, Object y){
//parameter is not an expression.
if (currentNode(x) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
if (y instanceof ParameterExpression) {
return this.equal(x, (ParameterExpression>) y);
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).equal(y), buildList(x, internalLiteral(y)), "equal");
}
/**
* Create a predicate for testing the arguments for inequality.
*
* @param x
* expression
* @param y
* object
* @return inequality predicate
*/
@Override
public Predicate notEqual(Expression> x, Object y){
if (currentNode(x) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
if (y instanceof ParameterExpression)
return this.notEqual(x, (ParameterExpression>)y);
return new CompoundExpressionImpl(this.metamodel, currentNode(x).notEqual(y), buildList(x, internalLiteral(y)), "not equal");
}
// comparisons for generic (non-numeric) operands:
/**
* Create a predicate for testing whether the first argument is greater than
* the second.
*
* @param x
* expression
* @param y
* expression
* @return greater-than predicate
*/
@Override
public > Predicate greaterThan(Expression extends Y> x, Expression extends Y> y){
if (currentNode(x) == null || currentNode(y) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThan(currentNode(y)), buildList(x, y), "greaterThan");
}
/**
* Create a predicate for testing whether the first argument is less than
* the second.
*
* @param x
* expression
* @param y
* expression
* @return less-than predicate
*/
@Override
public > Predicate lessThan(Expression extends Y> x, Expression extends Y> y){
if (currentNode(x) == null || currentNode(y) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThan(currentNode(y)), buildList(x,y), "lessThan");
}
/**
* Create a predicate for testing whether the first argument is greater than
* or equal to the second.
*
* @param x
* expression
* @param y
* expression
* @return greater-than-or-equal predicate
*/
@Override
public > Predicate greaterThanOrEqualTo(Expression extends Y> x, Expression extends Y> y){
if (currentNode(x) == null || currentNode(y) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThanEqual(currentNode(y)), buildList(x, y), "greaterThanEqual");
}
/**
* Create a predicate for testing whether the first argument is less than or
* equal to the second.
*
* @param x
* expression
* @param y
* expression
* @return less-than-or-equal predicate
*/
@Override
public > Predicate lessThanOrEqualTo(Expression extends Y> x, Expression extends Y> y){
if (currentNode(x) == null || currentNode(y) == null){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThanEqual(currentNode(y)), buildList(x, y), "lessThanEqual");
}
/**
* Create a predicate for testing whether the first argument is between the
* second and third arguments in value.
*
* @param v
* expression
* @param x
* expression
* @param y
* expression
* @return between predicate
*/
@Override
public > Predicate between(Expression extends Y> v, Expression extends Y> x, Expression extends Y> y){
return new CompoundExpressionImpl(this.metamodel, currentNode(v).between(currentNode(x), currentNode(y)), buildList(v, x, y), "between");
}
/**
* Create a predicate for testing whether the first argument is greater than
* the second.
*
* @param x
* expression
* @param y
* value
* @return greater-than predicate
*/
@Override
public > Predicate greaterThan(Expression extends Y> x, Y y){
if (currentNode(x) == null ){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
Expression expressionY = internalLiteral(y);
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThan(currentNode(expressionY)), buildList(x, expressionY), "greaterThan");
}
/**
* Create a predicate for testing whether the first argument is less than
* the second.
*
* @param x
* expression
* @param y
* value
* @return less-than predicate
*/
@Override
public > Predicate lessThan(Expression extends Y> x, Y y){
if (currentNode(x) == null ){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
Expression expressionY = internalLiteral(y);
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThan(currentNode(expressionY)), buildList(x, expressionY), "lessThan");
}
/**
* Create a predicate for testing whether the first argument is greater than
* or equal to the second.
*
* @param x
* expression
* @param y
* value
* @return greater-than-or-equal predicate
*/
@Override
public > Predicate greaterThanOrEqualTo(Expression extends Y> x, Y y){
if (currentNode(x) == null ){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
Expression expressionY = internalLiteral(y);
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThanEqual(currentNode(expressionY)), buildList(x, expressionY), "greaterThanEqual");
}
/**
* Create a predicate for testing whether the first argument is less than or
* equal to the second.
*
* @param x
* expression
* @param y
* value
* @return less-than-or-equal predicate
*/
@Override
public > Predicate lessThanOrEqualTo(Expression extends Y> x, Y y){
if (currentNode(x) == null ){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("OPERATOR_EXPRESSION_IS_CONJUNCTION"));
}
Expression expressionY = internalLiteral(y);
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThanEqual(currentNode(expressionY)), buildList(x, expressionY), "lessThanEqual");
}
/**
* Create a predicate for testing whether the first argument is between the
* second and third arguments in value.
*
* @param v
* expression
* @param x
* value
* @param y
* value
* @return between predicate
*/
@Override
public > Predicate between(Expression extends Y> v, Y x, Y y){
return new CompoundExpressionImpl(this.metamodel, currentNode(v).between(x, y), buildList(v, internalLiteral(x), internalLiteral(y)), "between");
}
protected static List> buildList(Expression>... expressions) {
// Immutable List causes test failures.
// Those lists are usually small (size 1-2) and modifications are rare. Default list size is too much.
List> list = new ArrayList<>(expressions.length + 2);
Collections.addAll(list, expressions);
return list;
}
// comparisons for numeric operands:
/**
* Create a predicate for testing whether the first argument is greater than
* the second.
*
* @param x
* expression
* @param y
* expression
* @return greater-than predicate
*/
@Override
public Predicate gt(Expression extends Number> x, Expression extends Number> y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThan(currentNode(y)), buildList(x, y), "gt");
}
/**
* Create a predicate for testing whether the first argument is less than
* the second.
*
* @param x
* expression
* @param y
* expression
* @return less-than predicate
*/
@Override
public Predicate lt(Expression extends Number> x, Expression extends Number> y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThan(currentNode(y)), buildList(x,y), "lessThan");
}
/**
* Create a predicate for testing whether the first argument is greater than
* or equal to the second.
*
* @param x
* expression
* @param y
* expression
* @return greater-than-or-equal predicate
*/
@Override
public Predicate ge(Expression extends Number> x, Expression extends Number> y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThanEqual(currentNode(y)), buildList(x, y), "ge");
}
/**
* Create a predicate for testing whether the first argument is less than or
* equal to the second.
*
* @param x
* expression
* @param y
* expression
* @return less-than-or-equal predicate
*/
@Override
public Predicate le(Expression extends Number> x, Expression extends Number> y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThanEqual(currentNode(y)), buildList(x, y), "le");
}
/**
* Create a predicate for testing whether the first argument is greater than
* the second.
*
* @param x
* expression
* @param y
* value
* @return greater-than predicate
*/
@Override
public Predicate gt(Expression extends Number> x, Number y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThan(y), buildList(x, internalLiteral(y)), "gt");
}
/**
* Create a predicate for testing whether the first argument is less than
* the second.
*
* @param x
* expression
* @param y
* value
* @return less-than predicate
*/
@Override
public Predicate lt(Expression extends Number> x, Number y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThan(y), buildList(x, internalLiteral(y)), "lt");
}
/**
* Create a predicate for testing whether the first argument is greater than
* or equal to the second.
*
* @param x
* expression
* @param y
* value
* @return greater-than-or-equal predicate
*/
@Override
public Predicate ge(Expression extends Number> x, Number y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).greaterThanEqual(y), buildList(x, internalLiteral(y)), "ge");
}
/**
* Create a predicate for testing whether the first argument is less than or
* equal to the second.
*
* @param x
* expression
* @param y
* value
* @return less-than-or-equal predicate
*/
@Override
public Predicate le(Expression extends Number> x, Number y){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).lessThanEqual(y), buildList(x, internalLiteral(y)), "le");
}
// numerical operations:
/**
* Create an expression that returns the arithmetic negation of its
* argument.
*
* @param x
* expression
* @return negated expression
*/
@Override
public Expression neg(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(), ExpressionMath.negate(currentNode(x)), buildList(x), "neg");
}
/**
* Create an expression that returns the absolute value of its argument.
*
* @param x
* expression
* @return absolute value
*/
@Override
public Expression abs(Expression x){
return new FunctionExpressionImpl<>(metamodel, x.getJavaType(), ExpressionMath.abs(currentNode(x)), buildList(x), "ABS");
}
/**
* Create an expression that returns the sum of its arguments.
*
* @param x
* expression
* @param y
* expression
* @return sum
*/
@Override
public Expression sum(Expression extends N> x, Expression extends N> y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getJavaType(), y.getJavaType()),
ExpressionMath.add(currentNode(x),currentNode(y)),
buildList(x,y),
"sum");
}
/**
* Create an aggregate expression applying the sum operation to an
* Integer-valued expression, returning a Long result.
* @param x expression representing input value to sum operation
* @return sum expression
*/
@Override
public Expression sumAsLong(Expression x) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.LONG, currentNode(x).sum(), buildList(x),"SUM");
}
/**
* Create an aggregate expression applying the sum operation to a
* Float-valued expression, returning a Double result.
* @param x expression representing input value to sum operation
* @return sum expression
*/
@Override
public Expression sumAsDouble(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.DOUBLE, currentNode(x).sum(), buildList(x),"SUM");
}
/**
* Create an expression that returns the product of its arguments.
*
* @param x
* expression
* @param y
* expression
* @return product
*/
@Override
public Expression prod(Expression extends N> x, Expression extends N> y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getJavaType(), y.getJavaType()),
ExpressionMath.multiply(currentNode(x),currentNode(y)),
buildList(x,y),
"prod");
}
/**
* Create an expression that returns the difference between its arguments.
*
* @param x
* expression
* @param y
* expression
* @return difference
*/
@Override
public Expression diff(Expression extends N> x, Expression extends N> y){
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(), ExpressionMath.subtract(currentNode(x), currentNode(y)), buildList(x, y), "diff");
}
/**
* Create an expression that returns the sum of its arguments.
*
* @param x
* expression
* @param y
* value
* @return sum
*/
@Override
public Expression sum(Expression extends N> x, N y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getJavaType(), y.getClass()),
ExpressionMath.add(currentNode(x),y),
buildList(x,internalLiteral(y)),
"sum");
}
/**
* Create an expression that returns the product of its arguments.
*
* @param x
* expression
* @param y
* value
* @return product
*/
@Override
public Expression prod(Expression extends N> x, N y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getJavaType(), y.getClass()),
ExpressionMath.multiply(currentNode(x),y),
buildList(x,internalLiteral(y)),
"prod");
}
/**
* Create an expression that returns the difference between its arguments.
*
* @param x
* expression
* @param y
* value
* @return difference
*/
@Override
@SuppressWarnings("unchecked") // y.getClass() cast
public Expression diff(Expression extends N> x, N y){
return new FunctionExpressionImpl<>(
this.metamodel,
(Class extends N>) y.getClass(),
ExpressionMath.subtract(currentNode(x), y),
buildList(x, internalLiteral(y)),
"diff");
}
/**
* Create an expression that returns the sum of its arguments.
*
* @param x
* value
* @param y
* expression
* @return sum
*/
@Override
public Expression sum(N x, Expression extends N> y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getClass(), y.getJavaType()),
ExpressionMath.add(new ConstantExpression(x, currentNode(y)),currentNode(y)),
buildList(internalLiteral(x),y),
"sum");
}
/**
* Create an expression that returns the product of its arguments.
*
* @param x
* value
* @param y
* expression
* @return product
*/
@Override
public Expression prod(N x, Expression extends N> y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getClass(), y.getJavaType()),
ExpressionMath.multiply(new ConstantExpression(x, currentNode(y)),currentNode(y)),
buildList(internalLiteral(x),y),
"prod");
}
/**
* Create an expression that returns the difference between its arguments.
*
* @param x
* value
* @param y
* expression
* @return difference
*/
@Override
public Expression diff(N x, Expression extends N> y){
Expression literal = internalLiteral(x);
return new FunctionExpressionImpl<>(
this.metamodel,
literal.getJavaType(),
ExpressionMath.subtract(currentNode(literal), currentNode(y)),
buildList(literal, y), "diff");
}
/**
* Create an expression that returns the quotient of its arguments.
*
* @param x
* expression
* @param y
* expression
* @return quotient
*/
@Override
public Expression quot(Expression extends Number> x, Expression extends Number> y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getJavaType(), y.getClass()),
ExpressionMath.divide(currentNode(x),currentNode(y)),
buildList(x,y),
"quot");
}
/**
* Create an expression that returns the quotient of its arguments.
*
* @param x
* expression
* @param y
* value
* @return quotient
*/
@Override
public Expression quot(Expression extends Number> x, Number y){
return new FunctionExpressionImpl<>(
this.metamodel,
BasicTypeHelperImpl.getInstance().extendedBinaryNumericPromotionClass(x.getJavaType(), y.getClass()),
ExpressionMath.divide(currentNode(x),y),
buildList(x,internalLiteral(y)),
"quot");
}
/**
* Create an expression that returns the quotient of its arguments.
*
* @param x
* value
* @param y
* expression
* @return quotient
*/
@Override
public Expression quot(Number x, Expression extends Number> y){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.NUMBER, ExpressionMath.divide(new ConstantExpression(x, currentNode(y)),currentNode(y)), buildList(internalLiteral(x),y), "quot");
}
/**
* Create an expression that returns the modulus of its arguments.
*
* @param x
* expression
* @param y
* expression
* @return modulus
*/
@Override
public Expression mod(Expression x, Expression y){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.INTEGER, ExpressionMath.mod(currentNode(x),currentNode(y)), buildList(x,y), "mod");
}
/**
* Create an expression that returns the modulus of its arguments.
*
* @param x
* expression
* @param y
* value
* @return modulus
*/
@Override
public Expression mod(Expression x, Integer y){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.INTEGER, ExpressionMath.mod(currentNode(x),y), buildList(x,internalLiteral(y)), "mod");
}
/**
* Create an expression that returns the modulus of its arguments.
*
* @param x
* value
* @param y
* expression
* @return modulus
*/
@Override
public Expression mod(Integer x, Expression y){
Expression xExp = internalLiteral(x);
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.INTEGER, ExpressionMath.mod(currentNode(xExp),currentNode(y)), buildList(xExp,y), "mod");
}
/**
* Create an expression that returns the square root of its argument.
*
* @param x
* expression
* @return modulus
*/
@Override
public Expression sqrt(Expression extends Number> x){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.DOUBLE, ExpressionMath.sqrt(currentNode(x)), buildList(x), "sqrt");
}
/**
* Create an expression that returns the sign of its argument, that is, {@code 1} if its argument is
* positive, {@code -1} if its argument is negative, or {@code 0} if its argument is exactly zero.
*
* @param x expression
* @return sign
*/
@Override
public Expression sign(Expression extends Number> x) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.INTEGER,
ExpressionMath.sign(currentNode(x)), buildList(x), "sign");
}
/**
* Create an expression that returns the ceiling of its argument, that is, the smallest integer greater than
* or equal to its argument.
*
* @param x expression
* @return ceiling
*/
@Override
public Expression ceiling(Expression x) {
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(),
ExpressionMath.ceil(currentNode(x)), buildList(x), "ceiling");
}
/**
* Create an expression that returns the floor of its argument, that is, the largest integer smaller than
* or equal to its argument.
*
* @param x expression
* @return floor
*/
@Override
public Expression floor(Expression x) {
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(),
ExpressionMath.floor(currentNode(x)), buildList(x), "floor");
}
/**
* Create an expression that returns the exponential of its argument, that is, Euler's number e
* raised to the power of its argument.
*
* @param x expression
* @return exponential
*/
@Override
public Expression exp(Expression extends Number> x) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.DOUBLE,
ExpressionMath.exp(currentNode(x)), buildList(x), "exp");
}
/**
* Create an expression that returns the natural logarithm of its argument.
*
* @param x expression
* @return natural logarithm
*/
@Override
public Expression ln(Expression extends Number> x) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.DOUBLE,
ExpressionMath.ln(currentNode(x)), buildList(x), "ln");
}
/**
* Create an expression that returns the first argument raised to the power of its second argument.
*
* @param x base
* @param y exponent
* @return the base raised to the power of the exponent
*/
@Override
public Expression power(Expression extends Number> x, Expression extends Number> y) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.DOUBLE,
ExpressionMath.power(currentNode(x),
currentNode(y)), buildList(x,y), "power");
}
/**
* Create an expression that returns the first argument raised to the power of its second argument.
*
* @param x base
* @param y exponent
* @return the base raised to the power of the exponent
*/
@Override
public Expression power(Expression extends Number> x, Number y) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.DOUBLE,
ExpressionMath.power(currentNode(x), y),
buildList(x, internalLiteral(y)), "power");
}
/**
* Create an expression that returns the first argument rounded to the number of decimal places given by the
* second argument.
*
* @param x base
* @param n number of decimal places
* @return the rounded value
*/
@Override
public Expression round(Expression x, Integer n) {
return new FunctionExpressionImpl<>(this.metamodel, x.getJavaType(),
ExpressionMath.round(currentNode(x), n),
buildList(x, internalLiteral(n)), "round");
}
// typecasts:
/**
* Typecast.
*
* @param number
* numeric expression
* @return Expression<Long>
*/
@Override
@SuppressWarnings("unchecked")
public Expression toLong(Expression extends Number> number){
return (Expression) number;
}
/**
* Typecast.
*
* @param number
* numeric expression
* @return Expression<Integer>
*/
@Override
@SuppressWarnings("unchecked")
public Expression toInteger(Expression extends Number> number){
return (Expression) number;
}
/**
* Typecast.
*
* @param number
* numeric expression
* @return Expression<Float>
*/
@Override
@SuppressWarnings("unchecked")
public Expression toFloat(Expression extends Number> number){
return (Expression) number;
}
/**
* Typecast.
*
* @param number
* numeric expression
* @return Expression<Double>
*/
@Override
@SuppressWarnings("unchecked")
public Expression toDouble(Expression extends Number> number){
return (Expression) number;
}
/**
* Typecast.
*
* @param number
* numeric expression
* @return Expression<BigDecimal>
*/
@Override
@SuppressWarnings("unchecked")
public Expression toBigDecimal(Expression extends Number> number){
return (Expression) number;
}
/**
* Typecast.
*
* @param number
* numeric expression
* @return Expression<BigInteger>
*/
@Override
@SuppressWarnings("unchecked")
public Expression toBigInteger(Expression extends Number> number){
return (Expression) number;
}
/**
* Typecast.
*
* @param character
* expression
* @return Expression<String>
*/
@Override
@SuppressWarnings("unchecked")
public Expression toString(Expression character) {
return (Expression)(Expression>) character;
}
// literals:
/**
* Create an expression literal.
*
* @return expression literal
*/
@Override
public Expression literal(T value){
if (value == null) {
throw new IllegalArgumentException( ExceptionLocalization.buildMessage("jpa_criteriaapi_null_literal_value", new Object[]{}));
}
return ExpressionImpl.createLiteral(value, metamodel);
}
/**
* Create an expression for a null literal with the given type.
*
* @param resultClass type of the null literal
* @return null expression literal
*/
@Override
public Expression nullLiteral(Class resultClass) {
return ExpressionImpl.createLiteral(null, metamodel, resultClass);
}
/**
* Create an expression literal but without null validation.
*
* @return expression literal
*/
protected Expression internalLiteral(T value){
return ExpressionImpl.createLiteral(value, metamodel);
}
// parameters:
/**
* Create a parameter.
* Create a parameter expression.
*
* @param paramClass parameter class
* @return parameter expression
*/
@Override
public ParameterExpression parameter(Class paramClass){
return new ParameterExpressionImpl<>(metamodel, paramClass);
}
/**
* Create a parameter expression with the given name.
*
* @param paramClass
* parameter class
* @return parameter
*/
@Override
public ParameterExpression parameter(Class paramClass, String name){
return new ParameterExpressionImpl<>(metamodel, paramClass, name);
}
// collection operations:
/**
* Create a predicate that tests whether a collection is empty.
*
* @param collection
* expression
* @return predicate
*/
@Override
public > Predicate isEmpty(Expression collection){
if (((InternalExpression)collection).isLiteral()){
if (((Collection>)((ConstantExpression)currentNode(collection)).getValue()).isEmpty()){
return conjunction();
}else{
return disjunction();
}
}
return new CompoundExpressionImpl(metamodel, currentNode(collection).size(ClassConstants.INTEGER).equal(0), buildList(collection), "isEmpty");
}
/**
* Create a predicate that tests whether a collection is not empty.
*
* @param collection
* expression
* @return predicate
*/
@Override
public > Predicate isNotEmpty(Expression collection){
return new CompoundExpressionImpl(metamodel, currentNode(collection).size(ClassConstants.INTEGER).equal(0).not(), buildList(collection), "isNotEmpty");
}
/**
* Create an expression that tests the size of a collection.
*
* @return size expression
*/
@Override
public > Expression size(C collection){
return internalLiteral(collection.size());
}
/**
* Create an expression that tests the size of a collection.
*
* @param collection
* expression
* @return size expression
*/
@Override
public > Expression size(Expression collection){
return new FunctionExpressionImpl<>(metamodel, ClassConstants.INTEGER, currentNode(collection).size(ClassConstants.INTEGER), buildList(collection), SIZE);
}
/**
* Create a predicate that tests whether an element is a member of a
* collection.
*
* @param elem
* element
* @param collection
* expression
* @return predicate
*/
@Override
public > Predicate isMember(E elem, Expression collection){
return new CompoundExpressionImpl(metamodel, currentNode(collection).equal(elem), buildList(collection, internalLiteral(elem)), "isMember");
}
/**
* Create a predicate that tests whether an element is not a member of a
* collection.
*
* @param elem
* element
* @param collection
* expression
* @return predicate
*/
@Override
public > Predicate isNotMember(E elem, Expression collection){
return new CompoundExpressionImpl(metamodel, currentNode(collection).notEqual(elem), buildList(collection, internalLiteral(elem)), "isMember");
}
/**
* Create a predicate that tests whether an element is a member of a
* collection.
*
* @param elem
* element expression
* @param collection
* expression
* @return predicate
*/
@Override
public > Predicate isMember(Expression elem, Expression collection){
return new CompoundExpressionImpl(metamodel, currentNode(collection).equal(currentNode(elem)), buildList(collection, elem), "isMember");
}
/**
* Create a predicate that tests whether an element is not a member of a
* collection.
*
* @param elem
* element expression
* @param collection
* expression
* @return predicate
*/
@Override
public > Predicate isNotMember(Expression elem, Expression collection){
ReportQuery subQuery = new ReportQuery();
subQuery.setReferenceClass(((ExpressionImpl>)elem).getJavaType());
org.eclipse.persistence.expressions.ExpressionBuilder elemBuilder = new org.eclipse.persistence.expressions.ExpressionBuilder();
org.eclipse.persistence.expressions.Expression collectionExp =currentNode(collection);
org.eclipse.persistence.expressions.Expression elemExp =currentNode(elem);
subQuery.setExpressionBuilder(elemBuilder);
subQuery.setShouldRetrieveFirstPrimaryKey(true);
subQuery.setSelectionCriteria(elemBuilder.equal(collectionExp).and(collectionExp.equal(elemExp)));
return new CompoundExpressionImpl(metamodel, currentNode(elem).notExists(subQuery), buildList(elem, collection), "isNotMemeber");
}
// get the values and keys collections of the Map, which may then
// be passed to size(), isMember(), isEmpty(), etc
/**
* Create an expression that returns the values of a map.
*
* @return collection expression
*/
@Override
public > Expression> values(M map){
return internalLiteral(map.values());
}
/**
* Create an expression that returns the keys of a map.
*
* @return set expression
*/
@Override
public > Expression> keys(M map){
return internalLiteral(map.keySet());
}
// string functions:
/**
* Create a predicate for testing whether the expression satisfies the given
* pattern.
*
* @param x
* string expression
* @param pattern
* string expression
* @return like predicate
*/
@Override
public Predicate like(Expression x, Expression pattern){
return new CompoundExpressionImpl(this.metamodel,
currentNode(x).like(currentNode(pattern)), buildList(x, pattern), "like");
}
/**
* Create a predicate for testing whether the expression satisfies the given
* pattern.
*
* @param x
* string expression
* @param pattern
* string expression
* @param escapeChar
* escape character expression
* @return like predicate
*/
@Override
public Predicate like(Expression x, Expression pattern, Expression escapeChar){
return new CompoundExpressionImpl(this.metamodel,
currentNode(x).like(currentNode(pattern), currentNode(escapeChar)), buildList(x, pattern, escapeChar), "like");
}
/**
* Create a predicate for testing whether the expression satisfies the given
* pattern.
*
* @param x
* string expression
* @param pattern
* string expression
* @param escapeChar
* escape character
* @return like predicate
*/
@Override
public Predicate like(Expression x, Expression pattern, char escapeChar){
return this.like(x, pattern, this.internalLiteral(escapeChar));
}
/**
* Create a predicate for testing whether the expression satisfies the given
* pattern.
*
* @param x
* string expression
* @param pattern
* string
* @return like predicate
*/
@Override
public Predicate like(Expression x, String pattern){
return new CompoundExpressionImpl(this.metamodel, currentNode(x).like(pattern), buildList(x, internalLiteral(pattern)), "like");
}
/**
* Create a predicate for testing whether the expression satisfies the given
* pattern.
*
* @param x
* string expression
* @param pattern
* string
* @param escapeChar
* escape character expression
* @return like predicate
*/
@Override
public Predicate like(Expression x, String pattern, Expression escapeChar){
return this.like(x, this.internalLiteral(pattern), escapeChar);
}
/**
* Create a predicate for testing whether the expression satisfies the given
* pattern.
*
* @param x
* string expression
* @param pattern
* string
* @param escapeChar
* escape character
* @return like predicate
*/
@Override
public Predicate like(Expression x, String pattern, char escapeChar){
String escapeString = String.valueOf(escapeChar);
return new CompoundExpressionImpl(this.metamodel,
currentNode(x).like(pattern, escapeString), buildList(x, internalLiteral(pattern), internalLiteral(escapeChar)), "like");
}
/**
* Create a predicate for testing whether the expression does not satisfy
* the given pattern.
*
* @param x
* string expression
* @param pattern
* string expression
* @return like predicate
*/
@Override
public Predicate notLike(Expression x, Expression pattern){
return new CompoundExpressionImpl(this.metamodel,
currentNode(x).notLike(currentNode(pattern)), buildList(x, pattern), "notLike");
}
/**
* Create a predicate for testing whether the expression does not satisfy
* the given pattern.
*
* @param x
* string expression
* @param pattern
* string expression
* @param escapeChar
* escape character expression
* @return like predicate
*/
@Override
public Predicate notLike(Expression x, Expression pattern, Expression escapeChar){
return new CompoundExpressionImpl(this.metamodel,
currentNode(x).notLike(currentNode(pattern),
currentNode(escapeChar)), buildList(x, pattern, escapeChar), "like");
}
/**
* Create a predicate for testing whether the expression does not satisfy
* the given pattern.
*
* @param x
* string expression
* @param pattern
* string expression
* @param escapeChar
* escape character
* @return like predicate
*/
@Override
public Predicate notLike(Expression x, Expression pattern, char escapeChar){
return this.notLike(x, pattern, this.internalLiteral(escapeChar));
}
/**
* Create a predicate for testing whether the expression does not satisfy
* the given pattern.
*
* @param x
* string expression
* @param pattern
* string
* @return like predicate
*/
@Override
public Predicate notLike(Expression x, String pattern){
return new CompoundExpressionImpl(this.metamodel,
currentNode(x).notLike(pattern), buildList(x, internalLiteral(pattern)), "notLike");
}
/**
* Create a predicate for testing whether the expression does not satisfy
* the given pattern.
*
* @param x
* string expression
* @param pattern
* string
* @param escapeChar
* escape character expression
* @return like predicate
*/
@Override
public Predicate notLike(Expression x, String pattern, Expression escapeChar){
return this.notLike(x, this.internalLiteral(pattern), escapeChar);
}
/**
* Create a predicate for testing whether the expression does not satisfy
* the given pattern.
*
* @param x
* string expression
* @param pattern
* string
* @param escapeChar
* escape character
* @return like predicate
*/
@Override
public Predicate notLike(Expression x, String pattern, char escapeChar){
return this.notLike(x, this.internalLiteral(pattern), this.internalLiteral(escapeChar));
}
@Override
public Expression concat(List> expressions) {
switch(expressions != null ? expressions.size() : 0) {
case 0:
return literal("");
case 1:
return expressions.get(0);
case 2:
return concat(expressions.get(0), expressions.get(1));
default:
Expression expression = expressions.get(0);
for (int i = 1; i < expressions.size(); i++) {
expression = concat(expression, expressions.get(i));
}
return expression;
}
}
/**
* String concatenation operation.
*
* @param x
* string expression
* @param y
* string expression
* @return expression corresponding to concatenation
*/
@Override
public Expression concat(Expression x, Expression y){
org.eclipse.persistence.expressions.Expression xNode = currentNode(x);
org.eclipse.persistence.expressions.Expression yNode = currentNode(y);
if (xNode.isParameterExpression() && yNode.isParameterExpression()) {
//some database require the type when concatting two parameters.
((org.eclipse.persistence.internal.expressions.ParameterExpression)xNode).setType(ClassConstants.STRING);
}
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, xNode.concat(yNode), buildList(x, y), CONCAT);
}
/**
* String concatenation operation.
*
* @param x
* string expression
* @param y
* string
* @return expression corresponding to concatenation
*/
@Override
public Expression concat(Expression x, String y){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).concat(y), buildList(x, internalLiteral(y)), CONCAT);
}
/**
* String concatenation operation.
*
* @param x
* string
* @param y
* string expression
* @return expression corresponding to concatenation
*/
@Override
public Expression concat(String x, Expression y){
Expression literal = internalLiteral(x);
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(literal).concat(currentNode(y)), buildList(literal, y), CONCAT);
}
/**
* Substring extraction operation. Extracts a substring starting at
* specified position through to end of the string. First position is 1.
*
* @param x
* string expression
* @param from
* start position expression
* @return expression corresponding to substring extraction
*/
@Override
public Expression substring(Expression x, Expression from) {
return new FunctionExpressionImpl<>(metamodel, ClassConstants.STRING, currentNode( x).substring(currentNode( from)), buildList(x, from), "subString");
}
/**
* Substring extraction operation. Extracts a substring starting at
* specified position through to end of the string. First position is 1.
*
* @param x
* string expression
* @param from
* start position
* @return expression corresponding to substring extraction
*/
@Override
public Expression substring(Expression x, int from){
return substring(x, this.internalLiteral(from));
}
/**
* Substring extraction operation. Extracts a substring of given length
* starting at specified position. First position is 1.
*
* @param x
* string expression
* @param from
* start position expression
* @param len
* length expression
* @return expression corresponding to substring extraction
*/
@Override
public Expression substring(Expression x, Expression from, Expression len){
return new FunctionExpressionImpl<>(metamodel, ClassConstants.STRING, currentNode(x).substring(currentNode(from), currentNode(len)), buildList(x, from, len), "subString");
}
/**
* Substring extraction operation. Extracts a substring of given length
* starting at specified position. First position is 1.
*
* @param x
* string expression
* @param from
* start position
* @param len
* length
* @return expression corresponding to substring extraction
*/
@Override
public Expression substring(Expression x, int from, int len){
return new FunctionExpressionImpl<>(metamodel, ClassConstants.STRING, currentNode(x).substring(from, len), buildList(x, internalLiteral(from), internalLiteral(len)), "subString");
}
/**
* Create expression to trim blanks from both ends of a string.
*
* @param x
* expression for string to trim
* @return trim expression
*/
@Override
public Expression trim(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).trim(), buildList(x), "trim");
}
/**
* Create expression to trim blanks from a string.
*
* @param ts
* trim specification
* @param x
* expression for string to trim
* @return trim expression
*/
@Override
public Expression trim(Trimspec ts, Expression x){
if(ts == Trimspec.LEADING) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).leftTrim(), buildList(x), "leftTrim");
} else if(ts == Trimspec.TRAILING) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).rightTrim(), buildList(x), "rightTrim");
}
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).rightTrim().leftTrim(), buildList(x), "bothTrim");
}
/**
* Create expression to trim character from both ends of a string.
*
* @param t
* expression for character to be trimmed
* @param x
* expression for string to trim
* @return trim expression
*/
@Override
public Expression trim(Expression t, Expression x){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).trim(currentNode(t)), buildList(x, t), "trim");
}
/**
* Create expression to trim character from a string.
*
* @param ts
* trim specification
* @param t
* expression for character to be trimmed
* @param x
* expression for string to trim
* @return trim expression
*/
@Override
public Expression trim(Trimspec ts, Expression t, Expression x){
if(ts == Trimspec.LEADING) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING,
currentNode(x).leftTrim(currentNode(t)), buildList(x, t), "leftTrim");
} else if(ts == Trimspec.TRAILING) {
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING,
currentNode(x).rightTrim(currentNode(t)), buildList(x, t), "rightTrim");
}
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING,
currentNode(x).rightTrim(currentNode(t)).leftTrim(currentNode(t)), buildList(x, t), "bothTrim");
}
/**
* Create expression to trim character from both ends of a string.
*
* @param t
* character to be trimmed
* @param x
* expression for string to trim
* @return trim expression
*/
@Override
public Expression trim(char t, Expression x){
return trim(this.internalLiteral(t), x);
}
/**
* Create expression to trim character from a string.
*
* @param ts
* trim specification
* @param t
* character to be trimmed
* @param x
* expression for string to trim
* @return trim expression
*/
@Override
public Expression trim(Trimspec ts, char t, Expression x){
return trim(ts, this.internalLiteral(t), x);
}
/**
* Create expression for converting a string to lowercase.
*
* @param x
* string expression
* @return expression to convert to lowercase
*/
@Override
public Expression lower(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).toLowerCase(), buildList(x), "lower");
}
/**
* Create expression for converting a string to uppercase.
*
* @param x
* string expression
* @return expression to convert to uppercase
*/
@Override
public Expression upper(Expression x){
return new FunctionExpressionImpl<>(this.metamodel, ClassConstants.STRING, currentNode(x).toUpperCase(), buildList(x), "upper");
}
/**
* Create expression to return length of a string.
*
* @param x
* string expression
* @return length expression
*/
@Override
public Expression length(Expression x){
return new FunctionExpressionImpl<>(metamodel, ClassConstants.INTEGER, currentNode(x).length(), buildList(x), "length");
}
@Override
public Expression left(Expression expression, int len) {
return new FunctionExpressionImpl<>(
this.metamodel, ClassConstants.STRING,
currentNode(expression).left(len), buildList(expression), "left");
}
@Override
public Expression left(Expression expression, Expression len) {
return new FunctionExpressionImpl<>(
this.metamodel, ClassConstants.STRING,
currentNode(expression).left(currentNode(len)), buildList(expression), "left");
}
@Override
public Expression right(Expression expression, int len) {
return new FunctionExpressionImpl<>(
this.metamodel, ClassConstants.STRING,
currentNode(expression).right(len), buildList(expression), "right");
}
@Override
public Expression right(Expression