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

reactor.rx.Promises Maven / Gradle / Ivy

There is a newer version: 3.36.0
Show newest version
/*
 * Copyright (c) 2011-2014 Pivotal Software, Inc.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package reactor.rx;

import org.reactivestreams.Publisher;
import reactor.Environment;
import reactor.core.Dispatcher;
import reactor.core.dispatch.SynchronousDispatcher;
import reactor.core.reactivestreams.PublisherFactory;
import reactor.core.reactivestreams.SubscriberWithContext;
import reactor.core.support.Assert;
import reactor.fn.Consumer;
import reactor.fn.Function;
import reactor.fn.Supplier;
import reactor.fn.tuple.Tuple;
import reactor.fn.tuple.Tuple2;
import reactor.fn.tuple.Tuple3;
import reactor.fn.tuple.Tuple4;
import reactor.fn.tuple.Tuple5;
import reactor.fn.tuple.Tuple6;
import reactor.fn.tuple.Tuple7;
import reactor.fn.tuple.Tuple8;
import reactor.rx.action.combination.MergeAction;

import java.util.Arrays;
import java.util.List;

/**
 * Helper methods for creating {@link reactor.rx.Promise} instances.
 *
 * @author Stephane Maldini
 * @author Jon Brisbin
 */
public final class Promises {

	/**
	 * Create a synchronous {@link Promise}.
	 *
	 * @param  type of the expected value
	 * @return A {@link Promise}.
	 */
	public static  Promise prepare() {
		return ready(null, SynchronousDispatcher.INSTANCE);
	}

	/**
	 * Create a {@link Promise}.
	 *
	 * @param env the {@link reactor.Environment} to use
	 * @param  type of the expected value
	 * @return a new {@link reactor.rx.Promise}
	 */
	public static  Promise prepare(Environment env) {
		return ready(env, env.getDefaultDispatcher());
	}

	/**
	 * Create a {@link Promise}.
	 *
	 * @param env        the {@link reactor.Environment} to use
	 * @param dispatcher the {@link reactor.core.Dispatcher} to use
	 * @param         type of the expected value
	 * @return a new {@link reactor.rx.Promise}
	 */
	public static  Promise ready(Environment env, Dispatcher dispatcher) {
		return new Promise(dispatcher, env);
	}

	/**
	 * Create a synchronous {@link Promise} producing the value for the {@link Promise} using the
	 * given supplier.
	 *
	 * @param supplier {@link Supplier} that will produce the value
	 * @param       type of the expected value
	 * @return A {@link Promise}.
	 */
	public static  Promise syncTask(Supplier supplier) {
		return task(null, SynchronousDispatcher.INSTANCE, supplier);
	}

	/**
	 * Create a {@link Promise} producing the value for the {@link Promise} using the
	 * given supplier.
	 *
	 * @param supplier {@link Supplier} that will produce the value
	 * @param env      The assigned environment
	 * @param       type of the expected value
	 * @return A {@link Promise}.
	 */
	public static  Promise task(Environment env, Supplier supplier) {
		return task(env, env.getDefaultDispatcher(), supplier);
	}

	/**
	 * Create a {@link Promise} producing the value for the {@link Promise} using the
	 * given supplier.
	 *
	 * @param supplier   {@link Supplier} that will produce the value
	 * @param env        The assigned environment
	 * @param dispatcher The dispatcher to schedule the value
	 * @param         type of the expected value
	 * @return A {@link Promise}.
	 */
	public static  Promise task(Environment env, Dispatcher dispatcher, final Supplier supplier) {
		Publisher p = PublisherFactory.forEach(new Consumer>() {
			@Override
			public void accept(SubscriberWithContext sub) {
				sub.onNext(supplier.get());
				sub.onComplete();
			}
		});
		return Streams.wrap(p)
		              .env(env)
		              .subscribeOn(dispatcher)
		              .next();
	}

	/**
	 * Create a {@link Promise} using the given value to complete the {@link Promise}
	 * immediately.
	 *
	 * @param value the value to complete the {@link Promise} with
	 * @param    the type of the value
	 * @return A {@link Promise} that is completed with the given value
	 */
	public static  Promise success(T value) {
		return success(null, SynchronousDispatcher.INSTANCE, value);
	}

	/**
	 * Create a {@link Promise} already completed without any data.
	 *
	 * @return A {@link Promise} that is completed
	 */
	public static Promise success() {
		return success(null, SynchronousDispatcher.INSTANCE, null);
	}

