Package com.espertech.esper.dataflow.ops

Source Code of com.espertech.esper.dataflow.ops.EPStatementSource$LocalEmitter

/*
* *************************************************************************************
*  Copyright (C) 2008 EsperTech, Inc. All rights reserved.                            *
*  http://esper.codehaus.org                                                          *
*  http://www.espertech.com                                                           *
*  ---------------------------------------------------------------------------------- *
*  The software in this package is published under the terms of the GPL license       *
*  a copy of which has been included with this distribution in the license.txt file.  *
* *************************************************************************************
*/

package com.espertech.esper.dataflow.ops;

import com.espertech.esper.client.*;
import com.espertech.esper.client.dataflow.EPDataFlowEPStatementFilter;
import com.espertech.esper.client.dataflow.EPDataFlowIRStreamCollector;
import com.espertech.esper.client.dataflow.EPDataFlowIRStreamCollectorContext;
import com.espertech.esper.client.dataflow.EPDataFlowSignal;
import com.espertech.esper.core.service.StatementLifecycleEvent;
import com.espertech.esper.core.service.StatementLifecycleObserver;
import com.espertech.esper.core.service.StatementLifecycleSvc;
import com.espertech.esper.dataflow.annotations.DataFlowContext;
import com.espertech.esper.dataflow.annotations.DataFlowOpParameter;
import com.espertech.esper.dataflow.annotations.DataFlowOperator;
import com.espertech.esper.dataflow.interfaces.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

@DataFlowOperator
public class EPStatementSource implements DataFlowSourceOperator, DataFlowOpLifecycle, StatementLifecycleObserver {
    private static final Log log = LogFactory.getLog(EPStatementSource.class);

    @DataFlowOpParameter
    private String statementName;

    @DataFlowOpParameter
    private EPDataFlowEPStatementFilter statementFilter;

    @DataFlowOpParameter
    private EPDataFlowIRStreamCollector collector;

    @DataFlowContext
    private EPDataFlowEmitter graphContext;

    private StatementLifecycleSvc statementLifecycleSvc;
    private Map<EPStatement, StatementAwareUpdateListener> listeners = new HashMap<EPStatement, StatementAwareUpdateListener>();
    private LinkedBlockingQueue<Object> emittables = new LinkedBlockingQueue<Object>();
    private boolean submitEventBean;

    private ThreadLocal<EPDataFlowIRStreamCollectorContext> collectorDataTL = new ThreadLocal<EPDataFlowIRStreamCollectorContext>() {
        protected synchronized EPDataFlowIRStreamCollectorContext initialValue() {
            return null;
        }
    };

    public DataFlowOpInitializeResult initialize(DataFlowOpInitializateContext context) throws Exception {

        if (context.getOutputPorts().size() != 1) {
            throw new IllegalArgumentException("EPStatementSource operator requires one output stream but produces " + context.getOutputPorts().size() + " streams");
        }

        if (statementName == null && statementFilter == null) {
            throw new EPException("Failed to find required 'statementName' or 'statementFilter' parameter");
        }
        if (statementName != null && statementFilter != null) {
            throw new EPException("Both 'statementName' or 'statementFilter' parameters were provided, only either one is expected");
        }

        DataFlowOpOutputPort portZero = context.getOutputPorts().get(0);
        if (portZero != null && portZero.getOptionalDeclaredType() != null && portZero.getOptionalDeclaredType().isWildcard()) {
            submitEventBean = true;
        }

        statementLifecycleSvc = context.getServicesContext().getStatementLifecycleSvc();
        return null;
    }

    public void next() throws InterruptedException {
        Object next = emittables.take();
        if (next instanceof EPDataFlowSignal) {
            EPDataFlowSignal signal = (EPDataFlowSignal) next;
            graphContext.submitSignal(signal);
        }
        else if (next instanceof PortAndMessagePair) {
            PortAndMessagePair pair = (PortAndMessagePair) next;
            graphContext.submitPort(pair.getPort(), pair.getMessage());
        }
        else {
            graphContext.submit(next);
        }
    }

    public synchronized void open(DataFlowOpOpenContext openContext) {
        // start observing statement management
        statementLifecycleSvc.addObserver(this);

        if (statementName != null) {
            EPStatement stmt = statementLifecycleSvc.getStatementByName(statementName);
            if (stmt != null) {
                addStatement(stmt);
            }
        }
        else {
            String[] statements = statementLifecycleSvc.getStatementNames();
            for (String name : statements) {
                EPStatement stmt = statementLifecycleSvc.getStatementByName(name);
                if (statementFilter.pass(stmt)) {
                    addStatement(stmt);
                }
            }
        }
    }

