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 super T> lhs, final Predicate super T> 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 super T> 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 super T> 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 super T> lhs, final Predicate super T> 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 super T, ? extends EX>
or(
final PredicateWhichThrows super T, ? extends EX> lhs,
final PredicateWhichThrows super T, ? extends EX> 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 super T> 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 super T> 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 super T> lhs, final Predicate super T> 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 super T> 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 super T> 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 super T> 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