/* * Copyright 2014 - 2017 Blazebit. * * Licensed 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 com.blazebit.persistence.impl.builder.predicate; import com.blazebit.persistence.CaseWhenAndThenBuilder; import com.blazebit.persistence.CaseWhenBuilder; import com.blazebit.persistence.CaseWhenOrThenBuilder; import com.blazebit.persistence.CaseWhenThenBuilder; import com.blazebit.persistence.FullQueryBuilder; import com.blazebit.persistence.LeafOngoingFinalSetOperationSubqueryBuilder; import com.blazebit.persistence.MultipleSubqueryInitiator; import com.blazebit.persistence.QuantifiableBinaryPredicateBuilder; import com.blazebit.persistence.RestrictionBuilder; import com.blazebit.persistence.SimpleCaseWhenBuilder; import com.blazebit.persistence.StartOngoingSetOperationSubqueryBuilder; import com.blazebit.persistence.SubqueryBuilder; import com.blazebit.persistence.SubqueryInitiator; import com.blazebit.persistence.impl.ClauseType; import com.blazebit.persistence.impl.MultipleSubqueryInitiatorImpl; import com.blazebit.persistence.impl.ParameterManager; import com.blazebit.persistence.impl.SubqueryAndExpressionBuilderListener; import com.blazebit.persistence.impl.SubqueryInitiatorFactory; import com.blazebit.persistence.impl.SubqueryInternalBuilder; import com.blazebit.persistence.impl.builder.expression.CaseWhenBuilderImpl; import com.blazebit.persistence.impl.builder.expression.ExpressionBuilder; import com.blazebit.persistence.impl.builder.expression.ExpressionBuilderEndedListener; import com.blazebit.persistence.impl.builder.expression.SimpleCaseWhenBuilderImpl; import com.blazebit.persistence.impl.expression.Expression; import com.blazebit.persistence.impl.expression.ExpressionFactory; import com.blazebit.persistence.impl.expression.SubqueryExpression; import com.blazebit.persistence.impl.predicate.BinaryExpressionPredicate; import com.blazebit.persistence.impl.predicate.Predicate; import com.blazebit.persistence.impl.predicate.PredicateBuilder; import com.blazebit.persistence.impl.predicate.PredicateQuantifier; import com.blazebit.persistence.impl.predicate.QuantifiableBinaryExpressionPredicate; import java.util.Collection; /** * * @author Christian Beikov * @author Moritz Becker * @since 1.0 */ public abstract class AbstractQuantifiablePredicateBuilder<T> extends SubqueryAndExpressionBuilderListener<T> implements QuantifiableBinaryPredicateBuilder<T>, PredicateBuilder { protected final Expression leftExpression; protected final SubqueryInitiatorFactory subqueryInitFactory; protected final ExpressionFactory expressionFactory; private final T result; private final PredicateBuilderEndedListener listener; private final boolean wrapNot; private Predicate predicate; private final ParameterManager parameterManager; private final ClauseType clauseType; private SubqueryInitiator<T> subqueryInitiator; public AbstractQuantifiablePredicateBuilder(T result, PredicateBuilderEndedListener listener, Expression leftExpression, boolean wrapNot, SubqueryInitiatorFactory subqueryInitFactory, ExpressionFactory expressionFactory, ParameterManager parameterManager, ClauseType clauseType) { this.result = result; this.listener = listener; this.wrapNot = wrapNot; this.leftExpression = leftExpression; this.subqueryInitFactory = subqueryInitFactory; this.expressionFactory = expressionFactory; this.parameterManager = parameterManager; this.clauseType = clauseType; } protected abstract QuantifiableBinaryExpressionPredicate createPredicate(Expression left, Expression right, PredicateQuantifier quantifier); protected T chain(Predicate predicate) { verifyBuilderEnded(); if (wrapNot) { predicate.negate(); } this.predicate = predicate; listener.onBuilderEnded(this); return result; } protected void chainSubbuilder(Predicate predicate) { verifyBuilderEnded(); if (wrapNot) { predicate.negate(); } this.predicate = predicate; } @Override public T value(Object value) { return chain(createPredicate(leftExpression, parameterManager.addParameterExpression(value, clauseType), PredicateQuantifier.ONE)); } @Override public T expression(String expression) { return chain(createPredicate(leftExpression, expressionFactory.createSimpleExpression(expression, false), PredicateQuantifier.ONE)); } @Override public MultipleSubqueryInitiator<T> subqueries(String expression) { return new MultipleSubqueryInitiatorImpl<T>(result, expressionFactory.createSimpleExpression(expression, true), new ExpressionBuilderEndedListener() { @Override public void onBuilderEnded(ExpressionBuilder builder) { chain(createPredicate(leftExpression, builder.getExpression(), PredicateQuantifier.ONE)); } }, subqueryInitFactory); } /* case when functions */ @Override public RestrictionBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>> caseWhen(String expression) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).when(expression); } @Override public CaseWhenAndThenBuilder<CaseWhenBuilder<T>> caseWhenAnd() { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenAnd(); } @Override public SubqueryInitiator<CaseWhenThenBuilder<CaseWhenBuilder<T>>> caseWhenExists() { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenExists(); } @Override public SubqueryInitiator<CaseWhenThenBuilder<CaseWhenBuilder<T>>> caseWhenNotExists() { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenNotExists(); } @Override public SubqueryBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>> caseWhenExists(FullQueryBuilder<?, ?> criteriaBuilder) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenExists(criteriaBuilder); } @Override public SubqueryBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>> caseWhenNotExists(FullQueryBuilder<?, ?> criteriaBuilder) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenNotExists(criteriaBuilder); } @Override public SubqueryInitiator<RestrictionBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>>> caseWhenSubquery() { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenSubquery(); } @Override public SubqueryInitiator<RestrictionBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>>> caseWhenSubquery(String subqueryAlias, String expression) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenSubquery(subqueryAlias, expression); } @Override public MultipleSubqueryInitiator<RestrictionBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>>> caseWhenSubqueries(String expression) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenSubqueries(expression); } @Override public SubqueryBuilder<RestrictionBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>>> caseWhenSubquery(FullQueryBuilder<?, ?> criteriaBuilder) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenSubquery(criteriaBuilder); } @Override public SubqueryBuilder<RestrictionBuilder<CaseWhenThenBuilder<CaseWhenBuilder<T>>>> caseWhenSubquery(String subqueryAlias, String expression, FullQueryBuilder<?, ?> criteriaBuilder) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenSubquery(subqueryAlias, expression, criteriaBuilder); } @Override public CaseWhenOrThenBuilder<CaseWhenBuilder<T>> caseWhenOr() { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new CaseWhenBuilderImpl<T>(result, this, subqueryInitFactory, expressionFactory, parameterManager, clauseType)).whenOr(); } @Override public SimpleCaseWhenBuilder<T> simpleCase(String caseOperand) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return startBuilder(new SimpleCaseWhenBuilderImpl<T>(result, this, expressionFactory, expressionFactory.createCaseOperandExpression(caseOperand))); } /* quantification functions */ @Override public SubqueryInitiator<T> all() { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ALL)); return subqueryInitFactory.createSubqueryInitiator(result, this, false); } @Override public SubqueryInitiator<T> any() { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ANY)); return subqueryInitFactory.createSubqueryInitiator(result, this, false); } @Override public SubqueryBuilder<T> all(FullQueryBuilder<?, ?> criteriaBuilder) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ALL)); return subqueryInitFactory.createSubqueryBuilder(result, this, false, criteriaBuilder); } @Override public SubqueryBuilder<T> any(FullQueryBuilder<?, ?> criteriaBuilder) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ANY)); return subqueryInitFactory.createSubqueryBuilder(result, this, false, criteriaBuilder); } public SubqueryBuilder<T> one(FullQueryBuilder<?, ?> criteriaBuilder) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return subqueryInitFactory.createSubqueryBuilder(result, this, false, criteriaBuilder); } @Override public SubqueryBuilder<T> from(Class<?> clazz) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().from(clazz); } @Override public SubqueryBuilder<T> from(Class<?> clazz, String alias) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().from(clazz, alias); } @Override public SubqueryBuilder<T> from(String correlationPath) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().from(correlationPath); } @Override public SubqueryBuilder<T> from(String correlationPath, String alias) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().from(correlationPath, alias); } @Override public StartOngoingSetOperationSubqueryBuilder<T, LeafOngoingFinalSetOperationSubqueryBuilder<T>> startSet() { return getSubqueryInitiator().startSet(); } @Override public SubqueryBuilder<T> fromOld(Class<?> entityClass) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromOld(entityClass); } @Override public SubqueryBuilder<T> fromOld(Class<?> entityClass, String alias) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromOld(entityClass, alias); } @Override public SubqueryBuilder<T> fromNew(Class<?> entityClass) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromNew(entityClass); } @Override public SubqueryBuilder<T> fromNew(Class<?> entityClass, String alias) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromNew(entityClass, alias); } @Override public SubqueryBuilder<T> fromValues(Class<?> valueClass, String alias, int valueCount) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromValues(valueClass, alias, valueCount); } @Override public SubqueryBuilder<T> fromIdentifiableValues(Class<?> valueClass, String alias, int valueCount) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromIdentifiableValues(valueClass, alias, valueCount); } @Override public <X> SubqueryBuilder<T> fromValues(Class<X> valueClass, String alias, Collection<X> values) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromValues(valueClass, alias, values); } @Override public <X> SubqueryBuilder<T> fromIdentifiableValues(Class<X> valueClass, String alias, Collection<X> values) { chainSubbuilder(createPredicate(leftExpression, null, PredicateQuantifier.ONE)); return getSubqueryInitiator().fromIdentifiableValues(valueClass, alias, values); } @Override public void onBuilderEnded(SubqueryInternalBuilder<T> builder) { super.onBuilderEnded(builder); // set the finished subquery builder on the previously created predicate if (predicate instanceof BinaryExpressionPredicate) { ((BinaryExpressionPredicate) predicate).setRight(new SubqueryExpression(builder)); } else { throw new IllegalStateException("SubqueryBuilder ended but predicate type was unexpected"); } listener.onBuilderEnded(this); } @Override public Predicate getPredicate() { return predicate; } protected SubqueryInitiator<T> getSubqueryInitiator() { if (subqueryInitiator == null) { subqueryInitiator = subqueryInitFactory.createSubqueryInitiator(result, this, false); } return subqueryInitiator; } @Override public void onBuilderEnded(ExpressionBuilder builder) { super.onBuilderEnded(builder); if (predicate instanceof BinaryExpressionPredicate) { ((BinaryExpressionPredicate) predicate).setRight(builder.getExpression()); } else { throw new IllegalStateException("ExpressionBuilder ended but predicate type was unexpected"); } listener.onBuilderEnded(AbstractQuantifiablePredicateBuilder.this); } }