Base.java
package no.motif;
import static no.motif.Iterate.on;
import java.util.Collection;
import java.util.Objects;
import no.motif.f.Do;
import no.motif.f.Fn;
import no.motif.f.Fn0;
import no.motif.f.Fn2;
import no.motif.f.Predicate;
import no.motif.f.Predicate.Always;
import no.motif.f.combine.Conjunction;
import no.motif.f.combine.ConjunctionPremise;
import no.motif.f.combine.Disjunction;
import no.motif.f.combine.DisjunctionPremise;
import no.motif.f.combine.DoChain;
import no.motif.f.combine.Fn2Chain;
import no.motif.f.combine.FnChain;
import no.motif.f.combine.RunnableChain;
import no.motif.f.combine.When;
import no.motif.f.combine.Where;
import no.motif.f.impl.Constant;
import no.motif.f.impl.Throw;
import no.motif.iter.ExtractingIterable;
import no.motif.types.Elements;
/**
* Basic functions.
*
* @see Predicate
* @see Fn
*/
public final class Base {
/**
* Shorthand for {@link #not(Predicate) not(}{@link #equalTo(Object) equalTo(o))}.
*
* @see #not(Predicate)
* @see #equalTo(Object)
*/
public static <T> Predicate<T> not(T o) { return not(equalTo(o)); }
/**
* Negates a predicate.
* @param p The predicate to negate.
* @return The new predicate.
*/
public static <T> Predicate<T> not(final Predicate<T> p) {
return new Predicate<T>() { @Override public boolean $(T value) { return !p.$(value); }}; }
/**
* Compose a predicate from taking the result of a function and apply it to
* another predicate.
*
* <pre>
* fn(T) ∈ P
* p(P) ∈ {true, false}
* <b>ƒ(T) = p(fn(T)) ∈ {true, false}</b>
* </pre>
*
* <p>
* This simple composition enables one to focus on writing {@link Fn functions}
* for your particular domain, and reusing basic predicates provided by <em>Motif</em>.
* </p>
*
* @param <P> The type of the predicate evaluating the function result.
* @param <T> The type of the resulting predicate.
* @param fn The function which result will be evaluated by the predicate. Takes
* an argument of <code>T</code>
* @param predicate Evaluates the result from the function, i.e. a value of <code>P</code>
* @return A predicate of <code>T</code>
*/
public static <T, P> Predicate<T> where(final Fn<T, P> fn, final Predicate<? super P> predicate) {
return new Where<T, P>(fn, predicate); }
/**
* Create a AND-expression of several predicates, starting with the one
* given to this method.
*
* @see Conjunction
* @see #allOf(Predicate...)
* @param predicate The first predicate.
* @return a new predicate which may be used to build up an AND-expression by
* chaining the {@link Conjunction#and(Predicate) and(anotherPredicate)} method.
*/
public static <T> Conjunction<T> both(Predicate<T> predicate) {
return new Conjunction<T>(predicate);
}
/**
* Create a AND-expression of several {@link Fn0 Fn0<Boolean>s}, starting with the one
* given to this method.
*
* @see ConjunctionPremise
* @param premise The first <code>Fn0<Boolean></code>.
* @return a new <code>Fn0<Boolean></code> which may be used to build up an AND-expression by
* chaining the {@link ConjunctionPremise#and(Fn0) and(anotherPremise)} method.
*/
public static ConjunctionPremise both(Fn0<Boolean> premise) {
return new ConjunctionPremise(premise);
}
/**
* Compose an AND-expression of several predicates.
*
* @see Conjunction
* @param predicates the predicates.
* @return a new predicate which is the conjunction (AND) of the given predicates.
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> Conjunction<T> allOf(Predicate<? super T> ... predicates) {
return new Conjunction<>(predicates);
}
/**
* Compose an AND-expression of several {@link Fn0 Fn0<Boolean>s}.
*
* @see ConjunctionPremise
* @param premises the <code>Fn0<Boolean>s</code>.
* @return a new <code>Fn0<Boolean></code> which is the conjunction
* (AND) of the given premises.
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static ConjunctionPremise allOf(Fn0<Boolean> ... premises) {
return new ConjunctionPremise(premises);
}
/**
* Shorthand for {@link #either(Predicate) either(}{@link #equalTo(Object) equalTo(o))}.
*
* @see #either(Predicate)
* @see Disjunction
*/
public static <T> Disjunction<T> either(T o) { return either(equalTo(o)); }
/**
* Create a OR-expression of several predicates, starting with the one
* given to this method.
*
* @see Disjunction
* @see #anyOf(Predicate...)
* @param predicate The first predicate.
* @return a new predicate which may be used to build up an OR-expression by
* chaining the {@link Disjunction#or(Predicate) or(anotherPredicate)} method.
*/
public static <T> Disjunction<T> either(Predicate<T> predicate) {
return new Disjunction<T>(predicate);
}
/**
* Create a OR-expression of several {@link Fn0 Fn0<Boolean>s},
* starting with the one given to this method.
*
* @see DisjunctionPremise
* @param premise The first <code>Fn0<Boolean></code>.
* @return a new <code>Fn0<Boolean></code> which may be used to build up an OR-expression by
* chaining the {@link DisjunctionPremise#or(Fn0) or(anotherPremise)} method.
*/
public static DisjunctionPremise either(Fn0<Boolean> premise) {
return new DisjunctionPremise(premise);
}
/**
* Shorthand for
* {@link #anyOf(Predicate...) anyOf(}{@link #equalTo(Object) equalTo(o1), equalTo(o2), ..., equalTo(on))}
*
* @param objects the candidate objects for equivalence check.
* @see Disjunction
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> Disjunction<T> anyOf(T ... objects) {
@SuppressWarnings("unchecked")
Predicate<T>[] equalToPredicates = on(objects)
.map(new Fn<T, Predicate<T>>() { @Override public Predicate<T> $(T o) { return equalTo(o); }})
.collect().toArray(new Predicate[objects.length]);
return anyOf(equalToPredicates);
}
/**
* Compose an OR-expression of several predicates.
*
* @see Disjunction
* @param predicates the predicates.
* @return a new predicate which is the disjunction (OR) of the given predicates.
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> Disjunction<T> anyOf(Predicate<? super T> ... predicates) {
return new Disjunction<>(predicates);
}
/**
* Compose an OR-expression of several {@link Fn0 Fn0<Boolean>s}.
*
* @see DisjunctionPremise
* @param premises the <code>Fn0<Boolean>s</code>.
* @return a new <code>Fn0<Boolean>s</code> which is the disjunction (OR) of the given premises.
*/
@SafeVarargs
@SuppressWarnings("varargs")
public static DisjunctionPremise anyOf(Fn0<Boolean> ... premises) {
return new DisjunctionPremise(premises);
}
/**
* Evaluate if all elements satisfies a predicate, i.e. the <em>Universal quantifier function</em>.
* Note that the predicate
*
* @param predicate The predicate which will evaluate all elements.
* @return a predicate which evaluates to <code>true</code> if all elements evaluates
* to true by the given predicate, false if any evaluates to <code>false</code>.
*/
public static <E, I extends Iterable<E>> Predicate<I> all(final Predicate<? super E> predicate) {
return new Predicate<I>() { @Override public boolean $(I iterable) {
return on(iterable).filter(not(predicate)).isEmpty(); }};}
/**
* Shorthand for {@link #exists(Predicate) exists(}{@link #equalTo(Object) equalTo(element))}
*
* @param element The element to look for in an {@link Iterable}.
* @return a predicate which evaluates to <code>true</code> if an element equal to the given
* element is found, <code>false</code> otherwise.
*/
public static <E, I extends Iterable<E>> Predicate<I> exists(E element) { return exists(equalTo(element)); }
/**
* Evaluate if an element exists, i.e. the <em>Existential quantifier function</em>.
*
* @param element The existance-deciding predicate.
* @return a predicate which evaluates to <code>true</code> if any element evaluates
* to true by the given predicate, <code>false</code> otherwise.
*/
public static <E, I extends Iterable<E>> Predicate<I> exists(final Predicate<? super E> element) {
return new Predicate<I>() { @Override public boolean $(I iterable) {
return on(iterable).exists(element); }};}
/**
* A synonym for {@link #equalTo(Object)}.
*/
public static <T> Predicate<T> is(T value) { return equalTo(value); }
/**
* Equality predicate, checks if values are equal to the given value.
*
* @param value the value the predicate should check for equality against.
*/
public static <T> Predicate<T> equalTo(final T value) { return equalTo(always(value)); }
/**
* Equality predicate, checks if values are equal to the value computed from the given {@link Fn0}.
*
* @param value the {@link Fn0} which will compute the value to check for equality against on each
* application of the predicate.
*/
public static <T> Predicate<T> equalTo(final Fn0<? super T> value) {
return new Predicate<T>() { @Override public boolean $(T input) {
return Objects.equals(input, value.$()); }}; }
/**
* Predicate evaluating if values are less than a given value.
*
* @param value the right operand, i.e. the predicate will evaluate
* if values are less than this value.
* @return the "<em>< value</em>" predicate
*/
public static <T extends Comparable<? super T>> Predicate<T> lessThan(final T value) {
return new Predicate<T>() { @Override public boolean $(T candidate) { return candidate.compareTo(value) < 0; }}; }
/**
* Predicate evaluating if values are equal to or less than a given value.
*
* @param value the right operand, i.e. the predicate will evaluate
* if values are equal to or less than this value.
* @return the "<em>=< value</em>" predicate
*/
public static <T extends Comparable<? super T>> Predicate<T> equalOrLessThan(T value) {
return either(equalTo(value)).or(lessThan(value)); }
/**
* Predicate evaluating if values are greater than a given value.
*
* @param value the right operand, i.e. the predicate will evaluate
* if values are greater than this value.
* @return the "<em>> value</em>" predicate
*/
public static <T extends Comparable<? super T>> Predicate<T> greaterThan(final T value) {
return new Predicate<T>() { @Override public boolean $(T candidate) { return candidate.compareTo(value) > 0; }}; }
/**
* Predicate evaluating if values are equal to or greater than a given value.
*
* @param value the right operand, i.e. the predicate will evaluate
* if values are equal to or greater than this value.
* @return the "<em>>= value</em>" predicate
*/
public static <T extends Comparable<? super T>> Predicate<T> equalOrGreaterThan(T value) {
return either(equalTo(value)).or(greaterThan(value)); }
/**
* Yields <code>true</code> for <code>null</code> values.
*/
public static final Predicate<Object> isNull = new Predicate<Object>() {
@Override public boolean $(Object value) { return value == null; }};
/**
* Yields <code>true</code> for all non-<code>null</code> values.
*/
public static final Predicate<Object> notNull = not(isNull);
/**
* A function to extract/derive several values from one object. The result of the
* extraction is an {@link Elements}s container of the least common supertype of
* the extractor {@link Fn}s' return types.
*
* @param extractors the {@link Fn}s which will extract values from each object passed
* to the function.
*
* @return the composed function which yields.
*/
@SafeVarargs
public static <T, E> Fn<T, Elements<E>> extract(final Fn<? super T, ? extends E> ... extractors) {
return new Fn<T, Elements<E>>() { @Override public Elements<E> $(T value) {
return on(new ExtractingIterable<T, E>(value, on(extractors))); }}; }
/**
* Yields the {@link String#valueOf(Object) string representation} of
* any object.
*/
public static final Fn<Object, String> toString = new Fn<Object, String>() {
@Override public String $(Object value) { return String.valueOf(value); }};
/**
* Yields the {@link Object#hashCode() hashCode} for objects, or 0 if <code>null</code>.
*/
public static final Fn<Object, Integer> hashCode = new Fn<Object, Integer>() {
@Override public Integer $(Object o) { return o != null ? o.hashCode() : 0; }};
/**
* Creates a "guarded" {@link Fn} using a {@link Predicate} to evaluate if the
* argument should be passed to the wrapped <code>Fn</code>. The function created
* by this method is essentially this ternary expression:
* <pre> condition(v) ? f(v) : null;</pre>
* To fall back to another value than <code>null</code>, call either {@link When#orElse(Fn) .orElse(Fn)}
* or {@link When#orElse(Object) .orElse(other)} on the returned object.
*
* @param condition Only when this evaluates to <code>true</code> will the function argument
* be applied to the given {@link Fn}.
* @param fn The {@link Fn} to apply if <code>condition</code> evaluates to <code>true</code>
*/
public static <I, O> When<I, O> when(Predicate<? super I> condition, Fn<? super I, ? extends O> fn) {
return new When<>(condition, fn);
}
/**
* Compose a chain of several functions into one {@link Fn}, where the result of
* each function is passed to its successor, and the last will yield the
* actual result of the chain. Use {@link FnChain#then(Fn) .then(Fn)} to append
* functions to the chain.
*
* <p><strong>Note:</strong> The chain does no internal inspection of the intermediate
* results passed to the next function, which means that any function which may
* return <code>null</code>, <em>must</em> have a <code>null</code>-safe successor
* function.
*
* @param fn The first function in the chain.
* @return the given function as the first function in a chain.
*/
public static final <I, O> FnChain<I, O> first(Fn<I, O> fn) {
return FnChain.chain(fn);
}
/**
* Compose a chain of several functions into one {@link Fn2}, where the result of
* each function is passed to its successor, and the last will yield the
* actual result of the chain. Use {@link Fn2Chain#then(Fn) .then(Fn)} to append
* functions to the chain.
*
* <p><strong>Note:</strong> The chain does no inspection of the intermediate
* results passed to the next function, which means that any function which may
* return <code>null</code>, <em>must</em> have a <code>null</code>-safe successor
* function.
*
* @param fn2 The first function in the chain.
* @return the given function as the first function in a chain.
*/
public static final <I1, I2, O> Fn2Chain<I1, I2, O, O> first(Fn2<I1, I2, O> fn2) {
return new Fn2Chain<>(fn2, NOP.<O>fn());
}
/**
* Compose several {@link Runnable}s as a single Runnable which will
* execute the given Runnables in sequence.
*
* @param runnable The first Runnable.
* @return the given Runnable as the first Runnable in a sequence.
*/
public static final RunnableChain first(Runnable runnable) {
return new RunnableChain(runnable, NOP.runnable);
}
/**
* Chain several {@link Do}s to be executed in sequence.
*
* @param action The first {@link Do} to execute.
* @return The given <code>Do</code> as the first <code>Do</code> in a sequence.
*/
public static <V> DoChain<V> first(Do<V> action) {
return new DoChain<>(action, NOP.doNothing);
}
/**
* Create a function which always yields the given value.
*
* @param value The value to yield.
*/
public static <I1, I2, V> Constant<I1, I2, V> always(V value) { return new Constant<>(value); }
/**
* Create a predicate which always yields the given <code>boolean</code> value.
*
* @param bool The <code>boolean</code> value to yield.
*/
@SuppressWarnings("unchecked")
public static <T> Predicate<T> always(boolean bool) {
return (Predicate<T>) (bool ? Predicate.Always.yes() : Predicate.Always.no());
}
/**
* Create a function which always throw the given exception. If the
* exception is not a {@link RuntimeException} it will be wrapped as such.
*
* @param ex The exception to throw.
*/
public static <I1, I2, O> Throw<I1, I2, O> alwaysThrow(Exception ex) { return new Throw<>(ex); }
/**
* Evaluates if objects are contained in the given <code>Iterable</code>.
*/
public static <T> Predicate<T> containedIn(final Iterable<? extends T> iterable) {
if (iterable == null) return Always.<T>no();
if (iterable instanceof Collection) {
final Collection<? extends T> collection = (Collection<? extends T>) iterable;
return collection.isEmpty() ? Always.<T>no() : new Predicate<T>() {
@Override public boolean $(T value) { return collection.contains(value); }};
} else {
final Elements<? extends T> elements = on(iterable);
return new Predicate<T>() {
@Override public boolean $(T value) { return elements.exists(is(value)); }};
}
}
private Base() {}
}