| /* |
| * Copyright (C) 2007 The Guava Authors |
| * |
| * 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.google.common.base; |
| |
| import static com.google.common.base.Preconditions.checkNotNull; |
| |
| import com.google.common.annotations.Beta; |
| import com.google.common.annotations.GwtCompatible; |
| import com.google.common.annotations.GwtIncompatible; |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.regex.Pattern; |
| import org.checkerframework.checker.nullness.compatqual.NullableDecl; |
| |
| /** |
| * Static utility methods pertaining to {@code Predicate} instances. |
| * |
| * <p>All methods return serializable predicates as long as they're given serializable parameters. |
| * |
| * <p>See the Guava User Guide article on <a |
| * href="https://github.com/google/guava/wiki/FunctionalExplained">the use of {@code Predicate}</a>. |
| * |
| * @author Kevin Bourrillion |
| * @since 2.0 |
| */ |
| @GwtCompatible(emulated = true) |
| public final class Predicates { |
| private Predicates() {} |
| |
| // TODO(kevinb): considering having these implement a VisitablePredicate |
| // interface which specifies an accept(PredicateVisitor) method. |
| |
| /** Returns a predicate that always evaluates to {@code true}. */ |
| @GwtCompatible(serializable = true) |
| public static <T> Predicate<T> alwaysTrue() { |
| return ObjectPredicate.ALWAYS_TRUE.withNarrowedType(); |
| } |
| |
| /** Returns a predicate that always evaluates to {@code false}. */ |
| @GwtCompatible(serializable = true) |
| public static <T> Predicate<T> alwaysFalse() { |
| return ObjectPredicate.ALWAYS_FALSE.withNarrowedType(); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the object reference being tested is |
| * null. |
| */ |
| @GwtCompatible(serializable = true) |
| public static <T> Predicate<T> isNull() { |
| return ObjectPredicate.IS_NULL.withNarrowedType(); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the object reference being tested is not |
| * null. |
| */ |
| @GwtCompatible(serializable = true) |
| public static <T> Predicate<T> notNull() { |
| return ObjectPredicate.NOT_NULL.withNarrowedType(); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the given predicate evaluates to {@code |
| * false}. |
| */ |
| public static <T> Predicate<T> not(Predicate<T> predicate) { |
| return new NotPredicate<T>(predicate); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if each of its components evaluates to |
| * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited" |
| * as soon as a false predicate is found. It defensively copies the iterable passed in, so future |
| * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the |
| * returned predicate will always evaluate to {@code true}. |
| */ |
| public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) { |
| return new AndPredicate<T>(defensiveCopy(components)); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if each of its components evaluates to |
| * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited" |
| * as soon as a false predicate is found. It defensively copies the array passed in, so future |
| * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the |
| * returned predicate will always evaluate to {@code true}. |
| */ |
| @SafeVarargs |
| public static <T> Predicate<T> and(Predicate<? super T>... components) { |
| return new AndPredicate<T>(defensiveCopy(components)); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if both of its components evaluate to {@code |
| * true}. The components are evaluated in order, and evaluation will be "short-circuited" as soon |
| * as a false predicate is found. |
| */ |
| public static <T> Predicate<T> and(Predicate<? super T> first, Predicate<? super T> second) { |
| return new AndPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second))); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if any one of its components evaluates to |
| * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited" |
| * as soon as a true predicate is found. It defensively copies the iterable passed in, so future |
| * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the |
| * returned predicate will always evaluate to {@code false}. |
| */ |
| public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) { |
| return new OrPredicate<T>(defensiveCopy(components)); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if any one of its components evaluates to |
| * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited" |
| * as soon as a true predicate is found. It defensively copies the array passed in, so future |
| * changes to it won't alter the behavior of this predicate. If {@code components} is empty, the |
| * returned predicate will always evaluate to {@code false}. |
| */ |
| @SafeVarargs |
| public static <T> Predicate<T> or(Predicate<? super T>... components) { |
| return new OrPredicate<T>(defensiveCopy(components)); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if either of its components evaluates to |
| * {@code true}. The components are evaluated in order, and evaluation will be "short-circuited" |
| * as soon as a true predicate is found. |
| */ |
| public static <T> Predicate<T> or(Predicate<? super T> first, Predicate<? super T> second) { |
| return new OrPredicate<T>(Predicates.<T>asList(checkNotNull(first), checkNotNull(second))); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the object being tested {@code equals()} |
| * the given target or both are null. |
| */ |
| public static <T> Predicate<T> equalTo(@NullableDecl T target) { |
| return (target == null) ? Predicates.<T>isNull() : new IsEqualToPredicate<T>(target); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the object being tested is an instance of |
| * the given class. If the object being tested is {@code null} this predicate evaluates to {@code |
| * false}. |
| * |
| * <p>If you want to filter an {@code Iterable} to narrow its type, consider using {@link |
| * com.google.common.collect.Iterables#filter(Iterable, Class)} in preference. |
| * |
| * <p><b>Warning:</b> contrary to the typical assumptions about predicates (as documented at |
| * {@link Predicate#apply}), the returned predicate may not be <i>consistent with equals</i>. For |
| * example, {@code instanceOf(ArrayList.class)} will yield different results for the two equal |
| * instances {@code Lists.newArrayList(1)} and {@code Arrays.asList(1)}. |
| */ |
| @GwtIncompatible // Class.isInstance |
| public static Predicate<Object> instanceOf(Class<?> clazz) { |
| return new InstanceOfPredicate(clazz); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the class being tested is assignable to |
| * (is a subtype of) {@code clazz}. Example: |
| * |
| * <pre>{@code |
| * List<Class<?>> classes = Arrays.asList( |
| * Object.class, String.class, Number.class, Long.class); |
| * return Iterables.filter(classes, subtypeOf(Number.class)); |
| * }</pre> |
| * |
| * The code above returns an iterable containing {@code Number.class} and {@code Long.class}. |
| * |
| * @since 20.0 (since 10.0 under the incorrect name {@code assignableFrom}) |
| */ |
| @GwtIncompatible // Class.isAssignableFrom |
| @Beta |
| public static Predicate<Class<?>> subtypeOf(Class<?> clazz) { |
| return new SubtypeOfPredicate(clazz); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the object reference being tested is a |
| * member of the given collection. It does not defensively copy the collection passed in, so |
| * future changes to it will alter the behavior of the predicate. |
| * |
| * <p>This method can technically accept any {@code Collection<?>}, but using a typed collection |
| * helps prevent bugs. This approach doesn't block any potential users since it is always possible |
| * to use {@code Predicates.<Object>in()}. |
| * |
| * @param target the collection that may contain the function input |
| */ |
| public static <T> Predicate<T> in(Collection<? extends T> target) { |
| return new InPredicate<T>(target); |
| } |
| |
| /** |
| * Returns the composition of a function and a predicate. For every {@code x}, the generated |
| * predicate returns {@code predicate(function(x))}. |
| * |
| * @return the composition of the provided function and predicate |
| */ |
| public static <A, B> Predicate<A> compose( |
| Predicate<B> predicate, Function<A, ? extends B> function) { |
| return new CompositionPredicate<>(predicate, function); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the {@code CharSequence} being tested |
| * contains any match for the given regular expression pattern. The test used is equivalent to |
| * {@code Pattern.compile(pattern).matcher(arg).find()} |
| * |
| * @throws IllegalArgumentException if the pattern is invalid |
| * @since 3.0 |
| */ |
| @GwtIncompatible // Only used by other GWT-incompatible code. |
| public static Predicate<CharSequence> containsPattern(String pattern) { |
| return new ContainsPatternFromStringPredicate(pattern); |
| } |
| |
| /** |
| * Returns a predicate that evaluates to {@code true} if the {@code CharSequence} being tested |
| * contains any match for the given regular expression pattern. The test used is equivalent to |
| * {@code pattern.matcher(arg).find()} |
| * |
| * @since 3.0 |
| */ |
| @GwtIncompatible(value = "java.util.regex.Pattern") |
| public static Predicate<CharSequence> contains(Pattern pattern) { |
| return new ContainsPatternPredicate(new JdkPattern(pattern)); |
| } |
| |
| // End public API, begin private implementation classes. |
| |
| // Package private for GWT serialization. |
| enum ObjectPredicate implements Predicate<Object> { |
| /** @see Predicates#alwaysTrue() */ |
| ALWAYS_TRUE { |
| @Override |
| public boolean apply(@NullableDecl Object o) { |
| return true; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.alwaysTrue()"; |
| } |
| }, |
| /** @see Predicates#alwaysFalse() */ |
| ALWAYS_FALSE { |
| @Override |
| public boolean apply(@NullableDecl Object o) { |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.alwaysFalse()"; |
| } |
| }, |
| /** @see Predicates#isNull() */ |
| IS_NULL { |
| @Override |
| public boolean apply(@NullableDecl Object o) { |
| return o == null; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.isNull()"; |
| } |
| }, |
| /** @see Predicates#notNull() */ |
| NOT_NULL { |
| @Override |
| public boolean apply(@NullableDecl Object o) { |
| return o != null; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.notNull()"; |
| } |
| }; |
| |
| @SuppressWarnings("unchecked") // safe contravariant cast |
| <T> Predicate<T> withNarrowedType() { |
| return (Predicate<T>) this; |
| } |
| } |
| |
| /** @see Predicates#not(Predicate) */ |
| private static class NotPredicate<T> implements Predicate<T>, Serializable { |
| final Predicate<T> predicate; |
| |
| NotPredicate(Predicate<T> predicate) { |
| this.predicate = checkNotNull(predicate); |
| } |
| |
| @Override |
| public boolean apply(@NullableDecl T t) { |
| return !predicate.apply(t); |
| } |
| |
| @Override |
| public int hashCode() { |
| return ~predicate.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof NotPredicate) { |
| NotPredicate<?> that = (NotPredicate<?>) obj; |
| return predicate.equals(that.predicate); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.not(" + predicate + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#and(Iterable) */ |
| private static class AndPredicate<T> implements Predicate<T>, Serializable { |
| private final List<? extends Predicate<? super T>> components; |
| |
| private AndPredicate(List<? extends Predicate<? super T>> components) { |
| this.components = components; |
| } |
| |
| @Override |
| public boolean apply(@NullableDecl T t) { |
| // Avoid using the Iterator to avoid generating garbage (issue 820). |
| for (int i = 0; i < components.size(); i++) { |
| if (!components.get(i).apply(t)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| // add a random number to avoid collisions with OrPredicate |
| return components.hashCode() + 0x12472c2c; |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof AndPredicate) { |
| AndPredicate<?> that = (AndPredicate<?>) obj; |
| return components.equals(that.components); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return toStringHelper("and", components); |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#or(Iterable) */ |
| private static class OrPredicate<T> implements Predicate<T>, Serializable { |
| private final List<? extends Predicate<? super T>> components; |
| |
| private OrPredicate(List<? extends Predicate<? super T>> components) { |
| this.components = components; |
| } |
| |
| @Override |
| public boolean apply(@NullableDecl T t) { |
| // Avoid using the Iterator to avoid generating garbage (issue 820). |
| for (int i = 0; i < components.size(); i++) { |
| if (components.get(i).apply(t)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| // add a random number to avoid collisions with AndPredicate |
| return components.hashCode() + 0x053c91cf; |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof OrPredicate) { |
| OrPredicate<?> that = (OrPredicate<?>) obj; |
| return components.equals(that.components); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return toStringHelper("or", components); |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| private static String toStringHelper(String methodName, Iterable<?> components) { |
| StringBuilder builder = new StringBuilder("Predicates.").append(methodName).append('('); |
| boolean first = true; |
| for (Object o : components) { |
| if (!first) { |
| builder.append(','); |
| } |
| builder.append(o); |
| first = false; |
| } |
| return builder.append(')').toString(); |
| } |
| |
| /** @see Predicates#equalTo(Object) */ |
| private static class IsEqualToPredicate<T> implements Predicate<T>, Serializable { |
| private final T target; |
| |
| private IsEqualToPredicate(T target) { |
| this.target = target; |
| } |
| |
| @Override |
| public boolean apply(T t) { |
| return target.equals(t); |
| } |
| |
| @Override |
| public int hashCode() { |
| return target.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof IsEqualToPredicate) { |
| IsEqualToPredicate<?> that = (IsEqualToPredicate<?>) obj; |
| return target.equals(that.target); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.equalTo(" + target + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#instanceOf(Class) */ |
| @GwtIncompatible // Class.isInstance |
| private static class InstanceOfPredicate implements Predicate<Object>, Serializable { |
| private final Class<?> clazz; |
| |
| private InstanceOfPredicate(Class<?> clazz) { |
| this.clazz = checkNotNull(clazz); |
| } |
| |
| @Override |
| public boolean apply(@NullableDecl Object o) { |
| return clazz.isInstance(o); |
| } |
| |
| @Override |
| public int hashCode() { |
| return clazz.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof InstanceOfPredicate) { |
| InstanceOfPredicate that = (InstanceOfPredicate) obj; |
| return clazz == that.clazz; |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.instanceOf(" + clazz.getName() + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#subtypeOf(Class) */ |
| @GwtIncompatible // Class.isAssignableFrom |
| private static class SubtypeOfPredicate implements Predicate<Class<?>>, Serializable { |
| private final Class<?> clazz; |
| |
| private SubtypeOfPredicate(Class<?> clazz) { |
| this.clazz = checkNotNull(clazz); |
| } |
| |
| @Override |
| public boolean apply(Class<?> input) { |
| return clazz.isAssignableFrom(input); |
| } |
| |
| @Override |
| public int hashCode() { |
| return clazz.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof SubtypeOfPredicate) { |
| SubtypeOfPredicate that = (SubtypeOfPredicate) obj; |
| return clazz == that.clazz; |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.subtypeOf(" + clazz.getName() + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#in(Collection) */ |
| private static class InPredicate<T> implements Predicate<T>, Serializable { |
| private final Collection<?> target; |
| |
| private InPredicate(Collection<?> target) { |
| this.target = checkNotNull(target); |
| } |
| |
| @Override |
| public boolean apply(@NullableDecl T t) { |
| try { |
| return target.contains(t); |
| } catch (NullPointerException | ClassCastException e) { |
| return false; |
| } |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof InPredicate) { |
| InPredicate<?> that = (InPredicate<?>) obj; |
| return target.equals(that.target); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return target.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.in(" + target + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#compose(Predicate, Function) */ |
| private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable { |
| final Predicate<B> p; |
| final Function<A, ? extends B> f; |
| |
| private CompositionPredicate(Predicate<B> p, Function<A, ? extends B> f) { |
| this.p = checkNotNull(p); |
| this.f = checkNotNull(f); |
| } |
| |
| @Override |
| public boolean apply(@NullableDecl A a) { |
| return p.apply(f.apply(a)); |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof CompositionPredicate) { |
| CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj; |
| return f.equals(that.f) && p.equals(that.p); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return f.hashCode() ^ p.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| // TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)") |
| return p + "(" + f + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#contains(Pattern) */ |
| @GwtIncompatible // Only used by other GWT-incompatible code. |
| private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable { |
| final CommonPattern pattern; |
| |
| ContainsPatternPredicate(CommonPattern pattern) { |
| this.pattern = checkNotNull(pattern); |
| } |
| |
| @Override |
| public boolean apply(CharSequence t) { |
| return pattern.matcher(t).find(); |
| } |
| |
| @Override |
| public int hashCode() { |
| // Pattern uses Object.hashCode, so we have to reach |
| // inside to build a hashCode consistent with equals. |
| |
| return Objects.hashCode(pattern.pattern(), pattern.flags()); |
| } |
| |
| @Override |
| public boolean equals(@NullableDecl Object obj) { |
| if (obj instanceof ContainsPatternPredicate) { |
| ContainsPatternPredicate that = (ContainsPatternPredicate) obj; |
| |
| // Pattern uses Object (identity) equality, so we have to reach |
| // inside to compare individual fields. |
| return Objects.equal(pattern.pattern(), that.pattern.pattern()) |
| && pattern.flags() == that.pattern.flags(); |
| } |
| return false; |
| } |
| |
| @Override |
| public String toString() { |
| String patternString = |
| MoreObjects.toStringHelper(pattern) |
| .add("pattern", pattern.pattern()) |
| .add("pattern.flags", pattern.flags()) |
| .toString(); |
| return "Predicates.contains(" + patternString + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| /** @see Predicates#containsPattern(String) */ |
| @GwtIncompatible // Only used by other GWT-incompatible code. |
| private static class ContainsPatternFromStringPredicate extends ContainsPatternPredicate { |
| |
| ContainsPatternFromStringPredicate(String string) { |
| super(Platform.compilePattern(string)); |
| } |
| |
| @Override |
| public String toString() { |
| return "Predicates.containsPattern(" + pattern.pattern() + ")"; |
| } |
| |
| private static final long serialVersionUID = 0; |
| } |
| |
| private static <T> List<Predicate<? super T>> asList( |
| Predicate<? super T> first, Predicate<? super T> second) { |
| // TODO(kevinb): understand why we still get a warning despite @SafeVarargs! |
| return Arrays.<Predicate<? super T>>asList(first, second); |
| } |
| |
| private static <T> List<T> defensiveCopy(T... array) { |
| return defensiveCopy(Arrays.asList(array)); |
| } |
| |
| static <T> List<T> defensiveCopy(Iterable<T> iterable) { |
| ArrayList<T> list = new ArrayList<T>(); |
| for (T element : iterable) { |
| list.add(checkNotNull(element)); |
| } |
| return list; |
| } |
| } |