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

com.blazebit.persistence.impl.builder.predicate.RestrictionBuilderImpl Maven / Gradle / Ivy

There is a newer version: 1.6.11
Show newest version
/*
 * Copyright 2014 - 2020 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.BetweenBuilder;
import com.blazebit.persistence.FullQueryBuilder;
import com.blazebit.persistence.LikeBuilder;
import com.blazebit.persistence.MultipleSubqueryInitiator;
import com.blazebit.persistence.QuantifiableBinaryPredicateBuilder;
import com.blazebit.persistence.SubqueryBuilder;
import com.blazebit.persistence.SubqueryInitiator;
import com.blazebit.persistence.impl.ClauseType;
import com.blazebit.persistence.impl.ExpressionUtils;
import com.blazebit.persistence.impl.MultipleSubqueryInitiatorImpl;
import com.blazebit.persistence.impl.ParameterManager;
import com.blazebit.persistence.impl.PredicateAndSubqueryBuilderEndedListener;
import com.blazebit.persistence.impl.SubqueryBuilderListener;
import com.blazebit.persistence.impl.SubqueryBuilderListenerImpl;
import com.blazebit.persistence.impl.SubqueryInitiatorFactory;
import com.blazebit.persistence.impl.SubqueryInternalBuilder;
import com.blazebit.persistence.impl.builder.expression.ExpressionBuilder;
import com.blazebit.persistence.impl.builder.expression.ExpressionBuilderEndedListener;
import com.blazebit.persistence.impl.builder.expression.SuperExpressionSubqueryBuilderListener;
import com.blazebit.persistence.internal.RestrictionBuilderExperimental;
import com.blazebit.persistence.parser.expression.Expression;
import com.blazebit.persistence.parser.expression.ExpressionFactory;
import com.blazebit.persistence.parser.expression.ParameterExpression;
import com.blazebit.persistence.parser.expression.PathExpression;
import com.blazebit.persistence.parser.expression.SubqueryExpression;
import com.blazebit.persistence.parser.expression.SyntaxErrorException;
import com.blazebit.persistence.parser.predicate.BinaryExpressionPredicate;
import com.blazebit.persistence.parser.predicate.EqPredicate;
import com.blazebit.persistence.parser.predicate.GePredicate;
import com.blazebit.persistence.parser.predicate.GtPredicate;
import com.blazebit.persistence.parser.predicate.InPredicate;
import com.blazebit.persistence.parser.predicate.IsEmptyPredicate;
import com.blazebit.persistence.parser.predicate.IsNullPredicate;
import com.blazebit.persistence.parser.predicate.LePredicate;
import com.blazebit.persistence.parser.predicate.LtPredicate;
import com.blazebit.persistence.parser.predicate.MemberOfPredicate;
import com.blazebit.persistence.parser.predicate.Predicate;
import com.blazebit.persistence.parser.predicate.PredicateBuilder;
import com.blazebit.persistence.parser.predicate.PredicateQuantifier;
import com.blazebit.persistence.parser.util.TypeUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 *
 * @author Christian Beikov
 * @author Moritz Becker
 * @since 1.0.0
 */
public class RestrictionBuilderImpl extends PredicateAndSubqueryBuilderEndedListener implements RestrictionBuilderExperimental, LeftHandsideSubqueryPredicateBuilder {

    private final T result;
    private final PredicateBuilderEndedListener listener;
    private Expression leftExpression;
    private final SubqueryInitiatorFactory subqueryInitFactory;
    private Predicate predicate;
    private final ExpressionFactory expressionFactory;
    private final ParameterManager parameterManager;
    private final ClauseType clause;
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private final SubqueryBuilderListenerImpl> betweenStartSubqueryBuilderListener = new LeftHandsideSubqueryPredicateBuilderListener();
    private SubqueryBuilderListenerImpl rightSuperExprSubqueryBuilderListener;
    private SubqueryBuilderListenerImpl> leftSuperExprSubqueryPredicateBuilderListener;
    private SuperExpressionRightHandsideSubqueryPredicateBuilder rightSuperExprSubqueryPredicateBuilderListener;

