This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push: new c7aea90 [LANG-1568] org.apache.commons.lang3.function.FailableBiFunction.andThen(FailableFunction<? super R, ? extends V, E>) c7aea90 is described below commit c7aea90a7a6e27d7159034cfbea64f796c6846af Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Wed Jun 24 18:25:47 2020 -0400 [LANG-1568] org.apache.commons.lang3.function.FailableBiFunction.andThen(FailableFunction<? super R, ? extends V, E>) --- .../commons/lang3/function/FailableBiConsumer.java | 6 +-- .../commons/lang3/function/FailableBiFunction.java | 33 +++++++++++++++ .../commons/lang3/function/FailableFunction.java | 16 +++++++ .../lang3/function/FailableFunctionsTest.java | 49 ++++++++++++++++------ 4 files changed, 88 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/apache/commons/lang3/function/FailableBiConsumer.java b/src/main/java/org/apache/commons/lang3/function/FailableBiConsumer.java index 5f56b06..6d5d99f 100644 --- a/src/main/java/org/apache/commons/lang3/function/FailableBiConsumer.java +++ b/src/main/java/org/apache/commons/lang3/function/FailableBiConsumer.java @@ -37,7 +37,7 @@ public interface FailableBiConsumer<T, U, E extends Throwable> { /** * Returns The NOP singleton. - * + * * @param <T> Consumed type 1. * @param <U> Consumed type 2. * @param <E> Thrown exception. @@ -62,9 +62,9 @@ public interface FailableBiConsumer<T, U, E extends Throwable> { * @param after the operation to perform after this one. * @return a composed {@code FailableBiConsumer} like {@link BiConsumer#andThen(BiConsumer)}. * @throws E Thrown when a consumer fails. - * @throws NullPointerException if {@code after} is null + * @throws NullPointerException if {@code after} is null. */ - default FailableBiConsumer<T, U, E> andThen(FailableBiConsumer<? super T, ? super U, E> after) throws E { + default FailableBiConsumer<T, U, E> andThen(final FailableBiConsumer<? super T, ? super U, E> after) throws E { Objects.requireNonNull(after); return (t, u) -> { diff --git a/src/main/java/org/apache/commons/lang3/function/FailableBiFunction.java b/src/main/java/org/apache/commons/lang3/function/FailableBiFunction.java index d112be8..be0e470 100644 --- a/src/main/java/org/apache/commons/lang3/function/FailableBiFunction.java +++ b/src/main/java/org/apache/commons/lang3/function/FailableBiFunction.java @@ -17,7 +17,9 @@ package org.apache.commons.lang3.function; +import java.util.Objects; import java.util.function.BiFunction; +import java.util.function.Function; /** * A functional interface like {@link BiFunction} that declares a {@code Throwable}. @@ -31,6 +33,37 @@ import java.util.function.BiFunction; @FunctionalInterface public interface FailableBiFunction<T, U, R, E extends Throwable> { + /** NOP singleton */ + @SuppressWarnings("rawtypes") + final FailableBiFunction NOP = (t, u) -> null; + + /** + * Returns The NOP singleton. + * + * @param <T> Consumed type 1. + * @param <U> Consumed type 2. + * @param <R> Return type. + * @param <E> Thrown exception. + * @return The NOP singleton. + */ + static <T, U, R, E extends Throwable> FailableBiFunction<T, U, R, E> nop() { + return NOP; + } + + /** + * Returns a composed {@code FailableBiFunction} that like {@link BiFunction#andThen(Function)}. + * + * @param <V> the type of output of the {@code after} function, and of the composed function + * @param after the operation to perform after this one. + * @return a composed {@code FailableBiFunction} that like {@link BiFunction#andThen(Function)}. + * @throws E Thrown when a consumer fails. + * @throws NullPointerException if after is null. + */ + default <V> FailableBiFunction<T, U, V, E> andThen(final FailableFunction<? super R, ? extends V, E> after) throws E { + Objects.requireNonNull(after); + return (final T t, final U u) -> after.apply(apply(t, u)); + } + /** * Applies this function. * diff --git a/src/main/java/org/apache/commons/lang3/function/FailableFunction.java b/src/main/java/org/apache/commons/lang3/function/FailableFunction.java index 7de4437..3d4b905 100644 --- a/src/main/java/org/apache/commons/lang3/function/FailableFunction.java +++ b/src/main/java/org/apache/commons/lang3/function/FailableFunction.java @@ -30,6 +30,22 @@ import java.util.function.Function; @FunctionalInterface public interface FailableFunction<T, R, E extends Throwable> { + /** NOP singleton */ + @SuppressWarnings("rawtypes") + final FailableFunction NOP = t -> null; + + /** + * Returns The NOP singleton. + * + * @param <T> Consumed type 1. + * @param <R> Return type. + * @param <E> Thrown exception. + * @return The NOP singleton. + */ + static <T, R, E extends Throwable> FailableFunction<T, R, E> nop() { + return NOP; + } + /** * Applies this function. * diff --git a/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java b/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java index 0560725..81da56e 100644 --- a/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java +++ b/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java @@ -45,9 +45,6 @@ import org.junit.jupiter.api.Test; */ public class FailableFunctionsTest { - private static final IllegalStateException ILLEGAL_STATE_EXCEPTION = new IllegalStateException(); - private static final OutOfMemoryError ERROR = new OutOfMemoryError(); - public static class CloseableObject { private boolean closed; @@ -69,7 +66,6 @@ public class FailableFunctionsTest { } } } - public static class FailureOnOddInvocations { private static int invocations; @@ -268,10 +264,15 @@ public class FailableFunctionsTest { } } + private static final OutOfMemoryError ERROR = new OutOfMemoryError(); + + private static final IllegalStateException ILLEGAL_STATE_EXCEPTION = new IllegalStateException(); + @Test void testAcceptBiConsumer() { final Testable<?, ?> testable = new Testable<>(null); - Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(Testable::test, testable, ILLEGAL_STATE_EXCEPTION)); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.accept(Testable::test, testable, ILLEGAL_STATE_EXCEPTION)); assertSame(ILLEGAL_STATE_EXCEPTION, e); e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(Testable::test, testable, ERROR)); @@ -632,28 +633,27 @@ public class FailableFunctionsTest { t.setThrowable(th); t.test(); }; - Throwable e; final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> nop = FailableBiConsumer.nop(); - e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failableBiConsumer).accept(testable, ERROR)); + final Throwable e = assertThrows(OutOfMemoryError.class, + () -> nop.andThen(failableBiConsumer).accept(testable, ERROR)); assertSame(ERROR, e); // Does not throw nop.andThen(nop); // Documented in Javadoc edge-case. assertThrows(NullPointerException.class, () -> failableBiConsumer.andThen(null)); - } @Test public void testBiFunction() { - final IllegalStateException ise = ILLEGAL_STATE_EXCEPTION; - final Testable<?, ?> testable = new Testable<>(ise); + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); final FailableBiFunction<Testable<?, ?>, Throwable, Integer, Throwable> failableBiFunction = (t, th) -> { t.setThrowable(th); - return Integer.valueOf(t.testAsInteger()); + return t.testAsInteger(); }; final BiFunction<Testable<?, ?>, Throwable, Integer> biFunction = Failable.asBiFunction(failableBiFunction); - Throwable e = assertThrows(IllegalStateException.class, () -> biFunction.apply(testable, ise)); - assertSame(ise, e); + Throwable e = assertThrows(IllegalStateException.class, + () -> biFunction.apply(testable, ILLEGAL_STATE_EXCEPTION)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); testable.setThrowable(ERROR); e = assertThrows(OutOfMemoryError.class, () -> biFunction.apply(testable, ERROR)); @@ -670,6 +670,29 @@ public class FailableFunctionsTest { } @Test + public void testBiFunctionAndThen() throws IOException { + // Unchecked usage pattern in JRE + final BiFunction<Object, Integer, Integer> nopBiFunction = (t, u) -> null; + final Function<Object, Integer> nopFunction = (t) -> null; + nopBiFunction.andThen(nopFunction); + // Checked usage pattern + final FailableBiFunction<Object, Integer, Integer, IOException> failingBiFunctionTest = (t, u) -> { + throw new IOException(); + }; + final FailableFunction<Object, Integer, IOException> failingFunction = (t) -> { throw new IOException(); }; + final FailableBiFunction<Object, Integer, Integer, IOException> nopFailableBiFunction = FailableBiFunction.nop(); + final FailableFunction<Object, Integer, IOException> nopFailableFunction = FailableFunction.nop(); + // + assertThrows(IOException.class, () -> failingBiFunctionTest.andThen(failingFunction).apply(null, null)); + assertThrows(IOException.class, () -> failingBiFunctionTest.andThen(nopFailableFunction).apply(null, null)); + // + assertThrows(IOException.class, () -> nopFailableBiFunction.andThen(failingFunction).apply(null, null)); + nopFailableBiFunction.andThen(nopFailableFunction).apply(null, null); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failingBiFunctionTest.andThen(null)); + } + + @Test @DisplayName("Test that asPredicate(FailableBiPredicate) is converted to -> BiPredicate ") public void testBiPredicate() { FailureOnOddInvocations.invocations = 0;