package throwing.bridge;

import java.util.Optional;
import java.util.function.Function;

@FunctionalInterface
interface RethrowChain<X extends Throwable, Y extends Throwable> {
    public static final RethrowChain<Throwable, Throwable> START = t -> Optional.empty();
    public static final RethrowChain<Throwable, Throwable> END = t -> {
        if (t instanceof Error) {
            throw (Error) t;
        } else if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            throw new AssertionError(t);
        }
    };

    @SuppressWarnings("unchecked")
    public static <X extends Throwable, Y extends Throwable> RethrowChain<X, Y> start() {
        return (RethrowChain<X, Y>) START;
    }

    @SuppressWarnings("unchecked")
    public static <X extends Throwable, Y extends Throwable> RethrowChain<X, Y> end() {
        return (RethrowChain<X, Y>) END;
    }

    public Optional<Y> handle(X t);

    default public <Z extends Throwable> RethrowChain<X, Z> rethrow(Function<? super Y, ? extends Z> mapper) {
        return t -> this.handle(t).map(mapper);
    }

    default public RethrowChain<X, Y> chain(RethrowChain<X, Y> second) {
        return this == START ? second : t -> {
            Optional<Y> o = this.handle(t);
            return o.isPresent() ? o : second.handle(t);
        };
    };

    default public Function<X, Y> finish() {
        return t -> this.chain(end()).handle(t).get();
    }
}

@@ -168,16 +168,49 @@
 rowable%3E
+ extends Function%3CX, Optional%3CY%3E%3E
  %7B%0A    p
@@ -947,45 +947,8 @@
  %7D%0A%0A
-    public Optional%3CY%3E handle(X t);%0A%0A
     
@@ -1074,27 +1074,21 @@
 rn t -%3E 
-this.handle
+apply
 (t).map(
@@ -1255,19 +1255,13 @@
 o = 
-this.handle
+apply
 (t);
@@ -1307,22 +1307,21 @@
  second.
-handle
+apply
 (t);%0A   
@@ -1393,44 +1393,77 @@
     
-return t -%3E this.chain(end()).handle
+RethrowChain%3CX, Y%3E c = this.chain(end());%0A        return t -%3E c.apply
 (t).

Make rethrow chain a Function