Просмотр исходного кода

State exit sequences now use leaf states in state switches ( YAKHMI-314 )

terfloth@itemis.de 13 лет назад
Родитель
Сommit
1fb6935ef0

+ 78 - 45
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/ModelSequencer.xtend

@@ -68,6 +68,7 @@ import org.yakindu.sct.model.stext.stext.BoolLiteral
 import javax.sound.sampled.BooleanControl$Type
 import org.yakindu.sct.model.sgraph.RegularState
 import org.yakindu.sct.model.sgraph.FinalState
+import org.yakindu.sct.model.sgraph.Vertex
 
 class ModelSequencer {
 	
@@ -324,6 +325,7 @@ class ModelSequencer {
 		l.filter( typeof(State) ).toList
 	}
 	
+	// TODO: rename since this list also includes the start state or change implementation and usages
 	def List<RegularState> parentStates(RegularState s) {
 		s.containers.filter( typeof(RegularState) ).toList		
 	}
@@ -477,27 +479,11 @@ class ModelSequencer {
 			s.create.createReactionSequence(r)
 		}])
 		
+		execState.reactSequence.name = 'react'
+		execState.reactSequence.comment = 'The reactions of state ' + state.name + '.'
+		
 		return execState.reactSequence
 	}	
-
-
-//	def Cycle defineCycle(FinalState state) {
-//	
-//		val execState = state.create
-//		val stateReaction = execState.createReactionSequence(null)
-//		val parents = state.parentStates		
-//		execState.cycle = parents.fold(null, [r, s | {
-//			s.create.createReactionSequence(r)
-//		}])
-//		
-//		return execState.cycle
-//	}	
-
-
-//	def Cycle defineCycle(ExecutionState state) {	
-//		state.cycle = state.createReactionSequence(null)
-//		return state.cycle
-//	}
 	
 
 	def Sequence createReactionSequence(ExecutionState state, Step localStep) {	
@@ -695,14 +681,24 @@ class ModelSequencer {
 	}
 	
 
-	def void defineStateExitSequence(Region r) {
+	def dispatch void defineStateExitSequence(Region r) {
 		
 		// process all states of a region
-		for ( s : r.vertices.filter(typeof(State))) defineStateExitSequence(s)
+		for ( s : r.vertices ) defineStateExitSequence(s)
 	}
 	
+	def dispatch void defineStateExitSequence(Vertex v) {}
+	
+	def dispatch void defineStateExitSequence(FinalState s) {
+		val execState = s.create
+		val seq = sexecFactory.createSequence
+		seq.name = "exitSequence"
+		seq.comment = "Default exit sequence for final state."
+		seq.steps += s.newExitStateStep
+		execState.exitSequence = seq
+	}
 	
-	def void defineStateExitSequence(State state) {
+	def dispatch void defineStateExitSequence(State state) {
 		
 		val execState = state.create
 		val seq = sexecFactory.createSequence
@@ -714,24 +710,50 @@ class ModelSequencer {
 			seq.steps += state.newExitStateStep
 					
 		} else {
-	
-			for ( r : state.subRegions ) {
-				defineStateExitSequence(r)
+
+			// first enforce calculation of all child exit sequences
+			state.subRegions.forEach( r | { r.defineStateExitSequence null })
+			
+			// collect leaf states
+			val List<RegularState> leafStates = state.collectLeafStates(new ArrayList<RegularState>())
+
+			// create a state switch
+			val StateSwitch sSwitch = sexecFactory.createStateSwitch
+							
+			// create a case for each leaf state				
+			for ( s : leafStates ) {
+
+				val caseSeq = sexecFactory.createSequence
 				
-				val StateSwitch sSwitch = sexecFactory.createStateSwitch
+				caseSeq.steps += s.create.exitSequence.newCall
 				
-				// collect leaf states
-				val List<State> leafStates = new ArrayList<State>()
+				val exitStates = s.parentStates
+				exitStates.removeAll(state.parentStates)
+				exitStates.remove(s)
 				
-				// create a case for each leaf state
 				// include exitAction calls up to the direct child level.
+				exitStates.fold(caseSeq , [ cs, exitState | {
+					 if (exitState.create.exitAction != null) cs.steps.add(exitState.create.exitAction.newCall) 
+					 cs
+				}]) 
 				
-				
-				for ( s : r.states ) {
-					if (s.create.exitSequence != null) sSwitch.cases.add(s.create.newCase(s.create.exitSequence.newCall))
-				}
-				seq.steps.add(sSwitch);
-			} 
+				if (s.create.exitSequence != null) sSwitch.cases.add(s.create.newCase(caseSeq))
+
+			}
+			
+			seq.steps.add(sSwitch);
+			
+	
+//			for ( r : state.subRegions ) {
+//				defineStateExitSequence(r)
+//				
+//				val StateSwitch sSwitch = sexecFactory.createStateSwitch
+//								
+//				for ( s : r.states ) {
+//					if (s.create.exitSequence != null) sSwitch.cases.add(s.create.newCase(s.create.exitSequence.newCall))
+//				}
+//				seq.steps.add(sSwitch);
+//			} 
 		}
 
 		if (execState.exitAction != null) seq.steps.add(execState.exitAction.newCall)
@@ -740,15 +762,26 @@ class ModelSequencer {
 	
 	
 	
-//	def List<State> collectLeafStates(State state, List<State> leafStates) {
-//		if ( state.simple ) 
-//			leafStates += state
-//		else
-//			
-//			
-//		return leafStates	
-//	}
+	def List<RegularState> collectLeafStates(RegularState state, List<RegularState> leafStates) {
+		if ( state.isLeaf ) 
+			leafStates += state
+		else if ( state instanceof State ) {
+			val State s = state as State		
+			for ( r : s.subRegions ) {
+				for ( v : r.vertices ) {
+					if (v instanceof RegularState) collectLeafStates(v as RegularState, leafStates)
+				}
+			}
+		}
+		return leafStates	
+	}
+	
+	
+	def dispatch isLeaf(RegularState s) { false }
+	
+	def dispatch isLeaf(FinalState s) {true}
 	
+	def dispatch isLeaf(State s) { s.simple }
 	
 	
 	def newCase(ExecutionState it, Step step) {
@@ -782,7 +815,7 @@ class ModelSequencer {
 	}
 	
 	
-	def newEnterStateStep(State s) {
+	def newEnterStateStep(RegularState s) {
 		var ess  = null as EnterState
 		if (s != null) {
 			ess = sexecFactory.createEnterState
@@ -791,7 +824,7 @@ class ModelSequencer {
 		return ess
 	}
 	
-	def newExitStateStep(State s) {
+	def newExitStateStep(RegularState s) {
 		var ess  = null as ExitState
 		if (s != null) {
 			ess = sexecFactory.createExitState

+ 166 - 34
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/ModelSequencer.java

@@ -45,6 +45,7 @@ import org.yakindu.sct.model.sgraph.Effect;
 import org.yakindu.sct.model.sgraph.Entry;
 import org.yakindu.sct.model.sgraph.Event;
 import org.yakindu.sct.model.sgraph.FinalState;
+import org.yakindu.sct.model.sgraph.NamedElement;
 import org.yakindu.sct.model.sgraph.Region;
 import org.yakindu.sct.model.sgraph.RegularState;
 import org.yakindu.sct.model.sgraph.SGraphFactory;
@@ -932,7 +933,14 @@ public class ModelSequencer {
       Sequence _fold = IterableExtensions.<RegularState, Sequence>fold(parents, null, _function);
       execState.setReactSequence(_fold);
       Sequence _reactSequence = execState.getReactSequence();
-      return _reactSequence;
+      _reactSequence.setName("react");
+      Sequence _reactSequence_1 = execState.getReactSequence();
+      String _name = state.getName();
+      String _operator_plus = StringExtensions.operator_plus("The reactions of state ", _name);
+      String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, ".");
+      _reactSequence_1.setComment(_operator_plus_1);
+      Sequence _reactSequence_2 = execState.getReactSequence();
+      return _reactSequence_2;
     }
   }
   
@@ -1341,15 +1349,33 @@ public class ModelSequencer {
     }
   }
   
-  public void defineStateExitSequence(final Region r) {
+  protected void _defineStateExitSequence(final Region r) {
     EList<Vertex> _vertices = r.getVertices();
-    Iterable<State> _filter = IterableExtensions.<State>filter(_vertices, org.yakindu.sct.model.sgraph.State.class);
-    for (State s : _filter) {
+    for (Vertex s : _vertices) {
       this.defineStateExitSequence(s);
     }
   }
   
-  public void defineStateExitSequence(final State state) {
+  protected void _defineStateExitSequence(final Vertex v) {
+  }
+  
+  protected void _defineStateExitSequence(final FinalState s) {
+    {
+      ExecutionState _create = this.factory.create(s);
+      final ExecutionState execState = _create;
+      SexecFactory _sexecFactory = this.sexecFactory();
+      Sequence _createSequence = _sexecFactory.createSequence();
+      final Sequence seq = _createSequence;
+      seq.setName("exitSequence");
+      seq.setComment("Default exit sequence for final state.");
+      EList<Step> _steps = seq.getSteps();
+      ExitState _newExitStateStep = this.newExitStateStep(s);
+      CollectionExtensions.<ExitState>operator_add(_steps, _newExitStateStep);
+      execState.setExitSequence(seq);
+    }
+  }
+  
+  protected void _defineStateExitSequence(final State state) {
     {
       ExecutionState _create = this.factory.create(state);
       final ExecutionState execState = _create;
@@ -1366,47 +1392,125 @@ public class ModelSequencer {
         ExitState _newExitStateStep = this.newExitStateStep(state);
         CollectionExtensions.<ExitState>operator_add(_steps, _newExitStateStep);
       } else {
-        EList<Region> _subRegions = state.getSubRegions();
-        for (Region r : _subRegions) {
-          {
-            this.defineStateExitSequence(r);
-            SexecFactory _sexecFactory_1 = this.sexecFactory();
-            StateSwitch _createStateSwitch = _sexecFactory_1.createStateSwitch();
-            final StateSwitch sSwitch = _createStateSwitch;
-            ArrayList<State> _arrayList = new ArrayList<State>();
-            final List<State> leafStates = _arrayList;
-            Iterable<State> _states = this.states(r);
-            for (State s : _states) {
+        {
+          EList<Region> _subRegions = state.getSubRegions();
+          final Function1<Region,Object> _function = new Function1<Region,Object>() {
+              public Object apply(final Region r) {
+                Object _xblockexpression = null;
+                {
+                  ModelSequencer.this.defineStateExitSequence(r);
+                  _xblockexpression = (null);
+                }
+                return _xblockexpression;
+              }
+            };
+          IterableExtensions.<Region>forEach(_subRegions, _function);
+          ArrayList<RegularState> _arrayList = new ArrayList<RegularState>();
+          List<RegularState> _collectLeafStates = this.collectLeafStates(state, _arrayList);
+          final List<RegularState> leafStates = _collectLeafStates;
+          SexecFactory _sexecFactory_1 = this.sexecFactory();
+          StateSwitch _createStateSwitch = _sexecFactory_1.createStateSwitch();
+          final StateSwitch sSwitch = _createStateSwitch;
+          for (RegularState s : leafStates) {
+            {
+              SexecFactory _sexecFactory_2 = this.sexecFactory();
+              Sequence _createSequence_1 = _sexecFactory_2.createSequence();
+              final Sequence caseSeq = _createSequence_1;
+              EList<Step> _steps_1 = caseSeq.getSteps();
               ExecutionState _create_1 = this.factory.create(s);
               Sequence _exitSequence = _create_1.getExitSequence();
-              boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_exitSequence, null);
-              if (_operator_notEquals) {
+              Call _newCall = this.factory.newCall(_exitSequence);
+              CollectionExtensions.<Call>operator_add(_steps_1, _newCall);
+              List<RegularState> _parentStates = this.parentStates(s);
+              final List<RegularState> exitStates = _parentStates;
+              List<RegularState> _parentStates_1 = this.parentStates(state);
+              exitStates.removeAll(_parentStates_1);
+              exitStates.remove(s);
+              final Function2<Sequence,RegularState,Sequence> _function_1 = new Function2<Sequence,RegularState,Sequence>() {
+                  public Sequence apply(final Sequence cs , final RegularState exitState) {
+                    Sequence _xblockexpression_1 = null;
+                    {
+                      ExecutionState _create_2 = ModelSequencer.this.factory.create(exitState);
+                      Step _exitAction = _create_2.getExitAction();
+                      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_exitAction, null);
+                      if (_operator_notEquals) {
+                        EList<Step> _steps_2 = cs.getSteps();
+                        ExecutionState _create_3 = ModelSequencer.this.factory.create(exitState);
+                        Step _exitAction_1 = _create_3.getExitAction();
+                        Call _newCall_1 = ModelSequencer.this.factory.newCall(_exitAction_1);
+                        _steps_2.add(_newCall_1);
+                      }
+                      _xblockexpression_1 = (cs);
+                    }
+                    return _xblockexpression_1;
+                  }
+                };
+              IterableExtensions.<RegularState, Sequence>fold(exitStates, caseSeq, _function_1);
+              ExecutionState _create_4 = this.factory.create(s);
+              Sequence _exitSequence_1 = _create_4.getExitSequence();
+              boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_exitSequence_1, null);
+              if (_operator_notEquals_1) {
                 EList<StateCase> _cases = sSwitch.getCases();
-                ExecutionState _create_2 = this.factory.create(s);
-                ExecutionState _create_3 = this.factory.create(s);
-                Sequence _exitSequence_1 = _create_3.getExitSequence();
-                Call _newCall = this.factory.newCall(_exitSequence_1);
-                StateCase _newCase = this.newCase(_create_2, _newCall);
+                ExecutionState _create_5 = this.factory.create(s);
+                StateCase _newCase = this.newCase(_create_5, caseSeq);
                 _cases.add(_newCase);
               }
             }
-            EList<Step> _steps_1 = seq.getSteps();
-            _steps_1.add(sSwitch);
           }
+          EList<Step> _steps_3 = seq.getSteps();
+          _steps_3.add(sSwitch);
         }
       }
-      Step _exitAction = execState.getExitAction();
-      boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_exitAction, null);
-      if (_operator_notEquals_1) {
-        EList<Step> _steps_2 = seq.getSteps();
-        Step _exitAction_1 = execState.getExitAction();
-        Call _newCall_1 = this.factory.newCall(_exitAction_1);
-        _steps_2.add(_newCall_1);
+      Step _exitAction_2 = execState.getExitAction();
+      boolean _operator_notEquals_2 = ObjectExtensions.operator_notEquals(_exitAction_2, null);
+      if (_operator_notEquals_2) {
+        EList<Step> _steps_4 = seq.getSteps();
+        Step _exitAction_3 = execState.getExitAction();
+        Call _newCall_2 = this.factory.newCall(_exitAction_3);
+        _steps_4.add(_newCall_2);
       }
       execState.setExitSequence(seq);
     }
   }
   
+  public List<RegularState> collectLeafStates(final RegularState state, final List<RegularState> leafStates) {
+    {
+      boolean _isLeaf = this.isLeaf(state);
+      if (_isLeaf) {
+        CollectionExtensions.<RegularState>operator_add(leafStates, state);
+      } else {
+        if ((state instanceof org.yakindu.sct.model.sgraph.State)) {
+          {
+            final State s = ((State) state);
+            EList<Region> _subRegions = s.getSubRegions();
+            for (Region r : _subRegions) {
+              EList<Vertex> _vertices = r.getVertices();
+              for (Vertex v : _vertices) {
+                if ((v instanceof org.yakindu.sct.model.sgraph.RegularState)) {
+                  this.collectLeafStates(((RegularState) v), leafStates);
+                }
+              }
+            }
+          }
+        }
+      }
+      return leafStates;
+    }
+  }
+  
+  protected boolean _isLeaf(final RegularState s) {
+    return false;
+  }
+  
+  protected boolean _isLeaf(final FinalState s) {
+    return true;
+  }
+  
+  protected boolean _isLeaf(final State s) {
+    boolean _isSimple = s.isSimple();
+    return _isSimple;
+  }
+  
   public StateCase newCase(final ExecutionState it, final Step step) {
     {
       SexecFactory _sexecFactory = this.sexecFactory();
@@ -1459,7 +1563,7 @@ public class ModelSequencer {
     }
   }
   
-  public EnterState newEnterStateStep(final State s) {
+  public EnterState newEnterStateStep(final RegularState s) {
     {
       EnterState ess = ((EnterState) null);
       boolean _operator_notEquals = ObjectExtensions.operator_notEquals(s, null);
@@ -1476,7 +1580,7 @@ public class ModelSequencer {
     }
   }
   
-  public ExitState newExitStateStep(final State s) {
+  public ExitState newExitStateStep(final RegularState s) {
     {
       ExitState ess = ((ExitState) null);
       boolean _operator_notEquals = ObjectExtensions.operator_notEquals(s, null);
@@ -1796,6 +1900,34 @@ public class ModelSequencer {
     }
   }
   
+  public void defineStateExitSequence(final NamedElement s) {
+    if ((s instanceof FinalState)) {
+      _defineStateExitSequence((FinalState)s);
+    } else if ((s instanceof State)) {
+      _defineStateExitSequence((State)s);
+    } else if ((s instanceof Region)) {
+      _defineStateExitSequence((Region)s);
+    } else if ((s instanceof Vertex)) {
+      _defineStateExitSequence((Vertex)s);
+    } else {
+      throw new IllegalArgumentException("Unhandled parameter types: " +
+        java.util.Arrays.<Object>asList(s).toString());
+    }
+  }
+  
+  public boolean isLeaf(final RegularState s) {
+    if ((s instanceof FinalState)) {
+      return _isLeaf((FinalState)s);
+    } else if ((s instanceof State)) {
+      return _isLeaf((State)s);
+    } else if ((s instanceof RegularState)) {
+      return _isLeaf((RegularState)s);
+    } else {
+      throw new IllegalArgumentException("Unhandled parameter types: " +
+        java.util.Arrays.<Object>asList(s).toString());
+    }
+  }
+  
   public Declaration replaced(final Declaration ed) {
     if ((ed instanceof TimeEvent)) {
       return _replaced((TimeEvent)ed);

+ 10 - 0
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/Assert.java

@@ -49,6 +49,16 @@ public class Assert {
 	}
 
 
+	public static Sequence assertedSequence(Step step) {
+
+		assertNotNull("Step is null", step);
+		assertTrue("Step is no Sequence (was " + step.getClass().getName() +")", step instanceof Sequence);
+
+		return (Sequence) step;
+	}
+
+
+
 	public static void assertStateSwitch(Step step, ExecutionState ... states ) {
 		
 		assertNotNull("Step is null", step);

+ 87 - 11
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/ModelSequencerStateTest.java

@@ -13,6 +13,7 @@ import org.yakindu.sct.model.sexec.ExitState;
 import org.yakindu.sct.model.sexec.If;
 import org.yakindu.sct.model.sexec.Reaction;
 import org.yakindu.sct.model.sexec.Sequence;
+import org.yakindu.sct.model.sexec.Step;
 import org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil.MinimalTSC;
 import org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil.OrthogonalFlatTSC;
 import org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil.SimpleFlatTSC;
@@ -243,7 +244,7 @@ public class ModelSequencerStateTest extends ModelSequencerTest {
 	
 	/**
 	 * A composite state must have a exit sequence. 
-	 * This exit sequence consists of an exit action call and a exit sequence call for each sub region.
+	 * This exit sequence consists of an exit action call and a state switch for all final states.
 	 */
 	@Test public void testCompositeStateExitSequence() {
 		Statechart sc = _createStatechart("cs"); {
@@ -294,23 +295,98 @@ public class ModelSequencerStateTest extends ModelSequencerTest {
 		
 		assertNotNull(_s1.getExitAction());
 		assertNotNull(_s1.getExitSequence());
-		assertEquals(3, _s1.getExitSequence().getSteps().size());
+		assertEquals(2, _s1.getExitSequence().getSteps().size());
 		
-		assertStateSwitch(_s1.getExitSequence().getSteps().get(0), _s2, _s3);
-		assertCall( assertedStateCase(_s1.getExitSequence().getSteps().get(0), _s2).getStep(), _s2.getExitSequence());
-		assertCall( assertedStateCase(_s1.getExitSequence().getSteps().get(0), _s3).getStep(), _s3.getExitSequence());
+		Step _switch =  _s1.getExitSequence().getSteps().get(0);
+		assertStateSwitch(_switch, _s2, _s3, _s4, _s5, _s6);
+		assertCall( assertedSequence(assertedStateCase(_switch, _s2).getStep()), 0, _s2.getExitSequence());
+		assertCall( assertedSequence(assertedStateCase(_switch, _s3).getStep()), 0, _s3.getExitSequence());
+		assertCall( assertedSequence(assertedStateCase(_switch, _s4).getStep()), 0, _s4.getExitSequence());
+		assertCall( assertedSequence(assertedStateCase(_switch, _s5).getStep()), 0, _s5.getExitSequence());
+		assertCall( assertedSequence(assertedStateCase(_switch, _s6).getStep()), 0, _s6.getExitSequence());
+
+		assertCall(_s1.getExitSequence(), 1, _s1.getExitAction());
+	}
+
+
+	
+	
+	/**
+	 * A composite state must have a exit sequence. 
+	 * This exit sequence consists of an exit action call and a state switch for all final states.
+	 */
+	@Test public void testCompositeStateExitSequence_Deep() {
 		
-		assertStateSwitch(_s1.getExitSequence().getSteps().get(1), _s4, _s5, _s6);
-		assertCall( assertedStateCase(_s1.getExitSequence().getSteps().get(1), _s4).getStep(), _s4.getExitSequence());
-		assertCall( assertedStateCase(_s1.getExitSequence().getSteps().get(1), _s5).getStep(), _s5.getExitSequence());
-		assertCall( assertedStateCase(_s1.getExitSequence().getSteps().get(1), _s6).getStep(), _s6.getExitSequence());
+		Statechart sc = _createStatechart("sc"); {  
+			
+			InterfaceScope s_scope = _createInterfaceScope("Interface", sc);
+			VariableDefinition v1 = _createVariableDefinition("v1", Type.INTEGER, s_scope);
+			EventDefinition e1 = _createEventDefinition("e1", s_scope);
+			
 
-		assertCall(_s1.getExitSequence(), 2, _s1.getExitAction());
+			Region r = _createRegion("r", sc); {
+				State s1 = _createState("s1", r); {
+					_createExitAssignment(v1, s1,  1);
 
-	}
+					Region r_s1 = _createRegion("r", s1); {
+						State s3 = _createState("s3", r_s1); {
+							_createExitAssignment(v1, s3, 2);
+							
+							Region r_s3 = _createRegion("r", s3); {
+								State s4 = _createState("s4", r_s3);
+								_createExitAssignment(v1, s4, 3);
 
+								FinalState fs = _createFinalState(r_s3);
+
+							}
+						}
+					}
+				}		
+				State s2 = _createState("s2", r); {
+					Region r_s1 = _createRegion("r", s2); {
+						_createState("s6", r_s1);
+					}
+				}
+			}
+
+		}
+		
+
+		ExecutionFlow flow = sequencer.transform(sc);
+		 
+		
+		ExecutionState _s1 = flow.getStates().get(0);
+		assertEquals("sc.r.s1", _s1.getName());
+
+		ExecutionState _s3 = flow.getStates().get(1);
+		assertEquals("sc.r.s1.r.s3", _s3.getName());
+
+		ExecutionState _s4 = flow.getStates().get(2);
+		assertEquals("sc.r.s1.r.s3.r.s4", _s4.getName());
+		
+		ExecutionState _fs = flow.getStates().get(3);
+		assertEquals("sc.r.s1.r.s3.r._final_", _fs.getName());
+		
+		ExecutionState _s6 = flow.getStates().get(5);
+		assertEquals("sc.r.s2.r.s6", _s6.getName());
+		
+		assertNull(_fs.getEntryAction());
+		assertNull(_fs.getExitAction());
+		assertNotNull(_fs.getExitSequence());
+		assertEquals(2, _s1.getExitSequence().getSteps().size());
+		
+		Step _switch =  _s1.getExitSequence().getSteps().get(0);
+		assertStateSwitch(_switch, _s4, _fs);
+		assertCall( assertedSequence(assertedStateCase(_switch, _s4).getStep()), 0, _s4.getExitSequence());
+		assertCall( assertedSequence(assertedStateCase(_switch, _s4).getStep()), 1, _s3.getExitAction());
+		assertCall( assertedSequence(assertedStateCase(_switch, _fs).getStep()), 0, _fs.getExitSequence());
+		assertCall( assertedSequence(assertedStateCase(_switch, _fs).getStep()), 1, _s3.getExitAction());
+
+		assertCall(_s1.getExitSequence(), 1, _s1.getExitAction());
 
 	
+	}
+
 
 	@Test public void testStateReaction_SimpleFlatTSC() {
 		SimpleFlatTSC tsc = new SimpleFlatTSC();