Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 340a61ee6c31ebd35b1d20ac814e1035e8c19fb7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
/*
 * Copyright (c) OSGi Alliance (2014, 2018). 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.lang.reflect.InvocationTargetException;

import org.osgi.annotation.versioning.ProviderType;
import org.osgi.util.function.Consumer;
import org.osgi.util.function.Function;
import org.osgi.util.function.Predicate;

/**
 * A Promise of a value.
 * <p>
 * A Promise represents a future value. It handles the interactions for
 * asynchronous processing. A {@link Deferred} object can be used to create a
 * Promise and later resolve the Promise. A Promise is used by the caller of an
 * asynchronous function to get the result or handle the error. The caller can
 * either get a callback when the Promise is resolved with a value or an error,
 * or the Promise can be used in chaining. In chaining, callbacks are provided
 * that receive the resolved Promise, and a new Promise is generated that
 * resolves based upon the result of a callback.
 * <p>
 * Both {@link #onResolve(Runnable) callbacks} and
 * {@link #then(Success, Failure) chaining} can be repeated any number of times,
 * even after the Promise has been resolved.
 * <p>
 * Example callback usage:
 * 
 * <pre>
 * Promise&lt;String&gt; foo = foo();
 * foo.onResolve(() -&gt; System.out.println("resolved"));
 * </pre>
 * 
 * Example chaining usage;
 * 
 * <pre>
 * Success&lt;String,String&gt; doubler = p -&gt; Promises
 * 		.resolved(p.getValue() + p.getValue());
 * Promise&lt;String&gt; foo = foo().then(doubler).then(doubler);
 * </pre>
 * 
 * @param <T> The value type associated with this Promise.
 * @ThreadSafe
 * @author $Id$
 */
@ProviderType
public interface Promise<T> {

	/**
	 * Returns whether this Promise has been resolved.
	 * 
	 * <p>
	 * This Promise may be successfully resolved or resolved with a failure.
	 * 
	 * @return {@code true} if this Promise was resolved either successfully or
	 *         with a failure; {@code false} if this Promise is unresolved.
	 */
	boolean isDone();

	/**
	 * Returns the value of this Promise.
	 * 
	 * <p>
	 * If this Promise is not {@link #isDone() resolved}, this method must block
	 * and wait for this Promise to be resolved before completing.
	 * 
	 * <p>
	 * If this Promise was successfully resolved, this method returns with the
	 * value of this Promise. If this Promise was resolved with a failure, this
	 * method must throw an {@code InvocationTargetException} with the
	 * {@link #getFailure() failure exception} as the cause.
	 * 
	 * @return The value of this resolved Promise.
	 * @throws InvocationTargetException If this Promise was resolved with a
	 *         failure. The cause of the {@code InvocationTargetException} is
	 *         the failure exception.
	 * @throws InterruptedException If the current thread was interrupted while
	 *         waiting.
	 */
	T getValue() throws InvocationTargetException, InterruptedException;

	/**
	 * Returns the failure of this Promise.
	 * 
	 * <p>
	 * If this Promise is not {@link #isDone() resolved}, this method must block
	 * and wait for this Promise to be resolved before completing.
	 * 
	 * <p>
	 * If this Promise was resolved with a failure, this method returns with the
	 * failure of this Promise. If this Promise was successfully resolved, this
	 * method must return {@code null}.
	 * 
	 * @return The failure of this resolved Promise or {@code null} if this
	 *         Promise was successfully resolved.
	 * @throws InterruptedException If the current thread was interrupted while
	 *         waiting.
	 */
	Throwable getFailure() throws InterruptedException;

	/**
	 * Register a callback to be called when this Promise is resolved.
	 * <p>
	 * The specified callback is called when this Promise is resolved either
	 * successfully or with a failure.
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * <p>
	 * Resolving this Promise <i>happens-before</i> any registered callback is
	 * called. That is, in a registered callback, {@link #isDone()} must return
	 * {@code true} and {@link #getValue()} and {@link #getFailure()} must not
	 * block.
	 * <p>
	 * A callback may be called on a different thread than the thread which
	 * registered the callback. So the callback must be thread safe but can rely
	 * upon that the registration of the callback <i>happens-before</i> the
	 * registered callback is called.
	 * 
	 * @param callback The callback to be called when this Promise is resolved.
	 *            Must not be {@code null}.
	 * @return This Promise.
	 */
	Promise<T> onResolve(Runnable callback);

