
net.cassite.f.Try Maven / Gradle / Ivy
package net.cassite.f;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
public class Try {
private Try() {
}
public static TryCode code(Supplier> c) {
return new TryCode<>(c);
}
public static class TryCode {
private final Supplier> c;
TryCode(Supplier> c) {
this.c = c;
}
public TryCatch except(Class exType, Function> exHandler) {
return new TryCatch(exType, exHandler);
}
public Monad composeFinally(Supplier> func) {
return except(Throwable.class, Future::failedFuture).composeFinally(func);
}
public class TryCatch {
private final LinkedHashMap, Function>> handlers = new LinkedHashMap<>();
TryCatch(Class exType, Function> exHandler) {
//noinspection unchecked
handlers.put(exType, (Function>) exHandler);
}
public TryCatch except(Class exType, Function> exHandler) {
if (handlers.containsKey(exType))
throw new Error("try-expression already has handler for " + exType.getName());
//noinspection unchecked
handlers.put(exType, (Function>) exHandler);
return this;
}
public Monad map(Function f) {
return compose(t -> F.unit(f.apply(t)));
}
public void setHandler(Handler> handler) {
compose(Future::succeededFuture).setHandler(handler);
}
public Monad composeFinally(Supplier> func) {
Monad fu = F.tbd();
setHandler(r -> {
Future> f;
try {
f = func.get();
} catch (Throwable t) {
// exception thrown in finally scope
fu.fail(t);
return;
}
f.setHandler(r2 -> {
if (r2.failed()) {
fu.fail(r2.cause());
} else {
if (r.failed()) {
fu.fail(r.cause());
} else {
T t = r.result();
fu.complete(t);
}
}
});
});
return fu;
}
private void handleFailed(Function> f, Future fu, Throwable ex) {
boolean found = false;
for (Map.Entry, Function>> entry : handlers.entrySet()) {
Class extends Throwable> type = entry.getKey();
if (type.isInstance(ex)) {
found = true;
Future fuT;
try {
fuT = entry.getValue().apply(ex);
} catch (Throwable t) {
// exception thrown in handler function
fu.fail(t);
return;
}
fuT.compose(f).setHandler(fu);
break;
}
}
if (!found) {
fu.fail(ex);
}
}
public Monad compose(Function> f) {
Monad fu = F.tbd();
try {
c.get().setHandler(res -> {
if (res.succeeded()) {
T t = res.result();
f.apply(t).setHandler(fu);
return;
}
Throwable ex = res.cause();
handleFailed(f, fu, ex);
});
} catch (Throwable ex) {
// exception thrown in code function
handleFailed(f, fu, ex);
}
return fu;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy