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

org.zodiac.sdk.async.promises.AsyncPromise Maven / Gradle / Ivy

package org.zodiac.sdk.async.promises;

import org.zodiac.sdk.async.promises.PromiseContext.Key;

/**
 * An asynchronous promise.  Unlike traditional promises that can be chained
 * together, these promises expect to that the logic they will trigger runs
 * asynchronously, and that continuing the chain of promises will occur some
 * time in the future.
 * 

* Promises can be chained together. *

*

Asynchronous promises have a PromiseContext which can be used to pass * additional objects along the chain of promises. *

* */ public abstract class AsyncPromise { public static AsyncPromise create(Logic toRun) { return new PromiseImpl<>(toRun); } public static AsyncPromise create(SimpleLogic toRun) { return new PromiseImpl<>(toRun); } abstract Key key(); /** * Run the promise, invoking the passed trigger with a result when the work * has completed. * @param input The input data * @param onDone The trigger * @return This. */ public abstract AsyncPromise start(T input, Trigger onDone); /** * Run the promise, using a no-op trigger, for promises that do not * need to pass back a result. * @param input The input * @return This. */ public final AsyncPromise start(final T input) { AsyncPromise.this.start(input, new Trigger() { @Override public void trigger(R obj, Throwable thrown) { if (thrown != null) { failed(thrown, key(), input); } } }); return this; } /** * Run the promise, using null as input (useful for instances whose * first type parameter is void). * * @return This. */ public final AsyncPromise start() { return start(null); } /** * Use this key to attach the input to the promise context. If set, * the input parameter will be automatically added to the context before * subsequent promises are called. * * @param key They key * @return This. */ public abstract AsyncPromise usingKey(PromiseContext.Key key); /** * Run an additional promise with new input data when this one * completes. * * @param The input type to the next promise * @param The output type of the next promise * @param q The input to the next promise * @param p The next promise * @return A promise that merges this and the passed one */ public final AsyncPromise then(final Q q, final AsyncPromise p) { AsyncPromise interim = new PromiseImpl<>(new Logic() { @Override public void run(R data, Trigger next, PromiseContext context) throws Exception { next.trigger(q, null); } }); return this.then(interim).then(p); } /** * Run an additional promise with new input data when this one * completes. * * @param The input type to the next promise * @param The output type of the next promise * @param q The input to the next promise * @param logic p The next unit of logic to run * @return A promise that merges this and the passed one */ public final AsyncPromise then(final Q q, final Logic logic) { AsyncPromise promise = new PromiseImpl<>(logic); return then(q, promise); } /** * Chain another promise to be run against the output of this one. * * @param The type of the next promise's output * @param logic The next promise * @return A promise which combine this and the next one */ public abstract AsyncPromise then(AsyncPromise logic); /** * Chain another promise to be run against the output of this one. * * @param The type of the next promise's output * @param next The logic to run against this promise's result * @return A promise which combine this and the next one */ public final AsyncPromise then(final SimpleLogic next) { return then(new Logic(){ @Override public void run(R data, Trigger trigger, PromiseContext context) throws Exception { next.run(data, trigger); } }); } /** * Chain another promise to be run against the output of this one. * * @param The type of the next promise's output * @param next The logic to run against this promise's result * @return A promise which combine this and the next one */ public final AsyncPromise then(Logic next) { AsyncPromise p = new PromiseImpl<>(next); return then(p); } abstract void setParent(AsyncPromise parent); abstract void failed(Throwable thrown, PromiseContext.Key key, R input); /** * Attach a failure handler to handle asynchronous failures. * The handler will be notified if promise execution is aborted * because of an error, and may run cleanup logic or whatever * is necessary. *

* If multiple faiure handlers are added at different points in * assembling a chain of AsyncPromises, the one nearest to the * failure will be called first; if it returns true, earlier * failure handlers will also be notified - the failure notification * propagates backward toward the beginning of the chain. *

* * @param failure The handler * @return This. */ public abstract AsyncPromise onFailure(FailureHandler failure); abstract boolean hasFailureHandler(); abstract PromiseContext context(); }