/** * Always run the given action, works like a finally clause. * * @param action Finally action. * @return This try result. */ public Try onComplete(Throwing.Runnable action) { try { action.run(); return this; } catch (Throwable x) { return Try.failure(x); } }
/** * In case of failure unwrap the exception provided by calling {@link Throwable#getCause()}. * Useful for clean/shorter stackstrace. * * Example for {@link java.lang.reflect.InvocationTargetException}: * * <pre>{@code * Try.run(() -> { * Method m = ...; * m.invoke(...); //might throw InvocationTargetException * }).unwrap(InvocationTargetException.class::isInstance) * .throwException(); * }</pre> * * @param predicate Exception filter. * @return This try for success or a new failure with exception unwrap. */ public Try unwrap(Throwing.Predicate<Throwable> predicate) { try { return getCause() .filter(predicate) .map(Throwable::getCause) .filter(Objects::nonNull) .map(x -> (Try) Try.failure(x)) .orElse(this); } catch (Throwable x) { return failure(x); } }
/** * In case of failure wrap an exception matching the given predicate to something else. * * @param predicate Exception predicate. * @param wrapper Exception mapper. * @param <X> Exception type. * @return This try for success or a new failure with exception wrapped. */ public <X extends Throwable> Try wrap(Throwing.Predicate<X> predicate, Throwing.Function<X, Throwable> wrapper) { try { return getCause() .filter(x -> predicate.test((X) x)) .map(x -> (Try) Try.failure(wrapper.apply((X) x))) .orElse(this); } catch (Throwable x) { return failure(x); } }
/** * Always run the given action, works like a finally clause. Exception will be null in case of success. * * @param action Finally action. * @return This try result. */ public Try onComplete(Throwing.Consumer<Throwable> action) { try { action.accept(getCause().orElse(null)); return this; } catch (Throwable x) { return Try.failure(x); } }