Skip to content

Commit 6670080

Browse files
Merge pull request #403 from zsxwing/cast
Implemented the 'cast' and 'ofType' operators
2 parents 440aa4d + da870a5 commit 6670080

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

rxjava-core/src/main/java/rx/Observable.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import rx.operators.OperationAverage;
3434
import rx.operators.OperationBuffer;
3535
import rx.operators.OperationCache;
36+
import rx.operators.OperationCast;
3637
import rx.operators.OperationCombineLatest;
3738
import rx.operators.OperationConcat;
3839
import rx.operators.OperationDebounce;
@@ -4369,6 +4370,44 @@ public BlockingObservable<T> toBlockingObservable() {
43694370
return BlockingObservable.from(this);
43704371
}
43714372

4373+
/**
4374+
* Converts the elements of an observable sequence to the specified type.
4375+
*
4376+
* @param klass
4377+
* The target class type which the elements will be converted to.
4378+
*
4379+
* @return An observable sequence that contains each element of the source
4380+
* sequence converted to the specified type.
4381+
*
4382+
* @see <a
4383+
* href="http://msdn.microsoft.com/en-us/library/hh211842(v=vs.103).aspx">MSDN:
4384+
* Observable.Cast</a>
4385+
*/
4386+
public <R> Observable<R> cast(final Class<R> klass) {
4387+
return create(OperationCast.cast(this, klass));
4388+
}
4389+
4390+
/**
4391+
* Filters the elements of an observable sequence based on the specified
4392+
* type.
4393+
*
4394+
* @param klass
4395+
* The class type to filter the elements in the source sequence
4396+
* on.
4397+
*
4398+
* @return An observable sequence that contains elements from the input
4399+
* sequence of type klass.
4400+
*
4401+
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229380(v=vs.103).aspx">MSDN: Observable.OfType</a>
4402+
*/
4403+
public <R> Observable<R> ofType(final Class<R> klass) {
4404+
return filter(new Func1<T, Boolean>() {
4405+
public Boolean call(T t) {
4406+
return klass.isInstance(t);
4407+
}
4408+
}).cast(klass);
4409+
}
4410+
43724411
/**
43734412
* Whether a given {@link Function} is an internal implementation inside rx.* packages or not.
43744413
* <p>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package rx.operators;
2+
3+
import static org.mockito.Mockito.mock;
4+
import static org.mockito.Mockito.never;
5+
import static org.mockito.Mockito.times;
6+
import static org.mockito.Mockito.verify;
7+
8+
import org.junit.Test;
9+
10+
import rx.Observable;
11+
import rx.Observable.OnSubscribeFunc;
12+
import rx.Observer;
13+
import rx.util.functions.Func1;
14+
15+
/**
16+
* Converts the elements of an observable sequence to the specified type.
17+
*/
18+
public class OperationCast {
19+
20+
public static <T, R> OnSubscribeFunc<R> cast(
21+
Observable<? extends T> source, final Class<R> klass) {
22+
return OperationMap.map(source, new Func1<T, R>() {
23+
public R call(T t) {
24+
return klass.cast(t);
25+
}
26+
});
27+
}
28+
29+
public static class UnitTest {
30+
31+
@Test
32+
public void testCast() {
33+
Observable<?> source = Observable.from(1, 2);
34+
Observable<Integer> observable = Observable.create(cast(source,
35+
Integer.class));
36+
37+
@SuppressWarnings("unchecked")
38+
Observer<Integer> aObserver = mock(Observer.class);
39+
observable.subscribe(aObserver);
40+
verify(aObserver, times(1)).onNext(1);
41+
verify(aObserver, times(1)).onNext(1);
42+
verify(aObserver, never()).onError(
43+
org.mockito.Matchers.any(Throwable.class));
44+
verify(aObserver, times(1)).onCompleted();
45+
}
46+
47+
@Test
48+
public void testCastWithWrongType() {
49+
Observable<?> source = Observable.from(1, 2);
50+
Observable<Boolean> observable = Observable.create(cast(source,
51+
Boolean.class));
52+
53+
@SuppressWarnings("unchecked")
54+
Observer<Boolean> aObserver = mock(Observer.class);
55+
observable.subscribe(aObserver);
56+
verify(aObserver, times(1)).onError(
57+
org.mockito.Matchers.any(ClassCastException.class));
58+
}
59+
}
60+
61+
}

rxjava-core/src/test/java/rx/ObservableTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import static org.mockito.Mockito.*;
2121

2222
import java.util.ArrayList;
23+
import java.util.LinkedList;
24+
import java.util.List;
2325
import java.util.concurrent.CountDownLatch;
2426
import java.util.concurrent.TimeUnit;
2527
import java.util.concurrent.atomic.AtomicInteger;
@@ -701,4 +703,42 @@ public void onNext(String v) {
701703
fail("It should be a NumberFormatException");
702704
}
703705
}
706+
707+
@Test
708+
public void testOfType() {
709+
Observable<String> observable = Observable.from(1, "abc", false, 2L).ofType(String.class);
710+
711+
@SuppressWarnings("unchecked")
712+
Observer<Object> aObserver = mock(Observer.class);
713+
observable.subscribe(aObserver);
714+
verify(aObserver, never()).onNext(1);
715+
verify(aObserver, times(1)).onNext("abc");
716+
verify(aObserver, never()).onNext(false);
717+
verify(aObserver, never()).onNext(2L);
718+
verify(aObserver, never()).onError(
719+
org.mockito.Matchers.any(Throwable.class));
720+
verify(aObserver, times(1)).onCompleted();
721+
}
722+
723+
@Test
724+
public void testOfTypeWithPolymorphism() {
725+
ArrayList<Integer> l1 = new ArrayList<Integer>();
726+
l1.add(1);
727+
LinkedList<Integer> l2 = new LinkedList<Integer>();
728+
l2.add(2);
729+
730+
@SuppressWarnings("rawtypes")
731+
Observable<List> observable = Observable.<Object>from(l1, l2, "123").ofType(List.class);
732+
733+
@SuppressWarnings("unchecked")
734+
Observer<Object> aObserver = mock(Observer.class);
735+
observable.subscribe(aObserver);
736+
verify(aObserver, times(1)).onNext(l1);
737+
verify(aObserver, times(1)).onNext(l2);
738+
verify(aObserver, never()).onNext("123");
739+
verify(aObserver, never()).onError(
740+
org.mockito.Matchers.any(Throwable.class));
741+
verify(aObserver, times(1)).onCompleted();
742+
}
743+
704744
}

0 commit comments

Comments
 (0)