/************************************************************************************** * 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.epl.parse; import com.espertech.esper.antlr.ASTUtil; import com.espertech.esper.epl.core.StreamTypeServiceImpl; import com.espertech.esper.epl.expression.*; import com.espertech.esper.epl.generated.EsperEPL2GrammarParser; import com.espertech.esper.epl.spec.*; import com.espertech.esper.epl.variable.VariableService; import com.espertech.esper.schedule.TimeProvider; import com.espertech.esper.type.IntValue; import org.antlr.runtime.tree.Tree; import java.util.List; import java.util.Map; /** * Builds an output limit spec from an output limit AST node. */ public class ASTOutputLimitHelper { /** * Build an output limit spec from the AST node supplied. * * @param node - parse node * @param astExprNodeMap is the map of current AST tree nodes to their respective expression root node * @param engineURI the engine uri * @param timeProvider provides time * @param variableService provides variable resolution * @param exprEvaluatorContext context for expression evaluatiom * @return output limit spec */ public static OutputLimitSpec buildOutputLimitSpec(Tree node, Map<Tree, ExprNode> astExprNodeMap, VariableService variableService, String engineURI, TimeProvider timeProvider, ExprEvaluatorContext exprEvaluatorContext) { int count = 0; Tree child = node.getChild(count); // parse type OutputLimitLimitType displayLimit = OutputLimitLimitType.DEFAULT; if (child.getType() == EsperEPL2GrammarParser.FIRST) { displayLimit = OutputLimitLimitType.FIRST; child = node.getChild(++count); } else if (child.getType() == EsperEPL2GrammarParser.LAST) { displayLimit = OutputLimitLimitType.LAST; child = node.getChild(++count); } else if (child.getType() == EsperEPL2GrammarParser.SNAPSHOT) { displayLimit = OutputLimitLimitType.SNAPSHOT; child = node.getChild(++count); } else if (child.getType() == EsperEPL2GrammarParser.ALL) { displayLimit = OutputLimitLimitType.ALL; child = node.getChild(++count); } // next is a variable, or time period, or number String variableName = null; double rate = -1; ExprNode whenExpression = null; List<ExprNode> crontabScheduleSpec = null; List<OnTriggerSetAssignment> thenExpressions = null; ExprTimePeriod timePeriodExpr = null; ExprNode andAfterTerminateExpr = null; List<OnTriggerSetAssignment> andAfterTerminateSetExpressions = null; if (node.getType() == EsperEPL2GrammarParser.TERM_LIMIT_EXPR) { Tree terminated = ASTUtil.findFirstNode(node, EsperEPL2GrammarParser.TERMINATED); if (terminated.getChildCount() != 0) { andAfterTerminateExpr = astExprNodeMap.remove(terminated.getChild(0)); Tree setExprNode = ASTUtil.findFirstNode(terminated, EsperEPL2GrammarParser.ON_SET_EXPR); if (setExprNode != null) { andAfterTerminateSetExpressions = ASTExprHelper.getOnTriggerSetAssignments(setExprNode, astExprNodeMap); } } // no action to walk any other expression } else if (node.getType() == EsperEPL2GrammarParser.WHEN_LIMIT_EXPR) { Tree expressionNode = node.getChild(count); whenExpression = astExprNodeMap.remove(expressionNode); if (node.getChildCount() > count+1) { Tree setExpr = ASTUtil.findFirstNode(node, EsperEPL2GrammarParser.ON_SET_EXPR); thenExpressions = ASTExprHelper.getOnTriggerSetAssignments(setExpr, astExprNodeMap); } } else if (node.getType() == EsperEPL2GrammarParser.CRONTAB_LIMIT_EXPR) { Tree parent = node.getChild(0); if (parent.getType() != EsperEPL2GrammarParser.CRONTAB_LIMIT_EXPR_PARAM) { parent = node.getChild(1); } crontabScheduleSpec = ASTExprHelper.getRemoveAllChildExpr(parent, astExprNodeMap); } else if (node.getType() == EsperEPL2GrammarParser.AFTER_LIMIT_EXPR) { // no action here, since AFTER time may occur in all } else { if (child.getType() == EsperEPL2GrammarParser.IDENT) { variableName = child.getText(); } else if (child.getType() == EsperEPL2GrammarParser.TIME_PERIOD) { timePeriodExpr = (ExprTimePeriod) astExprNodeMap.remove(child); } else { rate = Double.parseDouble(child.getText()); } } // get the AFTER time period ExprTimePeriod afterTimePeriodExpr = null; Integer afterNumberOfEvents = null; for (int i = 0; i < node.getChildCount(); i++) { if (node.getChild(i).getType() == EsperEPL2GrammarParser.AFTER) { ExprNode expression = astExprNodeMap.remove(node.getChild(i).getChild(0)); if (expression != null) { afterTimePeriodExpr = (ExprTimePeriod) expression; } else { Object constant = ASTConstantHelper.parse(node.getChild(i).getChild(0)); afterNumberOfEvents = ((Number) constant).intValue(); } } } Tree lastNode = node.getChild(node.getChildCount() - 1); boolean andAfterTerminate = (lastNode.getType() == EsperEPL2GrammarParser.TERMINATED) && andAfterTerminateExpr == null && node.getType() != EsperEPL2GrammarParser.TERM_LIMIT_EXPR; if (andAfterTerminate && lastNode.getChildCount() > 0) { andAfterTerminateExpr = astExprNodeMap.remove(lastNode.getChild(0)); Tree setExprNode = ASTUtil.findFirstNode(lastNode, EsperEPL2GrammarParser.ON_SET_EXPR); if (setExprNode != null) { andAfterTerminateSetExpressions = ASTExprHelper.getOnTriggerSetAssignments(setExprNode, astExprNodeMap); } } switch (node.getType()) { case EsperEPL2GrammarParser.EVENT_LIMIT_EXPR: return new OutputLimitSpec(rate, variableName, OutputLimitRateType.EVENTS, displayLimit, null, null, null, null, afterTimePeriodExpr, afterNumberOfEvents, andAfterTerminate, andAfterTerminateExpr, andAfterTerminateSetExpressions); case EsperEPL2GrammarParser.TIMEPERIOD_LIMIT_EXPR: return new OutputLimitSpec(null, null, OutputLimitRateType.TIME_PERIOD, displayLimit, null, null, null, timePeriodExpr, afterTimePeriodExpr, afterNumberOfEvents, andAfterTerminate, andAfterTerminateExpr, andAfterTerminateSetExpressions); case EsperEPL2GrammarParser.CRONTAB_LIMIT_EXPR: return new OutputLimitSpec(null, null, OutputLimitRateType.CRONTAB, displayLimit, null, null, crontabScheduleSpec, null, afterTimePeriodExpr, afterNumberOfEvents, andAfterTerminate, andAfterTerminateExpr, andAfterTerminateSetExpressions); case EsperEPL2GrammarParser.WHEN_LIMIT_EXPR: return new OutputLimitSpec(null, null, OutputLimitRateType.WHEN_EXPRESSION, displayLimit, whenExpression, thenExpressions, null, null, afterTimePeriodExpr, afterNumberOfEvents, andAfterTerminate, andAfterTerminateExpr, andAfterTerminateSetExpressions); case EsperEPL2GrammarParser.AFTER_LIMIT_EXPR: return new OutputLimitSpec(null, null, OutputLimitRateType.AFTER, displayLimit, null, null, null, null, afterTimePeriodExpr, afterNumberOfEvents, andAfterTerminate, andAfterTerminateExpr, andAfterTerminateSetExpressions); case EsperEPL2GrammarParser.TERM_LIMIT_EXPR: return new OutputLimitSpec(null, null, OutputLimitRateType.TERM, displayLimit, null, null, null, null, afterTimePeriodExpr, afterNumberOfEvents, andAfterTerminate, andAfterTerminateExpr, andAfterTerminateSetExpressions); default: throw new IllegalArgumentException("Node type " + node.getType() + " not a recognized output limit type"); } } /** * Builds a row limit specification. * @param node to interrogate * @return row limit spec */ public static RowLimitSpec buildRowLimitSpec(Tree node) { Object numRows; Object offset; if (node.getChildCount() == 1) { numRows = parseNumOrVariableIdent(node.getChild(0)); offset = null; } else { if (node.getChild(node.getChildCount()- 1).getType() == EsperEPL2GrammarParser.COMMA) { offset = parseNumOrVariableIdent(node.getChild(0)); numRows = parseNumOrVariableIdent(node.getChild(1)); } else { numRows = parseNumOrVariableIdent(node.getChild(0)); offset = parseNumOrVariableIdent(node.getChild(1)); } } Integer numRowsInt = null; String numRowsVariable = null; if (numRows instanceof String) { numRowsVariable = (String) numRows; } else { numRowsInt = (Integer) numRows; } Integer offsetInt = null; String offsetVariable = null; if (offset instanceof String) { offsetVariable = (String) offset; } else { offsetInt = (Integer) offset; } return new RowLimitSpec(numRowsInt, offsetInt, numRowsVariable, offsetVariable); } private static Object parseNumOrVariableIdent(Tree child) { if (child.getType() == EsperEPL2GrammarParser.IDENT) { return child.getText(); } else { return IntValue.parseString(child.getText()); } } }