1
1
/**
2
2
* Copyright 2014 Netflix, Inc.
3
- *
3
+ *
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
6
6
* You may obtain a copy of the License at
7
- *
7
+ *
8
8
* http://www.apache.org/licenses/LICENSE-2.0
9
- *
9
+ *
10
10
* Unless required by applicable law or agreed to in writing, software
11
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -79,7 +79,7 @@ public static <T> BlockingObservable<T> from(final Observable<? extends T> o) {
79
79
* need the {@link Subscriber#onCompleted()} or {@link Subscriber#onError(Throwable)} methods.
80
80
* <p>
81
81
* <img width="640" height="330" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.forEach.png" alt="">
82
- *
82
+ *
83
83
* @param onNext
84
84
* the {@link Action1} to invoke for each item emitted by the {@code BlockingObservable}
85
85
* @throws RuntimeException
@@ -143,7 +143,7 @@ public void onNext(T args) {
143
143
* Returns an {@link Iterator} that iterates over all items emitted by this {@code BlockingObservable}.
144
144
* <p>
145
145
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.getIterator.png" alt="">
146
- *
146
+ *
147
147
* @return an {@link Iterator} that can iterate over the items emitted by this {@code BlockingObservable}
148
148
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#transformations-tofuture-toiterable-and-toiteratorgetiterator">RxJava Wiki: getIterator()</a>
149
149
*/
@@ -154,21 +154,21 @@ public Iterator<T> getIterator() {
154
154
/**
155
155
* Returns the first item emitted by this {@code BlockingObservable}, or throws
156
156
* {@code NoSuchElementException} if it emits no items.
157
- *
157
+ *
158
158
* @return the first item emitted by this {@code BlockingObservable}
159
159
* @throws NoSuchElementException
160
160
* if this {@code BlockingObservable} emits no items
161
161
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#first-and-firstordefault">RxJava Wiki: first()</a>
162
162
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229177.aspx">MSDN: Observable.First</a>
163
163
*/
164
164
public T first () {
165
- return from (o .first ()). single ( );
165
+ return blockForSingle (o .first ());
166
166
}
167
167
168
168
/**
169
169
* Returns the first item emitted by this {@code BlockingObservable} that matches a predicate, or throws
170
170
* {@code NoSuchElementException} if it emits no such item.
171
- *
171
+ *
172
172
* @param predicate
173
173
* a predicate function to evaluate items emitted by this {@code BlockingObservable}
174
174
* @return the first item emitted by this {@code BlockingObservable} that matches the predicate
@@ -178,13 +178,13 @@ public T first() {
178
178
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229739.aspx">MSDN: Observable.First</a>
179
179
*/
180
180
public T first (Func1 <? super T , Boolean > predicate ) {
181
- return from (o .first (predicate )). single ( );
181
+ return blockForSingle (o .first (predicate ));
182
182
}
183
183
184
184
/**
185
185
* Returns the first item emitted by this {@code BlockingObservable}, or a default value if it emits no
186
186
* items.
187
- *
187
+ *
188
188
* @param defaultValue
189
189
* a default value to return if this {@code BlockingObservable} emits no items
190
190
* @return the first item emitted by this {@code BlockingObservable}, or the default value if it emits no
@@ -193,13 +193,13 @@ public T first(Func1<? super T, Boolean> predicate) {
193
193
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229320.aspx">MSDN: Observable.FirstOrDefault</a>
194
194
*/
195
195
public T firstOrDefault (T defaultValue ) {
196
- return from (o .take ( 1 )).singleOrDefault (defaultValue );
196
+ return blockForSingle (o .map ( Functions .< T > identity ( )).firstOrDefault (defaultValue ) );
197
197
}
198
198
199
199
/**
200
200
* Returns the first item emitted by this {@code BlockingObservable} that matches a predicate, or a default
201
201
* value if it emits no such items.
202
- *
202
+ *
203
203
* @param defaultValue
204
204
* a default value to return if this {@code BlockingObservable} emits no matching items
205
205
* @param predicate
@@ -210,31 +210,31 @@ public T firstOrDefault(T defaultValue) {
210
210
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229759.aspx">MSDN: Observable.FirstOrDefault</a>
211
211
*/
212
212
public T firstOrDefault (T defaultValue , Func1 <? super T , Boolean > predicate ) {
213
- return from (o .filter (predicate )) .firstOrDefault (defaultValue );
213
+ return blockForSingle (o .filter (predicate ). map ( Functions .< T > identity ()) .firstOrDefault (defaultValue ) );
214
214
}
215
215
216
216
/**
217
217
* Returns the last item emitted by this {@code BlockingObservable}, or throws
218
218
* {@code NoSuchElementException} if this {@code BlockingObservable} emits no items.
219
219
* <p>
220
220
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.last.png" alt="">
221
- *
221
+ *
222
222
* @return the last item emitted by this {@code BlockingObservable}
223
223
* @throws NoSuchElementException
224
224
* if this {@code BlockingObservable} emits no items
225
225
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#last-and-lastordefault">RxJava Wiki: last()</a>
226
226
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.last.aspx">MSDN: Observable.Last</a>
227
227
*/
228
228
public T last () {
229
- return from (o .last ()). single ( );
229
+ return blockForSingle (o .last ());
230
230
}
231
231
232
232
/**
233
233
* Returns the last item emitted by this {@code BlockingObservable} that matches a predicate, or throws
234
234
* {@code NoSuchElementException} if it emits no such items.
235
235
* <p>
236
236
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.last.p.png" alt="">
237
- *
237
+ *
238
238
* @param predicate
239
239
* a predicate function to evaluate items emitted by the {@code BlockingObservable}
240
240
* @return the last item emitted by the {@code BlockingObservable} that matches the predicate
@@ -244,15 +244,15 @@ public T last() {
244
244
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.last.aspx">MSDN: Observable.Last</a>
245
245
*/
246
246
public T last (final Func1 <? super T , Boolean > predicate ) {
247
- return from (o .last (predicate )). single ( );
247
+ return blockForSingle (o .last (predicate ));
248
248
}
249
249
250
250
/**
251
251
* Returns the last item emitted by this {@code BlockingObservable}, or a default value if it emits no
252
252
* items.
253
253
* <p>
254
254
* <img width="640" height="310" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.lastOrDefault.png" alt="">
255
- *
255
+ *
256
256
* @param defaultValue
257
257
* a default value to return if this {@code BlockingObservable} emits no items
258
258
* @return the last item emitted by the {@code BlockingObservable}, or the default value if it emits no
@@ -261,15 +261,15 @@ public T last(final Func1<? super T, Boolean> predicate) {
261
261
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.lastordefault.aspx">MSDN: Observable.LastOrDefault</a>
262
262
*/
263
263
public T lastOrDefault (T defaultValue ) {
264
- return from (o .takeLast ( 1 )).singleOrDefault (defaultValue );
264
+ return blockForSingle (o .map ( Functions .< T > identity ( )).lastOrDefault (defaultValue ) );
265
265
}
266
266
267
267
/**
268
268
* Returns the last item emitted by this {@code BlockingObservable} that matches a predicate, or a default
269
269
* value if it emits no such items.
270
270
* <p>
271
271
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.lastOrDefault.p.png" alt="">
272
- *
272
+ *
273
273
* @param defaultValue
274
274
* a default value to return if this {@code BlockingObservable} emits no matching items
275
275
* @param predicate
@@ -280,15 +280,15 @@ public T lastOrDefault(T defaultValue) {
280
280
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.lastordefault.aspx">MSDN: Observable.LastOrDefault</a>
281
281
*/
282
282
public T lastOrDefault (T defaultValue , Func1 <? super T , Boolean > predicate ) {
283
- return from (o .filter (predicate )) .lastOrDefault (defaultValue );
283
+ return blockForSingle (o .filter (predicate ). map ( Functions .< T > identity ()) .lastOrDefault (defaultValue ) );
284
284
}
285
285
286
286
/**
287
287
* Returns an {@link Iterable} that always returns the item most recently emitted by this
288
288
* {@code BlockingObservable}.
289
289
* <p>
290
290
* <img width="640" height="490" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.mostRecent.png" alt="">
291
- *
291
+ *
292
292
* @param initialValue
293
293
* the initial value that the {@link Iterable} sequence will yield if this
294
294
* {@code BlockingObservable} has not yet emitted an item
@@ -306,7 +306,7 @@ public Iterable<T> mostRecent(T initialValue) {
306
306
* returns that item.
307
307
* <p>
308
308
* <img width="640" height="490" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.next.png" alt="">
309
- *
309
+ *
310
310
* @return an {@link Iterable} that blocks upon each iteration until this {@code BlockingObservable} emits
311
311
* a new item, whereupon the Iterable returns that item
312
312
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#next">RxJava Wiki: next()</a>
@@ -325,7 +325,7 @@ public Iterable<T> next() {
325
325
* <p>
326
326
* Note also that an {@code onNext} directly followed by {@code onCompleted} might hide the {@code onNext}
327
327
* event.
328
- *
328
+ *
329
329
* @return an Iterable that always returns the latest item emitted by this {@code BlockingObservable}
330
330
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#latest">RxJava wiki: latest()</a>
331
331
* @see <a href="http://msdn.microsoft.com/en-us/library/hh212115.aspx">MSDN: Observable.Latest</a>
@@ -339,29 +339,29 @@ public Iterable<T> latest() {
339
339
* throw a {@code NoSuchElementException}.
340
340
* <p>
341
341
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.single.png" alt="">
342
- *
342
+ *
343
343
* @return the single item emitted by this {@code BlockingObservable}
344
344
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#single-and-singleordefault">RxJava Wiki: single()</a>
345
345
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.single.aspx">MSDN: Observable.Single</a>
346
346
*/
347
347
public T single () {
348
- return from (o .single ()). toIterable (). iterator (). next ( );
348
+ return blockForSingle (o .single ());
349
349
}
350
350
351
351
/**
352
352
* If this {@code BlockingObservable} completes after emitting a single item that matches a given predicate,
353
353
* return that item, otherwise throw a {@code NoSuchElementException}.
354
354
* <p>
355
355
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.single.p.png" alt="">
356
- *
356
+ *
357
357
* @param predicate
358
358
* a predicate function to evaluate items emitted by this {@link BlockingObservable}
359
359
* @return the single item emitted by this {@code BlockingObservable} that matches the predicate
360
360
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#single-and-singleordefault">RxJava Wiki: single()</a>
361
361
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.single.aspx">MSDN: Observable.Single</a>
362
362
*/
363
363
public T single (Func1 <? super T , Boolean > predicate ) {
364
- return from (o .single (predicate )). toIterable (). iterator (). next ( );
364
+ return blockForSingle (o .single (predicate ));
365
365
}
366
366
367
367
/**
@@ -370,7 +370,7 @@ public T single(Func1<? super T, Boolean> predicate) {
370
370
* value.
371
371
* <p>
372
372
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.singleOrDefault.png" alt="">
373
- *
373
+ *
374
374
* @param defaultValue
375
375
* a default value to return if this {@code BlockingObservable} emits no items
376
376
* @return the single item emitted by this {@code BlockingObservable}, or the default value if it emits no
@@ -379,7 +379,7 @@ public T single(Func1<? super T, Boolean> predicate) {
379
379
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.singleordefault.aspx">MSDN: Observable.SingleOrDefault</a>
380
380
*/
381
381
public T singleOrDefault (T defaultValue ) {
382
- return from (o .map (Functions .<T >identity ()).singleOrDefault (defaultValue )). single ( );
382
+ return blockForSingle (o .map (Functions .<T >identity ()).singleOrDefault (defaultValue ));
383
383
}
384
384
385
385
/**
@@ -388,7 +388,7 @@ public T singleOrDefault(T defaultValue) {
388
388
* emits no items, return a default value.
389
389
* <p>
390
390
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.singleOrDefault.p.png" alt="">
391
- *
391
+ *
392
392
* @param defaultValue
393
393
* a default value to return if this {@code BlockingObservable} emits no matching items
394
394
* @param predicate
@@ -399,7 +399,7 @@ public T singleOrDefault(T defaultValue) {
399
399
* @see <a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable.singleordefault.aspx">MSDN: Observable.SingleOrDefault</a>
400
400
*/
401
401
public T singleOrDefault (T defaultValue , Func1 <? super T , Boolean > predicate ) {
402
- return from (o .filter (predicate )) .singleOrDefault (defaultValue );
402
+ return blockForSingle (o .filter (predicate ). map ( Functions .< T > identity ()) .singleOrDefault (defaultValue ) );
403
403
}
404
404
405
405
/**
@@ -412,7 +412,7 @@ public T singleOrDefault(T defaultValue, Func1<? super T, Boolean> predicate) {
412
412
* If the {@code BlockingObservable} may emit more than one item, use {@code Observable.toList().toBlocking().toFuture()}.
413
413
* <p>
414
414
* <img width="640" height="395" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.toFuture.png" alt="">
415
- *
415
+ *
416
416
* @return a {@link Future} that expects a single item to be emitted by this {@code BlockingObservable}
417
417
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#transformations-tofuture-toiterable-and-toiteratorgetiterator">RxJava Wiki: toFuture()</a>
418
418
*/
@@ -424,7 +424,7 @@ public Future<T> toFuture() {
424
424
* Converts this {@code BlockingObservable} into an {@link Iterable}.
425
425
* <p>
426
426
* <img width="640" height="315" src="https://github.com/ReactiveX/RxJava/wiki/images/rx-operators/B.toIterable.png" alt="">
427
- *
427
+ *
428
428
* @return an {@link Iterable} version of this {@code BlockingObservable}
429
429
* @see <a href="https://github.com/ReactiveX/RxJava/wiki/Blocking-Observable-Operators#transformations-tofuture-toiterable-and-toiteratorgetiterator">RxJava Wiki: toIterable()</a>
430
430
*/
@@ -436,4 +436,52 @@ public Iterator<T> iterator() {
436
436
}
437
437
};
438
438
}
439
+
440
+ /**
441
+ * Helper method which handles the actual blocking for a single response.
442
+ * <p>
443
+ * If the {@link Observable} errors, it will be thrown right away.
444
+ *
445
+ * @return the actual item.
446
+ */
447
+ private T blockForSingle (final Observable <? extends T > observable ) {
448
+ final AtomicReference <T > returnItem = new AtomicReference <T >();
449
+ final AtomicReference <Throwable > returnException = new AtomicReference <Throwable >();
450
+ final CountDownLatch latch = new CountDownLatch (1 );
451
+
452
+ observable .subscribe (new Subscriber <T >() {
453
+ @ Override
454
+ public void onCompleted () {
455
+ latch .countDown ();
456
+ }
457
+
458
+ @ Override
459
+ public void onError (final Throwable e ) {
460
+ returnException .set (e );
461
+ latch .countDown ();
462
+ }
463
+
464
+ @ Override
465
+ public void onNext (final T item ) {
466
+ returnItem .set (item );
467
+ }
468
+ });
469
+
470
+ try {
471
+ latch .await ();
472
+ } catch (InterruptedException e ) {
473
+ Thread .currentThread ().interrupt ();
474
+ throw new RuntimeException ("Interrupted while waiting for subscription to complete." , e );
475
+ }
476
+
477
+ if (returnException .get () != null ) {
478
+ if (returnException .get () instanceof RuntimeException ) {
479
+ throw (RuntimeException ) returnException .get ();
480
+ } else {
481
+ throw new RuntimeException (returnException .get ());
482
+ }
483
+ }
484
+
485
+ return returnItem .get ();
486
+ }
439
487
}
0 commit comments