Browse Source

process entry of orthogonal sibling regions that are on the entry path of a teransition ( YAKHMI-442 )

terfloth@itemis.de 14 years ago
parent
commit
572c261a7c

+ 77 - 10
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/ModelSequencer.xtend

@@ -346,25 +346,89 @@ class ModelSequencer {
 		
 
 		// define entry behavior of the transition
+		
+		// first process all composite states on the path to the target state in top-down-order
 		t.entryStates().reverse.fold(sequence, [seq, state | {
 			if (state != t.target) { // since we call the entry sequence of the target state we have to exclude it here
+			
+				// in the case of orthogonal states we also have to enter sibling states.
+				val siblingRegions = state.parentRegion.composite.regions
+				
+				if (state.parentRegion != t.source.parentRegion) {
+					// process higher order sibling regions
+					for ( region : siblingRegions.take(siblingRegions.indexOf(state.parentRegion)) ) {
+						seq.addEnterRegion(region)
+					} 
+				}
+				
+				// perform entry on the transition path 			
 				if (state.create.entryAction != null) seq.steps.add(state.create.entryAction.newCall)
 				if ( _addTraceSteps ) seq.steps += newTraceStateEntered(state.create)
+				
 			}
 			seq
 		}])
 		
-		if (t.target != null ) 
+		// second process the target state entry behavior
+		if (t.target != null ) {
+
+			// in the case of orthogonal states we also have to enter sibling states.
+			val siblingRegions = t.target.parentRegion.composite.regions
+			
+			if (t.target.parentRegion != t.source.parentRegion) {
+				// process higher order sibling regions
+				for ( region : siblingRegions.take(siblingRegions.indexOf(t.target.parentRegion)) ) {
+					sequence.addEnterRegion(region)
+				} 	
+			}
+			
+			// perform entry on the transition path 			
 			if ( t.target instanceof RegularState) {
 				sequence.steps.add((t.target as RegularState).create.enterSequence.newCall )	
 			} else if ( t.target instanceof Choice ) {
 				sequence.steps.add((t.target as Choice).create.reactSequence.newCall )	
 			}
+				
+			if (t.target.parentRegion != t.source.parentRegion) {
+				// process lower order sibling regions 
+				for ( region : siblingRegions.drop(siblingRegions.indexOf(t.target.parentRegion)+1) ) {
+					sequence.addEnterRegion(region)
+				} 	
+			}
+		}
+		
+		
+		// third - process all entry behavior that has to be executed after the target state behavior in bottom-up-order
+		t.entryStates().fold(sequence, [seq, state | {
+			if (state != t.target) { // since we call the entry sequence of the target state we have to exclude it here
+			
+				// in the case of orthogonal states we also have to enter sibling states.
+				val siblingRegions = state.parentRegion.composite.regions
+				
+				if (state.parentRegion != t.source.parentRegion) {
+					// process lower order sibling regions 
+					for ( region : siblingRegions.drop(siblingRegions.indexOf(state.parentRegion)+1) ) {
+						seq.addEnterRegion(region)
+					} 				
+				}
+			}
+			seq
+		}])
+		
 			
 		return sequence
 	}	
 	
 	
