com.espertech.esper.pattern.EvalEveryDistinctStateExpireKeyNode.java Source code

Java tutorial

Introduction

Here is the source code for com.espertech.esper.pattern.EvalEveryDistinctStateExpireKeyNode.java

Source

/**************************************************************************************
 * 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.pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Contains the state collected by an "every" operator. The state includes handles to any sub-listeners
 * started by the operator.
 */
public class EvalEveryDistinctStateExpireKeyNode extends EvalStateNode implements Evaluator {
    protected final EvalEveryDistinctNode everyNode;
    protected final Map<EvalStateNode, LinkedHashMap<Object, Long>> spawnedNodes;
    protected MatchedEventMap beginState;

    /**
     * Constructor.
     * @param parentNode is the parent evaluator to call to indicate truth value
     * @param everyNode is the factory node associated to the state
     */
    public EvalEveryDistinctStateExpireKeyNode(Evaluator parentNode, EvalEveryDistinctNode everyNode) {
        super(parentNode);

        this.everyNode = everyNode;
        this.spawnedNodes = new LinkedHashMap<EvalStateNode, LinkedHashMap<Object, Long>>();

    }

    @Override
    public EvalNode getFactoryNode() {
        return everyNode;
    }

    public final void start(MatchedEventMap beginState) {
        this.beginState = beginState.shallowCopy();
        EvalStateNode childState = everyNode.getChildNode().newState(this, null, 0L);
        spawnedNodes.put(childState, new LinkedHashMap<Object, Long>());

        // During the start of the child we need to use the temporary evaluator to catch any event created during a start.
        // Events created during the start would likely come from the "not" operator.
        // Quit the new child again if
        EvalEveryStateSpawnEvaluator spawnEvaluator = new EvalEveryStateSpawnEvaluator(
                everyNode.getContext().getPatternContext().getStatementName());
        childState.setParentEvaluator(spawnEvaluator);
        childState.start(beginState);

        // If the spawned expression turned true already, just quit it
        if (spawnEvaluator.isEvaluatedTrue()) {
            childState.quit();
        } else {
            childState.setParentEvaluator(this);
        }
    }

    public final void evaluateFalse(EvalStateNode fromNode) {
        fromNode.quit();
        spawnedNodes.remove(fromNode);

        // Spawn all nodes below this EVERY node
        // During the start of a child we need to use the temporary evaluator to catch any event created during a start
        // Such events can be raised when the "not" operator is used.
        EvalEveryStateSpawnEvaluator spawnEvaluator = new EvalEveryStateSpawnEvaluator(
                everyNode.getContext().getPatternContext().getStatementName());
        EvalStateNode spawned = everyNode.getChildNode().newState(spawnEvaluator, null, 0L);
        spawned.start(beginState);

        // If the whole spawned expression already turned true, quit it again
        if (spawnEvaluator.isEvaluatedTrue()) {
            spawned.quit();
        } else {
            spawnedNodes.put(spawned, new LinkedHashMap<Object, Long>());
            spawned.setParentEvaluator(this);
        }
    }

    public final void evaluateTrue(MatchedEventMap matchEvent, EvalStateNode fromNode, boolean isQuitted) {
        // determine if this evaluation has been seen before from the same node
        Object matchEventKey = PatternExpressionUtil.getKeys(matchEvent, everyNode);
        boolean haveSeenThis = false;
        LinkedHashMap<Object, Long> keysFromNode = spawnedNodes.get(fromNode);
        if (keysFromNode != null) {
            // Clean out old keys
            Iterator<Map.Entry<Object, Long>> it = keysFromNode.entrySet().iterator();
            long currentTime = everyNode.getContext().getPatternContext().getTimeProvider().getTime();
            for (; it.hasNext();) {
                Map.Entry<Object, Long> entry = it.next();
                if (currentTime - entry.getValue() >= everyNode.getFactoryNode().getMsecToExpire()) {
                    it.remove();
                } else {
                    break;
                }
            }

            if (keysFromNode.containsKey(matchEventKey)) {
                haveSeenThis = true;
            } else {
                keysFromNode.put(matchEventKey, currentTime);
            }
        }

        if (isQuitted) {
            spawnedNodes.remove(fromNode);
        }

        // See explanation in EvalFilterStateNode for the type check
        if (fromNode.isFilterStateNode()) {
            // We do not need to newState new listeners here, since the filter state node below this node did not quit
        } else {
            // Spawn all nodes below this EVERY node
            // During the start of a child we need to use the temporary evaluator to catch any event created during a start
            // Such events can be raised when the "not" operator is used.
            EvalEveryStateSpawnEvaluator spawnEvaluator = new EvalEveryStateSpawnEvaluator(
                    everyNode.getContext().getPatternContext().getStatementName());
            EvalStateNode spawned = everyNode.getChildNode().newState(spawnEvaluator, null, 0L);
            spawned.start(beginState);

            // If the whole spawned expression already turned true, quit it again
            if (spawnEvaluator.isEvaluatedTrue()) {
                spawned.quit();
            } else {
                LinkedHashMap<Object, Long> keyset = new LinkedHashMap<Object, Long>();
                if (keysFromNode != null) {
                    keyset.putAll(keysFromNode);
                }
                spawnedNodes.put(spawned, keyset);
                spawned.setParentEvaluator(this);
            }
        }

        if (!haveSeenThis) {
            this.getParentEvaluator().evaluateTrue(matchEvent, this, false);
        }
    }

    public final void quit() {
        // Stop all child nodes
        for (EvalStateNode child : spawnedNodes.keySet()) {
            child.quit();
        }
    }

    public final Object accept(EvalStateNodeVisitor visitor, Object data) {
        return visitor.visit(this, data);
    }

    public final Object childrenAccept(EvalStateNodeVisitor visitor, Object data) {
        for (EvalStateNode spawnedNode : spawnedNodes.keySet()) {
            spawnedNode.accept(visitor, data);
        }

        return data;
    }

    public boolean isNotOperator() {
        return false;
    }

    public boolean isFilterStateNode() {
        return false;
    }

    public boolean isFilterChildNonQuitting() {
        return true;
    }

    public final String toString() {
        return "EvalEveryStateNode spawnedChildren=" + spawnedNodes.size();
    }

    private static final Log log = LogFactory.getLog(EvalEveryStateNode.class);
}