Exemple #1
0
        private static IList<FilterSpecParamForge> ComputePermutation(
            FilterSpecParaForgeMap filterParamExprMap,
            object[] permutation,
            FilterSpecParaForgeMap[][] orNodesMaps,
            FilterSpecCompilerArgs args)
        {
            FilterSpecParaForgeMap mapAll = new FilterSpecParaForgeMap();
            mapAll.Add(filterParamExprMap);

            // combine
            for (int orNodeNum = 0; orNodeNum < permutation.Length; orNodeNum++) {
                int orChildNodeNum = (int) permutation[orNodeNum];
                FilterSpecParaForgeMap mapOrSub = orNodesMaps[orNodeNum][orChildNodeNum];
                mapAll.Add(mapOrSub);
            }

            // consolidate across
            FilterSpecCompilerConsolidateUtil.Consolidate(mapAll, args.statementRawInfo.StatementName);

            IList<FilterSpecParamForge> filterParams = new List<FilterSpecParamForge>();
            filterParams.AddAll(mapAll.FilterParams);
            int countUnassigned = mapAll.CountUnassignedExpressions();

            if (countUnassigned == 0) {
                return filterParams;
            }

            FilterSpecParamForge node = MakeRemainingNode(mapAll.UnassignedExpressions, args);
            filterParams.Add(node);
            return filterParams;
        }
Exemple #2
0
        private static FilterSpecParamForge MakeBooleanExprParam(
            ExprNode exprNode,
            FilterSpecCompilerArgs args)
        {
            bool hasSubselectFilterStream = DetermineSubselectFilterStream(exprNode);
            bool hasTableAccess = DetermineTableAccessFilterStream(exprNode);

            ExprNodeVariableVisitor visitor =
                new ExprNodeVariableVisitor(args.compileTimeServices.VariableCompileTimeResolver);
            exprNode.Accept(visitor);
            bool hasVariable = visitor.IsVariables;

            ExprFilterSpecLookupableForge lookupable = new ExprFilterSpecLookupableForge(
                PROPERTY_NAME_BOOLEAN_EXPRESSION,
                null,
                exprNode.Forge.EvaluationType,
                false);

            return new FilterSpecParamExprNodeForge(
                lookupable,
                FilterOperator.BOOLEAN_EXPRESSION,
                exprNode,
                args.taggedEventTypes,
                args.arrayEventTypes,
                args.streamTypeService,
                hasSubselectFilterStream,
                hasTableAccess,
                hasVariable,
                args.compileTimeServices);
        }
        private static FilterSpecPlanPathForge ComputePermutation(
            FilterSpecParaForgeMap filterParamExprMap,
            object[] permutation,
            FilterSpecParaForgeMap[][] orNodesMaps,
            FilterSpecCompilerArgs args)
        {
            var mapAll = new FilterSpecParaForgeMap();
            mapAll.Add(filterParamExprMap);

            // combine
            for (var orNodeNum = 0; orNodeNum < permutation.Length; orNodeNum++) {
                var orChildNodeNum = permutation[orNodeNum].AsInt32();
                var mapOrSub = orNodesMaps[orNodeNum][orChildNodeNum];
                mapAll.Add(mapOrSub);
            }

            // consolidate across
            FilterSpecCompilerConsolidateUtil.Consolidate(mapAll, args.statementRawInfo.StatementName);

            IList<FilterSpecPlanPathTripletForge> filterParams = new List<FilterSpecPlanPathTripletForge>(mapAll.Triplets);
            var countUnassigned = mapAll.CountUnassignedExpressions();

            if (countUnassigned != 0) {
                FilterSpecPlanPathTripletForge node = MakeRemainingNode(mapAll.UnassignedExpressions, args);
                filterParams.Add(node);
            }

            FilterSpecPlanPathTripletForge[] triplets = filterParams.ToArray();
            return new FilterSpecPlanPathForge(triplets, null);
        }