	/**
	 * Register a callback to be called with the result of this Promise when
	 * this Promise is resolved successfully. The callback will not be called if
	 * this Promise is resolved with a failure.
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * <p>
	 * Resolving this Promise <i>happens-before</i> any registered callback is
	 * called. That is, in a registered callback, {@link #isDone()} must return
	 * {@code true} and {@link #getValue()} and {@link #getFailure()} must not
	 * block.
	 * <p>
	 * A callback may be called on a different thread than the thread which
	 * registered the callback. So the callback must be thread safe but can rely
	 * upon that the registration of the callback <i>happens-before</i> the
	 * registered callback is called.
	 * 
	 * @param success The Consumer callback that receives the value of this
	 *            Promise. Must not be {@code null}.
	 * @return This Promise.
	 * @since 1.1
	 */
	Promise<T> onSuccess(Consumer< ? super T> success);

	/**
	 * Register a callback to be called with the failure for this Promise when
	 * this Promise is resolved with a failure. The callback will not be called
	 * if this Promise is resolved successfully.
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * <p>
	 * Resolving this Promise <i>happens-before</i> any registered callback is
	 * called. That is, in a registered callback, {@link #isDone()} must return
	 * {@code true} and {@link #getValue()} and {@link #getFailure()} must not
	 * block.
	 * <p>
	 * A callback may be called on a different thread than the thread which
	 * registered the callback. So the callback must be thread safe but can rely
	 * upon that the registration of the callback <i>happens-before</i> the
	 * registered callback is called.
	 * 
	 * @param failure The Consumer callback that receives the failure of this
	 *            Promise. Must not be {@code null}.
	 * @return This Promise.
	 * @since 1.1
	 */
	Promise<T> onFailure(Consumer< ? super Throwable> failure);

	/**
	 * Chain a new Promise to this Promise with Success and Failure callbacks.
	 * <p>
	 * The specified {@link Success} callback is called when this Promise is
	 * successfully resolved and the specified {@link Failure} callback is
	 * called when this Promise is resolved with a failure.
	 * <p>
	 * This method returns a new Promise which is chained to this Promise. The
	 * returned Promise must be resolved when this Promise is resolved after the
	 * specified Success or Failure callback is executed. The result of the
	 * executed callback must be used to resolve the returned Promise. Multiple
	 * calls to this method can be used to create a chain of promises which are
	 * resolved in sequence.
	 * <p>
	 * If this Promise is successfully resolved, the Success callback is
	 * executed and the result Promise, if any, or thrown exception is used to
	 * resolve the returned Promise from this method. If this Promise is
	 * resolved with a failure, the Failure callback is executed and the
	 * returned Promise from this method is failed.
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * <p>
	 * Resolving this Promise <i>happens-before</i> any registered callback is
	 * called. That is, in a registered callback, {@link #isDone()} must return
	 * {@code true} and {@link #getValue()} and {@link #getFailure()} must not
	 * block.
	 * <p>
	 * A callback may be called on a different thread than the thread which
	 * registered the callback. So the callback must be thread safe but can rely
	 * upon that the registration of the callback <i>happens-before</i> the
	 * registered callback is called.
	 * 
	 * @param <R> The value type associated with the returned Promise.
	 * @param success The Success callback to be called when this Promise is
	 *            successfully resolved. May be {@code null} if no Success
	 *            callback is required. In this case, the returned Promise must
	 *            be resolved with the value {@code null} when this Promise is
	 *            successfully resolved.
	 * @param failure The Failure callback to be called when this Promise is
	 *            resolved with a failure. May be {@code null} if no Failure
	 *            callback is required.
	 * @return A new Promise which is chained to this Promise. The returned
	 *         Promise must be resolved when this Promise is resolved after the
	 *         specified Success or Failure callback, if any, is executed.
	 */
	<R> Promise<R> then(Success<? super T, ? extends R> success, Failure failure);

	/**
	 * Chain a new Promise to this Promise with a Success callback.
	 * <p>
	 * This method performs the same function as calling
	 * {@link #then(Success, Failure)} with the specified Success callback and
	 * {@code null} for the Failure callback.
	 * 
	 * @param <R> The value type associated with the returned Promise.
	 * @param success The Success callback to be called when this Promise is
	 *            successfully resolved. May be {@code null} if no Success
	 *            callback is required. In this case, the returned Promise must
	 *            be resolved with the value {@code null} when this Promise is
	 *            successfully resolved.
	 * @return A new Promise which is chained to this Promise. The returned
	 *         Promise must be resolved when this Promise is resolved after the
	 *         specified Success, if any, is executed.
	 * @see #then(Success, Failure)
	 */
	<R> Promise<R> then(Success<? super T, ? extends R> success);

