package fr.openwide.core.commons.util.functional;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
public final class Predicates2 {
private Predicates2() { }
/**
* An identity-like predicate evaluating to true when the input is true, false when it is false,
* and <strong>false when the input is null</strong>.
* @see Predicates2#isTrueOrNull()
*/
public static Predicate<Boolean> isTrue() {
return Predicates.equalTo(true);
}
/**
* An identity-like predicate evaluating to true when the input is true, false when it is false,
* and <strong>true when the input is null</strong>.
*/
public static Predicate<Boolean> isTrueOrNull() {
return Predicates.or(Predicates.equalTo(true), Predicates.isNull());
}
/**
* A not-like predicate evaluating to false when the input is true, true when it is false,
* and <strong>false when the input is null</strong>.
* @see Predicates2#isFalseOrNull()
*/
public static Predicate<Boolean> isFalse() {
return Predicates.equalTo(false);
}
/**
* A not-like predicate evaluating to false when the input is true, true when it is false,
* and <strong>true when the input is null</strong>.
*/
public static Predicate<Boolean> isFalseOrNull() {
return Predicates.or(Predicates.equalTo(false), Predicates.isNull());
}
public static <T extends Collection<?>> Predicate<T> isEmpty() {
return CollectionPredicate.IS_EMPTY.withNarrowedType();
}
public static <T extends Collection<?>> Predicate<T> notEmpty() {
return CollectionPredicate.NOT_EMPTY.withNarrowedType();
}
private enum CollectionPredicate implements Predicate<Collection<?>>, Serializable {
IS_EMPTY {
@Override
public boolean apply(Collection<?> input) {
return input == null || input.isEmpty();
}
},
NOT_EMPTY {
@Override
public boolean apply(Collection<?> input) {
return input != null && !input.isEmpty();
}
};
@SuppressWarnings("unchecked") // these Collection predicates work for any T that extends Collection<?>
<T extends Collection<?>> Predicate<T> withNarrowedType() {
return (Predicate<T>) this;
}
}
public static <T extends Map<?, ?>> Predicate<T> mapIsEmpty() {
return MapPredicate.IS_EMPTY.withNarrowedType();
}
public static <T extends Map<?, ?>> Predicate<T> mapNotEmpty() {
return MapPredicate.NOT_EMPTY.withNarrowedType();
}
private enum MapPredicate implements Predicate<Map<?, ?>>, Serializable {
IS_EMPTY {
@Override
public boolean apply(Map<?, ?> input) {
return input == null || input.isEmpty();
}
},
NOT_EMPTY {
@Override
public boolean apply(Map<?, ?> input) {
return input != null && !input.isEmpty();
}
};
@SuppressWarnings("unchecked") // these Map predicates work for any T that extends Map<?, ?>
<T extends Map<?, ?>> Predicate<T> withNarrowedType() {
return (Predicate<T>) this;
}
}
public static Predicate<Collection<?>> contains(Object referenceValue) {
return new ContainsPredicate(referenceValue);
}
private static class ContainsPredicate implements SerializablePredicate<Collection<?>> {
private static final long serialVersionUID = -9193654606378621631L;
private final Object referenceValue;
public ContainsPredicate(Object referenceValue) {
this.referenceValue = referenceValue;
}
@Override
public boolean apply(Collection<?> input) {
return input != null && input.contains(referenceValue);
}
@Override
public String toString() {
return "contains(" + referenceValue + ")";
}
}
public static Predicate<Collection<?>> containsAny(Iterable<?> referenceValues) {
return new ContainsAnyPredicate(referenceValues);
}
private static class ContainsAnyPredicate implements SerializablePredicate<Collection<?>> {
private static final long serialVersionUID = -9193654606378621631L;
private final Set<?> referenceValues;
public ContainsAnyPredicate(Iterable<?> referenceValues) {
this.referenceValues = Sets.newLinkedHashSet(checkNotNull(referenceValues));
}
@Override
public boolean apply(Collection<?> input) {
if (input == null) {
return false;
}
for (Object value : referenceValues) {
if (input.contains(value)) {
return true;
}
}
return false;
}
@Override
public String toString() {
return "containsAny(" + referenceValues + ")";
}
}
public static Predicate<String> hasText() {
return StringPredicate.HAS_TEXT;
}
private enum StringPredicate implements Predicate<String>, Serializable {
HAS_TEXT {
@Override
public boolean apply(String input) {
return StringUtils.isNotBlank(input);
}
}
}
public static <T> Predicate<T> comparesEqualTo(T value, Comparator<? super T> comparator) {
return new ComparesEqualToPredicate<T>(value, comparator);
}
private static class ComparesEqualToPredicate<T> implements SerializablePredicate<T> {
private static final long serialVersionUID = -9193654606378621631L;
private final T referenceValue;
private final Comparator<? super T> comparator;
public ComparesEqualToPredicate(T header, Comparator<? super T> comparator) {
this.referenceValue = header;
this.comparator = comparator;
}
@Override
public boolean apply(T input) {
return comparator.compare(referenceValue, input) == 0;
}
}
/**
* @return A predicate returning true if the given iterable is non-null, is non-empty and has at least one element
* that satisfies {@code itemPredicate}.
* @see Iterables#any(Iterable, Predicate)
*/
public static <T> Predicate<Iterable<? extends T>> any(Predicate<? super T> itemPredicate) {
return new IterableAnyPredicate<T>(itemPredicate);
}
private static class IterableAnyPredicate<T> implements Predicate<Iterable<? extends T>>, Serializable {
private static final long serialVersionUID = -359783441767977199L;
private final Predicate<? super T> itemPredicate;
public IterableAnyPredicate(Predicate<? super T> itemPredicate) {
super();
this.itemPredicate = itemPredicate;
}
@Override
public boolean apply(Iterable<? extends T> input) {
return input != null && Iterables.any(input, itemPredicate);
}
@Override
public String toString() {
return new StringBuilder().append("any(").append(itemPredicate).append(")").toString();
}
}
/**
* @return A predicate returning true if the given iterable is null, is empty or has only elements
* that satisfy {@code itemPredicate}.
* @see Iterables#all(Iterable, Predicate)
*/
public static <T> Predicate<Iterable<? extends T>> all(Predicate<? super T> itemPredicate) {
return new IterableAllPredicate<T>(itemPredicate);
}
private static class IterableAllPredicate<T> implements Predicate<Iterable<? extends T>>, Serializable {
private static final long serialVersionUID = -359783441767977199L;
private final Predicate<? super T> itemPredicate;
public IterableAllPredicate(Predicate<? super T> itemPredicate) {
super();
this.itemPredicate = itemPredicate;
}
@Override
public boolean apply(Iterable<? extends T> input) {
return input == null || Iterables.all(input, itemPredicate);
}
@Override
public String toString() {
return new StringBuilder().append("all(").append(itemPredicate).append(")").toString();
}
}
public static <T> Predicate<T> notNullAnd(Predicate<T> predicate) {
return Predicates.and(Predicates.notNull(), predicate);
}
public static <T> Predicate<T> notNullAndNot(Predicate<T> predicate) {
return notNullAnd(Predicates.not(predicate));
}
}