FunctionalCheckedExceptionWrappers.java

  1. /*
  2.  * *********************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2021 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.io.IOException;
  30. import java.io.UncheckedIOException;
  31. import java.util.function.Consumer;
  32. import java.util.function.Function;
  33. import java.util.function.Predicate;
  34. import java.util.function.Supplier;
  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 wrapper for a {@link Function} that catches exceptions and wraps them into {@link RuntimeException}s.
  150.      *
  151.      * @param function    the {@code Function} to wrap.
  152.      * @param <T>         the type of the function argument
  153.      * @param <R>         the type of the function return value
  154.      * @return            the wrapped {@code Function}
  155.      *
  156.      ******************************************************************************************************************/
  157.     @Nonnull
  158.     public static <T, R> Function<T, R> _f (@Nonnull final FunctionWithException<T, R> function)
  159.       {
  160.         return t ->
  161.           {
  162.             try
  163.               {
  164.                 return function.apply(t);
  165.               }
  166.             catch (Exception e)
  167.               {
  168.                 throw wrappedException(e);
  169.               }
  170.           };
  171.       }

  172.     /*******************************************************************************************************************
  173.      *
  174.      * A wrapper for a {@link Consumer} that catches exceptions and wraps them into {@link RuntimeException}s.
  175.      *
  176.      * @param consumer    the {@code Consumer} to wrap.
  177.      * @param <T>         the type of the {@code Consumer} argument
  178.      * @return            the wrapped {@code Consumer}
  179.      *
  180.      ******************************************************************************************************************/
  181.     @Nonnull
  182.     public static <T> Consumer<T> _c (@Nonnull final ConsumerWithException<T> consumer)
  183.       {
  184.         return t ->
  185.           {
  186.             try
  187.               {
  188.                 consumer.accept(t);
  189.               }
  190.             catch (Exception e)
  191.               {
  192.                 throw wrappedException(e);
  193.               }
  194.           };
  195.       }

  196.     /*******************************************************************************************************************
  197.      *
  198.      * A wrapper for a {@link Supplier} that catches exceptions and wraps them into {@link RuntimeException}s.
  199.      *
  200.      * @param supplier    the {@code Supplier} to wrap.
  201.      * @param <T>         the type of the {@code Supplier} argument
  202.      * @return            åthe wrapped {@code Supplier}
  203.      *
  204.      ******************************************************************************************************************/
  205.     @Nonnull
  206.     public static <T> Supplier<T> _s (@Nonnull final SupplierWithException<T> supplier)
  207.       {
  208.         return () ->
  209.           {
  210.             try
  211.               {
  212.                 return supplier.get();
  213.               }
  214.             catch (Exception e)
  215.               {
  216.                 throw wrappedException(e);
  217.               }
  218.           };
  219.       }

  220.     /*******************************************************************************************************************
  221.      *
  222.      * A wrapper for a {@link Predicate} that catches exceptions and wraps them into {@link RuntimeException}s.
  223.      *
  224.      * @param predicate   the {@code Predicate} to wrap.
  225.      * @param <T>         the type of the {@code Predicate} argument
  226.      * @return            åthe wrapped {@code Predicate}
  227.      *
  228.      ******************************************************************************************************************/
  229.     @Nonnull
  230.     public static <T> Predicate<T> _p (@Nonnull final PredicateWithException<T> predicate)
  231.       {
  232.         return t ->
  233.           {
  234.             try
  235.               {
  236.                 return predicate.test(t);
  237.               }
  238.             catch (Exception e)
  239.               {
  240.                 throw wrappedException(e);
  241.               }
  242.           };
  243.       }

  244.     /*******************************************************************************************************************
  245.      *
  246.      *
  247.      ******************************************************************************************************************/
  248.     @Nonnull
  249.     static RuntimeException wrappedException (@Nonnull final Exception e)
  250.       {
  251.         if (e instanceof RuntimeException)
  252.           {
  253.             return (RuntimeException)e;
  254.           }

  255.         if (e instanceof IOException)
  256.           {
  257.             return new UncheckedIOException((IOException)e);
  258.           }

  259.         return new RuntimeException(e);
  260.       }
  261.   }