    public RestrictionBuilderImpl(T result, PredicateBuilderEndedListener listener, Expression leftExpression, SubqueryInitiatorFactory subqueryInitFactory, ExpressionFactory expressionFactory, ParameterManager parameterManager, ClauseType clause) {
        this.leftExpression = leftExpression;
        this.listener = listener;
        this.result = result;
        this.subqueryInitFactory = subqueryInitFactory;
        this.expressionFactory = expressionFactory;
        this.parameterManager = parameterManager;
        this.clause = clause;
    }

    public RestrictionBuilderImpl(T result, PredicateBuilderEndedListener listener, SubqueryInitiatorFactory subqueryInitFactory, ExpressionFactory expressionFactory, ParameterManager parameterManager, ClauseType clause) {
        this.listener = listener;
        this.result = result;
        this.subqueryInitFactory = subqueryInitFactory;
        this.expressionFactory = expressionFactory;
        this.parameterManager = parameterManager;
        this.clause = clause;
    }

    @Override
    public void setLeftExpression(Expression leftExpression) {
        this.leftExpression = leftExpression;
    }

    private T chain(Predicate predicate) {
        verifyBuilderEnded();
        this.predicate = predicate;
        listener.onBuilderEnded(this);
        return result;
    }

    @Override
    public Predicate getPredicate() {
        return predicate;
    }
    
    @Override
    public BetweenBuilder between(Object start) {
        if (start == null) {
            throw new NullPointerException("start");
        }
        return startBuilder(new BetweenBuilderImpl(result, leftExpression, parameterManager.addParameterExpression(start, clause, subqueryInitFactory.getQueryBuilder()), expressionFactory, parameterManager, this, subqueryInitFactory, clause));
    }

    @Override
    public BetweenBuilder betweenLiteral(Object start) {
        if (start == null) {
            throw new NullPointerException("start");
        }
        String literal = TypeUtils.asLiteral(start, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return between(start);
        }
        return startBuilder(new BetweenBuilderImpl(result, leftExpression, expressionFactory.createInItemExpression(literal), expressionFactory, parameterManager, this, subqueryInitFactory, clause));
    }

    @Override
    public BetweenBuilder betweenExpression(String start) {
        return startBuilder(new BetweenBuilderImpl(result, leftExpression, expressionFactory.createSimpleExpression(start), expressionFactory, parameterManager, this, subqueryInitFactory, clause));
    }

