Multiverse-Core/src/main/java/org/mvplugins/multiverse/core/utils/result/Async.java

164 lines
5.5 KiB
Java

package org.mvplugins.multiverse.core.utils.result;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* Represents the result of an asynchronous operation that wraps a {@link CompletableFuture}.
*
* @param <T> The type of the value.
*/
public final class Async<T> {
/**
* Returns a new AsyncResult that is completed when all of the given AsyncResult complete.
*
* @param results The results to wait for.
* @return A new AsyncResult that is completed when all of the given AsyncResult complete.
*/
public static Async<Void> allOf(Async<?>... results) {
return new Async<>(CompletableFuture.allOf(Arrays.stream(results)
.map(result -> result.future)
.toArray(CompletableFuture[]::new)));
}
/**
* Returns a new AsyncResult that is completed when all of the given AsyncResult with the same type complete.
*
* @param results The results to wait for.
* @param <T> The type of the AsyncResult.
* @return A new AsyncResult that is completed when all of the given AsyncResult complete.
*/
public static <T> Async<List<T>> allOf(List<Async<T>> results) {
return new Async<>(CompletableFuture.allOf(results.stream()
.map(result -> result.future)
.toArray(CompletableFuture[]::new))
.thenApply(v -> results.stream()
.map(result -> result.future.join())
.toList()));
}
/**
* Wraps a CompletableFuture in an AsyncResult.
*
* @param future The future to wrap.
* @param <T> The type of the future.
* @return A new AsyncResult that is completed when the given future completes.
*/
public static <T> Async<T> of(CompletableFuture<T> future) {
return new Async<>(future);
}
/**
* Returns a new AsyncResult that is already completed with the given value.
*
* @param value The value to complete the AsyncResult with.
* @param <T> The type of the value.
* @return The completed AsyncResult.
*/
public static <T> Async<T> completedFuture(T value) {
return new Async<>(CompletableFuture.completedFuture(value));
}
/**
* Returns a new CompletableFuture that is already completed exceptionally with the given exception.
*
* @param throwable The exception to complete the AsyncResult with.
* @param <T> The type of the value.
* @return The completed AsyncResult.
*/
public static <T> Async<T> failedFuture(Throwable throwable) {
return new Async<>(CompletableFuture.failedFuture(throwable));
}
private final CompletableFuture<T> future;
/**
* Creates a new AsyncResult.
*/
public Async() {
this(new CompletableFuture<>());
}
private Async(CompletableFuture<T> future) {
this.future = future;
}
/**
* If not already completed, sets the value returned by related methods to the given value.
*
* @param value The value to complete the AsyncResult with.
* @return true if this invocation caused this AsyncResult to transition to a completed state, else false.
*/
public boolean complete(T value) {
return future.complete(value);
}
/**
* If not already completed, causes invocations of related methods to throw the given exception.
*
* @param throwable The exception to complete the AsyncResult with.
* @return true if this invocation caused this AsyncResult to transition to a completed state, else false.
*/
public boolean completeExceptionally(Throwable throwable) {
return future.completeExceptionally(throwable);
}
/**
* Executes the given action when this AsyncResult completes.
*
* @param consumer The action to perform.
* @return This AsyncResult.
*/
public Async<Void> thenAccept(Consumer<T> consumer) {
return new Async<>(future.thenAccept(consumer));
}
/**
* Executes the given action when this AsyncResult completes.
*
* @param runnable The action to perform.
* @return This AsyncResult.
*/
public Async<Void> thenRun(Runnable runnable) {
return new Async<>(future.thenRun(runnable));
}
/**
* Executes the given action when this AsyncResult completes and returns a new AsyncResult with the new value.
*
* @param function The action to perform.
* @param <U> The type of the new value.
* @return A new AsyncResult with the new value.
*/
public <U> Async<U> thenApply(Function<T, U> function) {
return new Async<>(future.thenApply(function));
}
/**
* Executes the given action when this AsyncResult completes with an exception.
*
* @param consumer The action to perform.
* @return This AsyncResult.
*/
public Async<T> exceptionally(Consumer<Throwable> consumer) {
return new Async<>(future.exceptionally(throwable -> {
consumer.accept(throwable);
return null;
}));
}
/**
* Executes the given action when this AsyncResult completes with an exception and returns a new AsyncResult with the new value.
*
* @param function The action to perform.
* @return A new AsyncResult with the new value.
*/
public Async<T> exceptionally(Function<Throwable, T> function) {
return new Async<>(future.exceptionally(function));
}
}