View Javadoc
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  
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   *
40   * A collections of utility methods for simplifying the syntax of lambda expressions with APIs that don't accept
41   * checked exceptions (such as {@link java.util.stream.Stream}): they provide wrapped functions that have no checked
42   * exception in the signature and whose implementation delegates to the original function wrapping an eventual checked
43   * exception into a {@link RuntimeException}. For instance, given the following method that could not be used as a
44   * {@link java.util.stream.Stream#filter(Predicate)} argument:
45   *
46   * <pre>
47   *   private boolean matchEven (final int number)
48   *           throws Exception
49   *     {
50   *       if (number == 13)
51   *         {
52   *           throw new Exception("13!");
53   *         }
54   *
55   *       return number % 2 == 0;
56   *     }
57   * </pre>
58   *
59   * working code can be written as:
60   *
61   * <pre>
62   *   try
63   *     {
64   *       List&lt;Integer&gt; numbers = IntStream.rangeClosed(1, 20)
65   *                                        .mapToObj(Integer::valueOf)
66   *                                        .filter(_p(this::matchEven)) // note the wrapper here
67   *                                        .collect(Collectors.toList());
68   *       ...
69   *     }
70   *   catch (RuntimeException e)
71   *     {
72   *       ...
73   *     }
74   * </pre>
75   *
76   * Any checked exception is wrapped by a {@code RuntimeException}, but {@link IOException} is wrapped by a
77   * {@link UncheckedIOException}.
78   *
79   * @author Fabrizio Giudici
80   * @it.tidalwave.javadoc.draft
81   * @since 3.2-ALPHA-1
82   *
83   **************************************************************************************************************************************************************/
84  @NoArgsConstructor(access = PRIVATE)
85  public final class FunctionalCheckedExceptionWrappers
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      @FunctionalInterface
96      public static interface FunctionWithException<T, R>
97        {
98          public R apply (T t)
99                  throws Exception;
100       }
101 
102     /***********************************************************************************************************************************************************
103      * A variant of {@link Consumer} that might throw an {@link Exception}. This interface must not be directly used,
104      * it's defined to let the compiler infer functional equivalence.
105      *
106      * @param <T>         the type of the {@code Consumer} argument
107      * @hidden
108      **********************************************************************************************************************************************************/
109     @FunctionalInterface
110     public static interface ConsumerWithException<T>
111       {
112         public void accept (T t)
113                 throws Exception;
114       }
115 
116     /***********************************************************************************************************************************************************
117      * A variant of {@link Supplier} that might throw an {@link Exception}. This interface must not be directly used,
118      * it's defined to let the compiler infer functional equivalence.
119      *
120      * @param <T>         the type of the {@code Supplier} argument
121      * @hidden
122      **********************************************************************************************************************************************************/
123     @FunctionalInterface
124     public static interface SupplierWithException<T>
125       {
126         public T get ()
127                 throws Exception;
128       }
129 
130     /***********************************************************************************************************************************************************
131      * A variant of {@link Predicate} that might throw an {@link Exception}. This interface must not be directly used,
132      * it's defined to let the compiler infer functional equivalence.
133      *
134      * @param <T>         the type of the {@code Predicate} argument
135      * @hidden
136      **********************************************************************************************************************************************************/
137     @FunctionalInterface
138     public static interface PredicateWithException<T>
139       {
140         public boolean test (T t)
141                 throws Exception;
142       }
143 
144     /***********************************************************************************************************************************************************
145      * A variant of {@link Runnable} that might throw an {@link Exception}. This interface must not be directly used,
146      * it's defined to let the compiler infer functional equivalence.
147      *
148      * @hidden
149      **********************************************************************************************************************************************************/
150     @FunctionalInterface
151     public static interface RunnableWithException
152       {
153         @SuppressWarnings("RedundantThrows")
154         public void run()
155                 throws Exception;
156       }
157 
158     /***********************************************************************************************************************************************************
159      * A wrapper for a {@link Function} that catches exceptions and wraps them into {@link RuntimeException}s.
160      *
161      * @param function    the {@code Function} to wrap.
162      * @param <T>         the type of the function argument
163      * @param <R>         the type of the function return value
164      * @return            the wrapped {@code Function}
165      **********************************************************************************************************************************************************/
166     @Nonnull
167     public static <T, R> Function<T, R> _f (@Nonnull final FunctionWithException<? super T, ? extends R> function)
168       {
169         return t ->
170           {
171             try
172               {
173                 return function.apply(t);
174               }
175             catch (Exception e)
176               {
177                 throw wrappedException(e);
178               }
179           };
180       }
181 
182     /***********************************************************************************************************************************************************
183      * A wrapper for a {@link Consumer} that catches exceptions and wraps them into {@link RuntimeException}s.
184      *
185      * @param consumer    the {@code Consumer} to wrap.
186      * @param <T>         the type of the {@code Consumer} argument
187      * @return            the wrapped {@code Consumer}
188      **********************************************************************************************************************************************************/
189     @Nonnull
190     public static <T> Consumer<T> _c (@Nonnull final ConsumerWithException<? super T> consumer)
191       {
192         return t ->
193           {
194             try
195               {
196                 consumer.accept(t);
197               }
198             catch (Exception e)
199               {
200                 throw wrappedException(e);
201               }
202           };
203       }
204 
205     /***********************************************************************************************************************************************************
206      * A wrapper for a {@link Supplier} that catches exceptions and wraps them into {@link RuntimeException}s.
207      *
208      * @param supplier    the {@code Supplier} to wrap.
209      * @param <T>         the type of the {@code Supplier} argument
210      * @return            the wrapped {@code Supplier}
211      **********************************************************************************************************************************************************/
212     @Nonnull
213     public static <T> Supplier<T> _s (@Nonnull final SupplierWithException<? extends T> supplier)
214       {
215         return () ->
216           {
217             try
218               {
219                 return supplier.get();
220               }
221             catch (Exception e)
222               {
223                 throw wrappedException(e);
224               }
225           };
226       }
227 
228     /***********************************************************************************************************************************************************
229      * A wrapper for a {@link Predicate} that catches exceptions and wraps them into {@link RuntimeException}s.
230      *
231      * @param predicate   the {@code Predicate} to wrap.
232      * @param <T>         the type of the {@code Predicate} argument
233      * @return            the wrapped {@code Predicate}
234      **********************************************************************************************************************************************************/
235     @Nonnull
236     public static <T> Predicate<T> _p (@Nonnull final PredicateWithException<? super T> predicate)
237       {
238         return t ->
239           {
240             try
241               {
242                 return predicate.test(t);
243               }
244             catch (Exception e)
245               {
246                 throw wrappedException(e);
247               }
248           };
249       }
250 
251     /***********************************************************************************************************************************************************
252      * A wrapper for an equivalent of {@link Runnable} that catches exceptions and wraps them into
253      * {@link RuntimeException}s.
254      *
255      * @param runnable    the {@code Runnable} to wrap.
256      * @return            the wrapped {@code Predicate}
257      * @since             3.2-ALPHA-12
258      **********************************************************************************************************************************************************/
259     @Nonnull
260     public static Runnable _r (@Nonnull final RunnableWithException runnable)
261       {
262         return () ->
263           {
264           try
265             {
266               runnable.run();
267             }
268           catch (Exception e)
269             {
270               throw wrappedException(e);
271             }
272           };
273       }
274 
275     /***********************************************************************************************************************************************************
276      * Wraps a throwable with a {@link RuntimeException}. Unchecked exceptions are not wrapped; {@link IOException}
277      * is wrapped with {@link UncheckedIOException}.
278      *
279      * @param   e   the exception to wrap
280      * @return      the wrapped exception
281      **********************************************************************************************************************************************************/
282     @Nonnull
283     public static RuntimeException wrappedException (@Nonnull final Throwable e)
284       {
285         if (e instanceof RuntimeException)
286           {
287             return (RuntimeException)e;
288           }
289 
290         if (e instanceof IOException)
291           {
292             return new UncheckedIOException((IOException)e);
293           }
294 
295         return new RuntimeException(e);
296       }
297   }