/************************************************************************************** * 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.filter; import com.espertech.esper.client.ConfigurationEngineDefaults; import com.espertech.esper.client.ConfigurationInformation; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventType; import com.espertech.esper.collection.Pair; import com.espertech.esper.epl.expression.ExprEvaluatorContext; import com.espertech.esper.epl.expression.ExprNode; import com.espertech.esper.epl.expression.ExprNodeVariableVisitor; import com.espertech.esper.epl.variable.VariableService; import com.espertech.esper.event.EventAdapterService; import com.espertech.esper.pattern.MatchedEventMap; import java.util.LinkedHashMap; import java.util.Map; /** * This class represents an arbitrary expression node returning a boolean value as a filter parameter in an {@link FilterSpecCompiled} filter specification. */ public final class FilterSpecParamExprNode extends FilterSpecParam { private final String statementName; private final ExprNode exprNode; private final LinkedHashMap<String, Pair<EventType, String>> taggedEventTypes; private final LinkedHashMap<String, Pair<EventType, String>> arrayEventTypes; private final transient EventAdapterService eventAdapterService; private final transient VariableService variableService; private final boolean hasVariable; private final boolean useLargeThreadingProfile; private final boolean hasFilterStreamSubquery; private static final long serialVersionUID = 2298436088557677833L; /** * Ctor. * @param lookupable is the lookup-able * @param filterOperator is expected to be the BOOLEAN_EXPR operator * @param exprNode represents the boolean expression * @param taggedEventTypes is null if the expression doesn't need other streams, or is filled with a ordered list of stream names and types * @param arrayEventTypes is a map of name tags and event type per tag for repeat-expressions that generate an array of events * @param variableService - provides access to variables * @param eventAdapterService for creating event types and event beans * @throws IllegalArgumentException for illegal args */ public FilterSpecParamExprNode(FilterSpecLookupable lookupable, FilterOperator filterOperator, ExprNode exprNode, LinkedHashMap<String, Pair<EventType, String>> taggedEventTypes, LinkedHashMap<String, Pair<EventType, String>> arrayEventTypes, VariableService variableService, EventAdapterService eventAdapterService, ConfigurationInformation configurationInformation, String statementName, boolean hasSubquery) throws IllegalArgumentException { super(lookupable, filterOperator); if (filterOperator != FilterOperator.BOOLEAN_EXPRESSION) { throw new IllegalArgumentException("Invalid filter operator for filter expression node"); } this.exprNode = exprNode; this.taggedEventTypes = taggedEventTypes; this.arrayEventTypes = arrayEventTypes; this.variableService = variableService; this.eventAdapterService = eventAdapterService; this.useLargeThreadingProfile = configurationInformation.getEngineDefaults().getExecution().getThreadingProfile() == ConfigurationEngineDefaults.ThreadingProfile.LARGE; this.statementName = statementName; this.hasFilterStreamSubquery = hasSubquery; ExprNodeVariableVisitor visitor = new ExprNodeVariableVisitor(); exprNode.accept(visitor); this.hasVariable = visitor.isHasVariables(); } /** * Returns the expression node of the boolean expression this filter parameter represents. * @return expression node */ public ExprNode getExprNode() { return exprNode; } /** * Returns the map of tag/stream names to event types that the filter expressions map use (for patterns) * @return map */ public LinkedHashMap<String, Pair<EventType, String>> getTaggedEventTypes() { return taggedEventTypes; } public final ExprNodeAdapterBase getFilterValue(MatchedEventMap matchedEvents, ExprEvaluatorContext exprEvaluatorContext) { EventBean[] events = null; if ((taggedEventTypes != null && !taggedEventTypes.isEmpty()) || (arrayEventTypes != null && !arrayEventTypes.isEmpty())) { int size = 0; size += (taggedEventTypes != null) ? taggedEventTypes.size() : 0; size += (arrayEventTypes != null) ? arrayEventTypes.size() : 0; events = new EventBean[size + 1]; int count = 1; if (taggedEventTypes != null) { for (String tag : taggedEventTypes.keySet()) { events[count] = matchedEvents.getMatchingEventByTag(tag); count++; } } if (arrayEventTypes != null) { for (Map.Entry<String, Pair<EventType, String>> entry : arrayEventTypes.entrySet()) { EventType compositeEventType = entry.getValue().getFirst(); events[count] = eventAdapterService.adapterForTypedMap(matchedEvents.getMatchingEventsAsMap(), compositeEventType); count++; } } } // non-pattern case if (events == null) { // if a subquery is present in a filter stream acquire the agent instance lock if (hasFilterStreamSubquery) { return new ExprNodeAdapterBaseStmtLock(statementName, exprNode, exprEvaluatorContext, variableService); } // no-variable no-prior event evaluation if (!hasVariable) { return new ExprNodeAdapterBase(statementName, exprNode, exprEvaluatorContext); } // with-variable no-prior event evaluation return new ExprNodeAdapterBaseVariables(statementName, exprNode, exprEvaluatorContext, variableService); } // pattern cases VariableService variableServiceToUse = hasVariable == false ? null : variableService; if (useLargeThreadingProfile) { // no-threadlocal evaluation // if a subquery is present in a pattern filter acquire the agent instance lock if (hasFilterStreamSubquery) { return new ExprNodeAdapterMultiStreamNoTLStmtLock(statementName, exprNode, exprEvaluatorContext, variableServiceToUse, events); } return new ExprNodeAdapterMultiStreamNoTL(statementName, exprNode, exprEvaluatorContext, variableServiceToUse, events); } else { if (hasFilterStreamSubquery) { return new ExprNodeAdapterMultiStreamStmtLock(statementName, exprNode, exprEvaluatorContext, variableServiceToUse, events); } // evaluation with threadlocal cache return new ExprNodeAdapterMultiStream(statementName, exprNode, exprEvaluatorContext, variableServiceToUse, events); } } public final String toString() { return super.toString() + " exprNode=" + exprNode.toString(); } public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof FilterSpecParamExprNode)) { return false; } FilterSpecParamExprNode other = (FilterSpecParamExprNode) obj; if (!super.equals(other)) { return false; } if (exprNode != other.exprNode) { return false; } return true; } public int hashCode() { int result = super.hashCode(); result = 31 * result + exprNode.hashCode(); return result; } }