	/**
	 * Create a {@link Promise} using the given value to complete the {@link Promise}
	 * immediately.
	 *
	 * @param value the value to complete the {@link Promise} with
	 * @param env   The assigned environment
	 * @param    the type of the value
	 * @return A {@link Promise} that is completed with the given value
	 */
	public static  Promise success(Environment env, T value) {
		return success(env, env.getDefaultDispatcher(), value);
	}

	/**
	 * Create a {@link Promise} using the given value to complete the {@link Promise}
	 * immediately.
	 *
	 * @param value      the value to complete the {@link Promise} with
	 * @param env        The assigned environment
	 * @param dispatcher The dispatcher to schedule the value
	 * @param         the type of the value
	 * @return A {@link Promise} that is completed with the given value
	 */
	public static  Promise success(Environment env, Dispatcher dispatcher, T value) {
		return new Promise(value, dispatcher, env);
	}

	/**
	 * Create synchronous {@link Promise} and use the given error to complete the {@link Promise}
	 * immediately.
	 *
	 * @param error the error to complete the {@link Promise} with
	 * @param    the type of the value
	 * @return A {@link Promise} that is completed with the given error
	 */
	public static  Promise error(Throwable error) {
		return error(null, SynchronousDispatcher.INSTANCE, error);
	}

	/**
	 * Create a {@link Promise} and use the given error to complete the {@link Promise}
	 * immediately.
	 *
	 * @param error the error to complete the {@link Promise} with
	 * @param env   The assigned environment
	 * @param    the type of the value
	 * @return A {@link Promise} that is completed with the given error
	 */
	public static  Promise error(Environment env, Throwable error) {
		return error(env, env.getDefaultDispatcher(), error);
	}

	/**
	 * Create a {@link Promise} and use the given error to complete the {@link Promise}
	 * immediately.
	 *
	 * @param error      the error to complete the {@link Promise} with
	 * @param env        The assigned environment
	 * @param dispatcher The dispatcher to schedule the value
	 * @param         the type of the value
	 * @return A {@link Promise} that is completed with the given error
	 */
	public static  Promise error(Environment env, Dispatcher dispatcher, Throwable error) {
		return new Promise(error, dispatcher, env);
	}


	/**
	 * Merge given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise
	 * Promises} have been fulfilled.
	 *
	 * @param p1,     p2
	 *                The promises to use.
	 * @param  The type of the function Tuple result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise> when(Promise p1, Promise p2) {
		return multiWhen(new Promise[]{p1, p2}).map(new Function, Tuple2>() {
			@Override
			public Tuple2 apply(List objects) {
				return Tuple.of((T1) objects.get(0), (T2) objects.get(1));
			}
		});
	}

	/**
	 * Merge given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise
	 * Promises} have been fulfilled.
	 *
	 * @param p1,        p2, p3
	 *                   The promises to use.
	 * @param  The type of the function Tuple result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise> when(Promise p1, Promise p2, Promise p3) {
		return multiWhen(new Promise[]{p1, p2, p3}).map(new Function, Tuple3>() {
			@Override
			public Tuple3 apply(List objects) {
				return Tuple.of((T1) objects.get(0), (T2) objects.get(1), (T3) objects.get(2));
			}
		});
	}

	/**
	 * Merge given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise
	 * Promises} have been fulfilled.
	 *
	 * @param p1,           p2, p3, p4
	 *                      The promises to use.
	 * @param  The type of the function Tuple result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise> when(Promise p1, Promise p2, Promise p3,
	                                                                    Promise p4) {
		return multiWhen(new Promise[]{p1, p2, p3, p4}).map(new Function, Tuple4>() {
			@Override
			public Tuple4 apply(List objects) {
				return Tuple.of((T1) objects.get(0), (T2) objects.get(1), (T3) objects.get(2), (T4) objects.get(3));
			}
		});
	}

	/**
	 * Merge given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise
	 * Promises} have been fulfilled.
	 *
	 * @param p1,              p2, p3, p4, p5
	 *                         The promises to use.
	 * @param  The type of the function Tuple result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise> when(Promise p1, Promise p2,
	                                                                            Promise p3, Promise p4,
	                                                                            Promise p5) {
		return multiWhen(new Promise[]{p1, p2, p3, p4, p5}).map(new Function, Tuple5>() {
			@Override
			public Tuple5 apply(List objects) {
				return Tuple.of((T1) objects.get(0), (T2) objects.get(1), (T3) objects.get(2), (T4) objects.get(3),
						(T5) objects.get(4));
			}
		});
	}

	/**
	 * Merge given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise
	 * Promises} have been fulfilled.
	 *
	 * @param p1,                 p2, p3, p4, p5, p6
	 *                            The promises to use.
	 * @param  The type of the function Tuple result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise> when(Promise p1, Promise p2,
	                                                                                    Promise p3, Promise p4,
	                                                                                    Promise p5, Promise p6) {
		return multiWhen(new Promise[]{p1, p2, p3, p4, p5, p6}).map(new Function, Tuple6>() {
			@Override
			public Tuple6 apply(List objects) {
				return Tuple.of((T1) objects.get(0), (T2) objects.get(1), (T3) objects.get(2), (T4) objects.get(3),
						(T5) objects.get(4), (T6) objects.get(5));
			}
		});
	}

	/**
	 * Merge given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise
	 * Promises} have been fulfilled.
	 *
	 * @param p1,                    p2, p3, p4, p5, p6, p7
	 *                               The promises to use.
	 * @param  The type of the function Tuple result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise> when(Promise p1,
	                                                                                            Promise p2,
	                                                                                            Promise p3,
	                                                                                            Promise p4,
	                                                                                            Promise p5,
	                                                                                            Promise p6,
	                                                                                            Promise p7) {
		return multiWhen(new Promise[]{p1, p2, p3, p4, p5, p6, p7}).map(new Function, Tuple7>() {
			@Override
			public Tuple7 apply(List objects) {
				return Tuple.of((T1) objects.get(0), (T2) objects.get(1), (T3) objects.get(2), (T4) objects.get(3),
						(T5) objects.get(4), (T6) objects.get(5), (T7) objects.get(6));
			}
		});
	}

	/**
	 * Merge given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise
	 * Promises} have been fulfilled.
	 *
	 * @param p1,                       p2, p3, p4, p5, p6, p7, p8
	 *                                  The promises to use.
	 * @param  The type of the function Tuple result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise> when(Promise p1,
	                                                                                                    Promise p2,
	                                                                                                    Promise p3,
	                                                                                                    Promise p4,
	                                                                                                    Promise p5,
	                                                                                                    Promise p6,
	                                                                                                    Promise p7,
	                                                                                                    Promise p8) {
		return multiWhen(new Promise[]{p1, p2, p3, p4, p5, p6, p7, p8}).map(new Function, Tuple8>() {
			@Override
			public Tuple8 apply(List objects) {
				return Tuple.of((T1) objects.get(0), (T2) objects.get(1), (T3) objects.get(2), (T4) objects.get(3),
						(T5) objects.get(4), (T6) objects.get(5), (T7) objects.get(6), (T8) objects.get(7));
			}
		});
	}

	/**
	 * Aggregate given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
	 * Promise Promises} have been fulfilled.
	 *
	 * @param promises The promises to use.
	 * @param       The type of the function result.
	 * @return a {@link Promise}.
	 */
	public static  Promise> when(final List> promises) {
		Assert.isTrue(promises.size() > 0, "Must aggregate at least one promise");

		return new MergeAction(SynchronousDispatcher.INSTANCE, promises)
				.buffer(promises.size())
				.next();
	}


	/**
	 * Pick the first result coming from any of the given promises and populate a new {@literal Promise}.
	 *
	 * @param promises The deferred promises to use.
	 * @param       The type of the function result.
	 * @return a {@link Promise}.
	 */
	public static  Promise any(Promise... promises) {
		return any(Arrays.asList(promises));
	}


	/**
	 * Pick the first result coming from any of the given promises and populate a new {@literal Promise}.
	 *
	 * @param promises The promises to use.
	 * @param       The type of the function result.
	 * @return a {@link Promise}.
	 */
	@SuppressWarnings("unchecked")
	public static  Promise any(List> promises) {
		Assert.isTrue(promises.size() > 0, "Must aggregate at least one promise");

		MergeAction mergeAction = new MergeAction(SynchronousDispatcher.INSTANCE, promises);

		return mergeAction.next();
	}


    /**
     * Aggregate given promises into a new a {@literal Promise} that will be fulfilled when all of the given {@literal
     * Promise Promises} have been fulfilled.
     *
     * @param promises The promises to use.
     * @param       The type of the function result.
     * @return a {@link Promise}.
     */
    private static  Promise> multiWhen(Promise... promises) {
        return when(Arrays.asList(promises));
    }

}