    @Override
    public SubqueryInitiator> betweenSubquery() {
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause));
        return subqueryInitFactory.createSubqueryInitiator(betweenBuilder, (SubqueryBuilderListener>) betweenStartSubqueryBuilderListener, false, clause);
    }

    @Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public SubqueryInitiator> betweenSubquery(String subqueryAlias, String expression) {
        leftSuperExprSubqueryPredicateBuilderListener = new SuperExpressionLeftHandsideSubqueryPredicateBuilder(subqueryAlias, expressionFactory.createSimpleExpression(expression, true));
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause));
        return subqueryInitFactory.createSubqueryInitiator(betweenBuilder, (SubqueryBuilderListener>) leftSuperExprSubqueryPredicateBuilderListener, false, clause);
    }

    @Override
    public MultipleSubqueryInitiator> betweenSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, expr, expressionFactory, parameterManager, this, subqueryInitFactory, clause));
        // We don't need a listener or marker here, because the resulting restriction builder can only be ended, when the initiator is ended
        return simpleMultipleBuilder(betweenBuilder, expr);
    }

    @Override
    public SubqueryBuilder> betweenSubquery(FullQueryBuilder criteriaBuilder) {
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause));
        return subqueryInitFactory.createSubqueryBuilder(betweenBuilder, (SubqueryBuilderListener>) betweenStartSubqueryBuilderListener, false, criteriaBuilder, clause);
    }

    @Override
    public SubqueryBuilder> betweenSubquery(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        leftSuperExprSubqueryPredicateBuilderListener = new SuperExpressionLeftHandsideSubqueryPredicateBuilder(subqueryAlias, expressionFactory.createSimpleExpression(expression, true));
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause));
        return subqueryInitFactory.createSubqueryBuilder(betweenBuilder, (SubqueryBuilderListener>) leftSuperExprSubqueryPredicateBuilderListener, false, criteriaBuilder, clause);
    }

    private  MultipleSubqueryInitiator simpleMultipleBuilder(X result, Expression expr) {
        MultipleSubqueryInitiator initiator = new MultipleSubqueryInitiatorImpl(result, expr, null, subqueryInitFactory, clause);
        return initiator;
    }
    
    private  MultipleSubqueryInitiator simpleMultipleBuilder(X result, Expression expr, final AbstractQuantifiablePredicateBuilder predicateBuilder) {
        MultipleSubqueryInitiatorImpl initiator = new MultipleSubqueryInitiatorImpl(result, expr, new ExpressionBuilderEndedListener() {

            @Override
            public void onBuilderEnded(ExpressionBuilder builder) {
                RestrictionBuilderImpl.this.predicate = predicateBuilder.createPredicate(leftExpression, builder.getExpression(), PredicateQuantifier.ONE);
                listener.onBuilderEnded(RestrictionBuilderImpl.this);
            }

        }, subqueryInitFactory, clause);

        startBuilder(predicateBuilder);
        predicateBuilder.startBuilder(initiator);
        return initiator;
    }

    @Override
    public BetweenBuilder notBetween(Object start) {
        if (start == null) {
            throw new NullPointerException("start");
        }
        return startBuilder(new BetweenBuilderImpl(result, leftExpression, parameterManager.addParameterExpression(start, clause, subqueryInitFactory.getQueryBuilder()), expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
    }

    @Override
    public BetweenBuilder notBetweenLiteral(Object start) {
        if (start == null) {
            throw new NullPointerException("start");
        }
        String literal = TypeUtils.asLiteral(start, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return notBetween(start);
        }
        return startBuilder(new BetweenBuilderImpl(result, leftExpression, expressionFactory.createInItemExpression(literal), expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
    }

    @Override
    public BetweenBuilder notBetweenExpression(String start) {
        return startBuilder(new BetweenBuilderImpl(result, leftExpression, expressionFactory.createSimpleExpression(start), expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
    }

    @Override
    public SubqueryInitiator> notBetweenSubquery() {
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
        return subqueryInitFactory.createSubqueryInitiator(betweenBuilder, (SubqueryBuilderListener>) betweenStartSubqueryBuilderListener, false, clause);
    }

    @Override
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public SubqueryInitiator> notBetweenSubquery(String subqueryAlias, String expression) {
        leftSuperExprSubqueryPredicateBuilderListener = new SuperExpressionLeftHandsideSubqueryPredicateBuilder(subqueryAlias, expressionFactory.createSimpleExpression(expression, true));
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
        return subqueryInitFactory.createSubqueryInitiator(betweenBuilder, (SubqueryBuilderListener>) leftSuperExprSubqueryPredicateBuilderListener, false, clause);
    }

    @Override
    public MultipleSubqueryInitiator> notBetweenSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, expr, expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
        // We don't need a listener or marker here, because the resulting restriction builder can only be ended, when the initiator is ended
        return simpleMultipleBuilder(betweenBuilder, expr);
    }

    @Override
    public SubqueryBuilder> notBetweenSubquery(FullQueryBuilder criteriaBuilder) {
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
        return subqueryInitFactory.createSubqueryBuilder(betweenBuilder, (SubqueryBuilderListener>) betweenStartSubqueryBuilderListener, false, criteriaBuilder, clause);
    }

    @Override
    public SubqueryBuilder> notBetweenSubquery(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        leftSuperExprSubqueryPredicateBuilderListener = new SuperExpressionLeftHandsideSubqueryPredicateBuilder(subqueryAlias, expressionFactory.createSimpleExpression(expression, true));
        BetweenBuilder betweenBuilder = startBuilder(new BetweenBuilderImpl(result, leftExpression, null, expressionFactory, parameterManager, this, subqueryInitFactory, clause, true));
        return subqueryInitFactory.createSubqueryBuilder(betweenBuilder, (SubqueryBuilderListener>) leftSuperExprSubqueryPredicateBuilderListener, false, criteriaBuilder, clause);
    }

    @Override
    public QuantifiableBinaryPredicateBuilder eq() {
        return startBuilder(new EqPredicateBuilder(result, this, leftExpression, false, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public T eq(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        return chain(new EqPredicate(leftExpression, parameterManager.addParameterExpression(value, clause, subqueryInitFactory.getQueryBuilder())));
    }

    @Override
    public T eqLiteral(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return eq(value);
        }
        return chain(new EqPredicate(leftExpression, expressionFactory.createInItemExpression(literal)));
    }

    @Override
    public T eqExpression(String expression) {
        return chain(new EqPredicate(leftExpression, expressionFactory.createSimpleExpression(expression, false)));
    }

    @Override
    public SubqueryInitiator eq(String subqueryAlias, String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startBuilder(new EqPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, false, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public MultipleSubqueryInitiator eqSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        return simpleMultipleBuilder(result, expr, new EqPredicateBuilder(result, this, leftExpression, false, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public SubqueryBuilder eq(FullQueryBuilder criteriaBuilder) {
        return startSubqueryBuilder(new EqPredicateBuilder(result, this, leftExpression, false, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public SubqueryBuilder eq(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startSubqueryBuilder(new EqPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, false, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public QuantifiableBinaryPredicateBuilder notEq() {
        return startBuilder(new EqPredicateBuilder(result, this, leftExpression, true, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public T notEq(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        return chain(new EqPredicate(leftExpression, parameterManager.addParameterExpression(value, clause, subqueryInitFactory.getQueryBuilder()), true));
    }

    @Override
    public T notEqLiteral(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return notEq(value);
        }
        return chain(new EqPredicate(leftExpression, expressionFactory.createInItemExpression(literal), true));
    }

    @Override
    public T notEqExpression(String expression) {
        return chain(new EqPredicate(leftExpression, expressionFactory.createSimpleExpression(expression, false), true));
    }

    @Override
    public SubqueryInitiator notEq(String subqueryAlias, String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startBuilder(new EqPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, true, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public MultipleSubqueryInitiator notEqSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        return simpleMultipleBuilder(result, expr, new EqPredicateBuilder(result, this, leftExpression, true, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public SubqueryBuilder notEq(FullQueryBuilder criteriaBuilder) {
        return startSubqueryBuilder(new EqPredicateBuilder(result, this, leftExpression, true, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public SubqueryBuilder notEq(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startSubqueryBuilder(new EqPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, true, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public QuantifiableBinaryPredicateBuilder gt() {
        return startBuilder(new GtPredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public T gt(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        return chain(new GtPredicate(leftExpression, parameterManager.addParameterExpression(value, clause, subqueryInitFactory.getQueryBuilder())));
    }

    @Override
    public T gtLiteral(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return gt(value);
        }
        return chain(new GtPredicate(leftExpression, expressionFactory.createInItemExpression(literal)));
    }

    @Override
    public T gtExpression(String expression) {
        return chain(new GtPredicate(leftExpression, expressionFactory.createSimpleExpression(expression, false)));
    }

    @Override
    public SubqueryInitiator gt(String subqueryAlias, String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startBuilder(new GtPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public MultipleSubqueryInitiator gtSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        return simpleMultipleBuilder(result, expr, new GtPredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public SubqueryBuilder gt(FullQueryBuilder criteriaBuilder) {
        return startSubqueryBuilder(new GtPredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public SubqueryBuilder gt(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startSubqueryBuilder(new GtPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public QuantifiableBinaryPredicateBuilder ge() {
        return startBuilder(new GePredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public T ge(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        return chain(new GePredicate(leftExpression, parameterManager.addParameterExpression(value, clause, subqueryInitFactory.getQueryBuilder())));
    }

    @Override
    public T geLiteral(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return ge(value);
        }
        return chain(new GePredicate(leftExpression, expressionFactory.createInItemExpression(literal)));
    }

    @Override
    public T geExpression(String expression) {
        return chain(new GePredicate(leftExpression, expressionFactory.createSimpleExpression(expression, false)));
    }

    @Override
    public SubqueryInitiator ge(String subqueryAlias, String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startBuilder(new GePredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public MultipleSubqueryInitiator geSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        return simpleMultipleBuilder(result, expr, new GePredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public SubqueryBuilder ge(FullQueryBuilder criteriaBuilder) {
        return startSubqueryBuilder(new GePredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public SubqueryBuilder ge(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startSubqueryBuilder(new GePredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public QuantifiableBinaryPredicateBuilder lt() {
        return startBuilder(new LtPredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public T lt(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        return chain(new LtPredicate(leftExpression, parameterManager.addParameterExpression(value, clause, subqueryInitFactory.getQueryBuilder())));
    }

    @Override
    public T ltLiteral(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return lt(value);
        }
        return chain(new LtPredicate(leftExpression, expressionFactory.createInItemExpression(literal)));
    }

    @Override
    public T ltExpression(String expression) {
        return chain(new LtPredicate(leftExpression, expressionFactory.createSimpleExpression(expression, false)));
    }

    @Override
    public SubqueryInitiator lt(String subqueryAlias, String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startBuilder(new LtPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public MultipleSubqueryInitiator ltSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        return simpleMultipleBuilder(result, expr, new LtPredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public SubqueryBuilder lt(FullQueryBuilder criteriaBuilder) {
        return startSubqueryBuilder(new LtPredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public SubqueryBuilder lt(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startSubqueryBuilder(new LtPredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public QuantifiableBinaryPredicateBuilder le() {
        return startBuilder(new LePredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public T le(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        return chain(new LePredicate(leftExpression, parameterManager.addParameterExpression(value, clause, subqueryInitFactory.getQueryBuilder())));
    }

    @Override
    public T leLiteral(Object value) {
        if (value == null) {
            throw new NullPointerException("value");
        }
        String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
        if (literal == null) {
            return le(value);
        }
        return chain(new LePredicate(leftExpression, expressionFactory.createInItemExpression(literal)));
    }

    @Override
    public T leExpression(String expression) {
        return chain(new LePredicate(leftExpression, expressionFactory.createSimpleExpression(expression, false)));
    }

    @Override
    public SubqueryInitiator le(String subqueryAlias, String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startBuilder(new LePredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public MultipleSubqueryInitiator leSubqueries(String expression) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        return simpleMultipleBuilder(result, expr, new LePredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause));
    }

    @Override
    public SubqueryBuilder le(FullQueryBuilder criteriaBuilder) {
        return startSubqueryBuilder(new LePredicateBuilder(result, this, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public SubqueryBuilder le(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        rightSuperExprSubqueryPredicateBuilderListener = new SuperExpressionRightHandsideSubqueryPredicateBuilder(subqueryAlias, expr, this);
        return startSubqueryBuilder(new LePredicateBuilder(result, rightSuperExprSubqueryPredicateBuilderListener, leftExpression, subqueryInitFactory, expressionFactory, parameterManager, clause), criteriaBuilder);
    }

    @Override
    public T inExpressions(String... parameterOrLiteralExpressions) {
        if (parameterOrLiteralExpressions == null) {
            throw new NullPointerException("parameterOrLiteralExpressions");
        }
        if (parameterOrLiteralExpressions.length == 0) {
            throw new IllegalArgumentException("empty parameterOrLiteralExpressions");
        }
        
        return chain(new InPredicate(leftExpression, expressionFactory.createInItemExpressions(parameterOrLiteralExpressions)));
    }

    @Override
    public T inCollectionExpression(String collectionParameterExpression) {
        if (collectionParameterExpression == null) {
            throw new NullPointerException("parameterOrCollectionExpression");
        }

        ParameterExpression collectionParameter = (ParameterExpression) expressionFactory.createInItemExpression(collectionParameterExpression);
        collectionParameter.setCollectionValued(true);
        return chain(new InPredicate(leftExpression, collectionParameter));
    }

    @Override
    public T in(Collection values) {
        if (values == null) {
            throw new NullPointerException("values");
        }
        return chain(new InPredicate(leftExpression, parameterManager.addParameterExpression(values, clause, subqueryInitFactory.getQueryBuilder())));
    }

    @Override
    public T in(Object... values) {
        return in(Arrays.asList(values));
    }

    @Override
    public T inLiterals(Collection values) {
        if (values == null) {
            throw new NullPointerException("values");
        }
        Expression[] literalValues = new Expression[values.size()];
        int i = 0;
        for (Object value : values) {
            String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
            if (literal == null) {
                return in(values);
            } else {
                literalValues[i++] = expressionFactory.createInItemExpression(literal);
            }
        }
        return chain(new InPredicate(leftExpression, literalValues));
    }

    @Override
    public T inLiterals(Object... values) {
        return inLiterals(Arrays.asList(values));
    }

    @Override
    public T notInExpressions(String... parameterOrLiteralExpressions) {
        if (parameterOrLiteralExpressions == null) {
            throw new NullPointerException("parameterOrLiteralExpressions");
        }
        if (parameterOrLiteralExpressions.length == 0) {
            throw new IllegalArgumentException("empty parameterOrLiteralExpressions");
        }

        return chain(new InPredicate(true, leftExpression, expressionFactory.createInItemExpressions(parameterOrLiteralExpressions)));
    }

    @Override
    public T notInCollectionExpression(String collectionParameterExpression) {
        if (collectionParameterExpression == null) {
            throw new NullPointerException("collectionParameterExpression");
        }

        ParameterExpression collectionParameter = (ParameterExpression) expressionFactory.createInItemExpression(collectionParameterExpression);
        collectionParameter.setCollectionValued(true);
        return chain(new InPredicate(true, leftExpression, collectionParameter));
    }

    @Override
    public T notIn(Collection values) {
        if (values == null) {
            throw new NullPointerException("values");
        }
        InPredicate inPredicate = new InPredicate(leftExpression, parameterManager.addParameterExpression(values, clause, subqueryInitFactory.getQueryBuilder()));
        inPredicate.setNegated(true);
        return chain(inPredicate);
    }

    @Override
    public T notIn(Object... values) {
        return notIn(Arrays.asList(values));
    }

    @Override
    public T notInLiterals(Collection values) {
        if (values == null) {
            throw new NullPointerException("values");
        }
        Expression[] literalValues = new Expression[values.size()];
        int i = 0;
        for (Object value : values) {
            String literal = TypeUtils.asLiteral(value, subqueryInitFactory.getQueryBuilder().getMetamodel().getEnumTypes().keySet());
            if (literal == null) {
                return notIn(values);
            } else {
                literalValues[i++] = expressionFactory.createInItemExpression(literal);
            }
        }
        InPredicate inPredicate = new InPredicate(leftExpression, literalValues);
        inPredicate.setNegated(true);
        return chain(inPredicate);
    }

    @Override
    public T notInLiterals(Object... values) {
        return notInLiterals(Arrays.asList(values));
    }

    @Override
    public T isNull() {
        return chain(new IsNullPredicate(leftExpression));
    }

    @Override
    public T isNotNull() {
        return chain(new IsNullPredicate(leftExpression, true));
    }

    @Override
    public T isEmpty() {
        return chain(new IsEmptyPredicate(makeCollectionValued(leftExpression)));
    }

    @Override
    public T isNotEmpty() {
        return chain(new IsEmptyPredicate(makeCollectionValued(leftExpression), true));
    }

    @Override
    public T isMemberOf(String expression) {
        return chain(new MemberOfPredicate(leftExpression, makeCollectionValued(expressionFactory.createPathExpression(expression))));
    }

    @Override
    public T isNotMemberOf(String expression) {
        return chain(new MemberOfPredicate(leftExpression, makeCollectionValued(expressionFactory.createPathExpression(expression)), true));
    }

    @Override
    public LikeBuilder like(boolean caseSensitive) {
        return startBuilder(new LikeBuilderImpl(result, this, leftExpression, expressionFactory, parameterManager, subqueryInitFactory, clause, false, caseSensitive));
    }

    @Override
    public LikeBuilder like() {
        return like(true);
    }

    @Override
    public LikeBuilder notLike(boolean caseSensitive) {
        return startBuilder(new LikeBuilderImpl(result, this, leftExpression, expressionFactory, parameterManager, subqueryInitFactory, clause, true, caseSensitive));
    }

    @Override
    public LikeBuilder notLike() {
        return notLike(true);
    }

    @Override
    public SubqueryInitiator in() {
        verifyBuilderEnded();
        this.predicate = new InPredicate(leftExpression);
        return subqueryInitFactory.createSubqueryInitiator(result, this, false, clause);
    }

    @Override
    public SubqueryInitiator notIn() {
        verifyBuilderEnded();
        this.predicate = new InPredicate(true, leftExpression);
        return subqueryInitFactory.createSubqueryInitiator(result, this, false, clause);
    }

    @Override
    public SubqueryInitiator in(String subqueryAlias, String expression) {
        return in(subqueryAlias, expression, false);
    }

    @Override
    public SubqueryInitiator notIn(String subqueryAlias, String expression) {
        return in(subqueryAlias, expression, true);
    }

    @Override
    public SubqueryBuilder in(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        return in(subqueryAlias, expression, false, criteriaBuilder);
    }

    @Override
    public SubqueryBuilder notIn(String subqueryAlias, String expression, FullQueryBuilder criteriaBuilder) {
        return in(subqueryAlias, expression, true, criteriaBuilder);
    }

    @Override
    public SubqueryBuilder in(FullQueryBuilder criteriaBuilder) {
        verifyBuilderEnded();
        this.predicate = new InPredicate(leftExpression);
        return subqueryInitFactory.createSubqueryBuilder(result, this, false, criteriaBuilder, clause);
    }

    @Override
    public SubqueryBuilder notIn(FullQueryBuilder criteriaBuilder) {
        verifyBuilderEnded();
        this.predicate = new InPredicate(true, leftExpression);
        return subqueryInitFactory.createSubqueryBuilder(result, this, false, criteriaBuilder, clause);
    }

    private SubqueryInitiator in(String subqueryAlias, String expression, boolean negated) {
        verifyBuilderEnded();

        this.predicate = new InPredicate(negated, leftExpression);
        Expression superExpression = expressionFactory.createSimpleExpression(expression);
        rightSuperExprSubqueryBuilderListener = new SuperExpressionSubqueryBuilderListener(subqueryAlias, superExpression) {

            @Override
            public void onBuilderEnded(SubqueryInternalBuilder builder) {
                super.onBuilderEnded(builder);
                onSubqueryBuilderEnded(superExpression);
                listener.onBuilderEnded(RestrictionBuilderImpl.this);
            }

        };
        return subqueryInitFactory.createSubqueryInitiator(result, rightSuperExprSubqueryBuilderListener, false, clause);
    }

    private SubqueryBuilder in(String subqueryAlias, String expression, boolean negated, FullQueryBuilder criteriaBuilder) {
        verifyBuilderEnded();

        this.predicate = new InPredicate(negated, leftExpression);
        Expression superExpression = expressionFactory.createSimpleExpression(expression);
        rightSuperExprSubqueryBuilderListener = new SuperExpressionSubqueryBuilderListener(subqueryAlias, superExpression) {

            @Override
            public void onBuilderEnded(SubqueryInternalBuilder builder) {
                super.onBuilderEnded(builder);
                onSubqueryBuilderEnded(superExpression);
                listener.onBuilderEnded(RestrictionBuilderImpl.this);
            }

        };
        return subqueryInitFactory.createSubqueryBuilder(result, rightSuperExprSubqueryBuilderListener, false, criteriaBuilder, clause);
    }

    @Override
    public MultipleSubqueryInitiator inSubqueries(String expression) {
        return inSubqueries(expression, false);
    }

    @Override
    public MultipleSubqueryInitiator notInSubqueries(String expression) {
        return inSubqueries(expression, true);
    }
    
    private MultipleSubqueryInitiator inSubqueries(String expression, boolean negated) {
        verifyBuilderEnded();

        Expression expr = expressionFactory.createSimpleExpression(expression, true);
        this.predicate = new InPredicate(negated, leftExpression);
        return new MultipleSubqueryInitiatorImpl(result, expr, new ExpressionBuilderEndedListener() {
            
            @Override
            public void onBuilderEnded(ExpressionBuilder builder) {
                onSubqueryBuilderEnded(builder.getExpression());
                listener.onBuilderEnded(RestrictionBuilderImpl.this);
            }
            
        }, subqueryInitFactory, clause);
    }

    @Override
    public RestrictionBuilderExperimental nonPortable() {
        return this;
    }

    @Override
    protected  X startBuilder(X builder) {
        betweenStartSubqueryBuilderListener.verifySubqueryBuilderEnded();
        return super.startBuilder(builder);
    }

    protected  SubqueryBuilder startSubqueryBuilder(AbstractQuantifiablePredicateBuilder builder, FullQueryBuilder criteriaBuilder) {
        betweenStartSubqueryBuilderListener.verifySubqueryBuilderEnded();
        return super.startBuilder(builder).one(criteriaBuilder);
    }

    @Override
    public void onBuilderEnded(PredicateBuilder builder) {
        super.onBuilderEnded(builder);
        predicate = builder.getPredicate();
        listener.onBuilderEnded(this);
    }

    @Override
    public void onBuilderEnded(SubqueryInternalBuilder builder) {
        super.onBuilderEnded(builder);
        onSubqueryBuilderEnded(new SubqueryExpression(builder));
        listener.onBuilderEnded(this);
    }

    private void onSubqueryBuilderEnded(Expression rightHandsideExpression) {
        if (predicate instanceof InPredicate) {
            ((InPredicate) predicate).setRight(new ArrayList(Arrays.asList(rightHandsideExpression)));
        } else {
            throw new IllegalStateException("SubqueryBuilder ended but predicate was not an IN predicate");
        }
    }

    @Override
    protected void verifyBuilderEnded() {
        super.verifyBuilderEnded();
        betweenStartSubqueryBuilderListener.verifySubqueryBuilderEnded();
        if (rightSuperExprSubqueryBuilderListener != null) {
            rightSuperExprSubqueryBuilderListener.verifySubqueryBuilderEnded();
        }
        if (leftSuperExprSubqueryPredicateBuilderListener != null) {
            leftSuperExprSubqueryPredicateBuilderListener.verifySubqueryBuilderEnded();
        }
    }

    private Expression makeCollectionValued(Expression expr) {
        if (expr instanceof PathExpression) {
            ((PathExpression) expr).setUsedInCollectionFunction(true);
        } else {
            throw new SyntaxErrorException("Function expects collection valued path and cannot be applied to predicate [" + expr + "]");
        }

        return expr;
    }

    /**
     * @author Christian Beikov
     * @since 1.0.0
     */
    private class SuperExpressionRightHandsideSubqueryPredicateBuilder implements PredicateBuilderEndedListener {

        private final PredicateBuilderEndedListener listener;
        private final String subqueryAlias;
        private Expression superExpression;

        public SuperExpressionRightHandsideSubqueryPredicateBuilder(String subqueryAlias, Expression superExpression, PredicateBuilderEndedListener listener) {
            this.listener = listener;
            this.subqueryAlias = subqueryAlias;
            this.superExpression = superExpression;
        }

        @Override
        public void onBuilderEnded(PredicateBuilder builder) {
            Predicate expression = builder.getPredicate();
            BinaryExpressionPredicate binaryPred = (BinaryExpressionPredicate) builder.getPredicate();
            SubqueryExpression subqueryExpr = (SubqueryExpression) binaryPred.getRight();
            superExpression = ExpressionUtils.replaceSubexpression(superExpression, subqueryAlias, subqueryExpr);
            binaryPred.setRight(superExpression);
            listener.onBuilderEnded(builder);
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy