All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 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