package com.github.aesteve.vertx.nubes.utils.async;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.logging.Logger;
import io.vertx.ext.web.RoutingContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public interface AsyncUtils {
static <T> Handler<AsyncResult<T>> completeFinally(Future<T> fut) {
return (res -> fut.complete());
}
static <T> Handler<AsyncResult<T>> completeOrFail(Future<T> fut) {
return res -> {
if (res.failed()) {
fut.fail(res.cause());
} else {
fut.complete(res.result());
}
};
}
static <T> Handler<AsyncResult<T>> ignoreResult(Future<Void> future) {
return res -> {
if (res.failed()) {
future.fail(res.cause());
} else {
future.complete();
}
};
}
static <T> AsyncResult<Void> withoutResult(AsyncResult<T> res) {
if (res.failed()) {
return Future.failedFuture(res.cause());
} else {
return Future.succeededFuture();
}
}
static <T> Handler<AsyncResult<T>> onSuccessOnly(Future<Void> future, Handler<T> handler) {
return res -> {
if (res.failed()) {
future.fail(res.cause());
return;
}
handler.handle(res.result());
};
}
static <T> Handler<AsyncResult<T>> onSuccessOnly(NoArgHandler block) {
return res -> {
if (res.failed()) {
return;
}
block.handle();
};
}
static <T> Handler<AsyncResult<T>> onSuccessOnly(Handler<T> handler) {
return res -> {
if (res.failed()) {
return;
}
handler.handle(res.result());
};
}
static <T> Handler<AsyncResult<T>> onFailureOnly(Handler<T> handler) {
return res -> {
if (res.failed()) {
handler.handle(res.result());
}
};
}
static <T> Handler<AsyncResult<T>> nextOrFail(RoutingContext context) {
return res -> {
if (res.failed()) {
context.fail(res.cause());
} else {
context.next();
}
};
}
static <T> Handler<AsyncResult<T>> failOr(RoutingContext context, Handler<AsyncResult<T>> handler) {
return res -> {
if (res.failed()) {
context.fail(res.cause());
} else {
handler.handle(res);
}
};
}
static <T, U, V> Future<V> chainOnSuccess(Handler<AsyncResult<T>> globalHandler, Future<U> future, Handler<Future<V>> nextHandler) {
Future<V> nextFuture = Future.future();
future.setHandler(res -> {
if (res.failed()) {
globalHandler.handle(Future.failedFuture(res.cause()));
} else {
nextHandler.handle(nextFuture);
}
});
return nextFuture;
}
static <T> void chainHandlers(Handler<AsyncResult<T>> global, List<Handler<Future<T>>> handlers) {
if (handlers == null || handlers.isEmpty()) {
global.handle(Future.succeededFuture());
return;
}
int nbHandlers = handlers.size();
Future<T> firstFuture = Future.future();
if (nbHandlers == 1) {
firstFuture.setHandler(global);
handlers.get(0).handle(firstFuture);
return;
}
List<Future<T>> futures = new ArrayList<>(handlers.size());
futures.add(firstFuture);
int i = 0;
for (Handler<Future<T>> handler : handlers) {
if (i > 0) {
Future<T> fut = futures.get(i - 1);
futures.add(chainOnSuccess(global, fut, handler));
}
i++;
}
futures.get(futures.size() - 1).setHandler(global);
handlers.get(0).handle(firstFuture);
}
static <T> void chainHandlers(Future<T> global, List<Handler<Future<T>>> handlers) {
chainHandlers(res -> {
if (res.failed()) {
global.fail(res.cause());
} else {
global.complete(res.result());
}
}, handlers);
}
static <T, U> Future<Void> chainOnSuccess(Handler<AsyncResult<T>> globalHandler, Future<U> future, List<Handler<Future<Void>>> list) {
List<Future<Void>> futures = new ArrayList<>(list.size());
int i = 0;
Future<Void> firstFuture = Future.future();
for (Handler<Future<Void>> handler : list) {
Future<Void> fut = i == 0 ? firstFuture : futures.get(i - 1);
futures.add(chainOnSuccess(globalHandler, fut, handler));
i++;
}
future.setHandler(res -> {
if (res.failed()) {
globalHandler.handle(Future.failedFuture(res.cause()));
} else {
list.get(0).handle(firstFuture);
}
});
return futures.get(futures.size() - 1);
}
@SafeVarargs
// or we're screwed...
static <T, U> Future<Void> chainOnSuccess(Handler<AsyncResult<T>> globalHandler, Future<U> future, Handler<Future<Void>>... handlers) {
List<Handler<Future<Void>>> list = Arrays.asList(handlers);
return AsyncUtils.chainOnSuccess(globalHandler, future, list);
}
static <T> Handler<AsyncResult<T>> logIfFailed(final String msg, final Logger log) {
return res -> {
if (res.failed()) {
if (msg != null) {
log.error(msg, res.cause());
} else {
log.error(res.cause());
}
}
};
}
}