--- /dev/null 2011-08-08 08:40:49.685541141 -0700 +++ new/src/share/classes/java/util/functions/Predicates.java 2011-08-09 10:55:28.000000000 -0700 @@ -0,0 +1,648 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util.functions; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +/** + * Static utility methods pertaining to {@code Predicate} instances. + * + *

All of the returned predicates are serializable if given serializable + * parameters. + */ +public final class Predicates { + + /** + * a predicate that evaluates to {@code true} if the reference + * being tested is {@code null}. + */ + public static final Predicate IS_NULL = #{Object t -> t == null}; + + /** + * a predicate that evaluates to {@code true} if the reference + * being tested is not {@code null}. + */ + public static final Predicate NON_NULL = #{Object t -> t != null}; + + /** + * a predicate who's result is always {@code false}. + */ + public static final Predicate FALSE = #{Object t -> false}; + + + /** + * a predicate who's result is always {@code true}. + */ + public static final Predicate TRUE = #{Object t -> true}; + + /** + * singleton utils + */ + private Predicates() { + throw new AssertionError("No instances!"); + } + + /** + * Returns a predicate that evaluates to {@code true} if the reference + * being tested is {@code null}. + * + * @return a predicate that evaluates to {@code true} if the reference + * being tested is {@code null} + */ + public static Predicate isNull() { + return (Predicate) IS_NULL; + } + + /** + * Returns a predicate that evaluates to {@code true} if the reference + * being tested is non-{@code null}. + * + * @return a predicate that evaluates to {@code true} if the reference + * being tested is is non-{@code null} + */ + public static Predicate nonNull() { + return (Predicate) NON_NULL; + } + + /** + * Returns a predicate who's result is always {@code false}. + * + * @return a predicate who's result is always {@code false}. + */ + public static Predicate alwaysFalse() { + return (Predicate) FALSE; + } + + /** + * Returns a predicate who's result is always {@code true}. + * + * @return a predicate who's result is always {@code true}. + */ + public static Predicate alwaysTrue() { + return (Predicate) TRUE; + } + + /** + * Returns a predicate that evaluates to {@code true} if the object being + * tested is an instance of the provided class. If the object being tested + * is {@code null} this predicate evaluates to {@code false}. + * + * @param clazz The target class to be matched by the predicate. + * @return a predicate that evaluates to {@code true} if the object being + * tested is an instance of the provided class + */ + public static Predicate instanceOf(Class clazz) { + return #{Object o -> clazz.isInstance(o)}; + } + + /** + * Returns a predicate that who's result is {@code target == object}. + * + * @param the type of predicate values. + * @param t The target value to be compared for identity equality. + * @return a predicate that who's result is {@code target == object} + */ + public static Predicate isSame(T target) { + return #{T t -> t == target}; + } + + /** + * Returns a predicate who's result matches + * {@code Objects.equals(target, t)}. + * + * @param the type of predicate values. + * @param t The target value to be compared for equality. + * @return a predicate who's result matches {@code Objects.equals(target, t)} + */ + public static Predicate isEqual(T target) { + if (null == target) + return Predicates.isNull(); + else + return #{T t -> target.equals(t)}; + } + + /** + * Creates a predicate that evaluates to {@code true} if the tested object + * is a member of the provided collection. The collection is not defensively + * copied so changes to it will alter the behavior of the predicate. + * + * @param Type of predicate values. + * @param target the collection against which objects will be tested. + * @return a predicate that evaluates to {@code true} if the tested object + * is a member of the provided collection. The collection is not defensively + * copied so changes to it will alter the behavior of the predicate. + */ + public static Predicate contains(Collection target) { + return #{T t -> target.contains(t)}; + } + + /** + * Creates a predicate that is a composition of a mapper and a predicate. + * The returned predicate's result is {@code predicate.eval(mapper.map(t))}. + * + * @return the composition of the provided mapper and predicate + */ + public static Predicate compose( + Predicate predicate, Mapper mapper) { + return #{T t -> predicate.eval(mapper.map(t))}; + } + + /** + * Returns a predicate that evaluates to {@code true} if the provided + * predicate evaluates to {@code false} + * + * @param the type of values evaluated by the predicate. + * @param predicate The predicate to be evaluated. + * @return A predicate who's result is the logical inverse of the provided + * predicate. + */ + public static > Predicate negate( + P predicate) { + return #{T t -> !predicate.eval(t)}; + } + + /** + * Returns a predicate that evaluates to {@code true} if all of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will terminate upon the first + * {@code false} predicate. + * + * @param the type of values evaluated by the predicates. + * @param first initial component predicate to be evaluated. + * @param second additional component predicate to be evaluated. + * @return A predicate who's result is {@code true} iff all component + * predicates are {@code true}. + */ + public static > Predicate and( + Predicate first, P second) { + if((null != first) && (first == second)) { + return (Predicate) first; + } + + Objects.requireNonNull(first); + Objects.requireNonNull(second); + + return #{T t -> first.eval(t) && second.eval(t)}; + } + + /** + * Returns a predicate that evaluates to {@code true} if all of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end upon the first + * {@code false} predicate. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. + * @return A predicate who's result is {@code true} iff all component + * predicates are {@code true}. + */ + public static > Predicate and( + Iterable

components) { + List

predicates = safeCopyOf(components); + if(predicates.isEmpty()) { + throw new IllegalArgumentException("no predicates"); + } + + return #{T t -> + for(P predicate : predicates) { + if(!predicate.eval(t)) { + return false; + } + } + return true;}; + } + + /** + * Returns a predicate that evaluates to {@code true} if all of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end upon the first + * {@code false} predicate. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. + * @return A predicate who's result is {@code true} iff all component + * predicates are {@code true}. + */ + static > Predicate and( + P first, Iterable

components) { + List

predicates = safeCopyOf(first, components); + + return #{T t -> + for(P predicate : predicates) { + if(!predicate.eval(t)) { + return false; + } + } + return true;}; + } + + /** + * Returns a predicate that evaluates to {@code true} if all of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end upon the first + * {@code false} predicate. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return A predicate who's result is {@code true} iff all component + * predicates are {@code true}. + */ + @SafeVarargs + public static > Predicate and( + P... components) { + P[] predicates = safeCopyOf(components); + if(0 == predicates.length) { + throw new IllegalArgumentException("no predicates"); + } + + return #{T t -> + for(P predicate : predicates) { + if(!predicate.eval(t)) { + return false; + } + } + return true;}; + } + /** + * Returns a predicate that evaluates to {@code true} if all of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end upon the first + * {@code false} predicate. + * + * @param the type of values evaluated by the predicates. + * @param first first predicate to be evaluated. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return A predicate who's result is {@code true} iff all component + * predicates are {@code true}. + */ + @SafeVarargs + static > Predicate and( + P first, P... components) { + P[] predicates = safeCopyOf(first, components); + if(0 == predicates.length) { + throw new IllegalArgumentException("no predicates"); + } + + return #{T t -> + for(P predicate : predicates) { + if(!predicate.eval(t)) { + return false; + } + } + return true;}; + } + + /** + * Returns a predicate that evaluates to {@code true} if any of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end upon the first + * {@code true} predicate. + * + * @param the type of values evaluated by the predicates. + * @param first initial component predicate to be evaluated. + * @param second additional component predicate to be evaluated. + * @return A predicate who's result is {@code true} if any component + * predicate's result is {@code true}. + */ + public static > Predicate or( + Predicate first, P second) { + if((null != first) && (first == second)) { + return first; + } + + Objects.requireNonNull(first); + Objects.requireNonNull(second); + + return #{T t -> first.eval(t) || second.eval(t)}; + } + + /** + * Returns a predicate that evaluates to {@code true} if any of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end upon the first + * {@code true} predicate. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return A predicate who's result is {@code true} if any component + * predicate's result is {@code true}. + */ + public static > Predicate or( + Iterable

components) { + List

predicates = safeCopyOf(components); + if(predicates.isEmpty()) { + throw new IllegalArgumentException("no predicates"); + } + + return #{T t -> + for(P predicate : predicates) { + if(predicate.eval(t)) { + return true; + } + } + return false;}; + } + + /** + * Returns a predicate that evaluates to {@code true} if any of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end upon the first + * {@code true} predicate. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return A predicate who's result is {@code true} if any component + * predicate's result is {@code true}. + */ + static > Predicate or( + P first, Iterable

components) { + List

predicates = safeCopyOf(first, components); + + return #{T t -> + for(P predicate : predicates) { + if(predicate.eval(t)) { + return true; + } + } + return false;}; + } + + /** + * Returns a predicate that evaluates to {@code true} if any of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will terminate upon the first + * {@code true} predicate. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return A predicate who's result is {@code true} if any component + * predicate's result is {@code true}. + */ + @SafeVarargs + public static > Predicate or( + P... components) { + P[] predicates = safeCopyOf(components); + if(0 == predicates.length) { + throw new IllegalArgumentException("no predicates"); + } + + return #{T t -> + for(P predicate : predicates) { + if(predicate.eval(t)) { + return true; + } + } + return false;}; + } + + /** + * Returns a predicate that evaluates to {@code true} if any of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will terminate upon the first + * {@code true} predicate. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return A predicate who's result is {@code true} if any component + * predicate's result is {@code true}. + */ + @SafeVarargs + static > Predicate or( + Predicate first, P... components) { + P[] predicates = safeCopyOf((P) first, components); + + return #{T t -> + for(P predicate : predicates) { + if(predicate.eval(t)) { + return true; + } + } + return false;}; + } + + /** + * Returns a predicate that evaluates to {@code true} if all or none of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end if a predicate result + * fails to match the first predicate's result. + * + * @param the type of values evaluated by the predicates. + * @param first initial component predicate to be evaluated. + * @param second additional component predicate to be evaluated. + * @return a predicate that evaluates to {@code true} if all or none of the + * component predicates evaluate to {@code true} + */ + public static > Predicate xor( + Predicate first, P second) { + if((null != first) && (first == second)) { + return #{T t -> false}; + } + + Objects.requireNonNull(first); + Objects.requireNonNull(second); + + return #{T t -> first.eval(t) ^ second.eval(t)}; + } + + /** + * Returns a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end if a predicate result + * fails to match the first predicate's result. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true} + */ + public static > Predicate xor( + Iterable

components) { + List

predicates = safeCopyOf(components); + if(predicates.isEmpty()) { + throw new IllegalArgumentException("no predicates"); + } + + return #{T t -> + Boolean initial = null; + for (P predicate : predicates) { + if (null == initial) { + initial = predicate.eval(t); + } else { + if (!(initial ^ predicate.eval(t))) { + return true; + } + } + } + return false;}; + } + + /** + * Returns a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will terminate if a predicate result + * fails to match the first predicate's result. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true} + */ + @SafeVarargs + public static > Predicate xor(P... components) { + P[] predicates = safeCopyOf(components); + if(0 == predicates.length) { + throw new IllegalArgumentException("no predicates"); + } + + return #{T t -> + Boolean initial = null; + for (P predicate : predicates) { + if (null == initial) { + initial = predicate.eval(t); + } else { + if (!(initial ^ predicate.eval(t))) { + return true; + } + } + } + return false;}; + } + + /** + * Returns a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end if a predicate result + * fails to match the first predicate's result. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true} + */ + @SafeVarargs + static > Predicate xor( + Predicate first, + P... components) { + P[] predicates = safeCopyOf((P) first, components); + + return #{T t -> + Boolean initial = null; + for (P predicate : predicates) { + if (null == initial) { + initial = predicate.eval(t); + } else { + if (!(initial ^ predicate.eval(t))) { + return true; + } + } + } + return false;}; + } + + /** + * Returns a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true}. The components are + * evaluated in order, and evaluation will end if a predicate result + * fails to match the first predicate's result. + * + * @param the type of values evaluated by the predicates. + * @param components The predicates to be evaluated. A copy is made of the + * components. + * @return a predicate that evaluates to {@code false} if all or none of the + * component predicates evaluate to {@code true} + */ + static > Predicate xor( + Predicate first, + Iterable

components) { + List

predicates = safeCopyOf((P) first, components); + + return #{T t -> + Boolean initial = null; + for (P predicate : predicates) { + if (null == initial) { + initial = predicate.eval(t); + } else { + if (!(initial ^ predicate.eval(t))) { + return true; + } + } + } + return false;}; + } + + // XXX mduigou These need to be moved somewhere. + + @SafeVarargs + static T[] safeCopyOf(T... array) { + T[] copy = Arrays.copyOf(array, array.length); + for(T each : copy) { + Objects.requireNonNull(each); + } + return copy; + } + + @SafeVarargs + static T[] safeCopyOf(T first, T... array) { + T[] copy = (T[]) Array.newInstance(array.getClass().getComponentType(), array.length + 1); + copy[0] = Objects.requireNonNull(first); + System.arraycopy(array, 0, copy, 1, array.length); + for(T each : copy) { + Objects.requireNonNull(each); + } + return copy; + } + + static List safeCopyOf(T first, Iterable iterable) { + ArrayList list = new ArrayList<>(); + list.add(Objects.requireNonNull(first)); + + for (T element : iterable) { + list.add(Objects.requireNonNull(element)); + } + return list; + } + + static List safeCopyOf(Iterable iterable) { + ArrayList list = new ArrayList<>(); + for (T element : iterable) { + list.add(Objects.requireNonNull(element)); + } + return list; + } +}