private static RuleSymbolInfo AnalyzeRule(RuleChainingBehavior behavior, Rule rule, RuleValidation validator, Tracer tracer)
        {
            RuleSymbolInfo rsi = new RuleSymbolInfo();

            if (rule.Condition != null)
            {
                rsi.conditionDependencies = rule.Condition.GetDependencies(validator);

                if ((rsi.conditionDependencies != null) && (tracer != null))
                {
                    tracer.TraceConditionSymbols(rule.Name, rsi.conditionDependencies);
                }
            }

            if (rule.thenActions != null)
            {
                rsi.thenSideEffects = GetActionSideEffects(behavior, rule.thenActions, validator);

                if ((rsi.thenSideEffects != null) && (tracer != null))
                {
                    tracer.TraceThenSymbols(rule.Name, rsi.thenSideEffects);
                }
            }

            if (rule.elseActions != null)
            {
                rsi.elseSideEffects = GetActionSideEffects(behavior, rule.elseActions, validator);

                if ((rsi.elseSideEffects != null) && (tracer != null))
                {
                    tracer.TraceElseSymbols(rule.Name, rsi.elseSideEffects);
                }
            }

            return(rsi);
        }
        internal static void ExecuteRuleSet(IList <RuleState> orderedRules, RuleExecution ruleExecution, Tracer tracer, string trackingKey)
        {
            // keep track of rule execution
            long[] executionCount = new long[orderedRules.Count];
            bool[] satisfied      = new bool[orderedRules.Count];
            // clear the halted flag
            ruleExecution.Halted = false;

            //ActivityExecutionContext activityExecutionContext = ruleExecution.ActivityExecutionContext;

            // loop until we hit the end of the list
            int current = 0;

            while (current < orderedRules.Count)
            {
                RuleState currentRuleState = orderedRules[current];

                // does this rule need to be evaluated?
                if (!satisfied[current])
                {
                    // yes, so evaluate it and determine the list of actions needed
                    if (tracer != null)
                    {
                        tracer.StartRule(currentRuleState.Rule.Name);
                    }
                    satisfied[current] = true;
                    bool result = currentRuleState.Rule.Condition.Evaluate(ruleExecution);
                    if (tracer != null)
                    {
                        tracer.RuleResult(currentRuleState.Rule.Name, result);
                    }

                    ICollection <RuleAction> actions = (result) ?
                                                       currentRuleState.Rule.thenActions :
                                                       currentRuleState.Rule.elseActions;
                    ICollection <int> activeRules = result ?
                                                    currentRuleState.ThenActionsActiveRules :
                                                    currentRuleState.ElseActionsActiveRules;

                    // are there any actions to be performed?
                    if ((actions != null) && (actions.Count > 0))
                    {
                        ++executionCount[current];
                        string ruleName = currentRuleState.Rule.Name;
                        if (tracer != null)
                        {
                            tracer.StartActions(ruleName, result);
                        }

                        // evaluate the actions
                        foreach (RuleAction action in actions)
                        {
                            action.Execute(ruleExecution);

                            // was Halt executed?
                            if (ruleExecution.Halted)
                            {
                                break;
                            }
                        }

                        // was Halt executed?
                        if (ruleExecution.Halted)
                        {
                            break;
                        }

                        // any fields updated?
                        if (activeRules != null)
                        {
                            foreach (int updatedRuleIndex in activeRules)
                            {
                                RuleState rs = orderedRules[updatedRuleIndex];
                                if (satisfied[updatedRuleIndex])
                                {
                                    // evaluate at least once, or repeatedly if appropriate
                                    if ((executionCount[updatedRuleIndex] == 0) || (rs.Rule.ReevaluationBehavior == RuleReevaluationBehavior.Always))
                                    {
                                        if (tracer != null)
                                        {
                                            tracer.TraceUpdate(ruleName, rs.Rule.Name);
                                        }
                                        satisfied[updatedRuleIndex] = false;
                                        if (updatedRuleIndex < current)
                                        {
                                            current = updatedRuleIndex;
                                        }
                                    }
                                }
                            }
                        }
                        continue;
                    }
                }
                ++current;
            }
            // no more rules to execute, so we are done
        }
        private static void AnalyzeRules(RuleChainingBehavior behavior, List <RuleState> ruleStates, RuleValidation validation, Tracer tracer)
        {
            int i;
            int numRules = ruleStates.Count;

            // if no chaining is required, then nothing to do
            if (behavior == RuleChainingBehavior.None)
            {
                return;
            }

            // Analyze all the rules and collect all the dependencies & side-effects
            RuleSymbolInfo[] ruleSymbols = new RuleSymbolInfo[numRules];
            for (i = 0; i < numRules; ++i)
            {
                ruleSymbols[i] = AnalyzeRule(behavior, ruleStates[i].Rule, validation, tracer);
            }

            for (i = 0; i < numRules; ++i)
            {
                RuleState currentRuleState = ruleStates[i];

                if (ruleSymbols[i].thenSideEffects != null)
                {
                    currentRuleState.ThenActionsActiveRules = AnalyzeSideEffects(ruleSymbols[i].thenSideEffects, ruleSymbols);

                    if ((currentRuleState.ThenActionsActiveRules != null) && (tracer != null))
                    {
                        tracer.TraceThenTriggers(currentRuleState.Rule.Name, currentRuleState.ThenActionsActiveRules, ruleStates);
                    }
                }

                if (ruleSymbols[i].elseSideEffects != null)
                {
                    currentRuleState.ElseActionsActiveRules = AnalyzeSideEffects(ruleSymbols[i].elseSideEffects, ruleSymbols);

                    if ((currentRuleState.ElseActionsActiveRules != null) && (tracer != null))
                    {
                        tracer.TraceElseTriggers(currentRuleState.Rule.Name, currentRuleState.ElseActionsActiveRules, ruleStates);
                    }
                }
            }
        }
        internal static IList <RuleState> Preprocess(RuleChainingBehavior behavior, ICollection <Rule> rules, RuleValidation validation, Tracer tracer)
        {
            // start by taking the active rules and make them into a list sorted by priority
            List <RuleState> orderedRules = new List <RuleState>(rules.Count);

            foreach (Rule r in rules)
            {
                if (r.Active)
                {
                    orderedRules.Add(new RuleState(r));
                }
            }
            orderedRules.Sort();

            // Analyze the rules to match side-effects with dependencies.
            // Note that the RuleSet needs to have been validated prior to this.
            AnalyzeRules(behavior, orderedRules, validation, tracer);

            // return the sorted list of rules
            return(orderedRules);
        }