package com.googlecode.totallylazy.functions; import com.googlecode.totallylazy.*; import com.googlecode.totallylazy.comparators.Comparators; import com.googlecode.totallylazy.predicates.Predicate; import com.googlecode.totallylazy.reflection.Methods; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.util.Comparator; import java.util.Iterator; import java.util.concurrent.Callable; import static com.googlecode.totallylazy.reflection.Methods.method; import static com.googlecode.totallylazy.Option.identity; import static com.googlecode.totallylazy.Sequences.sequence; public final class Callables { public static <T> Function1<Value<T>, T> value() { return value -> value.value(); } public static <T> Function1<Value<T>, T> value(Class<T> aClass) { return value(); } public static <T, R> Function1<T, R> asCallable1(final Callable<? extends R> callable) { return t -> callable.call(); } public static <T> Unary<T> nullGuard(final Function1<? super T, ? extends T> callable) { return o -> { if (o == null) return null; return callable.call(o); }; } public static <T> Unary<Sequence<T>> reduceAndShift(final Function2<? super T, ? super T, ? extends T> action) { return values -> values.tail().append(values.reduceLeft(action)); } public static <T, S> Function1<T, S> cast(final Class<? extends S> aClass) { return t -> aClass.cast(t); } public static <T, S> Function1<T, S> cast() { return Unchecked::cast; } public static Function1<Object, Class<?>> toClass() { return o -> { if(o == null) return Void.class; return o.getClass(); }; } public static <T, R extends Comparable<? super R>> Comparator<T> ascending(final Function1<? super T, ? extends R> callable) { return Comparators.ascending(callable); } public static <T, R extends Comparable<? super R>> Comparator<T> descending(final Function1<? super T, ? extends R> callable) { return Comparators.descending(callable); } public static Function1<Object, Integer> size() { return length(); } public static Function1<Object, Integer> length() { return instance -> { Class aClass = instance.getClass(); if (aClass.isArray()) { return Array.getLength(instance); } return sequence(method(instance, "size"), method(instance, "length")). flatMap(identity(Method.class)). headOption(). map(Methods.<Integer>invokeOn(instance)). getOrElse(Callables.<Integer>callThrows(new UnsupportedOperationException("Does not support fields yet"))); }; } public static <T> Unary<Sequence<T>> realise() { return Sequence<T>::realise; } public static <T> Function1<First<T>, T> first(Class<T> aClass) { return first(); } public static <T> Function1<First<T>, T> first() { return First::first; } public static <T> Function1<Iterable<T>, T> last(Class<T> t) { return last(); } public static <T> Function1<Iterable<T>, T> last() { return Sequences::last; } public static <F, S, R> Function1<Pair<F, S>, Pair<R, S>> first(final Function1<? super F, ? extends R> firstCallable, Class<S> sClass) { return first(firstCallable); } public static <F, S, R> Function1<Pair<F, S>, Pair<R, S>> first(final Function1<? super F, ? extends R> firstCallable) { return pair -> Pair.pair(firstCallable.call(pair.first()), pair.second()); } public static <T> Function1<Second<T>, T> second(Class<T> aClass) { return second(); } public static <T> Function1<Second<T>, T> second() { return second -> second.second(); } public static <F, S, R> Function1<Pair<F, S>, Pair<F, R>> second(final Function1<? super S, ? extends R> secondCallable) { return pair -> Pair.pair(pair.first(), secondCallable.call(pair.second())); } public static <T> Function1<Third<T>, T> third(Class<T> aClass) { return third(); } public static <T> Function1<Third<T>, T> third() { return third -> third.third(); } public static <F, S, T, R> Function1<Triple<F, S, T>, Triple<F, S, R>> third(final Function1<? super T, ? extends R> thirdCallable) { return triple -> Triple.triple(triple.first(), triple.second(), thirdCallable.call(triple.third())); } public static <T> Function1<Fourth<T>, T> fourth(Class<T> aClass) { return fourth(); } public static <T> Function1<Fourth<T>, T> fourth() { return fourth -> fourth.fourth(); } public static <F, S, T, Fo, R> Function1<Quadruple<F, S, T, Fo>, Quadruple<F, S, T, R>> fourth(final Function1<? super Fo, ? extends R> fourthCallable) { return quadruple -> Quadruple.quadruple(quadruple.first(), quadruple.second(), quadruple.third(), fourthCallable.call(quadruple.fourth())); } public static <T> Function1<Fifth<T>, T> fifth(Class<T> aClass) { return fifth(); } public static <T> Function1<Fifth<T>, T> fifth() { return fifth -> fifth.fifth(); } public static <F, S, T, Fo, Fi, R> Function1<Quintuple<F, S, T, Fo, Fi>, Quintuple<F, S, T, Fo, R>> fifth(final Function1<? super Fi, ? extends R> callable) { return quintuple -> Quintuple.quintuple(quintuple.first(), quintuple.second(), quintuple.third(), quintuple.fourth(), callable.call(quintuple.fifth())); } public static <T> Function1<Iterable<T>, T> head() { return iterable -> Sequences.head(iterable); } public final static Function1<Object, String> toString = new Function1<Object, String>() { public final String call(final Object value) { return value != null ? value.toString() : null; } @Override public String toString() { return "toString"; } }; public static <T> Function1<Object, String> asString() { return toString; } public static final Curried2<Integer, Object, Integer> hashCode = (hash, value) -> { if (value == null) return hash * 19; int current = value.hashCode(); return (current == 0 ? 19 : current) * hash; }; public static Curried2<Integer, Object, Integer> asHashCode() { return hashCode; } public static <T> Function1<Iterable<T>, Iterator<T>> asIterator() { return iterable -> iterable.iterator(); } public static <T> Function1<Iterator<T>, Iterable<T>> asIterable() { return iterator -> Sequences.forwardOnly(iterator); } public static <T> Function0<T> returns(final T t) { return Functions.returns(t); } public static <T, R> Function1<T, R> ignoreAndReturn(final R r) { return returns1(r); } public static <A, B> Function1<A, B> returns1(B result) { return Functions.returns1(result); } public static <A, B, C> Curried2<A, B, C> returns2(C result) { return Functions.returns2(result); } public static <T> Unary<T> returnArgument() { return Functions.identity(); } public static <T> Unary<T> returnArgument(final Class<T> aClass) { return returnArgument(); } public static <T> Function0<T> aNull(final Class<T> aClass) { return () -> null; } public static <T> Function0<T> callThrows(final Exception e) { return () -> { throw e; }; } public static <T> Function0<T> callThrows(final Exception e, final Class<T> aClass) { return callThrows(e); } public static <T> Function1<Callable<T>, T> call() { return callable -> callable.call(); } public static <T> Function1<Callable<T>, T> call(final Class<T> aClass) { return call(); } public static <T, R> Function1<Function1<T, R>, R> callWith(final T value) { return callable -> callable.call(value); } public static <A, B, C> Function0<C> deferApply(final Function2<? super A, ? super B, ? extends C> callable, final A a, final B b) { return () -> callable.call(a, b); } public static <A, B> Function0<B> deferApply(final Function1<? super A, ? extends B> callable, final A value) { return () -> callable.call(value); } public static <A, B> Function1<A, Function0<B>> deferReturn(final Function1<? super A, ? extends B> callable) { return a -> deferApply(callable, a); } public static <A, B, C> Function1<B, C> apply(final Function2<? super A, ? super B, ? extends C> callable, final A value) { return Functions.apply(callable, value); } public static <A, B, C, D> Curried2<B, C, D> apply(final Function3<? super A, ? super B, ? super C, ? extends D> callable, final A value) { return Functions.apply(callable, value); } public static <A, B, C> Function1<A, Function1<B, C>> curry(final Function2<? super A, ? super B, ? extends C> callable) { return (Curried2<A,B,C>) callable::call; } public static <A, B, C, D> Function1<A, Function1<B, Function1<C, D>>> curry(final Function3<? super A, ? super B, ? super C, ? extends D> callable) { return (Curried3<A,B,C,D>) callable::call; } public static <A, B, C> Curried2<A, B, C> uncurry2(final Function1<? super A, ? extends Function1<? super B, ? extends C>> callable) { return Functions.uncurry2(callable); } public static <A, B, C, D> Curried3<A, B, C, D> uncurry3(final Function1<? super A, ? extends Function1<? super B, ? extends Function1<? super C, ? extends D>>> callable) { return Functions.uncurry3(callable); } public static <L> Function1<Either<L, ?>, L> left(Class<L> aClass) { return left(); } public static <L> Function1<Either<L, ?>, L> left() { return either -> either.left(); } public static <R> Function1<Either<?, R>, R> right(Class<R> aClass) { return right(); } public static <R> Function1<Either<?, R>, R> right() { return either -> either.right(); } public static <A, B, C> Curried2<B, A, C> flip(final Function2<? super A, ? super B, ? extends C> callable) { return (s, t) -> callable.call(t, s); } public static <A, B, C> Function1<A, C> compose(final Function1<? super A, ? extends B> first, final Function1<? super B, ? extends C> second) { return a -> second.call(first.call(a)); } public static <A, B> Function1<A, B> compose(final Function1<? super A, ?> ignoreResult, final Callable<? extends B> callable) { return a -> { ignoreResult.call(a); return callable.call(); }; } public static <A, B> Function1<A, B> doThen(final Function1<? super A, ?> ignoreResult, final Callable<? extends B> callable) { return compose(ignoreResult, callable); } public static <A, B> Function0<B> compose(final Callable<? extends A> first, final Function1<? super A, ? extends B> second) { return () -> second.call(first.call()); } public static <A, B> Function1<A, B> interruptable(final Function1<? super A, ? extends B> function) { return Functions.interruptable(function); } public static <A, B, C> Function1<Pair<A, B>, C> pair(final Function2<? super A, ? super B, ? extends C> function) { return Functions.pair(function); } public static <A, B, C> Curried2<A, B, C> unpair(final Function1<? super Pair<? extends A, ? extends B>, ? extends C> function) { return Functions.unpair(function); } public static <A, B, C, D> Function1<Triple<A, B, C>, D> triple(final Function3<? super A, ? super B, ? super C, ? extends D> callable) { return Functions.triple(callable); } public static <A, B, C, D> Curried3<A, B, C, D> untriple(final Function1<? super Triple<? extends A, ? extends B, ? extends C>, ? extends D> callable) { return Functions.untriple(callable); } public static <L, R> Function1<L, Either<L, R>> asLeft() { return Either.functions.asLeft(); } public static <L, R> Function1<R, Either<L, R>> asRight() { return Either.functions.asRight(); } public static <T> Unary<T> replace(final Predicate<? super T> predicate, final Function1<? super T, ? extends T> callable) { return when(predicate, callable); } public static <T> Unary<T> when(final Predicate<? super T> predicate, final Function1<? super T, ? extends T> callable) { return value -> predicate.matches(value) ? callable.call(value) : value; } }