Exemple #4
0
 public static FilterSpecPlanForge PlanFilterParameters(
     IList<ExprNode> validatedNodes,
     FilterSpecCompilerArgs args)
 {
     var plan = PlanFilterParametersInternal(validatedNodes, args);
     PromoteControlConfirmSinglePathSingleTriplet(plan);
     return plan;
 }
Exemple #5
0
        private static FilterSpecPlanForge PlanFilterParametersInternal(
            IList<ExprNode> validatedNodes,
            FilterSpecCompilerArgs args)
        {
            if (validatedNodes.IsEmpty()) {
                return EMPTY;
            }

            if (args.compileTimeServices.Configuration.Compiler.Execution.FilterIndexPlanning == ConfigurationCompilerExecution.FilterIndexPlanningEnum.NONE) {
                DecomposeCheckAggregation(validatedNodes);
                return BuildNoPlan(validatedNodes, args);
            }

            var performConditionPlanning = HasLevelOrHint(FilterSpecCompilerIndexPlannerHint.CONDITIONS, args.statementRawInfo, args.compileTimeServices);
            var filterParamExprMap = new FilterSpecParaForgeMap();

            // Make filter parameter for each expression node, if it can be optimized.
            // Optionally receive a top-level control condition that negates
            var topLevelNegation = DecomposePopulateConsolidate(filterParamExprMap, performConditionPlanning, validatedNodes, args);

            // Use all filter parameter and unassigned expressions
            var countUnassigned = filterParamExprMap.CountUnassignedExpressions();

            // we are done if there are no remaining nodes
            if (countUnassigned == 0) {
                return MakePlanFromTriplets(filterParamExprMap.Triplets, topLevelNegation, args);
            }

            // determine max-width
            var filterServiceMaxFilterWidth = args.compileTimeServices.Configuration.Compiler.Execution.FilterServiceMaxFilterWidth;
            var hint = HintEnum.MAX_FILTER_WIDTH.GetHint(args.statementRawInfo.Annotations);
            if (hint != null) {
                var hintValue = HintEnum.MAX_FILTER_WIDTH.GetHintAssignedValue(hint);
                filterServiceMaxFilterWidth = int.Parse(hintValue);
            }

            FilterSpecPlanForge plan = null;
            if (filterServiceMaxFilterWidth > 0) {
                if (performConditionPlanning) {
                    plan = PlanRemainingNodesWithConditions(filterParamExprMap, args, filterServiceMaxFilterWidth, topLevelNegation);
                }
                else {
                    plan = PlanRemainingNodesBasic(filterParamExprMap, args, filterServiceMaxFilterWidth);
                }
            }

            if (plan != null) {
                return plan;
            }

            // handle no-plan
            var triplets = new List<FilterSpecPlanPathTripletForge>(filterParamExprMap.Triplets);
            var unassignedExpressions = filterParamExprMap.UnassignedExpressions;
            var triplet = MakeRemainingNode(unassignedExpressions, args);
            triplets.Add(triplet);
            return MakePlanFromTriplets(triplets, topLevelNegation, args);
        }
