public static <T0, T1, R> Func1<Observer<R>, Subscription> zip( Observable<T0> w0, Observable<T1> w1, Func2<T0, T1, R> zipFunction) { Aggregator<R> a = new Aggregator<R>(Functions.fromFunc(zipFunction)); a.addObserver(new ZipObserver<R, T0>(a, w0)); a.addObserver(new ZipObserver<R, T1>(a, w1)); return a; }
@SuppressWarnings("unchecked") public static <R> Func1<Observer<R>, Subscription> zip( Collection<Observable<?>> ws, FuncN<R> zipFunction) { Aggregator a = new Aggregator(zipFunction); for (Observable w : ws) { ZipObserver zipObserver = new ZipObserver(a, w); a.addObserver(zipObserver); } return a; }
@Override public void onNext(T args) { try { a.next(this, args); } catch (Exception e) { onError(e); } }
@SuppressWarnings("unchecked") /* mock calls don't do generics */ @Test public void testAggregate3Types() { FuncN<String> zipr = getConcatZipr(); /* create the aggregator which will execute the zip function when all Observables provide values */ Aggregator<String> a = new Aggregator<String>(zipr); /* define a Observer to receive aggregated events */ Observer<String> aObserver = mock(Observer.class); a.call(aObserver); /* mock the Observable Observers that are 'pushing' data for us */ ZipObserver<String, String> r1 = mock(ZipObserver.class); ZipObserver<String, Integer> r2 = mock(ZipObserver.class); ZipObserver<String, int[]> r3 = mock(ZipObserver.class); /* pretend we're starting up */ a.addObserver(r1); a.addObserver(r2); a.addObserver(r3); /* simulate the Observables pushing data into the aggregator */ a.next(r1, "hello"); a.next(r2, 2); a.next(r3, new int[] {5, 6, 7}); verify(aObserver, never()).onError(any(Exception.class)); verify(aObserver, never()).onCompleted(); verify(aObserver, times(1)).onNext("hello2[5, 6, 7]"); }
@SuppressWarnings("unchecked") /* mock calls don't do generics */ @Test public void testAggregatorUnsubscribe() { FuncN<String> zipr = getConcatZipr(); /* create the aggregator which will execute the zip function when all Observables provide values */ Aggregator<String> a = new Aggregator<String>(zipr); /* define a Observer to receive aggregated events */ Observer<String> aObserver = mock(Observer.class); Subscription subscription = a.call(aObserver); /* mock the Observable Observers that are 'pushing' data for us */ ZipObserver<String, String> r1 = mock(ZipObserver.class); ZipObserver<String, String> r2 = mock(ZipObserver.class); /* pretend we're starting up */ a.addObserver(r1); a.addObserver(r2); /* simulate the Observables pushing data into the aggregator */ a.next(r1, "hello"); a.next(r2, "world"); verify(aObserver, never()).onError(any(Exception.class)); verify(aObserver, never()).onCompleted(); verify(aObserver, times(1)).onNext("helloworld"); subscription.unsubscribe(); a.next(r1, "hello"); a.next(r2, "again"); verify(aObserver, times(0)).onError(any(Exception.class)); verify(aObserver, never()).onCompleted(); // we don't want to be called again after an error verify(aObserver, times(0)).onNext("helloagain"); }
@SuppressWarnings("unchecked") /* mock calls don't do generics */ @Test public void testAggregatorEarlyCompletion() { FuncN<String> zipr = getConcatZipr(); /* create the aggregator which will execute the zip function when all Observables provide values */ Aggregator<String> a = new Aggregator<String>(zipr); /* define a Observer to receive aggregated events */ Observer<String> aObserver = mock(Observer.class); a.call(aObserver); /* mock the Observable Observers that are 'pushing' data for us */ ZipObserver<String, String> r1 = mock(ZipObserver.class); ZipObserver<String, String> r2 = mock(ZipObserver.class); /* pretend we're starting up */ a.addObserver(r1); a.addObserver(r2); /* simulate the Observables pushing data into the aggregator */ a.next(r1, "one"); a.next(r1, "two"); a.complete(r1); a.next(r2, "A"); InOrder inOrder = inOrder(aObserver); inOrder.verify(aObserver, never()).onError(any(Exception.class)); inOrder.verify(aObserver, never()).onCompleted(); inOrder.verify(aObserver, times(1)).onNext("oneA"); a.complete(r2); inOrder.verify(aObserver, never()).onError(any(Exception.class)); inOrder.verify(aObserver, times(1)).onCompleted(); inOrder.verify(aObserver, never()).onNext(anyString()); }
@Override public void onError(Exception e) { a.error(this, e); }
@Override public void onCompleted() { a.complete(this); }