internal ContextDetailMatchPair( ContextSpecCondition condition, MatchEventSpec matches, ISet<string> allTags) { Condition = condition; Matches = matches; AllTags = allTags; }
internal PatternValidatedDesc( MatchEventSpec matchEventSpec, ISet<String> allTags, IList<StmtClassForgeableFactory> additionalForgeables) { this.MatchEventSpec = matchEventSpec; this.AllTags = allTags; this.AdditionalForgeables = additionalForgeables; }
internal ContextDetailMatchPair( ContextSpecCondition condition, MatchEventSpec matches, ISet<string> allTags, IList<StmtClassForgeableFactory> additionalForgeables) { Condition = condition; Matches = matches; AllTags = allTags; AdditionalForgeables = additionalForgeables; }
private Pair <MatchEventSpec, ISet <string> > ValidatePatternContextConditionPattern( StatementContext statementContext, ContextDetailConditionPattern pattern, ISet <string> eventTypesReferenced, MatchEventSpec priorMatches, ISet <string> priorAllTags) { var raw = new PatternStreamSpecRaw(pattern.PatternRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, new StreamSpecOptions(), false, false); var compiled = raw.Compile(statementContext, eventTypesReferenced, false, Collections.GetEmptyList <int>(), priorMatches, priorAllTags, false, true, false); pattern.PatternCompiled = compiled; return(new Pair <MatchEventSpec, ISet <string> >(new MatchEventSpec(compiled.TaggedEventTypes, compiled.ArrayEventTypes), compiled.AllTags)); }
private PatternValidatedDesc ValidatePatternContextConditionPattern( bool isStartCondition, int nestingLevel, ContextSpecConditionPattern pattern, ISet<string> eventTypesReferenced, MatchEventSpec priorMatches, ISet<string> priorAllTags, CreateContextValidationEnv validationEnv) { var raw = new PatternStreamSpecRaw( pattern.PatternRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT, false, false); var compiledDesc = StreamSpecCompiler.CompilePatternWTags( raw, eventTypesReferenced, false, priorMatches, priorAllTags, false, true, false, 0, validationEnv.StatementRawInfo, validationEnv.Services); var compiled = (PatternStreamSpecCompiled) compiledDesc.StreamSpecCompiled; pattern.PatternCompiled = compiled; pattern.PatternContext = new PatternContext( 0, compiled.MatchedEventMapMeta, true, nestingLevel, isStartCondition); var forges = compiled.Root.CollectFactories(); foreach (var forge in forges) { forge.CollectSelfFilterAndSchedule( validationEnv.FilterSpecCompileds, validationEnv.ScheduleHandleCallbackProviders); } var spec = new MatchEventSpec(compiled.TaggedEventTypes, compiled.ArrayEventTypes); return new PatternValidatedDesc(spec, compiled.AllTags, compiledDesc.AdditionalForgeables); }
private ContextDetailMatchPair ValidateRewriteContextCondition( EPServicesContext servicesContext, StatementContext statementContext, ContextDetailCondition endpoint, ISet <string> eventTypesReferenced, MatchEventSpec priorMatches, ISet <string> priorAllTags) { if (endpoint is ContextDetailConditionCrontab) { var crontab = (ContextDetailConditionCrontab)endpoint; var schedule = ExprNodeUtility.ToCrontabSchedule(ExprNodeOrigin.CONTEXTCONDITION, crontab.Crontab, statementContext, false); crontab.Schedule = schedule; return(new ContextDetailMatchPair(crontab, new MatchEventSpec(), new LinkedHashSet <string>())); } if (endpoint is ContextDetailConditionTimePeriod) { var timePeriod = (ContextDetailConditionTimePeriod)endpoint; var validationContext = new ExprValidationContext( new StreamTypeServiceImpl(servicesContext.EngineURI, false), statementContext.EngineImportService, statementContext.StatementExtensionServicesContext, null, statementContext.SchedulingService, statementContext.VariableService, statementContext.TableService, GetDefaultAgentInstanceContext(statementContext), statementContext.EventAdapterService, statementContext.StatementName, statementContext.StatementId, statementContext.Annotations, statementContext.ContextDescriptor, statementContext.ScriptingService, false, false, false, false, null, false); ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.CONTEXTCONDITION, timePeriod.TimePeriod, validationContext); if (timePeriod.TimePeriod.IsConstantResult) { if (timePeriod.TimePeriod.EvaluateAsSeconds(null, true, null) < 0) { throw new ExprValidationException("Invalid negative time period expression '" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(timePeriod.TimePeriod) + "'"); } } return(new ContextDetailMatchPair(timePeriod, new MatchEventSpec(), new LinkedHashSet <string>())); } if (endpoint is ContextDetailConditionPattern) { var pattern = (ContextDetailConditionPattern)endpoint; var matches = ValidatePatternContextConditionPattern(statementContext, pattern, eventTypesReferenced, priorMatches, priorAllTags); return(new ContextDetailMatchPair(pattern, matches.First, matches.Second)); } if (endpoint is ContextDetailConditionFilter) { var filter = (ContextDetailConditionFilter)endpoint; ValidateNotTable(servicesContext, filter.FilterSpecRaw.EventTypeName); // compile as filter if there are no prior match to consider if (priorMatches == null || (priorMatches.ArrayEventTypes.IsEmpty() && priorMatches.TaggedEventTypes.IsEmpty())) { var rawExpr = new FilterStreamSpecRaw(filter.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, new StreamSpecOptions()); var compiled = (FilterStreamSpecCompiled)rawExpr.Compile(statementContext, eventTypesReferenced, false, Collections.GetEmptyList <int>(), false, true, false, filter.OptionalFilterAsName); filter.FilterSpecCompiled = compiled.FilterSpec; var matchEventSpec = new MatchEventSpec(); var filterForType = compiled.FilterSpec.FilterForEventType; var allTags = new LinkedHashSet <string>(); if (filter.OptionalFilterAsName != null) { matchEventSpec.TaggedEventTypes.Put(filter.OptionalFilterAsName, new Pair <EventType, string>(filterForType, rawExpr.RawFilterSpec.EventTypeName)); allTags.Add(filter.OptionalFilterAsName); } return(new ContextDetailMatchPair(filter, matchEventSpec, allTags)); } // compile as pattern if there are prior matches to consider, since this is a type of followed-by relationship var factoryNode = servicesContext.PatternNodeFactory.MakeFilterNode(filter.FilterSpecRaw, filter.OptionalFilterAsName, 0); var pattern = new ContextDetailConditionPattern(factoryNode, true, false); var matches = ValidatePatternContextConditionPattern(statementContext, pattern, eventTypesReferenced, priorMatches, priorAllTags); return(new ContextDetailMatchPair(pattern, matches.First, matches.Second)); } else if (endpoint is ContextDetailConditionImmediate) { return(new ContextDetailMatchPair(endpoint, new MatchEventSpec(), new LinkedHashSet <string>())); } else { throw new IllegalStateException("Unrecognized endpoint type " + endpoint); } }
private static void RecursiveCompile( EvalForgeNode evalNode, ISet<string> eventTypeReferences, bool isInsertInto, MatchEventSpec tags, Stack<EvalForgeNode> parentNodeStack, ISet<string> allTagNamesOrdered, int streamNum, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { parentNodeStack.Push(evalNode); foreach (var child in evalNode.ChildNodes) { RecursiveCompile( child, eventTypeReferences, isInsertInto, tags, parentNodeStack, allTagNamesOrdered, streamNum, statementRawInfo, services); } parentNodeStack.Pop(); IDictionary<string, Pair<EventType, string>> newTaggedEventTypes = null; IDictionary<string, Pair<EventType, string>> newArrayEventTypes = null; if (evalNode is EvalFilterForgeNode) { var filterNode = (EvalFilterForgeNode) evalNode; var eventName = filterNode.RawFilterSpec.EventTypeName; if (services.TableCompileTimeResolver.Resolve(eventName) != null) { throw new ExprValidationException("Tables cannot be used in pattern filter atoms"); } var resolvedEventType = ResolveTypeName(eventName, services.EventTypeCompileTimeResolver); var finalEventType = resolvedEventType; var optionalTag = filterNode.EventAsName; var isPropertyEvaluation = false; var isParentMatchUntil = IsParentMatchUntil(evalNode, parentNodeStack); // obtain property event type, if final event type is properties if (filterNode.RawFilterSpec.OptionalPropertyEvalSpec != null) { var optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator( filterNode.RawFilterSpec.OptionalPropertyEvalSpec, resolvedEventType, filterNode.EventAsName, statementRawInfo, services); finalEventType = optionalPropertyEvaluator.FragmentEventType; isPropertyEvaluation = true; } // 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) { var pair = tags.TaggedEventTypes.Get(optionalTag); EventType existingType = null; if (pair != null) { existingType = pair.First; } if (existingType == null) { pair = tags.ArrayEventTypes.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.UnderlyingType.Name); } pair = new Pair<EventType, string>(finalEventType, eventName); // add tagged type if (isPropertyEvaluation || isParentMatchUntil) { 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). var selfStreamName = optionalTag; if (selfStreamName == null) { selfStreamName = "s_" + UuidGenerator.Generate(); } var filterTypes = new LinkedHashMap<string, Pair<EventType, string>>(); var typePair = new Pair<EventType, string>(finalEventType, eventName); filterTypes.Put(selfStreamName, typePair); filterTypes.PutAll(tags.TaggedEventTypes); // for the filter, specify all tags used var filterTaggedEventTypes = new LinkedHashMap<string, Pair<EventType, string>>(tags.TaggedEventTypes); filterTaggedEventTypes.Remove(optionalTag); // handle array tags (match-until clause) IDictionary<string, Pair<EventType, string>> arrayCompositeEventTypes = null; if (tags.ArrayEventTypes != null && !tags.ArrayEventTypes.IsEmpty()) { arrayCompositeEventTypes = new LinkedHashMap<string, Pair<EventType, string>>(); foreach (var entry in tags.ArrayEventTypes) { var specificArrayType = new LinkedHashMap<string, Pair<EventType, string>>(); specificArrayType.Put(entry.Key, entry.Value); var eventTypeName = services.EventTypeNameGeneratorStatement.GetAnonymousPatternNameWTag( streamNum, evalNode.FactoryNodeId, entry.Key); var mapProps = GetMapProperties( Collections.GetEmptyMap<string, Pair<EventType, string>>(), specificArrayType); var metadata = new EventTypeMetadata( eventTypeName, statementRawInfo.ModuleName, EventTypeTypeClass.PATTERNDERIVED, EventTypeApplicationType.MAP, NameAccessModifier.TRANSIENT, EventTypeBusModifier.NONBUS, false, EventTypeIdPair.Unassigned()); var mapEventType = BaseNestableEventUtil.MakeMapTypeCompileTime( metadata, mapProps, null, null, null, null, services.BeanEventTypeFactoryPrivate, services.EventTypeCompileTimeResolver); services.EventTypeCompileTimeRegistry.NewType(mapEventType); var tag = entry.Key; if (!filterTypes.ContainsKey(tag)) { var pair = new Pair<EventType, string>(mapEventType, tag); filterTypes.Put(tag, pair); arrayCompositeEventTypes.Put(tag, pair); } } } StreamTypeService streamTypeService = new StreamTypeServiceImpl(filterTypes, true, false); var exprNodes = filterNode.RawFilterSpec.FilterExpressions; var spec = FilterSpecCompiler.MakeFilterSpec( resolvedEventType, eventName, exprNodes, filterNode.RawFilterSpec.OptionalPropertyEvalSpec, filterTaggedEventTypes, arrayCompositeEventTypes, streamTypeService, null, statementRawInfo, services); filterNode.FilterSpec = spec; } else if (evalNode is EvalObserverForgeNode) { var observerNode = (EvalObserverForgeNode) evalNode; try { var observerForge = services.PatternResolutionService.Create(observerNode.PatternObserverSpec); var streamTypeService = GetStreamTypeService( tags.TaggedEventTypes, tags.ArrayEventTypes, observerNode, streamNum, statementRawInfo, services); var validationContext = new ExprValidationContextBuilder( streamTypeService, statementRawInfo, services).Build(); var validated = ValidateExpressions( ExprNodeOrigin.PATTERNOBSERVER, observerNode.PatternObserverSpec.ObjectParameters, validationContext); var convertor = new MatchedEventConvertorForge( tags.TaggedEventTypes, tags.ArrayEventTypes, allTagNamesOrdered); observerNode.ObserverFactory = observerForge; observerForge.SetObserverParameters(validated, convertor, validationContext); } catch (ObserverParameterException e) { throw new ExprValidationException( "Invalid parameter for pattern observer '" + observerNode.ToPrecedenceFreeEPL() + "': " + e.Message, e); } catch (PatternObjectException e) { throw new ExprValidationException( "Failed to resolve pattern observer '" + observerNode.ToPrecedenceFreeEPL() + "': " + e.Message, e); } } else if (evalNode is EvalGuardForgeNode) { var guardNode = (EvalGuardForgeNode) evalNode; try { var guardForge = services.PatternResolutionService.Create(guardNode.PatternGuardSpec); var streamTypeService = GetStreamTypeService( tags.TaggedEventTypes, tags.ArrayEventTypes, guardNode, streamNum, statementRawInfo, services); var validationContext = new ExprValidationContextBuilder( streamTypeService, statementRawInfo, services).Build(); var validated = ValidateExpressions( ExprNodeOrigin.PATTERNGUARD, guardNode.PatternGuardSpec.ObjectParameters, validationContext); var convertor = new MatchedEventConvertorForge( tags.TaggedEventTypes, tags.ArrayEventTypes, allTagNamesOrdered); guardNode.GuardForge = guardForge; guardForge.SetGuardParameters(validated, convertor, services); } catch (GuardParameterException e) { throw new ExprValidationException( "Invalid parameter for pattern guard '" + guardNode.ToPrecedenceFreeEPL() + "': " + e.Message, e); } catch (PatternObjectException e) { throw new ExprValidationException( "Failed to resolve pattern guard '" + guardNode.ToPrecedenceFreeEPL() + "': " + e.Message, e); } } else if (evalNode is EvalEveryDistinctForgeNode) { var distinctNode = (EvalEveryDistinctForgeNode) evalNode; var matchEventFromChildNodes = AnalyzeMatchEvent(distinctNode); var streamTypeService = GetStreamTypeService( matchEventFromChildNodes.TaggedEventTypes, matchEventFromChildNodes.ArrayEventTypes, distinctNode, streamNum, statementRawInfo, services); var validationContext = new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services).Build(); IList<ExprNode> validated; try { validated = ValidateExpressions( ExprNodeOrigin.PATTERNEVERYDISTINCT, distinctNode.Expressions, validationContext); } catch (ExprValidationPropertyException ex) { throw new ExprValidationPropertyException( ex.Message + ", every-distinct requires that all properties resolve from sub-expressions to the every-distinct", ex.InnerException); } var convertor = new MatchedEventConvertorForge( matchEventFromChildNodes.TaggedEventTypes, matchEventFromChildNodes.ArrayEventTypes, allTagNamesOrdered); distinctNode.Convertor = convertor; // Determine whether some expressions are constants or time period IList<ExprNode> distinctExpressions = new List<ExprNode>(); TimePeriodComputeForge timePeriodComputeForge = null; ExprNode expiryTimeExp = null; var count = -1; var last = validated.Count - 1; foreach (var expr in validated) { count++; if (count == last && expr is ExprTimePeriod) { expiryTimeExp = expr; var timePeriodExpr = (ExprTimePeriod) expiryTimeExp; timePeriodComputeForge = timePeriodExpr.TimePeriodComputeForge; } else if (expr.Forge.ForgeConstantType.IsCompileTimeConstant) { if (count == last) { var value = expr.Forge.ExprEvaluator.Evaluate(null, true, null); if (!value.IsNumber()) { throw new ExprValidationException( "Invalid parameter for every-distinct, expected number of seconds constant (constant not considered for distinct)"); } var secondsExpire = expr.Forge.ExprEvaluator.Evaluate(null, true, null); var timeExpire = secondsExpire == null ? (long?) null : (long?) services.ImportServiceCompileTime.TimeAbacus.DeltaForSecondsNumber( secondsExpire); if (timeExpire != null && timeExpire > 0) { timePeriodComputeForge = new TimePeriodComputeConstGivenDeltaForge(timeExpire.Value); expiryTimeExp = expr; } else { Log.Warn( "Invalid seconds-expire " + timeExpire + " for " + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(expr)); } } else { Log.Warn( "Every-distinct node utilizes an expression returning a constant value, please check expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(expr) + "', 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.SetDistinctExpressions(distinctExpressions, timePeriodComputeForge, expiryTimeExp); } else if (evalNode is EvalMatchUntilForgeNode) { var matchUntilNode = (EvalMatchUntilForgeNode) evalNode; // compile bounds expressions, if any var untilMatchEventSpec = new MatchEventSpec(tags.TaggedEventTypes, tags.ArrayEventTypes); var streamTypeService = GetStreamTypeService( untilMatchEventSpec.TaggedEventTypes, untilMatchEventSpec.ArrayEventTypes, matchUntilNode, streamNum, statementRawInfo, services); var validationContext = new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services).Build(); var lower = ValidateBounds(matchUntilNode.LowerBounds, validationContext); matchUntilNode.LowerBounds = lower; var upper = ValidateBounds(matchUntilNode.UpperBounds, validationContext); matchUntilNode.UpperBounds = upper; var single = ValidateBounds(matchUntilNode.SingleBound, validationContext); matchUntilNode.SingleBound = single; bool tightlyBound; if (matchUntilNode.SingleBound != null) { ValidateMatchUntil(matchUntilNode.SingleBound, matchUntilNode.SingleBound, false); tightlyBound = true; } else { var allowZeroLowerBounds = matchUntilNode.LowerBounds != null && matchUntilNode.UpperBounds != null; tightlyBound = ValidateMatchUntil( matchUntilNode.LowerBounds, matchUntilNode.UpperBounds, allowZeroLowerBounds); } if (matchUntilNode.SingleBound == null && !tightlyBound && matchUntilNode.ChildNodes.Count < 2) { throw new ExprValidationException("Variable bounds repeat operator requires an until-expression"); } var convertor = new MatchedEventConvertorForge( untilMatchEventSpec.TaggedEventTypes, untilMatchEventSpec.ArrayEventTypes, allTagNamesOrdered); matchUntilNode.Convertor = convertor; // compile new tag lists ISet<string> arrayTags = null; var matchUntilAnalysisResult = EvalNodeUtil.RecursiveAnalyzeChildNodes(matchUntilNode.ChildNodes[0]); foreach (var filterNode in matchUntilAnalysisResult.FilterNodes) { var optionalTag = filterNode.EventAsName; if (optionalTag != null) { if (arrayTags == null) { arrayTags = new HashSet<string>(); } arrayTags.Add(optionalTag); } } if (arrayTags != null) { foreach (var arrayTag in arrayTags) { if (!tags.ArrayEventTypes.ContainsKey(arrayTag)) { tags.ArrayEventTypes.Put(arrayTag, tags.TaggedEventTypes.Get(arrayTag)); tags.TaggedEventTypes.Remove(arrayTag); } } } matchUntilNode.TagsArrayedSet = GetIndexesForTags(allTagNamesOrdered, arrayTags); } else if (evalNode is EvalFollowedByForgeNode) { var followedByNode = (EvalFollowedByForgeNode) evalNode; StreamTypeService streamTypeService = new StreamTypeServiceImpl(false); var validationContext = new ExprValidationContextBuilder(streamTypeService, statementRawInfo, services).Build(); if (followedByNode.OptionalMaxExpressions != null) { IList<ExprNode> validated = new List<ExprNode>(); foreach (var maxExpr in followedByNode.OptionalMaxExpressions) { if (maxExpr == null) { validated.Add(null); } else { var visitor = new ExprNodeSummaryVisitor(); maxExpr.Accept(visitor); if (!visitor.IsPlain) { var errorMessage = "Invalid maximum expression in followed-by, " + visitor.Message + " are not allowed within the expression"; Log.Error(errorMessage); throw new ExprValidationException(errorMessage); } var validatedExpr = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.FOLLOWEDBYMAX, maxExpr, validationContext); validated.Add(validatedExpr); var returnType = validatedExpr.Forge.EvaluationType; if (returnType == null || !returnType.IsNumeric()) { var message = "Invalid maximum expression in followed-by, the expression must return an integer value"; throw new ExprValidationException(message); } } } followedByNode.OptionalMaxExpressions = validated; } } if (newTaggedEventTypes != null) { tags.TaggedEventTypes.PutAll(newTaggedEventTypes); } if (newArrayEventTypes != null) { tags.ArrayEventTypes.PutAll(newArrayEventTypes); } }
public static PatternStreamSpecCompiled CompilePatternWTags( PatternStreamSpecRaw streamSpecRaw, ISet<string> eventTypeReferences, bool isInsertInto, MatchEventSpec tags, ISet<string> priorAllTags, bool isJoin, bool isContextDeclaration, bool isOnTrigger, int streamNum, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { // validate if ((streamSpecRaw.IsSuppressSameEventMatches || streamSpecRaw.IsDiscardPartialsOnMatch) && (isJoin || isContextDeclaration || isOnTrigger)) { throw new ExprValidationException( "Discard-partials and suppress-matches is not supported in a joins, context declaration and on-action"); } if (tags == null) { tags = new MatchEventSpec(); } var nodeStack = new Stack<EvalForgeNode>(); // detemine ordered tags var allTagNamesOrdered = new LinkedHashSet<string>(); var filterFactoryNodes = EvalNodeUtil.RecursiveGetChildNodes( streamSpecRaw.EvalForgeNode, FilterForFilterFactoryNodes.INSTANCE); if (priorAllTags != null) { allTagNamesOrdered.AddAll(priorAllTags); } foreach (var filterNode in filterFactoryNodes) { var forge = (EvalFilterForgeNode) filterNode; int tagNumber; if (forge.EventAsName != null) { if (!allTagNamesOrdered.Contains(forge.EventAsName)) { allTagNamesOrdered.Add(forge.EventAsName); tagNumber = allTagNamesOrdered.Count - 1; } else { tagNumber = FindTagNumber(forge.EventAsName, allTagNamesOrdered); } forge.EventAsTagNumber = tagNumber; } } // construct root : assigns factory node ids var top = streamSpecRaw.EvalForgeNode; var root = new EvalRootForgeNode(top, statementRawInfo.Annotations); RecursiveCompile( top, eventTypeReferences, isInsertInto, tags, nodeStack, allTagNamesOrdered, streamNum, statementRawInfo, services); var hook = (PatternCompileHook) ImportUtil.GetAnnotationHook( statementRawInfo.Annotations, HookType.INTERNAL_PATTERNCOMPILE, typeof(PatternCompileHook), services.ImportServiceCompileTime); if (hook != null) { hook.Pattern(root); } return new PatternStreamSpecCompiled( root, tags.TaggedEventTypes, tags.ArrayEventTypes, allTagNamesOrdered, streamSpecRaw.ViewSpecs, streamSpecRaw.OptionalStreamName, streamSpecRaw.Options, streamSpecRaw.IsSuppressSameEventMatches, streamSpecRaw.IsDiscardPartialsOnMatch); }
private ContextDetailMatchPair ValidateRewriteContextCondition( bool isStartCondition, int nestingLevel, ContextSpecCondition endpoint, ISet<string> eventTypesReferenced, MatchEventSpec priorMatches, ISet<string> priorAllTags, CreateContextValidationEnv validationEnv) { if (endpoint is ContextSpecConditionCrontab) { var crontab = (ContextSpecConditionCrontab) endpoint; var forgesPerCrontab = new ExprForge[crontab.Crontabs.Count][]; for (int i = 0; i < crontab.Crontabs.Count; i++) { var item = crontab.Crontabs[i]; var forges = ScheduleExpressionUtil.CrontabScheduleValidate( ExprNodeOrigin.CONTEXTCONDITION, item, false, validationEnv.StatementRawInfo, validationEnv.Services); forgesPerCrontab[i] = forges; } crontab.ForgesPerCrontab = forgesPerCrontab; validationEnv.ScheduleHandleCallbackProviders.Add(crontab); return new ContextDetailMatchPair( crontab, new MatchEventSpec(), new LinkedHashSet<string>(), EmptyList<StmtClassForgeableFactory>.Instance); } if (endpoint is ContextSpecConditionTimePeriod) { var timePeriod = (ContextSpecConditionTimePeriod) endpoint; var validationContext = new ExprValidationContextBuilder( new StreamTypeServiceImpl(false), validationEnv.StatementRawInfo, validationEnv.Services).Build(); ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTEXTCONDITION, timePeriod.TimePeriod, validationContext); if (timePeriod.TimePeriod.IsConstantResult) { if (timePeriod.TimePeriod.EvaluateAsSeconds(null, true, null) < 0) { throw new ExprValidationException( "Invalid negative time period expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(timePeriod.TimePeriod) + "'"); } } validationEnv.ScheduleHandleCallbackProviders.Add(timePeriod); return new ContextDetailMatchPair( timePeriod, new MatchEventSpec(), new LinkedHashSet<string>(), EmptyList<StmtClassForgeableFactory>.Instance); } if (endpoint is ContextSpecConditionPattern) { var pattern = (ContextSpecConditionPattern) endpoint; var matches = ValidatePatternContextConditionPattern( isStartCondition, nestingLevel, pattern, eventTypesReferenced, priorMatches, priorAllTags, validationEnv); var validatedDesc = ValidatePatternContextConditionPattern( isStartCondition, nestingLevel, pattern, eventTypesReferenced, priorMatches, priorAllTags, validationEnv); return new ContextDetailMatchPair( pattern, validatedDesc.MatchEventSpec, validatedDesc.AllTags, validatedDesc.AdditionalForgeables); } if (endpoint is ContextSpecConditionFilter) { var filter = (ContextSpecConditionFilter) endpoint; ValidateNotTable(filter.FilterSpecRaw.EventTypeName, validationEnv.Services); // compile as filter if there are no prior match to consider if (priorMatches == null || priorMatches.ArrayEventTypes.IsEmpty() && priorMatches.TaggedEventTypes.IsEmpty()) { var rawExpr = new FilterStreamSpecRaw( filter.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDesc = StreamSpecCompiler.Compile( rawExpr, eventTypesReferenced, false, false, true, false, filter.OptionalFilterAsName, 0, validationEnv.StatementRawInfo, validationEnv.Services); var compiled = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; filter.FilterSpecCompiled = compiled.FilterSpecCompiled; var matchEventSpec = new MatchEventSpec(); var filterForType = compiled.FilterSpecCompiled.FilterForEventType; var allTags = new LinkedHashSet<string>(); if (filter.OptionalFilterAsName != null) { matchEventSpec.TaggedEventTypes.Put( filter.OptionalFilterAsName, new Pair<EventType, string>(filterForType, rawExpr.RawFilterSpec.EventTypeName)); allTags.Add(filter.OptionalFilterAsName); } validationEnv.FilterSpecCompileds.Add(compiled.FilterSpecCompiled); var serdeForgeables = SerdeEventTypeUtility.Plan( filter.FilterSpecCompiled.FilterForEventType, validationEnv.StatementRawInfo, validationEnv.Services.SerdeEventTypeRegistry, validationEnv.Services.SerdeResolver); var allForgeables = compiledDesc.AdditionalForgeables .Concat(serdeForgeables) .ToList(); return new ContextDetailMatchPair(filter, matchEventSpec, allTags, allForgeables); } // compile as pattern if there are prior matches to consider, since this is a type of followed-by relationship EvalForgeNode forgeNode = new EvalFilterForgeNode(validationEnv.Services.IsAttachPatternText, filter.FilterSpecRaw, filter.OptionalFilterAsName, 0); var pattern = new ContextSpecConditionPattern(forgeNode, true, false); var validated = ValidatePatternContextConditionPattern( isStartCondition, nestingLevel, pattern, eventTypesReferenced, priorMatches, priorAllTags, validationEnv); return new ContextDetailMatchPair(pattern, validated.MatchEventSpec, validated.AllTags, validated.AdditionalForgeables); } if (endpoint is ContextSpecConditionImmediate || endpoint is ContextSpecConditionNever) { return new ContextDetailMatchPair( endpoint, new MatchEventSpec(), new LinkedHashSet<String>(), EmptyList<StmtClassForgeableFactory>.Instance); } throw new IllegalStateException("Unrecognized endpoint type " + endpoint); }
private IList<StmtClassForgeableFactory> ValidateContextDetail( ContextSpec contextSpec, int nestingLevel, CreateContextValidationEnv validationEnv) { ISet<string> eventTypesReferenced = new HashSet<string>(); IList<StmtClassForgeableFactory> additionalForgeables = new List<StmtClassForgeableFactory>(); if (contextSpec is ContextSpecKeyed) { var segmented = (ContextSpecKeyed) contextSpec; IDictionary<string, EventType> asNames = new Dictionary<string, EventType>(); var partitionHasNameAssignment = false; Type[] getterTypes = null; foreach (var partition in segmented.Items) { Pair<FilterSpecCompiled, IList<StmtClassForgeableFactory>> pair = CompilePartitionedFilterSpec( partition.FilterSpecRaw, eventTypesReferenced, validationEnv); FilterSpecCompiled filterSpecCompiled = pair.First; additionalForgeables.AddAll(pair.Second); partition.FilterSpecCompiled = filterSpecCompiled; var getters = new EventPropertyGetterSPI[partition.PropertyNames.Count]; var serdes = new DataInputOutputSerdeForge[partition.PropertyNames.Count]; var eventType = (EventTypeSPI) filterSpecCompiled.FilterForEventType; getterTypes = new Type[partition.PropertyNames.Count]; for (var i = 0; i < partition.PropertyNames.Count; i++) { var propertyName = partition.PropertyNames[i]; var getter = eventType.GetGetterSPI(propertyName); if (getter == null) { throw new ExprValidationException( "For context '" + validationEnv.ContextName + "' property name '" + propertyName + "' not found on type " + eventType.Name); } getters[i] = getter; getterTypes[i] = eventType.GetPropertyType(propertyName); serdes[i] = validationEnv.Services.SerdeResolver.SerdeForFilter( getterTypes[i], validationEnv.StatementRawInfo); } partition.Getters = getters; partition.LookupableSerdes = serdes; if (partition.AliasName != null) { partitionHasNameAssignment = true; ValidateAsName(asNames, partition.AliasName, filterSpecCompiled.FilterForEventType); } } // plan multi-key, make sure we use the same multikey for all items MultiKeyPlan multiKeyPlan = MultiKeyPlanner.PlanMultiKey( getterTypes, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); foreach (ContextSpecKeyedItem partition in segmented.Items) { partition.KeyMultiKey = multiKeyPlan.ClassRef; } segmented.MultiKeyClassRef = multiKeyPlan.ClassRef; if (segmented.OptionalInit != null) { asNames.Clear(); foreach (var initCondition in segmented.OptionalInit) { ContextDetailMatchPair pair = ValidateRewriteContextCondition( true, nestingLevel, initCondition, eventTypesReferenced, new MatchEventSpec(), new EmptySet<string>(), validationEnv); additionalForgeables.AddAll(pair.AdditionalForgeables); var filterForType = initCondition.FilterSpecCompiled.FilterForEventType; var found = false; foreach (var partition in segmented.Items) { if (partition.FilterSpecCompiled.FilterForEventType == filterForType) { found = true; break; } } if (!found) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that all of the event types that are listed in the initialized-by also appear in the partition-by, type '" + filterForType.Name + "' is not one of the types listed in partition-by"); } if (initCondition.OptionalFilterAsName != null) { if (partitionHasNameAssignment) { throw new ExprValidationException( "Segmented context '" + validationEnv.ContextName + "' requires that either partition-by or initialized-by assign stream names, but not both"); } ValidateAsName(asNames, initCondition.OptionalFilterAsName, filterForType); } } } if (segmented.OptionalTermination != null) { var matchEventSpec = new MatchEventSpec(); var allTags = new LinkedHashSet<string>(); foreach (var partition in segmented.Items) { if (partition.AliasName != null) { allTags.Add(partition.AliasName); var eventType = partition.FilterSpecCompiled.FilterForEventType; matchEventSpec.TaggedEventTypes[partition.AliasName] = new Pair<EventType,string>( eventType, partition.FilterSpecRaw.EventTypeName); var serdeForgeables = SerdeEventTypeUtility.Plan( eventType, validationEnv.StatementRawInfo, validationEnv.Services.SerdeEventTypeRegistry, validationEnv.Services.SerdeResolver); additionalForgeables.AddAll(serdeForgeables); } } if (segmented.OptionalInit != null) { foreach (var initCondition in segmented.OptionalInit) { if (initCondition.OptionalFilterAsName != null) { allTags.Add(initCondition.OptionalFilterAsName); matchEventSpec.TaggedEventTypes.Put( initCondition.OptionalFilterAsName, new Pair<EventType, string>( initCondition.FilterSpecCompiled.FilterForEventType, initCondition.FilterSpecRaw.EventTypeName)); } } } var endCondition = ValidateRewriteContextCondition( false, nestingLevel, segmented.OptionalTermination, eventTypesReferenced, matchEventSpec, allTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); segmented.OptionalTermination = endCondition.Condition; } } else if (contextSpec is ContextSpecCategory) { // compile filter var category = (ContextSpecCategory) contextSpec; ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var raw = new FilterStreamSpecRaw( category.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDesc = StreamSpecCompiler.CompileFilter( raw, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); category.FilterSpecCompiled = result.FilterSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); // compile expressions foreach (var item in category.Items) { ValidateNotTable(category.FilterSpecRaw.EventTypeName, validationEnv.Services); var filterSpecRaw = new FilterSpecRaw( category.FilterSpecRaw.EventTypeName, Collections.SingletonList(item.Expression), null); var rawExpr = new FilterStreamSpecRaw( filterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); var compiledDescItems = StreamSpecCompiler.CompileFilter( rawExpr, false, false, true, false, null, validationEnv.StatementRawInfo, validationEnv.Services); var compiled = (FilterStreamSpecCompiled) compiledDescItems.StreamSpecCompiled; additionalForgeables.AddAll(compiledDescItems.AdditionalForgeables); compiled.FilterSpecCompiled.TraverseFilterBooleanExpr( node => validationEnv.FilterBooleanExpressions.Add(node)); item.FilterPlan = compiled.FilterSpecCompiled.Parameters; } } else if (contextSpec is ContextSpecHash) { var hashed = (ContextSpecHash) contextSpec; foreach (var hashItem in hashed.Items) { var raw = new FilterStreamSpecRaw( hashItem.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, StreamSpecOptions.DEFAULT); ValidateNotTable(hashItem.FilterSpecRaw.EventTypeName, validationEnv.Services); var compiledDesc = StreamSpecCompiler.Compile( raw, eventTypesReferenced, false, false, true, false, null, 0, validationEnv.StatementRawInfo, validationEnv.Services); additionalForgeables.AddAll(compiledDesc.AdditionalForgeables); var result = (FilterStreamSpecCompiled) compiledDesc.StreamSpecCompiled; validationEnv.FilterSpecCompileds.Add(result.FilterSpecCompiled); hashItem.FilterSpecCompiled = result.FilterSpecCompiled; // validate parameters var streamTypes = new StreamTypeServiceImpl( result.FilterSpecCompiled.FilterForEventType, null, true); var validationContext = new ExprValidationContextBuilder( streamTypes, validationEnv.StatementRawInfo, validationEnv.Services) .WithIsFilterExpression(true) .Build(); ExprNodeUtilityValidate.Validate( ExprNodeOrigin.CONTEXT, Collections.SingletonList(hashItem.Function), validationContext); } } else if (contextSpec is ContextSpecInitiatedTerminated) { var def = (ContextSpecInitiatedTerminated) contextSpec; var startCondition = ValidateRewriteContextCondition( true, nestingLevel, def.StartCondition, eventTypesReferenced, new MatchEventSpec(), new LinkedHashSet<string>(), validationEnv); additionalForgeables.AddAll(startCondition.AdditionalForgeables); var endCondition = ValidateRewriteContextCondition( false, nestingLevel, def.EndCondition, eventTypesReferenced, startCondition.Matches, startCondition.AllTags, validationEnv); additionalForgeables.AddAll(endCondition.AdditionalForgeables); def.StartCondition = startCondition.Condition; def.EndCondition = endCondition.Condition; if (def.DistinctExpressions != null) { if (!(startCondition.Condition is ContextSpecConditionFilter)) { throw new ExprValidationException( "Distinct-expressions require a stream as the initiated-by condition"); } var distinctExpressions = def.DistinctExpressions; if (distinctExpressions.Length == 0) { throw new ExprValidationException("Distinct-expressions have not been provided"); } var filter = (ContextSpecConditionFilter) startCondition.Condition; if (filter.OptionalFilterAsName == null) { throw new ExprValidationException( "Distinct-expressions require that a stream name is assigned to the stream using 'as'"); } var types = new StreamTypeServiceImpl( filter.FilterSpecCompiled.FilterForEventType, filter.OptionalFilterAsName, true); var validationContext = new ExprValidationContextBuilder(types, validationEnv.StatementRawInfo, validationEnv.Services) .WithAllowBindingConsumption(true) .Build(); for (var i = 0; i < distinctExpressions.Length; i++) { ExprNodeUtilityValidate.ValidatePlainExpression( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i]); distinctExpressions[i] = ExprNodeUtilityValidate.GetValidatedSubtree( ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i], validationContext); } var multiKeyPlan = MultiKeyPlanner.PlanMultiKey( distinctExpressions, false, @base.StatementRawInfo, validationEnv.Services.SerdeResolver); def.DistinctMultiKey = multiKeyPlan.ClassRef; additionalForgeables.AddAll(multiKeyPlan.MultiKeyForgeables); } } else if (contextSpec is ContextNested) { var nested = (ContextNested) contextSpec; var level = 0; ISet<string> namesUsed = new HashSet<string>(); namesUsed.Add(validationEnv.ContextName); foreach (var nestedContext in nested.Contexts) { if (namesUsed.Contains(nestedContext.ContextName)) { throw new ExprValidationException( "Context by name '" + nestedContext.ContextName + "' has already been declared within nested context '" + validationEnv.ContextName + "'"); } namesUsed.Add(nestedContext.ContextName); var forgeables = ValidateContextDetail(nestedContext.ContextDetail, level, validationEnv); additionalForgeables.AddAll(forgeables); level++; } } else { throw new IllegalStateException("Unrecognized context detail " + contextSpec); } return additionalForgeables; }
public static StreamSpecCompiledDesc CompilePatternWTags( PatternStreamSpecRaw streamSpecRaw, ISet<string> eventTypeReferences, bool isInsertInto, MatchEventSpec tags, ISet<string> priorAllTags, bool isJoin, bool isContextDeclaration, bool isOnTrigger, int streamNum, StatementRawInfo statementRawInfo, StatementCompileTimeServices services) { // validate if ((streamSpecRaw.IsSuppressSameEventMatches || streamSpecRaw.IsDiscardPartialsOnMatch) && (isJoin || isContextDeclaration || isOnTrigger)) { throw new ExprValidationException( "Discard-partials and suppress-matches is not supported in a joins, context declaration and on-action"); } if (tags == null) { tags = new MatchEventSpec(); } var nodeStack = new Stack<EvalForgeNode>(); // determine ordered tags ISet<string> allTagNamesOrdered = FilterSpecCompilerTagUtil.AssignEventAsTagNumber(priorAllTags, streamSpecRaw.EvalForgeNode); // construct root : assigns factory node ids var top = streamSpecRaw.EvalForgeNode; var root = new EvalRootForgeNode(services.IsAttachPatternText, top, statementRawInfo.Annotations); var additionalForgeables = new List<StmtClassForgeableFactory>(); RecursiveCompile( top, tags, nodeStack, allTagNamesOrdered, streamNum, additionalForgeables, statementRawInfo, services); var hook = (PatternCompileHook) ImportUtil.GetAnnotationHook( statementRawInfo.Annotations, HookType.INTERNAL_PATTERNCOMPILE, typeof(PatternCompileHook), services.ImportServiceCompileTime); hook?.Pattern(root); PatternStreamSpecCompiled compiled = new PatternStreamSpecCompiled( root, tags.TaggedEventTypes, tags.ArrayEventTypes, allTagNamesOrdered, streamSpecRaw.ViewSpecs, streamSpecRaw.OptionalStreamName, streamSpecRaw.Options, streamSpecRaw.IsSuppressSameEventMatches, streamSpecRaw.IsDiscardPartialsOnMatch); return new StreamSpecCompiledDesc(compiled, additionalForgeables); }