Exemple #6
0
        private static IList<FilterSpecParamForge>[] PlanRemainingNodesIfFeasible(
            FilterSpecParaForgeMap overallExpressions,
            FilterSpecCompilerArgs args,
            int filterServiceMaxFilterWidth)
        {
            IList<ExprNode> unassigned = overallExpressions.UnassignedExpressions;
            IList<ExprOrNode> orNodes = new List<ExprOrNode>(unassigned.Count);

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

            FilterSpecParaForgeMap expressionsWithoutOr = new FilterSpecParaForgeMap();
            expressionsWithoutOr.Add(overallExpressions);

            // first dimension: or-node index
            // second dimension: or child node index
            FilterSpecParaForgeMap[][] orNodesMaps = new FilterSpecParaForgeMap[orNodes.Count][];
            int countOr = 0;
            int sizeFactorized = 1;
            int[] sizePerOr = new int[orNodes.Count];
            foreach (ExprOrNode orNode in orNodes) {
                expressionsWithoutOr.RemoveNode(orNode);
                orNodesMaps[countOr] = new FilterSpecParaForgeMap[orNode.ChildNodes.Length];
                int len = orNode.ChildNodes.Length;

                for (int i = 0; i < len; i++) {
                    FilterSpecParaForgeMap map = new FilterSpecParaForgeMap();
                    orNodesMaps[countOr][i] = map;
                    IList<ExprNode> nodes = Collections.SingletonList(orNode.ChildNodes[i]);
                    DecomposePopulateConsolidate(map, nodes, args);
                }

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

            // we become too large
            if (sizeFactorized > filterServiceMaxFilterWidth) {
                return null;
            }

            // combine
            IList<FilterSpecParamForge>[] result = new IList<FilterSpecParamForge>[sizeFactorized];
            IEnumerable<object[]> permutations = CombinationEnumeration.FromZeroBasedRanges(sizePerOr);
            int count = 0;
            foreach (var permutation in permutations) {
                result[count] = ComputePermutation(expressionsWithoutOr, permutation, orNodesMaps, args);
                count++;
            }

            return result;
        }
Exemple #7
0
 private static FilterSpecPlanForge BuildNoPlan(
     IList<ExprNode> validatedNodes,
     FilterSpecCompilerArgs args)
 {
     var triplet = MakeRemainingNode(validatedNodes, args);
     FilterSpecPlanPathTripletForge[] triplets = {triplet};
     var path = new FilterSpecPlanPathForge(triplets, null);
     FilterSpecPlanPathForge[] paths = {path};
     return new FilterSpecPlanForge(paths, null, null, null);
 }
        internal static FilterSpecPlanForge PlanRemainingNodesBasic(
            FilterSpecParaForgeMap overallExpressions,
            FilterSpecCompilerArgs args,
            int filterServiceMaxFilterWidth)
        {
            var unassigned = overallExpressions.UnassignedExpressions;
            IList<ExprOrNode> 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 orNodesMaps = new FilterSpecParaForgeMap[orNodes.Count][];
            var countOr = 0;
            var sizeFactorized = 1;
            var sizePerOr = new int[orNodes.Count];
            foreach (var orNode in orNodes) {
                expressionsWithoutOr.RemoveNode(orNode);
                orNodesMaps[countOr] = new FilterSpecParaForgeMap[orNode.ChildNodes.Length];
                var len = orNode.ChildNodes.Length;

                for (var i = 0; i < len; i++) {
                    var map = new FilterSpecParaForgeMap();
                    orNodesMaps[countOr][i] = map;
                    var nodes = Collections.SingletonList(orNode.ChildNodes[i]);
                    DecomposePopulateConsolidate(map, false, nodes, args);
                }

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

            // we become too large
            if (sizeFactorized > filterServiceMaxFilterWidth) {
                return null;
            }

            // combine
            var result = new FilterSpecPlanPathForge[sizeFactorized];
            var count = 0;
            foreach (var permutation in CombinationEnumeration.FromZeroBasedRanges(sizePerOr)) {
                result[count] = ComputePermutation(expressionsWithoutOr, permutation, orNodesMaps, args);
                count++;
            }

            return new FilterSpecPlanForge(result, null, null, null);
        }
Exemple #9
0
        public static FilterSpecCompiled BuildNoStmtCtx(
            IList<ExprNode> validatedNodes,
            EventType eventType,
            string eventTypeName,
            string optionalStreamName,
            PropertyEvalSpec optionalPropertyEvalSpec,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            ISet<string> allTagNamesOrdered,
            StreamTypeService streamTypeService,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices)
        {
            PropertyEvaluatorForge optionalPropertyEvaluator = null;
            if (optionalPropertyEvalSpec != null) {
                optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator(
                    optionalPropertyEvalSpec,
                    eventType,
                    optionalStreamName,
                    statementRawInfo,
                    compileTimeServices);
            }

            // unwind "and" and "or"
            var unwound = FilterSpecCompilerIndexPlannerUnwindAndOr.UnwindAndOr(validatedNodes);

            var args = new FilterSpecCompilerArgs(
                taggedEventTypes,
                arrayEventTypes,
                allTagNamesOrdered,
                streamTypeService,
                null,
                statementRawInfo,
                compileTimeServices);
            var plan = FilterSpecCompilerIndexPlanner.PlanFilterParameters(unwound, args);

            var hook = (FilterSpecCompileHook) ImportUtil.GetAnnotationHook(
                statementRawInfo.Annotations,
                HookType.INTERNAL_FILTERSPEC,
                typeof(FilterSpecCompileHook),
                compileTimeServices.ImportServiceCompileTime);
            hook?.FilterIndexPlan(eventType, unwound, plan);

            if (compileTimeServices.Configuration.Compiler.Logging.IsEnableFilterPlan) {
                LogFilterPlans(unwound, plan, eventType, optionalStreamName, statementRawInfo);
            }

            if (Log.IsDebugEnabled) {
                Log.Debug(".makeFilterSpec spec=" + plan);
            }

            return new FilterSpecCompiled(eventType, eventTypeName, plan, optionalPropertyEvaluator);
        }
Exemple #10
0
 private static ExprAndNode MakeValidateAndNode(
     IList<ExprNode> remainingExprNodes,
     FilterSpecCompilerArgs args)
 {
     var andNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAnd(remainingExprNodes);
     var validationContext = new ExprValidationContextBuilder(args.streamTypeService, args.statementRawInfo, args.compileTimeServices)
         .WithAllowBindingConsumption(true)
         .WithContextDescriptor(args.contextDescriptor)
         .Build();
     andNode.Validate(validationContext);
     return andNode;
 }
Exemple #11
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);
 }
