All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cookingfox.lapasse.impl.command.bus.DefaultRxCommandBus Maven / Gradle / Ivy

There is a newer version: 0.5.6
Show newest version
package com.cookingfox.lapasse.impl.command.bus;

import com.cookingfox.lapasse.api.command.Command;
import com.cookingfox.lapasse.api.command.bus.RxCommandBus;
import com.cookingfox.lapasse.api.command.handler.CommandHandler;
import com.cookingfox.lapasse.api.command.handler.MultiCommandHandler;
import com.cookingfox.lapasse.api.command.handler.RxCommandHandler;
import com.cookingfox.lapasse.api.command.handler.RxMultiCommandHandler;
import com.cookingfox.lapasse.api.event.Event;
import com.cookingfox.lapasse.api.event.bus.EventBus;
import com.cookingfox.lapasse.api.logging.LoggerCollection;
import com.cookingfox.lapasse.api.message.store.MessageStore;
import com.cookingfox.lapasse.api.state.State;
import com.cookingfox.lapasse.api.state.observer.RxStateObserver;
import rx.Observable;
import rx.Scheduler;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

import java.util.Collection;
import java.util.Objects;

/**
 * Default implementation of {@link RxCommandBus}.
 *
 * @param  The concrete type of the state object.
 */
public class DefaultRxCommandBus
        extends DefaultCommandBus
        implements RxCommandBus {

    //----------------------------------------------------------------------------------------------
    // STATIC INITIALIZER
    //----------------------------------------------------------------------------------------------

    /**
     * @see DefaultCommandBus#SUPPORTED
     */
    static {
        // add supported command handler implementations
        SUPPORTED.add(RxCommandHandler.class);
        SUPPORTED.add(RxMultiCommandHandler.class);
    }

    //----------------------------------------------------------------------------------------------
    // PROPERTIES
    //----------------------------------------------------------------------------------------------

    protected Scheduler observeOnScheduler;
    protected Scheduler subscribeOnScheduler;

    //----------------------------------------------------------------------------------------------
    // CONSTRUCTOR
    //----------------------------------------------------------------------------------------------

    public DefaultRxCommandBus(MessageStore messageStore,
                               EventBus eventBus,
                               LoggerCollection loggers,
                               RxStateObserver stateObserver) {
        super(messageStore, eventBus, loggers, stateObserver);
    }

    //----------------------------------------------------------------------------------------------
    // PUBLIC METHODS
    //----------------------------------------------------------------------------------------------

    @Override
    public void setObserveOnScheduler(Scheduler observeOnScheduler) {
        this.observeOnScheduler = Objects.requireNonNull(observeOnScheduler,
                "Scheduler can not be null");
    }

    @Override
    public void setSubscribeOnScheduler(Scheduler subscribeOnScheduler) {
        this.subscribeOnScheduler = Objects.requireNonNull(subscribeOnScheduler,
                "Scheduler can not be null");
    }

    //----------------------------------------------------------------------------------------------
    // PROTECTED METHODS
    //----------------------------------------------------------------------------------------------

    /**
     * Apply `observeOn` and `subscribeOn` schedulers to observable.
     *
     * @param  The value type that the observable will emit.
     * @return Observable with the schedulers applied.
     */
    protected  Observable.Transformer applySchedulers() {
        return new Observable.Transformer() {
            @Override
            public Observable call(Observable observable) {
                return observable
                        .subscribeOn(getSubscribeOnScheduler())
                        .observeOn(getObserveOnScheduler());
            }
        };
    }

    @Override
    protected void executeCommandHandler(S state, final Command command,
                                         CommandHandler handler) {
        // not an Rx implementation: use default functionality
        if (!(handler instanceof RxCommandHandler)) {
            super.executeCommandHandler(state, command, handler);
            return;
        }

        try {
            ((RxCommandHandler) handler).handle(state, command)
                    .compose(this.applySchedulers())
                    .subscribe(new Action1() {
                        @Override
                        public void call(Event event) {
                            handleResult(null, command, event);
                        }
                    }, new Action1() {
                        @Override
                        public void call(Throwable error) {
                            handleResult(error, command, null);
                        }
                    });
        } catch (Throwable error) {
            handleResult(error, command, null);
        }
    }

    @Override
    protected void executeMultiCommandHandler(S state, final Command command,
                                              MultiCommandHandler handler) {
        // not an Rx implementation: use default functionality
        if (!(handler instanceof RxMultiCommandHandler)) {
            super.executeMultiCommandHandler(state, command, handler);
            return;
        }

        try {
            ((RxMultiCommandHandler) handler).handle(state, command)
                    .compose(this.>applySchedulers())
                    .subscribe(new Action1>() {
                        @Override
                        public void call(Collection events) {
                            handleMultiResult(null, command, events);
                        }
                    }, new Action1() {
                        @Override
                        public void call(Throwable error) {
                            handleMultiResult(error, command, null);
                        }
                    });
        } catch (Throwable error) {
            handleMultiResult(error, command, null);
        }
    }

    /**
     * Returns the `observeOn` scheduler. Sets it to {@link Schedulers#immediate()} if it is null.
     *
     * @return The `observeOn` scheduler.
     */
    protected Scheduler getObserveOnScheduler() {
        if (observeOnScheduler == null) {
            observeOnScheduler = Schedulers.immediate();
        }

        return observeOnScheduler;
    }

    /**
     * Returns the `subscribeOn` scheduler. Sets it to {@link Schedulers#immediate()} if it is null.
     *
     * @return The `subscribeOn` scheduler.
     */
    protected Scheduler getSubscribeOnScheduler() {
        if (subscribeOnScheduler == null) {
            subscribeOnScheduler = Schedulers.immediate();
        }

        return subscribeOnScheduler;
    }

}