Пример #1
0
        private Pair<FilterSpecCompiled, IList<StmtClassForgeableFactory>> CompilePartitionedFilterSpec(
            FilterSpecRaw filterSpecRaw,
            ISet<string> eventTypesReferenced,
            CreateContextValidationEnv validationEnv)
        {
            ValidateNotTable(filterSpecRaw.EventTypeName, validationEnv.Services);
            var raw = new FilterStreamSpecRaw(
                filterSpecRaw,
                ViewSpec.EMPTY_VIEWSPEC_ARRAY,
                null,
                StreamSpecOptions.DEFAULT);
            var compiledDesc = StreamSpecCompiler.Compile(
                raw,
                eventTypesReferenced,
                false,
                false,
                true,
                false,
                null,
                0,
                validationEnv.StatementRawInfo,
                validationEnv.Services);
            if (!(compiledDesc.StreamSpecCompiled is FilterStreamSpecCompiled filters)) {
                throw new ExprValidationException("Partition criteria may not include named windows");
            }

            var spec = filters.FilterSpecCompiled;
            validationEnv.FilterSpecCompileds.Add(spec);
            return new Pair<FilterSpecCompiled, IList<StmtClassForgeableFactory>>(
                spec,
                compiledDesc.AdditionalForgeables);
        }
Пример #2
0
 public static void WalkStreamSpecs(StatementSpecRaw spec, ExprNodeSubselectDeclaredDotVisitor visitor)
 {
     // Determine filter streams
     foreach (StreamSpecRaw rawSpec in spec.StreamSpecs)
     {
         if (rawSpec is FilterStreamSpecRaw)
         {
             FilterStreamSpecRaw raw = (FilterStreamSpecRaw)rawSpec;
             foreach (ExprNode filterExpr in raw.RawFilterSpec.FilterExpressions)
             {
                 filterExpr.Accept(visitor);
             }
         }
         if (rawSpec is PatternStreamSpecRaw)
         {
             PatternStreamSpecRaw   patternStreamSpecRaw = (PatternStreamSpecRaw)rawSpec;
             EvalNodeAnalysisResult analysisResult       = EvalNodeUtil.RecursiveAnalyzeChildNodes(patternStreamSpecRaw.EvalFactoryNode);
             foreach (EvalFactoryNode evalNode in analysisResult.ActiveNodes)
             {
                 if (evalNode is EvalFilterFactoryNode)
                 {
                     EvalFilterFactoryNode filterNode = (EvalFilterFactoryNode)evalNode;
                     foreach (ExprNode filterExpr in filterNode.RawFilterSpec.FilterExpressions)
                     {
                         filterExpr.Accept(visitor);
                     }
                 }
             }
         }
     }
 }
Пример #3
0
        private FilterSpecCompiled CompilePartitonedFilterSpec(
            FilterSpecRaw filterSpecRaw,
            ISet<string> eventTypesReferenced,
            CreateContextValidationEnv validationEnv)
        {
            ValidateNotTable(filterSpecRaw.EventTypeName, validationEnv.Services);
            var raw = new FilterStreamSpecRaw(
                filterSpecRaw,
                ViewSpec.EMPTY_VIEWSPEC_ARRAY,
                null,
                StreamSpecOptions.DEFAULT);
            var compiled = StreamSpecCompiler.Compile(
                raw,
                eventTypesReferenced,
                false,
                false,
                true,
                false,
                null,
                0,
                validationEnv.StatementRawInfo,
                validationEnv.Services);
            if (!(compiled is FilterStreamSpecCompiled)) {
                throw new ExprValidationException("Partition criteria may not include named windows");
            }

            var filters = (FilterStreamSpecCompiled) compiled;
            var spec = filters.FilterSpecCompiled;
            validationEnv.FilterSpecCompileds.Add(spec);
            return spec;
        }
        public static void WalkStreamSpecs(
            StatementSpecRaw spec,
            ExprNodeSubselectDeclaredDotVisitor visitor)
        {
            // determine pattern-filter subqueries
            foreach (StreamSpecRaw streamSpecRaw in spec.StreamSpecs) {
                if (streamSpecRaw is PatternStreamSpecRaw) {
                    PatternStreamSpecRaw patternStreamSpecRaw = (PatternStreamSpecRaw) streamSpecRaw;
                    EvalNodeAnalysisResult analysisResult =
                        EvalNodeUtil.RecursiveAnalyzeChildNodes(patternStreamSpecRaw.EvalForgeNode);
                    foreach (EvalForgeNode evalNode in analysisResult.ActiveNodes) {
                        if (evalNode is EvalFilterForgeNode) {
                            EvalFilterForgeNode filterNode = (EvalFilterForgeNode) evalNode;
                            foreach (ExprNode filterExpr in filterNode.RawFilterSpec.FilterExpressions) {
                                filterExpr.Accept(visitor);
                            }
                        }
                        else if (evalNode is EvalObserverForgeNode) {
                            int beforeCount = visitor.Subselects.Count;
                            EvalObserverForgeNode observerNode = (EvalObserverForgeNode) evalNode;
                            foreach (ExprNode param in observerNode.PatternObserverSpec.ObjectParameters) {
                                param.Accept(visitor);
                            }

                            if (visitor.Subselects.Count != beforeCount) {
                                throw new ExprValidationException(
                                    "Subselects are not allowed within pattern observer parameters, please consider using a variable instead");
                            }
                        }
                    }
                }
            }

            // determine filter streams
            foreach (StreamSpecRaw rawSpec in spec.StreamSpecs) {
                if (rawSpec is FilterStreamSpecRaw) {
                    FilterStreamSpecRaw raw = (FilterStreamSpecRaw) rawSpec;
                    foreach (ExprNode filterExpr in raw.RawFilterSpec.FilterExpressions) {
                        filterExpr.Accept(visitor);
                    }
                }
            }
        }
Пример #5
0
        private void ValidateContextDetail(
            EPServicesContext servicesContext,
            StatementContext statementContext,
            ISet <string> eventTypesReferenced,
            ContextDetail contextDetail,
            AgentInstanceContext agentInstanceContext)
        {
            if (contextDetail is ContextDetailPartitioned)
            {
                var segmented = (ContextDetailPartitioned)contextDetail;
                foreach (var partition in segmented.Items)
                {
                    ValidateNotTable(servicesContext, partition.FilterSpecRaw.EventTypeName);
                    var raw      = new FilterStreamSpecRaw(partition.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, new StreamSpecOptions());
                    var compiled = raw.Compile(statementContext, eventTypesReferenced, false, Collections.GetEmptyList <int>(), false, true, false, null);
                    if (!(compiled is FilterStreamSpecCompiled))
                    {
                        throw new ExprValidationException("Partition criteria may not include named windows");
                    }
                    var result = (FilterStreamSpecCompiled)compiled;
                    partition.FilterSpecCompiled = result.FilterSpec;
                }
            }
            else if (contextDetail is ContextDetailCategory)
            {
                // compile filter
                var category = (ContextDetailCategory)contextDetail;
                ValidateNotTable(servicesContext, category.FilterSpecRaw.EventTypeName);
                var raw    = new FilterStreamSpecRaw(category.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, new StreamSpecOptions());
                var result = (FilterStreamSpecCompiled)raw.Compile(statementContext, eventTypesReferenced, false, Collections.GetEmptyList <int>(), false, true, false, null);
                category.FilterSpecCompiled = result.FilterSpec;
                servicesContext.StatementEventTypeRefService.AddReferences(statementContext.StatementName, CollectionUtil.ToArray(eventTypesReferenced));

                // compile expressions
                foreach (var item in category.Items)
                {
                    ValidateNotTable(servicesContext, category.FilterSpecRaw.EventTypeName);
                    var filterSpecRaw = new FilterSpecRaw(category.FilterSpecRaw.EventTypeName, Collections.SingletonList(item.Expression), null);
                    var rawExpr       = new FilterStreamSpecRaw(filterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, new StreamSpecOptions());
                    var compiled      = (FilterStreamSpecCompiled)rawExpr.Compile(statementContext, eventTypesReferenced, false, Collections.GetEmptyList <int>(), false, true, false, null);
                    item.SetCompiledFilter(compiled.FilterSpec, agentInstanceContext);
                }
            }
            else if (contextDetail is ContextDetailHash)
            {
                var hashed = (ContextDetailHash)contextDetail;
                foreach (var hashItem in hashed.Items)
                {
                    var raw = new FilterStreamSpecRaw(hashItem.FilterSpecRaw, ViewSpec.EMPTY_VIEWSPEC_ARRAY, null, new StreamSpecOptions());
                    ValidateNotTable(servicesContext, hashItem.FilterSpecRaw.EventTypeName);
                    var result = (FilterStreamSpecCompiled)raw.Compile(statementContext, eventTypesReferenced, false, Collections.GetEmptyList <int>(), false, true, false, null);
                    hashItem.FilterSpecCompiled = result.FilterSpec;

                    // validate parameters
                    var streamTypes       = new StreamTypeServiceImpl(result.FilterSpec.FilterForEventType, null, true, statementContext.EngineURI);
                    var validationContext = new ExprValidationContext(
                        streamTypes,
                        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.Validate(ExprNodeOrigin.CONTEXT, Collections.SingletonList(hashItem.Function), validationContext);
                }
            }
            else if (contextDetail is ContextDetailInitiatedTerminated)
            {
                var def            = (ContextDetailInitiatedTerminated)contextDetail;
                var startCondition = ValidateRewriteContextCondition(servicesContext, statementContext, def.Start, eventTypesReferenced, new MatchEventSpec(), new LinkedHashSet <string>());
                var endCondition   = ValidateRewriteContextCondition(servicesContext, statementContext, def.End, eventTypesReferenced, startCondition.Matches, startCondition.AllTags);
                def.Start = startCondition.Condition;
                def.End   = endCondition.Condition;

                if (def.DistinctExpressions != null)
                {
                    if (!(startCondition.Condition is ContextDetailConditionFilter))
                    {
                        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 = (ContextDetailConditionFilter)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, servicesContext.EngineURI);
                    var validationContext = new ExprValidationContext(
                        types,
                        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, true, false,
                        null, false);
                    for (var i = 0; i < distinctExpressions.Length; i++)
                    {
                        ExprNodeUtility.ValidatePlainExpression(ExprNodeOrigin.CONTEXTDISTINCT, ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(distinctExpressions[i]), distinctExpressions[i]);
                        distinctExpressions[i] = ExprNodeUtility.GetValidatedSubtree(ExprNodeOrigin.CONTEXTDISTINCT, distinctExpressions[i], validationContext);
                    }
                }
            }
            else if (contextDetail is ContextDetailNested)
            {
                var nested = (ContextDetailNested)contextDetail;
                foreach (var nestedContext in nested.Contexts)
                {
                    ValidateContextDetail(servicesContext, statementContext, eventTypesReferenced, nestedContext.ContextDetail, agentInstanceContext);
                }
            }
            else
            {
                throw new IllegalStateException("Unrecognized context detail " + contextDetail);
            }
        }
Пример #6
0
        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);
            }
        }
