package io.trane.future; import java.time.Duration; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; final class ExceptionFuture<T> implements SatisfiedFuture<T> { private static final Logger logger = Logger.getLogger(ExceptionFuture.class.getName()); private final Throwable ex; protected ExceptionFuture(final Throwable ex) { NonFatalException.verify(ex); this.ex = ex; } @Override public final <R> Future<R> map(final Function<? super T, ? extends R> f) { return unsafeCast(); } @Override public final <R> Future<R> flatMap(final Function<? super T, ? extends Future<R>> f) { return unsafeCast(); } @Override public <R> Future<R> transform(final Transformer<? super T, ? extends R> t) { try { return new ValueFuture<>(t.onException(ex)); } catch (final Throwable error) { return new ExceptionFuture<>(error); } } @Override public <R> Future<R> transformWith(final Transformer<? super T, ? extends Future<R>> t) { try { return t.onException(ex); } catch (final Throwable error) { return new ExceptionFuture<>(error); } } @Override public <U, R> Future<R> biMap(final Future<U> other, final BiFunction<? super T, ? super U, ? extends R> f) { return unsafeCast(); } @Override public <U, R> Future<R> biFlatMap(final Future<U> other, final BiFunction<? super T, ? super U, ? extends Future<R>> f) { return unsafeCast(); } @Override public final Future<T> onSuccess(final Consumer<? super T> c) { return this; } @Override public final Future<T> onFailure(final Consumer<Throwable> c) { try { c.accept(ex); } catch (final Throwable error) { logger.log(Level.WARNING, "Error executing `onFailure` callback " + c + "for" + this, ex); NonFatalException.verify(error); } return this; } @Override public final Future<T> respond(final Responder<? super T> r) { try { r.onException(ex); } catch (final Throwable error) { logger.log(Level.WARNING, "Error executing `respond` callback " + r + "for" + this, ex); NonFatalException.verify(error); } return this; } @Override public final Future<T> rescue(final Function<Throwable, ? extends Future<T>> f) { try { return f.apply(ex); } catch (final Throwable error) { return new ExceptionFuture<>(error); } } @Override public final Future<Void> voided() { return unsafeCast(); } @Override public final T get(final Duration timeout) throws CheckedFutureException { if (ex instanceof RuntimeException) throw (RuntimeException) ex; if (ex instanceof Error) throw (Error) ex; else throw new CheckedFutureException(ex); } @Override public final String toString() { return String.format("ExceptionFuture(%s)", ex); } @Override public final int hashCode() { return (ex == null) ? 0 : ex.hashCode(); } @Override public final boolean equals(final Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final ExceptionFuture<?> other = (ExceptionFuture<?>) obj; if (ex == null) { if (other.ex != null) return false; } else if (!ex.equals(other.ex)) return false; return true; } }