diff options
Diffstat (limited to 'guava/src/com/google/common/base/Predicates.java')
-rw-r--r-- | guava/src/com/google/common/base/Predicates.java | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/guava/src/com/google/common/base/Predicates.java b/guava/src/com/google/common/base/Predicates.java new file mode 100644 index 0000000..5c42c55 --- /dev/null +++ b/guava/src/com/google/common/base/Predicates.java @@ -0,0 +1,626 @@ +/* + * 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 javax.annotation.Nullable; + +/** + * Static utility methods pertaining to {@code Predicate} instances. + * + * <p>All methods returns serializable predicates as long as they're given + * serializable parameters. + * + * <p>See the Guava User Guide article on <a href= + * "http://code.google.com/p/guava-libraries/wiki/FunctionalExplained">the + * use of {@code Predicate}</a>. + * + * @author Kevin Bourrillion + * @since 2.0 (imported from Google Collections Library) + */ +@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}. + */ + 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}. + */ + 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(@Nullable 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 from the given class. The returned predicate + * does not allow null inputs. + * + * @since 10.0 + */ + @GwtIncompatible("Class.isAssignableFrom") + @Beta + public static Predicate<Class<?>> assignableFrom(Class<?> clazz) { + return new AssignableFromPredicate(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<A, B>(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 java.util.regex.PatternSyntaxException if the pattern is invalid + * @since 3.0 + */ + @GwtIncompatible(value = "java.util.regex.Pattern") + public static Predicate<CharSequence> containsPattern(String pattern) { + return new ContainsPatternPredicate(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(pattern); + } + + // End public API, begin private implementation classes. + + // Package private for GWT serialization. + enum ObjectPredicate implements Predicate<Object> { + ALWAYS_TRUE { + @Override public boolean apply(@Nullable Object o) { + return true; + } + }, + ALWAYS_FALSE { + @Override public boolean apply(@Nullable Object o) { + return false; + } + }, + IS_NULL { + @Override public boolean apply(@Nullable Object o) { + return o == null; + } + }, + NOT_NULL { + @Override public boolean apply(@Nullable Object o) { + return o != null; + } + }; + + @SuppressWarnings("unchecked") // these Object predicates work for any T + <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(T t) { + return !predicate.apply(t); + } + @Override public int hashCode() { + return ~predicate.hashCode(); + } + @Override public boolean equals(@Nullable Object obj) { + if (obj instanceof NotPredicate) { + NotPredicate<?> that = (NotPredicate<?>) obj; + return predicate.equals(that.predicate); + } + return false; + } + @Override public String toString() { + return "Not(" + predicate.toString() + ")"; + } + private static final long serialVersionUID = 0; + } + + private static final Joiner COMMA_JOINER = Joiner.on(","); + + /** @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(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(@Nullable Object obj) { + if (obj instanceof AndPredicate) { + AndPredicate<?> that = (AndPredicate<?>) obj; + return components.equals(that.components); + } + return false; + } + @Override public String toString() { + return "And(" + COMMA_JOINER.join(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(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(@Nullable Object obj) { + if (obj instanceof OrPredicate) { + OrPredicate<?> that = (OrPredicate<?>) obj; + return components.equals(that.components); + } + return false; + } + @Override public String toString() { + return "Or(" + COMMA_JOINER.join(components) + ")"; + } + private static final long serialVersionUID = 0; + } + + /** @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(@Nullable Object obj) { + if (obj instanceof IsEqualToPredicate) { + IsEqualToPredicate<?> that = (IsEqualToPredicate<?>) obj; + return target.equals(that.target); + } + return false; + } + @Override public String toString() { + return "IsEqualTo(" + 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(@Nullable Object o) { + return clazz.isInstance(o); + } + @Override public int hashCode() { + return clazz.hashCode(); + } + @Override public boolean equals(@Nullable Object obj) { + if (obj instanceof InstanceOfPredicate) { + InstanceOfPredicate that = (InstanceOfPredicate) obj; + return clazz == that.clazz; + } + return false; + } + @Override public String toString() { + return "IsInstanceOf(" + clazz.getName() + ")"; + } + private static final long serialVersionUID = 0; + } + + /** @see Predicates#assignableFrom(Class) */ + @GwtIncompatible("Class.isAssignableFrom") + private static class AssignableFromPredicate + implements Predicate<Class<?>>, Serializable { + private final Class<?> clazz; + + private AssignableFromPredicate(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(@Nullable Object obj) { + if (obj instanceof AssignableFromPredicate) { + AssignableFromPredicate that = (AssignableFromPredicate) obj; + return clazz == that.clazz; + } + return false; + } + @Override public String toString() { + return "IsAssignableFrom(" + 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(T t) { + try { + return target.contains(t); + } catch (NullPointerException e) { + return false; + } catch (ClassCastException e) { + return false; + } + } + + @Override public boolean equals(@Nullable 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 "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(A a) { + return p.apply(f.apply(a)); + } + + @Override public boolean equals(@Nullable 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() { + return p.toString() + "(" + f.toString() + ")"; + } + + private static final long serialVersionUID = 0; + } + + /** + * @see Predicates#contains(Pattern) + * @see Predicates#containsPattern(String) + */ + @GwtIncompatible("Only used by other GWT-incompatible code.") + private static class ContainsPatternPredicate + implements Predicate<CharSequence>, Serializable { + final Pattern pattern; + + ContainsPatternPredicate(Pattern pattern) { + this.pattern = checkNotNull(pattern); + } + + ContainsPatternPredicate(String patternStr) { + this(Pattern.compile(patternStr)); + } + + @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(@Nullable 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()) + && Objects.equal(pattern.flags(), that.pattern.flags()); + } + return false; + } + + @Override public String toString() { + return Objects.toStringHelper(this) + .add("pattern", pattern) + .add("pattern.flags", Integer.toHexString(pattern.flags())) + .toString(); + } + + private static final long serialVersionUID = 0; + } + + @SuppressWarnings("unchecked") + private static <T> List<Predicate<? super T>> asList( + Predicate<? super T> first, Predicate<? super T> second) { + 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; + } +} |