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); }