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

de.unkrig.commons.lang.protocol.PredicateUtil Maven / Gradle / Ivy


/*
 * de.unkrig.commons - A general-purpose Java class library
 *
 * Copyright (c) 2011, Arno Unkrig
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 * following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 *       following disclaimer in the documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package de.unkrig.commons.lang.protocol;

import java.util.Collection;
import java.util.Map;

/**
 * Various {@link Predicate}-related utility methods.
 */
public final
class PredicateUtil {

    private
    PredicateUtil() {}

    /**
     * @return A {@link Predicate} which evaluates to the value (regardless of the subject)
     */
    public static  Predicate
    always(boolean value) { return value ? PredicateUtil.always() : PredicateUtil.never(); }

    /**
     * @return A {@link Predicate} which evaluates to {@code true} (regardless of the subject)
     */
    @SuppressWarnings("unchecked") public static  Predicate
    always() { return PredicateUtil.ALWAYS; }

    /**
     * @return A {@link Predicate} which evaluates to {@code false} (regardless of the subject)
     */
    @SuppressWarnings("unchecked") public static  Predicate
    never() { return PredicateUtil.NEVER; }

    @SuppressWarnings("rawtypes") private static final Predicate
    ALWAYS = new Predicate() {

        @Override public boolean
        evaluate(Object subject) { return true; }

        @Override public String
        toString() { return "ALWAYS"; }
    };

    @SuppressWarnings("rawtypes") private static final Predicate
    NEVER = new Predicate() {

        @Override public boolean
        evaluate(Object subject) { return false; }

        @Override public String
        toString() { return "NEVER"; }
    };

    /**
     * Creates and returns a {@link Predicate} for which the first evaluation will yield {@code true}, and,
     * after that, the time interval between adjacent {@code true} evaluations will (A) be minimal and (B) never
     * shorter than milliseconds.
     *
     * @deprecated Use "{@link PredicateUtil}{@code .}{@link PredicateUtil#ignoreSubject ignoreSubject}{@code (}{@link
     *             ProducerUtil}{@code .}{@link ProducerUtil#atMostEvery(long) atMostEvery}{@code
     *             (}milliseconds{@code ))}" instead
     */
    @Deprecated
    public static  Predicate
    atMostEvery(final long milliseconds) {

        return PredicateUtil.ignoreSubject(ProducerUtil.atMostEvery(milliseconds));
    }