Exemple #12
0
        internal static ExprNode DecomposePopulateConsolidate(
            FilterSpecParaForgeMap filterParamExprMap,
            bool performConditionPlanning,
            IList<ExprNode> validatedNodes,
            FilterSpecCompilerArgs args)
        {
            var constituents = DecomposeCheckAggregation(validatedNodes);

            // Remove constituents that are value-expressions
            ExprNode topLevelControl = null;
            if (performConditionPlanning) {
                IList<ExprNode> valueOnlyConstituents = null;
                foreach (var node in constituents) {
                    var visitor = new FilterSpecExprNodeVisitorValueLimitedExpr();
                    node.Accept(visitor);
                    if (visitor.IsLimited) {
                        if (valueOnlyConstituents == null) {
                            valueOnlyConstituents = new List<ExprNode>();
                        }

                        valueOnlyConstituents.Add(node);
                    }
                }

                if (valueOnlyConstituents != null) {
                    constituents.RemoveAll(valueOnlyConstituents);
                    topLevelControl = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(valueOnlyConstituents);
                }
            }

            // Make filter parameter for each expression node, if it can be optimized
            foreach (var constituent in constituents) {
                var triplet = FilterSpecCompilerIndexPlannerConstituent.MakeFilterParam(
                    constituent,
                    performConditionPlanning,
                    args.taggedEventTypes,
                    args.arrayEventTypes,
                    args.allTagNamesOrdered,
                    args.statementRawInfo.StatementName,
                    args.streamTypeService,
                    args.statementRawInfo,
                    args.compileTimeServices);
                filterParamExprMap.Put(constituent, triplet); // accepts null values as the expression may not be optimized
            }

            // Consolidate entries as possible, i.e. (a != 5 and a != 6) is (a not in (5,6))
            // Removes duplicates for same property and same filter operator for filter service index optimizations
            FilterSpecCompilerConsolidateUtil.Consolidate(filterParamExprMap, args.statementRawInfo.StatementName);
            return topLevelControl;
        }
