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

com.github.fieldintercept.util.FieldCompletableFuture Maven / Gradle / Ivy

The newest version!
package com.github.fieldintercept.util;

import com.github.fieldintercept.ReturnFieldDispatchAop;

import java.util.Collection;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;

public class FieldCompletableFuture extends SnapshotCompletableFuture {
    private transient final FieldCompletableFuture root;
    private transient final FieldCompletableFuture parent;
    private transient volatile ReturnFieldDispatchAop.GroupCollect groupCollect;
    private transient boolean parentDone;
    private transient Boolean useAggregation;
    private T value;

    public FieldCompletableFuture() {
        this.value = null;
        this.parent = null;
        this.root = null;
    }

    public FieldCompletableFuture(T value) {
        this.value = value;
        this.parent = null;
        this.root = null;
    }

    private FieldCompletableFuture(FieldCompletableFuture root, FieldCompletableFuture parent, CompletionStage stage) {
        this.value = null;
        this.root = root;
        this.parent = parent;
        stage.whenComplete(this::next);
    }

    public static  FieldCompletableFuture completableFuture(T value) {
        return new FieldCompletableFuture<>(value);
    }

    public static FieldCompletableFuture completableFuture(Object... value) {
        return new FieldCompletableFuture<>(value);
    }

    public FieldCompletableFuture useAggregation() {
        this.useAggregation = true;
        return this;
    }

    public FieldCompletableFuture disableAggregation() {
        this.useAggregation = false;
        return this;
    }

    public boolean isUseAggregation() {
        return useAggregation != null && useAggregation;
    }

    public boolean isChainCall() {
        return parent != null;
    }

    private void next(T result, Throwable throwable) {
        this.value = result;
        this.parentDone = true;
        if (throwable != null) {
            super.completeExceptionally(PlatformDependentUtil.unwrap(throwable));
            return;
        }
        if (!isNeedAutowired(result)) {
            super.complete(result);
            return;
        }

        try {
            FieldCompletableFuture future = new FieldCompletableFuture<>(result);
            if (threadSnapshot != null && threadSnapshot.isNeedReplay()) {
                threadSnapshot.replay(() -> groupCollect.autowiredFieldValue(future));
            } else {
                groupCollect.autowiredFieldValue(future);
            }
            if (future.isDone() && !future.isCompletedExceptionally()) {
                super.complete(result);
            } else {
                future.whenComplete((unused, throwable1) -> {
                    if (throwable1 != null) {
                        FieldCompletableFuture.super.completeExceptionally(PlatformDependentUtil.unwrap(throwable1));
                    } else {
                        FieldCompletableFuture.super.complete(result);
                    }
                });
            }
        } catch (Throwable e) {
            super.completeExceptionally(PlatformDependentUtil.unwrap(e));
        }
    }

    private boolean isNeedAutowired(T result) {
        try {
            return result != null && groupCollect != null && parent.get() != result && !groupCollect.isBasicType(result.getClass());
        } catch (Exception e) {
            return false;
        }
    }

    public T value() {
        return isDone() || parentDone || root == null ? value : root.value();
    }

    public boolean complete() {
        if (parentDone && !isDone()) {
            return false;
        } else {
            return complete(value());
        }
    }

    public void access(ReturnFieldDispatchAop.GroupCollect groupCollect) {
        if (this.groupCollect == groupCollect) {
            return;
        }
        this.groupCollect = groupCollect;
        ReturnFieldDispatchAop aop = groupCollect.getAop();
        if (useAggregation == null) {
            this.useAggregation = aop.isChainCallUseAggregation();
        }
        Collection> completeListeners = aop.getFieldCompletableBeforeCompleteListeners();
        if (completeListeners != null && !completeListeners.isEmpty()) {
            for (BiConsumer consumer : completeListeners) {
                addBeforeCompleteListener((BiConsumer) consumer);
            }
        }
        if (parent != null) {
            parent.access(groupCollect);
        }
    }

    @Override
    public boolean snapshot(Function taskDecorate) {
        if (parent != null) {
            parent.snapshot(taskDecorate);
        }
        return super.snapshot(taskDecorate);
    }

    @Override
    public boolean complete(T result, Throwable throwable) {
        if (root != null) {
            return root.complete(result, throwable);
        } else {
            return super.complete(value(), throwable);
        }
    }

    @Override
    public boolean complete(T value) {
        if (root != null) {
            return root.complete(value);
        } else {
            return super.complete(value());
        }
    }

    @Override
    public boolean completeExceptionally(Throwable ex) {
        if (root != null) {
            return root.completeExceptionally(ex);
        } else {
            return super.completeExceptionally(ex);
        }
    }

    @Override
    public  FieldCompletableFuture thenApply(Function fn) {
        return wrap(super.thenApply(fn));
    }

    @Override
    public  FieldCompletableFuture thenApplyAsync(Function fn) {
        return wrap(super.thenApplyAsync(fn));
    }

    @Override
    public  FieldCompletableFuture thenApplyAsync(Function fn, Executor executor) {
        return wrap(super.thenApplyAsync(fn, executor));
    }

    @Override
    public FieldCompletableFuture thenAccept(Consumer action) {
        return wrap(super.thenAccept(action));
    }