Пример #7
0
        public static StreamSpecCompiled CompileFilter(
            FilterStreamSpecRaw streamSpec,
            bool isInsertInto,
            bool isJoin,
            bool isContextDeclaration,
            bool isOnTrigger,
            string optionalStreamName,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices services)
        {
            // Determine the event type
            var rawFilterSpec = streamSpec.RawFilterSpec;
            var eventTypeName = rawFilterSpec.EventTypeName;

            var table = services.TableCompileTimeResolver.Resolve(eventTypeName);
            if (table != null) {
                if (streamSpec.ViewSpecs != null && streamSpec.ViewSpecs.Length > 0) {
                    throw new ExprValidationException("Views are not supported with tables");
                }

                if (streamSpec.RawFilterSpec.OptionalPropertyEvalSpec != null) {
                    throw new ExprValidationException("Contained-event expressions are not supported with tables");
                }

                StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                    new[] {table.InternalEventType},
                    new[] {optionalStreamName},
                    new[] {true},
                    false,
                    false);
                var validatedNodes = FilterSpecCompiler.ValidateAllowSubquery(
                    ExprNodeOrigin.FILTER,
                    rawFilterSpec.FilterExpressions,
                    streamTypeService,
                    null,
                    null,
                    statementRawInfo,
                    services);
                return new TableQueryStreamSpec(
                    streamSpec.OptionalStreamName,
                    streamSpec.ViewSpecs,
                    streamSpec.Options,
                    table,
                    validatedNodes);
            }

            // Could be a named window
            var namedWindowInfo = services.NamedWindowCompileTimeResolver.Resolve(eventTypeName);
            if (namedWindowInfo != null) {
                StreamTypeService streamTypeService = new StreamTypeServiceImpl(
                    new[] {namedWindowInfo.EventType},
                    new[] {optionalStreamName},
                    new[] {true},
                    false,
                    false);

                var validatedNodes = FilterSpecCompiler.ValidateAllowSubquery(
                    ExprNodeOrigin.FILTER,
                    rawFilterSpec.FilterExpressions,
                    streamTypeService,
                    null,
                    null,
                    statementRawInfo,
                    services);

                PropertyEvaluatorForge optionalPropertyEvaluator = null;
                if (rawFilterSpec.OptionalPropertyEvalSpec != null) {
                    optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator(
                        rawFilterSpec.OptionalPropertyEvalSpec,
                        namedWindowInfo.EventType,
                        streamSpec.OptionalStreamName,
                        statementRawInfo,
                        services);
                }

                return new NamedWindowConsumerStreamSpec(
                    namedWindowInfo,
                    streamSpec.OptionalStreamName,
                    streamSpec.ViewSpecs,
                    validatedNodes,
                    streamSpec.Options,
                    optionalPropertyEvaluator);
            }

            var eventType = ResolveTypeName(eventTypeName, services.EventTypeCompileTimeResolver);

            // Validate all nodes, make sure each returns a boolean and types are good;
            // Also decompose all AND super nodes into individual expressions
            StreamTypeService streamTypeServiceX = new StreamTypeServiceImpl(
                new[] {eventType},
                new[] {streamSpec.OptionalStreamName},
                new[] {true},
                false,
                false);

            var spec = FilterSpecCompiler.MakeFilterSpec(
                eventType,
                eventTypeName,
                rawFilterSpec.FilterExpressions,
                rawFilterSpec.OptionalPropertyEvalSpec,
                null,
                null, // no tags
                streamTypeServiceX,
                streamSpec.OptionalStreamName,
                statementRawInfo,
                services);

            return new FilterStreamSpecCompiled(
                spec,
                streamSpec.ViewSpecs,
                streamSpec.OptionalStreamName,
                streamSpec.Options);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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;
        }