package com.googlecode.totallylazy.predicates; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.functions.Function2; import com.googlecode.totallylazy.Callers; import com.googlecode.totallylazy.functions.Functions; import com.googlecode.totallylazy.Unchecked; import static com.googlecode.totallylazy.Unchecked.cast; import static java.lang.String.format; public class WherePredicate<T, R> extends LogicalPredicate<T> { private final Function1<? super T, ? extends R> callable; private final Predicate<? super R> predicate; private WherePredicate(final Function1<? super T, ? extends R> callable, final Predicate<? super R> predicate) { this.predicate = predicate; this.callable = callable; } public static <T, R> LogicalPredicate<T> where(final Function1<? super T, ? extends R> callable, final Predicate<? super R> predicate) { if(predicate instanceof AlwaysTrue) return Predicates.alwaysTrue(); if(predicate instanceof AlwaysFalse) return Predicates.alwaysFalse(); if(predicate instanceof Not) return Predicates.not(where(callable, Unchecked.<Not< ? super R >>cast(predicate).predicate())); return new WherePredicate<T, R>(callable, predicate); } public static <T, R> Function1<T, Predicate<T>> asWhere(final Function2<? super T, ? super T, ? extends R> callable, final Predicate<? super R> predicate) { return t -> where(Functions.apply(callable, t), predicate); } public boolean matches(T o) { return predicate.matches(Callers.call(callable, o)); } public Function1<T, R> callable() { return cast(callable); } public Predicate<R> predicate() { return cast(predicate); } @Override public boolean equals(Object obj) { return obj instanceof WherePredicate && callable.equals(((WherePredicate) obj).callable()) && predicate.equals(((WherePredicate) obj).predicate()); } @Override public int hashCode() { return 19 * callable.hashCode() * predicate.hashCode(); } @Override public String toString() { return format("where %s is %s", callable, predicate); } }