org.opencastproject.util.data.functions.Functions Maven / Gradle / Ivy
/*
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License
* at:
*
* http://opensource.org/licenses/ecl2.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
*/
package org.opencastproject.util.data.functions;
import static org.opencastproject.util.data.Either.left;
import static org.opencastproject.util.data.Either.right;
import org.opencastproject.util.data.Effect;
import org.opencastproject.util.data.Effect0;
import org.opencastproject.util.data.Either;
import org.opencastproject.util.data.Function;
import org.opencastproject.util.data.Function0;
import org.opencastproject.util.data.Function2;
import org.opencastproject.util.data.Predicate;
/** General purpose functions, especially function transformations. */
public final class Functions {
private Functions() {
}
/** Function composition: f . g = f(g(x)) = o(f, g)
*/
public static Function o(final Function super B, ? extends C> f,
final Function super A, ? extends B> g) {
return new Function() {
@Override
public C apply(A a) {
return f.apply(g.apply(a));
}
};
}
/** Function composition: f . g = f(g) = o(f, g)
*/
public static Function0 o(final Function super A, ? extends B> f, final Function0 extends A> g) {
return new Function0() {
@Override
public B apply() {
return f.apply(g.apply());
}
};
}
/** Left to right composition: f then g = g(f(x))
*/
public static Function then(final Function super A, ? extends B> f,
final Function super B, ? extends C> g) {
return new Function() {
@Override
public C apply(A a) {
return g.apply(f.apply(a));
}
};
}
/** Left to right composition: f then g = g(f)
*/
public static Function0 then(final Function0 extends A> f, final Function super A, ? extends B> g) {
return new Function0() {
@Override
public B apply() {
return g.apply(f.apply());
}
};
}
/** Apply f
and ignore its result, then apply g
. */
public static Function0 then(final Function0 extends A> f, final Function0 extends B> g) {
return new Function0() {
@Override
public B apply() {
f.apply();
return g.apply();
}
};
}
/**
* Create a new function from f
decorated with an exception transformer. Any exception that occurs during
* application of f
is passed to transformer
whose return value is then being thrown.
*/
public static Function rethrow(final Function super A, ? extends B> f,
final Function super Exception, ? extends Exception> transformer) {
return new Function() {
@Override
public B apply(A a) {
try {
return f.apply(a);
} catch (Exception e) {
return chuck(transformer.apply(e));
}
}
};
}
/**
* Create a new function from f
decorated with an exception handler. Any exception that occurs during
* application of f
is passed to handler
whose return value is then being returned.
*/
public static Function handle(final Function super A, ? extends B> f,
final Function super Exception, ? extends B> handler) {
return new Function() {
@Override
public B apply(A a) {
try {
return f.apply(a);
} catch (Exception e) {
return handler.apply(e);
}
}
};
}
/**
* Create a new function from f
decorated with an exception handler. The new function either returns the
* value of f
or in case of an exception being thrown on the application of f
the return
* value of handler
.
*/
public static Function> either(final Function super A, ? extends B> f,
final Function super Exception, ? extends C> handler) {
return new Function>() {
@Override
public Either apply(A a) {
try {
B b = f.apply(a);
return right(b);
} catch (Exception e) {
C c = handler.apply(e);
return left(c);
}
}
};
}
/** Curry a function of arity 2. */
// todo rename since its actually partial application
public static Function curry(final Function2 super A, ? super B, ? extends C> f, final A a) {
return new Function() {
@Override
public C apply(B b) {
return f.apply(a, b);
}
};
}
/** Curry a function of arity 2. (a, b) -gt; c =gt; a -gt; b -gt; c */
public static Function> curry(final Function2 super A, ? super B, ? extends C> f) {
return new Function>() {
@Override
public Function apply(final A a) {
return new Function() {
@Override
public C apply(B b) {
return f.apply(a, b);
}
};
}
};
}
/** Uncurry to a function of arity 2. a -gt; b -gt; c =gt; (a, b) -gt; c */
public static Function2 uncurry(final Function super A, Function> f) {
return new Function2() {
@Override
public C apply(A a, B b) {
return f.apply(a).apply(b);
}
};
}
/** Curry a function of arity 1. */
public static Function0 curry(final Function super A, ? extends B> f, final A a) {
return new Function0() {
@Override
public B apply() {
return f.apply(a);
}
};
}
/** Curry a function of arity 1. */
public static Function> curry(final Function f) {
return new Function>() {
@Override
public Function0 apply(final A a) {
return new Function0() {
@Override
public B apply() {
return f.apply(a);
}
};
}
};
}
/** Flip arguments of a function of arity 2. */
public static Function2 flip(final Function2 super A, ? super B, ? extends C> f) {
return new Function2() {
@Override
public C apply(B b, A a) {
return f.apply(a, b);
}
};
}
/** Turn a function into an effect by discarding its result. */
public static Effect toEffect(final Function super A, ? extends B> f) {
return new Effect() {
@Override
protected void run(A a) {
f.apply(a);
}
};
}
public static Predicate toPredicate(final Function super A, Boolean> f) {
return new Predicate() {
@Override
public Boolean apply(A a) {
return f.apply(a);
}
};
}
/** Noop effect. */
public static final Effect0 noop = new Effect0() {
@Override
protected void run() {
}
};
/** Identity function. */
public static Function identity() {
return new Function() {
@Override
public A apply(A a) {
return a;
}
};
}
/**
* Identity function. The type is based on the type of the example object to save some nasty typing, e.g.
* Function.<Integer>identity()
vs. identity(0)
*
* Please note that this constructor is only due to Java's insufficient type inference.
*/
public static Function identity(A example) {
return identity();
}
/**
* Identity function.
*
* @param clazz
* to describe the functions's type
*/
public static Function identity(Class clazz) {
return identity();
}
/** Create an effect that runs its argument. */
public static final Effect run = new Effect() {
@Override
protected void run(Effect0 e) {
e.apply();
}
};
/** Pure functions are covariant in their result type. */
public static Function co(Function super A, ? extends B> f) {
return (Function) f;
}
/** Pure functions are contravariant in their argument type. */
public static Function contra(Function super A, B> f) {
return (Function) f;
}
/** Pure functions are covariant in their result type and contravariant in their argument type. */
public static Function variant(Function super A, ? extends B> f) {
return (Function) f;
}
private static A castGeneric(Throwable t) throws T {
// The cast to T does not happen here but _after_ returning from the method at _assignment_ time
// But since there is no variable assignment. The Throwable is just thrown.
throw (T) t;
}
/**
* Throw a checked exception like a RuntimeException removing any needs to declare a throws clause.
*
* This technique has been described by James Iry at
* http://james-iry.blogspot.de/2010/08/on-removing-java-checked-exceptions-by.html
*/
public static A chuck(Throwable t) {
return Functions. castGeneric(t);
}
/** Convert function f
into a guava function. */
public static com.google.common.base.Function toGuava(final Function super A, ? extends B> f) {
return new com.google.common.base.Function() {
@Override
public B apply(A a) {
return f.apply(a);
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy