public void SetGuardParameters(
            IList<ExprNode> parameters,
            MatchedEventConvertorForge convertor,
            StatementCompileTimeServices services)
        {
            var message = "Timer-within-or-max-count guard requires two parameters: " +
                          "numeric or time period parameter and an integer-value expression parameter";

            if (parameters.Count != 2) {
                throw new GuardParameterException(message);
            }

            if (!parameters[0].Forge.EvaluationType.IsNumeric()) {
                throw new GuardParameterException(message);
            }

            var paramOneType = parameters[1].Forge.EvaluationType;
            if (paramOneType != typeof(int) && paramOneType != typeof(int)) {
                throw new GuardParameterException(message);
            }

            timeExpr = parameters[0];
            numCountToExpr = parameters[1];
            this.convertor = convertor;
            timeAbacus = services.ImportServiceCompileTime.TimeAbacus;
        }
 public FilterForEvalLimitedExprForge(
     ExprNode value,
     MatchedEventConvertorForge convertor,
     Coercer numberCoercer)
 {
     this.value = value;
     this.convertor = convertor;
     this.numberCoercer = numberCoercer;
 }
예제 #3
0
 public FilterSpecPlanForge(
     FilterSpecPlanPathForge[] paths,
     ExprNode filterConfirm,
     ExprNode filterNegate,
     MatchedEventConvertorForge convertorForge)
 {
     Paths = paths;
     FilterConfirm = filterConfirm;
     FilterNegate = filterNegate;
     ConvertorForge = convertorForge;
 }
예제 #4
0
 public FilterSpecParamValueLimitedExprForge(
     ExprFilterSpecLookupableForge lookupable,
     FilterOperator filterOperator,
     ExprNode value,
     MatchedEventConvertorForge convertor,
     Coercer numberCoercer)
     : base(lookupable, filterOperator)
 {
     this._value         = value;
     this._convertor     = convertor;
     this._numberCoercer = numberCoercer;
 }
예제 #5
0
 public static FilterSpecPlanForge MakePlanFromTriplets(
     ICollection<FilterSpecPlanPathTripletForge> triplets,
     ExprNode topLevelNegation,
     FilterSpecCompilerArgs args)
 {
     var path = MakePathFromTriplets(triplets, null);
     var convertor = new MatchedEventConvertorForge(
         args.taggedEventTypes,
         args.arrayEventTypes,
         args.allTagNamesOrdered,
         null,
         true);
     return new FilterSpecPlanForge(new[] {path}, null, topLevelNegation, convertor);
 }
예제 #6
0
        public void SetObserverParameters(
            IList<ExprNode> observerParameters,
            MatchedEventConvertorForge convertor,
            ExprValidationContext validationContext)
        {
            var message = "File exists observer takes a single string filename parameter";
            if (observerParameters.Count != 1) {
                throw new ObserverParameterException(message);
            }

            if (!(observerParameters[0].Forge.EvaluationType == typeof(string))) {
                throw new ObserverParameterException(message);
            }

            filenameExpression = observerParameters[0];
            this.convertor = convertor;
        }
예제 #7
0
        public void SetGuardParameters(
            IList<ExprNode> guardParameters,
            MatchedEventConvertorForge convertor,
            StatementCompileTimeServices services)
        {
            var message = "Count-to guard takes a single integer-value expression as parameter";
            if (guardParameters.Count != 1) {
                throw new GuardParameterException(message);
            }

            var paramType = guardParameters[0].Forge.EvaluationType;
            if (paramType != typeof(int?) && paramType != typeof(int)) {
                throw new GuardParameterException(message);
            }

            numCountToExpr = guardParameters[0];
            this.convertor = convertor;
        }
예제 #8
0
        public void SetGuardParameters(
            IList<ExprNode> parameters,
            MatchedEventConvertorForge convertor,
            StatementCompileTimeServices services)
        {
            var errorMessage = "Timer-within guard requires a single numeric or time period parameter";
            if (parameters.Count != 1) {
                throw new GuardParameterException(errorMessage);
            }

            if (!parameters[0].Forge.EvaluationType.IsNumeric()) {
                throw new GuardParameterException(errorMessage);
            }

            this.convertor = convertor;
            timeExpr = parameters[0];
            timeAbacus = services.ImportServiceCompileTime.TimeAbacus;
        }
