package io.kaif.util; import java.util.function.Function; import java.util.function.Supplier; public abstract class Try<T> { public static final class Success<T> extends Try<T> { private final T value; public Success(T value) { this.value = value; } @Override public boolean isSuccess() { return true; } @Override public boolean isFailure() { return false; } @Override public T get() { return value; } @Override public <U> Try<U> map(Function<? super T, ? extends U> mapper) { return Try.apply(() -> mapper.apply(value)); } @Override public <U> Try<U> flatMap(Function<? super T, ? extends Try<U>> mapper) { try { return mapper.apply(value); } catch (RuntimeException e) { return new Failure<>(e); } } public Try<Exception> failed() { return new Failure<>(new UnsupportedOperationException("Success.failed")); } @Override public Try<T> orElse(Try<T> defaultValue) { return this; } } public static final class Failure<T> extends Try<T> { private final RuntimeException exception; public Failure(RuntimeException exception) { this.exception = exception; } @Override public boolean isSuccess() { return false; } @Override public boolean isFailure() { return true; } @Override public T get() { throw exception; } @SuppressWarnings("unchecked") @Override public <U> Try<U> map(Function<? super T, ? extends U> mapper) { return (Try<U>) this; } @SuppressWarnings("unchecked") @Override public <U> Try<U> flatMap(Function<? super T, ? extends Try<U>> mapper) { return (Try<U>) this; } @Override public Try<Exception> failed() { return new Success<>(exception); } @Override public Try<T> orElse(Try<T> defaultValue) { return defaultValue; } } public static <T> Try<T> apply(Supplier<T> supplier) { try { return new Success<>(supplier.get()); } catch (RuntimeException e) { return new Failure<>(e); } } private Try() { } public abstract boolean isSuccess(); public abstract boolean isFailure(); public abstract T get(); public abstract <U> Try<U> map(Function<? super T, ? extends U> mapper); public abstract <U> Try<U> flatMap(Function<? super T, ? extends Try<U>> mapper); public abstract Try<Exception> failed(); public abstract Try<T> orElse(Try<T> defaultValue); }