ComposableIntPredicate.java
package org.klojang.check.types;
import java.util.function.IntPredicate;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static org.klojang.check.types.Private.testAgainstArray;
/**
* An extension of {@link IntPredicate} that acts as a bridge between {@code IntPredicate} and the relational
* interfaces in this package. It enables the composition of new tests from any number of instances of
* {@link Predicate}, {@link IntPredicate}, {@link Relation}, {@link IntRelation} and {@link IntObjRelation}.
* {@code ComposableIntPredicate} extends {@link IntPredicate} with a set of {@code default} methods that
* allow the composition to take place. For more information, see {@link ComposablePredicate}.
*/
@SuppressWarnings({"unchecked"}) @FunctionalInterface public interface ComposableIntPredicate extends
IntPredicate {
/**
* Returns the negation of this predicate.
*
* @return the negation of this predicate
*/
default ComposableIntPredicate negated() {
return x -> !meFirst(x);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test or the specified test.
*
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate orElse(IntPredicate test) {
return x -> meFirst(x) || test.test(x);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test or if it has the specified relation to the specified value.
*
* <blockquote><pre>{@code
* Check.that("foo bar").is(empty().orElse(hasSubstring(), "foo"));
* }</pre></blockquote>
*
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation, with the value of this {@code ComposablePredicate}
* now becoming the subject of that relation
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate orElse(IntRelation relation, int object) {
return x -> meFirst(x) || relation.exists(x, object);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test or the negation of the specified test.
*
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate orNot(IntPredicate test) {
return x -> meFirst(x) || !test.test(x);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test or if it does not have the specified relation to the specified value.
*
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation, with the value of this {@code ComposablePredicate}
* now becoming the subject of that relation
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate orNot(IntRelation relation, int object) {
return x -> meFirst(x) || !relation.exists(x, object);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test or if it has a particular relation to the specified set of values.
*
* @param relation the relationship test to combine this test with
* @param quantifier a logical quantifier modulating the relationship
* @param objects the set of values to test the value against
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate or(IntRelation relation, Quantifier quantifier, int... objects) {
return x -> meFirst(x) || testAgainstArray(x, relation, quantifier, objects);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if another value manages to pass the other test.
*
* @param value the value to be tested by the specified test
* @param test the test to combine this test with
* @param <T> the type of the value tested by the predicate
* @return a new test combining this test and the specified test
*/
default <T> ComposableIntPredicate orThat(T value, Predicate<T> test) {
return x -> meFirst(x) || test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if another value manages to pass the other test.
*
* @param value the value to be tested by the specified test
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate orThat(int value, IntPredicate test) {
return x -> meFirst(x) || test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if another value manages to pass the other test.
*
* @param subject the subject of the specified relation
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation
* @param <S> the type of the subject of the specified relation
* @param <O> the type of the object of the specified relation
* @return a new test combining this test and the specified test
*/
default <S, O> ComposableIntPredicate orThat(S subject, Relation<S, O> relation, O object) {
return x -> meFirst(x) || relation.exists(subject, object);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if another value manages to pass the other test.
*
* @param subject the subject of the specified relation
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate orThat(int subject, IntRelation relation, int object) {
return x -> meFirst(x) || relation.exists(subject, object);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if another value manages to pass the negation of the other
* test.
*
* @param value the value to be tested by the specified predicate
* @param test the test to combine this test with
* @param <T> the type of values being tested by the specified predicate
* @return a new test combining this test and the specified test
*/
default <T> ComposableIntPredicate orNot(T value, Predicate<T> test) {
return x -> meFirst(x) || !test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if another value manages to pass the negation of the other
* test.
*
* @param value the value to be tested by the specified predicate
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate orNot(int value, IntPredicate test) {
return x -> meFirst(x) || !test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if another value manages to pass the negation of the other
* test.
*
* @param subject the subject of the specified relation
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation
* @param <S> the type of the subject of the specified relation
* @param <O> the type of the object of the specified relation
* @return a new test combining this test and the specified test
*/
default <S, O> ComposableIntPredicate orNot(S subject, Relation<S, O> relation, O object) {
return x -> meFirst(x) || !relation.exists(subject, object);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test or if <i>another</i> value ({@code subject}) has a particular
* relation to the specified set of values.
*
* @param subject the subject of the specified {@code Relation}
* @param relation the relationship test to combine this test with
* @param quantifier a logical quantifier modulating the relationship
* @param objects the set of values to test the subject against
* @param <S> the type of the subject of the relation
* @param <O> the type of the object of the relation
* @param <P> the type of the values fed as "objects" into the relation
* @return a new test combining this test and the specified test
*/
default <S, O, P extends O> ComposableIntPredicate or(S subject,
Relation<S, O> relation,
Quantifier quantifier,
P... objects) {
return x -> meFirst(x) || testAgainstArray(subject, relation, quantifier, objects);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if <i>another</i> value ({@code subject}) has a particular
* relation to the specified set of values.
*
* @param subject the subject of the relation
* @param relation the relationship test to combine this test with
* @param quantifier a logical quantifier modulating the relationship
* @param objects the set of values to test the subject against
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate or(int subject,
IntRelation relation,
Quantifier quantifier,
int... objects) {
return x -> meFirst(x) || testAgainstArray(subject, relation, quantifier, objects);
}
/**
* Returns a new test combining this test with the specified free-form test. A value will pass the new test
* if it passes <i>this</i> test or if the provided expression evaluates to {@code true}.
*
* @param test the boolean expression to evaluate if the value fails to pass this test
* @return a new test combining this test and the specified free-form test
*/
default ComposableIntPredicate or(boolean test) {
return x -> meFirst(x) || test;
}
/**
* Returns a new test combining this test with the free-form test supplied by the specified
* {@code Supplier}. A value will pass the new test if it passes
* <i>this</i> test or if the expression supplied by the {@code Supplier}
* evaluates to {@code true}. The supplier's {@link Supplier#get() get()} method will only be called if the
* value fails to pass this test. Useful if evaluating the expression could be expensive.
*
* @param test the supplier of a boolean expression
* @return a new test combining this test and the specified free-form test
*/
default ComposableIntPredicate orEval(Supplier<Boolean> test) {
return x -> meFirst(x) || test.get();
}
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// [AND methods] ////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes both this test and the specified test.
*
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andAlso(IntPredicate test) {
return x -> meFirst(x) && test.test(x);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test and if it has the specified relation to the specified value.
*
* @param relation the relationship test to combine this test with
* @param object the object of the relation, with the value being tested now becoming the subject of the
* relation
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andAlso(IntRelation relation, int object) {
return x -> meFirst(x) && relation.exists(x, object);
}
/**
* Returns a new test combining this test with the specified free-form test. A value will pass the new test
* if it passes <i>this</i> test and if the provided expression evaluates to {@code true}.
*
* @param test the boolean expression to evaluate if the value fails to pass this test
* @return a new test combining this test and the specified free-form test
*/
default ComposableIntPredicate and(boolean test) {
return x -> meFirst(x) && test;
}
/**
* Returns a new test combining this test with the free-form test supplied by the specified
* {@code Supplier}. A value will pass the new test if it passes
* <i>this</i> test and if the expression supplied by the {@code Supplier}
* evaluates to {@code true}. The supplier's {@link Supplier#get() get()} method will only be called if the
* value passes this test. Useful if evaluating the boolean expression could be expensive.
*
* @param test the supplier of a boolean expression
* @return a new test combining this test and the specified free-form test
*/
default ComposableIntPredicate andEval(Supplier<Boolean> test) {
return x -> meFirst(x) && test.get();
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes both this test and the negation of the specified test.
*
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andNot(IntPredicate test) {
return x -> meFirst(x) && !test.test(x);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test and if it does not have the specified relation to the specified value.
*
* @param relation the relationship test to combine this test with
* @param object the object of the relation, with the value being tested now becoming the subject of the
* relation
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andNot(IntRelation relation, int object) {
return x -> meFirst(x) && !relation.exists(x, object);
}
/**
* Returns a new test combining this test and the specified test. A value will pass the new test if it
* passes <i>this</i> test and if it has a particular relation to the specified set of values.
*
* @param relation the relationship test to combine this test with
* @param quantifier a logical quantifier modulating the relationship
* @param objects the set of values to test the value against
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate and(IntRelation relation, Quantifier quantifier, int... objects) {
return x -> meFirst(x) && testAgainstArray(x, relation, quantifier, objects);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the other test.
*
* @param value the value to be tested by the specified predicate
* @param test the test to combine this test with
* @param <T> the type of values being tested by the specified predicate
* @return a new test combining this test and the specified test
*/
default <T> ComposableIntPredicate andThat(T value, Predicate<T> test) {
return x -> meFirst(x) && test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the other test.
*
* @param value the value to be tested by the specified predicate
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andThat(int value, IntPredicate test) {
return x -> meFirst(x) && test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the other test.
*
* @param subject the subject of the specified relation
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation
* @param <S> the type of the subject of the specified relation
* @param <O> the type of the object of the specified relation
* @return a new test combining this test and the specified test
*/
default <S, O> ComposableIntPredicate andThat(S subject, Relation<S, O> relation, O object) {
return x -> meFirst(x) && relation.exists(subject, object);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the other test.
*
* @param subject the subject of the specified relation
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andThat(int subject, IntRelation relation, int object) {
return x -> meFirst(x) && relation.exists(subject, object);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the negation of the other
* test.
*
* @param value the value to be tested by the specified predicate
* @param test the test to combine this test with
* @param <T> the type of values being tested by the specified predicate
* @return a new test combining this test and the specified test
*/
default <T> ComposableIntPredicate andNot(T value, Predicate<T> test) {
return x -> meFirst(x) && !test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the negation of the other
* test.
*
* @param value the value to be tested by the specified predicate
* @param test the test to combine this test with
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andNot(int value, IntPredicate test) {
return x -> meFirst(x) && !test.test(value);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the negation of the other
* test.
*
* @param subject the subject of the specified relation
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation
* @param <S> the type of the subject of the specified relation
* @param <O> the type of the object of the specified relation
* @return a new test combining this test and the specified test
*/
default <S, O> ComposableIntPredicate andNot(S subject, Relation<S, O> relation, O object) {
return x -> meFirst(x) && !relation.exists(subject, object);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if another value manages to pass the negation of the other
* test.
*
* @param subject the subject of the specified relation
* @param relation the relationship test to combine this test with
* @param object the object of the specified relation
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate andNot(int subject, IntRelation relation, int object) {
return x -> meFirst(x) && !relation.exists(subject, object);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if <i>another</i> value ({@code subject}) has a particular
* relation to the specified set of values.
*
* @param subject the subject of the specified {@code Relation}
* @param relation the relationship test to combine this test with
* @param quantifier a logical quantifier modulating the relationship
* @param objects the set of values to test the subject against
* @param <S> the type of the subject of the relation
* @param <O> the type of the object of the relation
* @param <P> the type of the values fed as "objects" into the relation
* @return a new test combining this test and the specified test
*/
default <S, O, P extends O> ComposableIntPredicate and(S subject,
Relation<S, O> relation,
Quantifier quantifier,
P... objects) {
return x -> meFirst(x) && testAgainstArray(subject, relation, quantifier, objects);
}
/**
* Returns a new test combining this test and the specified test. It combines two checks on two different
* values. A value will pass the new test if it passes
* <i>this</i> test and if <i>another</i> value ({@code subject}) has a particular
* relation to the specified set of values.
*
* @param subject the subject of the relation
* @param relation the relationship test to combine this test with
* @param quantifier a logical quantifier modulating the relationship
* @param objects the set of values to test the subject against
* @return a new test combining this test and the specified test
*/
default ComposableIntPredicate and(int subject,
IntRelation relation,
Quantifier quantifier,
int... objects) {
return x -> meFirst(x) && testAgainstArray(subject, relation, quantifier, objects);
}
private boolean meFirst(int i) {
return ComposableIntPredicate.this.test(i);
}
}