org.mycore.common.function.MCRThrowFunction Maven / Gradle / Ivy
/*
* This file is part of *** M y C o R e ***
* See http://www.mycore.de/ for details.
*
* MyCoRe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MyCoRe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MyCoRe. If not, see .
*/
package org.mycore.common.function;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* Represents a function that accepts one argument and produces a result and throws an Exception.
*
* Use {@link #toFunction()} or {@link #toFunction(BiFunction, Class)} to transform this
* MCRThrowFunction into a Function that can be handled throughout Java 8.
*
* @param the type of the input to the function
* @param the type of the result of the function
* @param the exception that is throw by this function-
*
* @since 2015.12
*/
@FunctionalInterface
public interface MCRThrowFunction {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t) throws E;
/**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(MCRThrowFunction)
*/
default MCRThrowFunction compose(MCRThrowFunction before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* Returns a composed function that first applies this function to
* its 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 the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*
* @see #compose(MCRThrowFunction)
*/
default MCRThrowFunction andThen(MCRThrowFunction after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* Returns a function that catches <E> and forwards it to the throwableHandler
together with the Exception.
*
* Use this method if you want to react on the certain Exceptions and return a result
* or rethrow a specific RuntimeExption.
* @param throwableHandler a BiFunction that handles original Input and caught Exception
* @param exClass class of exception to catch
*/
default Function toFunction(BiFunction throwableHandler, Class exClass) {
return t -> {
try {
return this.apply(t);
} catch (Throwable e) {
if (exClass.isAssignableFrom(e.getClass())) {
@SuppressWarnings("unchecked")
E handableException = (E) e;
return throwableHandler.apply(t, handableException);
}
throw (RuntimeException) e;
}
};
}
/**
* Returns a Function that applies <T> and catches any exception and wraps it into a {@link RuntimeException} if needed.
* Use this if you just want no specific exception handling.
*/
default Function toFunction() {
return toFunction((t, e) -> {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e);
}, Throwable.class);
}
}