View Javadoc
1   /*-
2    * #%L
3    * io.earcam.unexceptional
4    * %%
5    * Copyright (C) 2016 - 2017 earcam
6    * %%
7    * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8    * 
9    * You <b>must</b> choose to accept, in full - any individual or combination of 
10   * the following licenses:
11   * <ul>
12   * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13   * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14   * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15   * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16   * </ul>
17   * #L%
18   */
19  package io.earcam.unexceptional;
20  
21  import static java.util.Collections.unmodifiableMap;
22  
23  import java.io.IOException;
24  import java.io.Serializable;
25  import java.io.UncheckedIOException;
26  import java.lang.Thread.UncaughtExceptionHandler;
27  import java.lang.reflect.InvocationTargetException;
28  import java.lang.reflect.UndeclaredThrowableException;
29  import java.net.MalformedURLException;
30  import java.net.URI;
31  import java.net.URISyntaxException;
32  import java.net.URL;
33  import java.net.URLStreamHandler;
34  import java.security.GeneralSecurityException;
35  import java.util.Comparator;
36  import java.util.HashMap;
37  import java.util.HashSet;
38  import java.util.Map;
39  import java.util.Set;
40  import java.util.concurrent.Callable;
41  import java.util.function.BiConsumer;
42  import java.util.function.BiFunction;
43  import java.util.function.BinaryOperator;
44  import java.util.function.Consumer;
45  import java.util.function.Function;
46  import java.util.function.IntConsumer;
47  import java.util.function.Predicate;
48  import java.util.function.Supplier;
49  import java.util.function.ToDoubleFunction;
50  import java.util.function.ToIntBiFunction;
51  import java.util.function.ToIntFunction;
52  import java.util.function.ToLongFunction;
53  import java.util.stream.Stream;
54  
55  /**
56   * <p>
57   * Static utility for easy conversion of checked exceptions, and invocation of methods declaring checked exceptions.
58   * </p>
59   * 
60   * <p>
61   * There are many cases where you <i>know</i>, within a given context that a checked exception will not be raised, but
62   * if it is, then it's certainly <i>game over</i>. An example being URLs in server configuration.
63   * </p>
64   * 
65   * <p>
66   * The functionality centres around {@link java.util.function} given their beautifully broad application.
67   * </p>
68   * 
69   * <p>
70   * In addition, common standard library <i>annoyances</i> are included; e.g. {@link URL}, {@link URI}, and highly
71   * concise (re-read as terse one-liner - arguably laconic over expressive) for common IO streams usage.
72   * </p>
73   * 
74   * <p>
75   * When dealing with {@link Stream} from an IO source (e.g. the file system), it may be preferable (to pay a
76   * performance cost due to wrapping) and use {@link EmeticStream} which mirrors {@link Stream} functionality
77   * but with checked equivalent types.
78   * </p>
79   * 
80   * <h1>Exceptional</h1>
81   * <b>/ɪkˈsɛpʃ(ə)n(ə)l,ɛkˈsɛpʃ(ə)n(ə)l/</b>
82   * <p>
83   * <i>adjective:</i>
84   * </p>
85   * <p>
86   * 1. unusual; not typical.
87   * </p>
88   */
89  /* @javax.annotation.ParametersAreNonnullByDefault */
90  /* @edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault */
91  /* @net.jcip.annotations.Immutable */
92  @SuppressWarnings({
93  		"squid:S1905", // SonarQube false positives
94  		"squid:S1181"  // SonarQube necessary evil
95  })
96  public final class Exceptional implements Serializable {
97  
98  	private static final long serialVersionUID = -1350140594550206145L;
99  
100 	private static final Map<Class<? extends Throwable>, Function<Throwable, RuntimeException>> UNCHECK_MAP;
101 
102 	static {
103 		Map<Class<? extends Throwable>, Function<Throwable, RuntimeException>> map = new HashMap<>();
104 		// @formatter:off
105 		map.put(ReflectiveOperationException.class, e -> new UncheckedReflectiveException((ReflectiveOperationException)e));
106 		map.put(    GeneralSecurityException.class, e -> new UncheckedSecurityException((GeneralSecurityException)e));
107 		map.put(        InterruptedException.class, e -> new UncheckedInterruptException((InterruptedException)e));
108 		map.put(          URISyntaxException.class, e -> new UncheckedUriSyntaxException((URISyntaxException)e));
109 		map.put(            RuntimeException.class, RuntimeException.class::cast);
110 		map.put(                 IOException.class, e -> new UncheckedIOException((IOException)e));
111 		// @formatter:on
112 
113 		UNCHECK_MAP = unmodifiableMap(map);
114 	}
115 
116 	/**
117 	 * An {@link UncaughtExceptionHandler} that simply rethrows,
118 	 * wrapping in an appropriate unchecked if necessary
119 	 * 
120 	 * @since 0.2.0
121 	 */
122 	public static final UncaughtExceptionHandler RETHROWING = (t, e) -> Exceptional.rethrow(e);
123 
124 	/**
125 	 * An {@link UncaughtExceptionHandler} that simply swallows <i>all</i> exceptions,
126 	 * except subclasses of {@link Error}, which are rethrown.
127 	 * 
128 	 * @since 0.2.0
129 	 */
130 	public static final UncaughtExceptionHandler SWALLOWING = (t, e) -> Exceptional.swallow(e);
131 
132 
133 	private Exceptional()
134 	{
135 		throw new IllegalStateException("Why on earth would you want to instantiate this?");
136 	}
137 
138 
139 	/**
140 	 * @param earl the text URL
141 	 * @return a {@link URL} representation
142 	 * 
143 	 * @since 0.2.0
144 	 */
145 	public static URL url(CharSequence earl)
146 	{
147 		try {
148 			return new URL(earl.toString());
149 		} catch(MalformedURLException e) {
150 			throw uncheck(e);
151 		}
152 	}
153 
154 
155 	/**
156 	 * @param protocol e.g. https, ftp, sctp
157 	 * @param host hostname or IP
158 	 * @param port 0 to 65536
159 	 * @param path the "file" portion of the URL
160 	 * @param handler optional URLStreamHandler
161 	 * @return a {@link URL} representation
162 	 * 
163 	 * @since 0.2.0
164 	 */
165 	public static URL url(String protocol, String host, int port, String path, /* @Nullable */ URLStreamHandler handler)
166 	{
167 		try {
168 			return new URL(protocol, host, port, path, handler);
169 		} catch(MalformedURLException e) {
170 			throw uncheck(e);
171 		}
172 	}
173 
174 
175 	/**
176 	 * @param ʊri the text URI (as Earl is to URL, so ʊri (as in Uri Geller) is to URI)
177 	 * @return a {@link URI} representation
178 	 * 
179 	 * @since 0.2.0
180 	 */
181 	@SuppressWarnings("squid:S00117")  // utf8 in a parameter name is fine by me
182 	public static URI uri(CharSequence ʊri)
183 	{
184 		try {
185 			return new URI(ʊri.toString());
186 		} catch(URISyntaxException e) {
187 			throw uncheck(e);
188 		}
189 	}
190 
191 
192 	/**
193 	 * Invokes {@link URL#toURI()}, catching any {@link URISyntaxException} and rethrowing
194 	 * wrapped as {@link UncheckedUriSyntaxException}
195 	 * 
196 	 * @param earl the {@link URL} to convert
197 	 * @return the {@link URI} form of the <code>earl</code> argument
198 	 * 
199 	 * @since 0.3.0
200 	 */
201 	public static URI uri(URL earl)
202 	{
203 		try {
204 			return earl.toURI();
205 		} catch(URISyntaxException e) {
206 			throw uncheck(e);
207 		}
208 	}
209 
210 
211 	/**
212 	 * Will regurgitate any {@link Error} - otherwise will dutifully and silently <i>swallow</i> whole.
213 	 * Gulping of {@link InterruptedException}s will result in the current {@link Thread}'s interrupt
214 	 * flag being reset.
215 	 * 
216 	 * <b>Caution</b>: used carelessly/incorrectly this foul method will inevitably lead to a frustrating
217 	 * debugging session resulting in plenty of "doh"/"wtf" but never a "eureka" moment. Shooting of
218 	 * messenger is in breach of license terms.
219 	 * 
220 	 * @param caught the caught unmentionable
221 	 * 
222 	 * @since 0.2.0
223 	 */
224 	public static void swallow(Throwable caught)
225 	{
226 		resetIfInterrupt(caught);
227 		if(caught instanceof Error) {
228 			throw (Error) caught;
229 		}
230 	}
231 
232 
233 	/**
234 	 * Catching an {@link InterruptedException} clears the interrupt flag,
235 	 * this merely resets the flag IFF the <code>thrown</code> parameter is
236 	 * an instance of {@link InterruptedException}.
237 	 * 
238 	 * @param thrown possible {@link InterruptedException}
239 	 * 
240 	 * @since 0.2.0
241 	 */
242 	public static void resetIfInterrupt(Throwable thrown)
243 	{
244 		if(thrown instanceof InterruptedException) {
245 			Thread.currentThread().interrupt();
246 		}
247 	}
248 
249 
250 	/**
251 	 * Directly rethrows {@link Error}s or {@link RuntimeException}s, wraps
252 	 * checked exceptions appropriately
253 	 * 
254 	 * @param thrown the caught throwable to be rethrown as unchecked
255 	 * @return actually nothing, this just allows you to write {@code throw Exceptional.rethrow(e)} for methods than
256 	 * have return values.
257 	 * 
258 	 * @see #throwAsUnchecked(Throwable)
259 	 * 
260 	 * @since 0.2.0
261 	 */
262 	public static RuntimeException rethrow(Throwable thrown)
263 	{
264 		if(thrown instanceof Error) {
265 			throw (Error) thrown;
266 		}
267 		throw uncheck(thrown);
268 	}
269 
270 
271 	/**
272 	 * Invokes {@link CheckedRunnable#run()} catching any checked
273 	 * {@link Exception}s rethrowing them as unchecked.
274 	 * 
275 	 * @param runnable the checked runnable to run
276 	 * 
277 	 * @since 0.2.0
278 	 */
279 	public static void run(CheckedRunnable<?> runnable)
280 	{
281 		try {
282 			runnable.run();
283 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
284 			throw error;
285 		} catch(Throwable thrown) {
286 			throw uncheck(thrown);
287 		}
288 	}
289 
290 
291 	/**
292 	 * Convert a {@link CheckedRunnable} into a {@link Runnable}
293 	 * 
294 	 * @param runnable the checked runnable to wrap
295 	 * @return an unchecked wrapper around the <code>runnable</code> argument
296 	 * 
297 	 * @since 0.2.0
298 	 */
299 	public static Runnable uncheckRunnable(CheckedRunnable<?> runnable)
300 	{
301 		return () -> run(runnable);
302 	}
303 
304 
305 	/**
306 	 * Invokes {@link Callable#call()} catching any checked
307 	 * {@link Exception}s rethrowing as unchecked.
308 	 * 
309 	 * @param <T> the return type of the {@link Callable}
310 	 * 
311 	 * @param callable the {@link Callable} to execute
312 	 * @return the result of calling the {@link Callable}
313 	 * 
314 	 * @since 0.2.0
315 	 */
316 	public static <T> T call(Callable<T> callable)
317 	{
318 		try {
319 			return callable.call();
320 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
321 			throw error;
322 		} catch(Throwable thrown) {
323 			throw uncheck(thrown);
324 		}
325 	}
326 
327 
328 	/**
329 	 * <p>
330 	 * Converts {@link Throwable}s to {@link RuntimeException}s.
331 	 * </p>
332 	 * <p>
333 	 * If the supplied {@link Throwable} is already a {@link RuntimeException}, then it's simply cast and returned.
334 	 * </p>
335 	 * <p>
336 	 * {@link Error} subclasses will be wrapped in an {@link UncheckedException}.
337 	 * </p>
338 	 * <p>
339 	 * The interrupt flag will be reset IFF {@code caught instanceof InterruptedException}
340 	 * </p>
341 	 * 
342 	 * @param caught any {@link Throwable}
343 	 * @return a {@link RuntimeException}, typically a subclass of {@link UncheckedException} or an
344 	 * {@link UncheckedIOException}
345 	 * @see #rethrow(Throwable)
346 	 * 
347 	 * @since 0.2.0
348 	 */
349 	public static RuntimeException uncheck(Throwable caught)
350 	{
351 		return UNCHECK_MAP.entrySet().stream()
352 				.filter(e -> e.getKey().isInstance(caught))
353 				.map(e -> e.getValue().apply(caught))
354 				.findFirst()
355 				.orElseGet(() -> new UncheckedException(caught));
356 	}
357 
358 
359 	/**
360 	 * Converts {@link CheckedConsumer} to {@link Consumer}
361 	 * 
362 	 * @param <T> the consumed type
363 	 * 
364 	 * @param consumer a consumer that declares checked exception(s)
365 	 * @return a vanilla {@link java.util.function.Consumer}
366 	 * 
367 	 * @since 0.2.0
368 	 */
369 	@SuppressWarnings("unchecked")
370 	public static <T> Consumer<T> uncheckConsumer(CheckedConsumer<T, ?> consumer)
371 	{
372 		return (Consumer<T> & Serializable) t -> Exceptional.accept(consumer, t);
373 	}
374 
375 
376 	/**
377 	 * Invokes {@link CheckedConsumer#accept(Object)} catching any checked
378 	 * {@link Exception}s rethrowing as unchecked.
379 	 * 
380 	 * @param <T> the consumed type
381 	 * 
382 	 * @param consumer the consumer of the {@code value}
383 	 * @param value the value to be consumed
384 	 * 
385 	 * @since 0.2.0
386 	 */
387 	public static <T> void accept(CheckedConsumer<T, ?> consumer, T value)
388 	{
389 		try {
390 			consumer.accept(value);
391 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
392 			throw error;
393 		} catch(Throwable thrown) {
394 			throw uncheck(thrown);
395 		}
396 	}
397 
398 
399 	/**
400 	 * Converts {@link CheckedIntConsumer} to {@link IntConsumer}
401 	 * 
402 	 * @param consumer a consumer of primitive integer that declares checked exception(s)
403 	 * @return a vanilla {@link java.util.function.IntConsumer}
404 	 * 
405 	 * @since 0.5.0
406 	 */
407 	public static IntConsumer uncheckIntConsumer(CheckedIntConsumer<?> consumer)
408 	{
409 		return (IntConsumer & Serializable) t -> Exceptional.accept(consumer, t);
410 	}
411 
412 
413 	/**
414 	 * Invokes {@link CheckedIntConsumer#accept(int)} catching any checked
415 	 * {@link Exception}s rethrowing as unchecked.
416 	 * 
417 	 * @param consumer the consumer of the {@code int value}
418 	 * @param value the value to be consumed
419 	 * 
420 	 * @since 0.5.0
421 	 */
422 	public static void accept(CheckedIntConsumer<?> consumer, int value)
423 	{
424 		try {
425 			consumer.accept(value);
426 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
427 			throw error;
428 		} catch(Throwable thrown) {
429 			throw uncheck(thrown);
430 		}
431 	}
432 
433 
434 	/**
435 	 * Convert a {@link CheckedBiConsumer} into a {@link BiConsumer}.
436 	 * 
437 	 * @param <T> first argument type
438 	 * @param <U> last argument type
439 	 * 
440 	 * @param consumer the checked consumer
441 	 * @return an unchecked consumer wrapping the {@code consumer} argument
442 	 * 
443 	 * @since 0.2.0
444 	 */
445 	@SuppressWarnings("unchecked")
446 	public static <T, U> BiConsumer<T, U> uncheckBiConsumer(CheckedBiConsumer<T, U, ?> consumer)
447 	{
448 		return (BiConsumer<T, U> & Serializable) (t, u) -> Exceptional.accept(consumer, t, u);
449 	}
450 
451 
452 	/**
453 	 * Invokes {@link CheckedConsumer#accept(Object)} catching any checked
454 	 * {@link Exception}s rethrowing as unchecked.
455 	 * 
456 	 * @param <T> first argument type
457 	 * @param <U> last argument type
458 	 * 
459 	 * @param consumer the consumer of the {@code value}
460 	 * @param t first argument to be consumed
461 	 * @param u last argument to be consumed
462 	 * 
463 	 * @since 0.2.0
464 	 */
465 	public static <T, U> void accept(CheckedBiConsumer<T, U, ?> consumer, T t, U u)
466 	{
467 		try {
468 			consumer.accept(t, u);
469 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
470 			throw error;
471 		} catch(Throwable thrown) {
472 			throw uncheck(thrown);
473 		}
474 	}
475 
476 
477 	/**
478 	 * Converts a {@link CheckedFunction} into a {@link Function}.
479 	 * 
480 	 * @param <T> argument type
481 	 * @param <R> return type
482 	 * 
483 	 * @param function the checked function
484 	 * @return an unchecked function wrapping the {@code function} argument.
485 	 * 
486 	 * @since 0.2.0
487 	 */
488 	@SuppressWarnings("unchecked")
489 	public static <T, R> Function<T, R> uncheckFunction(CheckedFunction<T, R, ?> function)
490 	{
491 		return (Function<T, R> & Serializable) t -> Exceptional.apply(function, t);
492 	}
493 
494 
495 	/**
496 	 * Invokes {@link CheckedFunction#apply(Object)} catching any checked
497 	 * {@link Exception}s rethrowing as unchecked.
498 	 * 
499 	 * @param <T> argument type
500 	 * @param <R> return type
501 	 * 
502 	 * @param function the checked function to invoke with the {@code argument}
503 	 * @param argument the argument to apply to the function
504 	 * @return the result of applying {@code argument} to {@code function}
505 	 * 
506 	 * @since 0.2.0
507 	 */
508 	public static <T, R> R apply(CheckedFunction<T, R, ?> function, T argument)
509 	{
510 		try {
511 			return function.apply(argument);
512 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
513 			throw error;
514 		} catch(Throwable thrown) {
515 			throw uncheck(thrown);
516 		}
517 	}
518 
519 
520 	/**
521 	 * Convert a {@link CheckedBiFunction} into a {@link BiFunction}.
522 	 * 
523 	 * @param <T> first argument type
524 	 * @param <U> last argument type
525 	 * @param <R> return type
526 	 * 
527 	 * @param function the checked bi-function
528 	 * @return an unchecked bi-function wrapping the {@code function} argument.
529 	 * 
530 	 * @since 0.2.0
531 	 */
532 	@SuppressWarnings("unchecked")
533 	public static <T, U, R> BiFunction<T, U, R> uncheckBiFunction(CheckedBiFunction<T, U, R, ?> function)
534 	{
535 		return (BiFunction<T, U, R> & Serializable) (t, u) -> Exceptional.apply(function, t, u);
536 	}
537 
538 
539 	/**
540 	 * Invokes {@link CheckedFunction#apply(Object)} catching any checked
541 	 * {@link Exception}s rethrowing as unchecked.
542 	 * 
543 	 * @param <T> first argument type
544 	 * @param <U> last argument type
545 	 * @param <R> return type
546 	 * 
547 	 * @param function the checked function to invoke with the {@code argument}
548 	 * @param t the first argument to apply to the function
549 	 * @param u the second argument to apply to the function
550 	 * @return the result of applying {@code function} to the arguments {@code t} and {@code u}
551 	 * 
552 	 * @since 0.2.0
553 	 */
554 	public static <T, U, R> R apply(CheckedBiFunction<T, U, R, ?> function, T t, U u)
555 	{
556 		try {
557 			return function.apply(t, u);
558 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
559 			throw error;
560 		} catch(Throwable thrown) {
561 			throw uncheck(thrown);
562 		}
563 	}
564 
565 
566 	/**
567 	 * Converts a {@link CheckedBinaryOperator} into a {@link BinaryOperator}.
568 	 * 
569 	 * @param <T> operator type
570 	 * 
571 	 * @param operator the checked binary operator
572 	 * @return and unchecked wrapper around the {@code operator} argument
573 	 * 
574 	 * @since 0.2.0
575 	 */
576 	@SuppressWarnings("unchecked")
577 	public static <T> BinaryOperator<T> uncheckBinaryOperator(CheckedBinaryOperator<T, ?> operator)
578 	{
579 		return (BinaryOperator<T> & Serializable) (a, b) -> Exceptional.apply(operator, a, b);
580 	}
581 
582 
583 	/**
584 	 * Converts a {@link CheckedToDoubleFunction} into a {@link ToDoubleFunction}.
585 	 * 
586 	 * @param <T> argument type
587 	 * 
588 	 * @param function the checked to-double-function
589 	 * @return an unchecked to-double-function wrapping the {@code function} argument.
590 	 * 
591 	 * @since 0.2.0
592 	 */
593 	@SuppressWarnings("unchecked")
594 	public static <T> ToDoubleFunction<T> uncheckToDoubleFunction(CheckedToDoubleFunction<T, ?> function)
595 	{
596 		return (ToDoubleFunction<T> & Serializable) t -> Exceptional.applyAsDouble(function, t);
597 	}
598 
599 
600 	/**
601 	 * Invokes {@link CheckedToDoubleFunction#applyAsDouble(Object)} catching any checked
602 	 * {@link Exception}s rethrowing as unchecked.
603 	 * 
604 	 * @param <T> argument type
605 	 * 
606 	 * @param function the checked to-double function
607 	 * @param t the function argument
608 	 * @return the double result of applying the {@code function} to argument {@code t}
609 	 * 
610 	 * @since 0.2.0
611 	 */
612 	public static <T> double applyAsDouble(CheckedToDoubleFunction<T, ?> function, T t)
613 	{
614 		try {
615 			return function.applyAsDouble(t);
616 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
617 			throw error;
618 		} catch(Throwable thrown) {
619 			throw uncheck(thrown);
620 		}
621 	}
622 
623 
624 	/**
625 	 * Converts a {@link CheckedToIntFunction} into a {@link ToIntFunction}.
626 	 * 
627 	 * @param <T> argument type
628 	 * 
629 	 * @param function the checked to-int-function
630 	 * @return an unchecked to-int-function wrapping the {@code function} argument.
631 	 * 
632 	 * @since 0.2.0
633 	 */
634 	@SuppressWarnings("unchecked")
635 	public static <T> ToIntFunction<T> uncheckToIntFunction(CheckedToIntFunction<T, ?> function)
636 	{
637 		return (ToIntFunction<T> & Serializable) t -> Exceptional.applyAsInt(function, t);
638 	}
639 
640 
641 	/**
642 	 * Invokes {@link CheckedToIntFunction#applyAsInt(Object)} catching any checked
643 	 * {@link Exception}s rethrowing as unchecked.
644 	 * 
645 	 * @param <T> argument type
646 	 * 
647 	 * @param function the checked to-int function
648 	 * @param t the function argument
649 	 * @return the int result of applying the {@code function} to argument {@code t}
650 	 * 
651 	 * @since 0.2.0
652 	 */
653 	public static <T> int applyAsInt(CheckedToIntFunction<T, ?> function, T t)
654 	{
655 		try {
656 			return function.applyAsInt(t);
657 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
658 			throw error;
659 		} catch(Throwable thrown) {
660 			throw uncheck(thrown);
661 		}
662 	}
663 
664 
665 	/**
666 	 * Converts a {@link CheckedToLongFunction} into a {@link ToLongFunction}.
667 	 * 
668 	 * @param <T> argument type
669 	 * 
670 	 * @param function the checked to-long-function
671 	 * @return an unchecked to-long-function wrapping the {@code function} argument.
672 	 * 
673 	 * @since 0.2.0
674 	 */
675 	@SuppressWarnings("unchecked")
676 	public static <T> ToLongFunction<T> uncheckToLongFunction(CheckedToLongFunction<T, ?> function)
677 	{
678 		return (ToLongFunction<T> & Serializable) t -> Exceptional.applyAsLong(function, t);
679 	}
680 
681 
682 	/**
683 	 * Invokes {@link CheckedToLongFunction#applyAsLong(Object)} catching any checked
684 	 * {@link Exception}s rethrowing as unchecked.
685 	 * 
686 	 * @param <T> argument type
687 	 * 
688 	 * @param function the checked to-long function
689 	 * @param t the function argument
690 	 * @return the long result of applying the {@code function} to argument {@code t}
691 	 * 
692 	 * @since 0.2.0
693 	 */
694 	public static <T> long applyAsLong(CheckedToLongFunction<T, ?> function, T t)
695 	{
696 		try {
697 			return function.applyAsLong(t);
698 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
699 			throw error;
700 		} catch(Throwable thrown) {
701 			throw uncheck(thrown);
702 		}
703 	}
704 
705 
706 	/**
707 	 * Convert a {@link CheckedSupplier} into an unchecked {@link Supplier}.
708 	 * 
709 	 * @param <T> supplied type
710 	 * 
711 	 * @param supplier the checked supplier to wrap
712 	 * @return an unchecked supplier wrapping the {@code supplier} argument
713 	 * 
714 	 * @since 0.2.0
715 	 */
716 	@SuppressWarnings("unchecked")
717 	public static <T> Supplier<T> uncheckSupplier(CheckedSupplier<T, ?> supplier)
718 	{
719 		return (Supplier<T> & Serializable) () -> Exceptional.get(supplier);
720 	}
721 
722 
723 	/**
724 	 * Invokes {@link CheckedSupplier#get()} catching any checked
725 	 * {@link Exception}s rethrowing as unchecked.
726 	 * 
727 	 * @param <T> supplied type
728 	 * 
729 	 * @param supplier the checked supplier
730 	 * @return the result as supplied from the {@code supplier} argument
731 	 * 
732 	 * @since 0.2.0
733 	 */
734 	public static <T> T get(CheckedSupplier<T, ?> supplier)
735 	{
736 		try {
737 			return supplier.get();
738 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
739 			throw error;
740 		} catch(Throwable thrown) {
741 			throw uncheck(thrown);
742 		}
743 	}
744 
745 
746 	/**
747 	 * Converts a {@link CheckedPredicate} into a {@link Predicate}.
748 	 * 
749 	 * @param <T> tested type
750 	 * 
751 	 * @param predicate the checked predicate to wrap
752 	 * @return an unchecked predicate wrapping the {@code predicate} argument
753 	 * 
754 	 * @since 0.2.0
755 	 */
756 	@SuppressWarnings("unchecked")
757 	public static <T> Predicate<T> uncheckPredicate(CheckedPredicate<T, ?> predicate)
758 	{
759 		return (Predicate<T> & Serializable) t -> Exceptional.test(predicate, t);
760 	}
761 
762 
763 	/**
764 	 * Invokes {@link CheckedPredicate#test(Object)} catching any checked
765 	 * {@link Exception}s rethrowing as unchecked.
766 	 * 
767 	 * @param <T> tested type
768 	 * 
769 	 * @param predicate the checked predicate to test on the {@code value}
770 	 * @param value the value to be tested
771 	 * @return true IFF value passes predicate's test
772 	 * 
773 	 * @since 0.2.0
774 	 */
775 	public static <T> boolean test(CheckedPredicate<T, ?> predicate, T value)
776 	{
777 		try {
778 			return predicate.test(value);
779 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
780 			throw error;
781 		} catch(Throwable thrown) {
782 			throw uncheck(thrown);
783 		}
784 	}
785 
786 
787 	/**
788 	 * Converts a {@link CheckedComparator} into an unchecked {@link Comparator}.
789 	 * 
790 	 * @param <T> compared type
791 	 * 
792 	 * @param comparator the checked comparator to wrap
793 	 * @return an unchecked comparator wrapping the {@code comparator} argument
794 	 * 
795 	 * @since 0.2.0
796 	 */
797 	@SuppressWarnings("unchecked")
798 	public static <T> Comparator<T> uncheckComparator(CheckedComparator<T, ?> comparator)
799 	{
800 		return (Comparator<T> & Serializable) (a, b) -> Exceptional.applyAsInt(comparator, a, b);
801 	}
802 
803 
804 	/**
805 	 * Converts a {@link CheckedToIntBiFunction} into an unchecked {@link ToIntBiFunction}.
806 	 * 
807 	 * @param <T> first argument type
808 	 * @param <U> last argument type
809 	 * 
810 	 * @param function the checked bi-function
811 	 * @return an unchecked bi-function
812 	 */
813 	@SuppressWarnings("unchecked")
814 	public static <T, U> ToIntBiFunction<T, U> uncheckToIntBiFunction(CheckedToIntBiFunction<T, U, ?> function)
815 	{
816 		return (ToIntBiFunction<T, U> & Serializable) (a, b) -> Exceptional.applyAsInt(function, a, b);
817 	}
818 
819 
820 	/**
821 	 * Invokes {@link CheckedFunction#apply(Object)} catching any checked
822 	 * {@link Exception}s rethrowing as unchecked.
823 	 * 
824 	 * @param <T> first argument type
825 	 * @param <U> last argument type
826 	 * 
827 	 * @param function the checked function to invoke with the {@code argument}
828 	 * @param t the first argument to apply to the function
829 	 * @param u the second argument to apply to the function
830 	 * @return the result of applying {@code function} to the arguments {@code t} and {@code u}
831 	 * 
832 	 * @since 0.2.0
833 	 */
834 	public static <T, U> int applyAsInt(CheckedToIntBiFunction<T, U, ?> function, T t, U u)
835 	{
836 		try {
837 			return function.applyAsInt(t, u);
838 		} catch(Error error) {  // repeated tedious (likewise with tests) as Jacoco does not add enough probes
839 			throw error;
840 		} catch(Throwable thrown) {
841 			throw uncheck(thrown);
842 		}
843 	}
844 
845 
846 	/**
847 	 * <p>
848 	 * This fugly method relies on erasure to trick the compiler, allowing you to throw any checked
849 	 * exception without declaring so on the surrounding method. You are almost certainly better off
850 	 * using {@link #rethrow(Throwable)}.
851 	 * </p>
852 	 * <p>
853 	 * <b>Note</b>: this may well become an obsolete hack in future versions of Java if generics change.
854 	 * </p>
855 	 * 
856 	 * @param throwable the {@link Throwable} to be thrown
857 	 * @return this alleged return will never be received, but useful in that
858 	 * you may write <code>throws {@link Exceptional#throwAsUnchecked(Throwable)};</code>
859 	 * to placate the compiler WRT non-void method returns, and ensure Static Code
860 	 * Analysis doesn't accuse you of swallowing the exception.
861 	 * 
862 	 * @since 0.2.0
863 	 * 
864 	 * @see #rethrow(Throwable)
865 	 */
866 	public static RuntimeException throwAsUnchecked(Throwable throwable)
867 	{
868 		resetIfInterrupt(throwable);
869 		return Exceptional.<RuntimeException> eraseAndThrow(throwable);
870 	}
871 
872 
873 	@SuppressWarnings("unchecked")
874 	private static <T extends Throwable> RuntimeException eraseAndThrow(Throwable throwable) throws T
875 	{
876 		throw (T) throwable;
877 	}
878 
879 
880 	/**
881 	 * <p>
882 	 * Attempts to unwrap invocation and unchecked exceptions to their underlying cause.
883 	 * Unwrapping is recursively applied. The original wrapper exception is added to the suppressed
884 	 * throwables of the returned unwrapped throwable.
885 	 * </p>
886 	 * 
887 	 * <p>
888 	 * Unwraps: {@link InvocationTargetException}, {@link UndeclaredThrowableException}, {@link UncheckedIOException}
889 	 * and {@link UncheckedException}
890 	 * </p>
891 	 * 
892 	 * @param throwable to be unwrapped
893 	 * @return the root cause, or original throwable if not unwrapped
894 	 * 
895 	 * @since 0.2.0
896 	 * 
897 	 */
898 	public static Throwable unwrap(Throwable throwable)
899 	{
900 		Throwable unwrapped = unwrapping(throwable);
901 		if(unwrapped != throwable) {
902 			unwrapped.addSuppressed(throwable);
903 		}
904 		return unwrapped;
905 	}
906 
907 
908 	private static Throwable unwrapping(Throwable throwable)
909 	{
910 		Set<Throwable> seen = new HashSet<>();
911 		while(isUnwrappable(throwable) && !seen.contains(throwable)) {
912 			seen.add(throwable);
913 			throwable = throwable.getCause();
914 		}
915 		return throwable;
916 	}
917 
918 
919 	private static boolean isUnwrappable(Throwable throwable)
920 	{
921 		return throwable.getCause() != null
922 				&& (throwable instanceof InvocationTargetException
923 						|| throwable instanceof UndeclaredThrowableException
924 						|| throwable instanceof UncheckedIOException
925 						|| throwable instanceof UncheckedException);
926 	}
927 
928 
929 	/**
930 	 * <p>
931 	 * Recursively find the wrapped throwable
932 	 * </p>
933 	 * 
934 	 * <b>NOTE</b>: this method now just delegates to {@link #unwrap(Throwable)} and is therefore superfluous,
935 	 * as such it will be removed in the next major release without impact to client code; given
936 	 * this, it is not marked {@link Deprecated} to avoid unnecessary upcasting to {@link Throwable}.
937 	 *
938 	 * @param throwable to be unwrapped
939 	 * @return the value of {@link UndeclaredThrowableException#getUndeclaredThrowable()}
940 	 * 
941 	 * @since 0.2.0
942 	 * 
943 	 * @see #unwrap(Throwable)
944 	 */
945 	public static Throwable unwrap(UndeclaredThrowableException throwable)
946 	{
947 		return unwrap((Throwable) throwable);
948 	}
949 
950 
951 	/**
952 	 * <p>
953 	 * Recursively find the wrapped throwable
954 	 * </p>
955 	 * 
956 	 * <b>NOTE</b>: this method now just delegates to {@link #unwrap(Throwable)} and is therefore superfluous,
957 	 * as such it will be removed in the next major release without impact to client code; given
958 	 * this, it is not marked {@link Deprecated} to avoid unnecessary upcasting to {@link Throwable}.
959 	 *
960 	 * @param throwable to be unwrapped
961 	 * @return the value of {@link InvocationTargetException#getTargetException()}
962 	 * 
963 	 * @since 0.2.0
964 	 */
965 	public static Throwable unwrap(InvocationTargetException throwable)
966 	{
967 		return unwrap((Throwable) throwable);
968 	}
969 
970 
971 	/**
972 	 * Invokes the {@link Iterable#forEach(Consumer)} method having unchecked the consumer
973 	 * 
974 	 * @param <T> the consumed {@link Iterable}'s element type
975 	 * 
976 	 * @param iterable the Iterable to consume each element of
977 	 * @param consumer the checked consumer of the Iterable's elements
978 	 * 
979 	 * @since 0.4.0
980 	 * 
981 	 * @see #uncheckConsumer(CheckedConsumer)
982 	 */
983 	public static <T> void forEach(Iterable<T> iterable, CheckedConsumer<T, ?> consumer)
984 	{
985 		iterable.forEach(uncheckConsumer(consumer));
986 	}
987 
988 
989 	/**
990 	 * Invokes the {@link Map#forEach(BiConsumer)} method having unchecked the bi-consumer
991 	 * 
992 	 * @param <K> the consumed {@link Map}'s key type
993 	 * @param <V> the consumed {@link Map}'s value type
994 	 * 
995 	 * @param map the entries to consume
996 	 * @param consumer the consumer of the map's key value pairs
997 	 * 
998 	 * @since 0.4.0
999 	 * 
1000 	 * @see #uncheckBiConsumer(CheckedBiConsumer)
1001 	 */
1002 	public static <K, V> void forEach(Map<K, V> map, CheckedBiConsumer<K, V, ?> consumer)
1003 	{
1004 		map.forEach(uncheckBiConsumer(consumer));
1005 	}
1006 }