/** * Add an {@link Action0} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param action the action that should be invoked for the effect * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision * @deprecated use {@link #addAction(Class, Action0)} */ @Deprecated public <G extends F> SubtypeEffectHandlerBuilder<F, E> add( final Class<G> effectClass, final Action0 action) { return addAction(effectClass, action); }
/** * Add an {@link Action1} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param action the action that should be invoked for the effect * @param scheduler the scheduler that should be used to invoke the action * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision * @deprecated use {@link #addConsumer(Class, Action1, Scheduler)} */ @Deprecated public <G extends F> SubtypeEffectHandlerBuilder<F, E> add( final Class<G> effectClass, final Action1<G> action, Scheduler scheduler) { return addConsumer(effectClass, action, scheduler); }
/** * Add an {@link Observable.Transformer} for handling effects of a given type. The handler will * receive all effect objects that extend the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the effect class to handle * @param effectHandler the effect handler for the given effect class * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision * @deprecated use {@link #addTransformer(Class, Transformer)} */ @Deprecated public <G extends F> SubtypeEffectHandlerBuilder<F, E> add( final Class<G> effectClass, final Transformer<G, E> effectHandler) { return addTransformer(effectClass, effectHandler); }
.addFunction( A.class, a -> { throw expectedException; }) .withFatalErrorHandler( new Func1<Transformer<? extends TestEffect, TestEvent>, Action1<Throwable>>() { @Override Transformer<TestEffect, TestEvent> router = builder.build();
/** * Add a {@link Func1} for handling effects of a given type. The function will be invoked once * for every received effect object that extends the given class. The returned event will be * forwarded to the Mobius loop. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param function the function that should be invoked for the effect * @param scheduler the scheduler that should be used when invoking the function * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision */ public <G extends F> SubtypeEffectHandlerBuilder<F, E> addFunction( final Class<G> effectClass, final Function<G, E> function, Scheduler scheduler) { //noinspection ResultOfMethodCallIgnored checkNotNull(effectClass); //noinspection ResultOfMethodCallIgnored checkNotNull(function); return addTransformer(effectClass, Transformers.fromFunction(function, scheduler)); }
/** * Add an {@link Action1} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param consumer the consumer that should be invoked for the effect * @param scheduler the scheduler that should be used to invoke the action * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision */ public <G extends F> SubtypeEffectHandlerBuilder<F, E> addConsumer( final Class<G> effectClass, final Action1<G> consumer, Scheduler scheduler) { //noinspection ResultOfMethodCallIgnored checkNotNull(effectClass); //noinspection ResultOfMethodCallIgnored checkNotNull(consumer); return addTransformer(effectClass, Transformers.<G, E>fromConsumer(consumer, scheduler)); }
/** * Add an {@link Action0} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param action the action that should be invoked for the effect * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision */ public <G extends F> SubtypeEffectHandlerBuilder<F, E> addAction( final Class<G> effectClass, final Action0 action) { //noinspection ResultOfMethodCallIgnored checkNotNull(effectClass); //noinspection ResultOfMethodCallIgnored checkNotNull(action); return addTransformer(effectClass, Transformers.<G, E>fromAction(action)); }
/** * Add an {@link Action1} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param action the action that should be invoked for the effect * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision * @deprecated use {@link #addConsumer(Class, Action1)} */ @Deprecated public <G extends F> SubtypeEffectHandlerBuilder<F, E> add( final Class<G> effectClass, final Action1<G> action) { return addConsumer(effectClass, action); }
/** * Add a {@link Func1} for handling effects of a given type. The function will be invoked once * for every received effect object that extends the given class. The returned event will be * forwarded to the Mobius loop. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param function the function that should be invoked for the effect * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision */ public <G extends F> SubtypeEffectHandlerBuilder<F, E> addFunction( final Class<G> effectClass, final Function<G, E> function) { //noinspection ResultOfMethodCallIgnored checkNotNull(effectClass); //noinspection ResultOfMethodCallIgnored checkNotNull(function); return addTransformer(effectClass, Transformers.fromFunction(function)); }
/** * Add an {@link Action0} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param action the action that should be invoked for the effect * @param scheduler the scheduler that should be used to invoke the action * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision * @deprecated use {@link #addAction(Class, Action0, Scheduler)} */ @Deprecated public <G extends F> SubtypeEffectHandlerBuilder<F, E> add( final Class<G> effectClass, final Action0 action, Scheduler scheduler) { return addAction(effectClass, action, scheduler); }
/** * Add an {@link Action0} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param action the action that should be invoked for the effect * @param scheduler the scheduler that should be used to invoke the action * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision */ public <G extends F> SubtypeEffectHandlerBuilder<F, E> addAction( final Class<G> effectClass, final Action0 action, Scheduler scheduler) { //noinspection ResultOfMethodCallIgnored checkNotNull(effectClass); //noinspection ResultOfMethodCallIgnored checkNotNull(action); return addTransformer(effectClass, Transformers.<G, E>fromAction(action, scheduler)); }
/** * Add an {@link Action1} for handling effects of a given type. The action will be invoked once * for every received effect object that extends the given class. * * <p>Adding handlers for two effect classes where one is a super-class of the other is * considered a collision and is not allowed. Registering the same class twice is also * considered a collision. * * @param effectClass the class to handle * @param consumer the consumer that should be invoked for the effect * @param <G> the effect class as a type parameter * @return this builder * @throws IllegalArgumentException if there is a handler collision */ public <G extends F> SubtypeEffectHandlerBuilder<F, E> addConsumer( final Class<G> effectClass, final Action1<G> consumer) { //noinspection ResultOfMethodCallIgnored checkNotNull(effectClass); //noinspection ResultOfMethodCallIgnored checkNotNull(consumer); return addTransformer(effectClass, Transformers.<G, E>fromConsumer(consumer)); }
@Test public void effectHandlersShouldBeImmutable() throws Exception { // redo some test setup for test case specific conditions publishSubject = PublishSubject.create(); testSubscriber = TestSubscriber.create(); RxMobius.SubtypeEffectHandlerBuilder<TestEffect, TestEvent> builder = RxMobius.<TestEffect, TestEvent>subtypeEffectHandler() .addTransformer(A.class, (Observable<A> as) -> as.map(a -> AEvent.create(a.id()))); Transformer<TestEffect, TestEvent> router = builder.build(); // this should not lead to the effects router being capable of handling B effects builder.addTransformer(B.class, (Observable<B> bs) -> bs.map(b -> BEvent.create(b.id()))); publishSubject.compose(router).subscribe(testSubscriber); B effect = B.create(84); publishSubject.onNext(effect); publishSubject.onCompleted(); testSubscriber.awaitTerminalEvent(3, TimeUnit.SECONDS); testSubscriber.assertError(new UnknownEffectException(effect)); }
@Before public void setUp() throws Exception { cConsumer = new TestConsumer<>(); dAction = new TestAction(); Transformer<TestEffect, TestEvent> router = RxMobius.<TestEffect, TestEvent>subtypeEffectHandler() .addTransformer(A.class, (Observable<A> as) -> as.map(a -> AEvent.create(a.id()))) .addTransformer(B.class, (Observable<B> bs) -> bs.map(b -> BEvent.create(b.id()))) .addConsumer(C.class, cConsumer) .addAction(D.class, dAction) .addFunction(E.class, e -> AEvent.create(e.id())) .build(); publishSubject = PublishSubject.create(); testSubscriber = TestSubscriber.create(); publishSubject.compose(router).subscribe(testSubscriber); }
/** * Create an {@link SubtypeEffectHandlerBuilder} for handling effects based on their type. * * @param <F> the effect type * @param <E> the event type */ public static <F, E> SubtypeEffectHandlerBuilder<F, E> subtypeEffectHandler() { return new SubtypeEffectHandlerBuilder<>(); }
@Test public void shouldReportEffectClassCollisionWhenAddingSuperclass() throws Exception { RxMobius.SubtypeEffectHandlerBuilder<TestEffect, TestEvent> builder = RxMobius.<TestEffect, TestEvent>subtypeEffectHandler() .addTransformer(Child.class, childObservable -> null); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("collision"); builder.addTransformer(Parent.class, parentObservable -> null); }
@Test public void shouldReportEffectClassCollisionWhenAddingSubclass() throws Exception { RxMobius.SubtypeEffectHandlerBuilder<TestEffect, TestEvent> builder = RxMobius.<TestEffect, TestEvent>subtypeEffectHandler() .addTransformer(Parent.class, observable -> null); thrown.expect(IllegalArgumentException.class); thrown.expectMessage("collision"); builder.addTransformer(Child.class, observable -> null); }