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

com.cookingfox.lapasse.impl.logging.RxLoggerHelper Maven / Gradle / Ivy

The newest version!
package com.cookingfox.lapasse.impl.logging;

import com.cookingfox.lapasse.api.command.Command;
import com.cookingfox.lapasse.api.command.logging.CommandHandlerError;
import com.cookingfox.lapasse.api.command.logging.CommandHandlerResult;
import com.cookingfox.lapasse.api.command.logging.CommandLogger;
import com.cookingfox.lapasse.api.command.logging.CommandLoggerAware;
import com.cookingfox.lapasse.api.event.Event;
import com.cookingfox.lapasse.api.event.logging.EventHandlerError;
import com.cookingfox.lapasse.api.event.logging.EventHandlerResult;
import com.cookingfox.lapasse.api.event.logging.EventLogger;
import com.cookingfox.lapasse.api.event.logging.EventLoggerAware;
import com.cookingfox.lapasse.api.state.State;
import rx.Observable;
import rx.Subscriber;
import rx.functions.Action0;
import rx.subscriptions.Subscriptions;

import java.util.Collection;

import static java.util.Objects.requireNonNull;

/**
 * Rx helper methods for logging features.
 */
public final class RxLoggerHelper {

    //----------------------------------------------------------------------------------------------
    // CONSTRUCTOR (disabled)
    //----------------------------------------------------------------------------------------------

    private RxLoggerHelper() {
        throw new UnsupportedOperationException();
    }

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

    /**
     * Creates an observable for command handler errors.
     *
     * @param loggerAware The subject for which to observe command handler errors.
     * @return An observable for command handler errors.
     */
    public static Observable observeCommandHandlerErrors(
            CommandLoggerAware loggerAware) {
        return logCommand(requireNonNull(loggerAware), new RxCommandLogger() {
            @Override
            public void onCommandHandlerError(final Throwable e, final Command command) {
                subscriber.onNext(new CommandHandlerError() {
                    @Override
                    public Command getCommand() {
                        return command;
                    }

                    @Override
                    public Throwable getError() {
                        return e;
                    }
                });
            }
        });
    }

    /**
     * Creates an observable for command handler results.
     *
     * @param loggerAware The subject for which to observe command handler results.
     * @return An observable for command handler results.
     */
    public static Observable observeCommandHandlerResults(
            CommandLoggerAware loggerAware) {
        return logCommand(requireNonNull(loggerAware), new RxCommandLogger() {
            @Override
            public void onCommandHandlerResult(final Command command, final Collection events) {
                subscriber.onNext(new CommandHandlerResult() {
                    @Override
                    public Command getCommand() {
                        return command;
                    }

                    @Override
                    public Collection getEvents() {
                        return events;
                    }
                });
            }
        });
    }

    /**
     * Creates an observable for event handler errors.
     *
     * @param loggerAware The subject for which to observe event handler errors.
     * @param          The concrete type of the state object.
     * @return An observable for event handler errors.
     */
    public static  Observable observeEventHandlerErrors(
            EventLoggerAware loggerAware) {
        return logEvent(requireNonNull(loggerAware), new RxEventLogger() {
            @Override
            public void onEventHandlerError(final Throwable e, final Event event) {
                subscriber.onNext(new EventHandlerError() {
                    @Override
                    public Throwable getError() {
                        return e;
                    }

                    @Override
                    public Event getEvent() {
                        return event;
                    }
                });
            }
        });
    }

    /**
     * Creates an observable for event handler results.
     *
     * @param loggerAware The subject for which to observe event handler results.
     * @param          The concrete type of the state object.
     * @return An observable for event handler results.
     */
    public static  Observable observeEventHandlerResults(
            EventLoggerAware loggerAware) {
        return logEvent(requireNonNull(loggerAware), new RxEventLogger() {
            @Override
            public void onEventHandlerResult(final Event event, final S newState) {
                subscriber.onNext(new EventHandlerResult() {
                    @Override
                    public Event getEvent() {
                        return event;
                    }

                    @Override
                    public S getNewState() {
                        return newState;
                    }
                });
            }
        });
    }

    //----------------------------------------------------------------------------------------------
    // PRIVATE METHODS
    //----------------------------------------------------------------------------------------------

    /**
     * Creates an observable for the provided logger implementation. Adds the logger when subscribed
     * to the observable and removes it when unsubscribed.
     *
     * @param loggerAware The subject for which to observe handler log calls.
     * @param logger      The logger implementation.
     * @param          The concrete log call VO that will be emitted by the observable.
     * @return Observable for the provided log call VO.
     */
    static  Observable logCommand(final CommandLoggerAware loggerAware,
                                        final RxCommandLogger logger) {
        return Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscriber subscriber) {
                // set subscriber reference for logger
                logger.subscriber = subscriber;

                // add logger
                loggerAware.addCommandLogger(logger);

                // remove logger on subscriber unsubscribe
                subscriber.add(Subscriptions.create(new Action0() {
                    @Override
                    public void call() {
                        loggerAware.removeCommandLogger(logger);
                    }
                }));
            }
        });
    }

    /**
     * * Creates an observable for the provided logger implementation. Adds the logger when subscribed
     * to the observable and removes it when unsubscribed.
     *
     * @param loggerAware The subject for which to observe handler log calls.
     * @param logger      The logger implementation.
     * @param          The concrete type of the state object.
     * @param          The concrete log call VO that will be emitted by the observable.
     * @return Observable for the provided log call VO.
     */
    static  Observable logEvent(final EventLoggerAware loggerAware,
                                                       final RxEventLogger logger) {
        return Observable.create(new Observable.OnSubscribe() {
            @Override
            public void call(Subscriber subscriber) {
                // set subscriber reference for logger
                logger.subscriber = subscriber;

                // add logger
                loggerAware.addEventLogger(logger);

                // remove logger on subscriber unsubscribe
                subscriber.add(Subscriptions.create(new Action0() {
                    @Override
                    public void call() {
                        loggerAware.removeEventLogger(logger);
                    }
                }));
            }
        });
    }

    //----------------------------------------------------------------------------------------------
    // MEMBER CLASSES
    //----------------------------------------------------------------------------------------------

    /**
     * Helper class for usage with Rx subscriber.
     *
     * @param  The concrete type of the value this subscriber will receive.
     */
    static abstract class SubscriberAware {

        /**
         * The subscriber reference.
         */
        Subscriber subscriber;

    }

    /**
     * No-operation implementation of {@link CommandLogger} that is {@link SubscriberAware}.
     *
     * @param  The concrete type of the value which will be received by the subscriber.
     */
    static class RxCommandLogger extends SubscriberAware implements CommandLogger {

        @Override
        public void onCommandHandlerError(Throwable e, Command command) {
            // override in subclass
        }

        @Override
        public void onCommandHandlerResult(Command command, Collection events) {
            // override in subclass
        }

    }

    /**
     * No-operation implementation of {@link EventLogger} that is {@link SubscriberAware}.
     *
     * @param  The concrete type of the state object.
     * @param  The concrete type of the value which will be received by the subscriber.
     */
    static class RxEventLogger
            extends SubscriberAware implements EventLogger {

        @Override
        public void onEventHandlerError(Throwable e, Event event) {
            // override in subclass
        }

        @Override
        public void onEventHandlerResult(Event event, S newState) {
            // override in subclass
        }

    }

}