All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.internal.jpa.querydef.ExpressionImpl Maven / Gradle / Ivy

There is a newer version: 5.0.0-B05
Show newest version
/*
 * Copyright (c) 2011, 2023 Oracle and/or its affiliates. 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
//
package org.eclipse.persistence.internal.jpa.querydef;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.metamodel.Metamodel;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.expressions.ConstantExpression;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;

/**
 * 

* Purpose: Represents an Expression in the Criteria API heirarchy. *

* Description: Expressions are expression nodes that can not be joined from * and may or not be the result of a Path expression. * * @see jakarta.persistence.criteria Expression * * @author gyorke * @since EclipseLink 1.2 */ public class ExpressionImpl extends SelectionImpl implements Expression, InternalExpression{ protected Metamodel metamodel; protected boolean isLiteral; protected Object literal; // Non literal value protected ExpressionImpl(Metamodel metamodel, Class javaType, org.eclipse.persistence.expressions.Expression expressionNode){ super(javaType, expressionNode); this.metamodel = metamodel; } // Literal value public ExpressionImpl(Metamodel metamodel, Class javaType, org.eclipse.persistence.expressions.Expression expressionNode, Object value) { this(metamodel, javaType, expressionNode, value, true, null); } // Allows complete clone of the instance private ExpressionImpl( Metamodel metamodel, Class javaType, org.eclipse.persistence.expressions.Expression expressionNode, Object value, boolean isLiteral, String alias) { super(javaType, expressionNode, alias); this.metamodel = metamodel; this.literal = value; this.isLiteral = isLiteral; } @Override public Expression as(Class type) { // JPA spec: This shall return new instance according to spec, but historical code does only cast return buildExpressionForAs(type); } @Override public Expression cast(Class type) { // JPA spec: New instance with provided Java type return new ExpressionImpl<>(metamodel, type, currentNode, literal, isLiteral, alias); } @SuppressWarnings("unchecked") protected Expression buildExpressionForAs(Class type) { return (Expression) this; } @Override public Predicate equalTo(Expression value) { return new CompoundExpressionImpl( this.metamodel, this.currentNode.equal(currentNode(value)), List.of(this, value), "equals"); } @Override public Predicate equalTo(Object value) { return new CompoundExpressionImpl( this.metamodel, this.currentNode.equal(value), List.of(this, createLiteral(value, metamodel)), "equals"); } @Override public Predicate notEqualTo(Expression value) { return new CompoundExpressionImpl( this.metamodel, this.currentNode.notEqual(currentNode(value)), List.of(this, value), "not equal"); } @Override public Predicate notEqualTo(Object value) { return new CompoundExpressionImpl( this.metamodel, this.currentNode.notEqual(value), List.of(this, createLiteral(value, metamodel)), "not equal"); } @Override public Predicate in(Object... values) { List> list = new ArrayList<>(); list.add(this); return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(values), list, "in"); } /** * Apply a predicate to test whether the expression is a member * of the argument list. * @return predicate testing for membership */ @Override @SuppressWarnings("unchecked") // (Expression>), values prototype in JPA is too common public Predicate in(Expression... values) { if (values != null) { if (values.length == 1 && ((InternalExpression) values[0]).isParameter() && Collection.class.isAssignableFrom(((ParameterExpressionImpl) values[0]).getJavaType())) { // bug 349477 - Collection from Expression was lost during compilation // and if we know that Collection is there we should help the runtime // and route the execution to the right method return in((Expression>) values[0]); } List> list = new ArrayList<>(); list.add(this); if (values.length == 1 && ((InternalExpression) values[0]).isSubquery()) { list.add(values[0]); return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(((SubQueryImpl) values[0]).subQuery), list, "in"); } else { List inValues = new ArrayList<>(); for (Expression exp : values) { if (!((InternalExpression) exp).isLiteral() && !((InternalExpression) exp).isParameter()) { Object[] params = new Object[]{exp}; throw new IllegalArgumentException(ExceptionLocalization.buildMessage("CRITERIA_NON_LITERAL_PASSED_TO_IN",params)); } else { list.add(exp); inValues.add(((InternalSelection)exp).getCurrentNode()); } } return new CompoundExpressionImpl(this.metamodel, this.currentNode.in(inValues), list, "in"); } } throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NULL_PASSED_TO_EXPRESSION_IN")); } /** * Apply a predicate to test whether the expression is a member * of the collection. * @param values collection * @return predicate testing for membership */ @Override public Predicate in(Collection values) { List> list = new ArrayList<>(); list.add(this); return new InImpl<>(this.metamodel, this, values, list); } /** * Apply a predicate to test whether the expression is a member * of the collection. * @param values expression corresponding to collection * @return predicate testing for membership */ @Override public Predicate in(Expression> values) { List> list = new ArrayList<>(); list.add(values); list.add(this); return new InImpl<>(metamodel, this, (ExpressionImpl)values, list); } @Override public Predicate isNotNull() { List> list = new ArrayList<>(); list.add(this); return new CompoundExpressionImpl(this.metamodel, this.currentNode.notNull(), list, "not null"); } @Override public Predicate isNull() { List> list = new ArrayList<>(); list.add(this); return new CompoundExpressionImpl(this.metamodel, this.currentNode.isNull(), list, "is null"); } @Override public boolean isPredicate(){ return false; } @Override public boolean isSubquery(){ return false; } @Override public boolean isCompoundExpression(){ return false; } @Override public boolean isExpression(){ return true; } @Override public boolean isJunction(){ return false; } @Override public boolean isLiteral(){ return this.isLiteral; } @Override public boolean isParameter(){ return false; } @Override public void findRootAndParameters(CommonAbstractCriteriaImpl criteriaQuery){ //no-op because an expression will have no root } // Literal Expression factory method static Expression createLiteral(T value, Metamodel metamodel, Class resultClass) { return new ExpressionImpl<>( metamodel, resultClass, new ConstantExpression(value, new ExpressionBuilder()), value); } // Literal Expression factory method @SuppressWarnings("unchecked") static Expression createLiteral(T value, Metamodel metamodel) { return createLiteral(value, metamodel, value == null ? null : (Class) value.getClass()); } // Shortcut to return current expression node static org.eclipse.persistence.expressions.Expression currentNode(Expression expression) { return ((InternalSelection)expression).getCurrentNode(); } }