    @Override
    public FieldCompletableFuture thenAcceptAsync(Consumer action) {
        return wrap(super.thenAcceptAsync(action));
    }

    @Override
    public FieldCompletableFuture thenAcceptAsync(Consumer action, Executor executor) {
        return wrap(super.thenAcceptAsync(action, executor));
    }

    @Override
    public FieldCompletableFuture thenRun(Runnable action) {
        return wrap(super.thenRun(action));
    }

    @Override
    public FieldCompletableFuture thenRunAsync(Runnable action) {
        return wrap(super.thenRunAsync(action));
    }

    @Override
    public FieldCompletableFuture thenRunAsync(Runnable action, Executor executor) {
        return wrap(super.thenRunAsync(action, executor));
    }

    @Override
    public  FieldCompletableFuture thenCombine(CompletionStage other, BiFunction fn) {
        return wrap(super.thenCombine(other, fn));
    }

    @Override
    public  FieldCompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn) {
        return wrap(super.thenCombineAsync(other, fn));
    }

    @Override
    public  FieldCompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn, Executor executor) {
        return wrap(super.thenCombineAsync(other, fn, executor));
    }

    @Override
    public  FieldCompletableFuture thenAcceptBoth(CompletionStage other, BiConsumer action) {
        return wrap(super.thenAcceptBoth(other, action));
    }

    @Override
    public  FieldCompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action) {
        return wrap(super.thenAcceptBothAsync(other, action));
    }

    @Override
    public  FieldCompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action, Executor executor) {
        return wrap(super.thenAcceptBothAsync(other, action, executor));
    }

    @Override
    public FieldCompletableFuture runAfterBoth(CompletionStage other, Runnable action) {
        return wrap(super.runAfterBoth(other, action));
    }

    @Override
    public FieldCompletableFuture runAfterBothAsync(CompletionStage other, Runnable action) {
        return wrap(super.runAfterBothAsync(other, action));
    }

    @Override
    public FieldCompletableFuture runAfterBothAsync(CompletionStage other, Runnable action, Executor executor) {
        return wrap(super.runAfterBothAsync(other, action, executor));
    }

    @Override
    public  FieldCompletableFuture applyToEither(CompletionStage other, Function fn) {
        return wrap(super.applyToEither(other, fn));
    }

    @Override
    public  FieldCompletableFuture applyToEitherAsync(CompletionStage other, Function fn) {
        return wrap(super.applyToEitherAsync(other, fn));
    }

    @Override
    public  FieldCompletableFuture applyToEitherAsync(CompletionStage other, Function fn, Executor executor) {
        return wrap(super.applyToEitherAsync(other, fn, executor));
    }

    @Override
    public FieldCompletableFuture acceptEither(CompletionStage other, Consumer action) {
        return wrap(super.acceptEither(other, action));
    }

    @Override
    public FieldCompletableFuture acceptEitherAsync(CompletionStage other, Consumer action) {
        return wrap(super.acceptEitherAsync(other, action));
    }

    @Override
    public FieldCompletableFuture acceptEitherAsync(CompletionStage other, Consumer action, Executor executor) {
        return wrap(super.acceptEitherAsync(other, action, executor));
    }

    @Override
    public FieldCompletableFuture runAfterEither(CompletionStage other, Runnable action) {
        return wrap(super.runAfterEither(other, action));
    }

    @Override
    public FieldCompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action) {
        return wrap(super.runAfterEitherAsync(other, action));
    }

    @Override
    public FieldCompletableFuture runAfterEitherAsync(CompletionStage other, Runnable action, Executor executor) {
        return wrap(super.runAfterEitherAsync(other, action, executor));
    }

    @Override
    public  FieldCompletableFuture thenCompose(Function> fn) {
        return wrap(super.thenCompose(fn));
    }

    @Override
    public  FieldCompletableFuture thenComposeAsync(Function> fn) {
        return wrap(super.thenComposeAsync(fn));
    }

    @Override
    public  FieldCompletableFuture thenComposeAsync(Function> fn, Executor executor) {
        return wrap(super.thenComposeAsync(fn, executor));
    }

    @Override
    public FieldCompletableFuture whenComplete(BiConsumer action) {
        return wrap(super.whenComplete(action));
    }

    @Override
    public FieldCompletableFuture whenCompleteAsync(BiConsumer action) {
        return wrap(super.whenCompleteAsync(action));
    }

    @Override
    public FieldCompletableFuture whenCompleteAsync(BiConsumer action, Executor executor) {
        return wrap(super.whenCompleteAsync(action, executor));
    }

    @Override
    public  FieldCompletableFuture handle(BiFunction fn) {
        return wrap(super.handle(fn));
    }

    @Override
    public  FieldCompletableFuture handleAsync(BiFunction fn) {
        return wrap(super.handleAsync(fn));
    }

    @Override
    public  FieldCompletableFuture handleAsync(BiFunction fn, Executor executor) {
        return wrap(super.handleAsync(fn, executor));
    }

    @Override
    public FieldCompletableFuture exceptionally(Function fn) {
        return wrap(super.exceptionally(fn));
    }

    @Override
    public FieldCompletableFuture toCompletableFuture() {
        return this;
    }

    protected  FieldCompletableFuture wrap(CompletableFuture future) {
        return new FieldCompletableFuture<>(root == null ? this : root, this, future);
    }
}