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

org.esbtools.eventhandler.NestedTransformableFuture Maven / Gradle / Ivy

/*
 *  Copyright 2016 esbtools Contributors and/or its affiliates.
 *
 *  This file is part of esbtools.
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see .
 */

package org.esbtools.eventhandler;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

// TODO(ahenning,khowell): There is no consensus on whether this class should exist. There is
// consensus however that we should explore moving to a more explicit expression of batchable
// operations, which would remove the need for this class, so let's do that.
public class NestedTransformableFuture implements TransformableFuture {
    private final TransformableFuture> nestedFuture;

    public NestedTransformableFuture(TransformableFuture> nestedFuture) {
        this.nestedFuture = nestedFuture;
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return nestedFuture.cancel(mayInterruptIfRunning);
    }

    @Override
    public boolean isCancelled() {
        return nestedFuture.isCancelled();
    }

    @Override
    public boolean isDone() {
        return nestedFuture.isDone();
    }

    @Override
    public U get() throws InterruptedException, ExecutionException {
        TransformableFuture nextFuture = nestedFuture.get();
        return nextFuture == null ? null : nextFuture.get();
    }

    @Override
    public U get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
            TimeoutException {
        // TODO: Technically, we'd need to track time on first and do delta for second timeout
        // But we don't really care that much right now
        TransformableFuture nextFuture = nestedFuture.get(timeout, unit);
        return nextFuture == null ? null : nextFuture.get(timeout, unit);
    }

    @Override
    public  TransformableFuture transformSync(FutureTransform futureTransform) {
        return nestedFuture.transformAsync(
                nextFuture -> nextFuture.transformSync(futureTransform));
    }

    @Override
    public  TransformableFuture transformAsync(
            FutureTransform> futureTransform) {
        return nestedFuture.transformAsync(
                nextFuture -> nextFuture.transformAsync(futureTransform));
    }

    @Override
    public TransformableFuture transformAsyncIgnoringReturn(
            FutureTransform> futureTransform) {
        return nestedFuture.transformAsync(
                nextFuture -> nextFuture.transformAsyncIgnoringReturn(futureTransform));
    }

    /**
     * Because the result in this context is the result of a nested future, and "done" implies
     * having a result, we put off calling the callbacks until the nested future is done to
     * coincide with when this future has a result.
     */
    @Override
    public TransformableFuture whenDoneOrCancelled(FutureDoneCallback callback) {
        nestedFuture.whenDoneOrCancelled(() -> {
            final TransformableFuture nextFuture;
            try {
                nextFuture = nestedFuture.get();
            } catch (Exception e) {
                callback.onDoneOrCancelled();
                return;
            }
            nextFuture.whenDoneOrCancelled(callback);
        });
        return this;
    }
}