package org.osgl; import org.osgl.cache.CacheService; import org.osgl.concurrent.ContextLocal; import org.osgl.exception.*; import org.osgl.util.*; import java.io.*; import java.lang.annotation.Annotation; import java.lang.reflect.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; /** * <code>Osgl</code> is the umbrella namespace aggregates core utilities of OSGL toolkit: * <ul> * <li>Function interfaces and base implementations</li> * <li>currying utilities </li> * <li>Tuple and multi-elements tupbles</li> * <li>Option</li> * <li>core utilities like ts()</li> * <li>predefined functions aggregated in the <code>Osgl.F</code> namespace</li> * </ul> * <p>More about function interface</p> * <p>Under <code>Osgl</code>, there are six function interfaces defined, from <code>Osgl.Func0</code> * to <code>Osgl.Func5</code>, where the last digit means the number of parameters the function * is applied to. For example, the <code>apply</code> method of <code>Func0</code> takes * no parameter while that of <code>Func2</code> takes two parameters. All these function * interfaces are defined with generic type parameters, corresponding to the type of all * parameters and that of the return value. For procedure (a function that does not return anything), * the user application could use <code>Void</code> as the return value type, and return * <code>null</code> in the <code>apply</code> method implementation.</p> * <p>For each function interface, OSGL provide a base class, from <code>Osgl.F0</code> to * <code>Osgl.F5</code>. Within the base class, OSGL implement several utility methods, including</p> * <ul> * <li>currying methods, returns function takes fewer parameter with given parameter specified</li> * <li>chain, returns composed function with a function takes the result of this function</li> * <li>andThen, returns composed function with an array of same signature functions</li> * <li>breakOut, short cut the function execution sequence by throwing out a {@link Break} instance</li> * </ul> * <p>Usually user application should define their function implementation by extending the base class in order * to benefit from the utility methods; however in certain cases, e.g. a function implementation already * extends another base class, user implementation cannot extends the base function class, OSGL provides * easy way to convert user's implementation to corresponding base class implementation, here is one * example of how to do it:</p> * <pre> * void foo(Osgl.Func2<Integer, String> f) { * F2<Integer, String> newF = Osgl.f2(f); * newF.chain(...); * ... * } * </pre> * <p>Dumb functions, for certain case where a dumb function is needed, OSGL defines dumb function instances for * each function interface, say, from <code>Osgl.F0</code> to <code>Osgl.F5</code>. Note the name of the dumb function * instance is the same as the name of the base function class. But they belong to different concept, class and * instance, so there is no conflict in the code. For each dumb function instance, a corresponding type safe * version is provided, <code>Osgl.f0()</code> to <code>Osgl.f5()</code>, this is the same case of * <code>java.util.Collections.EMPTY_LIST</code> and <code>java.util.Collections.emptyList()</code></p> * <p>Utility methods</p> * * @author Gelin Luo * @version 0.8 */ public class Osgl implements Serializable { public static final Osgl INSTANCE = new Osgl(); protected Osgl() { } private Object readResolve() throws ObjectStreamException { return INSTANCE; } @Override public final boolean equals(Object obj) { return obj == this || obj instanceof Osgl; } @Override public final int hashCode() { return Osgl.class.hashCode(); } @Override public final String toString() { return "OSGL"; } // --- Functions and their default implementations /** * The base for all Fx function class implemention */ public static abstract class FuncBase { /** * Return a {@link Break} with payload. Here is an example of how to use this method: * <pre> * myData.accept(new Visitor(){ * public void apply(T e) { * if (...) { * throw breakOut(e); * } * } * }) * </pre> * * @param payload the object passed through the <code>Break</code> * @return a {@link Break} instance */ protected final Break breakOut(Object payload) { return new Break(payload); } } /** * Define a function that apply to no parameter (strictly this is not a function) * * @param <R> the generic type of the return value, could be <code>Void</code> * @see Osgl.Function * @see Osgl.Func2 * @see Osgl.Func3 * @see Osgl.Func4 * @see Osgl.Func5 * @see F0 * @since 0.2 */ public interface Func0<R> { /** * user application to implement main logic of applying the function * * @return the Result instance of type R after appplying the function * @throws NotAppliedException if the function doesn't apply to the current context * @throws Break to short cut collecting operations (fold/reduce) on an {@link org.osgl.util.C.Traversable container} */ R apply() throws NotAppliedException, Break; } /** * Default implementation for {@link Osgl.Func0}. Implementation of {@link Osgl.Func0} should * (nearly) always extend to this class instead of implement the interface directly * * @since 0.2 */ public static abstract class F0<R> extends FuncBase implements Func0<R> { /** * Applies this partial function to the given argument when it is contained in the function domain. * Applies fallback function where this partial function is not defined, i.e. any * {@link java.lang.RuntimeException} is captured * * @param fallback  if {@link RuntimeException} captured then apply this fallback function * @return the result of this function or the fallback function application */ public R applyOrElse(F0<? extends R> fallback) { try { return apply(); } catch (RuntimeException e) { return fallback.apply(); } } /** * Returns a composed function that applies this function to it's input and * then applies the {@code after} function to the result. If evaluation of either * function throws an exception, it is relayed to the caller of the composed * function. * * @param after the function applies after this function is applied * @param <T> the type of the output of the {@code before} function * @return the composed function * @throws NullPointerException if {@code before} is null */ public <T> F0<T> andThen(final Function<? super R, ? extends T> after) { E.NPE(after); final F0<R> me = this; return new F0<T>() { @Override public T apply() { return after.apply(me.apply()); } }; } /** * Returns a composed function that applied, in sequence, this function and * all functions specified one by one. If applying anyone of the functions * throws an exception, it is relayed to the caller of the composed function. * If an exception is thrown out, the following functions will not be applied. * <p>When apply the composed function, the result of the last function * is returned</p> * * @param fs a sequence of function to be applied after this function * @return a composed function */ public F0<R> andThen(final Func0<? extends R>... fs) { if (fs.length == 0) { return this; } final F0<R> me = this; return new F0<R>() { @Override public R apply() { R r = me.apply(); for (Func0<? extends R> f : fs) { r = f.apply(); } return r; } }; } /** * Returns a composed function that when applied, try to apply this function first, in case * a {@link java.lang.RuntimeException} is captured apply to the fallback function specified. This * method helps to implement partial function * * @param fallback the function to applied if this function doesn't apply in the current situation * @return the final result */ public F0<R> orElse(final Func0<? extends R> fallback) { final F0<R> me = this; return new F0<R>() { @Override public R apply() { try { return me.apply(); } catch (RuntimeException e) { return fallback.apply(); } } }; } /** * Turns this partial function into a plain function returning an Option result. * * @return a function that takes an argument x to Some(this.apply(x)) if this can be applied, and to None otherwise. */ public F0<Option<R>> lift() { final F0<R> me = this; return new F0<Option<R>>() { @Override public Option<R> apply() { try { return Osgl.some(me.apply()); } catch (RuntimeException e) { return Osgl.none(); } } }; } } /** * The class adapt traditional Factory to Function * * @param <T> the type of the instance been created by the factory */ public static abstract class Factory<T> extends F0<T> { @Override public T apply() throws NotAppliedException, Break { return create(); } /** * The abstract create method that will be called by * the {@link #apply()} method * * @return an instance the factory create */ public abstract T create(); } @SuppressWarnings("unchecked") public static <T> Factory<T> factory(final Func0<T> func) { if (func instanceof Factory) { return (Factory<T>) func; } return new Factory<T>() { @Override public T create() { return func.apply(); } }; } private static class DumbF0 extends F0<Object> implements Serializable { private static final long serialVersionUID = 2856835860950L; @Override public Object apply() throws NotAppliedException, Break { return null; } } /** * A dumb function for {@link Osgl.Func0} that does nothing and return <code>null</code> * * @see #f0() * @since 0.2 */ public static final F0 F0 = new DumbF0(); /** * Return a dumb function for {@link Osgl.Func0}. This is the type-safe version of {@link #F0} * * @param <T> a generic type that matches whatever type required by the context of applying the function * @return A dumb function that always return {@code null} * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> F0<T> f0() { return (F0<T>) F0; } /** * Convert a general {@link Osgl.Func0} typed function to {@link F0} type * * @param f0 a function of type {@link Func0} that returns type R value * @param <R> the generic type of the return value when applying function f0 * @return a {@link F0} type that is equaivlent to function f0 * @since 0.2 */ @SuppressWarnings("unchecked") public static <R> F0<R> f0(final Func0<? extends R> f0) { E.NPE(f0); if (f0 instanceof F0) { return (F0<R>) f0; } return new F0<R>() { @Override public R apply() { return f0.apply(); } }; } /** * Define a function structure that accept one parameter. This interface is created to make it * easily migrate to Java 8 in the future * * @param <T> the type of input parameter * @param <U> the type of the return value when this function applied to the parameter(s) * @see Osgl.Func0 * @see Osgl.Function * @see Osgl.Func2 * @see Osgl.Func3 * @see Osgl.Func4 * @see Osgl.Func5 * @see F1 * @since 0.2 */ public interface Function<T, U> { /** * Apply this function to <T> type parameter. * <p>In case implementing a partial function, it can throw out an * {@link NotAppliedException} if the function is not defined for * the given parameter(s)</p> * * @param t the argument * @return {@code U} type result * @throws NotAppliedException if the function doesn't apply to the parameter(s) * @throws Break to short cut collecting operations (fold/reduce) on an {@link org.osgl.util.C.Traversable container} */ U apply(T t) throws NotAppliedException, Break; } /** * Alias of {@link Function} * * @param <P1> the argument type * @param <R> the return value type * @since 0.2 */ public interface Func1<P1, R> extends Function<P1, R> { } /** * A {@link Function} function that support {@link #times(int)} operation * * @param <P1> the type of parameter the function applied to * @param <R> the type of return value of the function */ public interface MultiplicableFunction<P1, R> extends Function<P1, R> { /** * Returns a function with {@code n} times factor specified. When the function * returned applied to a param, the effect is the same as apply this function * {@code n} times to the same param * * @param n specify the times factor * @return the new function */ MultiplicableFunction<P1, R> times(int n); } /** * See <a href="http://en.wikipedia.org/wiki/Bijection">http://en.wikipedia.org/wiki/Bijection</a>. A * {@code Bijection} (mapping from {@code X} to {@code Y} is a special {@link Function} that has an * inverse function by itself also a {@code Bijection} mapping from {@code Y} to {@code X} * * @param <X> the type of parameter * @param <Y> the type of return value */ public interface Bijection<X, Y> extends Function<X, Y> { /** * Returns the inverse function mapping from {@code Y} back to {@code X} * * @return a function that map {@code Y} type element to {@code X} type element */ Bijection<Y, X> invert(); } /** * Base implementation of {@link Osgl.Function} function. User application should * (nearly) always make their implementation extend to this base class * instead of implement {@link Osgl.Function} directly * * @since 0.2 */ public static abstract class F1<P1, R> extends FuncBase implements Func1<P1, R>, Bijection<P1, R>, MultiplicableFunction<P1, R> { @Override public Bijection<R, P1> invert() { throw new NotAppliedException(); } @Override public MultiplicableFunction<P1, R> times(final int n) { E.illegalArgumentIf(n < 1); if (n == 1) return this; final F1<P1, R> me = this; return new F1<P1, R>() { @Override public R apply(P1 p1) throws NotAppliedException, Break { R r = null; for (int i = 0; i < n; ++i) { r = me.apply(p1); } return r; } }; } /** * Applies this partial function to the given argument when it is contained in the function domain. * Applies fallback function where this partial function is not defined. * * @param p1 the argument this function to be applied * @param fallback the function to be applied to the argument p1 when this function failed with any runtime exception * @return the result of this function or the fallback function application */ public R applyOrElse(P1 p1, F1<? super P1, ? extends R> fallback) { try { return apply(p1); } catch (RuntimeException e) { return fallback.apply(p1); } } public final F0<R> curry(final P1 p1) { final Function<P1, R> me = this; return new F0<R>() { @Override public R apply() { return me.apply(p1); } }; } /** * Returns a composed function that applies this function to it's input and * then applies the {@code after} function to the result. If evaluation of either * function throws an exception, it is relayed to the caller of the composed * function. * * @param <T> the type of return value of the new composed function * @param after the function applies after this function is applied * @return the composed function * @throws NullPointerException if @{code after} is null */ public <T> F1<P1, T> andThen(final Function<? super R, ? extends T> after) { E.NPE(after); final Function<P1, R> me = this; return new F1<P1, T>() { @Override public T apply(P1 p1) { return after.apply(me.apply(p1)); } }; } /** * Returns a composed function that applied, in sequence, this function and * all functions specified one by one. If applying anyone of the functions * throws an exception, it is relayed to the caller of the composed function. * If an exception is thrown out, the following functions will not be applied. * <p>When apply the composed function, the result of the last function * is returned</p> * * @param afters a sequence of function to be applied after this function * @return a composed function */ public F1<P1, R> andThen(final Function<? super P1, ? extends R>... afters) { if (0 == afters.length) { return this; } final F1<P1, R> me = this; return new F1<P1, R>() { @Override public R apply(P1 p1) { R r = me.apply(p1); for (Function<? super P1, ? extends R> f : afters) { r = f.apply(p1); } return r; } }; } /** * Returns a composed function that when applied, try to apply this function first, in case * a {@link NotAppliedException} is captured apply to the fallback function specified. This * method helps to implement partial function * * @param fallback the function to applied if this function doesn't apply to the parameter(s) * @return the composed function */ public F1<P1, R> orElse(final Function<? super P1, ? extends R> fallback) { final F1<P1, R> me = this; return new F1<P1, R>() { @Override public R apply(P1 p1) { try { return me.apply(p1); } catch (RuntimeException e) { return fallback.apply(p1); } } }; } /** * Returns an {@code F0<R>>} function by composing the specified {@code Func0<P1>} function * with this function applied last * * @param before the function to be applied first when applying the return function * @return an new function such that f() == apply(f0()) */ public F0<R> compose(final Func0<? extends P1> before) { final F1<P1, R> me = this; return new F0<R>() { @Override public R apply() { return me.apply(before.apply()); } }; } /** * Returns an {@code F1<X1, R>>} function by composing the specified * {@code Function<X1, P1>} function with this function applied last * * @param before the function to be applied first when applying the return function * @param <X1> type of argument takes by the {@code before} function * @return an new function such that f(a) == apply(f1(a)) */ public <X1> F1<X1, R> compose(final Function<? super X1, ? extends P1> before) { final F1<P1, R> me = this; return new F1<X1, R>() { @Override public R apply(X1 x1) { return me.apply(before.apply(x1)); } }; } /** * Returns an {@code F2<X1, X2, R>>} function by composing the specified * {@code Func2<X1, X2, P1>} function with this function applied last * * @param <X1> the type of first param the new function applied to * @param <X2> the type of second param the new function applied to * @param before the function to be applied first when applying the return function * @return an new function such that f(x1, x2) == apply(f1(x1, x2)) */ public <X1, X2> F2<X1, X2, R> compose(final Func2<? super X1, ? super X2, ? extends P1> before) { final F1<P1, R> me = this; return new F2<X1, X2, R>() { @Override public R apply(X1 x1, X2 x2) { return me.apply(before.apply(x1, x2)); } }; } /** * Returns an {@code F3<X1, X2, X3, R>>} function by composing the specified * {@code Func3<X1, X2, X3, P1>} function with this function applied last * * @param <X1> the type of first param the new function applied to * @param <X2> the type of second param the new function applied to * @param <X3> the type of third param the new function applied to * @param before the function to be applied first when applying the return function * @return an new function such that f(x1, x2, x3) == apply(f1(x1, x2, x3)) */ public <X1, X2, X3> F3<X1, X2, X3, R> compose(final Func3<? super X1, ? super X2, ? super X3, ? extends P1> before) { final F1<P1, R> me = this; return new F3<X1, X2, X3, R>() { @Override public R apply(X1 x1, X2 x2, X3 x3) { return me.apply(before.apply(x1, x2, x3)); } }; } /** * Returns an {@code F3<X1, X2, X3, X4, R>>} function by composing the specified * {@code Func3<X1, X2, X3, X4, P1>} function with this function applied last * * @param <X1> the type of first param the new function applied to * @param <X2> the type of second param the new function applied to * @param <X3> the type of third param the new function applied to * @param <X4> the type of fourth param the new function applied to * @param before the function to be applied first when applying the return function * @return an new function such that f(x1, x2, x3, x4) == apply(f1(x1, x2, x3, x4)) */ public <X1, X2, X3, X4> F4<X1, X2, X3, X4, R> compose(final Func4<? super X1, ? super X2, ? super X3, ? super X4, ? extends P1> before) { final F1<P1, R> me = this; return new F4<X1, X2, X3, X4, R>() { @Override public R apply(X1 x1, X2 x2, X3 x3, X4 x4) { return me.apply(before.apply(x1, x2, x3, x4)); } }; } /** * Returns an {@code F3<X1, X2, X3, X4, X5, R>>} function by composing the specified * {@code Func3<X1, X2, X3, X4, X5, P1>} function with this function applied last * * @param <X1> the type of first param the new function applied to * @param <X2> the type of second param the new function applied to * @param <X3> the type of third param the new function applied to * @param <X4> the type of fourth param the new function applied to * @param <X5> the type of fifth param the new function applied to * @param before the function to be applied first when applying the return function * @return an new function such that f(x1, x2, x3, x4, x5) == apply(f1(x1, x2, x3, x4, x5)) */ public <X1, X2, X3, X4, X5> F5<X1, X2, X3, X4, X5, R> compose(final Func5<? super X1, ? super X2, ? super X3, ? super X4, ? super X5, ? extends P1> before) { final F1<P1, R> me = this; return new F5<X1, X2, X3, X4, X5, R>() { @Override public R apply(X1 x1, X2 x2, X3 x3, X4 x4, X5 x5) { return me.apply(before.apply(x1, x2, x3, x4, x5)); } }; } /** * Turns this partial function into a plain function returning an Option result. * * @return a function that takes an argument x to Some(this.apply(x)) if this can be applied, and to None otherwise. */ public F1<P1, Option<R>> lift() { final F1<P1, R> me = this; return new F1<P1, Option<R>>() { @Override public Option<R> apply(P1 p1) { try { return Osgl.some(me.apply(p1)); } catch (RuntimeException e) { return Osgl.none(); } } }; } } private static class DumbF1 extends F1<Object, Object> implements Serializable { private static final long serialVersionUID = 2856835860951L; @Override public Object apply(Object o) throws NotAppliedException, Break { return null; } } /** * A dumb {@link Osgl.Function} implementation that does nothing and return null * * @see #f1() * @since 0.2 */ public static final F1 F1 = new DumbF1(); /** * The type-safe version of {@link #F1} * * @param <P1> the argument type * @param <R> the return value type * @return a dumb function {@link #F1} * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, R> F1<P1, R> f1() { return (F1<P1, R>) F1; } /** * Convert a general {@link Osgl.Function} function into a {@link F1} typed * function * * @param f1 the function that consumes {@code P1} and produce {@code R} * @param <P1> the argument type * @param <R> the return value type * @return whatever of type {@code R} * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, R> F1<P1, R> f1(final Function<? super P1, ? extends R> f1) { E.NPE(f1); if (f1 instanceof F1) { return (F1<P1, R>) f1; } return new F1<P1, R>() { @Override public R apply(P1 p1) { return f1.apply(p1); } @Override public MultiplicableFunction<P1, R> times(int n) { if (f1 instanceof MultiplicableFunction) { return ((MultiplicableFunction<P1, R>) f1).times(n); } return super.times(n); } }; } public static <X, Y> F1<X, Y> f1(final Bijection<X, Y> f1) { E.NPE(f1); if (f1 instanceof F1) { return (F1<X, Y>) f1; } return new F1<X, Y>() { @Override public Y apply(X p1) { return f1.apply(p1); } @Override public F1<Y, X> invert() { return Osgl.f1(f1.invert()); } @Override @SuppressWarnings("unchecked") public MultiplicableFunction<X, Y> times(int n) { if (f1 instanceof MultiplicableFunction) { return ((MultiplicableFunction<X, Y>) f1).times(n); } return super.times(n); } }; } /** * Define a function structure that accept two parameter * * @param <P1> the type of first parameter this function applied to * @param <P2> the type of second parameter this function applied to * @param <R> the type of the return value when this function applied to the parameter(s) * @see Osgl.Func0 * @see Osgl.Function * @see Osgl.Func3 * @see Osgl.Func4 * @see Osgl.Func5 * @see F2 * @since 0.2 */ public interface Func2<P1, P2, R> { /** * Apply the two params to the function * <p>In case implementing a partial function, it can throw out an * {@link NotAppliedException} if the function is not defined for * the given parameter(s)</p> * * @param p1 the first argument of type P1 * @param p2 the second argument of type P2 * @return the result of type R * @throws NotAppliedException if the function doesn't apply to the parameter(s) * @throws Break to short cut collecting operations (fold/reduce) on an {@link org.osgl.util.C.Traversable container} */ R apply(P1 p1, P2 p2) throws NotAppliedException, Break; } /** * Base implementation of {@link Osgl.Func2} function. User application should * (nearly) always make their implementation extend to this base class * instead of implement {@link Osgl.Func2} directly * * @since 0.2 */ public static abstract class F2<P1, P2, R> extends FuncBase implements Func2<P1, P2, R> { /** * Applies this partial function to the given argument when it is contained in the function domain. * Applies fallback function where this partial function is not defined. * * @param p1 the first param with type P1 * @param p2 the second param with type P2 * @param fallback the function to be called when an {@link RuntimeException} caught * @return the result of this function or the fallback function application */ public R applyOrElse(P1 p1, P2 p2, F2<? super P1, ? super P2, ? extends R> fallback) { try { return apply(p1, p2); } catch (RuntimeException e) { return fallback.apply(p1, p2); } } public final F0<R> curry(final P1 p1, final P2 p2) { final F2<P1, P2, R> me = this; return new F0<R>() { @Override public R apply() { return me.apply(p1, p2); } }; } public final F1<P1, R> curry(final P2 p2) { final F2<P1, P2, R> me = this; return new F1<P1, R>() { @Override public R apply(P1 p1) { return me.apply(p1, p2); } }; } /** * Returns a composed function from this function and the specified function that takes the * result of this function. When applying the composed function, this function is applied * first to given parameter and then the specified function is applied to the result of * this function. * * @param f the function takes the <code>R</code> type parameter and return <code>T</code> * type result * @param <T> the return type of function {@code f} * @return the composed function * @throws NullPointerException if <code>f</code> is null */ public <T> F2<P1, P2, T> andThen(final Function<? super R, ? extends T> f) { E.NPE(f); final Func2<P1, P2, R> me = this; return new F2<P1, P2, T>() { @Override public T apply(P1 p1, P2 p2) { R r = me.apply(p1, p2); return f.apply(r); } }; } /** * Returns a composed function that applied, in sequence, this function and * all functions specified one by one. If applying anyone of the functions * throws an exception, it is relayed to the caller of the composed function. * If an exception is thrown out, the following functions will not be applied. * <p>When apply the composed function, the result of the last function * is returned</p> * * @param fs a sequence of function to be applied after this function * @return a composed function */ public F2<P1, P2, R> andThen(final Func2<? super P1, ? super P2, ? extends R>... fs) { if (0 == fs.length) { return this; } final Func2<P1, P2, R> me = this; return new F2<P1, P2, R>() { @Override public R apply(P1 p1, P2 p2) { R r = me.apply(p1, p2); for (Func2<? super P1, ? super P2, ? extends R> f : fs) { r = f.apply(p1, p2); } return r; } }; } /** * Returns a composed function that when applied, try to apply this function first, in case * a {@link NotAppliedException} is captured apply to the fallback function specified. This * method helps to implement partial function * * @param fallback the function to applied if this function doesn't apply to the parameter(s) * @return the composed function */ public F2<P1, P2, R> orElse(final Func2<? super P1, ? super P2, ? extends R> fallback) { final F2<P1, P2, R> me = this; return new F2<P1, P2, R>() { @Override public R apply(P1 p1, P2 p2) { try { return me.apply(p1, p2); } catch (RuntimeException e) { return fallback.apply(p1, p2); } } }; } /** * Turns this partial function into a plain function returning an Option result. * * @return a function that takes an argument x to Some(this.apply(x)) if this can be applied, and to None otherwise. */ public F2<P1, P2, Option<R>> lift() { final F2<P1, P2, R> me = this; return new F2<P1, P2, Option<R>>() { @Override public Option<R> apply(P1 p1, P2 p2) { try { return Osgl.some(me.apply(p1, p2)); } catch (RuntimeException e) { return Osgl.none(); } } }; } } private static class DumbF2 extends F2<Object, Object, Object> implements Serializable { private static final long serialVersionUID = 2856835860952L; @Override public Object apply(Object o, Object o2) throws NotAppliedException, Break { return null; } } /** * A dumb {@link Osgl.Func2} implementation that does nothing and return null * * @see #f2() * @since 0.2 */ public static final F2 F2 = new DumbF2(); /** * The type-safe version of {@link #F2} * * @param <P1> the type of the first param the new function applied to * @param <P2> the type of the second param the new function applied to * @param <R> the type of new function application result * @return the dumb function {@link #F2} * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2, R> F2<P1, P2, R> f2() { return (F2<P1, P2, R>) F2; } /** * Convert a general {@link Osgl.Func2} function into a {@link F2} typed * function * * @param f2 the function that takes two arguments and return type {@code R} * @param <P1> the type of the first param the new function applied to * @param <P2> the type of the second param the new function applied to * @param <R> the type of new function application result * @return a {@code F2} instance corresponding to the specified {@code Func2} instance * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2, R> F2<P1, P2, R> f2(final Func2<? super P1, ? super P2, ? extends R> f2) { E.NPE(f2); if (f2 instanceof F2) { return (F2<P1, P2, R>) f2; } return new F2<P1, P2, R>() { @Override public R apply(P1 p1, P2 p2) { return f2.apply(p1, p2); } }; } /** * Define a function structure that accept three parameter * * @param <P1> the type of first parameter this function applied to * @param <P2> the type of second parameter this function applied to * @param <P3> the type of thrid parameter this function applied to * @param <R> the type of the return value when this function applied to the parameter(s) * @see Osgl.Func0 * @see Osgl.Function * @see Osgl.Func2 * @see Osgl.Func4 * @see Osgl.Func5 * @since 0.2 */ public interface Func3<P1, P2, P3, R> { /** * Run the function with parameters specified. * <p>In case implementing a partial function, it can throw out an * {@link NotAppliedException} if the function is not defined for * the given parameter(s)</p> * * @param p1 argument 1 * @param p2 argument 2 * @param p3 argument 3 * @return the result of function applied * @throws NotAppliedException if the function doesn't apply to the parameter(s) * @throws Break to short cut collecting operations (fold/reduce) on an {@link org.osgl.util.C.Traversable container} */ R apply(P1 p1, P2 p2, P3 p3) throws NotAppliedException, Break; } /** * Base implementation of {@link Osgl.Func3} function. User application should * (nearly) always make their implementation extend to this base class * instead of implement {@link Osgl.Func3} directly * * @since 0.2 */ public static abstract class F3<P1, P2, P3, R> extends FuncBase implements Func3<P1, P2, P3, R> { /** * Applies this partial function to the given argument when it is contained in the function domain. * Applies fallback function where this partial function is not defined. * * @param p1 the first argument * @param p2 the second argument * @param p3 the third argument * @param fallback the function to be called of application of this function failed with any runtime exception * @return the result of this function or the fallback function application */ public R applyOrElse(P1 p1, P2 p2, P3 p3, F3<? super P1, ? super P2, ? super P3, ? extends R> fallback) { try { return apply(p1, p2, p3); } catch (RuntimeException e) { return fallback.apply(p1, p2, p3); } } public final F0<R> curry(final P1 p1, final P2 p2, final P3 p3) { final F3<P1, P2, P3, R> me = this; return new F0<R>() { @Override public R apply() { return me.apply(p1, p2, p3); } }; } public final F1<P1, R> curry(final P2 p2, final P3 p3) { final F3<P1, P2, P3, R> me = this; return new F1<P1, R>() { @Override public R apply(P1 p1) { return me.apply(p1, p2, p3); } }; } public final F2<P1, P2, R> curry(final P3 p3) { final F3<P1, P2, P3, R> me = this; return new F2<P1, P2, R>() { @Override public R apply(P1 p1, P2 p2) { return me.apply(p1, p2, p3); } }; } /** * Returns a composed function from this function and the specified function that takes the * result of this function. When applying the composed function, this function is applied * first to given parameter and then the specified function is applied to the result of * this function. * * @param f the function takes the <code>R</code> type parameter and return <code>T</code> * type result * @param <T> the return type of function {@code f} * @return the composed function * @throws NullPointerException if <code>f</code> is null */ public <T> Func3<P1, P2, P3, T> andThen(final Function<? super R, ? extends T> f) { E.NPE(f); final Func3<P1, P2, P3, R> me = this; return new F3<P1, P2, P3, T>() { @Override public T apply(P1 p1, P2 p2, P3 p3) { R r = me.apply(p1, p2, p3); return f.apply(r); } }; } /** * Returns a composed function that applied, in sequence, this function and * all functions specified one by one. If applying anyone of the functions * throws an exception, it is relayed to the caller of the composed function. * If an exception is thrown out, the following functions will not be applied. * <p>When apply the composed function, the result of the last function * is returned</p> * * @param fs a sequence of function to be applied after this function * @return a composed function */ public Func3<P1, P2, P3, R> andThen( final Func3<? super P1, ? super P2, ? super P3, ? extends R>... fs ) { if (0 == fs.length) { return this; } final Func3<P1, P2, P3, R> me = this; return new F3<P1, P2, P3, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3) { R r = me.apply(p1, p2, p3); for (Func3<? super P1, ? super P2, ? super P3, ? extends R> f : fs) { r = f.apply(p1, p2, p3); } return r; } }; } /** * Returns a composed function that when applied, try to apply this function first, in case * a {@link NotAppliedException} is captured apply to the fallback function specified. This * method helps to implement partial function * * @param fallback the function to applied if this function doesn't apply to the parameter(s) * @return the composed function */ public F3<P1, P2, P3, R> orElse(final Func3<? super P1, ? super P2, ? super P3, ? extends R> fallback) { final F3<P1, P2, P3, R> me = this; return new F3<P1, P2, P3, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3) { try { return me.apply(p1, p2, p3); } catch (RuntimeException e) { return fallback.apply(p1, p2, p3); } } }; } /** * Turns this partial function into a plain function returning an Option result. * * @return a function that takes an argument x to Some(this.apply(x)) if this can be applied, and to None otherwise. */ public F3<P1, P2, P3, Option<R>> lift() { final F3<P1, P2, P3, R> me = this; return new F3<P1, P2, P3, Option<R>>() { @Override public Option<R> apply(P1 p1, P2 p2, P3 p3) { try { return Osgl.some(me.apply(p1, p2, p3)); } catch (RuntimeException e) { return Osgl.none(); } } }; } } private static class DumbF3 extends F3<Object, Object, Object, Object> implements Serializable { private static final long serialVersionUID = 2856835860953L; @Override public Object apply(Object o, Object o2, Object o3) throws NotAppliedException, Break { return null; } } /** * A dumb {@link Osgl.Func3} implementation that does nothing and return null * * @see #f3() * @since 0.2 */ public static final F3 F3 = new DumbF3(); /** * The type-safe version of {@link #F3} * * @param <P1> the type of first parameter this function applied to * @param <P2> the type of second parameter this function applied to * @param <P3> the type of thrid parameter this function applied to * @param <R> the type of the return value when this function applied to the parameter(s) * @return the dumb function {@link #F3} * @since 0.2 */ @SuppressWarnings({"unchecked", "unused"}) public static <P1, P2, P3, R> F3<P1, P2, P3, R> f3() { return F3; } /** * Convert a general {@link Osgl.Func3} function into a {@link F3} typed * function * * @param f3 the general function with three params * @param <P1> type of argument 1 * @param <P2> type of argument 2 * @param <P3> type of argument 3 * @param <R> return type * @return the {@link #F3} typed instance which is equivalent to f3 * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2, P3, R> F3<P1, P2, P3, R> f3(final Func3<? super P1, ? super P2, ? super P3, ? extends R> f3 ) { E.NPE(f3); if (f3 instanceof F3) { return (F3<P1, P2, P3, R>) f3; } return new F3<P1, P2, P3, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3) { return f3.apply(p1, p2, p3); } }; } /** * Define a function structure that accept four parameter * * @param <P1> the type of first parameter this function applied to * @param <P2> the type of second parameter this function applied to * @param <P3> the type of thrid parameter this function applied to * @param <P4> the type of fourth parameter this function applied to * @param <R> the type of the return value when this function applied to the parameter(s) * @see Osgl.Func0 * @see Osgl.Function * @see Osgl.Func2 * @see Osgl.Func4 * @see Osgl.Func5 * @since 0.2 */ public interface Func4<P1, P2, P3, P4, R> { /** * Run the function with parameters specified. * <p>In case implementing a partial function, it can throw out an * {@link NotAppliedException} if the function is not defined for * the given parameter(s)</p> * * @param p1 the first argument * @param p2 the second argument * @param p3 the third argument * @param p4 the fourth argument * @return whatever value of type {@code R} * @throws NotAppliedException if the function doesn't apply to the parameter(s) * @throws Break to short cut collecting operations (fold/reduce) on an {@link org.osgl.util.C.Traversable container} */ R apply(P1 p1, P2 p2, P3 p3, P4 p4) throws NotAppliedException, Break; } /** * Base implementation of {@link Osgl.Func4} function. User application should * (nearly) always make their implementation extend to this base class * instead of implement {@link Osgl.Func4} directly * * @since 0.2 */ public static abstract class F4<P1, P2, P3, P4, R> extends FuncBase implements Func4<P1, P2, P3, P4, R> { /** * Applies this partial function to the given argument when it is contained in the function domain. * Applies fallback function where this partial function is not defined. * * @param p1 the first argument * @param p2 the second argument * @param p3 the third argument * @param p4 the fourth argument * @param fallback the failover function to be called if application of this function failed with any * runtime exception * @return a composite function that apply to this function first and if failed apply to the callback function */ public R applyOrElse(P1 p1, P2 p2, P3 p3, P4 p4, F4<? super P1, ? super P2, ? super P3, ? super P4, ? extends R> fallback ) { try { return apply(p1, p2, p3, p4); } catch (RuntimeException e) { return fallback.apply(p1, p2, p3, p4); } } public final F0<R> curry(final P1 p1, final P2 p2, final P3 p3, final P4 p4) { final F4<P1, P2, P3, P4, R> me = this; return new F0<R>() { @Override public R apply() { return me.apply(p1, p2, p3, p4); } }; } public final F1<P1, R> curry(final P2 p2, final P3 p3, final P4 p4) { final F4<P1, P2, P3, P4, R> me = this; return new F1<P1, R>() { @Override public R apply(P1 p1) { return me.apply(p1, p2, p3, p4); } }; } public final F2<P1, P2, R> curry(final P3 p3, final P4 p4) { final F4<P1, P2, P3, P4, R> me = this; return new F2<P1, P2, R>() { @Override public R apply(P1 p1, P2 p2) { return me.apply(p1, p2, p3, p4); } }; } public final F3<P1, P2, P3, R> curry(final P4 p4) { final F4<P1, P2, P3, P4, R> me = this; return new F3<P1, P2, P3, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3) { return me.apply(p1, p2, p3, p4); } }; } /** * Returns a composed function from this function and the specified function that takes the * result of this function. When applying the composed function, this function is applied * first to given parameter and then the specified function is applied to the result of * this function. * * @param f the function takes the <code>R</code> type parameter and return <code>T</code> * type result * @param <T> the return type of function {@code f} * @return the composed function * @throws NullPointerException if <code>f</code> is null */ public <T> F4<P1, P2, P3, P4, T> andThen(final Function<? super R, ? extends T> f) { E.NPE(f); final Func4<P1, P2, P3, P4, R> me = this; return new F4<P1, P2, P3, P4, T>() { @Override public T apply(P1 p1, P2 p2, P3 p3, P4 p4) { R r = me.apply(p1, p2, p3, p4); return f.apply(r); } }; } /** * Returns a composed function that applied, in sequence, this function and * all functions specified one by one. If applying anyone of the functions * throws an exception, it is relayed to the caller of the composed function. * If an exception is thrown out, the following functions will not be applied. * <p>When apply the composed function, the result of the last function * is returned</p> * * @param fs a sequence of function to be applied after this function * @return a composed function */ public F4<P1, P2, P3, P4, R> andThen( final Func4<? super P1, ? super P2, ? super P3, ? super P4, ? extends R>... fs ) { if (0 == fs.length) { return this; } final Func4<P1, P2, P3, P4, R> me = this; return new F4<P1, P2, P3, P4, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3, P4 p4) { R r = me.apply(p1, p2, p3, p4); for (Func4<? super P1, ? super P2, ? super P3, ? super P4, ? extends R> f : fs) { r = f.apply(p1, p2, p3, p4); } return r; } }; } /** * Returns a composed function that when applied, try to apply this function first, in case * a {@link NotAppliedException} is captured apply to the fallback function specified. This * method helps to implement partial function * * @param fallback the function to applied if this function doesn't apply to the parameter(s) * @return the composed function */ public F4<P1, P2, P3, P4, R> orElse( final Func4<? super P1, ? super P2, ? super P3, ? super P4, ? extends R> fallback ) { final F4<P1, P2, P3, P4, R> me = this; return new F4<P1, P2, P3, P4, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3, P4 p4) { try { return me.apply(p1, p2, p3, p4); } catch (RuntimeException e) { return fallback.apply(p1, p2, p3, p4); } } }; } /** * Turns this partial function into a plain function returning an Option result. * * @return a function that takes an argument x to Some(this.apply(x)) if this can be applied, and to None otherwise. */ public F4<P1, P2, P3, P4, Option<R>> lift() { final F4<P1, P2, P3, P4, R> me = this; return new F4<P1, P2, P3, P4, Option<R>>() { @Override public Option<R> apply(P1 p1, P2 p2, P3 p3, P4 p4) { try { return Osgl.some(me.apply(p1, p2, p3, p4)); } catch (RuntimeException e) { return Osgl.none(); } } }; } } private static class DumbF4 extends F4<Object, Object, Object, Object, Object> implements Serializable { private static final long serialVersionUID = 2856835860954L; @Override public Object apply(Object o, Object o2, Object o3, Object o4) throws NotAppliedException, Break { return null; } } /** * A dumb {@link Osgl.Func4} implementation that does nothing and return null * * @see #f4() * @since 0.2 */ public static final F4 F4 = new DumbF4(); /** * The type-safe version of {@link #F4} * * @param <P1> type of first argument * @param <P2> type of second argument * @param <P3> type of third argument * @param <P4> type of fourth argument * @param <R> type of return value * @return the dumb {@link #F4} function * @since 0.2 */ @SuppressWarnings({"unchecked", "unused"}) public static <P1, P2, P3, P4, R> F4<P1, P2, P3, P4, R> f4() { return F4; } /** * Convert a general {@link Osgl.Func4} function into a {@link F4} typed * function * * @param f4 the function to be converted * @param <P1> type of first argument * @param <P2> type of second argument * @param <P3> type of third argument * @param <P4> type of fourth argument * @param <R> type of return value * @return the function of {@link F4} type that is equivalent to function {@code f4} * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2, P3, P4, R> F4<P1, P2, P3, P4, R> f4( final Func4<? super P1, ? super P2, ? super P3, ? super P4, ? extends R> f4 ) { E.NPE(f4); if (f4 instanceof F4) { return (F4<P1, P2, P3, P4, R>) f4; } return new F4<P1, P2, P3, P4, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3, P4 p4) { return f4.apply(p1, p2, p3, p4); } }; } /** * Define a function structure that accept five parameter * * @param <P1> the type of first parameter this function applied to * @param <P2> the type of second parameter this function applied to * @param <P3> the type of thrid parameter this function applied to * @param <P4> the type of fourth parameter this function applied to * @param <P5> the type of fifth parameter this function applied to * @param <R> the type of the return value when this function applied to the parameter(s) * @see Osgl.Func0 * @see Osgl.Function * @see Osgl.Func2 * @see Osgl.Func3 * @see Osgl.Func5 * @since 0.2 */ public interface Func5<P1, P2, P3, P4, P5, R> { /** * Run the function with parameters specified. * <p>In case implementing a partial function, it can throw out an * {@link NotAppliedException} if the function is not defined for * the given parameter(s)</p> * * @param p1 first argument * @param p2 second argument * @param p3 third argument * @param p4 fourth argument * @param p5 fifth argument * @return whatever with type {@code R} * @throws NotAppliedException if the function doesn't apply to the parameter(s) * @throws Break to short cut collecting operations (fold/reduce) on an {@link org.osgl.util.C.Traversable container} */ R apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) throws NotAppliedException, Break; } /** * Base implementation of {@link Osgl.Func5} function. User application should * (nearly) always make their implementation extend to this base class * instead of implement {@link Osgl.Func5} directly * * @since 0.2 */ public static abstract class F5<P1, P2, P3, P4, P5, R> extends FuncBase implements Func5<P1, P2, P3, P4, P5, R> { /** * Applies this partial function to the given argument when it is contained in the function domain. * Applies fallback function where this partial function is not defined. * * @param p1 the first argument * @param p2 the second argument * @param p3 the third argument * @param p4 the fourth argument * @param p5 the fifth argument * @param fallback the function to be called if application of this function failed with any runtime exception * @return a composite function apply to this function and then the callback function if this function failed */ public R applyOrElse(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, F5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? extends R> fallback ) { try { return apply(p1, p2, p3, p4, p5); } catch (RuntimeException e) { return fallback.apply(p1, p2, p3, p4, p5); } } public final F0<R> curry(final P1 p1, final P2 p2, final P3 p3, final P4 p4, final P5 p5) { final F5<P1, P2, P3, P4, P5, R> f5 = this; return new F0<R>() { @Override public R apply() { return f5.apply(p1, p2, p3, p4, p5); } }; } public final F1<P1, R> curry(final P2 p2, final P3 p3, final P4 p4, final P5 p5) { final F5<P1, P2, P3, P4, P5, R> f5 = this; return new F1<P1, R>() { @Override public R apply(P1 p1) { return f5.apply(p1, p2, p3, p4, p5); } }; } public final F2<P1, P2, R> curry(final P3 p3, final P4 p4, final P5 p5) { final F5<P1, P2, P3, P4, P5, R> f5 = this; return new F2<P1, P2, R>() { @Override public R apply(P1 p1, P2 p2) { return f5.apply(p1, p2, p3, p4, p5); } }; } public final F3<P1, P2, P3, R> curry(final P4 p4, final P5 p5) { final F5<P1, P2, P3, P4, P5, R> f5 = this; return new F3<P1, P2, P3, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3) { return f5.apply(p1, p2, p3, p4, p5); } }; } public final F4<P1, P2, P3, P4, R> curry(final P5 p5) { final F5<P1, P2, P3, P4, P5, R> f5 = this; return new F4<P1, P2, P3, P4, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3, P4 p4) { return f5.apply(p1, p2, p3, p4, p5); } }; } /** * Returns a composed function from this function and the specified function that takes the * result of this function. When applying the composed function, this function is applied * first to given parameter and then the specified function is applied to the result of * this function. * * @param f the function takes the <code>R</code> type parameter and return <code>T</code> * type result * @param <T> the return type of function {@code f} * @return the composed function * @throws NullPointerException if <code>f</code> is null */ public <T> F5<P1, P2, P3, P4, P5, T> andThen(final Function<? super R, ? extends T> f) { E.NPE(f); final F5<P1, P2, P3, P4, P5, R> me = this; return new F5<P1, P2, P3, P4, P5, T>() { @Override public T apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { R r = me.apply(p1, p2, p3, p4, p5); return f.apply(r); } }; } /** * Returns a composed function that applied, in sequence, this function and * all functions specified one by one. If applying anyone of the functions * throws an exception, it is relayed to the caller of the composed function. * If an exception is thrown out, the following functions will not be applied. * <p>When apply the composed function, the result of the last function * is returned</p> * * @param fs a sequence of function to be applied after this function * @return a composed function */ public F5<P1, P2, P3, P4, P5, R> andThen( final Func5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? extends R>... fs ) { if (0 == fs.length) { return this; } final F5<P1, P2, P3, P4, P5, R> me = this; return new F5<P1, P2, P3, P4, P5, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { R r = me.apply(p1, p2, p3, p4, p5); for (Func5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? extends R> f : fs) { r = f.apply(p1, p2, p3, p4, p5); } return r; } }; } /** * Returns a composed function that when applied, try to apply this function first, in case * a {@link NotAppliedException} is captured apply to the fallback function specified. This * method helps to implement partial function * * @param fallback the function to applied if this function doesn't apply to the parameter(s) * @return the composed function */ public F5<P1, P2, P3, P4, P5, R> orElse( final Func5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? extends R> fallback ) { final F5<P1, P2, P3, P4, P5, R> me = this; return new F5<P1, P2, P3, P4, P5, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { try { return me.apply(p1, p2, p3, p4, p5); } catch (RuntimeException e) { return fallback.apply(p1, p2, p3, p4, p5); } } }; } /** * Turns this partial function into a plain function returning an Option result. * * @return a function that takes an argument x to Some(this.apply(x)) if this can be applied, and to None otherwise. */ public F5<P1, P2, P3, P4, P5, Option<R>> lift() { final F5<P1, P2, P3, P4, P5, R> me = this; return new F5<P1, P2, P3, P4, P5, Option<R>>() { @Override public Option<R> apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { try { return Osgl.some(me.apply(p1, p2, p3, p4, p5)); } catch (RuntimeException e) { return Osgl.none(); } } }; } } private static class DumbF5 extends F5<Object, Object, Object, Object, Object, Object> implements Serializable { private static final long serialVersionUID = 2856835860955L; @Override public Object apply(Object o, Object o2, Object o3, Object o4, Object o5) throws NotAppliedException, Break { return null; } } /** * A dumb {@link Osgl.Func5} implementation that does nothing and return null * * @see #f5() * @since 0.2 */ public static final F5 F5 = new DumbF5(); /** * The type-safe version of {@link #F5} * * @param <P1> type of first argument * @param <P2> type of second argument * @param <P3> type of third argument * @param <P4> type of fourth argument * @param <P5> type of fifth argument * @param <R> type of return value * @return a dumb {@link #F5} function * @since 0.2 */ @SuppressWarnings({"unchecked", "unused"}) public static <P1, P2, P3, P4, P5, R> F5<P1, P2, P3, P4, P5, R> f5() { return F5; } /** * Convert a general {@link Osgl.Func5} function into a {@link F5} typed * function * * @param f5 the function to be converted * @param <P1> type of first argument * @param <P2> type of second argument * @param <P3> type of third argument * @param <P4> type of fourth argument * @param <P5> type of fifth argument * @param <R> type of return value * @return the function of {@link F5} type that is equivalent to function {@code f5} * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2, P3, P4, P5, R> F5<P1, P2, P3, P4, P5, R> f5( final Func5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? extends R> f5 ) { E.NPE(f5); if (f5 instanceof F5) { return (F5<P1, P2, P3, P4, P5, R>) f5; } return new F5<P1, P2, P3, P4, P5, R>() { @Override public R apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { return f5.apply(p1, p2, p3, p4, p5); } }; } // Define common used Function classes including Predicate and Visitor /** * Adapt JDK Comparator (since 1.2) to Functional programming. The class provides several java8 Comparator methods * * @param <T> the type of the element to be compared * @since 0.2 */ public static abstract class Comparator<T> extends F2<T, T, Integer> implements java.util.Comparator<T>, Serializable { @Override public Integer apply(T p1, T p2) throws NotAppliedException, Break { return compare(p1, p2); } /** * See <a href="http://download.java.net/jdk8/docs/api/java/util/Comparator.html#reversed()">Java 8 doc</a> * * @since 0.2 */ public Comparator<T> reversed() { if (this instanceof Reversed) { return ((Reversed<T>) this).cmp; } return new Reversed<T>(this); } /** * See <a href="http://download.java.net/jdk8/docs/api/java/util/Comparator.html#thenComparing(java.util.Comparator)">Java 8 doc</a> * * @since 0.2 */ public Comparator<T> thenComparing(final java.util.Comparator<? super T> other) { final Comparator<T> me = this; return new Comparator<T>() { @Override public int compare(T o1, T o2) { int ret = (me.compare(o1, o2)); return (0 == ret) ? other.compare(o1, o2) : ret; } }; } /** * See <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#thenComparing-java.util.function.Function-java.util.Comparator-">Java 8 doc</a> * * @param keyExtractor The function to extract the key for comparison * @param keyComparator The function to compare the extracted key * @param <U> the generic type of the key * @return a function that extract key of type {@code U} from element of type {@code T} * and run {@code keyComparator} to compare the two keys * @since 0.2 */ public <U extends Comparable<? super U>> Comparator<T> thenComparing( Function<? super T, ? extends U> keyExtractor, java.util.Comparator<? super U> keyComparator ) { return thenComparing(Osgl.F.comparing(keyExtractor, keyComparator)); } /** * See <a href="http://download.java.net/jdk8/docs/api/java/util/Comparator.html#thenComparing(java.util.function.Function)">Java 8 doc</a> * * @param keyExtractor the function that extract key of type U from instance of type T * @param <U> the key type * @return a comparator that applied if the result of this comparator is even */ public <U extends Comparable<? super U>> Comparator<T> thenComparing( Function<? super T, ? extends U> keyExtractor ) { return thenComparing(Osgl.F.comparing(keyExtractor)); } private static class NaturalOrder extends Comparator<Comparable<Object>> implements Serializable { private static final long serialVersionUID = -2658673713566062292L; static final NaturalOrder INSTANCE = new NaturalOrder(); @Override public int compare(Comparable<Object> c1, Comparable<Object> c2) { if (null == c1) return -1; if (null == c2) return 1; return c1.compareTo(c2); } private Object readResolve() { return INSTANCE; } @Override public Comparator<Comparable<Object>> reversed() { return ReverseOrder.INSTANCE; } } private static class ReverseOrder extends Comparator<Comparable<Object>> implements Serializable { private static final long serialVersionUID = -8026361379173504545L; static final ReverseOrder INSTANCE = new ReverseOrder(); @Override public int compare(Comparable<Object> c1, Comparable<Object> c2) { return c2.compareTo(c1); } private Object readResolve() { return INSTANCE; } @Override public Comparator<Comparable<Object>> reversed() { return NaturalOrder.INSTANCE; } } private static class Reversed<T> extends Comparator<T> { private static final long serialVersionUID = -8555952576466749416L; final Comparator<T> cmp; Reversed(Comparator<T> cmp) { E.NPE(cmp); this.cmp = cmp; } @Override public int compare(T t1, T t2) { return cmp.compare(t2, t1); } public boolean equals(Object o) { return (o == this) || (o instanceof Reversed && cmp.equals(((Reversed) o).cmp)); } public int hashCode() { return cmp.hashCode() ^ Integer.MIN_VALUE; } } } /** * Adapt a general {@link Func2} function with (T, T, Integer) type into {@link Comparator} * * @param f The function takes two params (the same type) and returns integer * @param <T> the type of the parameter * @return a {@link Comparator} instance backed by function {@code f} */ @SuppressWarnings("unchecked") public static <T> Comparator<T> comparator(final Func2<? super T, ? super T, Integer> f) { E.NPE(f); if (f instanceof Comparator) { return (Comparator<T>) f; } return new Comparator<T>() { @Override public int compare(T o1, T o2) { return f.apply(o1, o2); } }; } /** * Adapt a jdk {@link java.util.Comparator} into {@link Comparator osgl Comparator} * * @param <T> the element type the comparator compares * @param c the jdk compator * @return a {@link Comparator} instance backed by comparator {@code c} */ @SuppressWarnings("unchecked") public static <T> Comparator<T> comparator(final java.util.Comparator<? super T> c) { E.NPE(c); if (c instanceof Comparator) { return (Comparator<T>) c; } return new Comparator<T>() { @Override public int compare(T o1, T o2) { return c.compare(o1, o2); } }; } /** * <code>Predicate</code> is a predefined <code>Function<Boolean, T></code> typed * function with a set of utilities dealing with boolean operations. This is often known * as <a href="http://en.wikipedia.org/wiki/Predicate_(mathematical_logic)">Predicate</a> * <p>Note in user application, it should NOT assume an argument is of <code>Predicate</code> * typed function, instead the argument should always be declared as <code>Function<Boolean T></code>:</p> * <pre> * // bad way * void foo(Predicate<MyData> predicate) { * ... * } * // good way * void foo(Function<Boolean, MyData> predicate) { * Predicate<MyData> p = Osgl.predicate(predicate); * ... * } * </pre> * * @since 0.2 */ public static abstract class Predicate<T> extends Osgl.F1<T, Boolean> { @Override public final Boolean apply(T t) { return test(t); } /** * Sub class to implement this method to test on the supplied elements * * @param t the element to be test * @return {@code true} or {@code false} depends on the implementation */ public abstract boolean test(T t); /** * Returns a negate function of this * * @return the negate function */ public Predicate<T> negate() { return Osgl.F.negate(this); } /** * Return an <code>Predicate</code> predicate from a list of <code>Function<Boolean, T></code> * with AND operation. For any <code>T t</code> to be tested, if any specified predicates * must returns <code>false</code> on it, the resulting predicate will return <code>false</code>. * * @param predicates the predicate function array * @return a function that returns {@code true} only when all functions in {@code predicates} returns * {@code true} on a given argument * @since 0.2 */ public Predicate<T> and(final Function<? super T, Boolean>... predicates) { final Predicate<T> me = this; return new Predicate<T>() { @Override public boolean test(T t) { if (!me.test(t)) { return false; } for (Function<? super T, Boolean> f : predicates) { if (!f.apply(t)) { return false; } } return true; } }; } /** * Return an <code>Predicate</code> predicate from a list of <code>Function<Boolean, T></code> * with OR operation. For any <code>T t</code> to be tested, if any specified predicates * must returns <code>true</code> on it, the resulting predicate will return <code>true</code>. * * @param predicates the predicate functions * @return a function returns {@code true} if any one of the predicate functions returns * {@code true} on a given argument * @since 0.2 */ public Predicate<T> or(final Function<? super T, Boolean>... predicates) { final Predicate<T> me = this; return new Predicate<T>() { @Override public boolean test(T t) { if (me.test(t)) { return true; } for (Function<? super T, Boolean> f : predicates) { if (f.apply(t)) { return true; } } return false; } }; } public <R> F1<T, Option<R>> ifThen(final Function<? super T, R> func) { return new F1<T, Option<R>>() { @Override public Option<R> apply(T t) throws NotAppliedException, Break { if (test(t)) { return some(func.apply(t)); } return none(); } }; } public <R> F1<T, Option<R>> elseThen(final Function<? super T, R> func) { return negate().ifThen(func); } public static <T> Predicate<T> negate(final Osgl.Function<T, Boolean> predicate) { return new Osgl.Predicate<T>() { @Override public boolean test(T t) { return !predicate.apply(t); } }; } } /** * Convert a <code>Function<T, Boolean></code> typed function to * {@link Osgl.Predicate Predicate<T>} function. * <p>If the function specified is already a {@link Predicate}, then * the function itself is returned</p> * * @param f the function to be converted * @param <T> the argument type * @return a function of {@link Predicate} type that is equivalent to function {@code f} * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> Predicate<T> predicate(final Function<? super T, Boolean> f) { if (f instanceof Predicate) { return (Predicate<T>) f; } return new Predicate<T>() { @Override public boolean test(T t) { return f.apply(t); } }; } /** * Convert a general <code>Function<T, ?></code> typed function to * {@link Osgl.Predicate Predicate<T>} function. When the predicate function * returned apply to a param, it will first apply the specified {@code f1} to the * param, and they call {@link #bool(java.lang.Object)} to evaluate the boolean * value of the return object of the application. * <p>If the function specified is already a {@link Predicate}, then * the function itself is returned</p> * * @param f the function * @param <T> the argument type * @return the function of {@link Predicate} type that is equivalent to the function {@code f} * @since 0.2 */ @SuppressWarnings({"unused", "unchecked"}) public static <T> Predicate<T> generalPredicate(final Function<? super T, ?> f) { if (f instanceof Predicate) { return (Predicate<T>) f; } return new Predicate<T>() { @Override public boolean test(T t) { return bool(f.apply(t)); } }; } /** * Define a processor function which applied to one parameter and return the parameter instance after * processing on the parameter * * @param <T> the paramete type */ public abstract static class Processor<T> extends Osgl.F1<T, T> { @Override public T apply(T t) throws NotAppliedException, Break { process(t); return t; } /** * Subclass must override thie method to process the parameter * * @param t the object to be processed * @throws Break if logic decide it shall break external loop * @throws NotAppliedException if logic decide to skip further processing * on the object passed in */ public abstract void process(T t) throws Break, NotAppliedException; } /** * Define a visitor (known as Consumer in java 8) function which applied to one parameter and without return type * * @param <T> the type of the parameter the visitor function applied to */ public abstract static class Visitor<T> extends Osgl.F1<T, Void> { /** * Construct a visitor without payload */ public Visitor() { } @Override public final Void apply(T t) { visit(t); return null; } /** * User application to implement visit logic in this method * * @param t the element been visited * @throws Break if the logic decide to break visit progress (usually when visiting a sequence of elements) */ public abstract void visit(T t) throws Break; } public abstract static class V1<P1> extends Visitor<P1> { } @SuppressWarnings("unused") public abstract static class V2<P1, P2> extends Osgl.F2<P1, P2, Void> { @Override public final Void apply(P1 p1, P2 p2) throws NotAppliedException, Break { visit(p1, p2); return null; } public abstract void visit(P1 p1, P2 p2); } @SuppressWarnings("unused") public abstract static class V3<P1, P2, P3> extends Osgl.F3<P1, P2, P3, Void> { @Override public final Void apply(P1 p1, P2 p2, P3 p3) throws NotAppliedException, Break { visit(p1, p2, p3); return null; } public abstract void visit(P1 p1, P2 p2, P3 p3); } @SuppressWarnings("unused") public abstract static class V4<P1, P2, P3, P4> extends Osgl.F4<P1, P2, P3, P4, Void> { @Override public final Void apply(P1 p1, P2 p2, P3 p3, P4 p4) throws NotAppliedException, Break { visit(p1, p2, p3, p4); return null; } public abstract void visit(P1 p1, P2 p2, P3 p3, P4 p4); } @SuppressWarnings("unused") public abstract static class V5<P1, P2, P3, P4, P5> extends Osgl.F5<P1, P2, P3, P4, P5, Void> { @Override public final Void apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) throws NotAppliedException, Break { visit(p1, p2, p3, p4, p5); return null; } public abstract void visit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); } /** * */ /** * Convert a {@code Function<? super T, Void>} function into a {@link Visitor} * * @param f the function to be cast * @param <T> the argument type * @return a {@link Visitor} type function that is equal with the function {@code f} * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> Visitor<T> visitor(final Function<? super T, ?> f) { if (f instanceof Visitor) { return (Visitor<T>) f; } return new Visitor<T>() { @Override public void visit(T t) throws Break { f.apply(t); } }; } /** * Return a composed visitor function that only applies when the guard predicate test returns <code>true</code> * * @param predicate the predicate to test the element been visited * @param visitor the function that visit(accept) the element if the guard tested the element successfully * @param <T> the type of the element be tested and visited * @return the composed function */ public static <T> Visitor<T> guardedVisitor(final Function<? super T, Boolean> predicate, final Function<? super T, ?> visitor) { return new Visitor<T>() { @Override public void visit(T t) throws Break { if (predicate.apply(t)) { visitor.apply(t); } } }; } /** * A Break is used to shortcut a sequence of function executions */ public static class Break extends FastRuntimeException { private Object payload; /** * construct a Break without payload */ public Break() { } /** * Construct a Break with payload specified. Note here we can't use generic type for * the payload as java does not support generic typed throwable * * @param payload the payload object */ public Break(Object payload) { super("break out"); this.payload = payload; } /** * Return the payload * * @param <T> the type of the return value * @return the payload */ public <T> T get() { return Osgl.cast(payload); } } /** * A utility method to throw out a Break with payload * * @param e the payload object * @param <T> the type of the payload * @return a Break instance with the payload specified */ @SuppressWarnings("unused") public static <T> Break breakOut(T e) { throw new Break(e); } /** * A predefined Break instance without payload */ @SuppressWarnings("unused") public static final Break BREAK = new Break(); /** * <p>An {@code IndexedVisitor} provide a tool to iterate through a Map or indexed list * by passing the key/index and the value to the function.</p> * <p>Use {@code IndexedVisitor} to iterate through a {@code List}</p> * <pre> * C.List<Student> students = ... * students.each(new IndexedVisitor() { * {@literal @}Override * public void visit(int id, Student student) { * System.out.printf("ID: %s, Name: %s", id, student.getName()); * } * }) * </pre> * <p>Use {@code IndexedVisitor} to iterate through a {@code Map}</p> * * @param <K> the generic type of the key * @param <T> the generic type of the value */ public static abstract class IndexedVisitor<K, T> extends Osgl.F2<K, T, Void> { protected Map<String, ?> attr = new HashMap<String, Object>(); protected T any; protected String aStr; protected boolean aBool; protected int anInt; protected float aFloat; protected double aDouble; protected byte aByte; protected char aChar; protected long aLong; public IndexedVisitor() { } @SuppressWarnings("unused") public IndexedVisitor(Map<String, ?> map) { attr = new HashMap<String, Object>(map); } @SuppressWarnings("unused") public IndexedVisitor(T t) { any = t; } @SuppressWarnings("unused") public IndexedVisitor(String s) { aStr = s; } @SuppressWarnings("unused") public IndexedVisitor(boolean b) { aBool = b; } @SuppressWarnings("unused") public IndexedVisitor(int i) { anInt = i; } @SuppressWarnings("unused") public IndexedVisitor(long l) { aLong = l; } @SuppressWarnings("unused") public IndexedVisitor(double d) { aDouble = d; } @SuppressWarnings("unused") public IndexedVisitor(float f) { aFloat = f; } @SuppressWarnings("unused") public IndexedVisitor(byte b) { aByte = b; } @SuppressWarnings("unused") public IndexedVisitor(char c) { aChar = c; } public T get() { return any; } public String getStr() { return aStr; } public boolean getBoolean() { return aBool; } public int getInt() { return anInt; } public long getLong() { return aLong; } public float getFloat() { return aFloat; } public double getDouble() { return aDouble; } public char getChar() { return aChar; } public byte getByte() { return aByte; } @SuppressWarnings("unchecked") public <T> T get(String key) { return (T) attr.get(key); } @Override public final Void apply(K id, T t) { visit(id, t); return null; } public abstract void visit(K id, T t); } @SuppressWarnings("unused") public static <K, T> IndexedVisitor<K, T> indexGuardedVisitor(final Function<? super K, Boolean> guard, final Visitor<? super T> visitor ) { return new IndexedVisitor<K, T>() { @Override public void visit(K id, T t) throws Break { if (guard.apply(id)) { visitor.apply(t); } } }; } /** * A Transformer is literally a kind of {@link F1} function * * @param <FROM> The type of the element the transformer function applied to * @param <TO> The type of the result of transform of <code><FROM></code> */ public static abstract class Transformer<FROM, TO> extends Osgl.F1<FROM, TO> { @Override public final TO apply(FROM from) { return transform(from); } /** * The place sub class to implement the transform logic * * @param from the element to be transformed * @return the transformed object */ public abstract TO transform(FROM from); } @SuppressWarnings("unused") public static abstract class Operator<T> extends Osgl.F1<T, T> { @Override public abstract Operator<T> invert(); @Override public abstract Operator<T> times(int n); } // --- Tuple public static class Tuple<A, B> { final public A _1; final public B _2; public Tuple(A _1, B _2) { this._1 = _1; this._2 = _2; } @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof Tuple) { Tuple that = (Tuple) o; return eq(that._1, _1) && eq(that._2, _2); } return false; } @Override public int hashCode() { return hc(_1, _2); } @Override public String toString() { return "T2(_1: " + _1 + ", _2: " + _2 + ")"; } /** * Convert this {@code Tuple} instance into a Map with one key,value pair. Where * {@code key} is {@code _1} and {@code value} is {@code _2}; * @return the map as described */ @SuppressWarnings("unused") public Map<A, B> asMap() { Map<A, B> m = new HashMap<A, B>(); m.put(_1, _2); return m; } /** * Convert a list of {@code Tuple} instances into a Map. Where * {@code key} is {@code _1} and {@code value} is {@code _2}; * <p> * <b>Note</b> that the size of the returned map might be lesser than * the size of the tuple list if there are multiple {@code _1} has * the same value, and the last one is the winner and it's {@code _2} * will be put into the map * </p> * @param <K> the key type * @param <V> the value type * @param list the list of tuples to be transformed into map * @return the map as described */ @SuppressWarnings("unused") public static <K, V> Map<K, V> asMap(Collection<Tuple<K, V>> list) { Map<K, V> m = C.newMap(); for (Tuple<K, V> t: list) { m.put(t._1, t._2); } return m; } } @SuppressWarnings("unused") public static <P1, P2> Tuple<P1, P2> Tuple(P1 a, P2 b) { return new Tuple<P1, P2>(a, b); } public static class T2<A, B> extends Tuple<A, B> { public T2(A _1, B _2) { super(_1, _2); } } public static <A, B> T2<A, B> T2(A a, B b) { return new T2<A, B>(a, b); } public static class T3<A, B, C> { final public A _1; final public B _2; final public C _3; public T3(A _1, B _2, C _3) { this._1 = _1; this._2 = _2; this._3 = _3; } public T3<A, B, C> set1(A a) { return T3(a, _2, _3); } public T3<A, B, C> set2(B b) { return T3(_1, b, _3); } public T3<A, B, C> set3(C c) { return T3(_1, _2, c); } @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof T3) { T3 that = (T3) o; return Osgl.eq(that._1, _1) && Osgl.eq(that._2, _2) && Osgl.eq(that._3, _3); } return false; } @Override public int hashCode() { return Osgl.hc(_1, _2, _3); } @Override public String toString() { return "T3(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ")"; } } public static <A, B, C> T3<A, B, C> T3(A a, B b, C c) { return new T3<A, B, C>(a, b, c); } public static class T4<A, B, C, D> { final public A _1; final public B _2; final public C _3; final public D _4; public T4(A _1, B _2, C _3, D _4) { this._1 = _1; this._2 = _2; this._3 = _3; this._4 = _4; } @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof T4) { T4 that = (T4) o; return Osgl.eq(that._1, _1) && Osgl.eq(that._2, _2) && Osgl.eq(that._3, _3) && Osgl.eq(that._4, _4); } return false; } @Override public int hashCode() { return Osgl.hc(_1, _2, _3, _4); } @Override public String toString() { return "T4(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ")"; } } @SuppressWarnings("unchecked") public static <A, B, C, D> T4<A, B, C, D> T4(A a, B b, C c, D d) { return new T4<A, B, C, D>(a, b, c, d); } public static class T5<A, B, C, D, E> { final public A _1; final public B _2; final public C _3; final public D _4; final public E _5; public T5(A _1, B _2, C _3, D _4, E _5) { this._1 = _1; this._2 = _2; this._3 = _3; this._4 = _4; this._5 = _5; } @Override public boolean equals(Object o) { if (this == o) return true; if (o instanceof T5) { T5 that = (T5) o; return Osgl.eq(that._1, _1) && Osgl.eq(that._2, _2) && Osgl.eq(that._3, _3) && Osgl.eq(that._4, _4) && Osgl.eq(that._5, _5); } return false; } @Override public int hashCode() { return Osgl.hc(_1, _2, _3, _4, _5); } @Override public String toString() { return "T5(_1: " + _1 + ", _2: " + _2 + ", _3:" + _3 + ", _4:" + _4 + ", _5:" + _5 + ")"; } } @SuppressWarnings("unused") public static <A, B, C, D, E> T5<A, B, C, D, E> T5(A a, B b, C c, D d, E e) { return new T5<A, B, C, D, E>(a, b, c, d, e); } /** * Defines an option of element {@code T}. This class can be used to implement * the {@code else-if} semantic in functional programming and eliminate the * {@code null} value * * @param <T> the element type */ public static abstract class Option<T> implements Iterable<T>, Serializable { private Option() { } /** * Returns {@code true} if this {@code Option} is not {@link #NONE} * * @return {@code true} if there is a value present, otherwise {@code false} * @since 0.2 */ public final boolean isDefined() { return this != NONE; } /** * Negate of {@link #isDefined()} * * @return {@code true} if this option is not defined * @since 0.2 */ public boolean notDefined() { return !isDefined(); } /** * If a value is present in this {@code Option}, returns the value, * otherwise throws NoSuchElementException. * * @return the non-null value held by this {@code Option} * @throws NoSuchElementException if this {@code Option} is {@link #NONE} */ public abstract T get() throws NoSuchElementException; /** * If a value is present, and the value matches the given predicate, * return an {@code Option} describing the value, otherwise return * {@link #NONE}. * * @param predicate the function to test the value held by this {@code Option} * @return an {@code Option} describing the value of this {@code Option} if * a value is present and the value matches the given predicate, * otherwise {@link #NONE} */ public final Option<T> filter(Function<? super T, Boolean> predicate) { E.NPE(predicate); if (notDefined()) { return none(); } T v = get(); if (predicate.apply(v)) { return this; } else { return none(); } } /** * If a value is present, apply the provided mapping function to it, * and if the result is non-null, return an {@code Option} describing * the result. Otherwise return {@link #NONE}. * * @param mapper a mapping function to apply to the value, if present * @param <B> The type of the result of the mapping function * @return an Optional describing the result of applying a mapping * function to the value of this {@code Option}, if a value is * present, otherwise {@link #NONE} * @throws NullPointerException if the mapper function is {@code null} * @since 0.2 */ @SuppressWarnings("unchecked") public final <B> Option<B> map(final Function<? super T, ? extends B> mapper) { return isDefined() ? of(mapper.apply(get())) : NONE; } /** * If a value is present, apply the provided {@code Option}-bearing * mapping function to it, return that result, otherwise return * {@link #NONE}. This method is similar to {@link #map(Osgl.Function)}, * but the provided mapper is one whose result is already an * {@code Option}, and if invoked, {@code flatMap} does not wrap it * with an additional {@code Option}. * * @param <B> The type parameter to the {@code Option} returned by * @param mapper a mapping function to apply to the value, * @return the result of applying an {@code Option}-bearing mapping * function to the value of this {@code Option}, if a value * is present, otherwise {@link #NONE} * @throws NullPointerException if the mapping function is {@code null} * or returns a {@code null} result * @since 0.2 */ @SuppressWarnings("unchecked") public final <B> Option<B> flatMap(final Function<? super T, Option<B>> mapper) { E.NPE(mapper); Option<B> result = isDefined() ? mapper.apply(get()) : NONE; E.NPE(null == result); return result; } /** * Return the value if present, otherwise return {@code other}. * * @param other the value to be returned if there is no value present, * may be {@code null} * @return the value, if present, otherwise {@code other} */ public final T orElse(T other) { return isDefined() ? get() : other; } /** * Return the value if present, otherwise invoke {@code other} and return * the result of that invocation. * * @param other the function that is applied when no value is presented * @return the value if present otherwise the result of {@code other.apply()} * @throws NullPointerException if value is not present and other is null * @since 0.2 */ public final T orElse(Func0<? extends T> other) { return isDefined() ? get() : other.apply(); } public final void runWith(Function<? super T, ?> consumer) { if (isDefined()) { consumer.apply(get()); } } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj instanceof Option) { Option that = (Option) obj; return eq(get(), that.get()); } return false; } @Override public int hashCode() { return isDefined() ? get().hashCode() : 0; } @Override public abstract String toString(); @SuppressWarnings("unchecked") public static <T> None<T> none() { return (None<T>) NONE; } /** * Returns an {@code Option} with the specified present non-null value. * * @param value the value that cannot be {@code null} * @param <T> the type of the value * @return an Option instance describing the value * @throws NullPointerException if the value specified is {@code null} * @since 0.2 */ public static <T> Some<T> some(T value) { E.NPE(value); return new Some<T>(value); } /** * Returns an {@code Option} with the specified present value if it is not * {@code null} or {@link #NONE} otherwise. * * @param value the value * @param <T> the type of the value * @return an {@code Option} describing the value if it is not {@code null} * or {@link #NONE} if the value is {@code null} * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> Option<T> of(T value) { return null == value ? NONE : some(value); } /** * The runtime/instance function namespace */ public final class f { private f() { } /** * A function that when applied, returns if the {@code Option} is defined */ public final F0<Boolean> IS_DEFINED = new F0<Boolean>() { @Override public Boolean apply() { return Option.this != NONE; } }; /** * Negate of {@link #IS_DEFINED} */ @SuppressWarnings("unused") public final F0<Boolean> NOT_DEFINED = Osgl.F.negate(IS_DEFINED); /** * A function that when applied, returns the value described by this {@code Option} */ public final F0<T> GET = new F0<T>() { @Override public T apply() throws NotAppliedException, Break { return Option.this.get(); } }; /** * Returns a function that when applied, run {@link Osgl.Option#filter(Osgl.Function)} on this * {@code Option} * * @param predicate the predicate function * @return the function that returns either this option or {@link #NONE} if predicate failed * to test on the element in this option */ public final F0<Option<T>> filter(final Function<? super T, Boolean> predicate) { return new F0<Option<T>>() { @Override public Option<T> apply() throws NotAppliedException, Break { return Option.this.filter(predicate); } }; } /** * Returns a function that when applied, run {@link Osgl.Option#map(Osgl.Function)} on this * {@code Option} * * @param mapper the function that map {@code T} element to {@code B} object * @param <B> the type of returning option element type * @return the function returns either a {@code B} type option if this option * is defined or {@link #NONE} if this option is not defined */ public final <B> F0<Option<B>> map(final Function<? super T, ? extends B> mapper) { return new F0<Option<B>>() { @Override public Option<B> apply() throws NotAppliedException, Break { return Option.this.map(mapper); } }; } /** * Returns a function that when applied, run {@link Osgl.Option#flatMap(Osgl.Function)} on this * {@code Option} * * @param mapper the function that map an elemnet of type T to a {@code Option} of type B * @param <B> the element type of the {@code Option} * @return the function that flat map all {@code T} element to {@code B} Options */ public final <B> F0<Option<B>> flatMap(final Function<? super T, Option<B>> mapper) { return new F0<Option<B>>() { @Override public Option<B> apply() throws NotAppliedException, Break { return Option.this.flatMap(mapper); } }; } /** * Returns a function that when applied, run {@link Osgl.Option#orElse(Object)} on this * {@code Option} * * @param other the other value to be returned if this option is empty * @return the function implement {@code else if} semantic */ @SuppressWarnings("unused") public final F0<T> orElse(final T other) { return new F0<T>() { @Override public T apply() throws NotAppliedException, Break { return Option.this.orElse(other); } }; } /** * Returns a function that when applied, run {@link Osgl.Option#orElse(Osgl.Func0)} * on this {@code Option} * * @param other the function that generates another {@code T} element when this * option is empty * @return the function that implement the {@code else if} semantic on this Option */ @SuppressWarnings("unused") public final F0<T> orElse(final Func0<? extends T> other) { return new F0<T>() { @Override public T apply() throws NotAppliedException, Break { return Option.this.orElse(other); } }; } /** * Returns a function that when applied, run {@link Osgl.Option#runWith(Osgl.Function)} * on this {@code Option} * * @param consumer the function that consumes the element in this Option * @return a function that apply to {@code consumer} function if this Option is defined */ @SuppressWarnings("unused") public final F0<Void> runWith(final Function<? super T, ?> consumer) { return new F0<Void>() { @Override public Void apply() throws NotAppliedException, Break { Option.this.runWith(consumer); return null; } }; } } /** * A reference to this runtime function namesapce */ public final f f = new f(); } public static class None<T> extends Option<T> { private static final long serialVersionUID = 962498820763181262L; private None() { } @Override protected Object clone() throws CloneNotSupportedException { super.clone(); throw new CloneNotSupportedException(); } public static final None INSTANCE = new None(); @Override public T get() { throw new NoSuchElementException(); } public Iterator<T> iterator() { return Collections.<T>emptyList().iterator(); } @Override public String toString() { return "NONE"; } private Object readResolve() throws ObjectStreamException { return NONE; } } public static class Some<T> extends Option<T> { private static final long serialVersionUID = 962498820763181265L; final T value; public Some(T value) { this.value = value; } @Override public T get() { return value; } @Override public Iterator<T> iterator() { return Collections.singletonList(value).iterator(); } @Override public String toString() { return "Some(" + value + ")"; } } public static final None NONE = None.INSTANCE; @SuppressWarnings("unchecked") public static <T> Option<T> some(T a) { return null == a ? NONE : new Some(a); } @SuppressWarnings("unchecked") public static <T> None<T> none() { return (None<T>) NONE; } private static class VarListIterator<T> implements ListIterator<T> { private Var<T> var; private volatile boolean consumed; VarListIterator(Var<T> var, boolean consumed) { this(var); this.consumed = consumed; } VarListIterator(Var<T> var) { this.var = var; } @Override public boolean hasNext() { return !consumed; } @Override public boolean hasPrevious() { return consumed; } @Override public T next() { if (consumed) { throw new NoSuchElementException(); } consumed = true; return var.get(); } @Override public T previous() { if (!consumed) { throw new NoSuchElementException(); } consumed = false; return var.get(); } @Override public int nextIndex() { return consumed ? 1 : 0; } @Override public int previousIndex() { return consumed ? 0 : -1; } @Override public void set(T t) { var.set(t); } @Override public void add(T t) { throw new UnsupportedOperationException(); } @Override public void remove() { throw new UnsupportedOperationException(); } } public static class Var<T> extends ListBase<T> implements C.ListOrSet<T>, Func0<T> { private T v; public Var(T value) { v = value; } public final boolean isDefined() { return null != v; } public final boolean isNull() { return !isDefined(); } @Override public T apply() throws NotAppliedException, Break { return v; } @Override protected EnumSet<C.Feature> initFeatures() { return EnumSet.allOf(C.Feature.class); } @Override public Var<T> accept(Function<? super T, ?> visitor) { visitor.apply(v); return this; } @Override public Var<T> each(Function<? super T, ?> visitor) { return accept(visitor); } @Override public Var<T> forEach(Function<? super T, ?> visitor) { return accept(visitor); } @Override public T head() throws NoSuchElementException { return v; } @Override public Var<T> acceptLeft(Function<? super T, ?> visitor) { visitor.apply(v); return this; } @Override public <R> R reduceLeft(R identity, Func2<R, T, R> accumulator) { return accumulator.apply(identity, v); } @Override public Option<T> reduceLeft(Func2<T, T, T> accumulator) { return Osgl.some(v); } @Override public Option<T> findFirst(Function<? super T, Boolean> predicate) { if (predicate.apply(v)) { return Osgl.some(v); } else { return Osgl.none(); } } @Override public C.List<T> take(int n) { if (n == 0) { return C.list(); } else if (n < 0) { return drop(size() + n); } else { return this; } } @Override public C.List<T> tail() throws UnsupportedOperationException { return C.list(); } @Override public C.List<T> takeWhile(Function<? super T, Boolean> predicate) { if (predicate.apply(v)) { return this; } return C.list(); } @Override public C.List<T> drop(int n) throws IllegalArgumentException { if (n == 0) { return this; } return C.list(); } @Override public C.List<T> dropWhile(Function<? super T, Boolean> predicate) { if (predicate.apply(v)) { return C.list(); } return this; } @Override public C.ListOrSet<T> filter(Function<? super T, Boolean> predicate) { if (predicate.apply(v)) { return this; } return C.empty(); } @Override public <R> C.ListOrSet<R> map(Function<? super T, ? extends R> mapper) { return new Var<R>(mapper.apply(v)); } @Override public <R> C.List<R> flatMap(Function<? super T, ? extends Iterable<? extends R>> mapper) { ListBuilder<R> lb = new ListBuilder<R>(3); forEach(Osgl.f1(mapper).andThen(C.F.addAllTo(lb))); return lb.toList(); } @Override public <E> C.List<Osgl.T2<T, E>> zip(Iterable<E> iterable) { Iterator<E> itr = iterable.iterator(); if (itr.hasNext()) { return new Var<Osgl.T2<T, E>>(Osgl.T2(v, itr.next())); } return C.list(); } @Override public C.Sequence<T2<T, Integer>> zipWithIndex() { return new Var<T2<T, Integer>>(T2(v, 0)); } @Override public Var<T> lazy() { return this; } @Override public Var<T> eager() { return this; } @Override public Var<T> parallel() { return this; } @Override public Var<T> sequential() { return this; } @Override public int hashCode() { return hc(v); } @Override public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof Var) { Var v = (Var)o; return $.eq(v.get(), this.get()); } return false; } @Override public boolean isEmpty() { return false; } @Override public <R> R reduce(R identity, Func2<R, T, R> accumulator) { return reduceLeft(identity, accumulator); } @Override public Option<T> reduce(Func2<T, T, T> accumulator) { return reduceLeft(accumulator); } @Override public Option<T> findOne(Function<? super T, Boolean> predicate) { if (predicate.apply(v)) { return Osgl.some(v); } else { return Osgl.none(); } } @Override public boolean anyMatch(Function<? super T, Boolean> predicate) { return predicate.apply(v); } @Override public boolean noneMatch(Function<? super T, Boolean> predicate) { return !anyMatch(predicate); } @Override public boolean allMatch(Function<? super T, Boolean> predicate) { return anyMatch(predicate); } @Override public int size() throws UnsupportedOperationException { return 1; } @Override public C.List<T> subList(int fromIndex, int toIndex) { if (fromIndex < 0 || toIndex > 1 || fromIndex > toIndex) { throw new IndexOutOfBoundsException(); } if (fromIndex == toIndex) { return C.list(); } return this; } @Override public boolean addAll(Iterable<? extends T> iterable) { throw new UnsupportedOperationException(); } @Override public C.List<T> tail(int n) { if (n == 0) { return C.list(); } return this; } @Override public C.List<T> remove(Function<? super T, Boolean> predicate) { throw new UnsupportedOperationException(); } private class Csr implements Cursor<T> { private int id = 0; @Override public boolean isDefined() { return 0 == id; } @Override public int index() { return id; } @Override public boolean hasNext() { return -1 == id; } @Override public boolean hasPrevious() { return 1 == id; } @Override public Cursor<T> forward() throws UnsupportedOperationException { if (id == -1) { id = 0; return this; } throw new UnsupportedOperationException(); } @Override public Cursor<T> backward() throws UnsupportedOperationException { if (id == 1) { id = 0; } throw new UnsupportedOperationException(); } @Override public Cursor<T> parkLeft() { id = -1; return this; } @Override public Cursor<T> parkRight() { id = 1; return this; } @Override public T get() throws NoSuchElementException { if (id == 0) { return v; } throw new NoSuchElementException(); } @Override public Cursor<T> set(T t) throws IndexOutOfBoundsException, NullPointerException { if (id == 0) { v = t; return this; } throw new IndexOutOfBoundsException(); } @Override public Cursor<T> drop() throws NoSuchElementException, UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public Cursor<T> prepend(T t) throws IndexOutOfBoundsException { throw new UnsupportedOperationException(); } @Override public Cursor<T> append(T t) { throw new UnsupportedOperationException(); } } @Override public Cursor<T> locateFirst(Function<T, Boolean> predicate) { if (predicate.apply(v)) { return new Csr(); } return new Csr().parkRight(); } @Override public Cursor<T> locate(Function<T, Boolean> predicate) { return locateFirst(predicate); } @Override public Cursor<T> locateLast(Function<T, Boolean> predicate) { if (predicate.apply(v)) { return new Csr(); } return new Csr().parkLeft(); } @Override public C.List<T> insert(int index, T t) throws IndexOutOfBoundsException { if (index == 0) { return C.list(t, v); } else if (index == 1) { return C.list(v, t); } else { throw new IndexOutOfBoundsException(); } } @Override public C.List<T> insert(int index, T... ta) throws IndexOutOfBoundsException { if (index == 0) { return C.listOf(ta).prepend(v); } else if (index == 1) { return C.listOf(ta).append(v); } throw new IndexOutOfBoundsException(); } @Override public C.List<T> insert(int index, List<T> subList) throws IndexOutOfBoundsException { if (index == 0) { return C.list(subList).prepend(v); } else if (index == 1) { return C.list(subList).append(v); } throw new IndexOutOfBoundsException(); } @Override public C.List<T> reverse() { return this; } @Override public C.ListOrSet<T> without(Collection<? super T> col) { if (col.contains(v)) { return C.empty(); } return this; } @Override public C.ListOrSet<T> without(T element) { if (Osgl.eq(v, element)) return C.empty(); return this; } @Override public C.ListOrSet<T> without(T element, T... elements) { if (Osgl.eq(v, element)) return C.empty(); int id = search(v, elements); if (-1 == id) return this; return C.empty(); } @Override public C.Set<T> onlyIn(Collection<? extends T> col) { C.Set<T> set = C.newSet(col); if (col.contains(v)) { set.remove(v); } return set; } @Override public C.Set<T> withIn(Collection<T> col) { if (col.contains(v)) { return this; } return C.empty(); } @Override public C.List<T> acceptRight(Function<? super T, ?> visitor) { return accept(visitor); } @Override public C.List<T> acceptRight(Func2<Integer, ? super T, ?> indexedVisitor) { return accept(indexedVisitor); } @Override protected void forEachLeft(Function<? super T, ?> visitor) throws Break { visitor.apply(v); } @Override protected void forEachLeft(Func2<Integer, ? super T, ?> indexedVisitor) throws Break { indexedVisitor.apply(0, v); } @Override protected void forEachRight(Function<? super T, ?> visitor) throws Break { visitor.apply(v); } @Override protected void forEachRight(Func2<Integer, ? super T, ?> indexedVisitor) throws Break { indexedVisitor.apply(0, v); } @Override public <B> C.List<T2<T, B>> zip(List<B> list) { if (list.size() == 0) { return C.list(); } return C.list(T2(v, list.get(0))); } @Override public boolean add(T t) { throw new UnsupportedOperationException(); } @Override public ListIterator<T> listIterator(int index) { if (index == 0) { return new VarListIterator<T>(this); } else if (index == 1) { return new VarListIterator<T>(this, true); } throw new IndexOutOfBoundsException(); } @Override public ListIterator<T> listIterator() { return new VarListIterator<T>(this); } @Override public T last() throws NoSuchElementException { return v; } @Override public Iterator<T> reverseIterator() { return listIterator(0); } @Override public T get(int index) { if (index == 0) { return v; } throw new IndexOutOfBoundsException(); } public T get() { return v; } public Var<T> set(T value) { v = value; return this; } public Var<T> set(Var<T> var) { v = var.v; return this; } @Override public T set(int index, T element) { if (0 == index) { v = element; } throw new IndexOutOfBoundsException(); } @Override public void add(int index, T element) { throw new UnsupportedOperationException(); } @Override public T remove(int index) { throw new UnsupportedOperationException(); } @Override public int indexOf(Object o) { if (Osgl.eq(o, v)) { return 0; } return -1; } @Override public int lastIndexOf(Object o) { return indexOf(o); } @Override public void clear() { throw new UnsupportedOperationException(); } @Override public boolean addAll(int index, Collection<? extends T> c) { throw new UnsupportedOperationException(); } @Override protected void removeRange(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); } @Override public boolean contains(Object o) { return Osgl.eq(v, o); } @Override public Object[] toArray() { return new Object[]{v}; } @Override public <T> T[] toArray(T[] a) { T[] ta = (a.length > 0) ? a : newArray(a, 1); ta[0] = (T) v; if (ta.length > 1) { ta[1] = null; } return ta; } @Override public boolean remove(Object o) { throw new UnsupportedOperationException(); } @Override public boolean containsAll(Collection<?> c) { for (Object o : c) { if (Osgl.ne(o, v)) { return false; } } return true; } @Override public boolean addAll(Collection<? extends T> c) { throw new UnsupportedOperationException(); } @Override public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @Override public <R> R reduceRight(R identity, Func2<R, T, R> accumulator) { return reduce(identity, accumulator); } @Override public Option<T> reduceRight(Func2<T, T, T> accumulator) { return reduce(accumulator); } @Override public Option<T> findLast(Function<? super T, Boolean> predicate) { return findFirst(predicate); } @Override public Iterator<T> iterator() { return listIterator(); } public Var<T> update(Function<T, T> changer) { v = changer.apply(v); return this; } public Var<T> update(Osgl.Func0<T> changer) { v = changer.apply(); return this; } public Option<T> toOption() { if (null == v) { return Osgl.none(); } else { return Osgl.some(v); } } public class _f { public F1<T, Var<T>> setter() { return new F1<T, Var<T>>() { @Override public Var<T> apply(T t) throws NotAppliedException, Break { return Var.this.set(t); } }; } public <R> F1<R, Var<T>> mapper(final Function<R, T> mapper) { return new F1<R, Var<T>>() { @Override public Var<T> apply(R r) throws NotAppliedException, Break { return Var.this.set(mapper.apply(r)); } }; } public F1<T, Var<T>> updater(final Function<T, T> changer) { return new F1<T, Var<T>>() { @Override public Var<T> apply(T t) throws NotAppliedException, Break { return Var.this.update(f1(changer).curry(t)); } }; } public F1<T, Var<T>> updater(final Func2<T, T, T> changer) { return new Osgl.F1<T, Var<T>>() { @Override public Var<T> apply(T t) throws NotAppliedException, Break { F2<T, T, T> f2 = f2(changer); return Var.this.update(f2.curry(t)); } }; } } public _f f = new _f(); public static <T> Var<T> of(T t) { return new Var<T>(t); } } public static final class Val<T> extends Var<T> { public Val(T value) { super(value); } @Override public Var<T> set(T value) { throw new UnsupportedOperationException(); } @Override public T set(int index, T element) { throw new UnsupportedOperationException(); } public static <T> Val<T> of(T t) { return new Val<T>(t); } } public static <T> Var<T> var(T t) { return Var.of(t); } public static <T> Var<T> var() { return Var.of(null); } public static <T> Val<T> val(T t) { return Val.of(t); } public static <T> Const<T> constant(T t) { return Const.<T>of(t); } public static <T> Const<T> constant() { return Const.<T>of(null); } // --- common utilities /** * Check if two object is equals to each other. * * @param a the first object * @param b the second object * @return {@code true} if {@code a} equals to {@code b} * @see #ne(Object, Object) */ public static boolean eq(Object a, Object b) { if (a == b) { return true; } if (null == a || null == b) { return false; } return a.equals(b); } /** * Check if two objects are equals to each other. The comparison will do * array equal matching if needed * * @param a the first object * @param b the second object * @return {@code true} if the first object equals to the second object */ public static boolean eq2(Object a, Object b) { if (eq(a, b)) return true; Class<?> ca = a.getClass(); if (!ca.isArray()) return false; Class<?> cb = b.getClass(); if (ca != cb) return false; if (ca == boolean[].class) { return Arrays.equals((boolean[]) a, (boolean[]) b); } else if (ca == byte[].class) { return Arrays.equals((byte[]) a, (byte[]) b); } else if (ca == int[].class) { return Arrays.equals((int[]) a, (int[]) b); } else if (ca == char[].class) { return Arrays.equals((char[]) a, (char[]) b); } else if (ca == long[].class) { return Arrays.equals((long[]) a, (long[]) b); } else if (ca == float[].class) { return Arrays.equals((float[]) a, (float[]) b); } else if (ca == double[].class) { return Arrays.equals((double[]) a, (double[]) b); } else if (ca == short[].class) { return Arrays.equals((short[]) a, (short[]) b); } else { return Arrays.equals((Object[]) a, (Object[]) b); } } /** * Check if two {@code boolean} value equals to each other * @param a boolean a * @param b boolean b * @return {@code true} if {@code a == b} */ public static boolean eq(boolean a, boolean b) { return a == b; } /** * Check if two {@code byte} value equals to each other * @param a byte a * @param b byte b * @return {@code true} if {@code a == b} */ public static boolean eq(byte a, byte b) { return a == b; } /** * Check if two {@code char} value equals to each other * @param a char a * @param b char b * @return {@code true} if {@code a == b} */ public static boolean eq(char a, char b) { return a == b; } /** * Check if two {@code short} value equals to each other * @param a short a * @param b short b * @return {@code true} if {@code a == b} */ public static boolean eq(short a, short b) { return a == b; } /** * Check if two {@code int} value equals to each other * @param a int a * @param b int b * @return {@code true} if {@code a == b} */ public static boolean eq(int a, int b) { return a == b; } /** * Check if two {@code float} value equals to each other * @param a float a * @param b float b * @return {@code true} if {@code a == b} */ public static boolean eq(float a, float b) { return a == b; } /** * Check if two {@code long} value equals to each other * @param a long a * @param b long b * @return {@code true} if {@code a == b} */ public static boolean eq(long a, long b) { return a == b; } /** * Check if two {@code double} value equals to each other * @param a double a * @param b double b * @return {@code true} if {@code a == b} */ public static boolean eq(double a, double b) { return Double.doubleToLongBits(a) == Double.doubleToLongBits(b); } /** * Check if two objects are equals to each other. * * @param a the first object * @param b the second object * @return {@code false} if {@code a} equals to {@code b} * @see #eq(Object, Object) */ public static boolean ne(Object a, Object b) { return !eq(a, b); } /** * Evaluate an object's bool value. The rules are: * <table summary="boolean value evaluation rules"> * <thead> * <tr> * <th>case</th><th>bool value</th> * </tr> * </thead> * <tbody> * <tr><td>{@code null}</td><td>{@code false}</td></tr> * <tr><td>{@link #NONE}</td><td>{@code false}</td></tr> * <tr><td>String</td><td>{@link S#notEmpty(String) S.notEmpty(v)}</td></tr> * <tr><td>Collection</td><td>{@link java.util.Collection#isEmpty() !v.isEmpty()}</td></tr> * <tr><td>Array</td><td>length of the array > 0</td></tr> * <tr><td>Byte</td><td>{@code v != 0}</td></tr> * <tr><td>Char</td><td>{@code v != 0}</td></tr> * <tr><td>Integer</td><td>{@code v != 0}</td></tr> * <tr><td>Long</td><td>{@code v != 0L}</td></tr> * <tr><td>Float</td><td>{@code Math.abs(v) > Float.MIN_NORMAL}</td></tr> * <tr><td>Double</td><td>{@code Math.abs(v) > Double.MIN_NORMAL}</td></tr> * <tr><td>BigInteger</td><td>{@code !BigInteger.ZERO.equals(v)}</td></tr> * <tr><td>BigDecimal</td><td>{@code !BigDecimal.ZERO.equals(v)}</td></tr> * <tr><td>File</td><td>{@link java.io.File#exists() v.exists()}</td></tr> * <tr><td>{@link Osgl.Func0}</td><td>{@code bool(v.apply())}</td></tr> * <tr><td>Other types</td><td>{@code true}</td></tr> * </tbody> * </table> * * @param v the value to be evaluated * @return {@code true} if v evaluate to true, {@code false} otherwise */ public static boolean bool(Object v) { if (null == v || NONE == v) { return false; } if (v instanceof Boolean) { return (Boolean) v; } if (v instanceof String) { return S.notEmpty((String) v); } if (v instanceof Collection) { return !((Collection) v).isEmpty(); } if (v.getClass().isArray()) { return 0 < Array.getLength(v); } if (v instanceof Number) { if (v instanceof Float) { return bool((float) (Float) v); } if (v instanceof Double) { return bool((double) (Double) v); } if (v instanceof BigInteger) { return bool((BigInteger) v); } if (v instanceof BigDecimal) { return bool((BigDecimal) v); } return bool(((Number) v).intValue()); } if (v instanceof File) { return bool((File) v); } if (v instanceof Func0) { return not(((Func0) v).apply()); } for (Function<Object, Boolean> tester : conf.boolTesters) { try { return !(tester.apply(v)); } catch (RuntimeException e) { // ignore } } return true; } public static boolean bool(boolean v) { return v; } /** * Do bool evaluation on a String. * * @param s the string to be evaluated * @return {@code true} if s is not empty * @see S#empty(String) */ public static boolean bool(String s) { return !S.empty(s); } /** * Do bool evaluation on a collection. * * @param c the collection to be evaluated * @return {@code true} if the collection is not empty * @see java.util.Collection#isEmpty() */ public static boolean bool(Collection<?> c) { return null != c && !c.isEmpty(); } /** * Do bool evaluation on a byte value * * @param v the value to be evaluated * @return {@code true} if the value != 0 */ public static boolean bool(byte v) { return 0 != v; } /** * Do bool evaluation on a char value * * @param v the value to be evaluated * @return {@code true} if the value != 0 */ public static boolean bool(char v) { return 0 != v; } /** * Do bool evaluation on a int value * * @param v the value to be evaluated * @return {@code true} if the value != 0 */ public static boolean bool(int v) { return 0 != v; } /** * Do bool evaluation on a long value * * @param v the value to be evaluated * @return {@code true} if the value != 0 */ public static boolean bool(long v) { return 0L != v; } /** * Do bool evaluation on a float value * * @param v the value to be evaluated * @return {@code true} if {@code Math.abs(v) > Float.MIN_NORMAL} */ public static boolean bool(float v) { return Math.abs(v) > Float.MIN_NORMAL; } /** * Do bool evaluation on a double value * * @param v the value to be evaluated * @return {@code true} if {@code Math.abs(v) > Double.MIN_NORMAL} */ public static boolean bool(double v) { return Math.abs(v) > Double.MIN_NORMAL; } /** * Do bool evaluation on a BigDecimal value * * @param v the value to be evaluated * @return {@code true} if {@code !BigDecimal.ZERO.equals(v)} */ public static boolean bool(BigDecimal v) { return null != v && !BigDecimal.ZERO.equals(v); } /** * Do bool evaluation on a BigInteger value * * @param v the value to be evaluated * @return {@code true} if {@code !BigInteger.ZERO.equals(v)} */ public static boolean bool(BigInteger v) { return null != v && !BigInteger.ZERO.equals(v); } /** * Do bool evaluation on a File instance. * * @param v the file to be evaluated * @return {@code true} if {@code v.exists()} */ public static boolean bool(File v) { return null != v && v.exists(); } /** * Do bool evaluation on an {@link Osgl.Func0} instance. This will call * the {@link Osgl.Func0#apply()} method and continue to * do bool evaluation on the return value * * @param v the function to be evaluated * @return {@code bool(v.apply())} */ public static boolean bool(Func0<?> v) { return bool(v.apply()); } /** * Returns negative of {@link #bool(java.lang.Object)} * * @param o the object to be evaluated * @return {@code !(bool(o))} */ public static boolean not(Object o) { return !(bool(o)); } /** * Returns negative of a boolean value * * @param v the value to be evaluated * @return {@code !v} */ public static boolean not(boolean v) { return !v; } /** * Returns negative of {@link #bool(java.lang.String)} * * @param s the String to be evaluated * @return {@code !(bool(s))} * @see #bool(String) */ public static boolean not(String s) { return !bool(s); } /** * Returns negative of {@link #bool(java.util.Collection)} * * @param c the Collection to be evaluated * @return {@code !(bool(c))} * @see #bool(java.util.Collection) */ public static boolean not(Collection<?> c) { return null == c || c.isEmpty(); } /** * Returns negative of {@link #bool(byte)} * * @param v the byte to be evaluated * @return {@code !(bool(v))} */ public static boolean not(byte v) { return 0 == v; } /** * Returns negative of {@link #bool(char)} * * @param v the char to be evaluated * @return {@code !(bool(v))} */ public static boolean not(char v) { return 0 == v; } /** * Returns negative of {@link #bool(int)} * * @param v the int to be evaluated * @return {@code !(bool(v))} */ public static boolean not(int v) { return 0 == v; } /** * Returns negative of {@link #bool(long)} * * @param v the long to be evaluated * @return {@code !(bool(v))} */ public static boolean not(long v) { return 0L == v; } /** * Returns negative of {@link #bool(float)} * * @param v the float to be evaluated * @return {@code !(bool(v))} */ public static boolean not(float v) { return !bool(v); } /** * Returns negative of {@link #bool(double)} * * @param v the double to be evaluated * @return {@code !(bool(v))} */ public static boolean not(double v) { return !bool(v); } /** * Returns negative of {@link #bool(BigDecimal)} * * @param v the value to be evaluated * @return {@code !(bool(v))} */ public static boolean not(BigDecimal v) { return !bool(v); } /** * Returns negative of {@link #bool(BigInteger)} * * @param v the value to be evaluated * @return {@code !(bool(v))} */ public static boolean not(BigInteger v) { return !bool(v); } /** * Returns negative of {@link #bool(File)} * * @param file the file to be evaluated * @return {@code !(bool(file))} */ public static boolean not(File file) { return !bool(file); } /** * Returns negative of {@link #bool(Osgl.Func0)} * * @param f the function to be evaluated * @return {@code !(bool(f))} */ public static boolean not(Func0<?> f) { return !bool(f); } /** * Check if an object is {@code null} or {@link #NONE} * * @param o the object to test * @return {@code true} if {@code o} is {@code null} or {@link #NONE} */ public static boolean isNull(Object o) { return null == o || NONE == o; } /** * Check if any objects in the parameter list is null * * @param o the first object to be checked * @param oa the array of objects to be checked * @return {@code true} if any one of the argument is {@code null} */ public static boolean anyNull(Object o, Object... oa) { if (!isNull(o)) return true; for (int i = oa.length - 1; i >= 0; --i) { if (!isNull(oa[i])) return true; } return false; } public static boolean noneNull(Object o, Object... oa) { return !anyNull(o, oa); } /** * Returns String representation of an object instance. Predicate the object specified * is {@code null} or {@code Osgl.NONE}, then an empty string is returned * * @param o the object which will be converted into a string * @return a String representation of object */ public static String toString(Object o) { if (isNull(o)) { return ""; } return o.toString(); } public static String toString2(Object o) { if (isNull(o)) { return ""; } if (o.getClass().isArray()) { StringBuilder sb = S.newBuilder(); int len = Array.getLength(o); if (len == 0) { return "[]"; } sb.append("["); sb.append(toString2(Array.get(o, 0))); for (int i = 1; i < len; ++i) { sb.append(", ").append(toString2(Array.get(o, i))); } sb.append("]"); return sb.toString(); } return o.toString(); } /** * Alias of {@link org.osgl.util.S#fmt(String, Object...)} * * @param tmpl the format template * @param args the format arguments * @return the formatted string * @since 0.2 */ public static String fmt(String tmpl, Object... args) { return S.fmt(tmpl, args); } private static final int HC_INIT = 17; private static final int HC_FACT = 37; public static int iterableHashCode(Iterable<?> it) { int ret = HC_INIT; for (Object o : it) { ret = ret * HC_FACT + hc(o); } return ret; } public static int hc(boolean o) { return o ? 1231 : 1237; } public static int hc(boolean[] oa) { int ret = HC_INIT; for (boolean b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } public static int hc(short o) { return (int) o; } public static int hc(short[] oa) { int ret = HC_INIT; for (short b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } public static int hc(byte o) { return (int) o; } public static int hc(byte[] oa) { int ret = HC_INIT; for (byte b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } public static int hc(char o) { return (int) o; } public static int hc(char[] oa) { int ret = HC_INIT; for (char b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } public static int hc(int o) { return o; } public static int hc(int[] oa) { int ret = HC_INIT; for (int b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } public static int hc(float o) { return Float.floatToIntBits(o); } public static int hc(float[] oa) { int ret = HC_INIT; for (float b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } public static int hc(long o) { return (int) (o ^ (o >> 32)); } public static int hc(long[] oa) { int ret = HC_INIT; for (long b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } public static int hc(double o) { return hc(Double.doubleToLongBits(o)); } /** * Calculate hashcode of double array specified * * @param oa the double array * @return the hash code */ public static int hc(double[] oa) { int ret = HC_INIT; for (double b : oa) { ret = ret * HC_FACT + hc(b); } return ret; } /** * Calculate hashcode of objects specified * * @param o object on which hash code to be calculated * @return the calculated hash code */ public static int hc(Object o) { return hc_(o); } /** * Calculate hashcode of objects specified * * @param o1 object 1 * @param o2 object 2 * @return the calculated hash code */ public static int hc(Object o1, Object o2) { int i = 17; i = 31 * i + hc_(o1); i = 31 * i + hc_(o2); return i; } /** * Calculate hashcode of objects specified * * @param o1 object 1 * @param o2 object 2 * @param o3 object 3 * @return the calculated hash code */ public static int hc(Object o1, Object o2, Object o3) { int i = 17; i = 31 * i + hc_(o1); i = 31 * i + hc_(o2); i = 31 * i + hc_(o3); return i; } /** * Calculate hashcode of objects specified * * @param o1 object 1 * @param o2 object 2 * @param o3 object 3 * @param o4 object 4 * @return the calculated hash code */ public static int hc(Object o1, Object o2, Object o3, Object o4) { int i = 17; i = 31 * i + hc_(o1); i = 31 * i + hc_(o2); i = 31 * i + hc_(o3); i = 31 * i + hc_(o4); return i; } /** * Calculate hashcode of objects specified * * @param o1 object 1 * @param o2 object 2 * @param o3 object 3 * @param o4 object 4 * @param o5 object 5 * @return the calculated hash code */ public static int hc(Object o1, Object o2, Object o3, Object o4, Object o5) { int i = 17; i = 31 * i + hc_(o1); i = 31 * i + hc_(o2); i = 31 * i + hc_(o3); i = 31 * i + hc_(o4); i = 31 * i + hc_(o5); return i; } /** * Calculate hashcode of objects specified * * @param o1 object 1 * @param o2 object 2 * @param o3 object 3 * @param o4 object 4 * @param o5 object 5 * @param args other objects * @return the calculated hash code */ public static int hc(Object o1, Object o2, Object o3, Object o4, Object o5, Object... args) { int i = hc(o1, o2, o3, o4, o5); for (Object o : args) { i = 31 * i + hc(o); } return i; } private static int hc_(Object o) { if (null == o) { return HC_INIT * HC_FACT; } if (o.getClass().isArray()) { if (o instanceof int[]) { return hc((int[]) o); } else if (o instanceof long[]) { return hc((long[]) o); } else if (o instanceof char[]) { return hc((char[]) o); } else if (o instanceof byte[]) { return hc((byte[]) o); } else if (o instanceof double[]) { return hc((double[]) o); } else if (o instanceof float[]) { return hc((float[]) o); } else if (o instanceof short[]) { return hc((short[]) o); } else if (o instanceof boolean[]) { return hc((boolean[]) o); } int len = Array.getLength(o); int hc = 17; for (int i = 0; i < len; ++i) { hc = 31 * hc + hc_(Array.get(o, i)); } return hc; } else { return o.hashCode(); } } /** * Return {@link System#currentTimeMillis() current time millis} * * @return the current system time millis * @since 0.2 */ public static long ms() { return System.currentTimeMillis(); } /** * Return {@link System#nanoTime() current nano time} * * @return the current system nano time * @since 0.2 */ public static long ns() { return System.nanoTime(); } /** * Return current time stamp in nano seconds. Alias of {@link #ns()} * * @return the current system nao time * @since 0.2 */ public static long ts() { return System.nanoTime(); } /** * An empty method. */ public static void nil() { } private static ConcurrentHashMap<Class<? extends Enum>, Map<String, Enum>> enumLookup = new ConcurrentHashMap<>(); /** * Return an enum value from code * @param enumClass the enum class * @param name the name of the enum value. `name` is case insensitive * @param <T> the generic enum type * @return the enum value or `null` if there is no value has the name specified */ public static <T extends Enum<T>> T asEnum(Class<T> enumClass, String name) { return asEnum(enumClass, name, false); } /** * Return an enum value from code * @param enumClass the enum class * @param name the name of the enum value. `name` is case insensitive * @param caseSensitive specify whether it should do case sensitive lookup or case insensitive lookup * @param <T> the generic enum type * @return the enum value or `null` if there is no value has the name specified */ public static <T extends Enum<T>> T asEnum(final Class<T> enumClass, final String name, final boolean caseSensitive) { if (S.blank(name)) { return null; } Map<String, Enum> map = enumLookup.get(enumClass); if (null == map) { T[] values = enumClass.getEnumConstants(); map = new HashMap<>(values.length * 2); for (T value: values) { map.put(value.name().toUpperCase(), value); } enumLookup.putIfAbsent(enumClass, map); } String key = name.toUpperCase(); T retVal = (T) map.get(key); return caseSensitive && !retVal.name().equals(name) ? null : retVal; } /** * Search an element in a array * * @param element the element to be located * @param elements the array of element to be searched * @param <T> the type * @return the location of the element inside elements, or {@code -1} if not found */ public static <T> int search(T element, T... elements) { int len = elements.length; if (len == 0) return -1; boolean c = false; if (6 < len) { if (null != element) { c = element instanceof Comparable; } else { T t0 = elements[0]; if (t0 == null) return 0; c = t0 instanceof Comparable; } if (c) { Arrays.sort(elements); } } if (c) { return Arrays.binarySearch(elements, element); } else { for (int i = 0; i < len; ++i) { if (Osgl.eq(element, elements[i])) return i; } return -1; } } public static void echo(String msg, Object... args) { System.out.println(S.fmt(msg, args)); } public static void error(String msg, Object... args) { System.err.println(S.fmt(msg, args)); } public static <T> T ifNullThen(T t1, T def1) { return ensureGet(t1, def1); } public static <T> T ensureGet(T t1, T def1) { if (null != t1) { return t1; } E.NPE(def1); return def1; } public static <T> T ifNullThen(T t1, F0<T> def1) { return ensureGet(t1, def1); } public static <T> T ensureGet(T t1, F0<T> def1) { if (null != t1) { return t1; } t1 = def1.apply(); E.NPE(t1); return t1; } public static <T> T ensureGet(T t1, T def1, T def2) { if (null != t1) { return t1; } if (null != def1) { return def1; } E.npeIf(null == def2); return def2; } public static <T> T ensureGet(T t1, T def1, T def2, T def3) { if (null != t1) { return t1; } if (null != def1) { return def1; } if (null != def2) { return def2; } E.npeIf(null == def3); return def2; } public static <T> T ensureGet(T t1, List<T> defs) { if (null != t1) { return t1; } for (T t : defs) { if (null != t) { return t; } } throw new NullPointerException(); } public static <T> T times(Function<T, T> func, T initVal, int n) { if (n < 0) { throw E.invalidArg("the number of times must not be negative"); } if (n == 0) { return initVal; } T retVal = initVal; for (int i = 1; i < n; ++i) { retVal = func.apply(retVal); } return retVal; } public static <T> Meta<T> meta(T t) { return new Meta<T>(t); } // --- public static class Meta<T> { private T o; public Meta(T obj) { E.NPE(obj); o = obj; } public boolean is(Class<?> clz) { return clz.isAssignableFrom(o.getClass()); } public boolean isNot(Class<?> clz) { return !is(clz); } public boolean kindOf(Object object) { return is(object.getClass()); } } /** * Cast an object to a type. Returns an {@link Option} describing the casted value if * it can be casted to the type specified, otherwise returns {@link #NONE}. * * @param o the object to be casted * @param c specify the type to be casted to * @param <T> the type of the result option value * @return an {@code Option} describing the typed value or {@link #NONE} * if it cannot be casted */ public static <T> Option<T> cast(Object o, Class<T> c) { if (null == o) { return Option.none(); } if (c.isAssignableFrom(o.getClass())) { return Option.some((T) o); } return Option.none(); } @SuppressWarnings("unchecked") public static <T> T cast(Object o) { return (T) o; } public static <T> T notNull(T o) { E.NPE(o); return o; } /** * Set an object field value using reflection. * * @param fieldName the name of the field to be set * @param obj the object on which the value will be set * @param val the value to be set to the field * @param <T> the type of the object * @param <F> the type of the field value * @return the object that has the new value set on the field specified */ public static <T, F> T setField(String fieldName, T obj, F val) { Class<?> cls = obj.getClass(); try { Field f; try { f = cls.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { f = cls.getField(fieldName); } f.setAccessible(true); f.set(obj, val); } catch (Exception e) { E.unexpected(e); } return obj; } private static Map<Object, Class> __primitiveTypes = new HashMap<Object, Class>(); static { __primitiveTypes.put("int", int.class); __primitiveTypes.put("boolean", boolean.class); __primitiveTypes.put("byte", byte.class); __primitiveTypes.put("short", short.class); __primitiveTypes.put("char", char.class); __primitiveTypes.put("long", long.class); __primitiveTypes.put("float", float.class); __primitiveTypes.put("double", double.class); __primitiveTypes.put("int.class", int.class); __primitiveTypes.put("boolean.class", boolean.class); __primitiveTypes.put("byte.class", byte.class); __primitiveTypes.put("short.class", short.class); __primitiveTypes.put("char.class", char.class); __primitiveTypes.put("long.class", long.class); __primitiveTypes.put("float.class", float.class); __primitiveTypes.put("double.class", double.class); __primitiveTypes.put("int[]", int[].class); __primitiveTypes.put("boolean[]", boolean[].class); __primitiveTypes.put("byte[]", byte[].class); __primitiveTypes.put("short[]", short[].class); __primitiveTypes.put("char[]", char[].class); __primitiveTypes.put("long[]", long[].class); __primitiveTypes.put("float[]", float[].class); __primitiveTypes.put("double[]", double[].class); } private static Map<Object, Object> __primitiveInstances = new HashMap<Object, Object>(); static { __primitiveInstances.put("int", 0); __primitiveInstances.put("boolean", false); __primitiveInstances.put("byte", 0); __primitiveInstances.put("short", 0); __primitiveInstances.put("char", 0); __primitiveInstances.put("long", 0l); __primitiveInstances.put("float", 0f); __primitiveInstances.put("double", 0d); __primitiveInstances.put("int.class", 0); __primitiveInstances.put("boolean.class", false); __primitiveInstances.put("byte.class", 0); __primitiveInstances.put("short.class", 0); __primitiveInstances.put("char.class", 0); __primitiveInstances.put("long.class", 0l); __primitiveInstances.put("float.class", 0f); __primitiveInstances.put("double.class", 0d); __primitiveInstances.put(int.class, 0); __primitiveInstances.put(boolean.class, false); __primitiveInstances.put(byte.class, 0); __primitiveInstances.put(short.class, 0); __primitiveInstances.put(char.class, 0); __primitiveInstances.put(long.class, 0l); __primitiveInstances.put(float.class, 0f); __primitiveInstances.put(double.class, 0d); } private static Map<Class, Class> __primitiveToWrappers = new HashMap<Class, Class>(); private static Map<Class, Class> __wrapperToPrmitives = new HashMap<Class, Class>(); static { __primitiveToWrappers.put(int.class, Integer.class); __primitiveToWrappers.put(boolean.class, Boolean.class); __primitiveToWrappers.put(byte.class, Byte.class); __primitiveToWrappers.put(short.class, Short.class); __primitiveToWrappers.put(char.class, Character.class); __primitiveToWrappers.put(long.class, Long.class); __primitiveToWrappers.put(float.class, Float.class); __primitiveToWrappers.put(double.class, Double.class); __primitiveToWrappers.put(int[].class, Integer[].class); __primitiveToWrappers.put(boolean[].class, Boolean[].class); __primitiveToWrappers.put(byte[].class, Byte[].class); __primitiveToWrappers.put(short[].class, Short[].class); __primitiveToWrappers.put(char[].class, Character[].class); __primitiveToWrappers.put(long[].class, Long[].class); __primitiveToWrappers.put(float[].class, Float[].class); __primitiveToWrappers.put(double[].class, Double[].class); for (Map.Entry<Class, Class> entry : __primitiveToWrappers.entrySet()) { __wrapperToPrmitives.put(entry.getValue(), entry.getKey()); } } /** * Check if a give class `c` is a simple type. The following classes are considered to be simple type: * 1. primitive types, e.g. int.class * 2. Wrapper type of primitive types, e.g. Integer.class * 3. String.class * 4. Any class extends `Enum.class` * @param c the class to be checked * @return `true` if the give type `c` is simple type as described above */ public static boolean isSimpleType(Class<?> c) { return String.class == c || __wrapperToPrmitives.containsKey(c) || __primitiveToWrappers.containsKey(c) || Enum.class.isAssignableFrom(c); } public static Class wrapperClassOf(Class c) { if (c.isPrimitive()) { return __primitiveToWrappers.get(c); } if (c.isArray()) { Class c0 = __primitiveToWrappers.get(c); return null == c0 ? c : c0; } return c; } public static Class primitiveTypeOf(Class c) { if (c.isPrimitive()) { return c; } Class c0 = __wrapperToPrmitives.get(c); return null == c0 ? c : c0; } public static <T> Class<T> classForName(String className) { Class c = __primitiveTypes.get(className); if (null != c) return c; try { return (Class<T>) Class.forName(className); } catch (ClassNotFoundException e) { throw new UnexpectedClassNotFoundException(e); } } public static <T> Class<T> classForName(String className, ClassLoader classLoader) { Class c = __primitiveTypes.get(className); if (null != c) return c; try { if (className.contains("[")) { className = S.buffer().append("[L").append(S.before(className, "[")).append(";").toString(); } return (Class<T>) Class.forName(className, true, classLoader); } catch (ClassNotFoundException e) { throw new UnexpectedClassNotFoundException(e); } } public static <T> Option<Class<T>> safeClassForName(String className) { Class c = __primitiveTypes.get(className); if (null != c) return some((Class<T>) c); try { return Osgl.some((Class<T>) Class.forName(className)); } catch (Exception e) { return Osgl.none(); } } public static <T> Option<Class<T>> safeClassForName(String className, ClassLoader classLoader) { Class c = __primitiveTypes.get(className); if (null != c) return some((Class<T>) c); try { return Osgl.some((Class<T>) Class.forName(className, true, classLoader)); } catch (Exception e) { return Osgl.none(); } } public static <T> T newInstance(final String className) { Object o = __primitiveInstances.get(className); if (null != o) return (T) o; // see http://stackoverflow.com/questions/27719295/java-lang-internalerror-callersensitive-annotation-expected-at-frame-1 return new SecurityManager() { private T t; { try { Class caller = getClassContext()[3]; Class<T> c = (Class<T>) Class.forName(className, true, caller.getClassLoader()); t = c.newInstance(); } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } }.t; } public static <T> T newInstance(final String className, ClassLoader cl) { Object o = __primitiveInstances.get(className); if (null != o) return (T) o; try { Class<T> c = (Class<T>) Class.forName(className, true, cl); return c.newInstance(); } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } public static <T> Option<T> safeNewInstance(String className) { Object o = __primitiveInstances.get(className); if (null != o) return some((T) o); try { Class<T> c = (Class<T>) Class.forName(className); return Osgl.some(c.newInstance()); } catch (Exception e) { return Osgl.none(); } } private static boolean testMethodParamType(Class[] pts, Object p, int pos) { E.invalidArgIf(pos < 0); if (pos < pts.length) { Class pt = pts[pos]; pt = $.wrapperClassOf(pt); return (pt.isAssignableFrom(p.getClass())); } else { return false; } } public static <T> T newInstance(Class<T> c) { try { Constructor<T> ct = c.getDeclaredConstructor(); ct.setAccessible(true); return ct.newInstance(); } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } public static <T, P1> T newInstance(Class<T> c, P1 p1) { try { Constructor[] ca = c.getDeclaredConstructors(); for (Constructor<T> ct : ca) { Class[] pts = ct.getParameterTypes(); if (pts.length != 1 && !ct.isVarArgs()) { continue; } if (!testMethodParamType(pts, p1, 0)) { continue; } return ct.newInstance(p1); } throw new UnexpectedNewInstanceException("constructor not found"); } catch (UnexpectedNewInstanceException e) { throw e; } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } public static <T, P1, P2> T newInstance(Class<T> c, P1 p1, P2 p2) { try { Constructor[] ca = c.getConstructors(); for (Constructor<T> ct : ca) { Class[] pts = ct.getParameterTypes(); if (pts.length != 2 && !ct.isVarArgs()) { continue; } if (!testMethodParamType(pts, p1, 0)) { continue; } if (!testMethodParamType(pts, p2, 1)) { continue; } return ct.newInstance(p1, p2); } throw new UnexpectedNewInstanceException("constructor not found"); } catch (UnexpectedNewInstanceException e) { throw e; } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } public static <T, P1, P2, P3> T newInstance(Class<T> c, P1 p1, P2 p2, P3 p3) { try { Constructor[] ca = c.getConstructors(); for (Constructor<T> ct : ca) { Class[] pts = ct.getParameterTypes(); if (pts.length != 3 && !ct.isVarArgs()) { continue; } if (!testMethodParamType(pts, p1, 0)) { continue; } if (!testMethodParamType(pts, p2, 1)) { continue; } if (!testMethodParamType(pts, p3, 2)) { continue; } return ct.newInstance(p1, p2, p3); } throw new UnexpectedNewInstanceException("constructor not found"); } catch (UnexpectedNewInstanceException e) { throw e; } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } public static <T, P1, P2, P3, P4> T newInstance(Class<T> c, P1 p1, P2 p2, P3 p3, P4 p4) { try { Constructor[] ca = c.getConstructors(); for (Constructor<T> ct : ca) { Class[] pts = ct.getParameterTypes(); if (pts.length != 4 && !ct.isVarArgs()) { continue; } if (!testMethodParamType(pts, p1, 0)) { continue; } if (!testMethodParamType(pts, p2, 1)) { continue; } if (!testMethodParamType(pts, p3, 2)) { continue; } if (!testMethodParamType(pts, p4, 3)) { continue; } return ct.newInstance(p1, p2, p3, p4); } throw new UnexpectedNewInstanceException("constructor not found"); } catch (UnexpectedNewInstanceException e) { throw e; } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } public static <T, P1, P2, P3, P4, P5> T newInstance(Class<T> c, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { try { Constructor[] ca = c.getConstructors(); for (Constructor<T> ct : ca) { Class[] pts = ct.getParameterTypes(); if (pts.length != 5 && !ct.isVarArgs()) { continue; } if (!testMethodParamType(pts, p1, 0)) { continue; } if (!testMethodParamType(pts, p2, 1)) { continue; } if (!testMethodParamType(pts, p3, 2)) { continue; } if (!testMethodParamType(pts, p4, 3)) { continue; } if (!testMethodParamType(pts, p5, 4)) { continue; } return ct.newInstance(p1, p2, p3, p4, p5); } throw new UnexpectedNewInstanceException("constructor not found"); } catch (UnexpectedNewInstanceException e) { throw e; } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } public static <T> T newInstance(Class<T> c, Object p1, Object p2, Object p3, Object p4, Object p5, Object... pa) { try { Constructor[] ca = c.getConstructors(); int len = pa.length; for (Constructor<T> ct : ca) { Class[] pts = ct.getParameterTypes(); if (pts.length != 5 + len && !ct.isVarArgs()) { continue; } if (!testMethodParamType(pts, p1, 0)) { continue; } if (!testMethodParamType(pts, p2, 1)) { continue; } if (!testMethodParamType(pts, p3, 2)) { continue; } if (!testMethodParamType(pts, p4, 3)) { continue; } if (!testMethodParamType(pts, p5, 4)) { continue; } boolean shouldContinue = false; for (int i = 0; i < len; ++i) { Object p = pa[i]; if (!testMethodParamType(pts, p, 5 + i)) { shouldContinue = true; break; } } if (shouldContinue) { continue; } Object[] oa = new Object[5 + len]; oa[0] = p1; oa[1] = p2; oa[2] = p3; oa[3] = p4; oa[4] = p5; System.arraycopy(pa, 0, oa, 5, len); return ct.newInstance(oa); } throw new UnexpectedNewInstanceException("constructor not found"); } catch (UnexpectedNewInstanceException e) { throw e; } catch (Exception e) { throw new UnexpectedNewInstanceException(e); } } /** * Returns non-static field of a class by name. The field might be non-public declared in super classes * of the supplied class * @param c the class * @param name the name of the field * @return the field instance or `null` if not found */ public static Field fieldOf(Class<?> c, String name) { return fieldOf(c, name, true); } /** * Returns field of a class by name. The field could be non-public field of super class of * the class specified * @param c the class * @param name the name of the field * @param noStatic specify if static fields shall be included * @return the field instance or `null` if not found */ public static Field fieldOf(Class<?> c, String name, boolean noStatic) { return fieldOf(c, name, Object.class, noStatic); } /** * Returns field of a class by name. The field could be non-public field of super class of * the class specified * @param c the class * @param name the name of the field * @param rootClass the class that stops of the recurive operation. Default is Object.class * @param noStatic specify if static fields shall be included * @return the field instance or `null` if not found */ public static Field fieldOf(Class<?> c, String name, Class<?> rootClass, boolean noStatic) { List<Field> fields = fieldsOf(c, rootClass, noStatic); for (Field f : fields) { if (S.eq(f.getName(), name)) { return f; } } return null; } /** * Returns all fields of a class and all super classes. Note all fields returned will * be called on {@link Field#setAccessible(boolean)} with value `true` * * @param c the class * @return a list of fields */ public static List<Field> fieldsOf(Class<?> c) { return fieldsOf(c, true); } /** * Returns all fields of a class and all super classes. Note all fields returned will * be called on {@link Field#setAccessible(boolean)} with value `true` * * @param c the class * @param filter specify which field will be put into the list if not `null` * @return a list of fields */ public static List<Field> fieldsOf(Class<?> c, $.Function<Field, Boolean> filter) { return fieldsOf(c, Object.class, filter); } /** * Returns all fields of a class and all super classes. Note all fields returned will * be called on {@link Field#setAccessible(boolean)} with value `true` * @param c the class * @param noStatic specify if static fields shall be included. Default: `true` * @return a list of fields */ public static List<Field> fieldsOf(Class<?> c, boolean noStatic) { return fieldsOf(c, Object.class, noStatic); } /** * Returns all fields of a class and all super classes until root class. Note all fields returned will * be called on {@link Field#setAccessible(boolean)} with value `true` * @param c the class * @param rootClass the class that stops the recursive operation * @param noStatic specify if static fields should be included * @return a list of fields */ public static List<Field> fieldsOf(Class<?> c, Class<?> rootClass, boolean noStatic) { List<Field> fields = new ArrayList<Field>(); $.Predicate<Field> filter = noStatic ? new $.Predicate<Field>() { @Override public boolean test(Field field) { return !Modifier.isStatic(field.getModifiers()); } } : null; addFieldsToList(fields, c, rootClass, filter); return fields; } /** * Returns all fields of a class and all super classes until root class. Note all fields returned will * be called on {@link Field#setAccessible(boolean)} with value `true` * @param c the class * @param rootClass the class that stops the recursive lookup * @param filter specify what field should be put into the list if not `null` * @return the list of fields */ public static List<Field> fieldsOf(Class<?> c, Class<?> rootClass, $.Function<Field, Boolean> filter) { List<Field> fields = new ArrayList<Field>(); addFieldsToList(fields, c, rootClass, filter); return fields; } public static List<Field> fieldsOf(Class<?> c, $.Function<Class<?>, Boolean> classFilter, $.Function<Field, Boolean> fieldFilter) { List<Field> fields = new ArrayList<Field>(); addFieldsToList(fields, c, classFilter, fieldFilter); return fields; } private static void addFieldsToList(List<Field> list, Class<?> c, Class<?> rootClass, $.Function<Field, Boolean> filter) { if (c.isInterface()) { return; } Field[] fields = c.getDeclaredFields(); for (Field field : fields) { if (null != filter && !filter.apply(field)) { continue; } field.setAccessible(true); list.add(field); } if (c != rootClass) { c = c.getSuperclass(); if (null != c) { addFieldsToList(list, c, rootClass, filter); } } } private static void addFieldsToList(List<Field> list, Class<?> c, $.Function<Class<?>, Boolean> classFilter, $.Function<Field, Boolean> fieldFilter) { if (c.isInterface()) { return; } Field[] fields = c.getDeclaredFields(); for (Field field : fields) { if (null != fieldFilter && !fieldFilter.apply(field)) { continue; } field.setAccessible(true); list.add(field); } if (null != classFilter) { c = c.getSuperclass(); if (null != c && classFilter.apply(c)) { addFieldsToList(list, c, classFilter, fieldFilter); } } } /** * Invoke a static method by name and parameters * @param c the class * @param methodName the method name * @param pa the parameters * @param <T> the generic type of the class * @param <R> the generic type of the return result * @return the result of method invocation */ public static <T, R> R invokeStatic(Class<T> c, String methodName, Object ... pa) { return invokeMethod(null, c, null, methodName, pa); } /** * Invoke a static method by name and parameters. After invocation * it will cache the method into method bag supplied. This method * will convert all checked exception into corresponding runtime exception * @param methodBag the method bag * @param c the class * @param methodName the method name * @param pa the parameters * @param <T> the generic type of class * @param <R> the generic type of return instance * @return the result of method invocation */ public static <T, R> R invokeStatic(Var<Method> methodBag, Class<T> c, String methodName, Object ... pa) { return invokeMethod(methodBag, c, null, methodName, pa); } /** * Invoke a static method. This method will convert all checked exception * into corresponding runtime exception * @param method the method * @param pa the arguments to invoke the method * @param <R> the generic type of the return result * @return the result of the method invocation */ public static <R> R invokeStatic(Method method, Object ... pa) { try { return (R) method.invoke(null, pa); } catch (Exception e) { throw new UnexpectedMethodInvocationException(e); } } /** * Invoke a virtual method by instance, method name and arguments. This method * will convert all checked exception into corresponding runtime exception. * * After invocation, the method will be cached into the method bag supplied * * @param methodBag A function to cache the method found by name and arguments * @param o the instance on which the virtual method will be invoked * @param methodName the method name * @param pa the arguments * @param <T> generic type of the instance object * @param <R> generic type of the return result * @return result of method invocation */ public static <T, R> R invokeVirtual(Var<Method> methodBag, T o, String methodName, Object ... pa) { E.NPE(o); return invokeMethod(methodBag, null, o, methodName, pa); } /** * Invoke a virtual method by instance, method name and arguments. This method * will convert all checked exception into corresponding runtime exception * @param o the instance on which the virtual method will be invoked * @param methodName the method name * @param pa the arguments * @param <T> generic type of the instance object * @param <R> generic type of the return result * @return result of method invocation */ public static <T, R> R invokeVirtual(T o, String methodName, Object ... pa) { E.NPE(o); return invokeMethod(null, null, o, methodName, pa); } /** * Invoke a virtual {@link Method method}. This method will convert all checked exception * to corresponding runtime exception * @param o the instance on which the method will be invoked * @param method the method * @param pa the arguments * @param <T> generic type of the instance * @param <R> generic type of the result * @return result of method invocation */ public static <T, R> R invokeVirtual(T o, Method method, Object ... pa) { E.NPE(o); try { return (R) method.invoke(o, pa); } catch (Exception e) { throw new UnexpectedMethodInvocationException(e); } } /** * Returns {@link Method} by name and parameter value * @param c the class * @param methodName the method name * @param pa the parameter used to invoke the method * @return the method or `null` if not found */ public static Method getMethod(Class c, String methodName, Object ... pa) { Method[] ma = c.getMethods(); for (Method m: ma) { if (!m.getName().equals(methodName)) { continue; } Class[] pts = m.getParameterTypes(); boolean shouldContinue = false; int len = pts.length; for (int i = 0; i < len ; ++i) { Object p = pa[i]; if (!testMethodParamType(pts, p, i)) { shouldContinue = true; break; } } if (shouldContinue) { continue; } return m; } return null; } /** * Returns {@link Method} by name and argument type * @param c the class * @param methodName the method name * @param argTypes the argument types * @return the method or `null` if not found */ public static Method getMethod(Class c, String methodName, Class ... argTypes) { try { return c.getMethod(methodName, argTypes); } catch (NoSuchMethodException e) { return null; } } private static <T, R> R invokeMethod(Var<Method> methodBag, Class c, T o, String methodName, Object ... pa) { try { if (null == c) { c = o.getClass(); } Method[] ma = c.getMethods(); for (Method m: ma) { if (!m.getName().equals(methodName)) { continue; } Class[] pts = m.getParameterTypes(); boolean shouldContinue = false; int len = pts.length; for (int i = 0; i < len ; ++i) { Object p = pa[i]; if (!testMethodParamType(pts, p, i)) { shouldContinue = true; break; } } if (shouldContinue) { continue; } if (null != methodBag) { methodBag.set(m); } return (R) m.invoke(o, pa); } throw new UnexpectedNoSuchMethodException(c, methodName); } catch (UnexpectedNoSuchMethodException e) { throw e; } catch (Exception e) { throw new UnexpectedMethodInvocationException(e); } } public static PropertyHandlerFactory propertyHandlerFactory = new ReflectionPropertyHandlerFactory(); public static <T> T getProperty(Object entity, String property) { E.NPE(entity); if (property.contains("]")) { property = property.replace('[', '.').replace("]", ""); } if (property.contains(".")) { return getProperty(entity, property.split("\\.")); } else if (property.contains("/")) { return getProperty(entity, property.split("\\/")); } PropertyGetter gettter = propertyGetter(null, entity, property, false); return cast(gettter.get(entity, property)); } @SuppressWarnings("unchecked") public static <T> T getProperty(CacheService cache, Object entity, String property) { E.NPE(entity); if (property.contains("]")) { property = property.replace('[', '.').replace("]", ""); } if (property.contains(".")) { return getProperty(cache, entity, property.split("\\.")); } else if (property.contains("/")) { return getProperty(cache, entity, property.split("\\/")); } PropertyGetter gettter = propertyGetter(cache, entity, property, false); return cast(gettter.get(entity, property)); } public static void setProperty(Object entity, Object val, String property) { E.NPE(entity); if (property.contains("]")) { property = property.replace('[', '.').replace("]", ""); } if (property.contains(".")) { setProperty(entity, val, property.split("\\.")); } else if (property.contains("/")) { setProperty(entity, val, property.split("\\/")); } else { PropertySetter setter = propertySetter(null, entity, property); setter.set(entity, val, property); } } public static void setProperty(CacheService cache, Object entity, Object val, String property) { E.NPE(entity); if (property.contains("]")) { property = property.replace('[', '.').replace("]", ""); } if (property.contains(".")) { setProperty(cache, entity, val, property.split("\\.")); } else if (property.contains("/")) { setProperty(cache, entity, val, property.split("\\/")); } else { PropertySetter setter = propertySetter(cache, entity, property); setter.set(entity, val, property); } } @SuppressWarnings("unchecked") private static <T> T getProperty(Object entity, String ... propertyPath) { return getProperty(null, entity, propertyPath); } private static <T> T getProperty(CacheService cache, Object entity, String ... propertyPath) { if (null == entity) { return null; } int len = propertyPath.length; E.illegalArgumentIf(len < 1); Object lastEntity = null; for (int i = 0; i < len; ++i) { String prop = propertyPath[i]; String lastProp = i == 0 ? prop : propertyPath[i - 1]; if (entity instanceof ValueObject) { ValueObject vo = (ValueObject) entity; if (vo.isUDF()) { entity = vo.value(); } } if (entity instanceof List) { List<Class<?>> classList = findPropertyParameterizedType(lastEntity, lastProp); ListPropertyGetter getter = propertyHandlerFactory.createListPropertyGetter(classList.get(0)); lastEntity = entity; entity = getter.get(lastEntity, prop); } else if (entity instanceof Map) { List<Class<?>> classList = findPropertyParameterizedType(lastEntity, lastProp); if (null == classList) { PropertyGetter getter = propertyGetter(cache, entity, prop, false); lastEntity = entity; entity = getter.get(entity, prop); } else { MapPropertyGetter getter = propertyHandlerFactory.createMapPropertyGetter(classList.get(0), classList.get(1)); lastEntity = entity; entity = getter.get(lastEntity, prop); } } else { PropertyGetter getter = propertyGetter(cache, entity, prop, false); lastEntity = entity; entity = getter.get(entity, null); } if (null == entity) { return null; } } return (T) entity; } private static String propertyGetterKey(Class c, String p, boolean requireField) { return S.builder("osgl:pg:").append(requireField ? "f:": "").append(c.getName()).append(":").append(p).toString(); } @SuppressWarnings("unchecked") private static PropertyGetter propertyGetter(CacheService cache, Object entity, String property, boolean requireField) { PropertyGetter propertyGetter; Class c = entity.getClass(); String key = null; if (null != cache) { key = propertyGetterKey(c, property, requireField); propertyGetter = cache.get(key); if (null != propertyGetter) { return propertyGetter; } } propertyGetter = propertyHandlerFactory.createPropertyGetter(c, property, requireField); if (requireField) { propertyGetter.setNullValuePolicy(PropertyGetter.NullValuePolicy.CREATE_NEW); } if (null != cache) { cache.put(key, propertyGetter); } return propertyGetter; } private static Method findPropertyMethod(Class<?> c, String method) throws NoSuchMethodException { try { return c.getDeclaredMethod(method); } catch (NoSuchMethodException e) { return c.getMethod(method); } } private static Field findPropertyField(Class<?> c, String field) throws NoSuchFieldException { try { return c.getDeclaredField(field); } catch (NoSuchFieldException e) { return c.getField(field); } } private static List<Class<?>> findPropertyParameterizedType(Object entity, String prop) { Class<?> c = entity.getClass(); while (null != c && !Object.class.equals(c)) { try { String p = S.capFirst(prop); String getter = "get" + p; Method m = findPropertyMethod(c, getter); m.setAccessible(true); Type type = m.getGenericReturnType(); if (type instanceof ParameterizedType) { ParameterizedType ptype = cast(type); return findArgumentTypes(ptype); } else { return null; } } catch (NoSuchMethodException e) { try { Method m = findPropertyMethod(c, prop); m.setAccessible(true); Type type = m.getGenericReturnType(); if (type instanceof ParameterizedType) { ParameterizedType ptype = cast(type); return findArgumentTypes(ptype); } } catch (NoSuchMethodException e1) { try { Field f = findPropertyField(c, prop); f.setAccessible(true); Type type = f.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType ptype = cast(type); return findArgumentTypes(ptype); } } catch (NoSuchFieldException e2) { c = c.getSuperclass(); } } } } return null; } private static List<Class<?>> findArgumentTypes(ParameterizedType ptype) { List<Class<?>> retList = C.newList(); Type[] ta = ptype.getActualTypeArguments(); for (Type t: ta) { if (t instanceof Class) { retList.add((Class) t); } else if (t instanceof ParameterizedType) { retList.add((Class) ((ParameterizedType) t).getRawType()); } } return retList; } @SuppressWarnings("unchecked") private static void setProperty(final CacheService cache, Object entity, final Object val, String ... propertyPath) { E.NPE(entity); int len = propertyPath.length; E.illegalArgumentIf(len < 1); Object lastEntity = null; for (int i = 0; i < len; ++i) { String prop = propertyPath[i]; String lastProp = i == 0 ? prop : propertyPath[i - 1]; if (entity instanceof List) { List<Class<?>> classList = findPropertyParameterizedType(lastEntity, lastProp); if (i == len - 1) { ListPropertySetter setter = propertyHandlerFactory.createListPropertySetter(classList.get(0)); setter.set(entity, val, prop); } else { ListPropertyGetter getter = propertyHandlerFactory.createListPropertyGetter(classList.get(0)); getter.setNullValuePolicy(PropertyGetter.NullValuePolicy.CREATE_NEW); lastEntity = entity; entity = getter.get(lastEntity, prop); } } else if (entity instanceof Map) { List<Class<?>> classList = findPropertyParameterizedType(lastEntity, lastProp); if (i == len - 1) { MapPropertySetter setter = propertyHandlerFactory.createMapPropertySetter(classList.get(0), classList.get(1)); setter.set(entity, val, prop); } else { MapPropertyGetter getter = propertyHandlerFactory.createMapPropertyGetter(classList.get(0), classList.get(1)); getter.setNullValuePolicy(PropertyGetter.NullValuePolicy.CREATE_NEW); lastEntity = entity; entity = getter.get(lastEntity, prop); } } else { if (i == len - 1) { PropertySetter setter = propertySetter(cache, entity, prop); setter.set(entity, val, null); } else { PropertyGetter getter = propertyGetter(cache, entity, prop, true); lastEntity = entity; entity = getter.get(entity, null); } } } } private static void setProperty(Object entity, Object val, String ... propertyPath) { setProperty(null, entity, val, propertyPath); } private static String propertySetterKey(Class c, String p) { return S.builder("osgl:sg:").append(c.getName()).append(":").append(p).toString(); } @SuppressWarnings("unchecked") private static PropertySetter propertySetter(CacheService cache, Object entity, String property) { if (null == entity) { return null; } PropertySetter propertySetter; Class c = entity.getClass(); String key = null; if (null != cache) { key = propertySetterKey(c, property); propertySetter = cache.get(key); if (null != propertySetter) { return propertySetter; } } propertySetter = propertyHandlerFactory.createPropertySetter(c, property); if (null != cache) { cache.put(key, propertySetter); } return propertySetter; } public static <T> byte[] serialize(T obj) { E.NPE(obj); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); oos.close(); return baos.toByteArray(); } catch (IOException e) { throw E.ioException(e); } } public static <T> T materialize(byte[] ba, Class<T> c) { E.NPE(ba); return materialize(ba); } public static <T> T deserialize(byte[] ba, Class<T> c) { return materialize(ba, c); } public static <T> T materialize(byte[] ba) { E.NPE(ba); try { ByteArrayInputStream bais = new ByteArrayInputStream(ba); ObjectInputStream ois = new ObjectInputStream(bais); T t = (T) ois.readObject(); ois.close(); return t; } catch (IOException e) { throw E.ioException(e); } catch (ClassNotFoundException e) { throw E.unexpected(e); } } public static <T> T deserialize(byte[] ba) { return materialize(ba); } /** * Create an new array with specified array type and length * * @param model the model array * @param <T> the array component type * @return an new array with the same component type of model and length of model */ public static <T> T[] newArray(T[] model) { return newArray(model, model.length); } /** * Create an new array with specified type and length * * @param model the model array * @param size the new array length * @param <T> the component type * @return an new array with the same type of model and length equals to size */ @SuppressWarnings("unchecked") public static <T> T[] newArray(T[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } Class<?> c = model.getClass(); if (c == Object[].class) { return (T[]) new Object[size]; } return (T[]) Array.newInstance(c.getComponentType(), size); } public static int[] newArray(int[] model) { return newArray(model, model.length); } public static int[] newArray(int[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new int[size]; } public static byte[] newArray(byte[] model) { return newArray(model, model.length); } public static byte[] newArray(byte[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new byte[size]; } public static char[] newArray(char[] model) { return newArray(model, model.length); } public static char[] newArray(char[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new char[size]; } public static short[] newArray(short[] model) { return newArray(model, model.length); } public static short[] newArray(short[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new short[size]; } public static long[] newArray(long[] model) { return newArray(model, model.length); } public static long[] newArray(long[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new long[size]; } public static float[] newArray(float[] model) { return newArray(model, model.length); } public static float[] newArray(float[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new float[size]; } public static double[] newArray(double[] model) { return newArray(model, model.length); } public static double[] newArray(double[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new double[size]; } public static boolean[] newArray(boolean[] model) { return newArray(model, model.length); } public static boolean[] newArray(boolean[] model, int size) { if (size < 0) { throw new IllegalArgumentException(); } return new boolean[size]; } public static <T> T[] concat(T[] a, T t) { int l = a.length; T[] ret = Arrays.copyOf(a, l + 1); ret[l] = t; return ret; } public static <T> T[] concat(T[] a1, T[] a2) { T[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static <T> T[] concat(T[] a1, T[] a2, T[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (T[] a : rest) { len += a.length; } T[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (T[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static int[] concat(int[] a1, int[] a2) { int[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static int[] concat(int[] a1, int[] a2, int[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (int[] a : rest) { len += a.length; } int[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (int[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static boolean[] concat(boolean[] a1, boolean[] a2) { boolean[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static boolean[] concat(boolean[] a1, boolean[] a2, boolean[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (boolean[] a : rest) { len += a.length; } boolean[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (boolean[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static byte[] concat(byte[] a1, byte[] a2) { byte[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static byte[] concat(byte[] a1, byte[] a2, byte[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (byte[] a : rest) { len += a.length; } byte[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (byte[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static short[] concat(short[] a1, short[] a2) { short[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static short[] concat(short[] a1, short[] a2, short[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (short[] a : rest) { len += a.length; } short[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (short[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static char[] concat(char[] a1, char[] a2) { char[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static char[] concat(char[] a1, char[] a2, char[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (char[] a : rest) { len += a.length; } char[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (char[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static long[] concat(long[] a1, long[] a2) { long[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static long[] concat(long[] a1, long[] a2, long[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (long[] a : rest) { len += a.length; } long[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (long[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static float[] concat(float[] a1, float[] a2) { float[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static float[] concat(float[] a1, float[] a2, float[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (float[] a : rest) { len += a.length; } float[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (float[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static double[] concat(double[] a1, double[] a2) { double[] ret = Arrays.copyOf(a1, a1.length + a2.length); System.arraycopy(a2, 0, ret, a1.length, a2.length); return ret; } public static double[] concat(double[] a1, double[] a2, double[]... rest) { int l1 = a1.length, l2 = a2.length, l12 = l1 + l2, len = l12; for (double[] a : rest) { len += a.length; } double[] ret = Arrays.copyOf(a1, len); System.arraycopy(a2, 0, ret, l1, l2); int offset = l12; for (double[] a : rest) { int la = a.length; System.arraycopy(a, 0, ret, offset, la); offset += la; } return ret; } public static boolean[] reverse(boolean[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { boolean e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static byte[] reverse(byte[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { byte e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static char[] reverse(char[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { char e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static short[] reverse(short[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { short e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static int[] reverse(int[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { int e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static float[] reverse(float[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { float e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static long[] reverse(long[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { long e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static double[] reverse(double[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { double e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static Object[] reverse(Object[] a) { int len = a.length; for (int i = 0, mid = len >> 1, j = len - 1; i < mid; i++, j--) { Object e = a[i]; a[i] = a[j]; a[j] = e; } return a; } public static boolean[] asPrimitive(Boolean[] oa) { int len = oa.length; boolean[] pa = new boolean[len]; for (int i = 0; i < len; ++i) { Boolean O = oa[i]; pa[i] = null == O ? false : O; } return pa; } public static Boolean[] asObject(boolean[] pa) { int len = pa.length; Boolean[] oa = new Boolean[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static byte[] asPrimitive(Byte[] oa) { int len = oa.length; byte[] pa = new byte[len]; for (int i = 0; i < len; ++i) { Byte O = oa[i]; pa[i] = null == O ? 0 : O; } return pa; } public static Byte[] asObject(byte[] pa) { int len = pa.length; Byte[] oa = new Byte[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static char[] asPrimitive(Character[] oa) { int len = oa.length; char[] pa = new char[len]; for (int i = 0; i < len; ++i) { Character O = oa[i]; pa[i] = null == O ? 0 : O; } return pa; } public static Character[] asObject(char[] pa) { int len = pa.length; Character[] oa = new Character[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static short[] asPrimitive(Short[] oa) { int len = oa.length; short[] pa = new short[len]; for (int i = 0; i < len; ++i) { Short O = oa[i]; pa[i] = null == O ? 0 : O; } return pa; } public static Short[] asObject(short[] pa) { int len = pa.length; Short[] oa = new Short[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static int[] asPrimitive(Integer[] oa) { int len = oa.length; int[] pa = new int[len]; for (int i = 0; i < len; ++i) { Integer O = oa[i]; pa[i] = null == O ? 0 : O; } return pa; } public static Integer[] asObject(int[] pa) { int len = pa.length; Integer[] oa = new Integer[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static long[] asPrimitive(Long[] oa) { int len = oa.length; long[] pa = new long[len]; for (int i = 0; i < len; ++i) { Long O = oa[i]; pa[i] = null == O ? 0 : O; } return pa; } public static Long[] asObject(long[] pa) { int len = pa.length; Long[] oa = new Long[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static float[] asPrimitive(Float[] oa) { int len = oa.length; float[] pa = new float[len]; for (int i = 0; i < len; ++i) { Float O = oa[i]; pa[i] = null == O ? 0 : O; } return pa; } public static Float[] asObject(float[] pa) { int len = pa.length; Float[] oa = new Float[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static double[] asPrimitive(Double[] oa) { int len = oa.length; double[] pa = new double[len]; for (int i = 0; i < len; ++i) { Double O = oa[i]; pa[i] = null == O ? 0 : O; } return pa; } public static Double[] asObject(double[] pa) { int len = pa.length; Double[] oa = new Double[len]; for (int i = 0; i < len; ++i) { oa[i] = pa[i]; } return oa; } public static <T> T random(T t1, T... ta) { int l = ta.length; if (l == 0) return t1; int i = ThreadLocalRandom.current().nextInt(l + 1); if (i == l) return t1; return ta[i]; } public static <T> T random(T[] ta) { int l = ta.length; if (0 == l) return null; int i = ThreadLocalRandom.current().nextInt(l); return ta[i]; } public static <T> T random(List<T> list) { int l = list.size(); if (0 == l) return null; int i = ThreadLocalRandom.current().nextInt(l); return list.get(i); } public static <T> T random(C.Range<T> range) { int n = ThreadLocalRandom.current().nextInt(range.size()) + 1; return range.tail(n).head(); } public static String randomStr() { return S.random(); } public static String randomStr(int len) { return S.random(len); } public static <T> T NPE(T o) { E.NPE(o); return o; } /** * The default thread factory */ private static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (!t.isDaemon()) t.setDaemon(true); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } } private static ExecutorService _exec = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new DefaultThreadFactory() { }); /** * Execute callback asynchronously after delay specified * * @param callback the callback function to be executed * @param milliseconds the delay * @param <T> return type * @return the result of the callback */ public static <T> Future<T> async(final Osgl.F0<T> callback, final int milliseconds) { return _exec.submit(new Callable<T>() { @Override public T call() throws Exception { Thread.sleep(milliseconds); return callback.apply(); } }); } private static ContextLocal.Factory clf; static { String clfCls = System.getProperty(ContextLocal.CONF_CONTEXT_LOCAL_FACTORY); if (null == clfCls) { clf = ContextLocal.Factory.Predefined.defaultFactory(); } else { Osgl.Option<ContextLocal.Factory> fact = Osgl.safeNewInstance(clfCls); if (fact.isDefined()) { clf = fact.get(); } else { clf = ContextLocal.Factory.Predefined.defaultFactory(); } } } public static <T> ContextLocal<T> contextLocal() { return clf.create(); } public static <T> ContextLocal<T> contextLocal(ContextLocal.InitialValueProvider<T> ivp) { return clf.create(ivp); } private static Set<String> standardsAnnotationMethods = C.newSet(C.list("equals", "hashCode", "toString", "annotationType", "getClass")); private static boolean isStandardAnnotationMethod(Method m) { return standardsAnnotationMethods.contains(m.getName()); } /** * Evaluate Annotation properties * @param anno the annotation instance * @return a Map contains annotation instance properties */ public static Map<String, Object> evaluate(Annotation anno) { Map<String, Object> properties = new HashMap<String, Object>(); Class<? extends Annotation> annoClass = anno.annotationType(); Method[] ma = annoClass.getMethods(); for (Method m : ma) { if (isStandardAnnotationMethod(m)) { continue; } properties.put(m.getName(), $.invokeVirtual(anno, m)); } return properties; } // --- eof common utilities /** * Namespace to configure or extend OSGL _ utilities */ public static final class Conf { private final List<Function<Object, Boolean>> boolTesters = new ArrayList<Function<Object, Boolean>>(); /** * Register a boolean tester. A boolean tester is a {@link Function Function<Object, Boolean>} type function * that applied to {@code Object} type parameter and returns a boolean value of the Object been tested. It * should throw out {@link NotAppliedException} if the type of the object been tested is not recognized. * there is no need to test if the parameter is {@code null} in the tester as the utility will garantee the * object passed in is not null * <pre> * Osgl.Conf.registerBoolTester(new Osgl.F1<Boolean, Object>() { * {@literal @}Override * public Boolean apply(Object o) { * if (o instanceof Score) { * return ((Score)o).intValue() > 60; * } * if (o instanceof Person) { * return ((Person)o).age() > 16; * } * ... * // since we do not recognize the object type, raise the NotAppliedException out * throw new org.osgl.E.NotAppliedException(); * } * }); * </pre> * * @param tester the tester function takes an object as parameter and returns boolean * @return the {@link Conf} instance */ public Conf registerBoolTester(Function<Object, Boolean> tester) { E.NPE(tester); boolTesters.add(tester); return this; } } public static final Conf conf = new Conf(); public static final int JAVA_VERSION = VM.VERSION; public static final boolean IS_SERVER = VM.IS_SERVER; public static final boolean IS_64 = VM.IS_64; public static final OS OS = org.osgl.util.OS.get(); /** * The namespace to aggregate predefined core functions */ public enum F { ; /** * Return a one variable function that throw out a {@link Break} with payload specified when a predicate return * <code>true</code> on an element been tested * * @param predicate the predicate function that takes T type argument * @param payload the payload to be passed into the {@link Break} if predicate returns {@code true} * @param <P> the type of the payload object * @param <T> the type of the object to be consumed by the predicate * @return an new function that takes T argument and apply it to the predicate. If the result is {@code true} * then throw out the {@code Break} with payload specified * @since 0.2 */ public static <P, T> F1<T, Void> breakIf(final Function<? super T, Boolean> predicate, final P payload) { return new F1<T, Void>() { @Override public Void apply(T t) { if (predicate.apply(t)) { throw breakOut(payload); } return null; } }; } /** * Return a one variable function that throw out a {@link Break} when a predicate return * <code>true</code> on an element been tested. There is no payload specified and the <code>Break</code> * will use test result i.e. <code>true</code> as the payload * * @param predicate the predicate function * @param <T> the type of the object consumed by the predicate * @return a new function that applies the predicate and if the result is {@code true} then * throw out a {@link Break} with payload of the object been consumed * @since 0.2 */ public static <T> F1<T, Void> breakIf(final Function<? super T, Boolean> predicate) { return new F1<T, Void>() { @Override public Void apply(T t) { if (predicate.apply(t)) { throw breakOut(t); } return null; } }; } /** * Return a two variables function that throw out a {@link Break} with payload specified when * a two variables predicate return <code>true</code> on an element been tested * * @param predicate the function test the arguments * @param payload the payload to be thrown out if predicate function returns {@code true} on * the argument * @param <P> the payload type * @param <T1> the type of the first argument * @param <T2> the type of the second argument * @return a function that apply predicate to arguments and throw {@link Break} with payload * specified * @since 0.2 */ @SuppressWarnings("unused") public static <P, T1, T2> F2<T1, T2, Void> breakIf(final Func2<? super T1, ? super T2, Boolean> predicate, final P payload ) { return new F2<T1, T2, Void>() { @Override public Void apply(T1 t1, T2 t2) { if (predicate.apply(t1, t2)) { throw breakOut(payload); } return null; } }; } /** * Return a two variables function that throw out a {@link Break} when a two variables predicate return * <code>true</code> on an element been tested. There is no payload specified and the <code>Break</code> * will use test result i.e. <code>true</code> as the payload * * @param predicate the predicate function check if a break should be raised * @param <T1> the type of argument 1 * @param <T2> the type of argument 2 * @return the function that raise {@link Break} if predicate function says {@code true} on the * two arguments * @since 0.2 */ @SuppressWarnings("unused") public static <T1, T2> F2<T1, T2, Void> breakIf(final Func2<? super T1, ? super T2, Boolean> predicate) { return new F2<T1, T2, Void>() { @Override public Void apply(T1 t1, T2 t2) { if (predicate.apply(t1, t2)) { throw breakOut(true); } return null; } }; } /** * Return a three variables function that throw out a {@link Break} with payload specified when * a three variables predicate return <code>true</code> on an element been tested * * @param predicate the predicate function that takes three arguments and returns a boolean type value * @param payload the payload object to be * @param <P> Generic type for payload * @param <T1> generic type of the first argument taken by predicate * @param <T2> generic type of the second argument taken by predicate * @param <T3> generic type of the thrid argument taken by predicate * @return A function of {@link F3 F3<T1, T2, T3, Void>} type * @since 0.2 */ public static <P, T1, T2, T3> F3<T1, T2, T3, Void> breakIf( final Func3<? super T1, ? super T2, ? super T3, Boolean> predicate, final P payload ) { return new F3<T1, T2, T3, Void>() { @Override public Void apply(T1 t1, T2 t2, T3 t3) { if (predicate.apply(t1, t2, t3)) { throw breakOut(payload); } return null; } }; } /** * Return a three variables function that throw out a {@link Break} when a three variables predicate return * <code>true</code> on an element been tested. There is no payload specified and the <code>Break</code> * will use test result i.e. <code>true</code> as the payload * * @param predicate the predicate function that takes three arguments and returns a {@code boolean} type value * @param <T1> the generic type of the argument 1 * @param <T2> the generic type of the argument 2 * @param <T3> the generic type of the argument 3 * @return a function that check on three arguments and throw out {@code true} if the check returns {@code true} * @since 0.2 */ public static <T1, T2, T3> F3<T1, T2, T3, Void> breakIf( final Func3<? super T1, ? super T2, ? super T3, Boolean> predicate ) { return new F3<T1, T2, T3, Void>() { @Override public Void apply(T1 t1, T2 t2, T3 t3) { if (predicate.apply(t1, t2, t3)) { throw breakOut(true); } return null; } }; } /** * Return a four variables function that throw out a {@link Break} with payload specified when * a four variables predicate return <code>true</code> on an element been tested * * @param predicate the predicate function that takes four arguments and returns a {@code boolean} type value * @param payload the payload to be throw out if the predicate function returns {@code true} on given arguments * @param <P> the generic type of the payload * @param <T1> the generic type of the argument 1 * @param <T2> the generic type of the argument 2 * @param <T3> the generic type of the argument 3 * @param <T4> the generic type of the argument 4 * @return a function that check on four arguments and throw out payload if the check returns {@code true} * @since 0.2 */ public static <P, T1, T2, T3, T4> F4<T1, T2, T3, T4, Void> breakIf( final Func4<? super T1, ? super T2, ? super T3, ? super T4, Boolean> predicate, final P payload ) { return new F4<T1, T2, T3, T4, Void>() { @Override public Void apply(T1 t1, T2 t2, T3 t3, T4 t4) { if (predicate.apply(t1, t2, t3, t4)) { throw breakOut(payload); } return null; } }; } /** * Return a four variables function that throw out a {@link Break} when the predicate returns * <code>true</code> on an element been tested. There is no payload specified and the <code>Break</code> * will use test result i.e. <code>true</code> as the payload * * @param predicate the predicate function that takes four arguments and returns a {@code boolean} type value * @param <T1> the generic type of the argument 1 * @param <T2> the generic type of the argument 2 * @param <T3> the generic type of the argument 3 * @param <T4> the generic type of the argument 4 * @return a function that check on four arguments and throw out {@code true} if the check returns {@code true} * @since 0.2 */ public static <T1, T2, T3, T4> F4<T1, T2, T3, T4, Void> breakIf( final Func4<? super T1, ? super T2, ? super T3, ? super T4, Boolean> predicate ) { return new F4<T1, T2, T3, T4, Void>() { @Override public Void apply(T1 t1, T2 t2, T3 t3, T4 t4) { if (predicate.apply(t1, t2, t3, t4)) { throw breakOut(true); } return null; } }; } /** * Return a five variables function that throw out a {@link Break} with payload specified when * a five variables predicate return <code>true</code> on an element been tested * * @param predicate the predicate function that takes five arguments and returns a {@code boolean} type value * @param payload the payload to be throw out if the predicate function returns {@code true} on given arguments * @param <P> the generic type of the payload * @param <T1> the generic type of the argument 1 * @param <T2> the generic type of the argument 2 * @param <T3> the generic type of the argument 3 * @param <T4> the generic type of the argument 4 * @param <T5> the generic type of the argument 5 * @return a function that check on five arguments and throw out payload if the check returns {@code true} * @since 0.2 */ public static <P, T1, T2, T3, T4, T5> F5<T1, T2, T3, T4, T5, Void> breakIf( final Func5<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, Boolean> predicate, final P payload ) { return new F5<T1, T2, T3, T4, T5, Void>() { @Override public Void apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { if (predicate.apply(t1, t2, t3, t4, t5)) { throw breakOut(payload); } return null; } }; } /** * Return a five variables function that throw out a {@link Break} when the predicate returns * <code>true</code> on an element been tested. There is no payload specified and the <code>Break</code> * will use test result i.e. <code>true</code> as the payload * * @param predicate the predicate function that takes five arguments and returns a {@code boolean} type value * @param <T1> the generic type of the argument 1 * @param <T2> the generic type of the argument 2 * @param <T3> the generic type of the argument 3 * @param <T4> the generic type of the argument 4 * @param <T5> the generic type of the argument 5 * @return a function that check on five arguments and throw out {@code true} if the check returns {@code true} * @since 0.2 */ @SuppressWarnings("unused") public static <T1, T2, T3, T4, T5> F5<T1, T2, T3, T4, T5, Void> breakIf( final Func5<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, Boolean> predicate ) { return new F5<T1, T2, T3, T4, T5, Void>() { @Override public Void apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) { if (predicate.apply(t1, t2, t3, t4, t5)) { throw breakOut(true); } return null; } }; } /** * Returns a composed {@link Osgl.Predicate} function that for any given parameter, the test result is <code>true</code> * only when all of the specified predicates returns <code>true</code> when applied to the parameter * * @param predicates a collection of predicates that can be applied to a parameter and returns boolean value * @param <T> the type of the parameter the predicates applied to * @return a composed function * @since 0.2 */ public static <T> Predicate<T> and(final Collection<Function<? super T, Boolean>> predicates) { if (predicates.isEmpty()) { return yes(); } return new Predicate<T>() { @Override public boolean test(T t) { for (Function<? super T, Boolean> cond : predicates) { if (!cond.apply(t)) { return false; } } return true; } }; } /** * Returns a composed {@link Osgl.Predicate} function that for any given parameter, the test result is <code>true</code> * only when all of the specified predicates returns <code>true</code> when applied to the parameter * * @param predicates an array of predicates that can be applied to a parameter and returns boolean value * @param <T> the type of the parameter the predicates applied to * @return a composed function * @since 0.2 */ public static <T> Predicate<T> and(final Function<? super T, Boolean>... predicates) { if (predicates.length == 0) { return yes(); } return and(C.listOf(predicates)); } /** * Returns a composed {@link Osgl.Predicate} function that for any given parameter, the test result is <code>true</code> * only when any one of the specified predicates returns <code>true</code> when applied to the parameter * * @param predicates a collection of predicates that can be applied to a parameter and returns boolean value * @param <T> the type of the parameter the predicates applied to * @return a composed function * @since 0.2 */ public static <T> Predicate<T> or(final Collection<Function<? super T, Boolean>> predicates) { if (predicates.isEmpty()) { return no(); } return new Predicate<T>() { @Override public boolean test(T t) { for (Function<? super T, Boolean> cond : predicates) { if (cond.apply(t)) { return true; } } return false; } }; } /** * Returns a composed {@link Osgl.Predicate} function that for any given parameter, the test result is <code>true</code> * when any one of the specified predicates returns <code>true</code> on the parameter * * @param predicates an array of predicates that can be applied to a parameter and returns boolean value * @param <T> the type of the parameter the predicates applied to * @return a composed function * @since 0.2 */ public static <T> Predicate<T> or(final Function<? super T, Boolean>... predicates) { if (predicates.length == 0) { return no(); } return or(C.listOf(predicates)); } /** * Alias of {@link #or(Collection)} * * @param predicates the predicate functions * @param <T> the element type * @return a function that returns {@code true} if any one of the predicates returns {@code true} * on a given argument * @since 0.2 */ public static <T> Predicate<T> any(final Collection<Function<? super T, Boolean>> predicates) { return or(predicates); } /** * Alias of {@link #or(Osgl.Function[])} * * @param predicates an array of predicate functions * @param <T> the argument type * @return the function that returns {@code true} if any one of the predicate function * returns {@code true} * @since 0.2 */ public static <T> Predicate<T> any(final Function<? super T, Boolean>... predicates) { return or(predicates); } /** * Negation of {@link #or(Collection)} * * @param predicates an iterable of predicate functions * @param <T> the generic type of the argument the predicate functions take * @return a function that apply the argument to all predicate functions and return * {@code true} if all of them return {@code false} on the argument, or * {@code false} if any one of them returns {@code true} * @since 0.2 */ public static <T> Predicate<T> none(final Collection<Function<? super T, Boolean>> predicates) { return negate(or(predicates)); } /** * Negation of {@link #or(Osgl.Function[])} * * @param predicates an array of predicate functions * @param <T> the generic type of the argument the predicate functions take * @return a function that apply the argument to all predicate functions and return * {@code true} if all of them return {@code false} on the argument, or * {@code false} if any one of them returns {@code true} * @since 0.2 */ public static <T> Predicate<T> none(final Function<? super T, Boolean>... predicates) { return negate(or(predicates)); } /** * Returns a function that evaluate an argument's boolean value and negate the value * * @param <T> the type of the argument the function applied to * @return the function returns true if an argument evaluated to false, or vice versa */ public static <T> F1<T, Boolean> not() { return new F1<T, Boolean>() { @Override public Boolean apply(T t) throws NotAppliedException, Break { return Osgl.not(t); } }; } /** * Returns a inverted function of {@link Bijection} which map from X to Y, and the * returned function map from Y to X. This function will call {@link Bijection#invert()} * to get the return function * * @param f the bijection function to be inverted * @param <X> the argument type, and the result type of the return function * @param <Y> the result type, and the argument type of the return function * @return the inverted function of input function {@code f} */ public static <X, Y> Bijection<Y, X> invert(final Bijection<X, Y> f) { return Osgl.f1(f.invert()); } /** * Returns a negate function of the specified predicate function * * @param predicate the specified function that returns boolean value * @return the function that negate the specified predicate */ public static F0<Boolean> negate(final Func0<Boolean> predicate) { return new F0<Boolean>() { @Override public Boolean apply() { return !predicate.apply(); } }; } /** * Returns a negate function of the specified predicate function that applied to 1 params and * returns boolean value * * @param predicate the specified function that applied to the parameter and returns boolean value * @param <T> the type of the parameter to be applied * @return the function that negate the specified predicate */ public static <T> Predicate<T> negate(final Function<? super T, Boolean> predicate) { return new Predicate<T>() { @Override public boolean test(T t) { return !predicate.apply(t); } }; } /** * Returns a negate function of the specified predicate that applied to 2 parameters and returns boolean value * * @param predicate the function applied to 2 params and return boolean value * @param <P1> type of param one * @param <P2> type of param two * @return the function that negate predicate specified */ public static <P1, P2> F2<P1, P2, Boolean> negate(final Func2<? super P1, ? super P2, Boolean> predicate) { return new F2<P1, P2, Boolean>() { @Override public Boolean apply(P1 p1, P2 p2) { return !predicate.apply(p1, p2); } }; } /** * Returns a negate function of the specified predicate that applied to 3 parameters and returns boolean value * * @param predicate the function applied to 2 params and return boolean value * @param <P1> type of param one * @param <P2> type of param two * @param <P3> type of param three * @return the function that negate predicate specified */ public static <P1, P2, P3> F3<P1, P2, P3, Boolean> negate( final Func3<? super P1, ? super P2, ? super P3, Boolean> predicate ) { return new F3<P1, P2, P3, Boolean>() { @Override public Boolean apply(P1 p1, P2 p2, P3 p3) { return !predicate.apply(p1, p2, p3); } }; } /** * Returns a negate function of the specified predicate that applied to 3 parameters and returns boolean value * * @param predicate the function applied to 2 params and return boolean value * @param <P1> type of param one * @param <P2> type of param two * @param <P3> type of param three * @param <P4> type of param four * @return the function that negate predicate specified */ public static <P1, P2, P3, P4> F4<P1, P2, P3, P4, Boolean> negate( final Func4<? super P1, ? super P2, ? super P3, ? super P4, Boolean> predicate ) { return new F4<P1, P2, P3, P4, Boolean>() { @Override public Boolean apply(P1 p1, P2 p2, P3 p3, P4 p4) { return !predicate.apply(p1, p2, p3, p4); } }; } /** * Returns a negate function of the specified predicate that applied to 3 parameters and returns boolean value * * @param predicate the function applied to 2 params and return boolean value * @param <P1> type of param one * @param <P2> type of param two * @param <P3> type of param three * @param <P4> type of param four * @param <P5> type of param five * @return the function that negate predicate specified */ public static <P1, P2, P3, P4, P5> F5<P1, P2, P3, P4, P5, Boolean> negate( final Func5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, Boolean> predicate ) { return new F5<P1, P2, P3, P4, P5, Boolean>() { @Override public Boolean apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { return !predicate.apply(p1, p2, p3, p4, p5); } }; } /** * A predefined forever true predicate which returns <code>true</code> * on any element been tested * * @see #yes() * @since 0.2 */ public static final Predicate TRUE = new Predicate() { @Override public boolean test(Object o) { return true; } }; /** * A type-safe version of {@link #TRUE} * * @param <T> the argument type * @return a function that always returns {@code true} * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> Predicate<T> yes() { return TRUE; } /** * A predefined forever FALSE predicate which always return * <code>false</code> for whatever element been tested * * @see #no() * @since 0.2 */ @SuppressWarnings("unchecked") public static final Predicate FALSE = negate(TRUE); /** * A type-safe version of {@link #FALSE} * * @param <T> the argument type * @return a function that always return {@code false} * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> Predicate<T> no() { return FALSE; } /** * A predefined <code>Predicate</code> predicate test if the * element specified is <code>null</code> or {@link #NONE}. * * @since 0.2 */ public static final Predicate IS_NULL = new Predicate() { @Override public boolean test(Object o) { return null == o || NONE == o; } }; /** * The type-safe version of {@link #IS_NULL} * * @param <T> the argument type * @return a function that check if an argument is {@code null} or {@code NONE} * @since 0.2 */ @SuppressWarnings({"unused", "unchecked"}) public static <T> Predicate<T> isNull() { return IS_NULL; } /** * The type-safe version of {@link #IS_NULL} * * @param c the class that specifies the argument type * @param <T> the argument type * @return a function that check if the argument is {@code null} or {@code NONE} * @since 0.2 */ @SuppressWarnings({"unused", "unchecked"}) public static <T> Predicate<T> isNull(Class<T> c) { return IS_NULL; } /** * A predefined <code>Predicate</code> predicate test if the element * specified is NOT null * * @since 0.2 */ @SuppressWarnings("unchecked") public static final Predicate NOT_NULL = negate(IS_NULL); /** * The type-safe version of {@link #NOT_NULL} * * @param <T> the element type * @return a function that check if argument is {@code null} or {@code NONE} * @since 0.2 */ @SuppressWarnings({"unused", "unchecked"}) public static <T> Predicate<T> notNull() { return NOT_NULL; } /** * A predefined function that when apply to a parameter it return it directly, so for any Object o * <pre> * IDENTITY.apply(o) == o; * </pre> * * @since 0.2 */ public static final F1 IDENTITY = new F1() { @Override public Object apply(Object o) { return o; } @Override public Bijection invert() { return this; } }; /** * The type-safe version of {@link #IDENTITY} * * @param <T> the element type * @return the identity function that always return the argument itself * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> F1<T, T> identity() { return IDENTITY; } /** * The type-safe version of {@link #IDENTITY} * @param clz the class that restrict the type of <T> * @param <T> the generic type * @return the identity function that when get called, always return the parameter * @since 0.9 */ public static <T> F1<T, T> identity(Class<T> clz) { return IDENTITY; } private static <T extends Comparable<T>> F2<T, T, Boolean> _cmp(final boolean lt) { return new F2<T, T, Boolean>() { @Override public Boolean apply(T t1, T t2 ) throws NotAppliedException, Break { if (lt) { return (t1.compareTo(t2) < 0); } else { return (t1.compareTo(t2) > 0); } } }; } private static <T extends Comparable<T>> F1<T, Boolean> _cmp(final T v, final boolean lt) { return new F1<T, Boolean>() { @Override public Boolean apply(T t) throws NotAppliedException, Break { if (lt) { return t.compareTo(v) < 0; } else { return t.compareTo(v) > 0; } } }; } /** * Returns a function that apply to one parameter and compare it with the value {@code v} specified, * returns {@code true} if the parameter applied is less than {@code v} * * @param v the value to be compare with the function parameter * @param <T> the type of the value and parameter * @return the function that do the comparison * @since 0.2 */ public static <T extends Comparable<T>> F1<T, Boolean> lt(final T v) { return _cmp(v, true); } /** * Alias of {@link #lt(Comparable)} * * @param v a value used to check against function argument * @param <T> the element type * @return a function that check if a object is lesser than the value specified * @since 0.2 */ public static <T extends Comparable<T>> F1<T, Boolean> lessThan(final T v) { return lt(v); } /** * Returns a function that apply to one parameter and compare it with the value {@code v} specified, * returns {@code true} if the parameter applied is greater than {@code v} * * @param v the value to be compare with the function parameter * @param <T> the type of the value and parameter * @return the function that do the comparison * @since 0.2 */ public static <T extends Comparable<T>> F1<T, Boolean> gt(final T v) { return _cmp(v, false); } /** * Alias of {@link #gt(Comparable)} * * @param v the value used to check against function argument * @param <T> the element type * @return a function that check if a object is greater than the value specified * @since 0.2 */ public static <T extends Comparable<T>> F1<T, Boolean> greaterThan(final T v) { return gt(v); } /** * Returns a function that apply to one parameter and compare it with the value {@code v} specified, * returns {@code true} if the parameter applied is greater than or equals to {@code v} * * @param v the value to be compare with the function parameter * @param <T> the type of the value and parameter * @return the function that do the comparison * @since 0.2 */ public static <T extends Comparable<T>> F1<T, Boolean> gte(final T v) { return negate(lt(v)); } /** * Alias of {@link #gte(Comparable)} * * @param v the value used to check against function argument * @param <T> the element type * @return a function that check if an object is greater than or equals to the value specified * @since 0.2 */ @SuppressWarnings("unused") public static <T extends Comparable<T>> F1<T, Boolean> greaterThanOrEqualsTo(final T v) { return gte(v); } /** * Returns a function that apply to one parameter and compare it with the value {@code v} specified, * returns {@code true} if the parameter applied is less than or equals to {@code v} * * @param v the value to be compare with the function parameter * @param <T> the type of the value and parameter * @return the function that do the comparison * @since 0.2 */ public static <T extends Comparable<T>> F1<T, Boolean> lte(final T v) { return negate(gt(v)); } /** * Alias of {@link #lte(Comparable)} * * @param v the value to be used to check agains function arugment * @param <T> the element type * @return a function that check if a object is lesser than or equals to specified value * @since 0.2 */ @SuppressWarnings("unused") public static <T extends Comparable<T>> F1<T, Boolean> lessThanOrEqualsTo(final T v) { return lte(v); } /** * A function that apply to two parameters then return {@code true} if the first parameter * is less than the second one. The type of the two parameter should be the same and should * implements {@link Comparable} * * @since 0.2 */ public static final F2 LESS_THAN = F.<Comparable>_cmp(true); /** * A function that apply to two parameters then return {@code true} if the first parameter * is greater than the second one. The type of the two parameter should be the same and should * implements {@link Comparable} * * @since 0.2 */ public static final F2 GREATER_THAN = F.<Comparable>_cmp(false); /** * A function that apply to two parameters then return {@code true} if the first parameter * is less than or equal to the second one. The type of the two parameter should be the same * and should implements {@link Comparable} * * @since 0.2 */ public static final F2 LESS_THAN_OR_EQUAL_TO = negate(GREATER_THAN); /** * A function that apply to two parameters then return {@code true} if the first parameter * is greater than or equal to the second one. The type of the two parameter should be the same * and should implements {@link Comparable} * * @since 0.2 */ public static final F2 GREATER_THAN_OR_EQUAL_TO = negate(LESS_THAN); /** * Returns a function that check if a value is less than another one. This is the * type safe version of {@link #LESS_THAN} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @return the function that do the comparison * @since 0.2 */ @SuppressWarnings("unchecked") public static <T extends Comparable<T>> F2<T, T, Boolean> lt() { return LESS_THAN; } /** * Alias of {@link #lt()} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @return the function that do the comparison * @since 0.2 */ public static <T extends Comparable<T>> F2<T, T, Boolean> lessThan() { return lt(); } /** * Returns a function that check if a value is less than or equals to another one. * This is the type safe version of {@link #LESS_THAN_OR_EQUAL_TO} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @return the function that do the comparison * @since 0.2 */ @SuppressWarnings("unchecked") public static <T extends Comparable<T>> F2<T, T, Boolean> lte() { return LESS_THAN_OR_EQUAL_TO; } /** * Alias of {@link #lte()} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @return the function that do the comparison * @since 0.2 */ public static <T extends Comparable<T>> F2<T, T, Boolean> lessThanOrEqualsTo() { return lte(); } /** * Returns a function that check if a value is less than another one. * * @param <T> The type of the value been compared, should implements {@link Comparable} * @return the function that do the comparison * @since 0.2 */ @SuppressWarnings("unchecked") public static <T extends Comparable<T>> F2<T, T, Boolean> gt() { return GREATER_THAN; } /** * Alias of {@link #gt()} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @return the function that do the comparison * @since 0.2 */ @SuppressWarnings("unused") public static <T extends Comparable<T>> F2<T, T, Boolean> greaterThan() { return gt(); } /** * Returns a function that check if a value is greater than or equals to another one. * This is the type safe version of {@link #GREATER_THAN_OR_EQUAL_TO} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @return the function that do the comparison * @since 0.2 */ public static <T extends Comparable<T>> F2<T, T, Boolean> gte() { return negate(LESS_THAN); } /** * Alias of {@link #gte()} * * @param <T> the element type * @return a function that check if one element is greater than or equals to another * @since 0.2 */ @SuppressWarnings("unused") public static <T extends Comparable<T>> F2<T, T, Boolean> greaterThanOrEqualsTo() { return gte(); } private static <T> F2<T, T, Boolean> _cmp(final java.util.Comparator<? super T> c, final boolean lt) { return new F2<T, T, Boolean>() { @Override public Boolean apply(T t1, T t2) throws NotAppliedException, Break { if (lt) { return c.compare(t1, t2) < 0; } else { return c.compare(t1, t2) > 0; } } }; } /** * Returns a function that check if a value is less than another one using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> lt(final java.util.Comparator<? super T> c) { return _cmp(c, true); } /** * Alias of {@link #lt(java.util.Comparator)} * * @param c a comparator function * @param <T> element type * @return a function that use {@code c} to check if an element is lesser than another * @since 0.2 */ public static <T> F2<T, T, Boolean> lessThan(final java.util.Comparator<? super T> c) { return lt(c); } /** * Returns a function that check if a value is less than another one using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> gt(final java.util.Comparator<? super T> c) { return _cmp(c, false); } /** * Alias of {@link #gt(java.util.Comparator)} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> greaterThan(final java.util.Comparator<? super T> c) { return gt(c); } /** * Returns a function that check if a value is less than or equals to another one * using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> lte(final java.util.Comparator<? super T> c) { return negate(gt(c)); } /** * Alias of {@link #lte(java.util.Comparator)} * * @param c a comparator function * @param <T> the element type * @return a function that use {@code c} to check if an element is lesser than or equals to another * @since 0.2 */ @SuppressWarnings("unused") public static <T> F2<T, T, Boolean> lessThanOrEqualsTo(final java.util.Comparator<? super T> c) { return lte(c); } /** * Returns a function that check if a value is greater than or equals to another one * using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> gte(final java.util.Comparator<? super T> c) { return negate(lt(c)); } /** * Alias of {@link #gte(java.util.Comparator)} * * @param c a comparator function * @param <T> the element type * @return a function that use {@code c} to check if an element is greater than or equals to another * @since 0.2 */ @SuppressWarnings("unused") public static <T> F2<T, T, Boolean> greaterThanOrEqualsTo(final java.util.Comparator<? super T> c) { return gte(c); } private static <T> F2<T, T, Boolean> _cmp(final Func2<? super T, ? super T, Integer> c, final boolean lt) { return new F2<T, T, Boolean>() { @Override public Boolean apply(T t1, T t2) throws NotAppliedException, Break { if (lt) { return c.apply(t1, t2) < 0; } else { return c.apply(t1, t2) > 0; } } }; } /** * Returns a function that check if a value is less than another one using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> lt(final Func2<? super T, ? super T, Integer> c) { return _cmp(c, true); } /** * Alias of {@link #lt(java.util.Comparator)} * * @param c a comparator function * @param <T> the element type * @return a function that use function {@code c} to check if an element is lesser than another * @since 0.2 */ public static <T> F2<T, T, Boolean> lessThan(final Func2<? super T, ? super T, Integer> c) { return lt(c); } /** * Returns a function that check if a value is less than another one using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> gt(final Func2<? super T, ? super T, Integer> c) { return _cmp(c, false); } /** * Alias of {@link #gt(java.util.Comparator)} * * @param c a comparator function * @param <T> the element type * @return a function that use comparator function {@code c} to check if an object is greater than another * @since 0.2 */ public static <T> F2<T, T, Boolean> greaterThan(final Func2<? super T, ? super T, Integer> c) { return gt(c); } /** * Returns a function that check if a value is less than or equals to another one * using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> lte(final Func2<? super T, ? super T, Integer> c) { return negate(gt(c)); } /** * Alias of {@link #lte(java.util.Comparator)} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> lessThanOrEqualsTo(final Func2<? super T, ? super T, Integer> c) { return lte(c); } /** * Returns a function that check if a value is greater than or equals to another one * using the {@link Comparator} specified * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> gte(final Func2<? super T, ? super T, Integer> c) { return negate(lt(c)); } /** * Alias of {@link #gte(java.util.Comparator)} * * @param <T> The type of the value been compared, should implements {@link Comparable} * @param c The comparator that can compare the value * @return the function that do the comparison * @since 0.2 */ public static <T> F2<T, T, Boolean> greaterThanOrEqualsTo(final Func2<? super T, ? super T, Integer> c) { return gte(c); } /** * A predefined function that applies to two parameters and check if they are equals to each other */ public static final F2 EQ = new F2() { @Override public Object apply(Object a, Object b) { return Osgl.eq(a, b); } }; /** * Alias of {@link #EQ} * * @since 0.2 */ @SuppressWarnings("unused") public static final F2 EQUAL = EQ; /** * The type-safe version of {@link #EQ} * * @param <P1> the type of the first argument * @param <P2> the type of the second argument * @return a type-safe function that check equility of two objects * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2> F2<P1, P2, Boolean> eq() { return EQ; } /** * Alias of {@link #eq()} * * @param <P1> the type of the first argument * @param <P2> the type of the second argument * @return a type-safe function that check equility of two objects * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2> F2<P1, P2, Boolean> equal() { return EQ; } /** * Returns a {@link Predicate} that checkes if the argument * equals to the element specified * * @param element the object to be checked with argument when applying * the function * @param <P> the element type * @return the function that returns {@code true} if the argument equals * with the element specified or {@code false} otherwise */ public static <P> Predicate<P> eq(final P element) { return new Predicate<P>() { @Override public boolean test(P p) { return Osgl.eq(p, element); } }; } /** * A predefined function that applies to two parameters and check if they are not equals to * each other. This is a negate function of {@link #EQ} * * @since 0.2 */ public static final F2 NE = negate(EQ); /** * Alias of {@link #NE} * * @since 0.2 */ @SuppressWarnings("unused") public static final F2 NOT_EQUAL = NE; /** * The type-safe version of {@link #NE} * * @param <P1> type of the first argument * @param <P2> type of the second argument * @return the type-safe version of {@link #NE} * @since 0.2 */ @SuppressWarnings("unchecked") public static <P1, P2> F2<P1, P2, Boolean> ne() { return NE; } /** * Alias of {@link #ne()} * * @param <P1> type of the first argument * @param <P2> type of the second argument * @return the type-safe version of {@link #NE} * @since 0.2 */ @SuppressWarnings({"unchecked", "unused"}) public static <P1, P2> F2<P1, P2, Boolean> notEqual() { return NE; } public static final Comparator NATURAL_ORDER = Comparator.NaturalOrder.INSTANCE; public static final Comparator REVERSE_ORDER = Comparator.ReverseOrder.INSTANCE; @SuppressWarnings("unchecked") public static <T extends Comparable<T>> Comparator<T> naturalOrder() { return (Comparator<T>) NATURAL_ORDER; } @SuppressWarnings("unchecked") public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return (Comparator<T>) REVERSE_ORDER; } public static <T> Comparator<T> reverse(final java.util.Comparator<? super T> c) { return new Comparator<T>() { @Override public int compare(T o1, T o2) { return c.compare(o2, o1); } }; } public static <T, U extends Comparable<? super U>> Comparator<T> comparing( final Function<? super T, ? extends U> keyExtractor ) { E.NPE(keyExtractor); return new Comparator<T>() { @Override public int compare(T o1, T o2) { return (keyExtractor.apply(o1).compareTo(keyExtractor.apply(o2))); } }; } /** * Construct a {@link Comparator} with a function to extract the key of type U from given object of type T and * a comparator to compare type U * * @param keyExtractor the function to extract the key for comparison * @param keyComparator the {@link Comparator} that compares type U (the key type) * @param <T> the type of the object instance * @param <U> the type of the key extract from T * @return a comparator that compares type T objects */ public static <T, U> Comparator<T> comparing( final Function<? super T, ? extends U> keyExtractor, final java.util.Comparator<? super U> keyComparator ) { E.NPE(keyExtractor, keyComparator); return new Comparator<T>() { @Override public int compare(T o1, T o2) { return keyComparator.compare(keyExtractor.apply(o1), keyExtractor.apply(o2)); } }; } /** * A predefined function that calculate hash code of an object * * @see #hc(Object) * @since 0.2 */ public static final F1 HASH_CODE = new F1() { @Override public Integer apply(Object o) { return Osgl.hc(o); } }; /** * The type-safe version of {@link #HASH_CODE} * * @param <T> specifies the generic type of the argument passed to the returned function * @return a function of type {@link F1 F1<T, Integer>} that takes type {@code T} argument and * returns {@link Object#hashCode()} of the argument * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> F1<T, Integer> hc() { return HASH_CODE; } /** * A predefined function that when applied to an object instance, returns * String representation of the instance * * @see #toString2(Object) * @since 0.2 */ public static final F1 AS_STRING = new F1() { @Override public Object apply(Object o) { return Osgl.toString2(o); } }; /** * A type-safe version of {@link #AS_STRING}. It returns a function * that takes argument of type {@code T} and returns a String by calling * {@link Object#toString()} function on the argument * * @param <T> the generic type T of the returning function * @return a function of type {@link F1 F1<T, String>} * @since 0.2 */ @SuppressWarnings("unchecked") public static <T> F1<T, String> asString() { return AS_STRING; } /** * Type safe version of {@link #AS_STRING}. It returns a function that * takes argument of type {@code T} and returns a String by calling * {@link Object#toString()} function on the argument * * @param tClass the class specify the generic type * @param <T> the generic type T of the returning function * @return a function of type {@link F1 F1<T, String>} */ public static <T> F1<T, String> asString(Class<T> tClass) { return AS_STRING; } /** * A predicate function that when applied to a {@link java.lang.reflect.Field} type * object, returns `true` when the field is not static */ public static Predicate<Field> NON_STATIC_FIELD = new Predicate<Field>() { @Override public boolean test(Field field) { return !Modifier.isStatic(field.getModifiers()); } }; public static <BEAN> Transformer<BEAN, Object> propertyExtractor(final String property) { return new Transformer<BEAN, Object>() { @Override public Object transform(BEAN bean) { return $.getProperty(bean, property); } }; } /** * Returns a predicate function that when applied to a {@link Field} type * object, returns `true` if the field has specified annotation presented * @param annoClass the annotation * @return a predicate function as described above */ public static Predicate<Field> fieldWithAnnotation(final Class<? extends Annotation> annoClass) { return new Predicate<Field>() { @Override public boolean test(Field field) { return field.isAnnotationPresent(annoClass); } }; } } }