FunctionalCheckedExceptionWrappers.java

  1. /*
  2.  * *************************************************************************************************************************************************************
  3.  *
  4.  * TheseFoolishThings: Miscellaneous utilities
  5.  * http://tidalwave.it/projects/thesefoolishthings
  6.  *
  7.  * Copyright (C) 2009 - 2024 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 the License.
  12.  * 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 an "AS IS" BASIS, WITHOUT WARRANTIES OR
  17.  * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
  18.  *
  19.  * *************************************************************************************************************************************************************
  20.  *
  21.  * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
  22.  * git clone https://github.com/tidalwave-it/thesefoolishthings-src
  23.  *
  24.  * *************************************************************************************************************************************************************
  25.  */
  26. package it.tidalwave.util;

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

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

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

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

  125.     /***********************************************************************************************************************************************************
  126.      * A variant of {@link Predicate} that might throw an {@link Exception}. This interface must not be directly used,
  127.      * it's defined to let the compiler infer functional equivalence.
  128.      *
  129.      * @param <T>         the type of the {@code Predicate} argument
  130.      * @hidden
  131.      **********************************************************************************************************************************************************/
  132.     @FunctionalInterface
  133.     public static interface PredicateWithException<T>
  134.       {
  135.         public boolean test (T t)
  136.                 throws Exception;
  137.       }

  138.     /***********************************************************************************************************************************************************
  139.      * A variant of {@link Runnable} that might throw an {@link Exception}. This interface must not be directly used,
  140.      * it's defined to let the compiler infer functional equivalence.
  141.      *
  142.      * @hidden
  143.      **********************************************************************************************************************************************************/
  144.     @FunctionalInterface
  145.     public static interface RunnableWithException
  146.       {
  147.         @SuppressWarnings("RedundantThrows")
  148.         public void run()
  149.                 throws Exception;
  150.       }

  151.     /***********************************************************************************************************************************************************
  152.      * A wrapper for a {@link Function} that catches exceptions and wraps them into {@link RuntimeException}s.
  153.      *
  154.      * @param function    the {@code Function} to wrap.
  155.      * @param <T>         the type of the function argument
  156.      * @param <R>         the type of the function return value
  157.      * @return            the wrapped {@code Function}
  158.      **********************************************************************************************************************************************************/
  159.     @Nonnull
  160.     public static <T, R> Function<T, R> _f (@Nonnull final FunctionWithException<? super T, ? extends R> function)
  161.       {
  162.         return t ->
  163.           {
  164.             try
  165.               {
  166.                 return function.apply(t);
  167.               }
  168.             catch (Exception e)
  169.               {
  170.                 throw wrappedException(e);
  171.               }
  172.           };
  173.       }

  174.     /***********************************************************************************************************************************************************
  175.      * A wrapper for a {@link Consumer} that catches exceptions and wraps them into {@link RuntimeException}s.
  176.      *
  177.      * @param consumer    the {@code Consumer} to wrap.
  178.      * @param <T>         the type of the {@code Consumer} argument
  179.      * @return            the wrapped {@code Consumer}
  180.      **********************************************************************************************************************************************************/
  181.     @Nonnull
  182.     public static <T> Consumer<T> _c (@Nonnull final ConsumerWithException<? super 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.      * A wrapper for a {@link Supplier} that catches exceptions and wraps them into {@link RuntimeException}s.
  198.      *
  199.      * @param supplier    the {@code Supplier} to wrap.
  200.      * @param <T>         the type of the {@code Supplier} argument
  201.      * @return            the wrapped {@code Supplier}
  202.      **********************************************************************************************************************************************************/
  203.     @Nonnull
  204.     public static <T> Supplier<T> _s (@Nonnull final SupplierWithException<? extends T> supplier)
  205.       {
  206.         return () ->
  207.           {
  208.             try
  209.               {
  210.                 return supplier.get();
  211.               }
  212.             catch (Exception e)
  213.               {
  214.                 throw wrappedException(e);
  215.               }
  216.           };
  217.       }

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

  240.     /***********************************************************************************************************************************************************
  241.      * A wrapper for an equivalent of {@link Runnable} that catches exceptions and wraps them into
  242.      * {@link RuntimeException}s.
  243.      *
  244.      * @param runnable    the {@code Runnable} to wrap.
  245.      * @return            the wrapped {@code Predicate}
  246.      * @since             3.2-ALPHA-12
  247.      **********************************************************************************************************************************************************/
  248.     @Nonnull
  249.     public static Runnable _r (@Nonnull final RunnableWithException runnable)
  250.       {
  251.         return () ->
  252.           {
  253.           try
  254.             {
  255.               runnable.run();
  256.             }
  257.           catch (Exception e)
  258.             {
  259.               throw wrappedException(e);
  260.             }
  261.           };
  262.       }

  263.     /***********************************************************************************************************************************************************
  264.      * Wraps a throwable with a {@link RuntimeException}. Unchecked exceptions are not wrapped; {@link IOException}
  265.      * is wrapped with {@link UncheckedIOException}.
  266.      *
  267.      * @param   e   the exception to wrap
  268.      * @return      the wrapped exception
  269.      **********************************************************************************************************************************************************/
  270.     @Nonnull
  271.     public static RuntimeException wrappedException (@Nonnull final Throwable e)
  272.       {
  273.         if (e instanceof RuntimeException)
  274.           {
  275.             return (RuntimeException)e;
  276.           }

  277.         if (e instanceof IOException)
  278.           {
  279.             return new UncheckedIOException((IOException)e);
  280.           }

  281.         return new RuntimeException(e);
  282.       }
  283.   }