예제 #9
0
        public void SetGuardParameters(
            IList<ExprNode> parameters,
            MatchedEventConvertorForge convertor,
            StatementCompileTimeServices services)
        {
            var errorMessage =
                "Expression pattern guard requires a single expression as a parameter returning a true or false (boolean) value";
            if (parameters.Count != 1) {
                throw new GuardParameterException(errorMessage);
            }

            expression = parameters[0];

            if (parameters[0].Forge.EvaluationType.GetBoxedType() != typeof(bool?)) {
                throw new GuardParameterException(errorMessage);
            }

            this.convertor = convertor;
        }
예제 #10
0
        public void SetObserverParameters(
            IList<ExprNode> parameters,
            MatchedEventConvertorForge convertor,
            ExprValidationContext validationContext)
        {
            ObserverParameterUtil.ValidateNoNamedParameters(NAME, parameters);
            var errorMessage = NAME + " requires a single numeric or time period parameter";
            if (parameters.Count != 1) {
                throw new ObserverParameterException(errorMessage);
            }

            if (!(parameters[0] is ExprTimePeriod)) {
                var returnType = parameters[0].Forge.EvaluationType;
                if (!returnType.IsNumeric()) {
                    throw new ObserverParameterException(errorMessage);
                }
            }

            parameter = parameters[0];
            this.convertor = convertor;
            timeAbacus = validationContext.ImportService.TimeAbacus;
        }
예제 #11
0
        public void SetObserverParameters(
            IList<ExprNode> parameters,
            MatchedEventConvertorForge convertor,
            ExprValidationContext validationContext)
        {
            ObserverParameterUtil.ValidateNoNamedParameters("timer:at", parameters);
            if (Log.IsDebugEnabled) {
                Log.Debug(".setObserverParameters " + parameters);
            }

            if (parameters.Count < 5 || parameters.Count > 9) {
                throw new ObserverParameterException("Invalid number of parameters for timer:at");
            }

            this.parameters = parameters;
            this.convertor = convertor;

            // if all parameters are constants, lets try to evaluate and build a schedule for early validation
            var allConstantResult = true;
            foreach (var param in parameters) {
                if (!(param is ExprWildcard) && !param.Forge.ForgeConstantType.IsCompileTimeConstant) {
                    allConstantResult = false;
                }
            }

            if (allConstantResult) {
                try {
                    var observerParameters = EvaluateCompileTime(parameters);
                    spec = ScheduleSpecUtil.ComputeValues(observerParameters.ToArray());
                }
                catch (ScheduleParameterException e) {
                    throw new ObserverParameterException(
                        "Error computing crontab schedule specification: " + e.Message,
                        e);
                }
            }
        }
        private static FilterSpecParamFilterForEvalForge HandleRangeNodeEndpoint(
            ExprNode endpoint,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            string statementName,
            StatementRawInfo raw,
            StatementCompileTimeServices services)
        {
            // constant
            if (endpoint.Forge.ForgeConstantType.IsCompileTimeConstant) {
                var value = endpoint.Forge.ExprEvaluator.Evaluate(null, true, null);
                if (value == null) {
                    return null;
                }

                if (value is string) {
                    return new FilterForEvalConstantStringForge((string) value);
                }

                return new FilterForEvalConstantDoubleForge(value.AsDouble());
            }

            if (endpoint is ExprContextPropertyNode) {
                var node = (ExprContextPropertyNode) endpoint;
                if (node.Type == typeof(string)) {
                    return new FilterForEvalContextPropStringForge(node.Getter, node.PropertyName);
                }

                return new FilterForEvalContextPropDoubleForge(node.Getter, node.PropertyName);
            }

            if (endpoint.Forge.ForgeConstantType.IsDeployTimeTimeConstant && endpoint is ExprNodeDeployTimeConst) {
                var node = (ExprNodeDeployTimeConst) endpoint;
                if (endpoint.Forge.EvaluationType == typeof(string)) {
                    return new FilterForEvalDeployTimeConstStringForge(node);
                }

                return new FilterForEvalDeployTimeConstDoubleForge(node);
            }

            // or property
            if (endpoint is ExprIdentNode) {
                return GetIdentNodeDoubleEval((ExprIdentNode) endpoint, arrayEventTypes, statementName);
            }

            // or limited expression
            if (FilterSpecCompilerIndexPlannerHelper.HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.VALUECOMPOSITE, raw, services) &&
                IsLimitedValueExpression(endpoint)) {
                var returnType = endpoint.Forge.EvaluationType;
                MatchedEventConvertorForge convertor = GetMatchEventConvertor(endpoint, taggedEventTypes, arrayEventTypes, allTagNamesOrdered);
                if (returnType == typeof(string)) {
                    return new FilterForEvalLimitedExprForge(endpoint, convertor, null);
                }

                var coercer = SimpleNumberCoercerFactory.GetCoercer(returnType, typeof(double?));
                return new FilterForEvalLimitedExprForge(endpoint, convertor, coercer);
            }

            return null;
        }
