/* * Copyright (c) 2011-2013 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package io.vertx.core; import java.util.function.Function; /** * Encapsulates the result of an asynchronous operation. * <p> * Many operations in Vert.x APIs provide results back by passing an instance of this in a {@link io.vertx.core.Handler}. * <p> * The result can either have failed or succeeded. * <p> * If it failed then the cause of the failure is available with {@link #cause}. * <p> * If it succeeded then the actual result is available with {@link #result} * * @author <a href="http://tfox.org">Tim Fox</a> */ public interface AsyncResult<T> { /** * The result of the operation. This will be null if the operation failed. * * @return the result or null if the operation failed. */ T result(); /** * A Throwable describing failure. This will be null if the operation succeeded. * * @return the cause or null if the operation succeeded. */ Throwable cause(); /** * Did it succeed? * * @return true if it succeded or false otherwise */ boolean succeeded(); /** * Did it fail? * * @return true if it failed or false otherwise */ boolean failed(); /** * Apply a {@code mapper} function on this async result.<p> * * The {@code mapper} is called with the completed value and this mapper returns a value. This value will complete the result 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 async result is failed, 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 async result */ default <U> AsyncResult<U> map(Function<T, U> mapper) { if (mapper == null) { throw new NullPointerException(); } return new AsyncResult<U>() { @Override public U result() { if (succeeded()) { return mapper.apply(AsyncResult.this.result()); } else { return null; } } @Override public Throwable cause() { return AsyncResult.this.cause(); } @Override public boolean succeeded() { return AsyncResult.this.succeeded(); } @Override public boolean failed() { return AsyncResult.this.failed(); } }; } /** * Map the result of this async result to a specific {@code value}.<p> * * When this async result succeeds, this {@code value} will succeeed the async result returned by this method call.<p> * * When this async result fails, the failure will be propagated to the returned async result. * * @param value the value that eventually completes the mapped async result * @return the mapped async result */ default <V> AsyncResult<V> map(V value) { return map(t -> value); } /** * Map the result of this async result to {@code null}.<p> * * This is a convenience for {@code asyncResult.map((T) null)} or {@code asyncResult.map((Void) null)}.<p> * * When this async result succeeds, {@code null} will succeeed the async result returned by this method call.<p> * * When this async result fails, the failure will be propagated to the returned async result. * * @return the mapped async result */ default <V> AsyncResult<V> mapEmpty() { return map((V)null); } /** * Apply a {@code mapper} function on this async result.<p> * * The {@code mapper} is called with the failure and this mapper returns a value. This value will complete the result 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 async result is succeeded, the value will be propagated to the returned future and the {@code mapper} * will not be called. * * @param mapper the mapper function * @return the mapped async result */ default AsyncResult<T> otherwise(Function<Throwable, T> mapper) { if (mapper == null) { throw new NullPointerException(); } return new AsyncResult<T>() { @Override public T result() { if (AsyncResult.this.succeeded()) { return AsyncResult.this.result(); } else if (AsyncResult.this.failed()) { return mapper.apply(AsyncResult.this.cause()); } else { return null; } } @Override public Throwable cause() { return null; } @Override public boolean succeeded() { return AsyncResult.this.succeeded() || AsyncResult.this.failed(); } @Override public boolean failed() { return false; } }; } /** * Map the failure of this async result to a specific {@code value}.<p> * * When this async result fails, this {@code value} will succeeed the async result returned by this method call.<p> * * When this async succeeds, the result will be propagated to the returned async result. * * @param value the value that eventually completes the mapped async result * @return the mapped async result */ default AsyncResult<T> otherwise(T value) { return otherwise(err -> value); } /** * Map the failure of this async result to {@code null}.<p> * * This is a convenience for {@code asyncResult.otherwise((T) null)}.<p> * * When this async result fails, the {@code null} will succeeed the async result returned by this method call.<p> * * When this async succeeds, the result will be propagated to the returned async result. * * @return the mapped async result */ default AsyncResult<T> otherwiseEmpty() { return otherwise(err -> null); } }