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

paa.coder.noodleCriteriaBuilder.queryBuilder.specifications.NoodleSpecificationBuilder Maven / Gradle / Ivy

package paa.coder.noodleCriteriaBuilder.queryBuilder.specifications;

import paa.coder.noodleCriteriaBuilder.NoodleFactory;
import paa.coder.noodleCriteriaBuilder.interfaces.NoodlePredicate;
import paa.coder.noodleCriteriaBuilder.interfaces.PathFinder;
import paa.coder.noodleCriteriaBuilder.queryBuilder.SubqueryBuilder;
import paa.coder.noodleCriteriaBuilder.queryBuilder.expressions.SelectStore;

import javax.persistence.criteria.CommonAbstractCriteria;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class NoodleSpecificationBuilder implements NoodlePredicate {

    private final NoodleFactory noodleFactory;
    private Boolean isNot;
    private List predicates = new ArrayList<>();
    private Predicate.BooleanOperator operator = null;

    public static Optional getField(Object value){
        if(value != null && String.class.isAssignableFrom(value.getClass())){
            String field = ((String) value).trim();
            if(field.startsWith("#")){
                return Optional.of(field.replaceFirst("#", ""));
            }
        }
        return Optional.empty();
    }

    private NoodleSpecificationBuilder(NoodleFactory noodleFactory, Boolean isNot){
        this.noodleFactory = noodleFactory;
        this.isNot = isNot;
    }

    private NoodleSpecificationBuilder(NoodleFactory noodleFactory, NoodlePredicate init, Boolean isNot){
        this.noodleFactory = noodleFactory;
        predicates.add(init);
        this.isNot = isNot;
    }

    private NoodleSpecificationBuilder(NoodleFactory noodleFactory, NoodlePredicate left, NoodlePredicate right, Predicate.BooleanOperator operator){
        this.noodleFactory = noodleFactory;
        predicates.add(left);
        predicates.add(right);
        this.operator = operator;
        isNot = false;
    }

    private NoodleSpecificationBuilder(NoodleSpecificationBuilder noodleSpecificationBuilder){
        this.noodleFactory = noodleSpecificationBuilder.noodleFactory;
        this.isNot = noodleSpecificationBuilder.isNot;
        this.predicates = noodleSpecificationBuilder.predicates;
        this.operator = noodleSpecificationBuilder.operator;
    }

    @Override
    public Predicate apply(PathFinder pathFinder, CommonAbstractCriteria criteriaQuery, CriteriaBuilder criteriaBuilder){
        Predicate[] result = predicates
                .stream()
                .map(i -> i.apply(pathFinder, criteriaQuery, criteriaBuilder))
                .filter(Objects::nonNull)
                .toArray(Predicate[]::new);
        if(result.length == 0){
            return null;
        }
        Predicate p = Objects.equals(Predicate.BooleanOperator.OR, this.operator) ? criteriaBuilder.or(result) : criteriaBuilder.and(result);
        return isNot ? p.not() : p;
    }

    private NoodleSpecificationBuilder update(NoodlePredicate specification, Predicate.BooleanOperator operator){
        if(specification == null){
            return this;
        }
        if(this.operator == null || Objects.equals(operator, this.operator)){
            predicates.add(specification);
        }else{
            this.predicates = Stream.of(new NoodleSpecificationBuilder(this), specification).collect(Collectors.toList());
        }
        this.operator = operator;
        return this;
    }

    public NoodleSpecificationBuilder update(String field, String operator, Object value, Predicate.BooleanOperator predicateOperator){
        return update(toPredicate(field, operator, value, false), predicateOperator);
    }

    public NoodleSpecificationBuilder update(Consumer consumer, String operator, Object value,
                                             Predicate.BooleanOperator predicateOperator){
        return update(toPredicate(consumer, operator, value, false), predicateOperator);
    }

    public NoodleSpecificationBuilder update(Function fPred,
                                             Predicate.BooleanOperator predicateOperator){
        return update(fPred.apply(new Builder(noodleFactory)), predicateOperator);
    }

    public NoodleSpecificationBuilder updateNot(String field, String operator, Object value, Predicate.BooleanOperator predicateOperator){
        return update(toPredicate(field, operator, value, true), predicateOperator);
    }

    public NoodleSpecificationBuilder updateNot(Consumer consumer, String operator, Object value,
                                                Predicate.BooleanOperator predicateOperator){
        return update(toPredicate(consumer, operator, value, true), predicateOperator);
    }

    public NoodleSpecificationBuilder updateNot(Function fPred,
                                                Predicate.BooleanOperator predicateOperator){
        return update(fPred.apply(new Builder(noodleFactory, true)), predicateOperator);
    }

    public NoodleSpecificationBuilder andIsNotNul(String field){
        return and(field, "IS NOT NULL", null);
    }

    public NoodleSpecificationBuilder andIsNul(String field){
        return and(field, "IS NULL", null);
    }

    public NoodleSpecificationBuilder and(String field, Object value){
        return and(field, "=", value);
    }

    public NoodleSpecificationBuilder and(Consumer consumer, Object value){
        return and(consumer, "=", value);
    }

    public NoodleSpecificationBuilder andNot(String field, Object value){
        return andNot(field, "=", value);
    }

    public NoodleSpecificationBuilder andNot(Consumer consumer, Object value){
        return andNot(consumer, "=", value);
    }

    private static NoodlePredicate toPredicate(NoodleFactory noodleFactory, String field, String operator, Object value, Boolean isNot){
        return NoodleSpecificationBuilder
                .getField(value)
                .map(f -> (NoodlePredicate) new FieldToFieldSpecification(field, operator, f, isNot))
                .orElse(new SampleSpecification(noodleFactory, field, operator, value, isNot));
    }

    private static NoodlePredicate toPredicate(NoodleFactory noodleFactory, Consumer consumer, String operator, Object value,
                                               Boolean isNot){
        SelectStore.Single s = new SelectStore.Single();
        consumer.accept(s);
        return Optional
                .ofNullable(s.getExpression())
                .map(expression -> NoodleSpecificationBuilder
                        .getField(value)
                        .map(f -> (NoodlePredicate) new FieldToFieldSpecification(expression, operator, f, isNot))
                        .orElse(new SampleSpecification(noodleFactory, expression, operator, value, isNot)))
                .orElse(null);
    }

    private NoodlePredicate toPredicate(String field, String operator, Object value, Boolean isNot){
        return toPredicate(noodleFactory, field, operator, value, isNot);
    }

    private NoodlePredicate toPredicate(Consumer consumer, String operator, Object value, Boolean isNot){
        return toPredicate(noodleFactory, consumer, operator, value, isNot);
    }

    public NoodleSpecificationBuilder and(String field, String operator, Object value){
        return update(field, operator, value, Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder and(Consumer consumer, String operator, Object value){
        return update(consumer, operator, value, Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder andNot(String field, String operator, Object value){
        return updateNot(field, operator, value, Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder andNot(Consumer consumer, String operator, Object value){
        return updateNot(consumer, operator, value, Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder and(Function fPred){
        return update(fPred, Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder andNot(Function fPred){
        return updateNot(fPred, Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder orIsNotNul(String field){
        return or(field, "IS NOT NULL", null);
    }

    public NoodleSpecificationBuilder orIsNul(String field){
        return or(field, "IS NULL", null);
    }

    public NoodleSpecificationBuilder or(String field, Object value){
        return or(field, "=", value);
    }

    public NoodleSpecificationBuilder or(Consumer consumer, Object value){
        return or(consumer, "=", value);
    }

    public NoodleSpecificationBuilder orNot(String field, Object value){
        return orNot(field, "=", value);
    }

    public NoodleSpecificationBuilder orNot(Consumer consumer, Object value){
        return orNot(consumer, "=", value);
    }

    public NoodleSpecificationBuilder or(String field, String operator, Object value){
        return update(field, operator, value, Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder or(Consumer consumer, String operator, Object value){
        return update(consumer, operator, value, Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder orNot(String field, String operator, Object value){
        return updateNot(field, operator, value, Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder orNot(Consumer consumer, String operator, Object value){
        return updateNot(consumer, operator, value, Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder or(Function fPred){
        return update(fPred, Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder orNot(Function fPred){
        return updateNot(fPred, Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder andSubquery(String field, SubqueryBuilder.Initiator.Runner value){
        return andSubquery(field, "=", value);
    }

    public NoodleSpecificationBuilder andSubquery(String field, String operator, SubqueryBuilder.Initiator.Runner value){
        return update(new FieldSubquerySpecification<>(field, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory))),
                      Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder andSubqueryNot(String field, SubqueryBuilder.Initiator.Runner value){
        return andSubqueryNot(field, "=", value);
    }

    public NoodleSpecificationBuilder andSubqueryNot(String field, String operator, SubqueryBuilder.Initiator.Runner value){
        return update(new FieldSubquerySpecification<>(field, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory)), true),
                      Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder orSubquery(String field, SubqueryBuilder.Initiator.Runner value){
        return orSubquery(field, "=", value);
    }

    public NoodleSpecificationBuilder orSubquery(String field, String operator, SubqueryBuilder.Initiator.Runner value){
        return update(new FieldSubquerySpecification<>(field, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory))),
                      Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder orSubqueryNot(String field, SubqueryBuilder.Initiator.Runner value){
        return orSubqueryNot(field, "=", value);
    }

    public NoodleSpecificationBuilder orSubqueryNot(String field, String operator, SubqueryBuilder.Initiator.Runner value){
        return update(new FieldSubquerySpecification<>(field, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory)), true),
                      Predicate.BooleanOperator.OR);
    }


    public NoodleSpecificationBuilder andSubquery(SubqueryBuilder.Initiator.Runner value, Object o){
        return andSubquery(value, "=", o);
    }

    public NoodleSpecificationBuilder andSubquery( SubqueryBuilder.Initiator.Runner value,String operator,Object o){
        return update(new LiteralSubquerySpecification<>(o, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory))),
                      Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder andSubqueryNot(SubqueryBuilder.Initiator.Runner value, Object o){
        return andSubqueryNot(value, "=", o);
    }

    public NoodleSpecificationBuilder andSubqueryNot(SubqueryBuilder.Initiator.Runner value, String operator, Object o){
        return update(new LiteralSubquerySpecification<>(o, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory)), true),
                      Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder orSubquery(SubqueryBuilder.Initiator.Runner value,Object o){
        return orSubquery(value, "=", o);
    }

    public NoodleSpecificationBuilder orSubquery(SubqueryBuilder.Initiator.Runner value, String operator, Object o){
        return update(new LiteralSubquerySpecification<>(o, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory))),
                      Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder orSubqueryNot( SubqueryBuilder.Initiator.Runner value,Object o){
        return orSubqueryNot(value, "=", o);
    }

    public NoodleSpecificationBuilder orSubqueryNot(SubqueryBuilder.Initiator.Runner value, String operator,Object o){
        return update(new LiteralSubquerySpecification<>(o, operator, value.apply(new SubqueryBuilder.Initiator(noodleFactory)), true),
                      Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder andExists(SubqueryBuilder.Initiator.Runner value){
        return update(new ExistSpecification(value.apply(new SubqueryBuilder.Initiator(noodleFactory)), false),
                      Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder andNotExists(SubqueryBuilder.Initiator.Runner value){
        return update(new ExistSpecification(value.apply(new SubqueryBuilder.Initiator(noodleFactory)), true),
                      Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder orExists(SubqueryBuilder.Initiator.Runner value){
        return update(new ExistSpecification(value.apply(new SubqueryBuilder.Initiator(noodleFactory)), false),
                      Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder orNotExists(SubqueryBuilder.Initiator.Runner value){
        return update(new ExistSpecification(value.apply(new SubqueryBuilder.Initiator(noodleFactory)), true),
                      Predicate.BooleanOperator.OR);
    }

    public NoodleSpecificationBuilder andSame(Object value){
        return andSame(value,null);
    }
    public NoodleSpecificationBuilder andSame(Object value, String prefix){
        return update(new SameSpecification(new Builder(noodleFactory, false),value,prefix),Predicate.BooleanOperator.AND);
    }
    public NoodleSpecificationBuilder andNotSame(Object value){
        return andNotSame(value,null);
    }
    public NoodleSpecificationBuilder andNotSame(Object value, String prefix){
        return update(new SameSpecification(new Builder(noodleFactory, true),value,prefix),Predicate.BooleanOperator.AND);
    }

    public NoodleSpecificationBuilder orSame(Object value){
        return orSame(value,null);
    }
    public NoodleSpecificationBuilder orSame(Object value, String prefix){
        return update(new SameSpecification(new Builder(noodleFactory, false),value,prefix),Predicate.BooleanOperator.OR);
    }
    public NoodleSpecificationBuilder orNotSame(Object value){
        return orNotSame(value,null);
    }
    public NoodleSpecificationBuilder orNotSame(Object value, String prefix){
        return update(new SameSpecification(new Builder(noodleFactory, true),value,prefix),Predicate.BooleanOperator.OR);
    }



    public static class Builder implements NoodlePredicate.Builder {

        private final NoodleFactory noodleFactory;
        private final Boolean isNot;

        public Builder(NoodleFactory noodleFactory){
            this(noodleFactory, false);
        }

        public Builder(NoodleFactory noodleFactory, Boolean isNot){
            this.noodleFactory = noodleFactory;
            this.isNot = isNot;
        }

        @Override
        public NoodleSpecificationBuilder where(String field, String operator, Object value){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  NoodleSpecificationBuilder.toPredicate(noodleFactory, field, operator, value, false),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder whereNot(String field, String operator, Object value){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  NoodleSpecificationBuilder.toPredicate(noodleFactory, field, operator, value, true),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder whereSubquery(String field, String operator, SubqueryBuilder.Initiator.Runner value){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  new FieldSubquerySpecification<>(field,
                                                                                   operator,
                                                                                   value.apply(new SubqueryBuilder.Initiator(noodleFactory))),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder whereSubqueryNot(String field, String operator, SubqueryBuilder.Initiator.Runner value){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  new FieldSubquerySpecification<>(field,
                                                                                   operator,
                                                                                   value.apply(new SubqueryBuilder.Initiator(noodleFactory)),
                                                                                   true),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder whereSubquery(SubqueryBuilder.Initiator.Runner value,String operator,Object o){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  new LiteralSubquerySpecification<>(o,
                                                                                   operator,
                                                                                   value.apply(new SubqueryBuilder.Initiator(noodleFactory))),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder whereSubqueryNot(SubqueryBuilder.Initiator.Runner value,String operator,Object o){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  new LiteralSubquerySpecification<>(o,
                                                                                   operator,
                                                                                   value.apply(new SubqueryBuilder.Initiator(noodleFactory)),
                                                                                   true),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder where(Function fPred){
            return new NoodleSpecificationBuilder(noodleFactory, fPred.apply(new Builder(noodleFactory)), isNot);
        }

        @Override
        public NoodleSpecificationBuilder whereNot(Function fPred){
            return new NoodleSpecificationBuilder(noodleFactory, fPred.apply(new Builder(noodleFactory, true)), isNot);
        }

        @Override
        public NoodleSpecificationBuilder where(Consumer consumer, String operator, Object value){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  NoodleSpecificationBuilder.toPredicate(noodleFactory, consumer, operator, value, false),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder whereNot(Consumer consumer, String operator, Object value){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  NoodleSpecificationBuilder.toPredicate(noodleFactory, consumer, operator, value, true),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder same(Object value, String prefix){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  new SameSpecification(new Builder(noodleFactory, false),value,prefix),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder notSame(Object value, String prefix){
            return new NoodleSpecificationBuilder(noodleFactory,
                                                  new SameSpecification(new Builder(noodleFactory, true),value,prefix),
                                                  isNot);
        }

        @Override
        public NoodleSpecificationBuilder empty(){
            return new NoodleSpecificationBuilder(noodleFactory, isNot);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy