/* * Copyright (c) OSGi Alliance 2015. All Rights Reserved. * * 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 org.osgi.util.promise; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Static helper methods for Promises. */ public class Promises { /** * Create a new Promise that has been resolved with the specified value. * * @param value The value of the resolved Promise. * @param <T> The value type associated with the returned Promise. * @return A new Promise that has been resolved with the specified value. */ public static <T> Promise<T> resolved(T value) { Deferred<T> def = new Deferred<T>(); def.resolve(value); return def.getPromise(); } /** * Create a new Promise that has been resolved with the specified failure. * * @param failure The failure of the resolved Promise. Must not be null. * @param <T> The value type associated with the returned Promise. * @return A new Promise that has been resolved with the specified failure. */ public static <T> Promise<T> failed(Throwable failure) { if (failure == null) throw new NullPointerException(); Deferred<T> def = new Deferred<T>(); def.fail(failure); return def.getPromise(); } /** * Create a new Promise that is a latch on the resolution of the specified Promises. * <p/> * The new Promise acts as a gate and must be resolved after all of the specified Promises are resolved. * * @param promises The Promises which must be resolved before the returned Promise must be resolved. Must not be * null. * @param <T> The value type of the List value associated with the returned Promise. * @param <S> A subtype of the value type of the List value associated with the returned Promise. * @return A Promise that is resolved only when all the specified Promises are resolved. The returned Promise will * be successfully resolved, with a List of the values in the order of the specified Promises, if all the specified * Promises are successfully resolved. The List in the returned Promise is the property of the caller and is * modifiable. The returned Promise will be resolved with a failure of FailedPromisesException if any of the * specified Promises are resolved with a failure. The failure FailedPromisesException must contain all of the * specified Promises which resolved with a failure. */ public static <T, S> Promise<List<T>> all(final Collection<Promise<S>> promises) { if (promises == null) throw new NullPointerException(); final Deferred<List<T>> result = new Deferred<List<T>>(); final Collection<Promise<?>> failedPromises = new ArrayList<Promise<?>>(); final List<T> resolvedValues = new ArrayList<T>(); if (promises.size() == 0) { result.resolve(resolvedValues); } for (final Promise<S> promise : promises) { promise.then(new Success<S, T>() { @Override public Promise<T> call(Promise<S> resolved) throws Exception { // "S is subtype of the value type of the List" @SuppressWarnings("unchecked") T value = (T) resolved.getValue(); resolvedValues.add(value); if (resolvedValues.size() == promises.size()) { result.resolve(resolvedValues); } else if (failedPromises.size() + resolvedValues.size() == promises.size()) { result.fail(new FailedPromisesException(failedPromises)); } return null; } }, new Failure() { @Override public void fail(Promise<?> resolved) throws Exception { failedPromises.add(resolved); if (failedPromises.size() + resolvedValues.size() == promises.size()) { result.fail(new FailedPromisesException(failedPromises)); } } }); } return result.getPromise(); } /** * Create a new Promise that is a latch on the resolution of the specified Promises. * <p/> * The new Promise acts as a gate and must be resolved after all of the specified Promises are resolved. * * @param promises The Promises which must be resolved before the returned Promise must be resolved. Must not be * null. * @param <T> The value type associated with the specified Promises. * @return A Promise that is resolved only when all the specified Promises are resolved. The returned Promise will * be successfully resolved, with a List of the values in the order of the specified Promises, if all the specified * Promises are successfully resolved. The List in the returned Promise is the property of the caller and is * modifiable. The returned Promise will be resolved with a failure of FailedPromisesException if any of the * specified Promises are resolved with a failure. The failure FailedPromisesException must contain all of the * specified Promises which resolved with a failure. */ public static <T> Promise<List<T>> all(final Promise<? extends T>... promises) { if (promises == null) throw new NullPointerException(); List<Promise<T>> list = new ArrayList<Promise<T>>(); for (Promise<? extends T> promise : promises) { @SuppressWarnings("unchecked") Promise<T> pt = (Promise<T>) promise; list.add(pt); } return all(list); } }