	/**
	 * Chain a new Promise to this Promise with a Consumer callback that
	 * receives the value of this Promise when it is successfully resolved.
	 * <p>
	 * The specified {@link Consumer} is called when this Promise is resolved
	 * successfully.
	 * <p>
	 * This method returns a new Promise which is chained to this Promise. The
	 * returned Promise must be resolved when this Promise is resolved after the
	 * specified callback is executed. If the callback throws an exception, the
	 * returned Promise is failed with that exception. Otherwise the returned
	 * Promise is resolved with the success value from this Promise.
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * <p>
	 * Resolving this Promise <i>happens-before</i> any registered callback is
	 * called. That is, in a registered callback, {@link #isDone()} must return
	 * {@code true} and {@link #getValue()} and {@link #getFailure()} must not
	 * block.
	 * <p>
	 * A callback may be called on a different thread than the thread which
	 * registered the callback. So the callback must be thread safe but can rely
	 * upon that the registration of the callback <i>happens-before</i> the
	 * registered callback is called.
	 * 
	 * @param consumer The Consumer callback that receives the value of this
	 *            Promise. Must not be {@code null}.
	 * @return A new Promise which is chained to this Promise. The returned
	 *         Promise must be resolved when this Promise is resolved after the
	 *         specified Consumer is executed.
	 * @since 1.1
	 */
	Promise<T> thenAccept(Consumer< ? super T> consumer);

	/**
	 * Filter the value of this Promise.
	 * <p>
	 * If this Promise is successfully resolved, the returned Promise must
	 * either be resolved with the value of this Promise, if the specified
	 * Predicate accepts that value, or failed with a
	 * {@code NoSuchElementException}, if the specified Predicate does not
	 * accept that value. If the specified Predicate throws an exception, the
	 * returned Promise must be failed with the exception.
	 * <p>
	 * If this Promise is resolved with a failure, the returned Promise must be
	 * failed with that failure.
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * 
	 * @param predicate The Predicate to evaluate the value of this Promise.
	 *            Must not be {@code null}.
	 * @return A Promise that filters the value of this Promise.
	 */
	Promise<T> filter(Predicate<? super T> predicate);

	/**
	 * Map the value of this Promise.
	 * 
	 * <p>
	 * If this Promise is successfully resolved, the returned Promise must be
	 * resolved with the value of specified Function as applied to the value of
	 * this Promise. If the specified Function throws an exception, the returned
	 * Promise must be failed with the exception.
	 * 
	 * <p>
	 * If this Promise is resolved with a failure, the returned Promise must be
	 * failed with that failure.
	 * 
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * 
	 * @param <R> The value type associated with the returned Promise.
	 * @param mapper The Function that must map the value of this Promise to the
	 *        value that must be used to resolve the returned Promise. Must not
	 *        be {@code null}.
	 * @return A Promise that returns the value of this Promise as mapped by the
	 *         specified Function.
	 */
	<R> Promise<R> map(Function<? super T, ? extends R> mapper);

	/**
	 * FlatMap the value of this Promise.
	 * 
	 * <p>
	 * If this Promise is successfully resolved, the returned Promise must be
	 * resolved with the Promise from the specified Function as applied to the
	 * value of this Promise. If the specified Function throws an exception, the
	 * returned Promise must be failed with the exception.
	 * 
	 * <p>
	 * If this Promise is resolved with a failure, the returned Promise must be
	 * failed with that failure.
	 * 
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * 
	 * @param <R> The value type associated with the returned Promise.
	 * @param mapper The Function that must flatMap the value of this Promise to
	 *        a Promise that must be used to resolve the returned Promise. Must
	 *        not be {@code null}.
	 * @return A Promise that returns the value of this Promise as mapped by the
	 *         specified Function.
	 */
	<R> Promise<R> flatMap(Function<? super T, Promise<? extends R>> mapper);