    public synchronized void observe(StatementLifecycleEvent theEvent) {
        EPStatement stmt = theEvent.getStatement();
        if (theEvent.getEventType() == StatementLifecycleEvent.LifecycleEventType.STATECHANGE) {
            if (theEvent.getStatement().isStopped() || theEvent.getStatement().isDestroyed()) {
                StatementAwareUpdateListener listener = listeners.remove(stmt);
                if (listener != null) {
                    stmt.removeListener(listener);
                }
            }
            if (theEvent.getStatement().isStarted()) {
                if (statementFilter == null) {
                    if (theEvent.getStatement().getName().equals(statementName)) {
                        addStatement(stmt);
                    }
                }
                else {
                    if (statementFilter.pass(stmt)) {
                        addStatement(stmt);
                    }
                }
            }
        }
    }

    public void close(DataFlowOpCloseContext openContext) {
        for (Map.Entry<EPStatement, StatementAwareUpdateListener> entry : listeners.entrySet()) {
            try {
                entry.getKey().removeListener(entry.getValue());
            }
            catch (Exception ex) {
                log.debug("Exception encountered removing listener: " + ex.getMessage(), ex);
                // possible
            }
        }
        listeners.clear();
    }

    private void addStatement(EPStatement stmt) {
        // statement may be added already
        if (listeners.containsKey(stmt)) {
            return;
        }

        // attach listener
        StatementAwareUpdateListener listener;
        if (collector == null) {
            listener = new EmitterUpdateListener(emittables, submitEventBean);
        }
        else {
            LocalEmitter emitterForCollector = new LocalEmitter(emittables);
            listener = new EmitterCollectorUpdateListener(collector, emitterForCollector, collectorDataTL, submitEventBean);
        }
        stmt.addListener(listener);

        // save listener instance
        listeners.put(stmt, listener);
    }

    public static class EmitterUpdateListener implements StatementAwareUpdateListener {
        private final Queue<Object> queue;
        private final boolean submitEventBean;

        public EmitterUpdateListener(Queue<Object> queue, boolean submitEventBean) {
            this.queue = queue;
            this.submitEventBean = submitEventBean;
        }

        public void update(EventBean[] newEvents, EventBean[] oldEvents, EPStatement statement, EPServiceProvider epServiceProvider) {
            if (newEvents != null) {
                for (EventBean newEvent : newEvents) {
                    if (submitEventBean) {
                        queue.add(newEvent);
                    }
                    else {
                        Object underlying = newEvent.getUnderlying();
                        queue.add(underlying);
                    }
                }
            }
        }
    }

    public static class EmitterCollectorUpdateListener implements StatementAwareUpdateListener {
        private final EPDataFlowIRStreamCollector collector;
        private final LocalEmitter emitterForCollector;
        private final ThreadLocal<EPDataFlowIRStreamCollectorContext> collectorDataTL;
        private final boolean submitEventBean;

        public EmitterCollectorUpdateListener(EPDataFlowIRStreamCollector collector, LocalEmitter emitterForCollector, ThreadLocal<EPDataFlowIRStreamCollectorContext> collectorDataTL, boolean submitEventBean) {
            this.collector = collector;
            this.emitterForCollector = emitterForCollector;
            this.collectorDataTL = collectorDataTL;
            this.submitEventBean = submitEventBean;
        }

        public void update(EventBean[] newEvents, EventBean[] oldEvents, EPStatement statement, EPServiceProvider epServiceProvider) {

            EPDataFlowIRStreamCollectorContext holder = collectorDataTL.get();
            if (holder == null) {
                holder = new EPDataFlowIRStreamCollectorContext(emitterForCollector, submitEventBean, newEvents, oldEvents, statement, epServiceProvider);
                collectorDataTL.set(holder);
            }
            else {
                holder.setEpServiceProvider(epServiceProvider);
                holder.setStatement(statement);
                holder.setOldEvents(oldEvents);
                holder.setNewEvents(newEvents);
            }

            collector.collect(holder);
        }
    }

    public static class LocalEmitter implements EPDataFlowEmitter {

        private final LinkedBlockingQueue<Object> queue;

        public LocalEmitter(LinkedBlockingQueue<Object> queue) {
            this.queue = queue;
        }

        public void submit(Object object) {
            queue.add(object);
        }

        public void submitSignal(EPDataFlowSignal signal) {
            queue.add(signal);
        }

        public void submitPort(int portNumber, Object object) {
            queue.add(object);
        }
    }

    public static class PortAndMessagePair {
        private final int port;
        private final Object message;

        public PortAndMessagePair(int port, Object message) {
            this.port = port;
            this.message = message;
        }

        public int getPort() {
            return port;
        }

        public Object getMessage() {
            return message;
        }
    }
}
TOP

Related Classes of com.espertech.esper.dataflow.ops.EPStatementSource$LocalEmitter

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.