public void validate( StreamTypeService streamTypeService, MethodResolutionService methodResolutionService, ViewResourceDelegate viewResourceDelegate, TimeProvider timeProvider, VariableService variableService, ExprEvaluatorContext exprEvaluatorContext) throws ExprValidationException { if (this.getChildNodes().size() < 2) { throw new ExprValidationException("MinMax node must have at least 2 child nodes"); } evaluators = ExprNodeUtility.getEvaluators(this.getChildNodes()); for (ExprEvaluator child : evaluators) { Class childType = child.getType(); if (!JavaClassHelper.isNumeric(childType)) { throw new ExprValidationException( "Implicit conversion from datatype '" + childType.getSimpleName() + "' to numeric is not allowed"); } } // Determine result type, set up compute function Class childTypeOne = evaluators[0].getType(); Class childTypeTwo = evaluators[1].getType(); resultType = JavaClassHelper.getArithmaticCoercionType(childTypeOne, childTypeTwo); for (int i = 2; i < this.getChildNodes().size(); i++) { resultType = JavaClassHelper.getArithmaticCoercionType(resultType, evaluators[i].getType()); } ExprNode[] childNodes = this.getChildNodes().toArray(new ExprNode[this.getChildNodes().size()]); if (resultType == BigInteger.class) { SimpleNumberBigIntegerCoercer[] convertors = new SimpleNumberBigIntegerCoercer[childNodes.length]; for (int i = 0; i < childNodes.length; i++) { convertors[i] = SimpleNumberCoercerFactory.getCoercerBigInteger(evaluators[i].getType()); } computer = new MinMaxTypeEnum.ComputerBigIntCoerce( evaluators, convertors, (minMaxTypeEnum == MinMaxTypeEnum.MAX)); } else if (resultType == BigDecimal.class) { SimpleNumberBigDecimalCoercer[] convertors = new SimpleNumberBigDecimalCoercer[childNodes.length]; for (int i = 0; i < childNodes.length; i++) { convertors[i] = SimpleNumberCoercerFactory.getCoercerBigDecimal(evaluators[i].getType()); } computer = new MinMaxTypeEnum.ComputerBigDecCoerce( evaluators, convertors, (minMaxTypeEnum == MinMaxTypeEnum.MAX)); } else { if (minMaxTypeEnum == MinMaxTypeEnum.MAX) { computer = new MinMaxTypeEnum.MaxComputerDoubleCoerce(evaluators); } else { computer = new MinMaxTypeEnum.MinComputerDoubleCoerce(evaluators); } } }
public ExprNode validate(ExprValidationContext validationContext) throws ExprValidationException { // Must have 2 child nodes if (this.getChildNodes().length < 1) { throw new IllegalStateException("Group relational op node must have 1 or more parameters"); } evaluators = ExprNodeUtility.getEvaluators(this.getChildNodes()); Class typeOne = JavaClassHelper.getBoxedType(evaluators[0].getType()); // collections, array or map not supported if ((typeOne.isArray()) || (JavaClassHelper.isImplementsInterface(typeOne, Collection.class)) || (JavaClassHelper.isImplementsInterface(typeOne, Map.class))) { throw new ExprValidationException( "Collection or array comparison is not allowed for the IN, ANY, SOME or ALL keywords"); } List<Class> comparedTypes = new ArrayList<Class>(); comparedTypes.add(typeOne); hasCollectionOrArray = false; for (int i = 0; i < this.getChildNodes().length - 1; i++) { Class propType = evaluators[i + 1].getType(); if (propType.isArray()) { hasCollectionOrArray = true; if (propType.getComponentType() != Object.class) { comparedTypes.add(propType.getComponentType()); } } else if (JavaClassHelper.isImplementsInterface(propType, Collection.class)) { hasCollectionOrArray = true; } else if (JavaClassHelper.isImplementsInterface(propType, Map.class)) { hasCollectionOrArray = true; } else { comparedTypes.add(propType); } } // Determine common denominator type Class coercionType; try { coercionType = JavaClassHelper.getCommonCoercionType( comparedTypes.toArray(new Class[comparedTypes.size()])); } catch (CoercionException ex) { throw new ExprValidationException("Implicit conversion not allowed: " + ex.getMessage()); } // Must be either numeric or string if (coercionType != String.class) { if (!JavaClassHelper.isNumeric(coercionType)) { throw new ExprValidationException( "Implicit conversion from datatype '" + coercionType.getSimpleName() + "' to numeric is not allowed"); } } computer = relationalOpEnum.getComputer(coercionType, coercionType, coercionType); return null; }
private static List<ExprNode> validateExpressions( List<ExprNode> objectParameters, ExprValidationContext validationContext) throws ExprValidationException { if (objectParameters == null) { return objectParameters; } List<ExprNode> validated = new ArrayList<ExprNode>(); for (ExprNode node : objectParameters) { validated.add(ExprNodeUtility.getValidatedSubtree(node, validationContext)); } return validated; }
/** * Ctor. * * @param assignments the list of variable assignments * @param variableService variable service * @param eventAdapterService event adapters * @throws com.espertech.esper.epl.expression.core.ExprValidationException when variables cannot * be found */ public VariableReadWritePackage( List<OnTriggerSetAssignment> assignments, VariableService variableService, EventAdapterService eventAdapterService) throws ExprValidationException { this.metaData = new VariableMetaData[assignments.size()]; this.readersForGlobalVars = new VariableReader[assignments.size()]; this.mustCoerce = new boolean[assignments.size()]; this.writers = new WriteDesc[assignments.size()]; this.variableTypes = new HashMap<String, Object>(); this.eventAdapterService = eventAdapterService; this.variableService = variableService; Map<EventTypeSPI, CopyMethodDesc> eventTypeWrittenProps = new HashMap<EventTypeSPI, CopyMethodDesc>(); int count = 0; List<VariableTriggerSetDesc> assignmentList = new ArrayList<VariableTriggerSetDesc>(); for (OnTriggerSetAssignment expressionWithAssignments : assignments) { Pair<String, ExprNode> possibleVariableAssignment = ExprNodeUtility.checkGetAssignmentToVariableOrProp( expressionWithAssignments.getExpression()); if (possibleVariableAssignment == null) { throw new ExprValidationException( "Missing variable assignment expression in assignment number " + count); } assignmentList.add( new VariableTriggerSetDesc( possibleVariableAssignment.getFirst(), possibleVariableAssignment.getSecond().getExprEvaluator())); String fullVariableName = possibleVariableAssignment.getFirst(); String variableName = fullVariableName; String subPropertyName = null; int indexOfDot = variableName.indexOf('.'); if (indexOfDot != -1) { subPropertyName = variableName.substring(indexOfDot + 1, variableName.length()); variableName = variableName.substring(0, indexOfDot); } VariableMetaData variableMetadata = variableService.getVariableMetaData(variableName); metaData[count] = variableMetadata; if (variableMetadata == null) { throw new ExprValidationException( "Variable by name '" + variableName + "' has not been created or configured"); } if (variableMetadata.isConstant()) { throw new ExprValidationException( "Variable by name '" + variableName + "' is declared constant and may not be set"); } if (variableMetadata.getContextPartitionName() == null) { readersForGlobalVars[count] = variableService.getReader(variableName, VariableService.NOCONTEXT_AGENTINSTANCEID); } if (subPropertyName != null) { if (variableMetadata.getEventType() == null) { throw new ExprValidationException( "Variable by name '" + variableName + "' does not have a property named '" + subPropertyName + "'"); } EventType type = variableMetadata.getEventType(); if (!(type instanceof EventTypeSPI)) { throw new ExprValidationException( "Variable by name '" + variableName + "' event type '" + type.getName() + "' not writable"); } EventTypeSPI spi = (EventTypeSPI) type; EventPropertyWriter writer = spi.getWriter(subPropertyName); EventPropertyGetter getter = spi.getGetter(subPropertyName); if (writer == null) { throw new ExprValidationException( "Variable by name '" + variableName + "' the property '" + subPropertyName + "' is not writable"); } variableTypes.put(fullVariableName, spi.getPropertyType(subPropertyName)); CopyMethodDesc writtenProps = eventTypeWrittenProps.get(spi); if (writtenProps == null) { writtenProps = new CopyMethodDesc(variableName, new ArrayList<String>()); eventTypeWrittenProps.put(spi, writtenProps); } writtenProps.getPropertiesCopied().add(subPropertyName); writers[count] = new WriteDesc(spi, variableName, writer, getter); } else { // determine types Class expressionType = possibleVariableAssignment.getSecond().getExprEvaluator().getType(); if (variableMetadata.getEventType() != null) { if ((expressionType != null) && (!JavaClassHelper.isSubclassOrImplementsInterface( expressionType, variableMetadata.getEventType().getUnderlyingType()))) { throw new VariableValueException( "Variable '" + variableName + "' of declared event type '" + variableMetadata.getEventType().getName() + "' underlying type '" + variableMetadata.getEventType().getUnderlyingType().getName() + "' cannot be assigned a value of type '" + expressionType.getName() + "'"); } variableTypes.put(variableName, variableMetadata.getEventType().getUnderlyingType()); } else { Class variableType = variableMetadata.getType(); variableTypes.put(variableName, variableType); // determine if the expression type can be assigned if (variableType != java.lang.Object.class) { if ((JavaClassHelper.getBoxedType(expressionType) != variableType) && (expressionType != null)) { if ((!JavaClassHelper.isNumeric(variableType)) || (!JavaClassHelper.isNumeric(expressionType))) { throw new ExprValidationException( VariableServiceUtil.getAssigmentExMessage( variableName, variableType, expressionType)); } if (!(JavaClassHelper.canCoerce(expressionType, variableType))) { throw new ExprValidationException( VariableServiceUtil.getAssigmentExMessage( variableName, variableType, expressionType)); } mustCoerce[count] = true; } } } } count++; } this.assignments = assignmentList.toArray(new VariableTriggerSetDesc[assignmentList.size()]); if (eventTypeWrittenProps.isEmpty()) { copyMethods = Collections.EMPTY_MAP; return; } copyMethods = new HashMap<EventTypeSPI, EventBeanCopyMethod>(); for (Map.Entry<EventTypeSPI, CopyMethodDesc> entry : eventTypeWrittenProps.entrySet()) { List<String> propsWritten = entry.getValue().getPropertiesCopied(); String[] props = propsWritten.toArray(new String[propsWritten.size()]); EventBeanCopyMethod copyMethod = entry.getKey().getCopyMethod(props); if (copyMethod == null) { throw new ExprValidationException( "Variable '" + entry.getValue().getVariableName() + "' of declared type " + JavaClassHelper.getClassNameFullyQualPretty(entry.getKey().getUnderlyingType()) + "' cannot be assigned to"); } copyMethods.put(entry.getKey(), copyMethod); } }
private static void recursiveCompile( EvalNode evalNode, StatementContext context, Set<String> eventTypeReferences, boolean isInsertInto, MatchEventSpec tags, Deque<Integer> subexpressionIdStack) throws ExprValidationException { int counter = 0; for (EvalNode child : evalNode.getChildNodes()) { subexpressionIdStack.addLast(counter++); recursiveCompile( child, context, eventTypeReferences, isInsertInto, tags, subexpressionIdStack); subexpressionIdStack.removeLast(); } LinkedHashMap<String, Pair<EventType, String>> newTaggedEventTypes = null; LinkedHashMap<String, Pair<EventType, String>> newArrayEventTypes = null; if (evalNode instanceof EvalFilterNode) { EvalFilterNode filterNode = (EvalFilterNode) evalNode; String eventName = filterNode.getRawFilterSpec().getEventTypeName(); EventType resolvedEventType = FilterStreamSpecRaw.resolveType( context.getEngineURI(), eventName, context.getEventAdapterService(), context.getPlugInTypeResolutionURIs()); EventType finalEventType = resolvedEventType; String optionalTag = filterNode.getEventAsName(); boolean isPropertyEvaluation = false; // obtain property event type, if final event type is properties if (filterNode.getRawFilterSpec().getOptionalPropertyEvalSpec() != null) { PropertyEvaluator optionalPropertyEvaluator = PropertyEvaluatorFactory.makeEvaluator( filterNode.getRawFilterSpec().getOptionalPropertyEvalSpec(), resolvedEventType, filterNode.getEventAsName(), context.getEventAdapterService(), context.getMethodResolutionService(), context.getSchedulingService(), context.getVariableService(), context.getEngineURI(), context.getStatementId(), context.getStatementName(), context.getAnnotations(), subexpressionIdStack); finalEventType = optionalPropertyEvaluator.getFragmentEventType(); isPropertyEvaluation = true; } if (finalEventType instanceof EventTypeSPI) { eventTypeReferences.add(((EventTypeSPI) finalEventType).getMetadata().getPrimaryName()); } // If a tag was supplied for the type, the tags must stay with this type, i.e. a=BeanA -> // b=BeanA -> a=BeanB is a no if (optionalTag != null) { Pair<EventType, String> pair = tags.getTaggedEventTypes().get(optionalTag); EventType existingType = null; if (pair != null) { existingType = pair.getFirst(); } if (existingType == null) { pair = tags.getArrayEventTypes().get(optionalTag); if (pair != null) { throw new ExprValidationException( "Tag '" + optionalTag + "' for event '" + eventName + "' used in the repeat-until operator cannot also appear in other filter expressions"); } } if ((existingType != null) && (existingType != finalEventType)) { throw new ExprValidationException( "Tag '" + optionalTag + "' for event '" + eventName + "' has already been declared for events of type " + existingType.getUnderlyingType().getName()); } pair = new Pair<EventType, String>(finalEventType, eventName); // add tagged type if (isPropertyEvaluation) { newArrayEventTypes = new LinkedHashMap<String, Pair<EventType, String>>(); newArrayEventTypes.put(optionalTag, pair); } else { newTaggedEventTypes = new LinkedHashMap<String, Pair<EventType, String>>(); newTaggedEventTypes.put(optionalTag, pair); } } // For this filter, filter types are all known tags at this time, // and additionally stream 0 (self) is our event type. // Stream type service allows resolution by property name event if that name appears in other // tags. // by defaulting to stream zero. // Stream zero is always the current event type, all others follow the order of the map // (stream 1 to N). String selfStreamName = optionalTag; if (selfStreamName == null) { selfStreamName = "s_" + UuidGenerator.generate(); } LinkedHashMap<String, Pair<EventType, String>> filterTypes = new LinkedHashMap<String, Pair<EventType, String>>(); Pair<EventType, String> typePair = new Pair<EventType, String>(finalEventType, eventName); filterTypes.put(selfStreamName, typePair); filterTypes.putAll(tags.getTaggedEventTypes()); // for the filter, specify all tags used LinkedHashMap<String, Pair<EventType, String>> filterTaggedEventTypes = new LinkedHashMap<String, Pair<EventType, String>>(tags.getTaggedEventTypes()); filterTaggedEventTypes.remove(optionalTag); // handle array tags (match-until clause) LinkedHashMap<String, Pair<EventType, String>> arrayCompositeEventTypes = null; if (tags.getArrayEventTypes() != null) { arrayCompositeEventTypes = new LinkedHashMap<String, Pair<EventType, String>>(); String patternSubexEventType = getPatternSubexEventType(context.getStatementId(), "pattern", subexpressionIdStack); EventType arrayTagCompositeEventType = context .getEventAdapterService() .createSemiAnonymousMapType( patternSubexEventType, new HashMap(), tags.getArrayEventTypes(), isInsertInto); for (Map.Entry<String, Pair<EventType, String>> entry : tags.getArrayEventTypes().entrySet()) { String tag = entry.getKey(); if (!filterTypes.containsKey(tag)) { Pair<EventType, String> pair = new Pair<EventType, String>(arrayTagCompositeEventType, tag); filterTypes.put(tag, pair); arrayCompositeEventTypes.put(tag, pair); } } } StreamTypeService streamTypeService = new StreamTypeServiceImpl(filterTypes, context.getEngineURI(), true, false); List<ExprNode> exprNodes = filterNode.getRawFilterSpec().getFilterExpressions(); FilterSpecCompiled spec = FilterSpecCompiler.makeFilterSpec( resolvedEventType, eventName, exprNodes, filterNode.getRawFilterSpec().getOptionalPropertyEvalSpec(), filterTaggedEventTypes, arrayCompositeEventTypes, streamTypeService, context.getMethodResolutionService(), context.getSchedulingService(), context.getVariableService(), context.getEventAdapterService(), context.getEngineURI(), null, context, subexpressionIdStack); filterNode.setFilterSpec(spec); } else if (evalNode instanceof EvalObserverNode) { EvalObserverNode observerNode = (EvalObserverNode) evalNode; try { ObserverFactory observerFactory = context.getPatternResolutionService().create(observerNode.getPatternObserverSpec()); StreamTypeService streamTypeService = getStreamTypeService( context.getEngineURI(), context.getStatementId(), context.getEventAdapterService(), tags.taggedEventTypes, tags.arrayEventTypes, subexpressionIdStack, "observer"); ExprValidationContext validationContext = new ExprValidationContext( streamTypeService, context.getMethodResolutionService(), null, context.getSchedulingService(), context.getVariableService(), context, context.getEventAdapterService(), context.getStatementName(), context.getStatementId(), context.getAnnotations()); List<ExprNode> validated = validateExpressions( observerNode.getPatternObserverSpec().getObjectParameters(), validationContext); MatchedEventConvertor convertor = new MatchedEventConvertorImpl( tags.taggedEventTypes, tags.arrayEventTypes, context.getEventAdapterService()); observerNode.setObserverFactory(observerFactory); observerFactory.setObserverParameters(validated, convertor); } catch (ObserverParameterException e) { throw new ExprValidationException( "Invalid parameter for pattern observer: " + e.getMessage(), e); } catch (PatternObjectException e) { throw new ExprValidationException( "Failed to resolve pattern observer: " + e.getMessage(), e); } } else if (evalNode instanceof EvalGuardNode) { EvalGuardNode guardNode = (EvalGuardNode) evalNode; try { GuardFactory guardFactory = context.getPatternResolutionService().create(guardNode.getPatternGuardSpec()); StreamTypeService streamTypeService = getStreamTypeService( context.getEngineURI(), context.getStatementId(), context.getEventAdapterService(), tags.taggedEventTypes, tags.arrayEventTypes, subexpressionIdStack, "guard"); ExprValidationContext validationContext = new ExprValidationContext( streamTypeService, context.getMethodResolutionService(), null, context.getSchedulingService(), context.getVariableService(), context, context.getEventAdapterService(), context.getStatementName(), context.getStatementId(), context.getAnnotations()); List<ExprNode> validated = validateExpressions( guardNode.getPatternGuardSpec().getObjectParameters(), validationContext); MatchedEventConvertor convertor = new MatchedEventConvertorImpl( tags.taggedEventTypes, tags.arrayEventTypes, context.getEventAdapterService()); guardNode.setGuardFactory(guardFactory); guardFactory.setGuardParameters(validated, convertor); } catch (GuardParameterException e) { throw new ExprValidationException( "Invalid parameter for pattern guard: " + e.getMessage(), e); } catch (PatternObjectException e) { throw new ExprValidationException("Failed to resolve pattern guard: " + e.getMessage(), e); } } else if (evalNode instanceof EvalEveryDistinctNode) { EvalEveryDistinctNode distinctNode = (EvalEveryDistinctNode) evalNode; MatchEventSpec matchEventFromChildNodes = analyzeMatchEvent(distinctNode); StreamTypeService streamTypeService = getStreamTypeService( context.getEngineURI(), context.getStatementId(), context.getEventAdapterService(), matchEventFromChildNodes.getTaggedEventTypes(), matchEventFromChildNodes.getArrayEventTypes(), subexpressionIdStack, "every-distinct"); ExprValidationContext validationContext = new ExprValidationContext( streamTypeService, context.getMethodResolutionService(), null, context.getSchedulingService(), context.getVariableService(), context, context.getEventAdapterService(), context.getStatementName(), context.getStatementId(), context.getAnnotations()); List<ExprNode> validated; try { validated = validateExpressions(distinctNode.getExpressions(), validationContext); } catch (ExprValidationPropertyException ex) { throw new ExprValidationPropertyException( ex.getMessage() + ", every-distinct requires that all properties resolve from sub-expressions to the every-distinct", ex.getCause()); } MatchedEventConvertor convertor = new MatchedEventConvertorImpl( matchEventFromChildNodes.getTaggedEventTypes(), matchEventFromChildNodes.getArrayEventTypes(), context.getEventAdapterService()); distinctNode.setConvertor(convertor); // Determine whether some expressions are constants or time period List<ExprNode> distinctExpressions = new ArrayList<ExprNode>(); Long msecToExpire = null; for (ExprNode expr : validated) { if (expr instanceof ExprTimePeriod) { Double secondsExpire = (Double) ((ExprTimePeriod) expr).evaluate(null, true, context); if ((secondsExpire != null) && (secondsExpire > 0)) { msecToExpire = Math.round(1000d * secondsExpire); } log.debug("Setting every-distinct msec-to-expire to " + msecToExpire); } else if (expr.isConstantResult()) { log.warn( "Every-distinct node utilizes an expression returning a constant value, please check expression '" + expr.toExpressionString() + "', not adding expression to distinct-value expression list"); } else { distinctExpressions.add(expr); } } if (distinctExpressions.isEmpty()) { throw new ExprValidationException( "Every-distinct node requires one or more distinct-value expressions that each return non-constant result values"); } distinctNode.setExpressions(distinctExpressions, msecToExpire); } else if (evalNode instanceof EvalMatchUntilNode) { EvalMatchUntilNode matchUntilNode = (EvalMatchUntilNode) evalNode; // compile bounds expressions, if any MatchEventSpec untilMatchEventSpec = new MatchEventSpec(tags.getTaggedEventTypes(), tags.getArrayEventTypes()); StreamTypeService streamTypeService = getStreamTypeService( context.getEngineURI(), context.getStatementId(), context.getEventAdapterService(), untilMatchEventSpec.getTaggedEventTypes(), untilMatchEventSpec.getArrayEventTypes(), subexpressionIdStack, "until"); ExprValidationContext validationContext = new ExprValidationContext( streamTypeService, context.getMethodResolutionService(), null, context.getSchedulingService(), context.getVariableService(), context, context.getEventAdapterService(), context.getStatementName(), context.getStatementId(), context.getAnnotations()); String message = "Match-until bounds value expressions must return a numeric value"; if (matchUntilNode.getLowerBounds() != null) { ExprNode validated = ExprNodeUtility.getValidatedSubtree(matchUntilNode.getLowerBounds(), validationContext); matchUntilNode.setLowerBounds(validated); if ((validated.getExprEvaluator().getType() == null) || (!JavaClassHelper.isNumeric(validated.getExprEvaluator().getType()))) { throw new ExprValidationException(message); } } if (matchUntilNode.getUpperBounds() != null) { ExprNode validated = ExprNodeUtility.getValidatedSubtree(matchUntilNode.getUpperBounds(), validationContext); matchUntilNode.setUpperBounds(validated); if ((validated.getExprEvaluator().getType() == null) || (!JavaClassHelper.isNumeric(validated.getExprEvaluator().getType()))) { throw new ExprValidationException(message); } } MatchedEventConvertor convertor = new MatchedEventConvertorImpl( untilMatchEventSpec.getTaggedEventTypes(), untilMatchEventSpec.getArrayEventTypes(), context.getEventAdapterService()); matchUntilNode.setConvertor(convertor); // compile new tag lists Set<String> arrayTags = null; EvalNodeAnalysisResult matchUntilAnalysisResult = EvalNodeUtil.recursiveAnalyzeChildNodes(matchUntilNode.getChildNodes().get(0)); for (EvalFilterNode filterNode : matchUntilAnalysisResult.getFilterNodes()) { String optionalTag = filterNode.getEventAsName(); if (optionalTag != null) { if (arrayTags == null) { arrayTags = new HashSet<String>(); } arrayTags.add(optionalTag); } } if (arrayTags != null) { for (String arrayTag : arrayTags) { if (!tags.arrayEventTypes.containsKey(arrayTag)) { tags.arrayEventTypes.put(arrayTag, tags.taggedEventTypes.get(arrayTag)); tags.taggedEventTypes.remove(arrayTag); } } } matchUntilNode.setTagsArrayedSet(arrayTags); } else if (evalNode instanceof EvalFollowedByNode) { EvalFollowedByNode followedByNode = (EvalFollowedByNode) evalNode; StreamTypeService streamTypeService = new StreamTypeServiceImpl(context.getEngineURI(), false); ExprValidationContext validationContext = new ExprValidationContext( streamTypeService, context.getMethodResolutionService(), null, context.getSchedulingService(), context.getVariableService(), context, context.getEventAdapterService(), context.getStatementName(), context.getStatementId(), context.getAnnotations()); if (followedByNode.getOptionalMaxExpressions() != null) { List<ExprNode> validated = new ArrayList<ExprNode>(); for (ExprNode maxExpr : followedByNode.getOptionalMaxExpressions()) { if (maxExpr == null) { validated.add(null); } else { ExprNodeSummaryVisitor visitor = new ExprNodeSummaryVisitor(); maxExpr.accept(visitor); if (!visitor.isPlain()) { String errorMessage = "Invalid maximum expression in followed-by, " + visitor.getMessage() + " are not allowed within the expression"; log.error(errorMessage); throw new ExprValidationException(errorMessage); } ExprNode validatedExpr = ExprNodeUtility.getValidatedSubtree(maxExpr, validationContext); validated.add(validatedExpr); if ((validatedExpr.getExprEvaluator().getType() == null) || (!JavaClassHelper.isNumeric(validatedExpr.getExprEvaluator().getType()))) { String message = "Invalid maximum expression in followed-by, the expression must return an integer value"; throw new ExprValidationException(message); } } } followedByNode.setOptionalMaxExpressions(validated); } } if (newTaggedEventTypes != null) { tags.getTaggedEventTypes().putAll(newTaggedEventTypes); } if (newArrayEventTypes != null) { tags.getArrayEventTypes().putAll(newArrayEventTypes); } }
/** * 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; 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 = EPLTreeWalker.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 = new ArrayList<ExprNode>(parent.getChildCount()); for (int i = 0; i < parent.getChildCount(); i++) { crontabScheduleSpec.add(astExprNodeMap.remove(parent.getChild(i))); } } 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) { ExprNode expression = astExprNodeMap.remove(child); try { ExprValidationContext validationContext = new ExprValidationContext( new StreamTypeServiceImpl(engineURI, false), null, null, timeProvider, variableService, exprEvaluatorContext, null, null, null, null); timePeriodExpr = (ExprTimePeriod) ExprNodeUtility.getValidatedSubtree(expression, validationContext); } catch (ExprValidationException ex) { throw new ASTWalkException("Invalid time period expresion: " + ex.getMessage(), ex); } } 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) { try { ExprValidationContext validationContext = new ExprValidationContext( new StreamTypeServiceImpl(engineURI, false), null, null, timeProvider, variableService, exprEvaluatorContext, null, null, null, null); afterTimePeriodExpr = (ExprTimePeriod) ExprNodeUtility.getValidatedSubtree(expression, validationContext); } catch (ExprValidationException ex) { throw new ASTWalkException("Invalid time period expresion: " + ex.getMessage(), ex); } } else { Object constant = ASTConstantHelper.parse(node.getChild(i).getChild(0)); afterNumberOfEvents = ((Number) constant).intValue(); } } } switch (node.getType()) { case EsperEPL2GrammarParser.EVENT_LIMIT_EXPR: return new OutputLimitSpec( rate, variableName, OutputLimitRateType.EVENTS, displayLimit, null, null, null, null, afterTimePeriodExpr, afterNumberOfEvents); case EsperEPL2GrammarParser.TIMEPERIOD_LIMIT_EXPR: return new OutputLimitSpec( null, null, OutputLimitRateType.TIME_PERIOD, displayLimit, null, null, null, timePeriodExpr, afterTimePeriodExpr, afterNumberOfEvents); case EsperEPL2GrammarParser.CRONTAB_LIMIT_EXPR: return new OutputLimitSpec( null, null, OutputLimitRateType.CRONTAB, displayLimit, null, null, crontabScheduleSpec, null, afterTimePeriodExpr, afterNumberOfEvents); case EsperEPL2GrammarParser.WHEN_LIMIT_EXPR: return new OutputLimitSpec( null, null, OutputLimitRateType.WHEN_EXPRESSION, displayLimit, whenExpression, thenExpressions, null, null, afterTimePeriodExpr, afterNumberOfEvents); case EsperEPL2GrammarParser.AFTER_LIMIT_EXPR: return new OutputLimitSpec( null, null, OutputLimitRateType.AFTER, displayLimit, null, null, null, null, afterTimePeriodExpr, afterNumberOfEvents); default: throw new IllegalArgumentException( "Node type " + node.getType() + " not a recognized output limit type"); } }