/// <summary> /// Finds a transition which matches the initial state, target state and rule condition in the existing transitions /// </summary> /// <param name="condition"></param> /// <param name="initialState"></param> /// <param name="targetState"></param> /// <returns></returns> private bool findMatchingTransition(Rules.RuleCondition condition, State initialState, State targetState) { bool retVal = false; foreach (Transition t in Transitions) { if (t.RuleCondition == condition && t.Source == initialState && t.Target == targetState) { retVal = true; break; } } return(retVal); }
/// <summary> /// Adds a transition in the transitions sets /// </summary> /// <param name="update">The update state which provides the target of the transition</param> /// <param name="target">The target state, as determined by the update statement</param> /// <param name="filteredOut"></param> /// <param name="preCondition">the precondition (if any) which is used to determine the initial state</param> /// <param name="initial">The initial state</param> /// <returns> /// true if the transition has been filtered out. A transition can be filtered out if the target state is equal to the /// initial state or the initial state is null /// </returns> private bool AddTransition(VariableUpdateStatement update, State target, PreCondition preCondition, State initial) { bool retVal = false; if (SameParentStateMachine(initial, target)) { State initialState = StateMachine.StateInThisStateMachine(initial); // TargetState is the target state either in this state machine or in a sub state machine State targetState = StateMachine.StateInThisStateMachine(target); // Determine the rule condition (if any) related to this state machine Rules.RuleCondition condition = null; if (update != null) { Action action = update.Root as Action; condition = action.RuleCondition; } if (targetState != null || initialState != null) { // This transition is about this state machine. if (initialState != targetState && initialState != null) { // Check that the transition is not yet present // This case can occur when the same RuleCondition references two different states // in a substate machine. Only draws the transition once. if (!findMatchingTransition(condition, initialState, targetState)) { Transitions.Add(new Transition(preCondition, initialState, update, targetState)); } } else { if (initialState == initial) { retVal = true; } } } } return(retVal); }
/// <summary> /// Check if this rule corresponds to a transition for this state machine /// </summary> /// <param name="obj"></param> /// <param name="visitSubNodes"></param> public override void visit(RuleCondition obj, bool visitSubNodes) { Rules.RuleCondition ruleCondition = (Rules.RuleCondition)obj; foreach (Action action in ruleCondition.Actions) { try { foreach (VariableUpdateStatement update in action.UpdateStatements) { Type targetType = update.TargetType; if (targetType is StateMachine) { Expression expressionTree = update.Expression; if (expressionTree != null) { // HaCK: This is a bit rough, but should be sufficient for now... foreach (State stt1 in GetStates(expressionTree)) { // TargetState is the target state either in this state machine or in a sub state machine State targetState = StateMachine.StateInThisStateMachine(stt1); int transitionCount = Transitions.Count; bool filteredOut = false; // Finds the enclosing state of this action to determine the source state of this transition State enclosingState = EnclosingFinder <State> .find(action); if (enclosingState != null) { filteredOut = filteredOut || AddTransition(update, stt1, null, enclosingState); } if (!filteredOut) { foreach (PreCondition preCondition in ruleCondition.AllPreConditions) { // A transition from one state to another has been found foreach (State stt2 in GetStates(preCondition.Expression)) { filteredOut = filteredOut || AddTransition(update, stt1, preCondition, stt2); } } } if (Transitions.Count == transitionCount) { if (targetState == stt1 && targetState.EnclosingStateMachine == StateMachine) { if (!filteredOut) { Action enclosingAction = update.Root as Action; if (enclosingAction != null) { // No precondition could be found => one can reach this state at anytime if ( !findMatchingTransition(enclosingAction.RuleCondition, null, targetState)) { Transitions.Add(new Transition(null, null, update, targetState)); } } } } } } } else { action.AddError("Cannot parse expression"); } } } } catch (Exception e) { } } base.visit(obj, visitSubNodes); }