	/**
	 * Recover from a failure of this Promise with a recovery value.
	 * 
	 * <p>
	 * If this Promise is successfully resolved, the returned Promise must be
	 * resolved with the value of this Promise.
	 * 
	 * <p>
	 * If this Promise is resolved with a failure, the specified Function is
	 * applied to this Promise to produce a recovery value.
	 * <ul>
	 * <li>If the recovery value is not {@code null}, the returned Promise must
	 * be resolved with the recovery value.</li>
	 * <li>If the recovery value is {@code null}, the returned Promise must be
	 * failed with the failure of this Promise.</li>
	 * <li>If the specified Function throws an exception, the returned Promise
	 * must be failed with that exception.</li>
	 * </ul>
	 * 
	 * <p>
	 * To recover from a failure of this Promise with a recovery value of
	 * {@code null}, the {@link #recoverWith(Function)} method must be used. The
	 * specified Function for {@link #recoverWith(Function)} can return
	 * {@code Promises.resolved(null)} to supply the desired {@code null} value.
	 * 
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * 
	 * @param recovery If this Promise resolves with a failure, the specified
	 *        Function is called to produce a recovery value to be used to
	 *        resolve the returned Promise. Must not be {@code null}.
	 * @return A Promise that resolves with the value of this Promise or
	 *         recovers from the failure of this Promise.
	 */
	Promise<T> recover(Function<Promise<?>, ? extends T> recovery);

	/**
	 * Recover from a failure of this Promise with a recovery Promise.
	 * 
	 * <p>
	 * If this Promise is successfully resolved, the returned Promise must be
	 * resolved with the value of this Promise.
	 * 
	 * <p>
	 * If this Promise is resolved with a failure, the specified Function is
	 * applied to this Promise to produce a recovery Promise.
	 * <ul>
	 * <li>If the recovery Promise is not {@code null}, the returned Promise
	 * must be resolved with the recovery Promise.</li>
	 * <li>If the recovery Promise is {@code null}, the returned Promise must be
	 * failed with the failure of this Promise.</li>
	 * <li>If the specified Function throws an exception, the returned Promise
	 * must be failed with that exception.</li>
	 * </ul>
	 * 
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * 
	 * @param recovery If this Promise resolves with a failure, the specified
	 *        Function is called to produce a recovery Promise to be used to
	 *        resolve the returned Promise. Must not be {@code null}.
	 * @return A Promise that resolves with the value of this Promise or
	 *         recovers from the failure of this Promise.
	 */
	Promise<T> recoverWith(Function<Promise<?>, Promise<? extends T>> recovery);

	/**
	 * Fall back to the value of the specified Promise if this Promise fails.
	 * 
	 * <p>
	 * If this Promise is successfully resolved, the returned Promise must be
	 * resolved with the value of this Promise.
	 * 
	 * <p>
	 * If this Promise is resolved with a failure, the successful result of the
	 * specified Promise is used to resolve the returned Promise. If the
	 * specified Promise is resolved with a failure, the returned Promise must
	 * be failed with the failure of this Promise rather than the failure of the
	 * specified Promise.
	 * 
	 * <p>
	 * This method may be called at any time including before and after this
	 * Promise has been resolved.
	 * 
	 * @param fallback The Promise whose value must be used to resolve the
	 *        returned Promise if this Promise resolves with a failure. Must not
	 *        be {@code null}.
	 * @return A Promise that returns the value of this Promise or falls back to
	 *         the value of the specified Promise.
	 */
	Promise<T> fallbackTo(Promise<? extends T> fallback);

	/**
	 * Time out the resolution of this Promise.
	 * <p>
	 * If this Promise is successfully resolved before the timeout, the returned
	 * Promise is resolved with the value of this Promise. If this Promise is
	 * resolved with a failure before the timeout, the returned Promise is
	 * resolved with the failure of this Promise. If the timeout is reached
	 * before this Promise is resolved, the returned Promise is failed with a
	 * {@link TimeoutException}.
	 * 
	 * @param milliseconds The time to wait in milliseconds. Zero and negative
	 *            time is treated as an immediate timeout.
	 * @return A Promise that is resolved when either this Promise is resolved
	 *         or the specified timeout is reached.
	 * @since 1.1
	 */
	Promise<T> timeout(long milliseconds);

	/**
	 * Delay after the resolution of this Promise.
	 * <p>
	 * Once this Promise is resolved, resolve the returned Promise with this
	 * Promise after the specified delay.
	 * 
	 * @param milliseconds The time to delay in milliseconds. Zero and negative
	 *            time is treated as no delay.
	 * @return A Promise that is resolved with this Promise after this Promise
	 *         is resolved and the specified delay has elapsed.
	 * @since 1.1
	 */
	Promise<T> delay(long milliseconds);
}

Back to the top