/** * Singleton version of this supplier. * * @return A memo function. */ default Supplier<V> singleton() { if (this instanceof Memoized) { return this; } AtomicReference<V> ref = new AtomicReference<>(); return (Supplier<V> & Memoized) () -> { if (ref.get() == null) { ref.set(tryGet()); } return ref.get(); }; } }
private static <V, X extends Throwable> V fnOnFailure(Supplier<V> fn, Class<? extends X> type, java.util.function.Consumer<X> consumer) { try { return fn.tryGet(); } catch (Throwable x) { if (type.isInstance(x)) { consumer.accept(type.cast(x)); } throw sneakyThrow(x); } }
private static <V, X extends Throwable> V fnUnwrap(Supplier<V> fn, Class<? extends X> type) { try { return fn.tryGet(); } catch (Throwable x) { if (isFatal(x)) { throw sneakyThrow(x); } Throwable t = x; if (type.isInstance(x)) { t = Optional.ofNullable(x.getCause()).orElse(x); } throw sneakyThrow(t); } }
private static <R, X extends Throwable> R fnRecover(Supplier<R> fn, Class<? extends X> type, java.util.function.Function<X, R> recover) { try { return fn.tryGet(); } catch (Throwable x) { if (isFatal(x)) { throw sneakyThrow(x); } if (type.isInstance(x)) { return recover.apply(type.cast(x)); } throw sneakyThrow(x); } }
private static <V> V fnWrap(Supplier<V> fn, java.util.function.Function<Throwable, Exception> wrapper) { try { return fn.tryGet(); } catch (Throwable x) { if (isFatal(x)) { throw sneakyThrow(x); } throw sneakyThrow(wrapper.apply(x)); } }
private static <R> R fn(Supplier<R> fn, Supplier<R> orElse) { try { return fn.tryGet(); } catch (Throwable x) { if (isFatal(x)) { throw sneakyThrow(x); } return orElse.get(); } }
/** * Apply this function and unwrap any resulting exception. Useful to get clean/shorter stacktrace. * * @param type Exception to unwrap. * @param <X> Exception type. * @return A new function. */ default <X extends Throwable> Supplier<V> unwrap(Class<? extends X> type) { return () -> fnUnwrap(() -> tryGet(), type); }
private static <V> V fn(Supplier<V> fn) { try { return fn.tryGet(); } catch (Throwable x) { throw sneakyThrow(x); } }
/** * Apply this function and wrap any resulting exception. * * @param wrapper Exception wrapper. * @return A new function. */ default Supplier<V> wrap(java.util.function.Function<Throwable, Exception> wrapper) { return () -> fnWrap(() -> tryGet(), wrapper); }
/** * Apply this function and returns the given default value in case of exception. * * @param defaultValue Exceptional default value. * @return A new function. */ default Supplier<V> orElse(Supplier<V> defaultValue) { return () -> fn(() -> tryGet(), defaultValue); }
/** * Apply this function or recover from a specific exception in case of exception. * * @param type Exception filter. * @param fn Exception recover. * @param <X> Exception type. * @return A new function. */ default <X extends Throwable> Supplier<V> recover(Class<? extends X> type, java.util.function.Function<X, V> fn) { return () -> fnRecover(() -> tryGet(), type, fn); }
/** * * Apply this function and run the given action in case of exception. * * @param type Exception filter. * @param action Action to run when exception occurs. * @param <X> Exception type. * @return A new function. */ default <X extends Throwable> Supplier<V> onFailure(Class<X> type, java.util.function.Consumer<X> action) { return () -> fnOnFailure(() -> tryGet(), type, action); }