FunctionalCheckedExceptionWrappers.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
  8.  *
  9.  * *********************************************************************************************************************
  10.  *
  11.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  12.  * the License. You may obtain a copy of the License at
  13.  *
  14.  *     http://www.apache.org/licenses/LICENSE-2.0
  15.  *
  16.  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  17.  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
  18.  * specific language governing permissions and limitations under the License.
  19.  *
  20.  * *********************************************************************************************************************
  21.  *
  22.  * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
  23.  * git clone https://github.com/tidalwave-it/thesefoolishthings-src
  24.  *
  25.  * *********************************************************************************************************************
  26.  */
  27. package it.tidalwave.util;

  28. import javax.annotation.Nonnull;
  29. import java.util.function.Consumer;
  30. import java.util.function.Function;
  31. import java.util.function.Predicate;
  32. import java.util.function.Supplier;
  33. import java.io.IOException;
  34. import java.io.UncheckedIOException;
  35. import lombok.NoArgsConstructor;
  36. import static lombok.AccessLevel.PRIVATE;

  37. /***********************************************************************************************************************
  38.  *
  39.  * A collections of utility methods for simplifying the syntax of lambda expressions with APIs that don't accept
  40.  * checked exceptions (such as {@link java.util.stream.Stream}): they provide wrapped functions that have no checked
  41.  * exception in the signature and whose implementation delegates to the original function wrapping an eventual checked
  42.  * exception into a {@link RuntimeException}. For instance, given the following method that could not be used as a
  43.  * {@link java.util.stream.Stream#filter(Predicate)} argument:
  44.  *
  45.  * <pre>
  46.  *   private boolean matchEven (final int number)
  47.  *           throws Exception
  48.  *     {
  49.  *       if (number == 13)
  50.  *         {
  51.  *           throw new Exception("13!");
  52.  *         }
  53.  *
  54.  *       return number % 2 == 0;
  55.  *     }
  56.  * </pre>
  57.  *
  58.  * working code can be written as:
  59.  *
  60.  * <pre>
  61.  *   try
  62.  *     {
  63.  *       List&lt;Integer&gt; numbers = IntStream.rangeClosed(1, 20)
  64.  *                                        .mapToObj(Integer::valueOf)
  65.  *                                        .filter(_p(this::matchEven)) // note the wrapper here
  66.  *                                        .collect(Collectors.toList());
  67.  *       ...
  68.  *     }
  69.  *   catch (RuntimeException e)
  70.  *     {
  71.  *       ...
  72.  *     }
  73.  * </pre>
  74.  *
  75.  * Any checked exception is wrapped by a {@code RuntimeException}, but {@link IOException} is wrapped by a
  76.  * {@link UncheckedIOException}.
  77.  *
  78.  * @author Fabrizio Giudici
  79.  * @it.tidalwave.javadoc.draft
  80.  * @since 3.2-ALPHA-1
  81.  *
  82.  **********************************************************************************************************************/
  83. @NoArgsConstructor(access = PRIVATE)
  84. public final class FunctionalCheckedExceptionWrappers
  85.   {
  86.     /*******************************************************************************************************************
  87.      *
  88.      * A variant of {@link Function} that might throw an {@link Exception}. This interface must not be directly used,
  89.      * it's defined to let the compiler infer functional equivalence.
  90.      *
  91.      * @param <T>         the type of the function argument
  92.      * @param <R>         the type of the function return value
  93.      * @hidden
  94.      *
  95.      ******************************************************************************************************************/
  96.     @FunctionalInterface
  97.     public static interface FunctionWithException<T, R>
  98.       {
  99.         public R apply (T t)
  100.                 throws Exception;
  101.       }

  102.     /*******************************************************************************************************************
  103.      *
  104.      * A variant of {@link Consumer} that might throw an {@link Exception}. This interface must not be directly used,
  105.      * it's defined to let the compiler infer functional equivalence.
  106.      *
  107.      * @param <T>         the type of the {@code Consumer} argument
  108.      * @hidden
  109.      *
  110.      ******************************************************************************************************************/
  111.     @FunctionalInterface
  112.     public static interface ConsumerWithException<T>
  113.       {
  114.         public void accept (T t)
  115.                 throws Exception;
  116.       }

  117.     /*******************************************************************************************************************
  118.      *
  119.      * A variant of {@link Supplier} that might throw an {@link Exception}. This interface must not be directly used,
  120.      * it's defined to let the compiler infer functional equivalence.
  121.      *
  122.      * @param <T>         the type of the {@code Supplier} argument
  123.      * @hidden
  124.      *
  125.      ******************************************************************************************************************/
  126.     @FunctionalInterface
  127.     public static interface SupplierWithException<T>
  128.       {
  129.         public T get ()
  130.                 throws Exception;
  131.       }

  132.     /*******************************************************************************************************************
  133.      *
  134.      * A variant of {@link Predicate} that might throw an {@link Exception}. This interface must not be directly used,
  135.      * it's defined to let the compiler infer functional equivalence.
  136.      *
  137.      * @param <T>         the type of the {@code Predicate} argument
  138.      * @hidden
  139.      *
  140.      ******************************************************************************************************************/
  141.     @FunctionalInterface
  142.     public static interface PredicateWithException<T>
  143.       {
  144.         public boolean test (T t)
  145.                 throws Exception;
  146.       }

  147.     /*******************************************************************************************************************
  148.      *
  149.      * A variant of {@link Runnable} that might throw an {@link Exception}. This interface must not be directly used,
  150.      * it's defined to let the compiler infer functional equivalence.
  151.      *
  152.      * @hidden
  153.      *
  154.      ******************************************************************************************************************/
  155.     @FunctionalInterface
  156.     public static interface RunnableWithException
  157.       {
  158.         public void run()
  159.                 throws Exception;
  160.       }

  161.     /*******************************************************************************************************************
  162.      *
  163.      * A wrapper for a {@link Function} that catches exceptions and wraps them into {@link RuntimeException}s.
  164.      *
  165.      * @param function    the {@code Function} to wrap.
  166.      * @param <T>         the type of the function argument
  167.      * @param <R>         the type of the function return value
  168.      * @return            the wrapped {@code Function}
  169.      *
  170.      ******************************************************************************************************************/
  171.     @Nonnull
  172.     public static <T, R> Function<T, R> _f (@Nonnull final FunctionWithException<T, R> function)
  173.       {
  174.         return t ->
  175.           {
  176.             try
  177.               {
  178.                 return function.apply(t);
  179.               }
  180.             catch (Exception e)
  181.               {
  182.                 throw wrappedException(e);
  183.               }
  184.           };
  185.       }

  186.     /*******************************************************************************************************************
  187.      *
  188.      * A wrapper for a {@link Consumer} that catches exceptions and wraps them into {@link RuntimeException}s.
  189.      *
  190.      * @param consumer    the {@code Consumer} to wrap.
  191.      * @param <T>         the type of the {@code Consumer} argument
  192.      * @return            the wrapped {@code Consumer}
  193.      *
  194.      ******************************************************************************************************************/
  195.     @Nonnull
  196.     public static <T> Consumer<T> _c (@Nonnull final ConsumerWithException<T> consumer)
  197.       {
  198.         return t ->
  199.           {
  200.             try
  201.               {
  202.                 consumer.accept(t);
  203.               }
  204.             catch (Exception e)
  205.               {
  206.                 throw wrappedException(e);
  207.               }
  208.           };
  209.       }

  210.     /*******************************************************************************************************************
  211.      *
  212.      * A wrapper for a {@link Supplier} that catches exceptions and wraps them into {@link RuntimeException}s.
  213.      *
  214.      * @param supplier    the {@code Supplier} to wrap.
  215.      * @param <T>         the type of the {@code Supplier} argument
  216.      * @return            the wrapped {@code Supplier}
  217.      *
  218.      ******************************************************************************************************************/
  219.     @Nonnull
  220.     public static <T> Supplier<T> _s (@Nonnull final SupplierWithException<T> supplier)
  221.       {
  222.         return () ->
  223.           {
  224.             try
  225.               {
  226.                 return supplier.get();
  227.               }
  228.             catch (Exception e)
  229.               {
  230.                 throw wrappedException(e);
  231.               }
  232.           };
  233.       }

  234.     /*******************************************************************************************************************
  235.      *
  236.      * A wrapper for a {@link Predicate} that catches exceptions and wraps them into {@link RuntimeException}s.
  237.      *
  238.      * @param predicate   the {@code Predicate} to wrap.
  239.      * @param <T>         the type of the {@code Predicate} argument
  240.      * @return            the wrapped {@code Predicate}
  241.      *
  242.      ******************************************************************************************************************/
  243.     @Nonnull
  244.     public static <T> Predicate<T> _p (@Nonnull final PredicateWithException<T> predicate)
  245.       {
  246.         return t ->
  247.           {
  248.             try
  249.               {
  250.                 return predicate.test(t);
  251.               }
  252.             catch (Exception e)
  253.               {
  254.                 throw wrappedException(e);
  255.               }
  256.           };
  257.       }

  258.     /*******************************************************************************************************************
  259.      *
  260.      * A wrapper for an equivalent of {@link Runnable} that catches exceptions and wraps them into
  261.      * {@link RuntimeException}s.
  262.      *
  263.      * @param runnable    the {@code Runnable} to wrap.
  264.      * @return            the wrapped {@code Predicate}
  265.      * @since             3.2-ALPHA-12
  266.      *
  267.      ******************************************************************************************************************/
  268.     @Nonnull
  269.     public static Runnable _r (@Nonnull final RunnableWithException runnable)
  270.       {
  271.         return () ->
  272.           {
  273.           try
  274.             {
  275.               runnable.run();
  276.             }
  277.           catch (Exception e)
  278.             {
  279.               throw wrappedException(e);
  280.             }
  281.           };
  282.       }

  283.     /*******************************************************************************************************************
  284.      *
  285.      * Wraps a throwable with a {@link RuntimeException}. Unchecked exceptions are not wrapped; {@link IOException}
  286.      * is wrapped with {@link UncheckedIOException}.
  287.      *
  288.      * @param   e   the exception to wrap
  289.      * @return      the wrapped exception
  290.      *
  291.      ******************************************************************************************************************/
  292.     @Nonnull
  293.     public static RuntimeException wrappedException (@Nonnull final Throwable e)
  294.       {
  295.         if (e instanceof RuntimeException)
  296.           {
  297.             return (RuntimeException)e;
  298.           }

  299.         if (e instanceof IOException)
  300.           {
  301.             return new UncheckedIOException((IOException)e);
  302.           }

  303.         return new RuntimeException(e);
  304.       }
  305.   }