io.vertx.core.Future.java Source code

Java tutorial

Introduction

Here is the source code for io.vertx.core.Future.java

Source

/*
 * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 * which is available at https://www.apache.org/licenses/LICENSE-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 */

package io.vertx.core;

import io.vertx.codegen.annotations.Fluent;
import io.vertx.codegen.annotations.GenIgnore;
import io.vertx.codegen.annotations.VertxGen;
import io.vertx.core.impl.ContextInternal;
import io.vertx.core.spi.FutureFactory;

import java.util.function.Function;

/**
 * Represents the result of an action that may, or may not, have occurred yet.
 * <p>
 *
 * @author <a href="http://tfox.org">Tim Fox</a>
 */
@VertxGen
public interface Future<T> extends AsyncResult<T> {

    /**
     * Create a future that hasn't completed yet and that is passed to the {@code handler} before it is returned.
     *
     * @param handler the handler
     * @param <T> the result type
     * @return the future.
     */
    static <T> Future<T> future(Handler<Promise<T>> handler) {
        Promise<T> promise = Promise.promise();
        try {
            handler.handle(promise);
        } catch (Throwable e) {
            promise.tryFail(e);
        }
        return promise.future();
    }

    /**
     * Create a succeeded future with a null result
     *
     * @param <T>  the result type
     * @return  the future
     */
    static <T> Future<T> succeededFuture() {
        return factory.succeededFuture();
    }

    /**
     * Created a succeeded future with the specified result.
     *
     * @param result  the result
     * @param <T>  the result type
     * @return  the future
     */
    static <T> Future<T> succeededFuture(T result) {
        if (result == null) {
            return factory.succeededFuture();
        } else {
            return factory.succeededFuture(result);
        }
    }

    /**
     * Create a failed future with the specified failure cause.
     *
     * @param t  the failure cause as a Throwable
     * @param <T>  the result type
     * @return  the future
     */
    static <T> Future<T> failedFuture(Throwable t) {
        return factory.failedFuture(t);
    }

    /**
     * Create a failed future with the specified failure message.
     *
     * @param failureMessage  the failure message
     * @param <T>  the result type
     * @return  the future
     */
    static <T> Future<T> failedFuture(String failureMessage) {
        return factory.failureFuture(failureMessage);
    }

    /**
     * Has the future completed?
     * <p>
     * It's completed if it's either succeeded or failed.
     *
     * @return true if completed, false if not
     */
    boolean isComplete();

    /**
     * Like {@link #onComplete(Handler)}.
     */
    @Fluent
    default Future<T> setHandler(Handler<AsyncResult<T>> handler) {
        return onComplete(handler);
    }

    /**
     * Add a handler to be notified of the result.
     * <br/>
     * @param handler the handler that will be called with the result
     * @return a reference to this, so it can be used fluently
     */
    @Fluent
    Future<T> onComplete(Handler<AsyncResult<T>> handler);

    /**
     * Add a handler to be notified of the succeeded result.
     * <br/>
     * @param handler the handler that will be called with the succeeded result
     * @return a reference to this, so it can be used fluently
     */
    @Fluent
    default Future<T> onSuccess(Handler<T> handler) {
        return onComplete(ar -> {
            if (ar.succeeded()) {
                handler.handle(ar.result());
            }
        });
    }

    /**
     * Add a handler to be notified of the failed result.
     * <br/>
     * @param handler the handler that will be called with the failed result
     * @return a reference to this, so it can be used fluently
     */
    @Fluent
    default Future<T> onFailure(Handler<Throwable> handler) {
        return onComplete(ar -> {
            if (ar.failed()) {
                handler.handle(ar.cause());
            }
        });
    }

    /**
     * @return the handler for the result
     */
    Handler<AsyncResult<T>> getHandler();

    /**
     * The result of the operation. This will be null if the operation failed.
     *
     * @return the result or null if the operation failed.
     */
    @Override
    T result();

    /**
     * A Throwable describing failure. This will be null if the operation succeeded.
     *
     * @return the cause or null if the operation succeeded.
     */
    @Override
    Throwable cause();

    /**
     * Did it succeed?
     *
     * @return true if it succeded or false otherwise
     */
    @Override
    boolean succeeded();

