2222import java .util .function .Predicate ;
2323import java .util .stream .Collectors ;
2424
25+ import static java .util .Arrays .asList ;
26+
2527/**
2628 * This class validates instances of {@link BulletConfig}. Use {@link Validator.Entry} to define
2729 * fields and {@link Validator.Relationship} to define relationships between them.
@@ -414,7 +416,7 @@ public State evaluate(String description, String... keys) {
414416 if (!missingKeys .isEmpty ()) {
415417 throw new NullPointerException ("You must evaluate entries for " + missingKeys .stream ().collect (Collectors .joining (COMMA )));
416418 }
417- State state = new State (description , Arrays . asList (keys ));
419+ State state = new State (description , asList (keys ));
418420 states .add (state );
419421 return state ;
420422 }
@@ -505,6 +507,36 @@ public static boolean isNotNull(Object value) {
505507 return value != null ;
506508 }
507509
510+ /**
511+ * Checks to see if the value is null or not.
512+ *
513+ * @param value The object to check.
514+ * @return A boolean denoting if the value was null.
515+ */
516+ public static boolean isNull (Object value ) {
517+ return value == null ;
518+ }
519+
520+ /**
521+ * Checks to see if the value is true or not.
522+ *
523+ * @param value The object to check.
524+ * @return A boolean denoting if the value was true.
525+ */
526+ public static boolean isTrue (Object value ) {
527+ return isBoolean (value ) && ((Boolean ) value );
528+ }
529+
530+ /**
531+ * Checks to see if the value is false or not.
532+ *
533+ * @param value The object to check.
534+ * @return A boolean denoting if the value was false.
535+ */
536+ public static boolean isFalse (Object value ) {
537+ return isBoolean (value ) && !((Boolean ) value );
538+ }
539+
508540 /**
509541 * Checks to see if the value is of the provided type or not.
510542 *
@@ -630,6 +662,21 @@ public static boolean isNonEmptyList(Object value) {
630662 return isType (value , List .class ) && !((List ) value ).isEmpty ();
631663 }
632664
665+ /**
666+ * Checks to see if the given object refers to a class name that can be loaded.
667+ *
668+ * @param value The object to check if it is a class name.
669+ * @return A boolean denoting whether the given value was the name of a class.
670+ */
671+ public static boolean isClassName (Object value ) {
672+ try {
673+ Class .forName ((String ) value );
674+ } catch (Exception e ) {
675+ return false ;
676+ }
677+ return true ;
678+ }
679+
633680 // Unary Predicate Generators
634681
635682 /**
@@ -642,10 +689,32 @@ public static boolean isNonEmptyList(Object value) {
642689 @ SuppressWarnings ("unchecked" )
643690 public static <T > Predicate <Object > isIn (T ... values ) {
644691 Objects .requireNonNull (values );
645- Set <T > set = new HashSet <>(Arrays . asList (values ));
692+ Set <T > set = new HashSet <>(asList (values ));
646693 return set ::contains ;
647694 }
648695
696+ /**
697+ * Creates a {@link Predicate} that checks to see if the given object is a {@link List} and has at least n items
698+ * in it. Note that the object must be a List even if n is 0.
699+ *
700+ * @param n The minimum number of items that can be in the List.
701+ * @return A boolean denoting if the {@link List} has a size of at least the given parameter.
702+ */
703+ public static Predicate <Object > hasMinimumListSize (int n ) {
704+ return o -> isList (o ) && ((List ) o ).size () >= n ;
705+ }
706+
707+ /**
708+ * Creates a {@link Predicate} that checks to see if the given object is a {@link List} and has at most n items
709+ * in it. Note that the object must be a List even if n is 0.
710+ *
711+ * @param n The maximum number of items that can be in the List.
712+ * @return A boolean denoting if the {@link List} has a size of at most the given parameter.
713+ */
714+ public static Predicate <Object > hasMaximumListSize (int n ) {
715+ return o -> isList (o ) && ((List ) o ).size () <= n ;
716+ }
717+
649718 /**
650719 * Creates a {@link Predicate} that checks to see if the given object is a {@link Number} in the proper range.
651720 *
@@ -663,7 +732,66 @@ public static <T extends Number> Predicate<Object> isInRange(T min, T max) {
663732 return o -> isNumber (o ) && ((T ) o ).doubleValue () >= minimum && ((T ) o ).doubleValue () <= maximum ;
664733 }
665734
666- // Binary Predicates.
735+ /**
736+ * Creates a {@link Predicate} that checks to see if the given object is a non-empty {@link List} of the
737+ * given type.
738+ *
739+ * @param type The class of the contents of the list to check for.
740+ * @param <T> The type of the content in the list.
741+ * @return A Predicate that checks tor see if the value was a non-empty List of the given type.
742+ */
743+ @ SuppressWarnings ("unchecked" )
744+ public static <T > Predicate <Object > isListOfType (Class <T > type ) {
745+ return value -> {
746+ if (!isNonEmptyList (value )) {
747+ return false ;
748+ }
749+ List list = (List ) value ;
750+ return list .stream ().allMatch (i -> isType (i , type ));
751+ };
752+ }
753+
754+ /**
755+ * Creates a {@link Predicate} that is true if and only if all the provided predicates are true and false otherwise.
756+ *
757+ * @param predicates The predicates to be ANDed.
758+ * @return A predicate that is the AND of all the given predicates.
759+ */
760+ @ SafeVarargs
761+ public static Predicate <Object > and (Predicate <Object >... predicates ) {
762+ Predicate <Object > anded = UNARY_IDENTITY ;
763+ for (Predicate <Object > predicate : predicates ) {
764+ anded = anded .and (predicate );
765+ }
766+ return anded ;
767+ }
768+
769+ /**
770+ * Creates a {@link Predicate} that is true if any of the provided predicates are true and false otherwise.
771+ *
772+ * @param predicates The predicates to be ORed.
773+ * @return A predicate that is the OR of all the given predicates.
774+ */
775+ @ SafeVarargs
776+ public static Predicate <Object > or (Predicate <Object >... predicates ) {
777+ Predicate <Object > ored = not (UNARY_IDENTITY );
778+ for (Predicate <Object > predicate : predicates ) {
779+ ored = ored .or (predicate );
780+ }
781+ return ored ;
782+ }
783+
784+ /**
785+ * Creates a {@link Predicate} that is true if the given predicate is false and false if the given predicate is true.
786+ *
787+ * @param predicate The predicates to be negated.
788+ * @return A predicate that is the NOT of the given predicate.
789+ */
790+ public static Predicate <Object > not (Predicate <Object > predicate ) {
791+ return predicate .negate ();
792+ }
793+
794+ // Binary Predicates
667795
668796 /**
669797 * Checks to see if the first numeric object is greater than or equal to the second numeric object.
@@ -676,7 +804,20 @@ public static boolean isGreaterOrEqual(Object first, Object second) {
676804 return ((Number ) first ).doubleValue () >= ((Number ) second ).doubleValue ();
677805 }
678806
679- // Binary Predicate makers.
807+ /**
808+ * Checks to see if the first boolean object implies the second boolean object. In other words, does the first imply
809+ * the second. If first is true and second is false, this check is false. Otherwise, it is true.
810+ *
811+ * @param first The first boolean object.
812+ * @param second The second boolean object.
813+ * @return A boolean denoting whether the second is implied by the first.
814+ */
815+ public static boolean isImplied (Object first , Object second ) {
816+ // first -> second === ~first or second
817+ return !((Boolean ) first ) || ((Boolean ) second );
818+ }
819+
820+ // Binary Predicate Generators.
680821
681822 /**
682823 * Returns a {@link BiPredicate} that checks to see if the first argument is at least the given times
@@ -688,4 +829,31 @@ public static boolean isGreaterOrEqual(Object first, Object second) {
688829 public static BiPredicate <Object , Object > isAtleastNTimes (double n ) {
689830 return (greater , smaller ) -> ((Number ) greater ).doubleValue () >= n * ((Number ) smaller ).doubleValue ();
690831 }
832+
833+ /**
834+ * Returns a {@link BiPredicate} that checks to see if the first boolean argument implies the second
835+ * {@link Predicate}. In other words, if the first argument is true and the second argument evaluates to false
836+ * on the given {@link Predicate}, this check is false. Else, it is true.
837+ *
838+ * @param predicate The {@link Predicate} to test the second argument to the returned {@link BiPredicate} with.
839+ * @return The created {@link BiPredicate}.
840+ */
841+ public static BiPredicate <Object , Object > ifTrueThenCheck (Predicate <Object > predicate ) {
842+ // Can use isImplied(bool, predicate.test(object)) but is not lazy anymore
843+ return (bool , object ) -> !((Boolean ) bool ) || predicate .test (object );
844+ }
845+
846+ /**
847+ * Returns a {@link BiPredicate} that checks to see if the first {@link Predicate} implies the second. In other
848+ * words, if the first one evaluates to true on the first object in the BiPredicate and the second evaluates to
849+ * false on the second object, this check is false. Else, it is true. Analogous to
850+ * {@link Validator#isImplied(Object, Object)}.
851+ *
852+ * @param firstTest The first {@link Predicate}.
853+ * @param secondTest The second {@link Predicate}.
854+ * @return The created {@link BiPredicate}.
855+ */
856+ public static BiPredicate <Object , Object > isImpliedBy (Predicate <Object > firstTest , Predicate <Object > secondTest ) {
857+ return (first , second ) -> !(firstTest .test (first )) || secondTest .test (second );
858+ }
691859}
0 commit comments