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

com.speedment.runtime.field.internal.predicate.AbstractCombinedPredicate Maven / Gradle / Ivy

/**
 *
 * Copyright (c) 2006-2019, Speedment, Inc. All Rights Reserved.
 *
 * 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.speedment.runtime.field.internal.predicate;

import com.speedment.runtime.field.predicate.CombinedPredicate;

import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

import static com.speedment.runtime.field.internal.util.CollectionUtil.copyAndAdd;
import static java.util.Collections.unmodifiableList;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;

/**
 * Immutable aggregation of a number of {@link Predicate Predicates} of the same type
 * (e.g. AND or OR) that can be applied in combination.
 *
 * @param  the entity type
 *
 * @author Per Minborg
 * @author Emil Forslund
 * @since  2.2.0
 */
public abstract class AbstractCombinedPredicate
extends AbstractPredicate
implements CombinedPredicate {

    private final List> predicates;
    private final Type type;

    private AbstractCombinedPredicate(
            final Type type,
            final List> predicates) {

        this.type       = requireNonNull(type);
        this.predicates = requireNonNull(predicates);
    }

    protected List> getPredicates() {
        return unmodifiableList(predicates);
    }

    @Override
    public Stream> stream() {
        return predicates.stream();
    }

    @Override
    public int size() {
        return predicates.size();
    }

    @Override
    public Type getType() {
        return type;
    }

    @Override
    public abstract CombinedPredicate and(Predicate other);

    @Override
    public abstract CombinedPredicate or(Predicate other);

    /**
     * Specialization for {@code AND}-predicates.
     *
     * @param   the entity type
     */
    public static final class AndCombinedBasePredicate
    extends AbstractCombinedPredicate {

        public AndCombinedBasePredicate(
                List> predicates) {

            super(Type.AND, predicates);
        }

        @Override
        public boolean applyAsBoolean(ENTITY entity) {
            requireNonNull(entity);
            return stream().allMatch(p -> p.test(entity));
        }

        @Override
        public CombinedPredicate and(Predicate other) {
            requireNonNull(other);
            return new AndCombinedBasePredicate<>(
                copyAndAdd(getPredicates(), other)
            );
        }

        @Override
        public CombinedPredicate or(Predicate other) {
            requireNonNull(other);
            return CombinedPredicate.or(this, other);
        }

        @Override
        @SuppressWarnings("unchecked")
        public CombinedPredicate negate() {
            return new OrCombinedBasePredicate<>(
                getPredicates().stream()
                    .map(p -> (Predicate) p)
                    .map(Predicate::negate)
                    .collect(toList())
            );
        }
    }

    /**
     * Specialization for {@code OR}-predicates.
     *
     * @param   the entity type
     */
    public static final class OrCombinedBasePredicate
    extends AbstractCombinedPredicate {

        public OrCombinedBasePredicate(
                List> predicates) {

            super(Type.OR, predicates);
        }

        @Override
        public boolean applyAsBoolean(ENTITY entity) {
            requireNonNull(entity);
            return stream().anyMatch(p -> p.test(entity));
        }

        @Override
        public CombinedPredicate and(Predicate other) {
            requireNonNull(other);
            return CombinedPredicate.and(this, other);
        }

        @Override
        public CombinedPredicate or(Predicate other) {
            requireNonNull(other);
            return new OrCombinedBasePredicate<>(
                copyAndAdd(getPredicates(), other)
            );
        }

        @Override
        @SuppressWarnings("unchecked")
        public AndCombinedBasePredicate negate() {
            return new AndCombinedBasePredicate<>(
                getPredicates().stream()
                    .map(p -> (Predicate) p)
                    .map(Predicate::negate)
                    .collect(toList())
            );
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof CombinedPredicate)) return false;

        final CombinedPredicate that = (CombinedPredicate) o;
        final Iterator> it = predicates.iterator();
        return getType() == that.getType()
            && that.stream().allMatch(it.next()::equals);
    }

    @Override
    public int hashCode() {
        int result = getPredicates().hashCode();
        result = 31 * result + getType().hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "CombinedPredicate {type="
            + type.name()
            + ", predicates="
            + predicates
            + "}";
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy