| /* |
| * Copyright (c) 2011, 2021 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: |
| // Oracle - initial API and implementation |
| // |
| package org.eclipse.persistence.jpa.jpql.tools.model; |
| |
| import java.util.Collections; |
| import java.util.List; |
| import org.eclipse.persistence.jpa.jpql.ExpressionTools; |
| import org.eclipse.persistence.jpa.jpql.parser.TrimExpression.Specification; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.AllOrAnyExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.AndExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.BetweenExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.CollectionMemberExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.ComparisonExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.EmptyCollectionComparisonExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.ExistsExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.InExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.KeywordExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.LikeExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.LowerExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.NullComparisonExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.OrExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.SimpleSelectStatementStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.StateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.SubExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.SubstringExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.TrimExpressionStateObject; |
| import org.eclipse.persistence.jpa.jpql.tools.model.query.UpperExpressionStateObject; |
| import static org.eclipse.persistence.jpa.jpql.parser.Expression.*; |
| |
| /** |
| * The abstract implementation of {@link IConditionalExpressionStateObjectBuilder} that supports the |
| * creation of the conditional expression based on the JPQL grammar defined in JPA 2.0. |
| * |
| * @version 2.4 |
| * @since 2.4 |
| * @author Pascal Filion |
| */ |
| @SuppressWarnings("unchecked") |
| public abstract class AbstractConditionalExpressionStateObjectBuilder<T extends IAbstractConditionalExpressionStateObjectBuilder<T>> |
| extends AbstractScalarExpressionStateObjectBuilder<T> |
| implements IAbstractConditionalExpressionStateObjectBuilder<T> { |
| |
| /** |
| * Creates a new <code>AbstractStateObjectBuilder</code>. |
| * |
| * @param parent The parent of the expression to build, which is only required when a JPQL |
| * fragment needs to be parsed |
| */ |
| public AbstractConditionalExpressionStateObjectBuilder(StateObject parent) { |
| super(parent); |
| } |
| |
| @Override |
| public T all(SimpleSelectStatementStateObject subquery) { |
| allOrAny(ALL, subquery); |
| return (T) this; |
| } |
| |
| protected void allOrAny(String identifier, SimpleSelectStatementStateObject subquery) { |
| StateObject stateObject = new AllOrAnyExpressionStateObject(getParent(), identifier, subquery); |
| add(stateObject); |
| } |
| |
| @Override |
| public T and(T builder) { |
| |
| checkBuilder(builder); |
| |
| StateObject rightStateObject = pop(); |
| StateObject leftStateObject = pop(); |
| |
| StateObject stateObject = new AndExpressionStateObject( |
| getParent(), |
| leftStateObject, |
| rightStateObject |
| ); |
| |
| add(stateObject); |
| return (T) this; |
| } |
| |
| @Override |
| public T any(SimpleSelectStatementStateObject subquery) { |
| allOrAny(ANY, subquery); |
| return (T) this; |
| } |
| |
| protected void between(boolean not) { |
| |
| StateObject upperBoundStateObject = pop(); |
| StateObject lowerBoundStateObject = pop(); |
| StateObject firstStateObject = pop(); |
| |
| StateObject stateObject = new BetweenExpressionStateObject( |
| getParent(), |
| firstStateObject, |
| not, |
| lowerBoundStateObject, |
| upperBoundStateObject |
| ); |
| |
| add(stateObject); |
| } |
| |
| @Override |
| public T between(T lowerBoundExpression, T upperBoundExpression) { |
| checkBuilders(lowerBoundExpression, upperBoundExpression); |
| between(false); |
| return (T) this; |
| } |
| |
| @Override |
| public T collectionPath(String path) { |
| StateObject stateObject = buildCollectionPath(path); |
| add(stateObject); |
| return (T) this; |
| } |
| |
| protected void comparison(String identifier) { |
| comparison(identifier, pop()); |
| } |
| |
| protected void comparison(String identifier, StateObject rightStateObject) { |
| |
| StateObject leftStateObject = pop(); |
| |
| StateObject stateObject = new ComparisonExpressionStateObject( |
| getParent(), |
| leftStateObject, |
| identifier, |
| rightStateObject |
| ); |
| |
| add(stateObject); |
| } |
| |
| @Override |
| public T different(Number number) { |
| comparison(DIFFERENT, buildNumeric(number)); |
| return (T) this; |
| } |
| |
| @Override |
| public T different(String literal) { |
| comparison(DIFFERENT, literal(literal)); |
| return (T) this; |
| } |
| |
| @Override |
| public T different(T builder) { |
| checkBuilder(builder); |
| comparison(DIFFERENT); |
| return (T) this; |
| } |
| |
| @Override |
| public T equal(Number number) { |
| comparison(EQUAL, buildNumeric(number)); |
| return (T) this; |
| } |
| |
| @Override |
| public T equal(String literal) { |
| comparison(EQUAL, literal(literal)); |
| return (T) this; |
| } |
| |
| @Override |
| public T equal(T builder) { |
| checkBuilder(builder); |
| comparison(EQUAL); |
| return (T) this; |
| } |
| |
| protected void exists(boolean not, SimpleSelectStatementStateObject subquery) { |
| StateObject stateObject = new ExistsExpressionStateObject(getParent(), not, subquery); |
| add(stateObject); |
| } |
| |
| @Override |
| public T exists(SimpleSelectStatementStateObject subquery) { |
| exists(false, subquery); |
| return (T) this; |
| } |
| |
| @Override |
| public T FALSE() { |
| keyword(FALSE); |
| return (T) this; |
| } |
| |
| @Override |
| public T greaterThan(Number number) { |
| comparison(GREATER_THAN, buildNumeric(number)); |
| return (T) this; |
| } |
| |
| @Override |
| public T greaterThan(String literal) { |
| comparison(GREATER_THAN, literal(literal)); |
| return (T) this; |
| } |
| |
| @Override |
| public T greaterThan(T builder) { |
| checkBuilder(builder); |
| comparison(GREATER_THAN); |
| return (T) this; |
| } |
| |
| @Override |
| public T greaterThanOrEqual(Number number) { |
| comparison(GREATER_THAN_OR_EQUAL, buildNumeric(number)); |
| return (T) this; |
| } |
| |
| @Override |
| public T greaterThanOrEqual(String literal) { |
| comparison(GREATER_THAN_OR_EQUAL, literal(literal)); |
| return (T) this; |
| } |
| |
| @Override |
| public T greaterThanOrEqual(T builder) { |
| checkBuilder(builder); |
| comparison(GREATER_THAN_OR_EQUAL); |
| return (T) this; |
| } |
| |
| protected void in(boolean not, List<StateObject> inItems) { |
| |
| StateObject stateFieldPath = pop(); |
| |
| StateObject stateObject = new InExpressionStateObject( |
| getParent(), |
| stateFieldPath, |
| not, |
| inItems |
| ); |
| |
| add(stateObject); |
| } |
| |
| protected void in(boolean not, String... inItems) { |
| in(not, literals(inItems)); |
| } |
| |
| protected void in(boolean not, T... inItems) { |
| in(false, stateObjects(inItems)); |
| } |
| |
| @Override |
| public T in(SimpleSelectStatementStateObject subquery) { |
| in(false, Collections.<StateObject>singletonList(subquery)); |
| return (T) this; |
| } |
| |
| @Override |
| public T in(String... inItems) { |
| in(false, inItems); |
| return (T) this; |
| } |
| |
| @Override |
| public T in(T builder) { |
| checkBuilders(builder); |
| in(false, builder); |
| return (T) this; |
| } |
| |
| @Override |
| public T in(T builder1, T builder2) { |
| checkBuilders(builder1, builder2); |
| in(false, builder1, builder2); |
| return (T) this; |
| } |
| |
| protected void isEmpty(boolean not, String path) { |
| |
| StateObject stateObject = new EmptyCollectionComparisonExpressionStateObject( |
| getParent(), |
| not, |
| path |
| ); |
| |
| add(stateObject); |
| } |
| |
| @Override |
| public T isEmpty(String path) { |
| isEmpty(false, path); |
| return (T) this; |
| } |
| |
| @Override |
| public T isNotEmpty(String path) { |
| isEmpty(true, path); |
| return (T) this; |
| } |
| |
| @Override |
| public T isNotNull(String path) { |
| isNull(true, path); |
| return (T) this; |
| } |
| |
| protected void isNull(boolean not, String path) { |
| |
| StateObject stateObject; |
| |
| if (ExpressionTools.isParameter(path.charAt(0))) { |
| stateObject = buildInputParameter(path); |
| } |
| else { |
| stateObject = buildStateFieldPath(path); |
| } |
| |
| stateObject = new NullComparisonExpressionStateObject( |
| getParent(), |
| not, |
| stateObject |
| ); |
| |
| add(stateObject); |
| } |
| |
| @Override |
| public T isNull(String path) { |
| isNull(false, path); |
| return (T) this; |
| } |
| |
| protected void keyword(String identifier) { |
| StateObject stateObject = new KeywordExpressionStateObject(getParent(), identifier); |
| add(stateObject); |
| } |
| |
| protected void like(boolean not, String escapeCharacter) { |
| |
| StateObject patternValue = pop(); |
| StateObject string = pop(); |
| |
| StateObject stateObject = new LikeExpressionStateObject( |
| getParent(), |
| string, |
| not, |
| patternValue, |
| escapeCharacter |
| ); |
| |
| add(stateObject); |
| } |
| |
| @Override |
| public T like(String patternValue) { |
| like(string(patternValue)); |
| return (T) this; |
| } |
| |
| @Override |
| public T like(T patternValue) { |
| checkBuilder(patternValue); |
| like(false, null); |
| return (T) this; |
| } |
| |
| @Override |
| public T like(T patternValue, String escapeCharacter) { |
| checkBuilder(patternValue); |
| like(false, escapeCharacter); |
| return (T) this; |
| } |
| |
| @Override |
| public T lower(T builder) { |
| checkBuilder(builder); |
| StateObject stateObject = new LowerExpressionStateObject(getParent(), pop()); |
| add(stateObject); |
| return (T) this; |
| } |
| |
| @Override |
| public T lowerThan(Number number) { |
| comparison(LOWER_THAN, buildNumeric(number)); |
| return (T) this; |
| } |
| |
| @Override |
| public T lowerThan(String literal) { |
| comparison(LOWER_THAN, literal(literal)); |
| return (T) this; |
| } |
| |
| @Override |
| public T lowerThan(T builder) { |
| checkBuilder(builder); |
| comparison(LOWER_THAN); |
| return (T) this; |
| } |
| |
| @Override |
| public T lowerThanOrEqual(Number number) { |
| comparison(LOWER_THAN_OR_EQUAL, buildNumeric(number)); |
| return (T) this; |
| } |
| |
| @Override |
| public T lowerThanOrEqual(String literal) { |
| comparison(LOWER_THAN_OR_EQUAL, literal(literal)); |
| return (T) this; |
| } |
| |
| @Override |
| public T lowerThanOrEqual(T builder) { |
| checkBuilder(builder); |
| comparison(LOWER_THAN_OR_EQUAL); |
| return (T) this; |
| } |
| |
| protected void member(boolean not, boolean of, String collectionValuedPathExpression) { |
| |
| StateObject entity = pop(); |
| |
| StateObject stateObject = new CollectionMemberExpressionStateObject( |
| getParent(), |
| entity, |
| not, |
| of, |
| collectionValuedPathExpression |
| ); |
| |
| add(stateObject); |
| } |
| |
| @Override |
| public T member(String path) { |
| member(false, false, path); |
| return (T) this; |
| } |
| |
| @Override |
| public T memberOf(String path) { |
| member(false, true, path); |
| return (T) this; |
| } |
| |
| @Override |
| public T notBetween(T lowerBoundExpression, T upperBoundExpression) { |
| checkBuilders(lowerBoundExpression, upperBoundExpression); |
| between(true); |
| return (T) this; |
| } |
| |
| @Override |
| public T notExists(SimpleSelectStatementStateObject subquery) { |
| exists(true, subquery); |
| return (T) this; |
| } |
| |
| @Override |
| public T notIn(SimpleSelectStatementStateObject subquery) { |
| in(true, Collections.<StateObject>singletonList(subquery)); |
| return (T) this; |
| } |
| |
| @Override |
| public T notIn(String... inItems) { |
| in(true, inItems); |
| return (T) this; |
| } |
| |
| @Override |
| public T notIn(T builder) { |
| checkBuilders(builder); |
| in(true, builder); |
| return (T) this; |
| } |
| |
| @Override |
| public T notIn(T builder1, T builder2) { |
| checkBuilders(builder1, builder2); |
| in(true, builder1, builder2); |
| return (T) this; |
| } |
| |
| @Override |
| public T notLike(String patternValue) { |
| notLike(string(patternValue)); |
| return (T) this; |
| } |
| |
| @Override |
| public T notLike(T builder) { |
| checkBuilder(builder); |
| like(true, null); |
| return (T) this; |
| } |
| |
| @Override |
| public T notLike(T builder, String escapeCharacter) { |
| checkBuilder(builder); |
| like(true, escapeCharacter); |
| return (T) this; |
| } |
| |
| @Override |
| public T notMember(String path) { |
| member(true, false, path); |
| return (T) this; |
| } |
| |
| @Override |
| public T notMemberOf(String path) { |
| member(true, true, path); |
| return (T) this; |
| } |
| |
| @Override |
| public T NULL() { |
| keyword(NULL); |
| return (T) this; |
| } |
| |
| @Override |
| public T or(T builder) { |
| |
| checkBuilder(builder); |
| |
| StateObject rightStateObject = pop(); |
| StateObject leftStateObject = pop(); |
| |
| StateObject stateObject = new OrExpressionStateObject( |
| getParent(), |
| leftStateObject, |
| rightStateObject |
| ); |
| |
| add(stateObject); |
| return (T) this; |
| } |
| |
| @Override |
| public T some(SimpleSelectStatementStateObject subquery) { |
| allOrAny(SOME, subquery); |
| return (T) this; |
| } |
| |
| @Override |
| public T sub(StateObject stateObject) { |
| stateObject = new SubExpressionStateObject(getParent(), stateObject); |
| add(stateObject); |
| return (T) this; |
| } |
| |
| @Override |
| public T substring(T parameter1, T parameter2, T parameter3) { |
| |
| checkBuilders(parameter1, parameter2, parameter3); |
| |
| StateObject thirdStateObject = pop(); |
| StateObject secondStateObject = pop(); |
| StateObject firstStateObject = pop(); |
| |
| StateObject stateObject = new SubstringExpressionStateObject( |
| getParent(), |
| firstStateObject, |
| secondStateObject, |
| thirdStateObject |
| ); |
| |
| add(stateObject); |
| return (T) this; |
| } |
| |
| @Override |
| public T trim(Specification specification, String trimCharacter, T builder) { |
| |
| checkBuilder(builder); |
| StateObject stateObject = pop(); |
| |
| stateObject = new TrimExpressionStateObject( |
| getParent(), |
| specification, |
| ExpressionTools.stringIsNotEmpty(trimCharacter) ? literal(trimCharacter) : null, |
| stateObject |
| ); |
| |
| add(stateObject); |
| return (T) this; |
| } |
| |
| @Override |
| public T trim(Specification specification, T builder) { |
| return trim(specification, null, builder); |
| } |
| |
| @Override |
| public T TRUE() { |
| keyword(TRUE); |
| return (T) this; |
| } |
| |
| @Override |
| public T upper(T builder) { |
| checkBuilder(builder); |
| StateObject stateObject = new UpperExpressionStateObject(getParent(), pop()); |
| add(stateObject); |
| return (T) this; |
| } |
| |
| @Override |
| public T variable(String variable) { |
| StateObject stateObject = buildIdentificationVariable(variable); |
| add(stateObject); |
| return (T) this; |
| } |
| } |