001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3;
018
019import java.io.IOException;
020import java.io.UncheckedIOException;
021import java.lang.reflect.UndeclaredThrowableException;
022
023
024/** This class provides utility functions, and classes for working with the
025 * {@code java.util.function} package, or more generally, with Java 8
026 * lambdas.
027 * More specifically, it attempts to address the fact that lambdas are supposed
028 * not to throw Exceptions, at least not checked Exceptions, aka instances of
029 * {@link Exception}. This enforces the use of constructs like
030 * <pre>
031 *   Consumer&lt;java.lang.reflect.Method&gt; consumer = (m) -&gt; {
032 *       try {
033 *           m.invoke(o, args);
034 *       } catch (Throwable t) {
035 *           throw Functions.rethrow(t);
036 *       }
037 *   };
038 * </pre>
039 * By replacing a {@link java.util.function.Consumer Consumer&lt;O&gt;} with a
040 * {@link FailableConsumer FailableConsumer&lt;O,? extends Throwable&gt;}, this can be
041 * written like follows:
042 * <pre>
043 *   Functions.accept((m) -&gt; m.invoke(o,args));
044 * </pre>
045 * Obviously, the second version is much more concise and the spirit of
046 * Lambda expressions is met better than the second version.
047 */
048public class Functions {
049    @FunctionalInterface
050    public interface FailableRunnable<T extends Throwable> {
051        /**
052         * Runs the function.
053         * @throws T if the function fails
054         */
055        void run() throws T;
056    }
057    @FunctionalInterface
058    public interface FailableCallable<O, T extends Throwable> {
059        /**
060         * Calls the callable.
061         * @return The value returned from the callable
062         * @throws T if the callable fails
063         */
064        O call() throws T;
065    }
066    @FunctionalInterface
067    public interface FailableConsumer<O, T extends Throwable> {
068        /**
069         * Accepts the consumer.
070         * @param pObject the parameter for the consumable to accept
071         * @throws T if the consumer fails
072         */
073        void accept(O pObject) throws T;
074    }
075    @FunctionalInterface
076    public interface FailableBiConsumer<O1, O2, T extends Throwable> {
077        /**
078         * Accepts the consumer.
079         * @param pObject1 the first parameter for the consumable to accept
080         * @param pObject2 the second parameter for the consumable to accept
081         * @throws T if the consumer fails
082         */
083        void accept(O1 pObject1, O2 pObject2) throws T;
084    }
085    @FunctionalInterface
086    public interface FailableFunction<I, O, T extends Throwable> {
087        /**
088         * Apply the function.
089         * @param pInput the input for the function
090         * @return the result of the function
091         * @throws T if the function fails
092         */
093        O apply(I pInput) throws T;
094    }
095    @FunctionalInterface
096    public interface FailableBiFunction<I1, I2, O, T extends Throwable> {
097        /**
098         * Apply the function.
099         * @param pInput1 the first input for the function
100         * @param pInput2 the second input for the function
101         * @return the result of the function
102         * @throws T if the function fails
103         */
104        O apply(I1 pInput1, I2 pInput2) throws T;
105    }
106    @FunctionalInterface
107    public interface FailablePredicate<O, T extends Throwable> {
108        /**
109         * Test the predicate.
110         * @param pObject the object to test the predicate on
111         * @return the predicate's evaluation
112         * @throws T if the predicate fails
113         */
114        boolean test(O pObject) throws T;
115    }
116    @FunctionalInterface
117    public interface FailableBiPredicate<O1, O2, T extends Throwable> {
118        /**
119         * Test the predicate.
120         * @param pObject1 the first object to test the predicate on
121         * @param pObject2 the second object to test the predicate on
122         * @return the predicate's evaluation
123         * @throws T if the predicate fails
124         */
125        boolean test(O1 pObject1, O2 pObject2) throws T;
126    }
127
128    /**
129     * Runs a runnable and rethrows any exception as a {@link RuntimeException}.
130     * @param pRunnable The runnable to run
131     * @param <T> the type of checked exception the runnable may throw
132     */
133    public static <T extends Throwable> void run(FailableRunnable<T> pRunnable) {
134        try {
135            pRunnable.run();
136        } catch (Throwable t) {
137            throw rethrow(t);
138        }
139    }
140
141    /**
142     * Calls a callable and rethrows any exception as a {@link RuntimeException}.
143     * @param pCallable the callable to call
144     * @param <O> the return type of the callable
145     * @param <T> the type of checked exception the callable may throw
146     * @return the value returned from the callable
147     */
148    public static <O, T extends Throwable> O call(FailableCallable<O, T> pCallable) {
149        try {
150            return pCallable.call();
151        } catch (Throwable t) {
152            throw rethrow(t);
153        }
154    }
155
156    /**
157     * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
158     * @param pConsumer the consumer to consume
159     * @param pObject the object to consume by <code>pConsumer</code>
160     * @param <O> the type the consumer accepts
161     * @param <T> the type of checked exception the consumer may throw
162     */
163    public static <O, T extends Throwable> void accept(FailableConsumer<O, T> pConsumer, O pObject) {
164        try {
165            pConsumer.accept(pObject);
166        } catch (Throwable t) {
167            throw rethrow(t);
168        }
169    }
170
171    /**
172     * Consumes a consumer and rethrows any exception as a {@link RuntimeException}.
173     * @param pConsumer the consumer to consume
174     * @param pObject1 the first object to consume by <code>pConsumer</code>
175     * @param pObject2 the second object to consume by <code>pConsumer</code>
176     * @param <O1> the type of the first argument the consumer accepts
177     * @param <O2> the type of the second argument the consumer accepts
178     * @param <T> the type of checked exception the consumer may throw
179     */
180    public static <O1, O2, T extends Throwable> void accept(FailableBiConsumer<O1, O2, T> pConsumer, O1 pObject1, O2 pObject2) {
181        try {
182            pConsumer.accept(pObject1, pObject2);
183        } catch (Throwable t) {
184            throw rethrow(t);
185        }
186    }
187
188    /**
189     * Applies a function and rethrows any exception as a {@link RuntimeException}.
190     * @param pFunction the function to apply
191     * @param pInput the input to apply <code>pFunction</code> on
192     * @param <I> the type of the argument the function accepts
193     * @param <O> the return type of the function
194     * @param <T> the type of checked exception the function may throw
195     * @return the value returned from the function
196     */
197    public static <I, O, T extends Throwable> O apply(FailableFunction<I, O, T> pFunction, I pInput) {
198        try {
199            return pFunction.apply(pInput);
200        } catch (Throwable t) {
201            throw rethrow(t);
202        }
203    }
204
205    /**
206     * Applies a function and rethrows any exception as a {@link RuntimeException}.
207     * @param pFunction the function to apply
208     * @param pInput1 the first input to apply <code>pFunction</code> on
209     * @param pInput2 the second input to apply <code>pFunction</code> on
210     * @param <I1> the type of the first argument the function accepts
211     * @param <I2> the type of the second argument the function accepts
212     * @param <O> the return type of the function
213     * @param <T> the type of checked exception the function may throw
214     * @return the value returned from the function
215     */
216    public static <I1, I2, O, T extends Throwable> O apply(FailableBiFunction<I1, I2, O, T> pFunction, I1 pInput1, I2 pInput2) {
217        try {
218            return pFunction.apply(pInput1, pInput2);
219        } catch (Throwable t) {
220            throw rethrow(t);
221        }
222    }
223
224    /**
225     * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
226     * @param pPredicate the predicate to test
227     * @param pObject the input to test by <code>pPredicate</code>
228     * @param <O> the type of argument the predicate tests
229     * @param <T> the type of checked exception the predicate may throw
230     * @return the boolean value returned by the predicate
231     */
232    public static <O, T extends Throwable> boolean test(FailablePredicate<O, T> pPredicate, O pObject) {
233        try {
234            return pPredicate.test(pObject);
235        } catch (Throwable t) {
236            throw rethrow(t);
237        }
238    }
239
240    /**
241     * Tests a predicate and rethrows any exception as a {@link RuntimeException}.
242     * @param pPredicate the predicate to test
243     * @param pObject1 the first input to test by <code>pPredicate</code>
244     * @param pObject2 the second input to test by <code>pPredicate</code>
245     * @param <O1> the type of the first argument the predicate tests
246     * @param <O2> the type of the second argument the predicate tests
247     * @param <T> the type of checked exception the predicate may throw
248     * @return the boolean value returned by the predicate
249     */
250    public static <O1, O2, T extends Throwable> boolean test(FailableBiPredicate<O1, O2, T> pPredicate, O1 pObject1, O2 pObject2) {
251        try {
252            return pPredicate.test(pObject1, pObject2);
253        } catch (Throwable t) {
254            throw rethrow(t);
255        }
256    }
257
258    /**
259     * A simple try-with-resources implementation, that can be used, if your
260     * objects do not implement the {@link AutoCloseable} interface. The method
261     * executes the {@code pAction}. The method guarantees, that <em>all</em>
262     * the {@code pResources} are being executed, in the given order, afterwards,
263     * and regardless of success, or failure. If either the original action, or
264     * any of the resource action fails, then the <em>first</em> failure (aka
265     * {@link Throwable} is rethrown. Example use:
266     * <pre>
267     *   final FileInputStream fis = new FileInputStream("my.file");
268     *   Functions.tryWithResources(useInputStream(fis), null, () -&gt; fis.close());
269     * </pre>
270     * @param pAction The action to execute. This object <em>will</em> always
271     *   be invoked.
272     * @param pErrorHandler An optional error handler, which will be invoked finally,
273     *   if any error occurred. The error handler will receive the first
274     *   error, aka {@link Throwable}.
275     * @param pResources The resource actions to execute. <em>All</em> resource
276     *   actions will be invoked, in the given order. A resource action is an
277     *   instance of {@link FailableRunnable}, which will be executed.
278     * @see #tryWithResources(FailableRunnable, FailableRunnable...)
279     */
280    @SafeVarargs
281    public static void tryWithResources(FailableRunnable<? extends Throwable> pAction,
282                                            FailableConsumer<Throwable, ? extends Throwable> pErrorHandler,
283                                            FailableRunnable<? extends Throwable>... pResources) {
284        final FailableConsumer<Throwable, ? extends Throwable> errorHandler;
285        if (pErrorHandler == null) {
286            errorHandler = (t) -> rethrow(t);
287        } else {
288            errorHandler = pErrorHandler;
289        }
290        if (pResources != null) {
291            for (FailableRunnable<? extends Throwable> runnable : pResources) {
292                if (runnable == null) {
293                    throw new NullPointerException("A resource action must not be null.");
294                }
295            }
296        }
297        Throwable th = null;
298        try {
299            pAction.run();
300        } catch (Throwable t) {
301            th = t;
302        }
303        if (pResources != null) {
304            for (FailableRunnable<? extends Object> runnable : pResources) {
305                try {
306                    runnable.run();
307                } catch (Throwable t) {
308                    if (th == null) {
309                        th = t;
310                    }
311                }
312            }
313        }
314        if (th != null) {
315            try {
316                errorHandler.accept(th);
317            } catch (Throwable t) {
318                throw rethrow(t);
319            }
320        }
321    }
322
323    /**
324     * A simple try-with-resources implementation, that can be used, if your
325     * objects do not implement the {@link AutoCloseable} interface. The method
326     * executes the {@code pAction}. The method guarantees, that <em>all</em>
327     * the {@code pResources} are being executed, in the given order, afterwards,
328     * and regardless of success, or failure. If either the original action, or
329     * any of the resource action fails, then the <em>first</em> failure (aka
330     * {@link Throwable} is rethrown. Example use:
331     * <pre>
332     *   final FileInputStream fis = new FileInputStream("my.file");
333     *   Functions.tryWithResources(useInputStream(fis), () -&gt; fis.close());
334     * </pre>
335     * @param pAction The action to execute. This object <em>will</em> always
336     *   be invoked.
337     * @param pResources The resource actions to execute. <em>All</em> resource
338     *   actions will be invoked, in the given order. A resource action is an
339     *   instance of {@link FailableRunnable}, which will be executed.
340     * @see #tryWithResources(FailableRunnable, FailableConsumer, FailableRunnable...)
341     */
342    @SafeVarargs
343    public static void tryWithResources(FailableRunnable<? extends Throwable> pAction,
344                                            FailableRunnable<? extends Throwable>... pResources) {
345        tryWithResources(pAction, null, pResources);
346    }
347
348    /**
349     * Rethrow a {@link Throwable} as an unchecked exception.
350     * @param pThrowable The throwable to rethrow
351     * @return Never returns anything, this method never terminates normally
352     */
353    public static RuntimeException rethrow(Throwable pThrowable) {
354        if (pThrowable == null) {
355            throw new NullPointerException("The Throwable must not be null.");
356        } else {
357            if (pThrowable instanceof RuntimeException) {
358                throw (RuntimeException) pThrowable;
359            } else if (pThrowable instanceof Error) {
360                throw (Error) pThrowable;
361            } else if (pThrowable instanceof IOException) {
362                throw new UncheckedIOException((IOException) pThrowable);
363            } else {
364                throw new UndeclaredThrowableException(pThrowable);
365            }
366        }
367    }
368}