Exemple #13
0
        public static IList<FilterSpecParamForge>[] PlanFilterParameters(
            IList<ExprNode> validatedNodes,
            FilterSpecCompilerArgs args)
        {
            if (validatedNodes.IsEmpty()) {
                return AllocateListArray(0);
            }

            FilterSpecParaForgeMap filterParamExprMap = new FilterSpecParaForgeMap();

            // Make filter parameter for each expression node, if it can be optimized
            DecomposePopulateConsolidate(filterParamExprMap, validatedNodes, args);

            // Use all filter parameter and unassigned expressions
            IList<FilterSpecParamForge> filterParams = new List<FilterSpecParamForge>();
            filterParams.AddAll(filterParamExprMap.FilterParams);
            int countUnassigned = filterParamExprMap.CountUnassignedExpressions();

            // we are done if there are no remaining nodes
            if (countUnassigned == 0) {
                return AllocateListArraySizeOne(filterParams);
            }

            // determine max-width
            int filterServiceMaxFilterWidth =
                args.compileTimeServices.Configuration.Compiler.Execution.FilterServiceMaxFilterWidth;
            var hint = HintEnum.MAX_FILTER_WIDTH.GetHint(args.statementRawInfo.Annotations);
            if (hint != null) {
                string hintValue = HintEnum.MAX_FILTER_WIDTH.GetHintAssignedValue(hint);
                filterServiceMaxFilterWidth = Int32.Parse(hintValue);
            }

            IList<FilterSpecParamForge>[] plan = null;
            if (filterServiceMaxFilterWidth > 0) {
                plan = PlanRemainingNodesIfFeasible(filterParamExprMap, args, filterServiceMaxFilterWidth);
            }

            if (plan != null) {
                return plan;
            }

            // handle no-plan
            FilterSpecParamForge node = MakeRemainingNode(filterParamExprMap.UnassignedExpressions, args);
            filterParams.Add(node);
            return AllocateListArraySizeOne(filterParams);
        }
Exemple #14
0
        private static FilterSpecParamForge MakeRemainingNode(
            IList<ExprNode> unassignedExpressions,
            FilterSpecCompilerArgs args)
        {
            if (unassignedExpressions.IsEmpty()) {
                throw new ArgumentException();
            }

            // any unoptimized expression nodes are put under one AND
            ExprNode exprNode;
            if (unassignedExpressions.Count == 1) {
                exprNode = unassignedExpressions[0];
            }
            else {
                exprNode = MakeValidateAndNode(unassignedExpressions, args);
            }

            return MakeBooleanExprParam(exprNode, args);
        }
Exemple #15
0
        private static void DecomposePopulateConsolidate(
            FilterSpecParaForgeMap filterParamExprMap,
            IList<ExprNode> validatedNodes,
            FilterSpecCompilerArgs args)
        {
            IList<ExprNode> constituents = DecomposeCheckAggregation(validatedNodes);

            // Make filter parameter for each expression node, if it can be optimized
            foreach (ExprNode constituent in constituents) {
                FilterSpecParamForge param = FilterSpecCompilerMakeParamUtil.MakeFilterParam(
                    constituent,
                    args.arrayEventTypes,
                    args.statementRawInfo.StatementName);
                filterParamExprMap.Put(constituent, param); // accepts null values as the expression may not be optimized
            }

            // Consolidate entries as possible, i.e. (a != 5 and a != 6) is (a not in (5,6))
            // Removes duplicates for same property and same filter operator for filter service index optimizations
            FilterSpecCompilerConsolidateUtil.Consolidate(filterParamExprMap, args.statementRawInfo.StatementName);
        }
