/* __ __ __ __ __ ___
* \ \ / / \ \ / / __/
* \ \/ / /\ \ \/ / /
* \____/__/ \__\____/__/.ɪᴏ
* ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ
*/
package io.vavr.control;
import io.vavr.*;
import io.vavr.collection.Seq;
import io.vavr.collection.Iterator;
import io.vavr.collection.Vector;
import java.io.Serializable;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import static io.vavr.API.Match;
import static io.vavr.control.TryModule.isFatal;
import static io.vavr.control.TryModule.sneakyThrow;
/**
* The Try control gives us the ability write safe code without focusing on try-catch blocks in the presence of exceptions.
* <p>
* The following exceptions are considered to be fatal/non-recoverable:
* <ul>
* <li>{@linkplain InterruptedException}</li>
* <li>{@linkplain LinkageError}</li>
* <li>{@linkplain ThreadDeath}</li>
* <li>{@linkplain VirtualMachineError} (i.e. {@linkplain OutOfMemoryError} or {@linkplain StackOverflowError})</li>
* </ul>
* <p>
* <strong>Important note:</strong> Try may re-throw (undeclared) exceptions, e.g. on {@code get()}. From within a
* dynamic proxy {@link java.lang.reflect.InvocationHandler} this will lead to an
* {@link java.lang.reflect.UndeclaredThrowableException}. For more information, please read
* <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/proxy.html">Dynamic Proxy Classes</a>.
*
* @param <T> Value type in the case of success.
* @author Daniel Dietrich
*/
public interface Try<T> extends Value<T>, Serializable {
long serialVersionUID = 1L;
/**
* Creates a Try of a CheckedFunction0.
*
* @param supplier A checked supplier
* @param <T> Component type
* @return {@code Success(supplier.apply())} if no exception occurs, otherwise {@code Failure(throwable)} if an
* exception occurs calling {@code supplier.apply()}.
*/
static <T> Try<T> of(CheckedFunction0<? extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
try {
return new Success<>(supplier.apply());
} catch (Throwable t) {
return new Failure<>(t);
}
}
/**
* Creates a Try of a Supplier.
*
* @param supplier A supplier
* @param <T> Component type
* @return {@code Success(supplier.get())} if no exception occurs, otherwise {@code Failure(throwable)} if an
* exception occurs calling {@code supplier.get()}.
*/
static <T> Try<T> ofSupplier(Supplier<? extends T> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return of(supplier::get);
}
/**
* Creates a Try of a Callable.
*
* @param callable A callable
* @param <T> Component type
* @return {@code Success(callable.call())} if no exception occurs, otherwise {@code Failure(throwable)} if an
* exception occurs calling {@code callable.call()}.
*/
static <T> Try<T> ofCallable(Callable<? extends T> callable) {
Objects.requireNonNull(callable, "callable is null");
return of(callable::call);
}
/**
* Creates a Try of a CheckedRunnable.
*
* @param runnable A checked runnable
* @return {@code Success(null)} if no exception occurs, otherwise {@code Failure(throwable)} if an exception occurs
* calling {@code runnable.run()}.
*/
static Try<Void> run(CheckedRunnable runnable) {
Objects.requireNonNull(runnable, "runnable is null");
try {
runnable.run();
return new Success<>(null); // null represents the absence of an value, i.e. Void
} catch (Throwable t) {
return new Failure<>(t);
}
}
/**
* Creates a Try of a Runnable.
*
* @param runnable A runnable
* @return {@code Success(null)} if no exception occurs, otherwise {@code Failure(throwable)} if an exception occurs
* calling {@code runnable.run()}.
*/
static Try<Void> runRunnable(Runnable runnable) {
Objects.requireNonNull(runnable, "runnable is null");
return run(runnable::run);
}
/**
* Reduces many {@code Try}s into a single {@code Try} by transforming an
* {@code Iterable<Try<? extends T>>} into a {@code Try<Seq<T>>}. If any of
* the {@code Try}s are {@link Try.Failure}, then this returns a {@link Try.Failure}.
*
* @param values An {@link Iterable} of {@code Try}s
* @param <T> type of the Trys
* @return A {@code Try} of a {@link Seq} of results
* @throws NullPointerException if {@code values} is null
*/
static <T> Try<Seq<T>> sequence(Iterable<? extends Try<? extends T>> values) {
Objects.requireNonNull(values, "values is null");
Vector<T> vector = Vector.empty();
for (Try<? extends T> value : values) {
if (value.isFailure()) {
return Try.failure(value.getCause());
}
vector = vector.append(value.get());
}
return Try.success(vector);
}
/**
* Creates a {@link Success} that contains the given {@code value}. Shortcut for {@code new Success<>(value)}.
*
* @param value A value.
* @param <T> Type of the given {@code value}.
* @return A new {@code Success}.
*/
static <T> Try<T> success(T value) {
return new Success<>(value);
}
/**
* Creates a {@link Failure} that contains the given {@code exception}. Shortcut for {@code new Failure<>(exception)}.
*
* @param exception An exception.
* @param <T> Component type of the {@code Try}.
* @return A new {@code Failure}.
*/
static <T> Try<T> failure(Throwable exception) {
return new Failure<>(exception);
}
/**
* Narrows a widened {@code Try<? extends T>} to {@code Try<T>}
* by performing a type-safe cast. This is eligible because immutable/read-only
* collections are covariant.
*
* @param t A {@code Try}.
* @param <T> Component type of the {@code Try}.
* @return the given {@code t} instance as narrowed type {@code Try<T>}.
*/
@SuppressWarnings("unchecked")
static <T> Try<T> narrow(Try<? extends T> t) {
return (Try<T>) t;
}
/**
* Shortcut for {@code andThenTry(consumer::accept)}, see {@link #andThenTry(CheckedConsumer)}.
*
* @param consumer A consumer
* @return this {@code Try} if this is a {@code Failure} or the consumer succeeded, otherwise the
* {@code Failure} of the consumption.
* @throws NullPointerException if {@code consumer} is null
*/
default Try<T> andThen(Consumer<? super T> consumer) {
Objects.requireNonNull(consumer, "consumer is null");
return andThenTry(consumer::accept);
}
/**
* Passes the result to the given {@code consumer} if this is a {@code Success}.
* <p>
* The main use case is chaining checked functions using method references:
*
* <pre>
* <code>
* Try.of(() -> 100)
* .andThen(i -> System.out.println(i));
*
* </code>
* </pre>
*
* @param consumer A checked consumer
* @return this {@code Try} if this is a {@code Failure} or the consumer succeeded, otherwise the
* {@code Failure} of the consumption.
* @throws NullPointerException if {@code consumer} is null
*/
default Try<T> andThenTry(CheckedConsumer<? super T> consumer) {
Objects.requireNonNull(consumer, "consumer is null");
if (isFailure()) {
return this;
} else {
try {
consumer.accept(get());
return this;
} catch (Throwable t) {
return new Failure<>(t);
}
}
}
/**
* Shortcut for {@code andThenTry(runnable::run)}, see {@link #andThenTry(CheckedRunnable)}.
*
* @param runnable A runnable
* @return this {@code Try} if this is a {@code Failure} or the runnable succeeded, otherwise the
* {@code Failure} of the run.
* @throws NullPointerException if {@code runnable} is null
*/
default Try<T> andThen(Runnable runnable) {
Objects.requireNonNull(runnable, "runnable is null");
return andThenTry(runnable::run);
}
/**
* Runs the given runnable if this is a {@code Success}, otherwise returns this {@code Failure}.
* <p>
* The main use case is chaining runnables using method references:
*
* <pre>
* <code>
* Try.run(A::methodRef).andThen(B::methodRef).andThen(C::methodRef);
* </code>
* </pre>
*
* Please note that these lines are semantically the same:
*
* <pre>
* <code>
* Try.run(this::doStuff)
* .andThen(this::doMoreStuff)
* .andThen(this::doEvenMoreStuff);
*
* Try.run(() -> {
* doStuff();
* doMoreStuff();
* doEvenMoreStuff();
* });
* </code>
* </pre>
*
* @param runnable A checked runnable
* @return this {@code Try} if this is a {@code Failure} or the runnable succeeded, otherwise the
* {@code Failure} of the run.
* @throws NullPointerException if {@code runnable} is null
*/
default Try<T> andThenTry(CheckedRunnable runnable) {
Objects.requireNonNull(runnable, "runnable is null");
if (isFailure()) {
return this;
} else {
try {
runnable.run();
return this;
} catch (Throwable t) {
return new Failure<>(t);
}
}
}
/**
* Collects value that is in the domain of the given {@code partialFunction} by mapping the value to type {@code R}.
*
* <pre>{@code
* partialFunction.isDefinedAt(value)
* }</pre>
*
* If the element makes it through that filter, the mapped instance is wrapped in {@code Try}
*
* <pre>{@code
* R newValue = partialFunction.apply(value)
* }</pre>
*
*
* @param partialFunction A function that is not necessarily defined on value of this try.
* @param <R> The new value type
* @return A new {@code Try} instance containing value of type {@code R}
* @throws NullPointerException if {@code partialFunction} is null
*/
@SuppressWarnings("unchecked")
default <R> Try<R> collect(PartialFunction<? super T, ? extends R> partialFunction){
Objects.requireNonNull(partialFunction, "partialFunction is null");
return filter(partialFunction::isDefinedAt).map(partialFunction::apply);
}
/**
* Returns {@code Success(throwable)} if this is a {@code Failure(throwable)}, otherwise
* a {@code Failure(new NoSuchElementException("Success.failed()"))} if this is a Success.
*
* @return a new Try
*/
default Try<Throwable> failed() {
if (isFailure()) {
return new Success<>(getCause());
} else {
return new Failure<>(new NoSuchElementException("Success.failed()"));
}
}
/**
* Shortcut for {@code filterTry(predicate::test, throwableSupplier)}, see
* {@link #filterTry(CheckedPredicate, Supplier)}}.
*
* @param predicate A predicate
* @param throwableSupplier A supplier of a throwable
* @return a {@code Try} instance
* @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is null
*/
default Try<T> filter(Predicate<? super T> predicate, Supplier<? extends Throwable> throwableSupplier) {
Objects.requireNonNull(predicate, "predicate is null");
Objects.requireNonNull(throwableSupplier, "throwableSupplier is null");
return filterTry(predicate::test, throwableSupplier);
}
/**
* Shortcut for {@code filterTry(predicate::test, errorProvider::apply)}, see
* {@link #filterTry(CheckedPredicate, CheckedFunction1)}}.
*
* @param predicate A predicate
* @param errorProvider A function that provides some kind of Throwable for T
* @return a {@code Try} instance
* @throws NullPointerException if {@code predicate} or {@code errorProvider} is null
*/
default Try<T> filter(Predicate<? super T> predicate, Function<? super T, ? extends Throwable> errorProvider) {
Objects.requireNonNull(predicate, "predicate is null");
Objects.requireNonNull(errorProvider, "errorProvider is null");
return filterTry(predicate::test, errorProvider::apply);
}
/**
* Shortcut for {@code filterTry(predicate::test)}, see {@link #filterTry(CheckedPredicate)}}.
*
* @param predicate A predicate
* @return a {@code Try} instance
* @throws NullPointerException if {@code predicate} is null
*/
default Try<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return filterTry(predicate::test);
}
/**
* Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate.
* <p>
* Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception
* occurs testing the predicate. The returned Failure wraps a Throwable instance provided by the given
* {@code throwableSupplier}.
*
* @param predicate A checked predicate
* @param throwableSupplier A supplier of a throwable
* @return a {@code Try} instance
* @throws NullPointerException if {@code predicate} or {@code throwableSupplier} is null
*/
default Try<T> filterTry(CheckedPredicate<? super T> predicate, Supplier<? extends Throwable> throwableSupplier) {
Objects.requireNonNull(predicate, "predicate is null");
Objects.requireNonNull(throwableSupplier, "throwableSupplier is null");
if (isFailure()) {
return this;
} else {
try {
if (predicate.test(get())) {
return this;
} else {
return new Failure<>(throwableSupplier.get());
}
} catch (Throwable t) {
return new Failure<>(t);
}
}
}
/**
* Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate.
* <p>
* Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception
* occurs testing the predicate. The returned Failure wraps a Throwable instance provided by the given
* {@code errorProvider}.
*
* @param predicate A checked predicate
* @param errorProvider A provider of a throwable
* @return a {@code Try} instance
* @throws NullPointerException if {@code predicate} or {@code errorProvider} is null
*/
default Try<T> filterTry(CheckedPredicate<? super T> predicate, CheckedFunction1<? super T, ? extends Throwable> errorProvider) {
Objects.requireNonNull(predicate, "predicate is null");
Objects.requireNonNull(errorProvider, "errorProvider is null");
return flatMapTry(t -> predicate.test(t) ? this : failure(errorProvider.apply(t)));
}
/**
* Returns {@code this} if this is a Failure or this is a Success and the value satisfies the predicate.
* <p>
* Returns a new Failure, if this is a Success and the value does not satisfy the Predicate or an exception
* occurs testing the predicate. The returned Failure wraps a {@link NoSuchElementException} instance.
*
* @param predicate A checked predicate
* @return a {@code Try} instance
* @throws NullPointerException if {@code predicate} is null
*/
default Try<T> filterTry(CheckedPredicate<? super T> predicate) {
Objects.requireNonNull(predicate, "predicate is null");
return filterTry(predicate, () -> new NoSuchElementException("Predicate does not hold for " + get()));
}
/**
* Shortcut for {@code flatMapTry(mapper::apply)}, see {@link #flatMapTry(CheckedFunction1)}.
*
* @param mapper A mapper
* @param <U> The new component type
* @return a {@code Try}
* @throws NullPointerException if {@code mapper} is null
*/
default <U> Try<U> flatMap(Function<? super T, ? extends Try<? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return flatMapTry((CheckedFunction1<T, Try<? extends U>>) mapper::apply);
}
/**
* FlatMaps the value of a Success or returns a Failure.
*
* @param mapper A mapper
* @param <U> The new component type
* @return a {@code Try}
* @throws NullPointerException if {@code mapper} is null
*/
@SuppressWarnings("unchecked")
default <U> Try<U> flatMapTry(CheckedFunction1<? super T, ? extends Try<? extends U>> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (isFailure()) {
return (Failure<U>) this;
} else {
try {
return (Try<U>) mapper.apply(get());
} catch (Throwable t) {
return new Failure<>(t);
}
}
}
/**
* Gets the result of this Try if this is a {@code Success} or throws if this is a {@code Failure}.
* <p>
* <strong>IMPORTANT! If this is a {@link Failure}, the underlying {@code cause} of type {@link Throwable} is thrown.</strong>
* <p>
* The thrown exception is exactly the same as the result of {@link #getCause()}.
*
* @return The result of this {@code Try}.
*/
@Override
T get();
/**
* Gets the cause if this is a Failure or throws if this is a Success.
*
* @return The cause if this is a Failure
* @throws UnsupportedOperationException if this is a Success
*/
Throwable getCause();
/**
* A {@code Try}'s value is computed synchronously.
*
* @return false
*/
@Override
default boolean isAsync() {
return false;
}
/**
* Checks whether this Try has no result, i.e. is a Failure.
*
* @return true if this is a Failure, returns false if this is a Success.
*/
@Override
boolean isEmpty();
/**
* Checks if this is a Failure.
*
* @return true, if this is a Failure, otherwise false, if this is a Success
*/
boolean isFailure();
/**
* A {@code Try}'s value is computed eagerly.
*
* @return false
*/
@Override
default boolean isLazy() {
return false;
}
/**
* A {@code Try} is a single-valued.
*
* @return {@code true}
*/
@Override
default boolean isSingleValued() {
return true;
}
/**
* Checks if this is a Success.
*
* @return true, if this is a Success, otherwise false, if this is a Failure
*/
boolean isSuccess();
@Override
default Iterator<T> iterator() {
return isSuccess() ? Iterator.of(get()) : Iterator.empty();
}
/**
* Shortcut for {@code mapTry(mapper::apply)}, see {@link #mapTry(CheckedFunction1)}.
*
* @param <U> The new component type
* @param mapper A checked function
* @return a {@code Try}
* @throws NullPointerException if {@code mapper} is null
*/
@Override
default <U> Try<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return mapTry(mapper::apply);
}
/**
* Maps the cause to a new exception if this is a {@code Failure} or returns this instance if this is a {@code Success}.
* <p>
* If none of the given cases matches the cause, the same {@code Failure} is returned.
*
* @param cases A not necessarily exhaustive sequence of cases that will be matched against a cause.
* @return A new {@code Try} if this is a {@code Failure}, otherwise this.
*/
@GwtIncompatible
@SuppressWarnings({ "unchecked", "varargs" })
default Try<T> mapFailure(Match.Case<? extends Throwable, ? extends Throwable>... cases) {
if (isSuccess()) {
return this;
} else {
final Option<Throwable> x = Match(getCause()).option(cases);
return x.isEmpty() ? this : failure(x.get());
}
}
/**
* Runs the given checked function if this is a {@code Success},
* passing the result of the current expression to it.
* If this expression is a {@code Failure} then it'll return a new
* {@code Failure} of type R with the original exception.
* <p>
* The main use case is chaining checked functions using method references:
*
* <pre>
* <code>
* Try.of(() -> 0)
* .map(x -> 1 / x); // division by zero
* </code>
* </pre>
*
* @param <U> The new component type
* @param mapper A checked function
* @return a {@code Try}
* @throws NullPointerException if {@code mapper} is null
*/
@SuppressWarnings("unchecked")
default <U> Try<U> mapTry(CheckedFunction1<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
if (isFailure()) {
return (Failure<U>) this;
} else {
try {
return new Success<>(mapper.apply(get()));
} catch (Throwable t) {
return new Failure<>(t);
}
}
}
/**
* Consumes the throwable if this is a Failure.
*
* @param action An exception consumer
* @return this
* @throws NullPointerException if {@code action} is null
*/
default Try<T> onFailure(Consumer<? super Throwable> action) {
Objects.requireNonNull(action, "action is null");
if (isFailure()) {
action.accept(getCause());
}
return this;
}
/**
* Consumes the value if this is a Success.
*
* @param action A value consumer
* @return this
* @throws NullPointerException if {@code action} is null
*/
default Try<T> onSuccess(Consumer<? super T> action) {
Objects.requireNonNull(action, "action is null");
if (isSuccess()) {
action.accept(get());
}
return this;
}
@SuppressWarnings("unchecked")
default Try<T> orElse(Try<? extends T> other) {
Objects.requireNonNull(other, "other is null");
return isSuccess() ? this : (Try<T>) other;
}
@SuppressWarnings("unchecked")
default Try<T> orElse(Supplier<? extends Try<? extends T>> supplier) {
Objects.requireNonNull(supplier, "supplier is null");
return isSuccess() ? this : (Try<T>) supplier.get();
}
default T getOrElseGet(Function<? super Throwable, ? extends T> other) {
Objects.requireNonNull(other, "other is null");
if (isFailure()) {
return other.apply(getCause());
} else {
return get();
}
}
default void orElseRun(Consumer<? super Throwable> action) {
Objects.requireNonNull(action, "action is null");
if (isFailure()) {
action.accept(getCause());
}
}
default <X extends Throwable> T getOrElseThrow(Function<? super Throwable, X> exceptionProvider) throws X {
Objects.requireNonNull(exceptionProvider, "exceptionProvider is null");
if (isFailure()) {
throw exceptionProvider.apply(getCause());
} else {
return get();
}
}
/**
* Applies the action to the value of a Success or does nothing in the case of a Failure.
*
* @param action A Consumer
* @return this {@code Try}
* @throws NullPointerException if {@code action} is null
*/
@Override
default Try<T> peek(Consumer<? super T> action) {
Objects.requireNonNull(action, "action is null");
if (isSuccess()) {
action.accept(get());
}
return this;
}
/**
* Returns {@code this}, if this is a {@code Success} or this is a {@code Failure} and the cause is not assignable
* from {@code cause.getClass()}. Otherwise tries to recover the exception of the failure with {@code f},
* i.e. calling {@code Try.of(() -> f.apply((X) getCause())}.
*
* @param <X> Exception type
* @param exception The specific exception type that should be handled
* @param f A recovery function taking an exception of type {@code X}
* @return a {@code Try}
* @throws NullPointerException if {@code exception} is null or {@code f} is null
*/
@GwtIncompatible
@SuppressWarnings("unchecked")
default <X extends Throwable> Try<T> recover(Class<X> exception, Function<? super X, ? extends T> f) {
Objects.requireNonNull(exception, "exception is null");
Objects.requireNonNull(f, "f is null");
if (isFailure()) {
final Throwable cause = getCause();
if (exception.isAssignableFrom(cause.getClass())) {
return Try.of(() -> f.apply((X) cause));
}
}
return this;
}
/**
* Returns {@code this}, if this is a {@code Success} or this is a {@code Failure} and the cause is not assignable
* from {@code cause.getClass()}. Otherwise tries to recover the exception of the failure with {@code f} <b>which returns Try</b>.
* If {@link Try#isFailure()} returned by {@code f} function is <code>true</code> it means that recovery cannot take place due to some circumstances.
*
* @param <X> Exception type
* @param exception The specific exception type that should be handled
* @param f A recovery function taking an exception of type {@code X} and returning Try as a result of recovery.
* If Try is {@link Try#isSuccess()} then recovery ends up successfully. Otherwise the function was not able to recover.
* @return a {@code Try}
*/
@GwtIncompatible
@SuppressWarnings("unchecked")
default <X extends Throwable> Try<T> recoverWith(Class<X> exception, Function<? super X, Try<? extends T>> f){
Objects.requireNonNull(exception, "exception is null");
Objects.requireNonNull(f, "f is null");
if(isFailure()){
final Throwable cause = getCause();
if (exception.isAssignableFrom(cause.getClass())) {
try {
return narrow(f.apply((X) cause));
} catch (Throwable t) {
return new Failure<>(t);
}
}
}
return this;
}
@GwtIncompatible
default <X extends Throwable> Try<T> recoverWith(Class<X> exception, Try<? extends T> recovered){
return (isFailure() && exception.isAssignableFrom(getCause().getClass()))
? narrow(recovered)
: this;
}
/**
* Returns {@code this}, if this is a {@code Success} or this is a {@code Failure} and the cause is not assignable
* from {@code cause.getClass()}. Otherwise returns a {@code Success} containing the given {@code value}.
*
* @param <X> Exception type
* @param exception The specific exception type that should be handled
* @param value A value that is used in case of a recovery
* @return a {@code Try}
* @throws NullPointerException if {@code exception} is null
*/
@GwtIncompatible
default <X extends Throwable> Try<T> recover(Class<X> exception, T value) {
Objects.requireNonNull(exception, "exception is null");
return (isFailure() && exception.isAssignableFrom(getCause().getClass()))
? Try.success(value)
: this;
}
/**
* Returns {@code this}, if this is a {@code Success}, otherwise tries to recover the exception of the failure with {@code f},
* i.e. calling {@code Try.of(() -> f.apply(throwable))}.
*
* @param f A recovery function taking a Throwable
* @return a {@code Try}
* @throws NullPointerException if {@code f} is null
*/
default Try<T> recover(Function<? super Throwable, ? extends T> f) {
Objects.requireNonNull(f, "f is null");
if (isFailure()) {
return Try.of(() -> f.apply(getCause()));
} else {
return this;
}
}
/**
* Returns {@code this}, if this is a Success, otherwise tries to recover the exception of the failure with {@code f},
* i.e. calling {@code f.apply(cause.getCause())}. If an error occurs recovering a Failure, then the new Failure is
* returned.
*
* @param f A recovery function taking a Throwable
* @return a {@code Try}
* @throws NullPointerException if {@code f} is null
*/
@SuppressWarnings("unchecked")
default Try<T> recoverWith(Function<? super Throwable, ? extends Try<? extends T>> f) {
Objects.requireNonNull(f, "f is null");
if (isFailure()) {
try {
return (Try<T>) f.apply(getCause());
} catch (Throwable t) {
return new Failure<>(t);
}
} else {
return this;
}
}
/**
* Converts this {@code Try} to an {@link Either}.
*
* @return A new {@code Either}
*/
default Either<Throwable, T> toEither() {
if (isFailure()) {
return Either.left(getCause());
} else {
return Either.right(get());
}
}
/**
* Transforms this {@code Try}.
*
* @param f A transformation
* @param <U> Type of transformation result
* @return An instance of type {@code U}
* @throws NullPointerException if {@code f} is null
*/
default <U> U transform(Function<? super Try<T>, ? extends U> f) {
Objects.requireNonNull(f, "f is null");
return f.apply(this);
}
/**
* Provides try's finally behavior no matter what the result of the operation is.
*
* @param runnable A runnable
* @return this {@code Try}.
* @throws NullPointerException if {@code runnable} is null
*/
default Try<T> andFinally(Runnable runnable) {
Objects.requireNonNull(runnable, "runnable is null");
return andFinallyTry(runnable::run);
}
/**
* Provides try's finally behavior no matter what the result of the operation is.
*
* @param runnable A runnable
* @return this {@code Try}.
* @throws NullPointerException if {@code runnable} is null
*/
default Try<T> andFinallyTry(CheckedRunnable runnable) {
Objects.requireNonNull(runnable, "runnable is null");
try {
runnable.run();
return this;
} catch (Throwable t) {
return new Failure<>(t);
}
}
@Override
boolean equals(Object o);
@Override
int hashCode();
@Override
String toString();
/**
* A succeeded Try.
*
* @param <T> component type of this Success
* @author Daniel Dietrich
*/
final class Success<T> implements Try<T>, Serializable {
private static final long serialVersionUID = 1L;
private final T value;
/**
* Constructs a Success.
*
* @param value The value of this Success.
*/
private Success(T value) {
this.value = value;
}
@Override
public T get() {
return value;
}
@Override
public Throwable getCause() {
throw new UnsupportedOperationException("getCause on Success");
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean isFailure() {
return false;
}
@Override
public boolean isSuccess() {
return true;
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof Success && Objects.equals(value, ((Success<?>) obj).value));
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@Override
public String stringPrefix() {
return "Success";
}
@Override
public String toString() {
return stringPrefix() + "(" + value + ")";
}
}
/**
* A failed Try.
*
* @param <T> component type of this Failure
* @author Daniel Dietrich
*/
final class Failure<T> implements Try<T>, Serializable {
private static final long serialVersionUID = 1L;
private final Throwable cause;
/**
* Constructs a Failure.
*
* @param cause A cause of type Throwable, may not be null.
* @throws NullPointerException if {@code cause} is null
* @throws Throwable if the given {@code cause} is fatal, i.e. non-recoverable
*/
private Failure(Throwable cause) {
Objects.requireNonNull(cause, "cause is null");
if (isFatal(cause)) {
sneakyThrow(cause);
}
this.cause = cause;
}
@Override
public T get() {
return sneakyThrow(cause);
}
@Override
public Throwable getCause() {
return cause;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean isFailure() {
return true;
}
@Override
public boolean isSuccess() {
return false;
}
@Override
public boolean equals(Object obj) {
return (obj == this) || (obj instanceof Failure && Arrays.deepEquals(cause.getStackTrace(), ((Failure<?>) obj).cause.getStackTrace()));
}
@Override
public String stringPrefix() {
return "Failure";
}
@Override
public int hashCode() {
return Arrays.hashCode(cause.getStackTrace());
}
@Override
public String toString() {
return stringPrefix() + "(" + cause + ")";
}
}
// -- try with resources
/**
* Creates a {@code Try}-with-resources builder that operates on one {@link AutoCloseable} resource.
*
* @param t1Supplier The supplier of the first resource.
* @param <T1> Type of the 1st resource.
* @return a new {@link WithResources1} instance.
*/
static <T1 extends AutoCloseable> WithResources1<T1> withResources(CheckedFunction0<? extends T1> t1Supplier) {
return new WithResources1<>(t1Supplier);
}
/**
* Creates a {@code Try}-with-resources builder that operates on two {@link AutoCloseable} resources.
*
* @param t1Supplier The supplier of the 1st resource.
* @param t2Supplier The supplier of the 2nd resource.
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @return a new {@link WithResources2} instance.
*/
static <T1 extends AutoCloseable, T2 extends AutoCloseable> WithResources2<T1, T2> withResources(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier) {
return new WithResources2<>(t1Supplier, t2Supplier);
}
/**
* Creates a {@code Try}-with-resources builder that operates on three {@link AutoCloseable} resources.
*
* @param t1Supplier The supplier of the 1st resource.
* @param t2Supplier The supplier of the 2nd resource.
* @param t3Supplier The supplier of the 3rd resource.
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @return a new {@link WithResources3} instance.
*/
static <T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable> WithResources3<T1, T2, T3> withResources(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier) {
return new WithResources3<>(t1Supplier, t2Supplier, t3Supplier);
}
/**
* Creates a {@code Try}-with-resources builder that operates on four {@link AutoCloseable} resources.
*
* @param t1Supplier The supplier of the 1st resource.
* @param t2Supplier The supplier of the 2nd resource.
* @param t3Supplier The supplier of the 3rd resource.
* @param t4Supplier The supplier of the 4th resource.
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @return a new {@link WithResources4} instance.
*/
static <T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable> WithResources4<T1, T2, T3, T4> withResources(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier) {
return new WithResources4<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier);
}
/**
* Creates a {@code Try}-with-resources builder that operates on five {@link AutoCloseable} resources.
*
* @param t1Supplier The supplier of the 1st resource.
* @param t2Supplier The supplier of the 2nd resource.
* @param t3Supplier The supplier of the 3rd resource.
* @param t4Supplier The supplier of the 4th resource.
* @param t5Supplier The supplier of the 5th resource.
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
* @return a new {@link WithResources5} instance.
*/
static <T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable> WithResources5<T1, T2, T3, T4, T5> withResources(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier) {
return new WithResources5<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier);
}
/**
* Creates a {@code Try}-with-resources builder that operates on six {@link AutoCloseable} resources.
*
* @param t1Supplier The supplier of the 1st resource.
* @param t2Supplier The supplier of the 2nd resource.
* @param t3Supplier The supplier of the 3rd resource.
* @param t4Supplier The supplier of the 4th resource.
* @param t5Supplier The supplier of the 5th resource.
* @param t6Supplier The supplier of the 6th resource.
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
* @param <T6> Type of the 6th resource.
* @return a new {@link WithResources6} instance.
*/
static <T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable, T6 extends AutoCloseable> WithResources6<T1, T2, T3, T4, T5, T6> withResources(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier, CheckedFunction0<? extends T6> t6Supplier) {
return new WithResources6<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier, t6Supplier);
}
/**
* Creates a {@code Try}-with-resources builder that operates on seven {@link AutoCloseable} resources.
*
* @param t1Supplier The supplier of the 1st resource.
* @param t2Supplier The supplier of the 2nd resource.
* @param t3Supplier The supplier of the 3rd resource.
* @param t4Supplier The supplier of the 4th resource.
* @param t5Supplier The supplier of the 5th resource.
* @param t6Supplier The supplier of the 6th resource.
* @param t7Supplier The supplier of the 7th resource.
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
* @param <T6> Type of the 6th resource.
* @param <T7> Type of the 7th resource.
* @return a new {@link WithResources7} instance.
*/
static <T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable, T6 extends AutoCloseable, T7 extends AutoCloseable> WithResources7<T1, T2, T3, T4, T5, T6, T7> withResources(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier, CheckedFunction0<? extends T6> t6Supplier, CheckedFunction0<? extends T7> t7Supplier) {
return new WithResources7<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier, t6Supplier, t7Supplier);
}
/**
* Creates a {@code Try}-with-resources builder that operates on eight {@link AutoCloseable} resources.
*
* @param t1Supplier The supplier of the 1st resource.
* @param t2Supplier The supplier of the 2nd resource.
* @param t3Supplier The supplier of the 3rd resource.
* @param t4Supplier The supplier of the 4th resource.
* @param t5Supplier The supplier of the 5th resource.
* @param t6Supplier The supplier of the 6th resource.
* @param t7Supplier The supplier of the 7th resource.
* @param t8Supplier The supplier of the 8th resource.
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
* @param <T6> Type of the 6th resource.
* @param <T7> Type of the 7th resource.
* @param <T8> Type of the 8th resource.
* @return a new {@link WithResources8} instance.
*/
static <T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable, T6 extends AutoCloseable, T7 extends AutoCloseable, T8 extends AutoCloseable> WithResources8<T1, T2, T3, T4, T5, T6, T7, T8> withResources(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier, CheckedFunction0<? extends T6> t6Supplier, CheckedFunction0<? extends T7> t7Supplier, CheckedFunction0<? extends T8> t8Supplier) {
return new WithResources8<>(t1Supplier, t2Supplier, t3Supplier, t4Supplier, t5Supplier, t6Supplier, t7Supplier, t8Supplier);
}
/**
* A {@code Try}-with-resources builder that operates on one {@link AutoCloseable} resource.
*
* @param <T1> Type of the 1st resource.
*/
final class WithResources1<T1 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private WithResources1(CheckedFunction0<? extends T1> t1Supplier) {
this.t1Supplier = t1Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes one {@code AutoClosable} resource.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */
public <R> Try<R> of(CheckedFunction1<? super T1, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply()) {
return f.apply(t1);
}
});
}
}
/**
* A {@code Try}-with-resources builder that operates on two {@link AutoCloseable} resources.
*
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
*/
final class WithResources2<T1 extends AutoCloseable, T2 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private final CheckedFunction0<? extends T2> t2Supplier;
private WithResources2(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier) {
this.t1Supplier = t1Supplier;
this.t2Supplier = t2Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes two {@code AutoClosable} resources.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */
public <R> Try<R> of(CheckedFunction2<? super T1, ? super T2, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply()) {
return f.apply(t1, t2);
}
});
}
}
/**
* A {@code Try}-with-resources builder that operates on three {@link AutoCloseable} resources.
*
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
*/
final class WithResources3<T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private final CheckedFunction0<? extends T2> t2Supplier;
private final CheckedFunction0<? extends T3> t3Supplier;
private WithResources3(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier) {
this.t1Supplier = t1Supplier;
this.t2Supplier = t2Supplier;
this.t3Supplier = t3Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes three {@code AutoClosable} resources.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */
public <R> Try<R> of(CheckedFunction3<? super T1, ? super T2, ? super T3, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply()) {
return f.apply(t1, t2, t3);
}
});
}
}
/**
* A {@code Try}-with-resources builder that operates on four {@link AutoCloseable} resources.
*
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
*/
final class WithResources4<T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private final CheckedFunction0<? extends T2> t2Supplier;
private final CheckedFunction0<? extends T3> t3Supplier;
private final CheckedFunction0<? extends T4> t4Supplier;
private WithResources4(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier) {
this.t1Supplier = t1Supplier;
this.t2Supplier = t2Supplier;
this.t3Supplier = t3Supplier;
this.t4Supplier = t4Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes four {@code AutoClosable} resources.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */
public <R> Try<R> of(CheckedFunction4<? super T1, ? super T2, ? super T3, ? super T4, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply()) {
return f.apply(t1, t2, t3, t4);
}
});
}
}
/**
* A {@code Try}-with-resources builder that operates on five {@link AutoCloseable} resources.
*
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
*/
final class WithResources5<T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private final CheckedFunction0<? extends T2> t2Supplier;
private final CheckedFunction0<? extends T3> t3Supplier;
private final CheckedFunction0<? extends T4> t4Supplier;
private final CheckedFunction0<? extends T5> t5Supplier;
private WithResources5(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier) {
this.t1Supplier = t1Supplier;
this.t2Supplier = t2Supplier;
this.t3Supplier = t3Supplier;
this.t4Supplier = t4Supplier;
this.t5Supplier = t5Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes five {@code AutoClosable} resources.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */
public <R> Try<R> of(CheckedFunction5<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply()) {
return f.apply(t1, t2, t3, t4, t5);
}
});
}
}
/**
* A {@code Try}-with-resources builder that operates on six {@link AutoCloseable} resources.
*
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
* @param <T6> Type of the 6th resource.
*/
final class WithResources6<T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable, T6 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private final CheckedFunction0<? extends T2> t2Supplier;
private final CheckedFunction0<? extends T3> t3Supplier;
private final CheckedFunction0<? extends T4> t4Supplier;
private final CheckedFunction0<? extends T5> t5Supplier;
private final CheckedFunction0<? extends T6> t6Supplier;
private WithResources6(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier, CheckedFunction0<? extends T6> t6Supplier) {
this.t1Supplier = t1Supplier;
this.t2Supplier = t2Supplier;
this.t3Supplier = t3Supplier;
this.t4Supplier = t4Supplier;
this.t5Supplier = t5Supplier;
this.t6Supplier = t6Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes six {@code AutoClosable} resources.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */
public <R> Try<R> of(CheckedFunction6<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply(); T6 t6 = t6Supplier.apply()) {
return f.apply(t1, t2, t3, t4, t5, t6);
}
});
}
}
/**
* A {@code Try}-with-resources builder that operates on seven {@link AutoCloseable} resources.
*
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
* @param <T6> Type of the 6th resource.
* @param <T7> Type of the 7th resource.
*/
final class WithResources7<T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable, T6 extends AutoCloseable, T7 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private final CheckedFunction0<? extends T2> t2Supplier;
private final CheckedFunction0<? extends T3> t3Supplier;
private final CheckedFunction0<? extends T4> t4Supplier;
private final CheckedFunction0<? extends T5> t5Supplier;
private final CheckedFunction0<? extends T6> t6Supplier;
private final CheckedFunction0<? extends T7> t7Supplier;
private WithResources7(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier, CheckedFunction0<? extends T6> t6Supplier, CheckedFunction0<? extends T7> t7Supplier) {
this.t1Supplier = t1Supplier;
this.t2Supplier = t2Supplier;
this.t3Supplier = t3Supplier;
this.t4Supplier = t4Supplier;
this.t5Supplier = t5Supplier;
this.t6Supplier = t6Supplier;
this.t7Supplier = t7Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes seven {@code AutoClosable} resources.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try")/* https://bugs.openjdk.java.net/browse/JDK-8155591 */
public <R> Try<R> of(CheckedFunction7<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply(); T6 t6 = t6Supplier.apply(); T7 t7 = t7Supplier.apply()) {
return f.apply(t1, t2, t3, t4, t5, t6, t7);
}
});
}
}
/**
* A {@code Try}-with-resources builder that operates on eight {@link AutoCloseable} resources.
*
* @param <T1> Type of the 1st resource.
* @param <T2> Type of the 2nd resource.
* @param <T3> Type of the 3rd resource.
* @param <T4> Type of the 4th resource.
* @param <T5> Type of the 5th resource.
* @param <T6> Type of the 6th resource.
* @param <T7> Type of the 7th resource.
* @param <T8> Type of the 8th resource.
*/
final class WithResources8<T1 extends AutoCloseable, T2 extends AutoCloseable, T3 extends AutoCloseable, T4 extends AutoCloseable, T5 extends AutoCloseable, T6 extends AutoCloseable, T7 extends AutoCloseable, T8 extends AutoCloseable> {
private final CheckedFunction0<? extends T1> t1Supplier;
private final CheckedFunction0<? extends T2> t2Supplier;
private final CheckedFunction0<? extends T3> t3Supplier;
private final CheckedFunction0<? extends T4> t4Supplier;
private final CheckedFunction0<? extends T5> t5Supplier;
private final CheckedFunction0<? extends T6> t6Supplier;
private final CheckedFunction0<? extends T7> t7Supplier;
private final CheckedFunction0<? extends T8> t8Supplier;
private WithResources8(CheckedFunction0<? extends T1> t1Supplier, CheckedFunction0<? extends T2> t2Supplier, CheckedFunction0<? extends T3> t3Supplier, CheckedFunction0<? extends T4> t4Supplier, CheckedFunction0<? extends T5> t5Supplier, CheckedFunction0<? extends T6> t6Supplier, CheckedFunction0<? extends T7> t7Supplier, CheckedFunction0<? extends T8> t8Supplier) {
this.t1Supplier = t1Supplier;
this.t2Supplier = t2Supplier;
this.t3Supplier = t3Supplier;
this.t4Supplier = t4Supplier;
this.t5Supplier = t5Supplier;
this.t6Supplier = t6Supplier;
this.t7Supplier = t7Supplier;
this.t8Supplier = t8Supplier;
}
/**
* Wraps the result of a computation that may fail in a {@code Try}.
*
* @param f A computation that takes eight {@code AutoClosable} resources.
* @param <R> Result type of the computation.
* @return A new {@code Try} instance.
*/
@SuppressWarnings("try"/* https://bugs.openjdk.java.net/browse/JDK-8155591 */)
public <R> Try<R> of(CheckedFunction8<? super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? super T8, ? extends R> f) {
return Try.of(() -> {
try (T1 t1 = t1Supplier.apply(); T2 t2 = t2Supplier.apply(); T3 t3 = t3Supplier.apply(); T4 t4 = t4Supplier.apply(); T5 t5 = t5Supplier.apply(); T6 t6 = t6Supplier.apply(); T7 t7 = t7Supplier.apply(); T8 t8 = t8Supplier.apply()) {
return f.apply(t1, t2, t3, t4, t5, t6, t7, t8);
}
});
}
}
}
interface TryModule {
static boolean isFatal(Throwable throwable) {
return throwable instanceof InterruptedException
|| throwable instanceof LinkageError
|| throwable instanceof ThreadDeath
|| throwable instanceof VirtualMachineError;
}
// DEV-NOTE: we do not plan to expose this as public API
@SuppressWarnings("unchecked")
static <T extends Throwable, R> R sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}