Package com.netflix.eventbus.bridge

Source Code of com.netflix.eventbus.bridge.AbstractEventBusBridge$Builder

package com.netflix.eventbus.bridge;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.Inject;
import com.netflix.eventbus.spi.DynamicSubscriber;
import com.netflix.eventbus.spi.EventBus;
import com.netflix.eventbus.spi.EventFilter;
import com.netflix.eventbus.spi.Subscribe;

/**
* Implements basic functionality of registering for the event bus and
* forwarding events to another messaging API.
*
* @author elandau
*
*/
public abstract class AbstractEventBusBridge implements EventBusBridge {
    public static final Boolean DEFAULT_AUTO_START = true;
    public static final Supplier<EventBusBridgeStats> DEFAULT_STATS_SUPPLIER = new Supplier<EventBusBridgeStats>() {
        @Override
        public EventBusBridgeStats get() {
            return new SimpleEventBusBridgeStats();
        }
    };
   
    /**
     * Base builder with support for fluent subsclasses
     *
     * Note that the subclass's Build method MUST call validate().
     *
     * @param <T>   The subclasses's Builder.
     */
    public static abstract class Builder<T extends Builder<T>> {
        protected EventBus eventBus;
        protected Class<?> eventType;
        protected Supplier<EventBusBridgeStats> statsSupplier = DEFAULT_STATS_SUPPLIER;
        protected boolean autoStart = DEFAULT_AUTO_START;
        protected EventFilter filter;
       
        /**
         * The event bus to use
         * @param eventBus
         */
        @Inject
        public T withEventBus(EventBus eventBus) {
            this.eventBus = eventBus;
            return self();
        }
       
        /**
         * Specify the event type to listen to.  This can be a primitive, Pojo, or
         * Annotatable.
         * @param eventType
         */
        public T withEventType(Class<?> eventType) {
            this.eventType = eventType;
            return self();
        }
       
        /**
         * Predicate used to filter which events may be sent to the sink
         * @param filter
         */
        public T withFilter(EventFilter filter) {
            this.filter = filter;
            return self();
        }
       
        /**
         * Externally provided stats supplier
         * @param supplier
         */
        public T withStatsSupplier(Supplier<EventBusBridgeStats> supplier) {
            if (supplier != null)
                this.statsSupplier = supplier;
            return self();
        }

        /**
         * Indicate whether the bridge should begin consuming messages immediately
         * after being constructed, otherwise events will not be consumed until
         * resume() is called.
         * @param autoStart
         * @return
         */
        public T withAutoStart(Boolean autoStart) {
            this.autoStart = autoStart;
            return self();
        }
       
        /**
         * Externally provided specific instance of stats object
         * @param stats
         */
        public T withStats(EventBusBridgeStats stats) {
            if (stats != null)
                this.statsSupplier = Suppliers.ofInstance(stats);
            return self();
        }
       
        protected void validate() throws Exception {
            Preconditions.checkNotNull(eventType,  "Must specify an event type");
            Preconditions.checkNotNull(eventBus,   "Must specify an event bus");
        }
       
        /**
         * Trick to allow for fluent API using the base Builder and the subclass's
         * builder.  The subclass must implement self() as 'return this;'.
         * @return
         */
        protected abstract T self();
    }
   
    protected final EventBus            eventBus;
    protected final EventBusBridgeStats stats;
    protected final Class<?>            eventType;
    protected final Object              subscriber;
    protected final EventFilter         filter;
    protected volatile Boolean          paused = false;
   
    protected AbstractEventBusBridge(Builder<?> init) throws Exception {
        this.eventBus  = init.eventBus;
        this.stats     = init.statsSupplier.get();
        this.eventType = init.eventType;
        this.paused    = !init.autoStart;
        this.filter    = init.filter;
       
        this.subscriber = new DynamicSubscriber() {
            @Override
            public Class<?> getEventType() {
                return eventType;
            }

            @Subscribe
            public void consume(Object obj) {
                try {
                    if (!paused) {
                        sendEvent(obj);
                        stats.incConsumeCount();
                    }
                }
                catch (Exception e) {
                    stats.incConsumeErrorCount(e);
                }
            }
        };
    }
   
    @PostConstruct
    final public void init() throws Exception  {
        preInit();
        if (!this.isPaused()) {
            paused = true;
            resume();
        }
    }
   
    @PreDestroy
    final public void shutdown() throws Exception {
        pause();
        postShutdown();
    }
   
    /**
     * Template method for sending an event
     * @param event
     * @throws Exception
     * @deprecated Use {@link onNextEvent} instead
     */
    @Deprecated
    protected abstract void sendEvent(Object event) throws Exception;
   
    protected void onNextEvent(Object event) throws Exception {
        sendEvent(event);
    }
   
    /**
     * Template method giving the subclass a chance to initialize any connection
     * as init time.
     * @throws Exception
     */
    protected void preInit() throws Exception {
    }
   
    /**
     * Template method giving the subclass a chance to do final cleanup after
     * the bridge is terminated
     * @throws Exception
     */
    protected void postShutdown() throws Exception {
    }
   
    /**
     * Template method giving the subclass a chance to perform any necessary
     * steps prior to resuming consumption of messages.  Note that preResume()
     * is called immediately after preInit() during the first initialization
     * phase.   This is a good place to resume any threads previous
     *
     * This call is thread safe.
     *
     * @throws Exception
     */
    protected void preResume() throws Exception {
    }
   
    /**
     * Template method giving the subclass a chance to perform any necessary
     * steps immediately after pausing consumption of messages.  This is a
     * good place to temporarily suspend any threads specific to the
     * bridge implementation.
     *
     * This call is thread safe.
     *
     * @throws Exception
     */
    protected void postPause() throws Exception {
    }
   
    @Override
    final public synchronized void pause() throws Exception {
        if (paused == false) {
            paused = true;
            this.eventBus.unregisterSubscriber(subscriber);
            postPause();
        }
    }
   
    @Override
    final public synchronized void resume() throws Exception {
        if (paused == true) {
            preResume();
            if (filter != null)
                this.eventBus.registerSubscriber(filter, subscriber);
            else
                this.eventBus.registerSubscriber(subscriber);       
            paused = false;
        }
    }
   
    public boolean isPaused() {
        return paused;
    }
   
    public long getConsumeErrorCount() {
        return stats.getConsumeErrorCount();
    }
   
    public long getConsumeCount() {
        return stats.getConsumeCount();
    }
   
    public Exception getLastConsumeException() {
        return stats.getLastConsumeException();
    }
   
    public EventBusBridgeStats getStats() {
        return new ImmutableEventBusBridgeStats(stats);
    }
}
TOP

Related Classes of com.netflix.eventbus.bridge.AbstractEventBusBridge$Builder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.