    /**
     * Did it fail?
     *
     * @return true if it failed or false otherwise
     */
    @Override
    boolean failed();

    /**
     * Alias for {@link #compose(Function)}.
     */
    default <U> Future<U> flatMap(Function<T, Future<U>> mapper) {
        return compose(mapper);
    }

    /**
     * Compose this future with a {@code mapper} function.<p>
     *
     * When this future (the one on which {@code compose} is called) succeeds, the {@code mapper} will be called with
     * the completed value and this mapper returns another future object. This returned future completion will complete
     * the future returned by this method call.<p>
     *
     * If the {@code mapper} throws an exception, the returned future will be failed with this exception.<p>
     *
     * When this future fails, the failure will be propagated to the returned future and the {@code mapper}
     * will not be called.
     *
     * @param mapper the mapper function
     * @return the composed future
     */
    default <U> Future<U> compose(Function<T, Future<U>> mapper) {
        return compose(mapper, Future::failedFuture);
    }

    /**
     * @return the context associated with this future or {@code null} when
     */
    default Context context() {
        return null;
    }

    /**
     * Compose this future with a {@code successMapper} and {@code failureMapper} functions.<p>
     *
     * When this future (the one on which {@code compose} is called) succeeds, the {@code successMapper} will be called with
     * the completed value and this mapper returns another future object. This returned future completion will complete
     * the future returned by this method call.<p>
     *
     * When this future (the one on which {@code compose} is called) fails, the {@code failureMapper} will be called with
     * the failure and this mapper returns another future object. This returned future completion will complete
     * the future returned by this method call.<p>
     *
     * If any mapper function throws an exception, the returned future will be failed with this exception.<p>
     *
     * @param successMapper the function mapping the success
     * @param failureMapper the function mapping the failure
     * @return the composed future
     */
    default <U> Future<U> compose(Function<T, Future<U>> successMapper,
            Function<Throwable, Future<U>> failureMapper) {
        if (successMapper == null) {
            throw new NullPointerException();
        }
        if (failureMapper == null) {
            throw new NullPointerException();
        }
        ContextInternal ctx = (ContextInternal) context();
        Promise<U> ret;
        if (ctx != null) {
            ret = ctx.promise();
        } else {
            ret = Promise.promise();
        }
        setHandler(ar -> {
            if (ar.succeeded()) {
                Future<U> apply;
                try {
                    apply = successMapper.apply(ar.result());
                } catch (Throwable e) {
                    ret.fail(e);
                    return;
                }
                apply.setHandler(ret);
            } else {
                Future<U> apply;
                try {
                    apply = failureMapper.apply(ar.cause());
                } catch (Throwable e) {
                    ret.fail(e);
                    return;
                }
                apply.setHandler(ret);
            }
        });
        return ret.future();
    }

    /**
     * Apply a {@code mapper} function on this future.<p>
     *
     * When this future succeeds, the {@code mapper} will be called with the completed value and this mapper
     * returns a value. This value will complete the future returned by this method call.<p>
     *
     * If the {@code mapper} throws an exception, the returned future will be failed with this exception.<p>
     *
     * When this future fails, the failure will be propagated to the returned future and the {@code mapper}
     * will not be called.
     *
     * @param mapper the mapper function
     * @return the mapped future
     */
    default <U> Future<U> map(Function<T, U> mapper) {
        if (mapper == null) {
            throw new NullPointerException();
        }
        ContextInternal ctx = (ContextInternal) context();
        Promise<U> ret;
        if (ctx != null) {
            ret = ctx.promise();
        } else {
            ret = Promise.promise();
        }
        setHandler(ar -> {
            if (ar.succeeded()) {
                U mapped;
                try {
                    mapped = mapper.apply(ar.result());
                } catch (Throwable e) {
                    ret.fail(e);
                    return;
                }
                ret.complete(mapped);
            } else {
                ret.fail(ar.cause());
            }
        });
        return ret.future();
    }