예제 #13
0
        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);
            }
        }
예제 #14
0
        public void SetObserverParameters(
            IList<ExprNode> parameters,
            MatchedEventConvertorForge convertor,
            ExprValidationContext validationContext)
        {
            this.convertor = convertor;

            // obtains name parameters
            IDictionary<string, ExprNamedParameterNode> namedExpressions;
            try {
                namedExpressions = ExprNodeUtilityValidate.GetNamedExpressionsHandleDups(parameters);
                ExprNodeUtilityValidate.ValidateNamed(namedExpressions, NAMED_PARAMETERS);
            }
            catch (ExprValidationException e) {
                throw new ObserverParameterException(e.Message, e);
            }

            var isoStringExpr = namedExpressions.Get(ISO_NAME);
            if (namedExpressions.Count == 1 && isoStringExpr != null) {
                try {
                    allConstantResult = ExprNodeUtilityValidate.ValidateNamedExpectType(
                        isoStringExpr,
                        new[] {typeof(string)});
                }
                catch (ExprValidationException ex) {
                    throw new ObserverParameterException(ex.Message, ex);
                }

                scheduleComputer = new TimerScheduleSpecComputeISOStringForge(isoStringExpr.ChildNodes[0]);
            }
            else if (isoStringExpr != null) {
                throw new ObserverParameterException(
                    "The '" + ISO_NAME + "' parameter is exclusive of other parameters");
            }
            else if (namedExpressions.Count == 0) {
                throw new ObserverParameterException("No parameters provided");
            }
            else {
                allConstantResult = true;
                var dateNamedNode = namedExpressions.Get(DATE_NAME);
                var repetitionsNamedNode = namedExpressions.Get(REPETITIONS_NAME);
                var periodNamedNode = namedExpressions.Get(PERIOD_NAME);
                if (dateNamedNode == null && periodNamedNode == null) {
                    throw new ObserverParameterException("Either the date or period parameter is required");
                }

                try {
                    if (dateNamedNode != null) {
                        allConstantResult = ExprNodeUtilityValidate.ValidateNamedExpectType(
                            dateNamedNode,
                            new[] {
                                typeof(string),
                                typeof(DateTimeEx),
                                typeof(DateTimeOffset),
                                typeof(DateTime),
                                typeof(long)
                            });
                    }

                    if (repetitionsNamedNode != null) {
                        allConstantResult &= ExprNodeUtilityValidate.ValidateNamedExpectType(
                            repetitionsNamedNode,
                            new[] {typeof(int), typeof(long)});
                    }

                    if (periodNamedNode != null) {
                        allConstantResult &= ExprNodeUtilityValidate.ValidateNamedExpectType(
                            periodNamedNode,
                            new[] {typeof(TimePeriod)});
                    }
                }
                catch (ExprValidationException ex) {
                    throw new ObserverParameterException(ex.Message, ex);
                }

                var dateNode = dateNamedNode == null ? null : dateNamedNode.ChildNodes[0];
                var repetitionsNode = repetitionsNamedNode == null ? null : repetitionsNamedNode.ChildNodes[0];
                var periodNode = periodNamedNode == null ? null : (ExprTimePeriod) periodNamedNode.ChildNodes[0];
                scheduleComputer = new TimerScheduleSpecComputeFromExprForge(dateNode, repetitionsNode, periodNode);
            }

            if (allConstantResult) {
                try {
                    scheduleComputer.VerifyComputeAllConst(validationContext);
                }
                catch (ScheduleParameterException ex) {
                    throw new ObserverParameterException(ex.Message, ex);
                }
            }
        }
        internal static FilterSpecPlanForge PlanRemainingNodesWithConditions(
            FilterSpecParaForgeMap overallExpressions,
            FilterSpecCompilerArgs args,
            int filterServiceMaxFilterWidth,
            ExprNode topLevelNegator)
        {
            var unassigned = overallExpressions.UnassignedExpressions;
            var orNodes    = new List <ExprOrNode>(unassigned.Count);

            foreach (var node in unassigned)
            {
                if (node is ExprOrNode)
                {
                    orNodes.Add((ExprOrNode)node);
                }
            }

            var expressionsWithoutOr = new FilterSpecParaForgeMap();

            expressionsWithoutOr.Add(overallExpressions);

            // first dimension: or-node index
            // second dimension: or child node index
            var countOr        = 0;
            var sizeFactorized = 1;
            var sizePerOr      = new int[orNodes.Count];
            var orChildNodes   = new OrChildNode[orNodes.Count][];
            var hasControl     = false;

            foreach (var orNode in orNodes)
            {
                expressionsWithoutOr.RemoveNode(orNode);

                // get value-nodes and non-value nodes
                var nonValueNodes = GetNonValueChildNodes(orNode);
                var valueNodes    = new List <ExprNode>(Arrays.AsList(orNode.ChildNodes));
                valueNodes.RemoveAll(nonValueNodes);
                ExprNode singleValueNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalOrWhenNeeded(valueNodes);

                // get all child nodes; last one is confirm if present
                IList <ExprNode> allChildNodes = new List <ExprNode>(nonValueNodes);
                if (singleValueNode != null)
                {
                    allChildNodes.Add(singleValueNode);
                }

                var len = allChildNodes.Count;
                orChildNodes[countOr] = new OrChildNode[len];

                for (var i = 0; i < len; i++)
                {
                    var child = allChildNodes[i];
                    if (child == singleValueNode)
                    {
                        hasControl = true;
                        orChildNodes[countOr][i] = new OrChildNodeV(singleValueNode);
                    }
                    else
                    {
                        var map     = new FilterSpecParaForgeMap();
                        var nodes   = Collections.SingletonList(child);
                        var confirm = DecomposePopulateConsolidate(map, true, nodes, args);
                        if (confirm == null)
                        {
                            orChildNodes[countOr][i] = new OrChildNodeNV(child, map);
                        }
                        else
                        {
                            hasControl = true;
                            orChildNodes[countOr][i] = new OrChildNodeNVNegated(child, map, confirm);
                        }
                    }
                }

                sizePerOr[countOr] = len;
                sizeFactorized     = sizeFactorized * len;
                countOr++;
            }

            // compute permutations
            var permutations           = new CombPermutationTriplets[sizeFactorized];
            var combinationEnumeration = CombinationEnumeration.FromZeroBasedRanges(sizePerOr);
            var count = 0;

            foreach (var permutation in combinationEnumeration)
            {
                permutations[count] = ComputePermutation(expressionsWithoutOr, permutation, orChildNodes, hasControl, args);
                count++;
            }

            // Remove any permutations that only have a control-confirm
            var result             = new List <FilterSpecPlanPathForge>(sizeFactorized);
            var pathControlConfirm = new List <ExprNode>();

            foreach (var permutation in permutations)
            {
                if (permutation.Triplets.Length > 0)
                {
                    result.Add(new FilterSpecPlanPathForge(permutation.Triplets, permutation.NegateCondition));
                }
                else
                {
                    pathControlConfirm.Add(permutation.NegateCondition);
                }
            }

            if (result.Count > filterServiceMaxFilterWidth)
            {
                return(null);
            }

            var      pathArray         = result.ToArray();
            ExprNode topLevelConfirmer = ExprNodeUtilityMake.ConnectExpressionsByLogicalOrWhenNeeded(pathControlConfirm);

            // determine when the path-negate condition is the same as the root confirm-expression
            if (topLevelConfirmer != null)
            {
                var not = new ExprNotNode();
                not.AddChildNode(topLevelConfirmer);
                foreach (var path in pathArray)
                {
                    if (ExprNodeUtilityCompare.DeepEquals(not, path.PathNegate, true))
                    {
                        path.PathNegate = null;
                    }
                }
            }

            var convertor = new MatchedEventConvertorForge(
                args.taggedEventTypes,
                args.arrayEventTypes,
                args.allTagNamesOrdered,
                null,
                true);

            return(new FilterSpecPlanForge(pathArray, topLevelConfirmer, topLevelNegator, convertor));
        }