Exemple #16
0
        public static FilterSpecCompiled BuildNoStmtCtx(
            IList<ExprNode> validatedNodes,
            EventType eventType,
            string eventTypeName,
            string optionalStreamName,
            PropertyEvalSpec optionalPropertyEvalSpec,
            IDictionary<string, Pair<EventType, string>> taggedEventTypes,
            IDictionary<string, Pair<EventType, string>> arrayEventTypes,
            StreamTypeService streamTypeService,
            StatementRawInfo statementRawInfo,
            StatementCompileTimeServices compileTimeServices
        )
        {
            PropertyEvaluatorForge optionalPropertyEvaluator = null;
            if (optionalPropertyEvalSpec != null) {
                optionalPropertyEvaluator = PropertyEvaluatorForgeFactory.MakeEvaluator(
                    optionalPropertyEvalSpec,
                    eventType,
                    optionalStreamName,
                    statementRawInfo,
                    compileTimeServices);
            }

            var args = new FilterSpecCompilerArgs(
                taggedEventTypes,
                arrayEventTypes,
                streamTypeService,
                null,
                statementRawInfo,
                compileTimeServices);
            IList<FilterSpecParamForge>[] spec = FilterSpecCompilerPlanner.PlanFilterParameters(validatedNodes, args);

            if (Log.IsDebugEnabled) {
                Log.Debug(".makeFilterSpec spec=" + spec);
            }

            return new FilterSpecCompiled(eventType, eventTypeName, spec, optionalPropertyEvaluator);
        }
        private static CombPermutationTriplets ComputePermutation(
            FilterSpecParaForgeMap filterParamExprMap,
            object[] permutation,
            OrChildNode[][] orChildNodes,
            bool hasControl,
            FilterSpecCompilerArgs args)
        {
            var mapAll = new FilterSpecParaForgeMap();

            mapAll.Add(filterParamExprMap);

            // combine
            IList <ExprNode> nvPerOr      = new List <ExprNode>(permutation.Length);
            IList <ExprNode> negatingPath = new List <ExprNode>(permutation.Length);

            for (var orNodeNum = 0; orNodeNum < permutation.Length; orNodeNum++)
            {
                int orChildNodeNum = permutation[orNodeNum].AsInt32();
                var current        = orChildNodes[orNodeNum][orChildNodeNum];
                if (current is OrChildNodeNV)
                {
                    var nv = (OrChildNodeNV)current;
                    mapAll.Add(nv.Map);
                    if (current is OrChildNodeNVNegated)
                    {
                        negatingPath.Add(((OrChildNodeNVNegated)current).Control);
                    }
                }
                else
                {
                    var v = (OrChildNodeV)current;
                    negatingPath.Add(v.Node);
                }

                var orChildNodesForCurrent = orChildNodes[orNodeNum];
                foreach (var other in orChildNodesForCurrent)
                {
                    if (current == other)
                    {
                        continue;
                    }

                    if (other is OrChildNodeV)
                    {
                        var v   = (OrChildNodeV)other;
                        var not = new ExprNotNode();
                        not.AddChildNode(v.Node);
                        nvPerOr.Add(not);
                    }
                }
            }

            // consolidate across
            FilterSpecCompilerConsolidateUtil.Consolidate(mapAll, args.statementRawInfo.StatementName);

            IList <FilterSpecPlanPathTripletForge> triplets = new List <FilterSpecPlanPathTripletForge>(mapAll.Triplets);
            var countUnassigned = mapAll.CountUnassignedExpressions();

            if (countUnassigned != 0)
            {
                var triplet = MakeRemainingNode(mapAll.UnassignedExpressions, args);
                triplets.Add(triplet);
            }

            // without conditions we are done
            var tripletsArray = triplets.ToArray();

            if (!hasControl)
            {
                return(new CombPermutationTriplets(tripletsArray, null));
            }

            var negatingNode = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(negatingPath);
            var excluded     = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(nvPerOr);
            var merged       = ExprNodeUtilityMake.ConnectExpressionsByLogicalAndWhenNeeded(negatingNode, excluded);

            return(new CombPermutationTriplets(tripletsArray, merged));
        }
        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));
        }