/** * Recover from failure if and only if the exception is a subclass of the given exception filter. * The recover function will be executed in case of failure. * * @param exception Exception filter. * @param fn Recover function. * @param <X> Exception type. * @return This try on success, a new success try from recover or a failure try in case of exception. */ public <X extends Throwable> Value<V> recoverWith(Class<X> exception, Throwing.Function<X, Value<V>> fn) { return (Value<V>) getCause() .filter(exception::isInstance) .map(x -> { try { return fn.apply((X) x); } catch (Throwable ex) { return failure(ex); } }) .orElse(this); }
/** * Always run the given action, works like a finally clause. Exception and value might be null. * Exception will be null in case of success. * * @param action Finally action. * @return This try result. */ public Value<V> onComplete(final Throwing.Consumer2<V, Throwable> action) { try { V value = isSuccess() ? get() : null; action.accept(value, getCause().orElse(null)); return this; } catch (Throwable x) { return (Value<V>) failure(x); } }