Failable.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.apache.commons.lang3.function;

  18. import java.io.IOException;
  19. import java.io.UncheckedIOException;
  20. import java.lang.reflect.UndeclaredThrowableException;
  21. import java.util.Collection;
  22. import java.util.Objects;
  23. import java.util.concurrent.Callable;
  24. import java.util.function.BiConsumer;
  25. import java.util.function.BiFunction;
  26. import java.util.function.BiPredicate;
  27. import java.util.function.Consumer;
  28. import java.util.function.Function;
  29. import java.util.function.Predicate;
  30. import java.util.function.Supplier;
  31. import java.util.stream.Stream;

  32. import org.apache.commons.lang3.exception.ExceptionUtils;
  33. import org.apache.commons.lang3.stream.Streams;
  34. import org.apache.commons.lang3.stream.Streams.FailableStream;

  35. /**
  36.  * This class provides utility functions, and classes for working with the {@code java.util.function} package, or more
  37.  * generally, with Java 8 lambdas. More specifically, it attempts to address the fact that lambdas are supposed not to
  38.  * throw Exceptions, at least not checked Exceptions, AKA instances of {@link Exception}. This enforces the use of
  39.  * constructs like:
  40.  *
  41.  * <pre>{@code
  42.  * Consumer<java.lang.reflect.Method> consumer = m -&gt; {
  43.  *     try {
  44.  *         m.invoke(o, args);
  45.  *     } catch (Throwable t) {
  46.  *         throw Failable.rethrow(t);
  47.  *     }
  48.  * };
  49.  * }
  50.  * </pre>
  51.  *
  52.  * <p>
  53.  * By replacing a {@link java.util.function.Consumer Consumer&lt;O&gt;} with a {@link FailableConsumer
  54.  * FailableConsumer&lt;O,? extends Throwable&gt;}, this can be written like follows:
  55.  * </p>
  56.  *
  57.  * <pre>
  58.  * Functions.accept((m) -&gt; m.invoke(o, args));
  59.  * </pre>
  60.  *
  61.  * <p>
  62.  * Obviously, the second version is much more concise and the spirit of Lambda expressions is met better than the second
  63.  * version.
  64.  * </p>
  65.  *
  66.  * @since 3.11
  67.  */
  68. public class Failable {

  69.     /**
  70.      * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
  71.      *
  72.      * @param consumer the consumer to consume
  73.      * @param object1 the first object to consume by {@code consumer}
  74.      * @param object2 the second object to consume by {@code consumer}
  75.      * @param <T> the type of the first argument the consumer accepts
  76.      * @param <U> the type of the second argument the consumer accepts
  77.      * @param <E> the type of checked exception the consumer may throw
  78.      */
  79.     public static <T, U, E extends Throwable> void accept(final FailableBiConsumer<T, U, E> consumer, final T object1,
  80.         final U object2) {
  81.         run(() -> consumer.accept(object1, object2));
  82.     }

  83.     /**
  84.      * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
  85.      *
  86.      * @param consumer the consumer to consume
  87.      * @param object the object to consume by {@code consumer}
  88.      * @param <T> the type the consumer accepts
  89.      * @param <E> the type of checked exception the consumer may throw
  90.      */
  91.     public static <T, E extends Throwable> void accept(final FailableConsumer<T, E> consumer, final T object) {
  92.         run(() -> consumer.accept(object));
  93.     }

  94.     /**
  95.      * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
  96.      *
  97.      * @param consumer the consumer to consume
  98.      * @param value the value to consume by {@code consumer}
  99.      * @param <E> the type of checked exception the consumer may throw
  100.      */
  101.     public static <E extends Throwable> void accept(final FailableDoubleConsumer<E> consumer, final double value) {
  102.         run(() -> consumer.accept(value));
  103.     }

  104.     /**
  105.      * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
  106.      *
  107.      * @param consumer the consumer to consume
  108.      * @param value the value to consume by {@code consumer}
  109.      * @param <E> the type of checked exception the consumer may throw
  110.      */
  111.     public static <E extends Throwable> void accept(final FailableIntConsumer<E> consumer, final int value) {
  112.         run(() -> consumer.accept(value));
  113.     }

  114.     /**
  115.      * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
  116.      *
  117.      * @param consumer the consumer to consume
  118.      * @param value the value to consume by {@code consumer}
  119.      * @param <E> the type of checked exception the consumer may throw
  120.      */
  121.     public static <E extends Throwable> void accept(final FailableLongConsumer<E> consumer, final long value) {
  122.         run(() -> consumer.accept(value));
  123.     }

  124.     /**
  125.      * Applies a function and rethrows any exception as a {@link RuntimeException}.
  126.      *
  127.      * @param function the function to apply
  128.      * @param input1 the first input to apply {@code function} on
  129.      * @param input2 the second input to apply {@code function} on
  130.      * @param <T> the type of the first argument the function accepts
  131.      * @param <U> the type of the second argument the function accepts
  132.      * @param <R> the return type of the function
  133.      * @param <E> the type of checked exception the function may throw
  134.      * @return the value returned from the function
  135.      */
  136.     public static <T, U, R, E extends Throwable> R apply(final FailableBiFunction<T, U, R, E> function, final T input1,
  137.         final U input2) {
  138.         return get(() -> function.apply(input1, input2));
  139.     }

  140.     /**
  141.      * Applies a function and rethrows any exception as a {@link RuntimeException}.
  142.      *
  143.      * @param function the function to apply
  144.      * @param input the input to apply {@code function} on
  145.      * @param <T> the type of the argument the function accepts
  146.      * @param <R> the return type of the function
  147.      * @param <E> the type of checked exception the function may throw
  148.      * @return the value returned from the function
  149.      */
  150.     public static <T, R, E extends Throwable> R apply(final FailableFunction<T, R, E> function, final T input) {
  151.         return get(() -> function.apply(input));
  152.     }

  153.     /**
  154.      * Applies a function and rethrows any exception as a {@link RuntimeException}.
  155.      *
  156.      * @param function the function to apply
  157.      * @param left the first input to apply {@code function} on
  158.      * @param right the second input to apply {@code function} on
  159.      * @param <E> the type of checked exception the function may throw
  160.      * @return the value returned from the function
  161.      */
  162.     public static <E extends Throwable> double applyAsDouble(final FailableDoubleBinaryOperator<E> function,
  163.         final double left, final double right) {
  164.         return getAsDouble(() -> function.applyAsDouble(left, right));
  165.     }

  166.     /**
  167.      * Converts the given {@link FailableBiConsumer} into a standard {@link BiConsumer}.
  168.      *
  169.      * @param <T> the type of the first argument of the consumers
  170.      * @param <U> the type of the second argument of the consumers
  171.      * @param consumer a failable {@link BiConsumer}
  172.      * @return a standard {@link BiConsumer}
  173.      */
  174.     public static <T, U> BiConsumer<T, U> asBiConsumer(final FailableBiConsumer<T, U, ?> consumer) {
  175.         return (input1, input2) -> accept(consumer, input1, input2);
  176.     }

  177.     /**
  178.      * Converts the given {@link FailableBiFunction} into a standard {@link BiFunction}.
  179.      *
  180.      * @param <T> the type of the first argument of the input of the functions
  181.      * @param <U> the type of the second argument of the input of the functions
  182.      * @param <R> the type of the output of the functions
  183.      * @param function a {@link FailableBiFunction}
  184.      * @return a standard {@link BiFunction}
  185.      */
  186.     public static <T, U, R> BiFunction<T, U, R> asBiFunction(final FailableBiFunction<T, U, R, ?> function) {
  187.         return (input1, input2) -> apply(function, input1, input2);
  188.     }

  189.     /**
  190.      * Converts the given {@link FailableBiPredicate} into a standard {@link BiPredicate}.
  191.      *
  192.      * @param <T> the type of the first argument used by the predicates
  193.      * @param <U> the type of the second argument used by the predicates
  194.      * @param predicate a {@link FailableBiPredicate}
  195.      * @return a standard {@link BiPredicate}
  196.      */
  197.     public static <T, U> BiPredicate<T, U> asBiPredicate(final FailableBiPredicate<T, U, ?> predicate) {
  198.         return (input1, input2) -> test(predicate, input1, input2);
  199.     }

  200.     /**
  201.      * Converts the given {@link FailableCallable} into a standard {@link Callable}.
  202.      *
  203.      * @param <V> the type used by the callables
  204.      * @param callable a {@link FailableCallable}
  205.      * @return a standard {@link Callable}
  206.      */
  207.     public static <V> Callable<V> asCallable(final FailableCallable<V, ?> callable) {
  208.         return () -> call(callable);
  209.     }

  210.     /**
  211.      * Converts the given {@link FailableConsumer} into a standard {@link Consumer}.
  212.      *
  213.      * @param <T> the type used by the consumers
  214.      * @param consumer a {@link FailableConsumer}
  215.      * @return a standard {@link Consumer}
  216.      */
  217.     public static <T> Consumer<T> asConsumer(final FailableConsumer<T, ?> consumer) {
  218.         return input -> accept(consumer, input);
  219.     }

  220.     /**
  221.      * Converts the given {@link FailableFunction} into a standard {@link Function}.
  222.      *
  223.      * @param <T> the type of the input of the functions
  224.      * @param <R> the type of the output of the functions
  225.      * @param function a {code FailableFunction}
  226.      * @return a standard {@link Function}
  227.      */
  228.     public static <T, R> Function<T, R> asFunction(final FailableFunction<T, R, ?> function) {
  229.         return input -> apply(function, input);
  230.     }

  231.     /**
  232.      * Converts the given {@link FailablePredicate} into a standard {@link Predicate}.
  233.      *
  234.      * @param <T> the type used by the predicates
  235.      * @param predicate a {@link FailablePredicate}
  236.      * @return a standard {@link Predicate}
  237.      */
  238.     public static <T> Predicate<T> asPredicate(final FailablePredicate<T, ?> predicate) {
  239.         return input -> test(predicate, input);
  240.     }

  241.     /**
  242.      * Converts the given {@link FailableRunnable} into a standard {@link Runnable}.
  243.      *
  244.      * @param runnable a {@link FailableRunnable}
  245.      * @return a standard {@link Runnable}
  246.      */
  247.     public static Runnable asRunnable(final FailableRunnable<?> runnable) {
  248.         return () -> run(runnable);
  249.     }

  250.     /**
  251.      * Converts the given {@link FailableSupplier} into a standard {@link Supplier}.
  252.      *
  253.      * @param <T> the type supplied by the suppliers
  254.      * @param supplier a {@link FailableSupplier}
  255.      * @return a standard {@link Supplier}
  256.      */
  257.     public static <T> Supplier<T> asSupplier(final FailableSupplier<T, ?> supplier) {
  258.         return () -> get(supplier);
  259.     }

  260.     /**
  261.      * Calls a callable and rethrows any exception as a {@link RuntimeException}.
  262.      *
  263.      * @param callable the callable to call
  264.      * @param <V> the return type of the callable
  265.      * @param <E> the type of checked exception the callable may throw
  266.      * @return the value returned from the callable
  267.      */
  268.     public static <V, E extends Throwable> V call(final FailableCallable<V, E> callable) {
  269.         return get(callable::call);
  270.     }

  271.     /**
  272.      * Invokes a supplier, and returns the result.
  273.      *
  274.      * @param supplier The supplier to invoke.
  275.      * @param <T> The suppliers output type.
  276.      * @param <E> The type of checked exception, which the supplier can throw.
  277.      * @return The object, which has been created by the supplier
  278.      */
  279.     public static <T, E extends Throwable> T get(final FailableSupplier<T, E> supplier) {
  280.         try {
  281.             return supplier.get();
  282.         } catch (final Throwable t) {
  283.             throw rethrow(t);
  284.         }
  285.     }

  286.     /**
  287.      * Invokes a boolean supplier, and returns the result.
  288.      *
  289.      * @param supplier The boolean supplier to invoke.
  290.      * @param <E> The type of checked exception, which the supplier can throw.
  291.      * @return The boolean, which has been created by the supplier
  292.      */
  293.     public static <E extends Throwable> boolean getAsBoolean(final FailableBooleanSupplier<E> supplier) {
  294.         try {
  295.             return supplier.getAsBoolean();
  296.         } catch (final Throwable t) {
  297.             throw rethrow(t);
  298.         }
  299.     }

  300.     /**
  301.      * Invokes a double supplier, and returns the result.
  302.      *
  303.      * @param supplier The double supplier to invoke.
  304.      * @param <E> The type of checked exception, which the supplier can throw.
  305.      * @return The double, which has been created by the supplier
  306.      */
  307.     public static <E extends Throwable> double getAsDouble(final FailableDoubleSupplier<E> supplier) {
  308.         try {
  309.             return supplier.getAsDouble();
  310.         } catch (final Throwable t) {
  311.             throw rethrow(t);
  312.         }
  313.     }

  314.     /**
  315.      * Invokes an int supplier, and returns the result.
  316.      *
  317.      * @param supplier The int supplier to invoke.
  318.      * @param <E> The type of checked exception, which the supplier can throw.
  319.      * @return The int, which has been created by the supplier
  320.      */
  321.     public static <E extends Throwable> int getAsInt(final FailableIntSupplier<E> supplier) {
  322.         try {
  323.             return supplier.getAsInt();
  324.         } catch (final Throwable t) {
  325.             throw rethrow(t);
  326.         }
  327.     }

  328.     /**
  329.      * Invokes a long supplier, and returns the result.
  330.      *
  331.      * @param supplier The long supplier to invoke.
  332.      * @param <E> The type of checked exception, which the supplier can throw.
  333.      * @return The long, which has been created by the supplier
  334.      */
  335.     public static <E extends Throwable> long getAsLong(final FailableLongSupplier<E> supplier) {
  336.         try {
  337.             return supplier.getAsLong();
  338.         } catch (final Throwable t) {
  339.             throw rethrow(t);
  340.         }
  341.     }

  342.     /**
  343.      * Invokes a short supplier, and returns the result.
  344.      *
  345.      * @param supplier The short supplier to invoke.
  346.      * @param <E> The type of checked exception, which the supplier can throw.
  347.      * @return The short, which has been created by the supplier
  348.      */
  349.     public static <E extends Throwable> short getAsShort(final FailableShortSupplier<E> supplier) {
  350.         try {
  351.             return supplier.getAsShort();
  352.         } catch (final Throwable t) {
  353.             throw rethrow(t);
  354.         }
  355.     }

  356.     /**
  357.      * Rethrows a {@link Throwable} as an unchecked exception. If the argument is already unchecked, namely a
  358.      * {@link RuntimeException} or {@link Error} then the argument will be rethrown without modification. If the
  359.      * exception is {@link IOException} then it will be wrapped into a {@link UncheckedIOException}. In every other
  360.      * cases the exception will be wrapped into a {@code
  361.      * UndeclaredThrowableException}
  362.      *
  363.      * <p>
  364.      * Note that there is a declared return type for this method, even though it never returns. The reason for that is
  365.      * to support the usual pattern:
  366.      * </p>
  367.      *
  368.      * <pre>
  369.      * throw rethrow(myUncheckedException);
  370.      * </pre>
  371.      *
  372.      * <p>
  373.      * instead of just calling the method. This pattern may help the Java compiler to recognize that at that point an
  374.      * exception will be thrown and the code flow analysis will not demand otherwise mandatory commands that could
  375.      * follow the method call, like a {@code return} statement from a value returning method.
  376.      * </p>
  377.      *
  378.      * @param throwable The throwable to rethrow possibly wrapped into an unchecked exception
  379.      * @return Never returns anything, this method never terminates normally.
  380.      */
  381.     public static RuntimeException rethrow(final Throwable throwable) {
  382.         Objects.requireNonNull(throwable, "throwable");
  383.         ExceptionUtils.throwUnchecked(throwable);
  384.         if (throwable instanceof IOException) {
  385.             throw new UncheckedIOException((IOException) throwable);
  386.         }
  387.         throw new UndeclaredThrowableException(throwable);
  388.     }

  389.     /**
  390.      * Runs a runnable and rethrows any exception as a {@link RuntimeException}.
  391.      *
  392.      * @param runnable The runnable to run
  393.      * @param <E> the type of checked exception the runnable may throw
  394.      */
  395.     public static <E extends Throwable> void run(final FailableRunnable<E> runnable) {
  396.         try {
  397.             runnable.run();
  398.         } catch (final Throwable t) {
  399.             throw rethrow(t);
  400.         }
  401.     }

  402.     /**
  403.      * Converts the given collection into a {@link FailableStream}. The {@link FailableStream} consists of the
  404.      * collections elements. Shortcut for
  405.      *
  406.      * <pre>
  407.      * Functions.stream(collection.stream());
  408.      * </pre>
  409.      *
  410.      * @param collection The collection, which is being converted into a {@link FailableStream}.
  411.      * @param <E> The collections element type. (In turn, the result streams element type.)
  412.      * @return The created {@link FailableStream}.
  413.      */
  414.     public static <E> FailableStream<E> stream(final Collection<E> collection) {
  415.         return new FailableStream<>(collection.stream());
  416.     }

  417.     /**
  418.      * Converts the given stream into a {@link FailableStream}. The {@link FailableStream} consists of the same
  419.      * elements, than the input stream. However, failable lambdas, like {@link FailablePredicate},
  420.      * {@link FailableFunction}, and {@link FailableConsumer} may be applied, rather than {@link Predicate},
  421.      * {@link Function}, {@link Consumer}, etc.
  422.      *
  423.      * @param stream The stream, which is being converted into a {@link FailableStream}.
  424.      * @param <T> The streams element type.
  425.      * @return The created {@link FailableStream}.
  426.      */
  427.     public static <T> FailableStream<T> stream(final Stream<T> stream) {
  428.         return new FailableStream<>(stream);
  429.     }

  430.     /**
  431.      * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
  432.      *
  433.      * @param predicate the predicate to test
  434.      * @param object1 the first input to test by {@code predicate}
  435.      * @param object2 the second input to test by {@code predicate}
  436.      * @param <T> the type of the first argument the predicate tests
  437.      * @param <U> the type of the second argument the predicate tests
  438.      * @param <E> the type of checked exception the predicate may throw
  439.      * @return the boolean value returned by the predicate
  440.      */
  441.     public static <T, U, E extends Throwable> boolean test(final FailableBiPredicate<T, U, E> predicate,
  442.         final T object1, final U object2) {
  443.         return getAsBoolean(() -> predicate.test(object1, object2));
  444.     }

  445.     /**
  446.      * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
  447.      *
  448.      * @param predicate the predicate to test
  449.      * @param object the input to test by {@code predicate}
  450.      * @param <T> the type of argument the predicate tests
  451.      * @param <E> the type of checked exception the predicate may throw
  452.      * @return the boolean value returned by the predicate
  453.      */
  454.     public static <T, E extends Throwable> boolean test(final FailablePredicate<T, E> predicate, final T object) {
  455.         return getAsBoolean(() -> predicate.test(object));
  456.     }

  457.     /**
  458.      * A simple try-with-resources implementation, that can be used, if your objects do not implement the
  459.      * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em>
  460.      * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure.
  461.      * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA
  462.      * {@link Throwable}) is rethrown. Example use:
  463.      *
  464.      * <pre>{@code
  465.      * final FileInputStream fis = new FileInputStream("my.file");
  466.      * Functions.tryWithResources(useInputStream(fis), null, () -> fis.close());
  467.      * }</pre>
  468.      *
  469.      * @param action The action to execute. This object <em>will</em> always be invoked.
  470.      * @param errorHandler An optional error handler, which will be invoked finally, if any error occurred. The error
  471.      *        handler will receive the first error, AKA {@link Throwable}.
  472.      * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given
  473.      *        order. A resource action is an instance of {@link FailableRunnable}, which will be executed.
  474.      * @see #tryWithResources(FailableRunnable, FailableRunnable...)
  475.      */
  476.     @SafeVarargs
  477.     public static void tryWithResources(final FailableRunnable<? extends Throwable> action,
  478.         final FailableConsumer<Throwable, ? extends Throwable> errorHandler,
  479.         final FailableRunnable<? extends Throwable>... resources) {
  480.         final FailableConsumer<Throwable, ? extends Throwable> actualErrorHandler;
  481.         if (errorHandler == null) {
  482.             actualErrorHandler = Failable::rethrow;
  483.         } else {
  484.             actualErrorHandler = errorHandler;
  485.         }
  486.         Streams.of(resources).forEach(r -> Objects.requireNonNull(r, "runnable"));
  487.         Throwable th = null;
  488.         try {
  489.             action.run();
  490.         } catch (final Throwable t) {
  491.             th = t;
  492.         }
  493.         if (resources != null) {
  494.             for (final FailableRunnable<?> runnable : resources) {
  495.                 try {
  496.                     runnable.run();
  497.                 } catch (final Throwable t) {
  498.                     if (th == null) {
  499.                         th = t;
  500.                     }
  501.                 }
  502.             }
  503.         }
  504.         if (th != null) {
  505.             try {
  506.                 actualErrorHandler.accept(th);
  507.             } catch (final Throwable t) {
  508.                 throw rethrow(t);
  509.             }
  510.         }
  511.     }

  512.     /**
  513.      * A simple try-with-resources implementation, that can be used, if your objects do not implement the
  514.      * {@link AutoCloseable} interface. The method executes the {@code action}. The method guarantees, that <em>all</em>
  515.      * the {@code resources} are being executed, in the given order, afterwards, and regardless of success, or failure.
  516.      * If either the original action, or any of the resource action fails, then the <em>first</em> failure (AKA
  517.      * {@link Throwable}) is rethrown. Example use:
  518.      *
  519.      * <pre>{@code
  520.      * final FileInputStream fis = new FileInputStream("my.file");
  521.      * Functions.tryWithResources(useInputStream(fis), () -> fis.close());
  522.      * }</pre>
  523.      *
  524.      * @param action The action to execute. This object <em>will</em> always be invoked.
  525.      * @param resources The resource actions to execute. <em>All</em> resource actions will be invoked, in the given
  526.      *        order. A resource action is an instance of {@link FailableRunnable}, which will be executed.
  527.      * @see #tryWithResources(FailableRunnable, FailableConsumer, FailableRunnable...)
  528.      */
  529.     @SafeVarargs
  530.     public static void tryWithResources(final FailableRunnable<? extends Throwable> action, final FailableRunnable<? extends Throwable>... resources) {
  531.         tryWithResources(action, null, resources);
  532.     }

  533.     private Failable() {
  534.         // empty
  535.     }

  536. }