+	
+	def addEnterRegion(Sequence seq, Region r) {
+		val entryState = r.entry?.target?.create
+					
+		if (entryState != null && entryState.enterSequence != null) 
+				seq.steps.add(entryState.enterSequence.newCall);
+	}
+
+
 	def newTraceReactionFired(Reaction r) {
 		val rf = sexecFactory.createReactionFired
 		rf.reaction = r
@@ -859,10 +923,11 @@ class ModelSequencer {
 			for ( r : state.regions ) {
 				defineStateEnterSequence(r)
 				
-				val entryState = r.entry?.target?.create
-				
-				if (entryState != null && entryState.enterSequence != null) 
-					seq.steps.add(entryState.enterSequence.newCall);
+				seq.addEnterRegion(r)
+//				val entryState = r.entry?.target?.create
+//				
+//				if (entryState != null && entryState.enterSequence != null) 
+//					seq.steps.add(entryState.enterSequence.newCall);
 			} 
 		}
 
@@ -879,7 +944,7 @@ class ModelSequencer {
 		// iterate over all regions
 		for ( r : sc.regions) defineStateExitSequence(r)
 	}
-	
+		
 
 	def dispatch void defineStateExitSequence(Region r) {
 		
@@ -1021,10 +1086,12 @@ class ModelSequencer {
 		enterSequence.comment = "Default enter sequence for statechart " + sc.name
 		
 		for ( r : sc.regions) {
-			if ( r.entry?.target != null) {
-				val step = r.entry?.target?.create.enterSequence.newCall
-				if (step != null) enterSequence.steps.add(step);
-			}
+			enterSequence.addEnterRegion(r)
+			
+//			if ( r.entry?.target != null) {
+//				val step = r.entry?.target?.create.enterSequence.newCall
+//				if (step != null) enterSequence.steps.add(step);
+//			}
 		} 
 		
 		flow.enterSequence = enterSequence

+ 138 - 57
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/ModelSequencer.java

@@ -49,6 +49,7 @@ import org.yakindu.sct.model.sexec.UnscheduleTimeEvent;
 import org.yakindu.sct.model.sexec.transformation.FactoryExtension;
 import org.yakindu.sct.model.sexec.transformation.StatechartExtensions;
 import org.yakindu.sct.model.sgraph.Choice;
+import org.yakindu.sct.model.sgraph.CompositeElement;
 import org.yakindu.sct.model.sgraph.Declaration;
 import org.yakindu.sct.model.sgraph.Effect;
 import org.yakindu.sct.model.sgraph.Entry;
@@ -597,10 +598,26 @@ public class ModelSequencer {
               boolean _operator_notEquals_4 = ObjectExtensions.operator_notEquals(state_1, _target);
               if (_operator_notEquals_4) {
                 {
+                  Region _parentRegion = state_1.getParentRegion();
+                  CompositeElement _composite = _parentRegion.getComposite();
+                  EList<Region> _regions = _composite.getRegions();
+                  final EList<Region> siblingRegions = _regions;
+                  Region _parentRegion_1 = state_1.getParentRegion();
+                  Vertex _source_4 = t.getSource();
+                  Region _parentRegion_2 = _source_4.getParentRegion();
+                  boolean _operator_notEquals_5 = ObjectExtensions.operator_notEquals(_parentRegion_1, _parentRegion_2);
+                  if (_operator_notEquals_5) {
+                    Region _parentRegion_3 = state_1.getParentRegion();
+                    int _indexOf = siblingRegions.indexOf(_parentRegion_3);
+                    Iterable<Region> _take = IterableExtensions.<Region>take(siblingRegions, _indexOf);
+                    for (Region region : _take) {
+                      ModelSequencer.this.addEnterRegion(seq_1, region);
+                    }
+                  }
                   ExecutionState _create_4 = ModelSequencer.this.factory.create(state_1);
                   Step _entryAction = _create_4.getEntryAction();
-                  boolean _operator_notEquals_5 = ObjectExtensions.operator_notEquals(_entryAction, null);
-                  if (_operator_notEquals_5) {
+                  boolean _operator_notEquals_6 = ObjectExtensions.operator_notEquals(_entryAction, null);
+                  if (_operator_notEquals_6) {
                     EList<Step> _steps_5 = seq_1.getSteps();
                     ExecutionState _create_5 = ModelSequencer.this.factory.create(state_1);
                     Step _entryAction_1 = _create_5.getEntryAction();
@@ -622,32 +639,131 @@ public class ModelSequencer {
         };
       IterableExtensions.<State, Sequence>fold(_reverse, sequence, _function_1);
       Vertex _target_1 = t.getTarget();
-      boolean _operator_notEquals_6 = ObjectExtensions.operator_notEquals(_target_1, null);
-      if (_operator_notEquals_6) {
-        Vertex _target_2 = t.getTarget();
-        if ((_target_2 instanceof org.yakindu.sct.model.sgraph.RegularState)) {
-          EList<Step> _steps_7 = sequence.getSteps();
+      boolean _operator_notEquals_7 = ObjectExtensions.operator_notEquals(_target_1, null);
+      if (_operator_notEquals_7) {
+        {
+          Vertex _target_2 = t.getTarget();
+          Region _parentRegion_4 = _target_2.getParentRegion();
+          CompositeElement _composite_1 = _parentRegion_4.getComposite();
+          EList<Region> _regions_1 = _composite_1.getRegions();
+          final EList<Region> siblingRegions_1 = _regions_1;
           Vertex _target_3 = t.getTarget();
-          ExecutionState _create_7 = this.factory.create(((RegularState) _target_3));
-          Sequence _enterSequence = _create_7.getEnterSequence();
-          Call _newCall_3 = this.factory.newCall(_enterSequence);
-          _steps_7.add(_newCall_3);
-        } else {
-          Vertex _target_4 = t.getTarget();
-          if ((_target_4 instanceof org.yakindu.sct.model.sgraph.Choice)) {
-            EList<Step> _steps_8 = sequence.getSteps();
-            Vertex _target_5 = t.getTarget();
-            ExecutionChoice _create_8 = this.factory.create(((Choice) _target_5));
-            Sequence _reactSequence = _create_8.getReactSequence();
-            Call _newCall_4 = this.factory.newCall(_reactSequence);
-            _steps_8.add(_newCall_4);
+          Region _parentRegion_5 = _target_3.getParentRegion();
+          Vertex _source_5 = t.getSource();
+          Region _parentRegion_6 = _source_5.getParentRegion();
+          boolean _operator_notEquals_8 = ObjectExtensions.operator_notEquals(_parentRegion_5, _parentRegion_6);
+          if (_operator_notEquals_8) {
+            Vertex _target_4 = t.getTarget();
+            Region _parentRegion_7 = _target_4.getParentRegion();
+            int _indexOf_1 = siblingRegions_1.indexOf(_parentRegion_7);
+            Iterable<Region> _take_1 = IterableExtensions.<Region>take(siblingRegions_1, _indexOf_1);
+            for (Region region_1 : _take_1) {
+              this.addEnterRegion(sequence, region_1);
+            }
+          }
+          Vertex _target_5 = t.getTarget();
+          if ((_target_5 instanceof org.yakindu.sct.model.sgraph.RegularState)) {
+            EList<Step> _steps_7 = sequence.getSteps();
+            Vertex _target_6 = t.getTarget();
+            ExecutionState _create_7 = this.factory.create(((RegularState) _target_6));
+            Sequence _enterSequence = _create_7.getEnterSequence();
+            Call _newCall_3 = this.factory.newCall(_enterSequence);
+            _steps_7.add(_newCall_3);
+          } else {
+            Vertex _target_7 = t.getTarget();
+            if ((_target_7 instanceof org.yakindu.sct.model.sgraph.Choice)) {
+              EList<Step> _steps_8 = sequence.getSteps();
+              Vertex _target_8 = t.getTarget();
+              ExecutionChoice _create_8 = this.factory.create(((Choice) _target_8));
+              Sequence _reactSequence = _create_8.getReactSequence();
+              Call _newCall_4 = this.factory.newCall(_reactSequence);
+              _steps_8.add(_newCall_4);
+            }
+          }
+          Vertex _target_9 = t.getTarget();
+          Region _parentRegion_8 = _target_9.getParentRegion();
+          Vertex _source_6 = t.getSource();
+          Region _parentRegion_9 = _source_6.getParentRegion();
+          boolean _operator_notEquals_9 = ObjectExtensions.operator_notEquals(_parentRegion_8, _parentRegion_9);
+          if (_operator_notEquals_9) {
+            Vertex _target_10 = t.getTarget();
+            Region _parentRegion_10 = _target_10.getParentRegion();
+            int _indexOf_2 = siblingRegions_1.indexOf(_parentRegion_10);
+            int _operator_plus = IntegerExtensions.operator_plus(((Integer)_indexOf_2), ((Integer)1));
+            Iterable<Region> _drop = IterableExtensions.<Region>drop(siblingRegions_1, _operator_plus);
+            for (Region region_2 : _drop) {
+              this.addEnterRegion(sequence, region_2);
+            }
           }
         }
       }
+      List<State> _entryStates_1 = this.entryStates(t);
+      final Function2<Sequence,State,Sequence> _function_2 = new Function2<Sequence,State,Sequence>() {
+          public Sequence apply(final Sequence seq_2 , final State state_2) {
+            Sequence _xblockexpression_2 = null;
+            {
+              Vertex _target_11 = t.getTarget();
+              boolean _operator_notEquals_10 = ObjectExtensions.operator_notEquals(state_2, _target_11);
+              if (_operator_notEquals_10) {
+                {
+                  Region _parentRegion_11 = state_2.getParentRegion();
+                  CompositeElement _composite_2 = _parentRegion_11.getComposite();
+                  EList<Region> _regions_2 = _composite_2.getRegions();
+                  final EList<Region> siblingRegions_2 = _regions_2;
+                  Region _parentRegion_12 = state_2.getParentRegion();
+                  Vertex _source_7 = t.getSource();
+                  Region _parentRegion_13 = _source_7.getParentRegion();
+                  boolean _operator_notEquals_11 = ObjectExtensions.operator_notEquals(_parentRegion_12, _parentRegion_13);
+                  if (_operator_notEquals_11) {
+                    Region _parentRegion_14 = state_2.getParentRegion();
+                    int _indexOf_3 = siblingRegions_2.indexOf(_parentRegion_14);
+                    int _operator_plus_1 = IntegerExtensions.operator_plus(((Integer)_indexOf_3), ((Integer)1));
+                    Iterable<Region> _drop_1 = IterableExtensions.<Region>drop(siblingRegions_2, _operator_plus_1);
+                    for (Region region_3 : _drop_1) {
+                      ModelSequencer.this.addEnterRegion(seq_2, region_3);
+                    }
+                  }
+                }
+              }
+              _xblockexpression_2 = (seq_2);
+            }
+            return _xblockexpression_2;
+          }
+        };
+      IterableExtensions.<State, Sequence>fold(_entryStates_1, sequence, _function_2);
       return sequence;
     }
   }
   
+  public Boolean addEnterRegion(final Sequence seq, final Region r) {
+    Boolean _xblockexpression = null;
+    {
+      Entry _entry = this.entry(r);
+      State _target = this==null?(State)null:this.target(_entry);
+      ExecutionState _create = this.factory==null?(ExecutionState)null:this.factory.create(_target);
+      final ExecutionState entryState = _create;
+      Boolean _xifexpression = null;
+      boolean _operator_and = false;
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(entryState, null);
+      if (!_operator_notEquals) {
+        _operator_and = false;
+      } else {
+        Sequence _enterSequence = entryState.getEnterSequence();
+        boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_enterSequence, null);
+        _operator_and = BooleanExtensions.operator_and(_operator_notEquals, _operator_notEquals_1);
+      }
+      if (_operator_and) {
+        EList<Step> _steps = seq.getSteps();
+        Sequence _enterSequence_1 = entryState.getEnterSequence();
+        Call _newCall = this.factory.newCall(_enterSequence_1);
+        boolean _add = _steps.add(_newCall);
+        _xifexpression = _add;
+      }
+      _xblockexpression = (_xifexpression);
+    }
+    return _xblockexpression;
+  }
+  
   public ReactionFired newTraceReactionFired(final Reaction r) {
     ReactionFired _xblockexpression = null;
     {
@@ -1697,25 +1813,7 @@ public class ModelSequencer {
         for (Region r : _regions) {
           {
             this.defineStateEnterSequence(r);
-            Entry _entry = this.entry(r);
-            State _target = this==null?(State)null:this.target(_entry);
-            ExecutionState _create_1 = this.factory==null?(ExecutionState)null:this.factory.create(_target);
-            final ExecutionState entryState = _create_1;
-            boolean _operator_and = false;
-            boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(entryState, null);
-            if (!_operator_notEquals_1) {
-              _operator_and = false;
-            } else {
-              Sequence _enterSequence = entryState.getEnterSequence();
-              boolean _operator_notEquals_2 = ObjectExtensions.operator_notEquals(_enterSequence, null);
-              _operator_and = BooleanExtensions.operator_and(_operator_notEquals_1, _operator_notEquals_2);
-            }
-            if (_operator_and) {
-              EList<Step> _steps_3 = seq.getSteps();
-              Sequence _enterSequence_1 = entryState.getEnterSequence();
-              Call _newCall_1 = this.factory.newCall(_enterSequence_1);
-              _steps_3.add(_newCall_1);
-            }
+            this.addEnterRegion(seq, r);
           }
         }
       }
@@ -1988,24 +2086,7 @@ public class ModelSequencer {
       enterSequence.setComment(_operator_plus);
       EList<Region> _regions = sc.getRegions();
       for (Region r : _regions) {
-        Entry _entry = this.entry(r);
-        State _target = this==null?(State)null:this.target(_entry);
-        boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_target, null);
-        if (_operator_notEquals) {
-          {
-            Entry _entry_1 = this.entry(r);
-            State _target_1 = this==null?(State)null:this.target(_entry_1);
-            ExecutionState _create = this.factory==null?(ExecutionState)null:this.factory.create(_target_1);
-            Sequence _enterSequence = _create.getEnterSequence();
-            Call _newCall = this.factory.newCall(_enterSequence);
-            final Call step = _newCall;
-            boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(step, null);
-            if (_operator_notEquals_1) {
-              EList<Step> _steps = enterSequence.getSteps();
-              _steps.add(step);
-            }
-          }
-        }
+        this.addEnterRegion(enterSequence, r);
       }
       flow.setEnterSequence(enterSequence);
       return enterSequence;

+ 1 - 0
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/AllTests.java

@@ -11,6 +11,7 @@ import org.junit.runners.Suite.SuiteClasses;
 	ModelSequencerStateTest.class,
 	ModelSequencerStateReactionTest.class,
 	ModelSequencerHierarchyTest.class,
+	ModelSequencerOrthogonalityTest.class,
 	ModelSequencerStateVectorTest.class})
 public class AllTests {
 	

+ 405 - 0
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/ModelSequencerOrthogonalityTest.java

@@ -0,0 +1,405 @@
+package org.yakindu.sct.model.sexec.transformation.test;
+
+import static org.junit.Assert.*;
+import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil.*;
+
+import org.junit.Test;
+import org.yakindu.sct.model.sexec.ExecutionFlow;
+import org.yakindu.sct.model.sexec.ExecutionState;
+import org.yakindu.sct.model.sexec.Reaction;
+import org.yakindu.sct.model.sexec.Sequence;
+import org.yakindu.sct.model.sgraph.Entry;
+import org.yakindu.sct.model.sgraph.EntryKind;
+import org.yakindu.sct.model.sgraph.Region;
+import org.yakindu.sct.model.sgraph.State;
+import org.yakindu.sct.model.sgraph.Statechart;
+import org.yakindu.sct.model.stext.stext.InterfaceScope;
+import org.yakindu.sct.model.stext.stext.VariableDefinition;
+
+ 
+public class ModelSequencerOrthogonalityTest extends ModelSequencerTest {
+
+
+	/**
+	 * The entry sequence of an and state must perform a entry for all sub regions. 
+	 */
+	@Test public void testAndStateEntry() {
+		
+		Statechart sc = _createStatechart("sc"); {  
+			
+			Region r = _createRegion("r", sc); {
+				Entry r_entry = _createEntry(EntryKind.INITIAL, null, r);
+				State s1 = _createState("s1", r); {
+
+					Region r2 = _createRegion("r2", s1); {
+						Entry r2_entry = _createEntry(EntryKind.INITIAL, null, r2);
+						State s2 = _createState("s2", r2);
+						_createTransition(r2_entry, s2);
+					}
+							
+					Region r3 = _createRegion("r3", s1); {
+						Entry r3_entry = _createEntry(EntryKind.INITIAL, null, r3);
+						State s3 = _createState("s3", r3);
+						_createTransition(r3_entry, s3);
+					}
+				}		
+				_createTransition(r_entry, s1);
+			}
+		}
+			
+		ExecutionFlow flow = sequencer.transform(sc);
+		
+		
+		ExecutionState _s1 = flow.getStates().get(0);
+		assertEquals("sc.r.s1", _s1.getName());
+
+		Sequence s1EnterSeq = _s1.getEnterSequence();
+		assertNotNull(s1EnterSeq);
+		assertEquals(2, s1EnterSeq.getSteps().size());
+
+		assertCall(s1EnterSeq, 0, flow.getStates().get(1)
+				.getEnterSequence());
+		assertCall(s1EnterSeq, 1, flow.getStates().get(2)
+				.getEnterSequence());
+		
+	}
+	
+	
+	/**
+	 * The transition to a leaf state with orthogonal siblings must invoke the entry sequence of the orthogonal sibling regions. 
+	 */
+	@Test public void testSiblingRegionEntryOnTargetState() {
+		
+		Statechart sc = _createStatechart("sc"); {  
+			
+			InterfaceScope s_scope = _createInterfaceScope("Interface", sc);
+			VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, s_scope);
+
+			Region r = _createRegion("r", sc); {
+				Entry r_entry = _createEntry(EntryKind.INITIAL, null, r);
+				State s1 = _createState("s1", r); {
+
+					Region r2 = _createRegion("r2", s1); {
+						Entry r2_entry = _createEntry(EntryKind.INITIAL, null, r2);
+						State s2 = _createState("s2", r2);
+						_createTransition(r2_entry, s2);
+					}
+							
+					Region r3 = _createRegion("r3", s1); {
+						Entry r3_entry = _createEntry(EntryKind.INITIAL, null, r3);
+						State s3 = _createState("s3", r3);
+						_createTransition(r3_entry, s3);
+					}
+
+					Region r4 = _createRegion("r4", s1); {
+						Entry r4_entry = _createEntry(EntryKind.INITIAL, null, r4);
+						State s4 = _createState("s4", r4);
+						_createTransition(r4_entry, s4);
+					}
+				}		
+				_createTransition(r_entry, s1);
+				State s5 = _createState("s5", r);
+				_createTransition(s5, findState(sc, "s3"));
+			}
+		}
+			
+		ExecutionFlow flow = sequencer.transform(sc);
+		
+		ExecutionState _s2 = flow.getStates().get(1);
+		assertEquals("sc.r.s1.r2.s2", _s2.getName());
+		ExecutionState _s3 = flow.getStates().get(2);
+		assertEquals("sc.r.s1.r3.s3", _s3.getName());
+		ExecutionState _s4 = flow.getStates().get(3);
+		assertEquals("sc.r.s1.r4.s4", _s4.getName());
+		ExecutionState _s5 = flow.getStates().get(4);
+		assertEquals("sc.r.s5", _s5.getName());
+
+		
+		Reaction _t = _s5.getReactions().get(0);
+		assertTrue(_t.isTransition());
+		
+		Sequence _effect = (Sequence) _t.getEffect();
+		assertEquals(4, _effect.getSteps().size());
+		
+		assertCall(_effect, 0, _s5.getExitSequence());
+		assertCall(_effect, 1, _s2.getEnterSequence());
+		assertCall(_effect, 2, _s3.getEnterSequence());
+		assertCall(_effect, 3, _s4.getEnterSequence());
+	}
+	
+	
+	/**
+	 * For all and-states that a on the entry path of a transition the enter sequences for all orthogonal parts must be called.
+	 */
+	@Test public void testSiblingRegionEntryOnComposite() {
+		
+		Statechart sc = _createStatechart("sc"); {  
+			
+			InterfaceScope s_scope = _createInterfaceScope("Interface", sc);
+			VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, s_scope);
+
+			Region r = _createRegion("r", sc); {
+				Entry r_entry = _createEntry(EntryKind.INITIAL, null, r);
+				State s1 = _createState("s1", r); {
+
+					Region r2 = _createRegion("r2", s1); {
+						Entry r2_entry = _createEntry(EntryKind.INITIAL, null, r2);
+						State s2 = _createState("s2", r2);
+						_createTransition(r2_entry, s2);
+					}
+							
+					Region r3 = _createRegion("r3", s1); {
+						Entry r3_entry = _createEntry(EntryKind.INITIAL, null, r3);
+						State s3 = _createState("s3", r3); {
+							Region r3a = _createRegion("r3a", s3); {
+								Entry r3a_entry = _createEntry(EntryKind.INITIAL, null, r3a);
+								State s3a = _createState("s3a", r3a);
+								_createTransition(r3a_entry, s3a);
+							}
+							Region r3b = _createRegion("r3b", s3); {
+								Entry r3b_entry = _createEntry(EntryKind.INITIAL, null, r3b);
+								State s3b = _createState("s3b", r3b);
+								_createTransition(r3b_entry, s3b);
+							}
+							Region r3c = _createRegion("r3c", s3); {
+								Entry r3c_entry = _createEntry(EntryKind.INITIAL, null, r3c);
+								State s3c = _createState("s3c", r3c);
+								_createTransition(r3c_entry, s3c);
+							}
+						}
+						_createEntryAssignment(v1, s3, 42);
+						_createTransition(r3_entry, s3);					
+					}
+
+					Region r4 = _createRegion("r4", s1); {
+						Entry r4_entry = _createEntry(EntryKind.INITIAL, null, r4);
+						State s4 = _createState("s4", r4);
+						_createTransition(r4_entry, s4);
+					}
+				}		
+				_createTransition(r_entry, s1);
+				State s5 = _createState("s5", r);
+				
+				_createTransition(s5, findState(sc, "s3b"));
+			}
+		}
+			
+		ExecutionFlow flow = sequencer.transform(sc);
+		
+		ExecutionState _s2 = flow.getStates().get(1);
+		assertEquals("sc.r.s1.r2.s2", _s2.getName());
+		ExecutionState _s3 = flow.getStates().get(2);
+		assertEquals("sc.r.s1.r3.s3", _s3.getName());
+		ExecutionState _s3a = flow.getStates().get(3);
+		assertEquals("sc.r.s1.r3.s3.r3a.s3a", _s3a.getName());
+		ExecutionState _s3b = flow.getStates().get(4);
+		assertEquals("sc.r.s1.r3.s3.r3b.s3b", _s3b.getName());
+		ExecutionState _s3c = flow.getStates().get(5);
+		assertEquals("sc.r.s1.r3.s3.r3c.s3c", _s3c.getName());
+		ExecutionState _s4 = flow.getStates().get(6);
+		assertEquals("sc.r.s1.r4.s4", _s4.getName());
+		ExecutionState _s5 = flow.getStates().get(7);
+		assertEquals("sc.r.s5", _s5.getName());
+
+		
+		Reaction _t = _s5.getReactions().get(0);
+		assertTrue(_t.isTransition());
+		
+		Sequence _effect = (Sequence) _t.getEffect();
+		assertEquals(7, _effect.getSteps().size());
+		
+		assertCall(_effect, 0, _s5.getExitSequence());
+		assertCall(_effect, 1, _s2.getEnterSequence());
+		assertCall(_effect, 2, _s3.getEntryAction());
+		assertCall(_effect, 3, _s3a.getEnterSequence());
+		assertCall(_effect, 4, _s3b.getEnterSequence());
+		assertCall(_effect, 5, _s3c.getEnterSequence());
+		assertCall(_effect, 6, _s4.getEnterSequence());
+	}
+	
+	
+
+	/**
+	 * Local transition within a region with orthogonal siblings does not have to invoke sibling region entries.
+	 */
+	@Test public void testSiblingStateTransition() {
+		
+		Statechart sc = _createStatechart("sc"); {  
+			
+			InterfaceScope s_scope = _createInterfaceScope("Interface", sc);
+			VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, s_scope);
+
+			Region r = _createRegion("r", sc); {
+				Entry r_entry = _createEntry(EntryKind.INITIAL, null, r);
+				State s1 = _createState("s1", r); {
+
+					Region r2 = _createRegion("r2", s1); {
+						Entry r2_entry = _createEntry(EntryKind.INITIAL, null, r2);
+						State s2 = _createState("s2", r2);
+						_createTransition(r2_entry, s2);
+					}
+							
+					Region r3 = _createRegion("r3", s1); {
+						Entry r3_entry = _createEntry(EntryKind.INITIAL, null, r3);
+						State s3 = _createState("s3", r3); {
+							Region r3a = _createRegion("r3a", s3); {
+								Entry r3a_entry = _createEntry(EntryKind.INITIAL, null, r3a);
+								State s3a = _createState("s3a", r3a);
+								_createTransition(r3a_entry, s3a);
+							}
+							Region r3b = _createRegion("r3b", s3); {
+								Entry r3b_entry = _createEntry(EntryKind.INITIAL, null, r3b);
+								State s3b = _createState("s3b", r3b);
+								State s3b2 = _createState("s3b2", r3b);
+								_createTransition(r3b_entry, s3b);
+							}
+							Region r3c = _createRegion("r3c", s3); {
+								Entry r3c_entry = _createEntry(EntryKind.INITIAL, null, r3c);
+								State s3c = _createState("s3c", r3c);
+								_createTransition(r3c_entry, s3c);
+							}
+						}
+						_createEntryAssignment(v1, s3, 42);
+						_createTransition(r3_entry, s3);					
+					}
+
+					Region r4 = _createRegion("r4", s1); {
+						Entry r4_entry = _createEntry(EntryKind.INITIAL, null, r4);
+						State s4 = _createState("s4", r4);
+						_createTransition(r4_entry, s4);
+					}
+				}		
+				_createTransition(r_entry, s1);
+				State s5 = _createState("s5", r);
+				
+				_createTransition(findState(sc, "s3b"), findState(sc, "s3b2"));
+			}
+		}
+			
+		ExecutionFlow flow = sequencer.transform(sc);
+		
+		ExecutionState _s2 = flow.getStates().get(1);
+		assertEquals("sc.r.s1.r2.s2", _s2.getName());
+		ExecutionState _s3 = flow.getStates().get(2);
+		assertEquals("sc.r.s1.r3.s3", _s3.getName());
+		ExecutionState _s3a = flow.getStates().get(3);
+		assertEquals("sc.r.s1.r3.s3.r3a.s3a", _s3a.getName());
+		ExecutionState _s3b = flow.getStates().get(4);
+		assertEquals("sc.r.s1.r3.s3.r3b.s3b", _s3b.getName());
+		ExecutionState _s3b2 = flow.getStates().get(5);
+		assertEquals("sc.r.s1.r3.s3.r3b.s3b2", _s3b2.getName());
+		ExecutionState _s3c = flow.getStates().get(6);
+		assertEquals("sc.r.s1.r3.s3.r3c.s3c", _s3c.getName());
+		ExecutionState _s4 = flow.getStates().get(7);
+		assertEquals("sc.r.s1.r4.s4", _s4.getName());
+		ExecutionState _s5 = flow.getStates().get(8);
+		assertEquals("sc.r.s5", _s5.getName());
+
+		
+		Reaction _t = _s3b.getReactions().get(0);
+		assertTrue(_t.isTransition());
+		
+		Sequence _effect = (Sequence) _t.getEffect();
+		assertEquals(2, _effect.getSteps().size());
+		
+		assertCall(_effect, 0, _s3b.getExitSequence());
+		assertCall(_effect, 1, _s3b2.getEnterSequence());
+	}
+	
+	/**
+	 * A transition from a state with orthogonal siblings that dives into a non orthogonal sibling state must exclude the source state sibling entry behavior.
+	 */
+	@Test public void testSourceSiblingExclusion() {
+		
+		Statechart sc = _createStatechart("sc"); {  
+			
+			InterfaceScope s_scope = _createInterfaceScope("Interface", sc);
+			VariableDefinition v1 = _createVariableDefinition("v1", TYPE_INTEGER, s_scope);
+
+			Region r = _createRegion("r", sc); {
+				Entry r_entry = _createEntry(EntryKind.INITIAL, null, r);
+				State s1 = _createState("s1", r); {
+
+					Region r2 = _createRegion("r2", s1); {
+						Entry r2_entry = _createEntry(EntryKind.INITIAL, null, r2);
+						State s2 = _createState("s2", r2);
+						_createTransition(r2_entry, s2);
+					}
+							
+					Region r3 = _createRegion("r3", s1); {
+						Entry r3_entry = _createEntry(EntryKind.INITIAL, null, r3);
+						State s3 = _createState("s3", r3); {
+							Region r3a = _createRegion("r3a", s3); {
+								Entry r3a_entry = _createEntry(EntryKind.INITIAL, null, r3a);
+								State s3a = _createState("s3a", r3a);
+								_createTransition(r3a_entry, s3a);
+							}
+							Region r3b = _createRegion("r3b", s3); {
+								Entry r3b_entry = _createEntry(EntryKind.INITIAL, null, r3b);
+								State s3b = _createState("s3b", r3b);
+								State s3b2 = _createState("s3b2", r3b);
+								_createTransition(r3b_entry, s3b);
+							}
+							Region r3c = _createRegion("r3c", s3); {
+								Entry r3c_entry = _createEntry(EntryKind.INITIAL, null, r3c);
+								State s3c = _createState("s3c", r3c);
+								_createTransition(r3c_entry, s3c);
+							}
+						}
+						State s3z = _createState("s3z", r3);
+						_createEntryAssignment(v1, s3, 42);
+						_createTransition(r3_entry, s3);					
+					}
+
+					Region r4 = _createRegion("r4", s1); {
+						Entry r4_entry = _createEntry(EntryKind.INITIAL, null, r4);
+						State s4 = _createState("s4", r4);
+						_createTransition(r4_entry, s4);
+					}
+				}		
+				_createTransition(r_entry, s1);
+				State s5 = _createState("s5", r);
+				
+				_createTransition(findState(sc, "s3z"), findState(sc, "s3b2"));
+			}
+		}
+			
+		ExecutionFlow flow = sequencer.transform(sc);
+		
+		ExecutionState _s2 = flow.getStates().get(1);
+		assertEquals("sc.r.s1.r2.s2", _s2.getName());
+		ExecutionState _s3 = flow.getStates().get(2);
+		assertEquals("sc.r.s1.r3.s3", _s3.getName());
+		ExecutionState _s3a = flow.getStates().get(3);
+		assertEquals("sc.r.s1.r3.s3.r3a.s3a", _s3a.getName());
+		ExecutionState _s3b = flow.getStates().get(4);
+		assertEquals("sc.r.s1.r3.s3.r3b.s3b", _s3b.getName());
+		ExecutionState _s3b2 = flow.getStates().get(5);
+		assertEquals("sc.r.s1.r3.s3.r3b.s3b2", _s3b2.getName());
+		ExecutionState _s3c = flow.getStates().get(6);
+		assertEquals("sc.r.s1.r3.s3.r3c.s3c", _s3c.getName());
+		ExecutionState _s3z = flow.getStates().get(7);
+		assertEquals("sc.r.s1.r3.s3z", _s3z.getName());
+		ExecutionState _s4 = flow.getStates().get(8);
+		assertEquals("sc.r.s1.r4.s4", _s4.getName());
+		ExecutionState _s5 = flow.getStates().get(9);
+		assertEquals("sc.r.s5", _s5.getName());
+
+		
+		Reaction _t = _s3z.getReactions().get(0);
+		assertTrue(_t.isTransition());
+		
+		Sequence _effect = (Sequence) _t.getEffect();
+		assertEquals(5, _effect.getSteps().size());
+		
+		assertCall(_effect, 0, _s3z.getExitSequence());
+		assertCall(_effect, 1, _s3.getEntryAction());
+		assertCall(_effect, 2, _s3a.getEnterSequence());
+		assertCall(_effect, 3, _s3b2.getEnterSequence());
+		assertCall(_effect, 4, _s3c.getEnterSequence());
+	}
+	
+
+
+
+}