Predicates.java

  1. package com.github.dakusui.pcond.forms;

  2. import com.github.dakusui.pcond.core.printable.PrintablePredicateFactory;
  3. import com.github.dakusui.pcond.core.printable.PrintablePredicateFactory.Leaf;
  4. import com.github.dakusui.pcond.core.printable.PrintablePredicateFactory.ParameterizedLeafFactory;
  5. import com.github.dakusui.pcond.core.refl.MethodQuery;
  6. import com.github.dakusui.pcond.core.refl.Parameter;
  7. import com.github.dakusui.pcond.internals.InternalChecks;

  8. import java.util.Collection;
  9. import java.util.function.Function;
  10. import java.util.function.Predicate;
  11. import java.util.stream.Stream;

  12. import static com.github.dakusui.pcond.core.refl.ReflUtils.invokeMethod;
  13. import static com.github.dakusui.pcond.forms.Printables.function;
  14. import static com.github.dakusui.pcond.forms.Printables.predicate;
  15. import static com.github.dakusui.pcond.internals.InternalUtils.formatObject;
  16. import static java.lang.String.format;
  17. import static java.util.Arrays.asList;
  18. import static java.util.Collections.singletonList;
  19. import static java.util.Objects.requireNonNull;

  20. /**
  21.  * An entry point for acquiring predicate objects.
  22.  * Predicates retrieved by methods in this class are all "printable".
  23.  */
  24. public class Predicates {
  25.     private Predicates() {
  26.     }

  27.     public static <T> Predicate<T> alwaysTrue() {
  28.         return Leaf.ALWAYS_TRUE.instance();
  29.     }

  30.     public static Predicate<Boolean> isTrue() {
  31.         return Leaf.IS_TRUE.instance();
  32.     }

  33.     public static Predicate<Boolean> isFalse() {
  34.         return Leaf.IS_FALSE.instance();
  35.     }

  36.     public static <T> Predicate<T> isNull() {
  37.         return Leaf.IS_NULL.instance();
  38.     }

  39.     public static <T> Predicate<T> isNotNull() {
  40.         return Leaf.IS_NOT_NULL.instance();
  41.     }

  42.     public static <T> Predicate<T> isEqualTo(T value) {
  43.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.IS_EQUAL_TO, singletonList(value));
  44.     }

  45.     public static <T> Predicate<T> isSameReferenceAs(T value) {
  46.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.OBJECT_IS_SAME_AS, singletonList(value));
  47.     }

  48.     @SuppressWarnings({"unchecked", "RedundantClassCall"})
  49.     public static <T> Function<Class<?>, Predicate<T>> isInstanceOf() {
  50.         return Function.class.cast(Def.IS_INSTANCE_OF$2);
  51.     }

  52.     public static Predicate<Object> isInstanceOf(Class<?> value) {
  53.         return applyOnceExpectingPredicate(requireNonNull(value), isInstanceOf());
  54.     }

  55.     private static <T, R> Predicate<R> applyOnceExpectingPredicate(T value, Function<T, Predicate<R>> p) {
  56.         return predicate(() -> format("%s[%s]", p, formatObject(value)), p.apply(value));
  57.     }

  58.     public static <T extends Comparable<? super T>> Predicate<T> gt(T value) {
  59.         return greaterThan(value);
  60.     }

  61.     public static <T extends Comparable<? super T>> Predicate<T> greaterThan(T value) {
  62.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.GREATER_THAN, singletonList(value));
  63.     }

  64.     public static <T extends Comparable<? super T>> Predicate<T> ge(T value) {
  65.         return greaterThanOrEqualTo(value);
  66.     }

  67.     public static <T extends Comparable<? super T>> Predicate<T> greaterThanOrEqualTo(T value) {
  68.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.GREATER_THAN_OR_EQUAL_TO, singletonList(value));
  69.     }

  70.     public static <T extends Comparable<? super T>> Predicate<T> lt(T value) {
  71.         return lessThan(value);
  72.     }

  73.     public static <T extends Comparable<? super T>> Predicate<T> lessThan(T value) {
  74.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.LESS_THAN, singletonList(value));
  75.     }

  76.     public static <T extends Comparable<? super T>> Predicate<T> le(T value) {
  77.         return lessThanOrEqualTo(value);
  78.     }

  79.     public static <T extends Comparable<? super T>> Predicate<T> lessThanOrEqualTo(T value) {
  80.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.LESS_THAN_OR_EQUAL_TO, singletonList(value));
  81.     }

  82.     public static <T extends Comparable<T>> Predicate<T> eq(T value) {
  83.         return equalTo(value);
  84.     }

  85.     public static <T extends Comparable<T>> Predicate<T> equalTo(T value) {
  86.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.EQUAL_TO, singletonList(value));
  87.     }

  88.     public static Predicate<String> matchesRegex(String regex) {
  89.         requireNonNull(regex);
  90.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.MATCHES_REGEX, singletonList(regex));
  91.     }

  92.     public static Predicate<String> containsString(String string) {
  93.         requireNonNull(string);
  94.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.CONTAINS_STRING, singletonList(string));
  95.     }

  96.     public static Predicate<String> startsWith(String string) {
  97.         requireNonNull(string);
  98.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.STARTS_WITH, singletonList(string));
  99.     }

  100.     public static Predicate<String> endsWith(String string) {
  101.         requireNonNull(string);
  102.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.ENDS_WITH, singletonList(string));
  103.     }

  104.     public static Predicate<String> equalsIgnoreCase(String string) {
  105.         requireNonNull(string);
  106.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.EQUALS_IGNORE_CASE, singletonList(string));
  107.     }

  108.     public static Predicate<String> isEmptyString() {
  109.         return Leaf.IS_EMPTY_STRING.instance();
  110.     }

  111.     public static Predicate<String> isNullOrEmptyString() {
  112.         return Leaf.IS_NULL_OR_EMPTY_STRING.instance();
  113.     }

  114.     public static <E> Predicate<Collection<E>> contains(Object entry) {
  115.         return ParameterizedLeafFactory.create(ParameterizedLeafFactory.CONTAINS, singletonList(entry));
  116.     }

  117.     public static Predicate<Object[]> isEmptyArray() {
  118.         return Leaf.IS_EMPTY_ARRAY.instance();
  119.     }

  120.     public static Predicate<? super Collection<?>> isEmpty() {
  121.         return Leaf.IS_EMPTY_COLLECTION.instance();
  122.     }

  123.     public static <E> Predicate<Stream<E>> allMatch(Predicate<E> predicate) {
  124.         requireNonNull(predicate);
  125.         return PrintablePredicateFactory.allMatch(predicate);
  126.     }

  127.     public static <E> Predicate<Stream<E>> noneMatch(Predicate<E> predicate) {
  128.         requireNonNull(predicate);
  129.         return PrintablePredicateFactory.noneMatch(predicate);
  130.     }

  131.     public static <E> Predicate<Stream<E>> anyMatch(Predicate<E> predicate) {
  132.         requireNonNull(predicate);
  133.         return PrintablePredicateFactory.anyMatch(predicate);
  134.     }

  135.     @SafeVarargs
  136.     public static <T> Predicate<T> and(Predicate<? super T>... predicates) {
  137.         return PrintablePredicateFactory.and(asList(predicates));
  138.     }

  139.     @SafeVarargs
  140.     public static <T> Predicate<T> or(Predicate<? super T>... predicates) {
  141.         return PrintablePredicateFactory.or(asList(predicates));
  142.     }

  143.     @SafeVarargs
  144.     public static <T> Predicate<T> allOf(Predicate<? super T>... predicates) {
  145.         return PrintablePredicateFactory.allOf(asList(predicates));
  146.     }

  147.     @SafeVarargs
  148.     public static <T> Predicate<T> anyOf(Predicate<? super T>... predicates) {
  149.         return PrintablePredicateFactory.anyOf(asList(predicates));
  150.     }

  151.     public static <T> Predicate<T> not(Predicate<T> cond) {
  152.         return PrintablePredicateFactory.not(cond);
  153.     }

  154.     public static <O, P> PrintablePredicateFactory.TransformingPredicate.Factory<P, O> transform(String funcName, Function<O, P> func) {
  155.         return transform(function(funcName, func));
  156.     }

  157.     public static <O, P> PrintablePredicateFactory.TransformingPredicate.Factory<P, O> transform(Function<O, P> function) {
  158.         return PrintablePredicateFactory.transform(function);
  159.     }

  160.     /**
  161.      * // @formatter:off
  162.    * Returns a {@link Predicate} created from a method specified by a {@code methodQuery}.
  163.    * If the {@code methodQuery} matches none or more than one methods, a {@code RuntimeException} will be thrown.
  164.    *
  165.    * The suffix {@code p} stands for "predicate" following the custom in LISP culture
  166.    * and it is necessary to avoid collision with {@link Functions#call(MethodQuery)} method.
  167.    *
  168.    * // @formatter:on
  169.      *
  170.      * @param methodQuery A query object that specifies a method to be invoked by the returned predicate.
  171.      * @param <T>         the type of the input to the returned predicate
  172.      * @return Created predicate.
  173.      * @see Functions#classMethod(Class, String, Object[])
  174.      * @see Functions#instanceMethod(Object, String, Object[])
  175.      * @see Functions#parameter()
  176.      */
  177.     @SuppressWarnings("ConstantConditions")
  178.     public static <T> Predicate<T> callp(MethodQuery methodQuery) {
  179.         return predicate(
  180.                 methodQuery.describe(),
  181.                 t -> InternalChecks.ensureValue(
  182.                         invokeMethod(methodQuery.bindActualArguments((o) -> o instanceof Parameter, o -> t)),
  183.                         v -> v instanceof Boolean,
  184.                         v -> format("Method matched with '%s' must return a boolean value but it gave: '%s'.", methodQuery.describe(), v)));
  185.     }

  186.     /**
  187.      * // @formatter:off
  188.    * Returns a predicate that calls a method which matches the given {@code methodName}
  189.    * and {@code args} on the object given as input to it.
  190.    *
  191.    * Note that method look up is done when the predicate is applied.
  192.    * This means this method does not throw any exception by itself and in case
  193.    * you give wrong {@code methodName} or {@code arguments}, an exception will be
  194.    * thrown when the returned function is applied.
  195.    * // @formatter:on
  196.      *
  197.      * @param methodName The method name
  198.      * @param arguments  Arguments passed to the method.
  199.      * @param <T>        The type of input to the returned predicate
  200.      * @return A predicate that invokes the method matching the {@code methodName} and {@code args}
  201.      * @see Functions#parameter()
  202.      */
  203.     public static <T> Predicate<T> callp(String methodName, Object... arguments) {
  204.         return callp(Functions.instanceMethod(Functions.parameter(), methodName, arguments));
  205.     }

  206.     enum Def {
  207.         ;

  208.         public static final Function<Class<?>, Predicate<?>> IS_INSTANCE_OF$2 = function(() -> "isInstanceOf", (Class<?> c) -> c::isInstance);
  209.     }

  210. }