/// <summary> /// Executes a single rule priority (shared version of the method) /// </summary> /// <param name="priority"></param> private void InnerExecuteOnePriority(acceptor.RulePriority priority) { Util.DontNotify(() => { CacheImpact = new CacheImpact(); CurrentPriority = priority; // Activates the processing engine HashSet <Activation> activations = new HashSet <Activation>(); foreach (Dictionary dictionary in EfsSystem.Instance.Dictionaries) { foreach (NameSpace nameSpace in dictionary.NameSpaces) { SetupNameSpaceActivations(priority, activations, nameSpace); } } List <VariableUpdate> updates = new List <VariableUpdate>(); EvaluateActivations(activations, priority, updates); CheckUpdatesCompatibility(updates); ApplyUpdates(updates); ClearCaches(); CheckExpectationsState(priority); }); }
/// <summary> /// Evaluates the rule and its sub rules /// </summary> /// <param name="runner"></param> /// <param name="priority">the priority level : a rule can be activated only if its priority level == priority</param> /// <param name="instance">The instance on which the rule must be evaluated</param> /// <param name="activations">the rule conditions to be activated</param> /// <param name="explanation">The explanation part to be filled</param> /// <returns>the number of actions that were activated during this evaluation</returns> public bool Evaluate(Runner runner, acceptor.RulePriority?priority, IModelElement instance, HashSet <Activation> activations, ExplanationPart explanation) { bool retVal = false; if (UpdatedBy.Count == 0 && !IsRemoved && (priority == null || ActivationPriorities.Contains((acceptor.RulePriority)priority))) { long start = Environment.TickCount; foreach (RuleCondition ruleCondition in RuleConditions) { retVal = ruleCondition.Evaluate(runner, priority, instance, activations, explanation); if (retVal) { break; } } // Guard evaluation execution time long stop = Environment.TickCount; long span = (stop - start); ExecutionTimeInMilli += span; } return(retVal); }
/// <summary> /// Constructor /// </summary> /// <param name="id"></param> /// <param name="instance"></param> /// <param name="priority"></param> public ModelEvent(string id, INamable instance, acceptor.RulePriority?priority) { Id = id; Message = id; Instance = instance; Priority = priority; }
/// <summary> /// Constructor /// </summary> /// <param name="activation"></param> /// <param name="priority"></param> public RuleFired(Activation activation, acceptor.RulePriority?priority) : base(activation.RuleCondition.Name, activation.RuleCondition, priority) { Activation = activation; Explanation = Activation.Explanation; Updates = new List <VariableUpdate>(); }
/// <summary> /// Add actions when leaving a state /// </summary> /// <param name="priority"></param> /// <param name="updates"></param> /// <param name="variable"></param> /// <param name="leaveState"></param> /// <param name="enterState"></param> private void HandleLeaveState(acceptor.RulePriority?priority, List <VariableUpdate> updates, IVariable variable, State leaveState, State enterState) { if (!_processedStates.Contains(leaveState)) { _processedStates.Add(leaveState); if (!leaveState.getStateMachine().Contains(leaveState, enterState)) { if (leaveState.getLeaveAction() != null) { Rules.Rule rule = (Rules.Rule)leaveState.getLeaveAction(); ExplanationPart explanation = new ExplanationPart(rule, "Rule evaluation"); HashSet <Activation> newActivations = new HashSet <Activation>(); List <VariableUpdate> newUpdates = new List <VariableUpdate>(); // the priority is not specified for the rule evaluation since // the rules of the leave states have to be executed regardless the priority rule.Evaluate(this, null, variable, newActivations, explanation); EvaluateActivations(newActivations, priority, newUpdates); updates.AddRange(newUpdates); } if (leaveState.EnclosingState != null) { HandleLeaveState(priority, updates, variable, leaveState.EnclosingState, enterState); } } _processedStates.Remove(leaveState); } }
/// <summary> /// Complete the 'updates' parameters by considering leave & enter state rules. /// Avoid considering twice the same transition for all updates provided as parameter /// </summary> /// <param name="priority"></param> /// <param name="updates">The variable update list to be completed according to enter and leave actions</param> public void HandleEnterAndLeaveStateActions(acceptor.RulePriority?priority, List <VariableUpdate> updates) { List <Tuple <State, State> > transitions = new List <Tuple <State, State> >(); List <VariableUpdate> currentUpdates = updates; while (currentUpdates.Count > 0) { List <VariableUpdate> newUpdates = new List <VariableUpdate>(); foreach (VariableUpdate update in currentUpdates) { foreach (Change change in update.Changes.Changes) { if (change.Variable.Type is StateMachine) { State leavingState = (State)change.PreviousValue; State enteringState = (State)change.NewValue; bool transitionFound = false; foreach (Tuple <State, State> transition in transitions) { if ((transition.Item1 == leavingState) && (transition.Item2 == enteringState)) { transitionFound = true; break; } } if (!transitionFound) { Tuple <State, State> transition = new Tuple <State, State>(leavingState, enteringState); transitions.Add(transition); HandleLeaveState(priority, newUpdates, change.Variable, leavingState, enteringState); HandleEnterState(priority, newUpdates, change.Variable, leavingState, enteringState); } } } } updates.AddRange(newUpdates); currentUpdates = newUpdates; } }
/// <summary> /// Activates the rules in the dictionary until stabilisation /// </summary> public void Cycle() { CurrentPriority = null; LastActivationTime = Time; Utils.ModelElement.Errors = new Dictionary <Utils.ModelElement, List <ElementLog> >(); foreach (acceptor.RulePriority priority in PrioritiesOrder) { InnerExecuteOnePriority(priority); } CurrentPriority = null; RegisterErrors(Utils.ModelElement.Errors); EventTimeLine.GarbageCollect(); NextCycle(); }
/// <summary> /// Evaluates the rule and its sub rules /// </summary> /// <param name="runner"></param> /// <param name="priority">the priority level : a rule can be activated only if its priority level == priority</param> /// <param name="instance">The instance on which the rule must be evaluated</param> /// <param name="ruleConditions">the rule conditions to be activated</param> /// <param name="explanation">The explanation part to be filled</param> /// <param name="runner"></param> /// <returns>the number of actions that were activated during this evaluation</returns> public bool Evaluate(Runner runner, acceptor.RulePriority?priority, IModelElement instance, HashSet <Activation> activations, ExplanationPart explanation) { bool retVal = false; ExplanationPart conditionExplanation = ExplanationPart.CreateSubExplanation(explanation, this); InterpretationContext context = new InterpretationContext(instance); retVal = EvaluatePreConditions(context, conditionExplanation, runner); if (retVal) { if (conditionExplanation != null) { conditionExplanation.Message = "Condition " + Name + " satisfied"; } foreach (Rule subRule in SubRules) { subRule.Evaluate(runner, priority, instance, activations, conditionExplanation); } if (priority == null || EnclosingRule.getPriority() == priority) { activations.Add(new Activation(this, instance, conditionExplanation)); } } else { if (conditionExplanation != null) { conditionExplanation.Message = "Condition " + Name + " not satisfied"; } } return(retVal); }
/// <summary> /// Applies the selected actions and update the system state /// </summary> /// <param name="activations"></param> /// <param name="priority"></param> /// <param name="updates">Provides all the updates that have been evaluated</param> public void EvaluateActivations(HashSet <Activation> activations, acceptor.RulePriority?priority, List <VariableUpdate> updates) { foreach (Activation activation in activations) { if (activation.RuleCondition.Actions.Count > 0) { // Register the fact that a rule has been triggered RuleFired ruleFired = new RuleFired(activation, priority); EventTimeLine.AddModelEvent(ruleFired, true); ExplanationPart changesExplanation = ExplanationPart.CreateSubExplanation(activation.Explanation, "Changes"); // Registers all model updates due to this rule triggering foreach (Action action in activation.RuleCondition.Actions) { if (action.Statement != null) { VariableUpdate variableUpdate = new VariableUpdate(action, activation.Instance, priority); variableUpdate.ComputeChanges(false, this); EventTimeLine.AddModelEvent(variableUpdate, false); ruleFired.AddVariableUpdate(variableUpdate); if (changesExplanation != null) { changesExplanation.SubExplanations.Add(variableUpdate.Explanation); } updates.Add(variableUpdate); } else { action.AddError("Cannot parse action statement"); } } } } HandleEnterAndLeaveStateActions(priority, updates); }
/// <summary> /// Constructor /// </summary> /// <param name="subStep">The activated step</param> /// <param name="priority"></param> public SubStepActivated(SubStep subStep, acceptor.RulePriority?priority) : base(subStep.Name, subStep, priority) { SubStep = subStep; }
/// <summary> /// Constructor /// </summary> /// <param name="expect">the expectation which changed</param> /// <param name="newState">the new expectation state</param> /// <param name="prevState">the previous expectation state</param> /// <param name="message">the message associated to this expectation state change</param> public ExpectationStateChange(Expect expect, acceptor.RulePriority?priority, ExplanationPart explain) : base("Expectation state change", expect.Expectation, priority) { Expect = expect; Explanation = explain; }
/// <summary> /// Constructor /// </summary> /// <param name="expect"></param> /// <param name="priority"></param> /// <param name="explain"></param> public ExpectationReached(Expect expect, acceptor.RulePriority?priority, ExplanationPart explain) : base(expect, priority, explain) { Message = "Expectation reached : " + Expect.Expectation.Name; }
/// <summary> /// Constructor /// </summary> /// <param name="expect"></param> /// <param name="priority"></param> /// <param name="explain"></param> public FailedExpectation(Expect expect, acceptor.RulePriority?priority, ExplanationPart explain) : base(expect, priority, explain) { Message = "Failed expectation : " + Expect.Expectation.Name; }
/// <summary> /// Constructor /// </summary> /// <param name="id"></param> /// <param name="message"></param> public ModelEvent(string id, string message, acceptor.RulePriority?priority) { Id = id; Message = message; Priority = priority; }
/// <summary> /// Constructor /// </summary> /// <param name="action">The action which raised the variable update></param> public VariableUpdate(Action action, IModelElement instance, acceptor.RulePriority?priority) : base(action.ExpressionText, instance, priority) { Action = action; }
/// <summary> /// Constructor /// </summary> /// <param name="id"></param> public Expect(Expectation expectation, acceptor.RulePriority?priority) : base(expectation.ExpressionText, expectation, priority) { Expectation = expectation; State = EventState.Active; }
/// <summary> /// Constructor /// </summary> /// <param name="id"></param> public ModelInterpretationFailure(ElementLog log, INamable instance, acceptor.RulePriority?priority) : base(log.Log, instance, priority) { Log = log; }