    /**
     * Map the result of a future to a specific {@code value}.<p>
     *
     * When this future succeeds, this {@code value} will complete the future returned by this method call.<p>
     *
     * When this future fails, the failure will be propagated to the returned future.
     *
     * @param value the value that eventually completes the mapped future
     * @return the mapped future
     */
    default <V> Future<V> map(V value) {
        ContextInternal ctx = (ContextInternal) context();
        Promise<V> ret;
        if (ctx != null) {
            ret = ctx.promise();
        } else {
            ret = Promise.promise();
        }
        setHandler(ar -> {
            if (ar.succeeded()) {
                ret.complete(value);
            } else {
                ret.fail(ar.cause());
            }
        });
        return ret.future();
    }

    /**
     * Map the result of a future to {@code null}.<p>
     *
     * This is a conveniency for {@code future.map((T) null)} or {@code future.map((Void) null)}.<p>
     *
     * When this future succeeds, {@code null} will complete the future returned by this method call.<p>
     *
     * When this future fails, the failure will be propagated to the returned future.
     *
     * @return the mapped future
     */
    @Override
    default <V> Future<V> mapEmpty() {
        return (Future<V>) AsyncResult.super.mapEmpty();
    }

    /**
     * Handles a failure of this Future by returning the result of another Future.
     * If the mapper fails, then the returned future will be failed with this failure.
     *
     * @param mapper A function which takes the exception of a failure and returns a new future.
     * @return A recovered future
     */
    default Future<T> recover(Function<Throwable, Future<T>> mapper) {
        if (mapper == null) {
            throw new NullPointerException();
        }
        ContextInternal ctx = (ContextInternal) context();
        Promise<T> ret;
        if (ctx != null) {
            ret = ctx.promise();
        } else {
            ret = Promise.promise();
        }
        setHandler(ar -> {
            if (ar.succeeded()) {
                ret.complete(result());
            } else {
                Future<T> mapped;
                try {
                    mapped = mapper.apply(ar.cause());
                } catch (Throwable e) {
                    ret.fail(e);
                    return;
                }
                mapped.setHandler(ret);
            }
        });
        return ret.future();
    }

    /**
     * Apply a {@code mapper} function on this future.<p>
     *
     * When this future fails, the {@code mapper} will be called with the completed value and this mapper
     * returns a value. This value will complete the future returned by this method call.<p>
     *
     * If the {@code mapper} throws an exception, the returned future will be failed with this exception.<p>
     *
     * When this future succeeds, the result will be propagated to the returned future and the {@code mapper}
     * will not be called.
     *
     * @param mapper the mapper function
     * @return the mapped future
     */
    default Future<T> otherwise(Function<Throwable, T> mapper) {
        if (mapper == null) {
            throw new NullPointerException();
        }
        ContextInternal ctx = (ContextInternal) context();
        Promise<T> ret;
        if (ctx != null) {
            ret = ctx.promise();
        } else {
            ret = Promise.promise();
        }
        setHandler(ar -> {
            if (ar.succeeded()) {
                ret.complete(result());
            } else {
                T value;
                try {
                    value = mapper.apply(ar.cause());
                } catch (Throwable e) {
                    ret.fail(e);
                    return;
                }
                ret.complete(value);
            }
        });
        return ret.future();
    }

    /**
     * Map the failure of a future to a specific {@code value}.<p>
     *
     * When this future fails, this {@code value} will complete the future returned by this method call.<p>
     *
     * When this future succeeds, the result will be propagated to the returned future.
     *
     * @param value the value that eventually completes the mapped future
     * @return the mapped future
     */
    default Future<T> otherwise(T value) {
        ContextInternal ctx = (ContextInternal) context();
        Promise<T> ret;
        if (ctx != null) {
            ret = ctx.promise();
        } else {
            ret = Promise.promise();
        }
        setHandler(ar -> {
            if (ar.succeeded()) {
                ret.complete(result());
            } else {
                ret.complete(value);
            }
        });
        return ret.future();
    }

    /**
     * Map the failure of a future to {@code null}.<p>
     *
     * This is a convenience for {@code future.otherwise((T) null)}.<p>
     *
     * When this future fails, the {@code null} value will complete the future returned by this method call.<p>
     *
     * When this future succeeds, the result will be propagated to the returned future.
     *
     * @return the mapped future
     */
    default Future<T> otherwiseEmpty() {
        return (Future<T>) AsyncResult.super.otherwiseEmpty();
    }

    @GenIgnore
    FutureFactory factory = ServiceHelper.loadFactory(FutureFactory.class);

}