    /**
     * Returns a {@link Predicate} which evaluates to {@code true} iff both lhs and rhs evaluate
     * to {@code true}.
     * 

* Notice that iff either of the lhs and the rhs is {@link #never()}, then none of the * two will ever be evaluated. *

*/ @SuppressWarnings("unchecked") public static Predicate and(final Predicate lhs, final Predicate rhs) { if (lhs == PredicateUtil.NEVER || rhs == PredicateUtil.NEVER) return PredicateUtil.NEVER; if (lhs == PredicateUtil.ALWAYS) return (Predicate) rhs; if (rhs == PredicateUtil.ALWAYS) return (Predicate) lhs; return new Predicate() { @Override public boolean evaluate(T subject) { return lhs.evaluate(subject) && rhs.evaluate(subject); } @Override public String toString() { return lhs + " && " + rhs; } }; } /** * Returns a {@link Predicate} which evaluates to {@code true} iff both the rhs is {@code true} * and the lhs evaluates to {@code true}. *

* Notice that iff the rhs is {@code false}, then the lhs will ever be evaluated. *

*/ @SuppressWarnings("unchecked") public static Predicate and(Predicate lhs, boolean rhs) { return ( !rhs ? PredicateUtil.NEVER : lhs == PredicateUtil.ALWAYS ? PredicateUtil.always(rhs) : (Predicate) lhs ); } /** * Returns a {@link Predicate} which evaluates to {@code true} iff both the lhs is {@code true} and * the rhs evaluates to {@code true}. *

* Notice that iff the lhs is {@code false}, then the rhs will ever be evaluated. *

*/ @SuppressWarnings("unchecked") public static Predicate and(boolean lhs, Predicate rhs) { return ( !lhs ? PredicateUtil.NEVER : rhs == PredicateUtil.ALWAYS ? PredicateUtil.always(lhs) : (Predicate) rhs ); } /** * Returns {@link Predicate} which evaluates to {@code true} if lhs, or rhs, or both evaluate * to {@code true}. *

* Notice that iff either of the lhs and the rhs is {@link #always()}, then none of the * two will ever be evaluated. *

*/ @SuppressWarnings("unchecked") public static Predicate or(final Predicate lhs, final Predicate rhs) { if (lhs == PredicateUtil.ALWAYS || rhs == PredicateUtil.ALWAYS) return PredicateUtil.ALWAYS; if (lhs == PredicateUtil.NEVER) return (Predicate) rhs; if (rhs == PredicateUtil.NEVER) return (Predicate) lhs; return new Predicate() { @Override public boolean evaluate(T subject) { return lhs.evaluate(subject) || rhs.evaluate(subject); } @Override public String toString() { return lhs + " || " + rhs; } }; } /** * Returns {@link Predicate} which evaluates to {@code true} if lhs, or rhs, or both evaluate * to {@code true}. *

* Notice that iff either of the lhs and the rhs is {@link #always()}, then none of the * two will ever be evaluated. *

*/ @SuppressWarnings("unchecked") public static PredicateWhichThrows or( final PredicateWhichThrows lhs, final PredicateWhichThrows rhs ) { if (lhs == PredicateUtil.ALWAYS || rhs == PredicateUtil.ALWAYS) return PredicateUtil.ALWAYS; if (lhs == PredicateUtil.NEVER) return rhs; if (rhs == PredicateUtil.NEVER) return lhs; return new PredicateWhichThrows() { @Override public boolean evaluate(T subject) throws EX { return lhs.evaluate(subject) || rhs.evaluate(subject); } @Override public String toString() { return lhs + " || " + rhs; } }; } /** * Returns a {@link Predicate} which evaluates to {@code true} the lhs evaluates to {@code true}, or the * rhs is {@code true}, or both. *

* Notice that iff the rhs is {@code true}, then the lhs will ever be evaluated. *

*/ @SuppressWarnings("unchecked") public static Predicate or(Predicate lhs, boolean rhs) { return ( rhs ? PredicateUtil.ALWAYS : lhs == PredicateUtil.NEVER ? PredicateUtil.always(rhs) : (Predicate) lhs ); } /** * Returns a {@link Predicate} which evaluates to {@code true} if the lhs is {@code true}, or the * rhs evaluates to {@code true}, or both. *

* Notice that iff the lhs is {@code true}, then the rhs will ever be evaluated. *

*/ @SuppressWarnings("unchecked") public static Predicate or(boolean lhs, Predicate rhs) { return ( lhs ? PredicateUtil.ALWAYS : rhs == PredicateUtil.NEVER ? PredicateUtil.always(lhs) : (Predicate) rhs ); } /** * @return A {@link Predicate} which evaluates to {@code true} iff exactly one of lhs or * rhs evaluate to {@code true} */ @SuppressWarnings("unchecked") public static Predicate xor(final Predicate lhs, final Predicate rhs) { if (lhs == PredicateUtil.ALWAYS) { if (rhs == PredicateUtil.ALWAYS) return PredicateUtil.NEVER; if (rhs == PredicateUtil.NEVER) return PredicateUtil.ALWAYS; } if (lhs == PredicateUtil.NEVER) { if (rhs == PredicateUtil.ALWAYS) return PredicateUtil.ALWAYS; if (rhs == PredicateUtil.NEVER) return PredicateUtil.NEVER; } return new Predicate() { @Override public boolean evaluate(T subject) { return lhs.evaluate(subject) ^ rhs.evaluate(subject); } @Override public String toString() { return lhs + " ^ " + rhs; } }; } /** * @return A {@link Predicate} which evaluates to {@code true} iff either the lhs evaluates to {@code * true} and rhs is {@code false}, or the lhs evaluates to {@code false} and * rhs is {@code true} */ @SuppressWarnings("unchecked") public static Predicate xor(Predicate lhs, boolean rhs) { return rhs ? PredicateUtil.not(lhs) : (Predicate) lhs; } /** * @return A {@link Predicate} which evaluates to {@code true} iff either lhs is {@code true} and the * rhs evaluates to {@code false}, or the lhs is {@code false} and the * rhs evaluates to {@code true} */ @SuppressWarnings("unchecked") public static Predicate xor(boolean lhs, Predicate rhs) { return lhs ? PredicateUtil.not(rhs) : (Predicate) rhs; } /** * @return A {@link Predicate} which evaluates to {@code true} iff the delegate evaluates to {@code * false} */ public static Predicate not(final Predicate delegate) { if (delegate == PredicateUtil.NEVER) return PredicateUtil.always(); if (delegate == PredicateUtil.ALWAYS) return PredicateUtil.never(); return new Predicate() { @Override public boolean evaluate(T subject) { return !delegate.evaluate(subject); } @Override public String toString() { return "!" + delegate; } }; } /** * Shorthand for "{@link #always(boolean) always}{@code (}value{@code )}". * * @return A {@link Predicate} which evaluates to the negation of the value (regardless of the subject) */ public static Predicate not(boolean value) { return PredicateUtil.always(!value); } /** * @return A {@link Predicate} which evaluates to {@code true} for any subject that is less than the * other */ public static > Predicate less(final C other) { return new Predicate() { @Override public boolean evaluate(C subject) { return other.compareTo(subject) > 0; } @Override public String toString() { return "< " + other; } }; } /** * @return A {@link Predicate} which evaluates to {@code true} for any given subject that is less than or * equal to the other */ public static > Predicate lessEqual(final C other) { return new Predicate() { @Override public boolean evaluate(C subject) { return other.compareTo(subject) >= 0; } @Override public String toString() { return "<= " + other; } }; } /** * @return A {@link Predicate} which evaluates to {@code true} for any given subject that is greater * than the other */ public static > Predicate greater(final C other) { return new Predicate() { @Override public boolean evaluate(C subject) { return other.compareTo(subject) < 0; } @Override public String toString() { return "> " + other; } }; } /** * @return A {@link Predicate} which evaluates to {@code true} for any given subject that is greater * than or equal to the other */ public static > Predicate greaterEqual(final C other) { return new Predicate() { @Override public boolean evaluate(C subject) { return other.compareTo(subject) <= 0; } @Override public String toString() { return ">= " + other; } }; } /** * @return A {@link Predicate} which evaluates to {@code true} for any given * subject that is (arithmetically) equal to the other * @see Comparable#compareTo(Object) */ public static > Predicate equal(final C other) { return new Predicate() { @Override public boolean evaluate(C subject) { return other.compareTo(subject) == 0; } @Override public String toString() { return "== " + other; } }; } /** * @return A {@link Predicate} which evaluates to {@code true} for any given * subject that is (arithmetically) not equal to the other * @see Comparable#compareTo(Object) */ public static > Predicate notEqual(final C other) { return new Predicate() { @Override public boolean evaluate(C subject) { return other.compareTo(subject) != 0; } @Override public String toString() { return "!= " + other; } }; } /** * @return A predicate that evaluates to "min {@code <=} subject <= max", or, if * min {@code >} max, to "subject {@code >=} min {@code ||} * subject {@code <=} max" */ public static > Predicate between(final C min, final C max) { return ( max.compareTo(min) >= 0 ? new Predicate() { @Override public boolean evaluate(C subject) { return min.compareTo(subject) <= 0 && max.compareTo(subject) >= 0; } @Override public String toString() { return min + "-" + max; } } : new Predicate() { @Override public boolean evaluate(C subject) { return min.compareTo(subject) >= 0 || max.compareTo(subject) <= 0; } @Override public String toString() { return min + "-" + max; } } ); } /** * Value equality, as opposed to arithmetical equality. * * @see #equal(Comparable) */ public static Predicate equal(final T other) { return new Predicate() { @Override public boolean evaluate(T subject) { return other.equals(subject); } @Override public String toString() { return "eq " + other; } }; } /** Value inequality. */ public static Predicate notEqual(final T other) { return new Predicate() { @Override public boolean evaluate(T subject) { return !other.equals(subject); } @Override public String toString() { return "nq " + other; } }; } /** * Returns a "{@link Predicate}{@code }" that evaluates to {@code true} iff the current time is after the * given expirationTime (in milliseconds). *

* (The returned predicate ignores its subject argument.) *

* * @param expirationTime Milliseconds since Jan 1 1970, UTC * @deprecated Use "{@link PredicateUtil}{@code .}{@link PredicateUtil#ignoreSubject(Producer) * ignoreSubject}{@code (}{@link ProducerUtil}{@code .}{@link ProducerUtil#after(long) * after}{@code (}expirationTime{@code ))}" instead */ @Deprecated public static Predicate after(final long expirationTime) { return PredicateUtil.ignoreSubject(ProducerUtil.after(expirationTime)); } /** * Returns a predicate that evaluates the format against the delegate after each "*" in the * format has been replaced with the subject. */ public static > T forString(final String format, final T delegate) { @SuppressWarnings("unchecked") T result = (T) new Predicate() { @Override public boolean evaluate(String subject) { return delegate.evaluate(format.replace("*", subject)); } }; return result; } /** * Converts a {@link Predicate} into a {@link PredicateWhichThrows}, which is possible iff the source's element * type is a subclass of the target's element type. * * @param The subject type * @param The target predicate's exception */ public static PredicateWhichThrows asPredicateWhichThrows(final Predicate source) { return new PredicateWhichThrows() { @Override public boolean evaluate(T subject) { return source.evaluate(subject); } }; } /** * Converts a {@link PredicateWhichThrows} into a {@link Predicate}, which is possible iff the source's exception * is a subclass of {@link RuntimeException} and the source's element type is a subclass of the target's element * type. * * @param The predicate subject type * @param The source predicate's exception */ public static Predicate asPredicate(final PredicateWhichThrows source) { return new Predicate() { @Override public boolean evaluate(T subject) { return source.evaluate(subject); } }; } /** * @return A predicate which checks whether the given collection contains the subject */ public static Predicate contains(final Collection collection) { return new Predicate() { @Override public boolean evaluate(T subject) { return collection.contains(subject); } }; } /** * @return A {@link Predicate} that evaluates to {@code true} iff the map contains a key equal to the * predicate subject */ public static Predicate containsKey(final Map map) { return new Predicate() { @Override public boolean evaluate(K subject) { return map.containsKey(subject); } }; } /** * @return A {@link Predicate} that evaluates to {@code true} iff the mapping contains a key equal to the * predicate subject */ public static Predicate containsKey(final Mapping mapping) { return new Predicate() { @Override public boolean evaluate(K subject) { return mapping.containsKey(subject); } }; } /** * @return A predicate which, when evaluated, ignores its subject, and returns the next product * of the delegate */ public static PredicateWhichThrows ignoreSubject(final ProducerWhichThrows delegate) { return new PredicateWhichThrows() { @Override public boolean evaluate(T subject) throws EX { Boolean b = delegate.produce(); return b != null && b; } }; } /** * @return A predicate which, when evaluated, ignores its subject, and returns the next product * of the delegate */ public static Predicate ignoreSubject(final Producer delegate) { return new Predicate() { @Override public boolean evaluate(T subject) { Boolean b = delegate.produce(); return b != null && b; } }; } /** * Wraps the delegate such that its declared exception is caught, ignored, and the * defaultValue is returned. */ public static Predicate ignoreExceptions( final Class exceptionClass, final PredicateWhichThrows delegate, final boolean defaultValue ) { return new Predicate() { @Override public boolean evaluate(T subject) { try { return delegate.evaluate(subject); } catch (RuntimeException re) { if (!exceptionClass.isAssignableFrom(re.getClass())) throw re; } catch (Error e) { // SUPPRESS CHECKSTYLE IllegalCatch if (!exceptionClass.isAssignableFrom(e.getClass())) throw e; } catch (Throwable t) { // SUPPRESS CHECKSTYLE IllegalCatch assert exceptionClass.isAssignableFrom(t.getClass()); } return defaultValue; } }; } /** * Creates and returns a proxy to the delegate with a synchronized {@link * PredicateWhichThrows#evaluate(Object) evaluate()} method. * * @see PredicateWhichThrows */ public static PredicateWhichThrows synchronizedPredicate(final PredicateWhichThrows delegate) { return new PredicateWhichThrows() { @Override public synchronized boolean evaluate(T subject) throws EX { return delegate.evaluate(subject); } }; } }