/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* 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 com.espertech.esper.client.EventBean;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.pattern.guard.Guard;
import com.espertech.esper.pattern.guard.Quitable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
/**
* This class represents the state of a "within" operator in the evaluation state tree.
* The within operator applies to a subexpression and is thus expected to only
* have one child node.
*/
public class EvalGuardStateNode extends EvalStateNode implements Evaluator, Quitable {
protected EvalGuardNode evalGuardNode;
protected EvalStateNode activeChildNode;
protected Guard guard;
protected MatchedEventMap beginState;
/**
* Constructor.
*
* @param parentNode is the parent evaluator to call to indicate truth value
* @param evalGuardNode is the factory node associated to the state
*/
public EvalGuardStateNode(Evaluator parentNode,
EvalGuardNode evalGuardNode) {
super(parentNode);
this.evalGuardNode = evalGuardNode;
}
public void removeMatch(Set<EventBean> matchEvent) {
if (PatternConsumptionUtil.containsEvent(matchEvent, beginState)) {
quit();
this.getParentEvaluator().evaluateFalse(this, true);
} else {
if (activeChildNode != null) {
activeChildNode.removeMatch(matchEvent);
}
}
}
@Override
public EvalNode getFactoryNode() {
return evalGuardNode;
}
public PatternAgentInstanceContext getContext() {
return evalGuardNode.getContext();
}
public void start(MatchedEventMap beginState) {
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().qPatternGuardStart(evalGuardNode, beginState);
}
this.beginState = beginState;
guard = evalGuardNode.getFactoryNode().getGuardFactory().makeGuard(evalGuardNode.getContext(), beginState, this, null, null);
activeChildNode = evalGuardNode.getChildNode().newState(this, null, 0L);
// Start the single child state
activeChildNode.start(beginState);
// Start the guard
guard.startGuard();
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().aPatternGuardStart();
}
}
public final void evaluateTrue(MatchedEventMap matchEvent, EvalStateNode fromNode, boolean isQuitted) {
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().qPatternGuardEvaluateTrue(evalGuardNode, matchEvent);
}
boolean haveQuitted = activeChildNode == null;
// If one of the children quits, remove the child
if (isQuitted) {
activeChildNode = null;
// Stop guard, since associated subexpression is gone
guard.stopGuard();
}
if (!haveQuitted) {
boolean guardPass = guard.inspect(matchEvent);
if (guardPass) {
this.getParentEvaluator().evaluateTrue(matchEvent, this, isQuitted);
}
}
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().aPatternGuardEvaluateTrue(isQuitted);
}
}
public final void evaluateFalse(EvalStateNode fromNode, boolean restartable) {
activeChildNode = null;
this.getParentEvaluator().evaluateFalse(this, true);
}
public final void quit() {
if (activeChildNode == null) {
return;
}
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().qPatternGuardQuit(evalGuardNode);
}
if (activeChildNode != null) {
activeChildNode.quit();
guard.stopGuard();
}
activeChildNode = null;
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().aPatternGuardQuit();
}
}
public final void accept(EvalStateNodeVisitor visitor) {
visitor.visitGuard(evalGuardNode.getFactoryNode(), this, guard);
if (activeChildNode != null) {
activeChildNode.accept(visitor);
}
}
public final String toString() {
return "EvaluationWitinStateNode activeChildNode=" + activeChildNode +
" guard=" + guard;
}
public boolean isNotOperator() {
return false;
}
public boolean isFilterStateNode() {
return false;
}
public boolean isFilterChildNonQuitting() {
return false;
}
public boolean isObserverStateNodeNonRestarting() {
return false;
}
public void guardQuit() {
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().qPatternGuardGuardQuit(evalGuardNode);
}
// It is possible that the child node has already been quit such as when the parent wait time was shorter.
// 1. parent node's guard indicates quit to all children
// 2. this node's guards also indicates quit, however that already occured
if (activeChildNode != null) {
activeChildNode.quit();
}
activeChildNode = null;
// Indicate to parent state that this is permanently false.
this.getParentEvaluator().evaluateFalse(this, true);
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().aPatternGuardGuardQuit();
}
}
private static final Logger log = LoggerFactory.getLogger(EvalGuardStateNode.class);
}