You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2020/06/24 22:25:54 UTC

[commons-lang] branch master updated: [LANG-1568] org.apache.commons.lang3.function.FailableBiFunction.andThen(FailableFunction)

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 <ga...@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;