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

io.sphere.sdk.utils.CompletableFutureUtils Maven / Gradle / Ivy

There is a newer version: 1.0.0-M26
Show newest version
package io.sphere.sdk.utils;

import io.sphere.sdk.utils.functional.TriFunction;
import org.apache.commons.lang3.tuple.Pair;

import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public final class CompletableFutureUtils {
    private CompletableFutureUtils() {
    }

    public static  CompletableFuture successful(final T object) {
        return CompletableFuture.completedFuture(object);
    }

    static  Throwable blockForFailure(final CompletionStage future) {
        try {
            future.toCompletableFuture().join();
            throw new NoSuchElementException(future + " did not complete exceptionally.");
        } catch (final CompletionException e1) {
            return e1.getCause();
        }
    }

    public static  CompletableFuture failed(final Throwable e) {
        final CompletableFuture future = new CompletableFuture<>();
        future.completeExceptionally(e);
        return future;
    }

    public static  void transferResult(final CompletionStage source,
                                          final CompletableFuture target) {
        source.whenComplete((result, throwable) -> {
            final boolean isSuccessful = throwable == null;
            if (isSuccessful) {
                target.complete(result);
            } else {
                target.completeExceptionally(throwable);
            }
        });
    }

    public static  CompletionStage onFailure(final CompletionStage future, final Consumer consumer) {
        return future.whenCompleteAsync((value, throwable) -> {
            if (throwable != null) {
                consumer.accept(throwable);
            }
        });
    }

    public static  CompletionStage onSuccess(final CompletionStage future, final Consumer consumer) {
        return future.whenCompleteAsync((value, throwable) -> {
            if (throwable == null) {
                consumer.accept(value);
            }
        });
    }

    public static  CompletionStage recover(final CompletionStage future, final Function f) {
        return future.exceptionally(f);
    }

    public static  CompletionStage recoverWith(final CompletionStage future, final Function> f) {
        final CompletableFuture result = new CompletableFuture<>();
        final BiConsumer action = (value, error) -> {
            if (value != null) {
                result.complete(value);
            } else {
                final CompletionStage alternative = f.apply(error);
                alternative.whenComplete((alternativeValue, alternativeError) -> {
                    if (alternativeValue != null) {
                        result.complete(alternativeValue);
                    } else {
                        result.completeExceptionally(alternativeError);
                    }
                });
            }
        };
        future.whenComplete(action);
        return result;
    }

    public static  T orElseThrow(final CompletionStage stage, Supplier exceptionSupplier) throws X, ExecutionException, InterruptedException {
        final CompletableFuture future = stage.toCompletableFuture();
        if (future.isDone()) {
            return future.get();
        } else {
            throw exceptionSupplier.get();
        }
    }

    public static  T orElseGet(final CompletionStage stage, final Supplier other) throws ExecutionException, InterruptedException {
        final CompletableFuture future = stage.toCompletableFuture();
        return future.isDone() ? future.get() : other.get();
    }

    public static  CompletionStage map(final CompletionStage future, final Function f) {
        return future.thenApply(f);
    }

    public static  CompletionStage flatMap(final CompletionStage future, final Function> f) {
        return future.thenCompose(f);
    }

    public static  CompletionStage thenCombine(final CompletionStage a, final CompletionStage b, final CompletionStage c, final TriFunction f) {
        final CompletionStage> pairCompletionStage = a.thenCombine(b, (aa, bb) -> Pair.of(aa, bb));
        return pairCompletionStage.thenCombine(c, (pp, cc) -> f.apply(pp.getLeft(), pp.getRight(), cc));
    }
}