|
15 | 15 | */
|
16 | 16 | package rx;
|
17 | 17 |
|
| 18 | +import static org.junit.Assert.assertEquals; |
18 | 19 | import static org.mockito.Matchers.*;
|
19 | 20 | import static org.mockito.Mockito.*;
|
20 | 21 |
|
21 |
| -import java.util.ArrayList; |
22 |
| -import java.util.Arrays; |
23 |
| -import java.util.List; |
24 |
| -import java.util.Map; |
25 |
| -import java.util.concurrent.CountDownLatch; |
26 |
| -import java.util.concurrent.Future; |
27 |
| -import java.util.concurrent.TimeUnit; |
28 |
| -import java.util.concurrent.TimeoutException; |
| 22 | +import java.util.*; |
| 23 | +import java.util.concurrent.*; |
29 | 24 | import java.util.concurrent.atomic.AtomicReference;
|
30 | 25 |
|
31 | 26 | import org.junit.Before;
|
|
58 | 53 | import rx.plugins.RxJavaPlugins;
|
59 | 54 | import rx.util.AtomicObservableSubscription;
|
60 | 55 | import rx.util.AtomicObserver;
|
| 56 | +import rx.util.Exceptions; |
61 | 57 | import rx.util.Range;
|
62 | 58 | import rx.util.functions.Action0;
|
63 | 59 | import rx.util.functions.Action1;
|
@@ -1524,6 +1520,79 @@ public static <T> Observable<List<T>> toList(final Observable<T> that) {
|
1524 | 1520 | return _create(OperationToObservableList.toObservableList(that));
|
1525 | 1521 | }
|
1526 | 1522 |
|
| 1523 | + /** |
| 1524 | + * Converts an observable sequence to an Iterable. |
| 1525 | + * |
| 1526 | + * @param that the source Observable |
| 1527 | + * @return Observable converted to Iterable. |
| 1528 | + */ |
| 1529 | + public static <T> Iterable<T> toIterable(final Observable<T> that) { |
| 1530 | + final BlockingQueue<Notification<T>> notifications = new LinkedBlockingQueue<Notification<T>>(); |
| 1531 | + |
| 1532 | + materialize(that).subscribe(new Observer<Notification<T>>() { |
| 1533 | + @Override |
| 1534 | + public void onCompleted() { |
| 1535 | + // ignore |
| 1536 | + } |
| 1537 | + |
| 1538 | + @Override |
| 1539 | + public void onError(Exception e) { |
| 1540 | + // ignore |
| 1541 | + } |
| 1542 | + |
| 1543 | + @Override |
| 1544 | + public void onNext(Notification<T> args) { |
| 1545 | + notifications.offer(args); |
| 1546 | + } |
| 1547 | + }); |
| 1548 | + |
| 1549 | + final Iterator<T> it = new Iterator<T>() { |
| 1550 | + private Notification<T> buf; |
| 1551 | + |
| 1552 | + @Override |
| 1553 | + public boolean hasNext() { |
| 1554 | + if (buf == null) { |
| 1555 | + buf = take(); |
| 1556 | + } |
| 1557 | + return !buf.isOnCompleted(); |
| 1558 | + } |
| 1559 | + |
| 1560 | + @Override |
| 1561 | + public T next() { |
| 1562 | + if (buf == null) { |
| 1563 | + buf = take(); |
| 1564 | + } |
| 1565 | + if (buf.isOnError()) { |
| 1566 | + throw Exceptions.propagate(buf.getException()); |
| 1567 | + } |
| 1568 | + |
| 1569 | + T result = buf.getValue(); |
| 1570 | + buf = null; |
| 1571 | + return result; |
| 1572 | + } |
| 1573 | + |
| 1574 | + private Notification<T> take() { |
| 1575 | + try { |
| 1576 | + return notifications.take(); |
| 1577 | + } catch (InterruptedException e) { |
| 1578 | + throw Exceptions.propagate(e); |
| 1579 | + } |
| 1580 | + } |
| 1581 | + |
| 1582 | + @Override |
| 1583 | + public void remove() { |
| 1584 | + throw new UnsupportedOperationException("Read-only iterator"); |
| 1585 | + } |
| 1586 | + }; |
| 1587 | + |
| 1588 | + return new Iterable<T>() { |
| 1589 | + @Override |
| 1590 | + public Iterator<T> iterator() { |
| 1591 | + return it; |
| 1592 | + } |
| 1593 | + }; |
| 1594 | + } |
| 1595 | + |
1527 | 1596 | /**
|
1528 | 1597 | * Converts an Iterable sequence to an Observable sequence.
|
1529 | 1598 | *
|
@@ -2544,6 +2613,15 @@ public Observable<List<T>> toSortedList(final Object sortFunction) {
|
2544 | 2613 | return toSortedList(this, sortFunction);
|
2545 | 2614 | }
|
2546 | 2615 |
|
| 2616 | + /** |
| 2617 | + * Converts an observable sequence to an Iterable. |
| 2618 | + * |
| 2619 | + * @return Observable converted to Iterable. |
| 2620 | + */ |
| 2621 | + public Iterable<T> toIterable() { |
| 2622 | + return toIterable(this); |
| 2623 | + } |
| 2624 | + |
2547 | 2625 | public static class UnitTest {
|
2548 | 2626 |
|
2549 | 2627 | @Mock
|
@@ -2623,6 +2701,52 @@ public void testSequenceEqual() {
|
2623 | 2701 | verify(result, times(1)).onNext(false);
|
2624 | 2702 | }
|
2625 | 2703 |
|
| 2704 | + |
| 2705 | + @Test |
| 2706 | + public void testToIterable() { |
| 2707 | + Observable<String> obs = toObservable("one", "two", "three"); |
| 2708 | + |
| 2709 | + Iterator<String> it = obs.toIterable().iterator(); |
| 2710 | + |
| 2711 | + assertEquals(true, it.hasNext()); |
| 2712 | + assertEquals("one", it.next()); |
| 2713 | + |
| 2714 | + assertEquals(true, it.hasNext()); |
| 2715 | + assertEquals("two", it.next()); |
| 2716 | + |
| 2717 | + assertEquals(true, it.hasNext()); |
| 2718 | + assertEquals("three", it.next()); |
| 2719 | + |
| 2720 | + assertEquals(false, it.hasNext()); |
| 2721 | + |
| 2722 | + } |
| 2723 | + |
| 2724 | + @Test(expected = TestException.class) |
| 2725 | + public void testToIterableWithException() { |
| 2726 | + Observable<String> obs = create(new Func1<Observer<String>, Subscription>() { |
| 2727 | + |
| 2728 | + @Override |
| 2729 | + public Subscription call(Observer<String> observer) { |
| 2730 | + observer.onNext("one"); |
| 2731 | + observer.onError(new TestException()); |
| 2732 | + return Observable.noOpSubscription(); |
| 2733 | + } |
| 2734 | + }); |
| 2735 | + |
| 2736 | + Iterator<String> it = obs.toIterable().iterator(); |
| 2737 | + |
| 2738 | + assertEquals(true, it.hasNext()); |
| 2739 | + assertEquals("one", it.next()); |
| 2740 | + |
| 2741 | + assertEquals(true, it.hasNext()); |
| 2742 | + it.next(); |
| 2743 | + |
| 2744 | + } |
| 2745 | + |
| 2746 | + private static class TestException extends RuntimeException { |
| 2747 | + |
| 2748 | + } |
| 2749 | + |
2626 | 2750 | }
|
2627 | 2751 |
|
2628 | 2752 | }
|
0 commit comments