Parcourir la source

Add local reactions to states in execution flow (task #109).

terfloth@itemis.de il y a 13 ans
Parent
commit
6cfa86e855
18 fichiers modifiés avec 863 ajouts et 99 suppressions
  1. 1 0
      plugins/org.yakindu.sct.model.sexec.edit/plugin.properties
  2. 28 0
      plugins/org.yakindu.sct.model.sexec.edit/src/org/yakindu/sct/model/sexec/provider/ReactionItemProvider.java
  3. 1 0
      plugins/org.yakindu.sct.model.sexec/model/sexec.ecore
  4. 27 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/Reaction.java
  5. 38 1
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/SexecPackage.java
  6. 68 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/impl/ReactionImpl.java
  7. 1 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/impl/SexecFactoryImpl.java
  8. 11 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/impl/SexecPackageImpl.java
  9. 7 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/FactoryExtension.xtend
  10. 63 19
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/ModelSequencer.xtend
  11. 29 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/StatechartExtensions.xtend
  12. 1 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/util/SexecAdapterFactory.java
  13. 1 0
      plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/util/SexecSwitch.java
  14. 36 10
      plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/FactoryExtension.java
  15. 202 60
      plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/ModelSequencer.java
  16. 70 1
      plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/StatechartExtensions.java
  17. 254 3
      test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/ModelSequencerTest.java
  18. 25 5
      test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/SCTTestUtil.java

+ 1 - 0
plugins/org.yakindu.sct.model.sexec.edit/plugin.properties

@@ -68,3 +68,4 @@ _UI_TimeEvent_periodic_feature = Periodic
 _UI_ScheduleTimeEvent_timeEvent_feature = Time Event
 _UI_ScheduleTimeEvent_timeValue_feature = Time Value
 _UI_UnscheduleTimeEvent_timeEvent_feature = Time Event
+_UI_Reaction_transition_feature = Transition

+ 28 - 0
plugins/org.yakindu.sct.model.sexec.edit/src/org/yakindu/sct/model/sexec/provider/ReactionItemProvider.java

@@ -13,12 +13,14 @@ import java.util.List;
 import org.eclipse.emf.common.notify.AdapterFactory;
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.edit.provider.ComposeableAdapterFactory;
 import org.eclipse.emf.edit.provider.IEditingDomainItemProvider;
 import org.eclipse.emf.edit.provider.IItemLabelProvider;
 import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
 import org.eclipse.emf.edit.provider.IItemPropertySource;
 import org.eclipse.emf.edit.provider.IStructuredItemContentProvider;
 import org.eclipse.emf.edit.provider.ITreeItemContentProvider;
+import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
 import org.eclipse.emf.edit.provider.ViewerNotification;
 import org.yakindu.sct.model.sexec.Reaction;
 import org.yakindu.sct.model.sexec.SexecFactory;
@@ -59,10 +61,33 @@ public class ReactionItemProvider
 		if (itemPropertyDescriptors == null) {
 			super.getPropertyDescriptors(object);
 
+			addTransitionPropertyDescriptor(object);
 		}
 		return itemPropertyDescriptors;
 	}
 
+	/**
+	 * This adds a property descriptor for the Transition feature.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	protected void addTransitionPropertyDescriptor(Object object) {
+		itemPropertyDescriptors.add
+			(createItemPropertyDescriptor
+				(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(),
+				 getResourceLocator(),
+				 getString("_UI_Reaction_transition_feature"),
+				 getString("_UI_PropertyDescriptor_description", "_UI_Reaction_transition_feature", "_UI_Reaction_type"),
+				 SexecPackage.Literals.REACTION__TRANSITION,
+				 true,
+				 false,
+				 false,
+				 ItemPropertyDescriptor.BOOLEAN_VALUE_IMAGE,
+				 null,
+				 null));
+	}
+
 	/**
 	 * This specifies how to implement {@link #getChildren} and is used to deduce an appropriate feature for an
 	 * {@link org.eclipse.emf.edit.command.AddCommand}, {@link org.eclipse.emf.edit.command.RemoveCommand} or
@@ -131,6 +156,9 @@ public class ReactionItemProvider
 		updateChildren(notification);
 
 		switch (notification.getFeatureID(Reaction.class)) {
+			case SexecPackage.REACTION__TRANSITION:
+				fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true));
+				return;
 			case SexecPackage.REACTION__CHECK:
 			case SexecPackage.REACTION__EFFECT:
 				fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), true, false));

+ 1 - 0
plugins/org.yakindu.sct.model.sexec/model/sexec.ecore

@@ -44,6 +44,7 @@
         containment="true"/>
     <eStructuralFeatures xsi:type="ecore:EReference" name="effect" eType="#//Step"
         containment="true"/>
+    <eStructuralFeatures xsi:type="ecore:EAttribute" name="transition" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EBoolean"/>
   </eClassifiers>
   <eClassifiers xsi:type="ecore:EClass" name="Step" abstract="true" eSuperTypes="#//NamedElement">
     <eStructuralFeatures xsi:type="ecore:EAttribute" name="comment" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>

+ 27 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/Reaction.java

@@ -17,6 +17,7 @@ package org.yakindu.sct.model.sexec;
  * <ul>
  *   <li>{@link org.yakindu.sct.model.sexec.Reaction#getCheck <em>Check</em>}</li>
  *   <li>{@link org.yakindu.sct.model.sexec.Reaction#getEffect <em>Effect</em>}</li>
+ *   <li>{@link org.yakindu.sct.model.sexec.Reaction#isTransition <em>Transition</em>}</li>
  * </ul>
  * </p>
  *
@@ -77,4 +78,30 @@ public interface Reaction extends NamedElement {
 	 */
 	void setEffect(Step value);
 
+	/**
+	 * Returns the value of the '<em><b>Transition</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>Transition</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>Transition</em>' attribute.
+	 * @see #setTransition(boolean)
+	 * @see org.yakindu.sct.model.sexec.SexecPackage#getReaction_Transition()
+	 * @model
+	 * @generated
+	 */
+	boolean isTransition();
+
+	/**
+	 * Sets the value of the '{@link org.yakindu.sct.model.sexec.Reaction#isTransition <em>Transition</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>Transition</em>' attribute.
+	 * @see #isTransition()
+	 * @generated
+	 */
+	void setTransition(boolean value);
+
 } // Reaction

+ 38 - 1
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/SexecPackage.java

@@ -79,6 +79,15 @@ public interface SexecPackage extends EPackage {
 	 */
 	int EXECUTION_FLOW__SCOPES = SGraphPackage.SCOPED_ELEMENT__SCOPES;
 
+	/**
+	 * The feature id for the '<em><b>Namespace</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int EXECUTION_FLOW__NAMESPACE = SGraphPackage.SCOPED_ELEMENT__NAMESPACE;
+
 	/**
 	 * The feature id for the '<em><b>Name</b></em>' attribute.
 	 * <!-- begin-user-doc -->
@@ -434,6 +443,15 @@ public interface SexecPackage extends EPackage {
 	 */
 	int REACTION__EFFECT = NAMED_ELEMENT_FEATURE_COUNT + 1;
 
+	/**
+	 * The feature id for the '<em><b>Transition</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int REACTION__TRANSITION = NAMED_ELEMENT_FEATURE_COUNT + 2;
+
 	/**
 	 * The number of structural features of the '<em>Reaction</em>' class.
 	 * <!-- begin-user-doc -->
@@ -441,7 +459,7 @@ public interface SexecPackage extends EPackage {
 	 * @generated
 	 * @ordered
 	 */
-	int REACTION_FEATURE_COUNT = NAMED_ELEMENT_FEATURE_COUNT + 2;
+	int REACTION_FEATURE_COUNT = NAMED_ELEMENT_FEATURE_COUNT + 3;
 
 	/**
 	 * The feature id for the '<em><b>Name</b></em>' attribute.
@@ -1105,6 +1123,17 @@ public interface SexecPackage extends EPackage {
 	 */
 	EReference getReaction_Effect();
 
+	/**
+	 * Returns the meta object for the attribute '{@link org.yakindu.sct.model.sexec.Reaction#isTransition <em>Transition</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>Transition</em>'.
+	 * @see org.yakindu.sct.model.sexec.Reaction#isTransition()
+	 * @see #getReaction()
+	 * @generated
+	 */
+	EAttribute getReaction_Transition();
+
 	/**
 	 * Returns the meta object for class '{@link org.yakindu.sct.model.sexec.NamedElement <em>Named Element</em>}'.
 	 * <!-- begin-user-doc -->
@@ -1601,6 +1630,14 @@ public interface SexecPackage extends EPackage {
 		 */
 		EReference REACTION__EFFECT = eINSTANCE.getReaction_Effect();
 
+		/**
+		 * The meta object literal for the '<em><b>Transition</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute REACTION__TRANSITION = eINSTANCE.getReaction_Transition();
+
 		/**
 		 * The meta object literal for the '{@link org.yakindu.sct.model.sexec.impl.NamedElementImpl <em>Named Element</em>}' class.
 		 * <!-- begin-user-doc -->

+ 68 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/impl/ReactionImpl.java

@@ -25,6 +25,7 @@ import org.yakindu.sct.model.sexec.Step;
  * <ul>
  *   <li>{@link org.yakindu.sct.model.sexec.impl.ReactionImpl#getCheck <em>Check</em>}</li>
  *   <li>{@link org.yakindu.sct.model.sexec.impl.ReactionImpl#getEffect <em>Effect</em>}</li>
+ *   <li>{@link org.yakindu.sct.model.sexec.impl.ReactionImpl#isTransition <em>Transition</em>}</li>
  * </ul>
  * </p>
  *
@@ -51,6 +52,26 @@ public class ReactionImpl extends NamedElementImpl implements Reaction {
 	 */
 	protected Step effect;
 
+	/**
+	 * The default value of the '{@link #isTransition() <em>Transition</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #isTransition()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final boolean TRANSITION_EDEFAULT = false;
+
+	/**
+	 * The cached value of the '{@link #isTransition() <em>Transition</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #isTransition()
+	 * @generated
+	 * @ordered
+	 */
+	protected boolean transition = TRANSITION_EDEFAULT;
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -156,6 +177,27 @@ public class ReactionImpl extends NamedElementImpl implements Reaction {
 			eNotify(new ENotificationImpl(this, Notification.SET, SexecPackage.REACTION__EFFECT, newEffect, newEffect));
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public boolean isTransition() {
+		return transition;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setTransition(boolean newTransition) {
+		boolean oldTransition = transition;
+		transition = newTransition;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, SexecPackage.REACTION__TRANSITION, oldTransition, transition));
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -184,6 +226,8 @@ public class ReactionImpl extends NamedElementImpl implements Reaction {
 				return getCheck();
 			case SexecPackage.REACTION__EFFECT:
 				return getEffect();
+			case SexecPackage.REACTION__TRANSITION:
+				return isTransition();
 		}
 		return super.eGet(featureID, resolve, coreType);
 	}
@@ -202,6 +246,9 @@ public class ReactionImpl extends NamedElementImpl implements Reaction {
 			case SexecPackage.REACTION__EFFECT:
 				setEffect((Step)newValue);
 				return;
+			case SexecPackage.REACTION__TRANSITION:
+				setTransition((Boolean)newValue);
+				return;
 		}
 		super.eSet(featureID, newValue);
 	}
@@ -220,6 +267,9 @@ public class ReactionImpl extends NamedElementImpl implements Reaction {
 			case SexecPackage.REACTION__EFFECT:
 				setEffect((Step)null);
 				return;
+			case SexecPackage.REACTION__TRANSITION:
+				setTransition(TRANSITION_EDEFAULT);
+				return;
 		}
 		super.eUnset(featureID);
 	}
@@ -236,8 +286,26 @@ public class ReactionImpl extends NamedElementImpl implements Reaction {
 				return check != null;
 			case SexecPackage.REACTION__EFFECT:
 				return effect != null;
+			case SexecPackage.REACTION__TRANSITION:
+				return transition != TRANSITION_EDEFAULT;
 		}
 		return super.eIsSet(featureID);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	@Override
+	public String toString() {
+		if (eIsProxy()) return super.toString();
+
+		StringBuffer result = new StringBuffer(super.toString());
+		result.append(" (transition: ");
+		result.append(transition);
+		result.append(')');
+		return result.toString();
+	}
+
 } //ReactionImpl

+ 1 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/impl/SexecFactoryImpl.java

@@ -11,6 +11,7 @@ import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.impl.EFactoryImpl;
 import org.eclipse.emf.ecore.plugin.EcorePlugin;
+import org.yakindu.sct.model.sexec.*;
 import org.yakindu.sct.model.sexec.Call;
 import org.yakindu.sct.model.sexec.Check;
 import org.yakindu.sct.model.sexec.CheckRef;

+ 11 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/impl/SexecPackageImpl.java

@@ -365,6 +365,15 @@ public class SexecPackageImpl extends EPackageImpl implements SexecPackage {
 		return (EReference)reactionEClass.getEStructuralFeatures().get(1);
 	}
 
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getReaction_Transition() {
+		return (EAttribute)reactionEClass.getEStructuralFeatures().get(2);
+	}
+
 	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -717,6 +726,7 @@ public class SexecPackageImpl extends EPackageImpl implements SexecPackage {
 		reactionEClass = createEClass(REACTION);
 		createEReference(reactionEClass, REACTION__CHECK);
 		createEReference(reactionEClass, REACTION__EFFECT);
+		createEAttribute(reactionEClass, REACTION__TRANSITION);
 
 		stepEClass = createEClass(STEP);
 		createEAttribute(stepEClass, STEP__COMMENT);
@@ -834,6 +844,7 @@ public class SexecPackageImpl extends EPackageImpl implements SexecPackage {
 		initEClass(reactionEClass, Reaction.class, "Reaction", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
 		initEReference(getReaction_Check(), this.getCheck(), null, "check", null, 0, 1, Reaction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 		initEReference(getReaction_Effect(), this.getStep(), null, "effect", null, 0, 1, Reaction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
+		initEAttribute(getReaction_Transition(), ecorePackage.getEBoolean(), "transition", null, 0, 1, Reaction.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
 
 		initEClass(stepEClass, Step.class, "Step", IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS);
 		initEAttribute(getStep_Comment(), ecorePackage.getEString(), "comment", null, 0, 1, Step.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);

+ 7 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/FactoryExtension.xtend

@@ -34,6 +34,7 @@ import org.yakindu.sct.model.sexec.TimeEvent
 import org.yakindu.sct.model.sexec.ScheduleTimeEvent
 import org.yakindu.sct.model.sgraph.Statement
 import org.yakindu.sct.model.sexec.UnscheduleTimeEvent
+import org.yakindu.sct.model.stext.stext.LocalReaction
 
 class FactoryExtension {
 	
@@ -69,6 +70,12 @@ class FactoryExtension {
 	
 	def Reaction create r : sexecFactory.createReaction create(Transition tr){
 		r.name = tr.id
+		r.transition = true
+	}
+	
+	def Reaction create r : sexecFactory.createReaction create(LocalReaction lr){
+		r.name = lr.id
+		r.transition = false
 	}
 	
 	def CheckRef newRef(Check check) {

+ 63 - 19
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/ModelSequencer.xtend

@@ -79,6 +79,7 @@ class ModelSequencer {
 		sc.mapStates(ef)
 		sc.mapTimeEvents(ef)
 		sc.mapTransitions(ef)
+		sc.mapLocalReactions(ef)
 		
 		// derive all additional information that is necessary for the execution
 		ef.defineStateVector(sc)
@@ -209,6 +210,37 @@ class ModelSequencer {
 	}
 
 
+
+
+	def ExecutionFlow mapLocalReactions(Statechart statechart, ExecutionFlow r){
+		var content = EcoreUtil2::eAllContentsAsList(statechart)
+		val allStates = content.filter(e | e instanceof State)
+		allStates.forEach( s | (s as State).mapStateLocalReactions);
+		return r
+	}
+
+	def ExecutionState mapStateLocalReactions(State state) {
+		val _state = state.create
+		
+		_state.reactions.addAll( 
+			state.localReactions
+				.filter( typeof( LocalReaction ))
+				// ignore all reaction that are just entry or exit actions
+				.filter(lr | (lr.trigger as ReactionTrigger).triggers.empty || ! (lr.trigger as ReactionTrigger).triggers.filter( t | t instanceof RegularEventSpec || t instanceof TimeEventSpec).toList.empty)
+				.map(t | t.mapReaction)
+		)
+		return _state
+	}
+	 
+	 
+	def Reaction mapReaction(LocalReaction lr) {
+		val r = lr.create 
+		if (lr.trigger != null) r.check = mapToCheck(lr.trigger)
+		r.effect = mapToEffect(lr)
+		return r
+	}
+
+
 	def Sequence mapToEffect(Transition t) {
 		val sequence = sexecFactory.createSequence 
 
@@ -225,6 +257,12 @@ class ModelSequencer {
 		return sequence
 	}	
 	
+	
+	def Sequence mapToEffect(LocalReaction lr) {
+		if (lr.effect != null) lr.effect.mapEffect	
+	}	
+
+	
 	def dispatch Sequence mapEffect(Effect effect) {}
 	
 	def dispatch Sequence mapEffect(ReactionEffect effect) {
@@ -337,15 +375,29 @@ class ModelSequencer {
 		val cycle = sexecFactory.createCycle
 		state.cycle = cycle
 		
-		val step = state.reactions.reverseView.fold(null as If, [s, reaction | {
+		val localReactions = state.reactions.filter(r | ! r.transition).toList
+		var localSteps = sexecFactory.createSequence
+		localSteps.steps.addAll(localReactions.map(lr | {
+				var ifStep = sexecFactory.createIf
+				ifStep.check = lr.check.newRef		
+				ifStep.thenStep = lr.effect.newCall
+				ifStep
+		}))
+		if (localSteps.steps.empty) localSteps = null
+				
+				
+		val transitionReactions = state.reactions.filter(r | r.transition).toList
+		val transitionStep = transitionReactions.reverseView.fold(localSteps as Step, [s, reaction | {
 				var ifStep = sexecFactory.createIf
 				ifStep.check = reaction.check.newRef		
 				ifStep.thenStep = reaction.effect.newCall
 				ifStep.elseStep = s
-				ifStep
+				ifStep as Step
 			}])
-			
-		if (step != null) cycle.steps.add(step)
+
+	
+		if (transitionStep != null) cycle.steps.add(transitionStep)		
+		else if (localSteps != null) cycle.steps.add(localSteps)
 		
 		return cycle
 	}
@@ -364,10 +416,13 @@ class ModelSequencer {
 	
 	def dispatch Statement buildCondition (ReactionTrigger t) {
 		val triggerCheck = if (! t.triggers.empty) t.triggers.reverseView.fold(null as Expression,
-			[s,e | 
-				if (s==null) raised(e)  
-				else raised(e).or(s)
-			]
+			[s,e | {
+				val Expression raised = raised(e)
+				
+				if (raised == null) s
+				else if (s==null) raised  
+				else raised.or(s)
+			}]
 		) else null;
 		
 		val guard = if ( t.guardExpression != null ) EcoreUtil::copy(t.guardExpression) else null;
@@ -527,17 +582,6 @@ class ModelSequencer {
 			if (entry.outgoingTransitions.size > 0) entry.outgoingTransitions.get(0).target as State
 		}
 	}
-
-	/**
-	 * Returns a list of all local reactions defined for a state. This includes also entry and exit actions but excludes 
-	 * local reactions of child states.
-	 * 
-	 * TODO: remove this function as soon the localReactions property in the sgraph model is correctly derived.
-	 */
-	def List<LocalReaction> localReactions_(State state)	{
-		if (state.scopes != null && state.scopes.size > 0 ) state.scopes.get(0).declarations.filter(typeof(LocalReaction)).toList
-		else new ArrayList<LocalReaction>()
-	}
 	 
 	def List<LocalReaction> entryReactions(State state) {
 		state.localReactions

+ 29 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/transformation/StatechartExtensions.xtend

@@ -11,6 +11,9 @@ import java.util.List
 import java.util.ArrayList
 import org.yakindu.sct.model.stext.stext.TimeEventSpec
 import org.eclipse.xtext.EcoreUtil2
+import org.yakindu.sct.model.stext.stext.LocalReaction
+import org.yakindu.sct.model.sgraph.ReactiveElement
+import org.yakindu.sct.model.sgraph.Scope
 
 class StatechartExtensions {
 	
@@ -79,6 +82,25 @@ class StatechartExtensions {
 		return tesList
 	}
 
+
+	def dispatch ReactiveElement reactiveElement(Reaction r) {
+		r.scope.reactiveElement		
+	}
+
+	def dispatch ReactiveElement reactiveElement(Transition tr) {
+		if (tr.source instanceof State) tr as State
+		else null
+	}
+	
+	
+	def Scope scope(Reaction r) {
+		if (r.eContainer instanceof Scope) r.eContainer as Scope
+	} 
+
+	def ReactiveElement reactiveElement(Scope s) {
+		if (s.eContainer instanceof ReactiveElement) s.eContainer as ReactiveElement
+	}	
+	
 	//=================================================================
 	// naming util extensions
 	//
@@ -93,6 +115,13 @@ class StatechartExtensions {
 		"tr" + if (t.source != null) t.source.outgoingTransitions.indexOf(t) else ""
 	}
 	
+	/**
+	 * The id of a local reaction is unique within the context of its source vertex.
+	 */	
+	def dispatch String id(LocalReaction t) {
+		"lr" + if (t.reactiveElement != null) t.reactiveElement.localReactions.indexOf(t) else ""
+	}
+	
 	
 	
 }

+ 1 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/util/SexecAdapterFactory.java

@@ -10,6 +10,7 @@ import org.eclipse.emf.common.notify.Adapter;
 import org.eclipse.emf.common.notify.Notifier;
 import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
 import org.eclipse.emf.ecore.EObject;
+import org.yakindu.sct.model.sexec.*;
 import org.yakindu.sct.model.sexec.Call;
 import org.yakindu.sct.model.sexec.Check;
 import org.yakindu.sct.model.sexec.CheckRef;

+ 1 - 0
plugins/org.yakindu.sct.model.sexec/src/org/yakindu/sct/model/sexec/util/SexecSwitch.java

@@ -9,6 +9,7 @@ package org.yakindu.sct.model.sexec.util;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.util.Switch;
+import org.yakindu.sct.model.sexec.*;
 import org.yakindu.sct.model.sexec.Call;
 import org.yakindu.sct.model.sexec.Check;
 import org.yakindu.sct.model.sexec.CheckRef;

+ 36 - 10
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/FactoryExtension.java

@@ -27,6 +27,7 @@ import org.yakindu.sct.model.sgraph.Transition;
 import org.yakindu.sct.model.stext.stext.EventDefinition;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
+import org.yakindu.sct.model.stext.stext.LocalReaction;
 import org.yakindu.sct.model.stext.stext.ReactionTrigger;
 import org.yakindu.sct.model.stext.stext.StextFactory;
 import org.yakindu.sct.model.stext.stext.VariableDefinition;
@@ -44,7 +45,7 @@ public class FactoryExtension {
   
   public ExecutionFlow create(final Statechart statechart) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(statechart);
-    final ExecutionFlow r;
+    ExecutionFlow r;
     synchronized (_createCache_create) {
       if (_createCache_create.containsKey(_cacheKey)) {
         return _createCache_create.get(_cacheKey);
@@ -63,7 +64,7 @@ public class FactoryExtension {
   
   protected Scope _create(final InterfaceScope scope) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(scope);
-    final InterfaceScope r;
+    InterfaceScope r;
     synchronized (_createCache_create_1) {
       if (_createCache_create_1.containsKey(_cacheKey)) {
         return _createCache_create_1.get(_cacheKey);
@@ -82,7 +83,7 @@ public class FactoryExtension {
   
   protected Scope _create(final InternalScope scope) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(scope);
-    final InternalScope r;
+    InternalScope r;
     synchronized (_createCache_create_2) {
       if (_createCache_create_2.containsKey(_cacheKey)) {
         return _createCache_create_2.get(_cacheKey);
@@ -99,7 +100,7 @@ public class FactoryExtension {
   
   public EventDefinition create(final EventDefinition event) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(event);
-    final EventDefinition r;
+    EventDefinition r;
     synchronized (_createCache_create_3) {
       if (_createCache_create_3.containsKey(_cacheKey)) {
         return _createCache_create_3.get(_cacheKey);
@@ -115,7 +116,7 @@ public class FactoryExtension {
   
   public VariableDefinition create(final VariableDefinition v) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(v);
-    final VariableDefinition r;
+    VariableDefinition r;
     synchronized (_createCache_create_4) {
       if (_createCache_create_4.containsKey(_cacheKey)) {
         return _createCache_create_4.get(_cacheKey);
@@ -131,7 +132,7 @@ public class FactoryExtension {
   
   public ExecutionState create(final State state) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(state);
-    final ExecutionState r;
+    ExecutionState r;
     synchronized (_createCache_create_5) {
       if (_createCache_create_5.containsKey(_cacheKey)) {
         return _createCache_create_5.get(_cacheKey);
@@ -156,7 +157,7 @@ public class FactoryExtension {
   
   public Check createCheck(final ReactionTrigger tr) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(tr);
-    final Check r;
+    Check r;
     synchronized (_createCache_createCheck) {
       if (_createCache_createCheck.containsKey(_cacheKey)) {
         return _createCache_createCheck.get(_cacheKey);
@@ -176,7 +177,7 @@ public class FactoryExtension {
   
   public org.yakindu.sct.model.sexec.Reaction create(final Transition tr) {
     final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(tr);
-    final org.yakindu.sct.model.sexec.Reaction r;
+    org.yakindu.sct.model.sexec.Reaction r;
     synchronized (_createCache_create_6) {
       if (_createCache_create_6.containsKey(_cacheKey)) {
         return _createCache_create_6.get(_cacheKey);
@@ -186,8 +187,33 @@ public class FactoryExtension {
       r = _createReaction;
       _createCache_create_6.put(_cacheKey, r);
     }
-    String _id = this.sce.id(tr);
-    r.setName(_id);
+    {
+      String _id = this.sce.id(tr);
+      r.setName(_id);
+      r.setTransition(true);
+    }
+    return r;
+  }
+  
+  private final HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction> _createCache_create_7 = new HashMap<ArrayList<?>,org.yakindu.sct.model.sexec.Reaction>();
+  
+  public org.yakindu.sct.model.sexec.Reaction create(final LocalReaction lr) {
+    final ArrayList<?>_cacheKey = CollectionLiterals.newArrayList(lr);
+    org.yakindu.sct.model.sexec.Reaction r;
+    synchronized (_createCache_create_7) {
+      if (_createCache_create_7.containsKey(_cacheKey)) {
+        return _createCache_create_7.get(_cacheKey);
+      }
+      SexecFactory _sexecFactory = this.sexecFactory();
+      org.yakindu.sct.model.sexec.Reaction _createReaction = _sexecFactory.createReaction();
+      r = _createReaction;
+      _createCache_create_7.put(_cacheKey, r);
+    }
+    {
+      String _id = this.sce.id(lr);
+      r.setName(_id);
+      r.setTransition(false);
+    }
     return r;
   }
   

+ 202 - 60
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/ModelSequencer.java

@@ -93,6 +93,7 @@ public class ModelSequencer {
       this.mapStates(sc, ef);
       this.mapTimeEvents(sc, ef);
       this.mapTransitions(sc, ef);
+      this.mapLocalReactions(sc, ef);
       this.defineStateVector(ef, sc);
       this.defineEnterSequence(ef, sc);
       this.defineStateCycles(ef, sc);
@@ -305,6 +306,96 @@ public class ModelSequencer {
     }
   }
   
+  public ExecutionFlow mapLocalReactions(final Statechart statechart, final ExecutionFlow r) {
+    {
+      List<EObject> _eAllContentsAsList = EcoreUtil2.eAllContentsAsList(statechart);
+      List<EObject> content = _eAllContentsAsList;
+      final Function1<EObject,Boolean> _function = new Function1<EObject,Boolean>() {
+          public Boolean apply(final EObject e) {
+            return (e instanceof org.yakindu.sct.model.sgraph.State);
+          }
+        };
+      Iterable<EObject> _filter = IterableExtensions.<EObject>filter(content, _function);
+      final Iterable<EObject> allStates = _filter;
+      final Function1<EObject,ExecutionState> _function_1 = new Function1<EObject,ExecutionState>() {
+          public ExecutionState apply(final EObject s) {
+            ExecutionState _mapStateLocalReactions = ModelSequencer.this.mapStateLocalReactions(((State) s));
+            return _mapStateLocalReactions;
+          }
+        };
+      IterableExtensions.<EObject>forEach(allStates, _function_1);
+      return r;
+    }
+  }
+  
+  public ExecutionState mapStateLocalReactions(final State state) {
+    {
+      ExecutionState _create = this.factory.create(state);
+      final ExecutionState _state = _create;
+      EList<Reaction> _reactions = _state.getReactions();
+      EList<org.yakindu.sct.model.sgraph.Reaction> _localReactions = state.getLocalReactions();
+      Iterable<LocalReaction> _filter = IterableExtensions.<LocalReaction>filter(_localReactions, org.yakindu.sct.model.stext.stext.LocalReaction.class);
+      final Function1<LocalReaction,Boolean> _function = new Function1<LocalReaction,Boolean>() {
+          public Boolean apply(final LocalReaction lr) {
+            boolean _operator_or = false;
+            Trigger _trigger = lr.getTrigger();
+            EList<EventSpec> _triggers = ((ReactionTrigger) _trigger).getTriggers();
+            boolean _isEmpty = _triggers.isEmpty();
+            if (_isEmpty) {
+              _operator_or = true;
+            } else {
+              Trigger _trigger_1 = lr.getTrigger();
+              EList<EventSpec> _triggers_1 = ((ReactionTrigger) _trigger_1).getTriggers();
+              final Function1<EventSpec,Boolean> _function_1 = new Function1<EventSpec,Boolean>() {
+                  public Boolean apply(final EventSpec t) {
+                    boolean _operator_or_1 = false;
+                    if ((t instanceof org.yakindu.sct.model.stext.stext.RegularEventSpec)) {
+                      _operator_or_1 = true;
+                    } else {
+                      _operator_or_1 = BooleanExtensions.operator_or((t instanceof org.yakindu.sct.model.stext.stext.RegularEventSpec), (t instanceof org.yakindu.sct.model.stext.stext.TimeEventSpec));
+                    }
+                    return ((Boolean)_operator_or_1);
+                  }
+                };
+              Iterable<EventSpec> _filter_1 = IterableExtensions.<EventSpec>filter(_triggers_1, _function_1);
+              List<EventSpec> _list = IterableExtensions.<EventSpec>toList(_filter_1);
+              boolean _isEmpty_1 = _list.isEmpty();
+              boolean _operator_not = BooleanExtensions.operator_not(_isEmpty_1);
+              _operator_or = BooleanExtensions.operator_or(_isEmpty, _operator_not);
+            }
+            return ((Boolean)_operator_or);
+          }
+        };
+      Iterable<LocalReaction> _filter_2 = IterableExtensions.<LocalReaction>filter(_filter, _function);
+      final Function1<LocalReaction,Reaction> _function_2 = new Function1<LocalReaction,Reaction>() {
+          public Reaction apply(final LocalReaction t_1) {
+            Reaction _mapReaction = ModelSequencer.this.mapReaction(t_1);
+            return _mapReaction;
+          }
+        };
+      Iterable<Reaction> _map = IterableExtensions.<LocalReaction, Reaction>map(_filter_2, _function_2);
+      CollectionExtensions.<Reaction>addAll(_reactions, _map);
+      return _state;
+    }
+  }
+  
+  public Reaction mapReaction(final LocalReaction lr) {
+    {
+      Reaction _create = this.factory.create(lr);
+      final Reaction r = _create;
+      Trigger _trigger = lr.getTrigger();
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_trigger, null);
+      if (_operator_notEquals) {
+        Trigger _trigger_1 = lr.getTrigger();
+        Check _mapToCheck = this.mapToCheck(_trigger_1);
+        r.setCheck(_mapToCheck);
+      }
+      Sequence _mapToEffect = this.mapToEffect(lr);
+      r.setEffect(_mapToEffect);
+      return r;
+    }
+  }
+  
   public Sequence mapToEffect(final Transition t) {
     {
       SexecFactory _sexecFactory = this.sexecFactory();
@@ -383,6 +474,18 @@ public class ModelSequencer {
     }
   }
   
+  public Sequence mapToEffect(final LocalReaction lr) {
+    Sequence _xifexpression = null;
+    Effect _effect = lr.getEffect();
+    boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_effect, null);
+    if (_operator_notEquals) {
+      Effect _effect_1 = lr.getEffect();
+      Sequence _mapEffect = this.mapEffect(_effect_1);
+      _xifexpression = _mapEffect;
+    }
+    return _xifexpression;
+  }
+  
   protected Sequence _mapEffect(final Effect effect) {
     return null;
   }
@@ -659,32 +762,87 @@ public class ModelSequencer {
       final Cycle cycle = _createCycle;
       state.setCycle(cycle);
       EList<Reaction> _reactions = state.getReactions();
-      Iterable<Reaction> _reverseView = ListExtensions.<Reaction>reverseView(_reactions);
-      final Function2<If,Reaction,If> _function = new Function2<If,Reaction,If>() {
-          public If apply(final If s , final Reaction reaction) {
+      final Function1<Reaction,Boolean> _function = new Function1<Reaction,Boolean>() {
+          public Boolean apply(final Reaction r) {
+            boolean _isTransition = r.isTransition();
+            boolean _operator_not = BooleanExtensions.operator_not(_isTransition);
+            return ((Boolean)_operator_not);
+          }
+        };
+      Iterable<Reaction> _filter = IterableExtensions.<Reaction>filter(_reactions, _function);
+      List<Reaction> _list = IterableExtensions.<Reaction>toList(_filter);
+      final List<Reaction> localReactions = _list;
+      SexecFactory _sexecFactory_1 = this.sexecFactory();
+      Sequence _createSequence = _sexecFactory_1.createSequence();
+      Sequence localSteps = _createSequence;
+      EList<Step> _steps = localSteps.getSteps();
+      final Function1<Reaction,If> _function_1 = new Function1<Reaction,If>() {
+          public If apply(final Reaction lr) {
             If _xblockexpression = null;
             {
-              SexecFactory _sexecFactory_1 = ModelSequencer.this.sexecFactory();
-              If _createIf = _sexecFactory_1.createIf();
+              SexecFactory _sexecFactory_2 = ModelSequencer.this.sexecFactory();
+              If _createIf = _sexecFactory_2.createIf();
               If ifStep = _createIf;
-              Check _check = reaction.getCheck();
+              Check _check = lr.getCheck();
               CheckRef _newRef = ModelSequencer.this.factory.newRef(_check);
               ifStep.setCheck(_newRef);
-              Step _effect = reaction.getEffect();
+              Step _effect = lr.getEffect();
               Call _newCall = ModelSequencer.this.factory.newCall(_effect);
               ifStep.setThenStep(_newCall);
-              ifStep.setElseStep(s);
               _xblockexpression = (ifStep);
             }
             return _xblockexpression;
           }
         };
-      If _fold = IterableExtensions.<Reaction, If>fold(_reverseView, ((If) null), _function);
-      final If step = _fold;
-      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(step, null);
+      List<If> _map = ListExtensions.<Reaction, If>map(localReactions, _function_1);
+      _steps.addAll(_map);
+      EList<Step> _steps_1 = localSteps.getSteps();
+      boolean _isEmpty = _steps_1.isEmpty();
+      if (_isEmpty) {
+        localSteps = null;
+      }
+      EList<Reaction> _reactions_1 = state.getReactions();
+      final Function1<Reaction,Boolean> _function_2 = new Function1<Reaction,Boolean>() {
+          public Boolean apply(final Reaction r_1) {
+            boolean _isTransition_1 = r_1.isTransition();
+            return ((Boolean)_isTransition_1);
+          }
+        };
+      Iterable<Reaction> _filter_1 = IterableExtensions.<Reaction>filter(_reactions_1, _function_2);
+      List<Reaction> _list_1 = IterableExtensions.<Reaction>toList(_filter_1);
+      final List<Reaction> transitionReactions = _list_1;
+      Iterable<Reaction> _reverseView = ListExtensions.<Reaction>reverseView(transitionReactions);
+      final Function2<Step,Reaction,Step> _function_3 = new Function2<Step,Reaction,Step>() {
+          public Step apply(final Step s , final Reaction reaction) {
+            Step _xblockexpression_1 = null;
+            {
+              SexecFactory _sexecFactory_3 = ModelSequencer.this.sexecFactory();
+              If _createIf_1 = _sexecFactory_3.createIf();
+              If ifStep_1 = _createIf_1;
+              Check _check_1 = reaction.getCheck();
+              CheckRef _newRef_1 = ModelSequencer.this.factory.newRef(_check_1);
+              ifStep_1.setCheck(_newRef_1);
+              Step _effect_1 = reaction.getEffect();
+              Call _newCall_1 = ModelSequencer.this.factory.newCall(_effect_1);
+              ifStep_1.setThenStep(_newCall_1);
+              ifStep_1.setElseStep(s);
+              _xblockexpression_1 = (((Step) ifStep_1));
+            }
+            return _xblockexpression_1;
+          }
+        };
+      Step _fold = IterableExtensions.<Reaction, Step>fold(_reverseView, ((Step) localSteps), _function_3);
+      final Step transitionStep = _fold;
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(transitionStep, null);
       if (_operator_notEquals) {
-        EList<Step> _steps = cycle.getSteps();
-        _steps.add(step);
+        EList<Step> _steps_2 = cycle.getSteps();
+        _steps_2.add(transitionStep);
+      } else {
+        boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(localSteps, null);
+        if (_operator_notEquals_1) {
+          EList<Step> _steps_3 = cycle.getSteps();
+          _steps_3.add(localSteps);
+        }
       }
       return cycle;
     }
@@ -720,17 +878,28 @@ public class ModelSequencer {
         Iterable<EventSpec> _reverseView = ListExtensions.<EventSpec>reverseView(_triggers_1);
         final Function2<Expression,EventSpec,Expression> _function = new Function2<Expression,EventSpec,Expression>() {
             public Expression apply(final Expression s , final EventSpec e) {
-              Expression _xifexpression_1 = null;
-              boolean _operator_equals = ObjectExtensions.operator_equals(s, null);
-              if (_operator_equals) {
+              Expression _xblockexpression_1 = null;
+              {
                 Expression _raised = ModelSequencer.this.raised(e);
-                _xifexpression_1 = _raised;
-              } else {
-                Expression _raised_1 = ModelSequencer.this.raised(e);
-                Expression _or = ModelSequencer.this.or(_raised_1, s);
-                _xifexpression_1 = _or;
+                final Expression raised = _raised;
+                Expression _xifexpression_1 = null;
+                boolean _operator_equals = ObjectExtensions.operator_equals(raised, null);
+                if (_operator_equals) {
+                  _xifexpression_1 = s;
+                } else {
+                  Expression _xifexpression_2 = null;
+                  boolean _operator_equals_1 = ObjectExtensions.operator_equals(s, null);
+                  if (_operator_equals_1) {
+                    _xifexpression_2 = raised;
+                  } else {
+                    Expression _or = ModelSequencer.this.or(raised, s);
+                    _xifexpression_2 = _or;
+                  }
+                  _xifexpression_1 = _xifexpression_2;
+                }
+                _xblockexpression_1 = (_xifexpression_1);
               }
-              return _xifexpression_1;
+              return _xblockexpression_1;
             }
           };
         Expression _fold = IterableExtensions.<EventSpec, Expression>fold(_reverseView, ((Expression) null), _function);
@@ -739,18 +908,18 @@ public class ModelSequencer {
         _xifexpression = null;
       }
       final Expression triggerCheck = _xifexpression;
-      Expression _xifexpression_2 = null;
+      Expression _xifexpression_3 = null;
       Expression _guardExpression = t.getGuardExpression();
       boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_guardExpression, null);
       if (_operator_notEquals) {
         Expression _guardExpression_1 = t.getGuardExpression();
         Expression _copy = EcoreUtil.<Expression>copy(_guardExpression_1);
-        _xifexpression_2 = _copy;
+        _xifexpression_3 = _copy;
       } else {
-        _xifexpression_2 = null;
+        _xifexpression_3 = null;
       }
-      final Expression guard = _xifexpression_2;
-      Expression _xifexpression_3 = null;
+      final Expression guard = _xifexpression_3;
+      Expression _xifexpression_4 = null;
       boolean _operator_and = false;
       boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(triggerCheck, null);
       if (!_operator_notEquals_1) {
@@ -761,18 +930,18 @@ public class ModelSequencer {
       }
       if (_operator_and) {
         Expression _and = this.and(triggerCheck, guard);
-        _xifexpression_3 = _and;
+        _xifexpression_4 = _and;
       } else {
-        Expression _xifexpression_4 = null;
+        Expression _xifexpression_5 = null;
         boolean _operator_notEquals_3 = ObjectExtensions.operator_notEquals(triggerCheck, null);
         if (_operator_notEquals_3) {
-          _xifexpression_4 = triggerCheck;
+          _xifexpression_5 = triggerCheck;
         } else {
-          _xifexpression_4 = guard;
+          _xifexpression_5 = guard;
         }
-        _xifexpression_3 = _xifexpression_4;
+        _xifexpression_4 = _xifexpression_5;
       }
-      _xblockexpression = (_xifexpression_3);
+      _xblockexpression = (_xifexpression_4);
     }
     return _xblockexpression;
   }
@@ -1117,33 +1286,6 @@ public class ModelSequencer {
     return _xifexpression;
   }
   
-  public List<LocalReaction> localReactions_(final State state) {
-    List<LocalReaction> _xifexpression = null;
-    boolean _operator_and = false;
-    EList<Scope> _scopes = state.getScopes();
-    boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_scopes, null);
-    if (!_operator_notEquals) {
-      _operator_and = false;
-    } else {
-      EList<Scope> _scopes_1 = state.getScopes();
-      int _size = _scopes_1.size();
-      boolean _operator_greaterThan = ComparableExtensions.<Integer>operator_greaterThan(((Integer)_size), ((Integer)0));
-      _operator_and = BooleanExtensions.operator_and(_operator_notEquals, _operator_greaterThan);
-    }
-    if (_operator_and) {
-      EList<Scope> _scopes_2 = state.getScopes();
-      Scope _get = _scopes_2.get(0);
-      EList<Declaration> _declarations = _get.getDeclarations();
-      Iterable<LocalReaction> _filter = IterableExtensions.<LocalReaction>filter(_declarations, org.yakindu.sct.model.stext.stext.LocalReaction.class);
-      List<LocalReaction> _list = IterableExtensions.<LocalReaction>toList(_filter);
-      _xifexpression = _list;
-    } else {
-      ArrayList<LocalReaction> _arrayList = new ArrayList<LocalReaction>();
-      _xifexpression = _arrayList;
-    }
-    return _xifexpression;
-  }
-  
   public List<LocalReaction> entryReactions(final State state) {
     EList<org.yakindu.sct.model.sgraph.Reaction> _localReactions = state.getLocalReactions();
     final Function1<org.yakindu.sct.model.sgraph.Reaction,Boolean> _function = new Function1<org.yakindu.sct.model.sgraph.Reaction,Boolean>() {

+ 70 - 1
plugins/org.yakindu.sct.model.sexec/xtend-gen/org/yakindu/sct/model/sexec/transformation/StatechartExtensions.java

@@ -13,12 +13,15 @@ import org.eclipse.xtext.xbase.lib.IterableExtensions;
 import org.eclipse.xtext.xbase.lib.ObjectExtensions;
 import org.eclipse.xtext.xbase.lib.StringExtensions;
 import org.yakindu.sct.model.sgraph.Reaction;
+import org.yakindu.sct.model.sgraph.ReactiveElement;
 import org.yakindu.sct.model.sgraph.Region;
+import org.yakindu.sct.model.sgraph.Scope;
 import org.yakindu.sct.model.sgraph.State;
 import org.yakindu.sct.model.sgraph.Statechart;
 import org.yakindu.sct.model.sgraph.Transition;
 import org.yakindu.sct.model.sgraph.Trigger;
 import org.yakindu.sct.model.sgraph.Vertex;
+import org.yakindu.sct.model.stext.stext.LocalReaction;
 import org.yakindu.sct.model.stext.stext.TimeEventSpec;
 
 @SuppressWarnings("all")
@@ -160,6 +163,43 @@ public class StatechartExtensions {
     }
   }
   
+  protected ReactiveElement _reactiveElement(final Reaction r) {
+    Scope _scope = this.scope(r);
+    ReactiveElement _reactiveElement = this.reactiveElement(_scope);
+    return _reactiveElement;
+  }
+  
+  protected ReactiveElement _reactiveElement(final Transition tr) {
+    State _xifexpression = null;
+    Vertex _source = tr.getSource();
+    if ((_source instanceof org.yakindu.sct.model.sgraph.State)) {
+      _xifexpression = ((State) tr);
+    } else {
+      _xifexpression = null;
+    }
+    return _xifexpression;
+  }
+  
+  public Scope scope(final Reaction r) {
+    Scope _xifexpression = null;
+    EObject _eContainer = r.eContainer();
+    if ((_eContainer instanceof org.yakindu.sct.model.sgraph.Scope)) {
+      EObject _eContainer_1 = r.eContainer();
+      _xifexpression = ((Scope) _eContainer_1);
+    }
+    return _xifexpression;
+  }
+  
+  public ReactiveElement reactiveElement(final Scope s) {
+    ReactiveElement _xifexpression = null;
+    EObject _eContainer = s.eContainer();
+    if ((_eContainer instanceof org.yakindu.sct.model.sgraph.ReactiveElement)) {
+      EObject _eContainer_1 = s.eContainer();
+      _xifexpression = ((ReactiveElement) _eContainer_1);
+    }
+    return _xifexpression;
+  }
+  
   protected String _id(final Object obj) {
     return null;
   }
@@ -180,6 +220,22 @@ public class StatechartExtensions {
     return _operator_plus;
   }
   
+  protected String _id(final LocalReaction t) {
+    Comparable<? extends Object> _xifexpression = null;
+    ReactiveElement _reactiveElement = this.reactiveElement(t);
+    boolean _operator_notEquals = ObjectExtensions.operator_notEquals(_reactiveElement, null);
+    if (_operator_notEquals) {
+      ReactiveElement _reactiveElement_1 = this.reactiveElement(t);
+      EList<Reaction> _localReactions = _reactiveElement_1.getLocalReactions();
+      int _indexOf = _localReactions.indexOf(t);
+      _xifexpression = _indexOf;
+    } else {
+      _xifexpression = "";
+    }
+    String _operator_plus = StringExtensions.operator_plus("lr", _xifexpression);
+    return _operator_plus;
+  }
+  
   public int maxOrthogonality(final Vertex s) {
     if ((s instanceof State)) {
       return _maxOrthogonality((State)s);
@@ -191,8 +247,21 @@ public class StatechartExtensions {
     }
   }
   
+  public ReactiveElement reactiveElement(final Reaction tr) {
+    if ((tr instanceof Transition)) {
+      return _reactiveElement((Transition)tr);
+    } else if ((tr instanceof Reaction)) {
+      return _reactiveElement((Reaction)tr);
+    } else {
+      throw new IllegalArgumentException("Unhandled parameter types: " +
+        java.util.Arrays.<Object>asList(tr).toString());
+    }
+  }
+  
   public String id(final Object t) {
-    if ((t instanceof Transition)) {
+    if ((t instanceof LocalReaction)) {
+      return _id((LocalReaction)t);
+    } else if ((t instanceof Transition)) {
       return _id((Transition)t);
     } else if ((t instanceof Object)) {
       return _id((Object)t);

+ 254 - 3
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/ModelSequencerTest.java

@@ -6,13 +6,13 @@ import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createEntry;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createEntryAction;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createEventDefinition;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createExitAction;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createInterfaceScope;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createInternalScope;
+import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createLocalReaction;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createReactionEffect;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createReactionTrigger;
 import static org.yakindu.sct.model.sexec.transformation.test.SCTTestUtil._createRegion;
@@ -42,6 +42,7 @@ import org.yakindu.sct.model.sexec.TimeEvent;
 import org.yakindu.sct.model.sexec.UnscheduleTimeEvent;
 import org.yakindu.sct.model.sexec.transformation.ModelSequencer;
 import org.yakindu.sct.model.sexec.transformation.SequencerModule;
+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;
 import org.yakindu.sct.model.sgraph.Declaration;
@@ -58,17 +59,19 @@ import org.yakindu.sct.model.stext.stext.Assignment;
 import org.yakindu.sct.model.stext.stext.AssignmentOperator;
 import org.yakindu.sct.model.stext.stext.ElementReferenceExpression;
 import org.yakindu.sct.model.stext.stext.EventDefinition;
-import org.yakindu.sct.model.stext.stext.Expression;
 import org.yakindu.sct.model.stext.stext.InterfaceScope;
 import org.yakindu.sct.model.stext.stext.InternalScope;
 import org.yakindu.sct.model.stext.stext.LocalReaction;
 import org.yakindu.sct.model.stext.stext.LogicalAndExpression;
 import org.yakindu.sct.model.stext.stext.LogicalOrExpression;
+import org.yakindu.sct.model.stext.stext.LogicalRelationExpression;
 import org.yakindu.sct.model.stext.stext.MultiplicativeOperator;
 import org.yakindu.sct.model.stext.stext.NumericalMultiplyDivideExpression;
 import org.yakindu.sct.model.stext.stext.PrimitiveValueExpression;
 import org.yakindu.sct.model.stext.stext.ReactionEffect;
 import org.yakindu.sct.model.stext.stext.ReactionTrigger;
+import org.yakindu.sct.model.stext.stext.RelationalOperator;
+import org.yakindu.sct.model.stext.stext.StextFactory;
 import org.yakindu.sct.model.stext.stext.TimeEventType;
 import org.yakindu.sct.model.stext.stext.TimeUnit;
 import org.yakindu.sct.model.stext.stext.Type;
@@ -445,7 +448,7 @@ public class ModelSequencerTest {
 	}
 	
 
-	@Test public void testStateCycle_SimpleFlatTSC() {
+	@Test public void testStateCycle() {
 		OrthogonalFlatTSC tsc = new OrthogonalFlatTSC();
 		
 		ExecutionFlow flow = sequencer.transform(tsc.sc);
@@ -486,8 +489,256 @@ public class ModelSequencerTest {
 	}
 	
 
+	@Test public void testStateCycle_WithLocalReactions() {
+		SimpleFlatTSC tsc = new SimpleFlatTSC();
+
+		VariableDefinition v1 = _createVariableDefinition("v1", Type.INTEGER, tsc.s_scope);
+
+		// the first local reaction conforms to "e1 / x=42;" 
+		LocalReaction lr1 = _createLocalReaction(tsc.s1, null);
+		_createRegularEventSpec(tsc.e1, (ReactionTrigger) lr1.getTrigger());
+		ReactionEffect lr1_eff = _createReactionEffect(lr1);
+		Assignment assign1 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("42"), lr1_eff); 
+
+		// the secont local reaction conforms to "e1 [x==42] / x=0;" 
+		LocalReaction lr2 = _createLocalReaction(tsc.s1, null);
+		_createRegularEventSpec(tsc.e1, (ReactionTrigger) lr2.getTrigger());
+		LogicalRelationExpression lr2_equals = StextFactory.eINSTANCE.createLogicalRelationExpression();
+		lr2_equals.setOperator(RelationalOperator.EQUALS);
+		ElementReferenceExpression lr2_varRef = StextFactory.eINSTANCE.createElementReferenceExpression();
+		lr2_varRef.setValue(v1);
+		PrimitiveValueExpression lr2_value = _createValue("42");
+		lr2_equals.setLeftOperand(lr2_varRef);
+		lr2_equals.setRightOperand(lr2_value);
+		((ReactionTrigger) lr2.getTrigger()).setGuardExpression(lr2_equals);
+		ReactionEffect lr2_eff = _createReactionEffect(lr2);
+		Assignment assign2 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("0"), lr2_eff); 
+
+		// the third local reaction conforms to: "[x==0] / x=1;"
+		LocalReaction lr3 = _createLocalReaction(tsc.s1, null);
+		LogicalRelationExpression lr3_equals = StextFactory.eINSTANCE.createLogicalRelationExpression();
+		lr3_equals.setOperator(RelationalOperator.EQUALS);
+		ElementReferenceExpression lr3_varRef = StextFactory.eINSTANCE.createElementReferenceExpression();
+		lr3_varRef.setValue(v1);
+		PrimitiveValueExpression lr3_value = _createValue("0");
+		lr3_equals.setLeftOperand(lr3_varRef);
+		lr3_equals.setRightOperand(lr3_value);
+		((ReactionTrigger) lr3.getTrigger()).setGuardExpression(lr3_equals);
+		ReactionEffect lr3_eff = _createReactionEffect(lr3);
+		Assignment assign3 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("1"), lr3_eff); 
+		
+		
+		ExecutionFlow flow = sequencer.transform(tsc.sc);
+
+		// test state with one outgoing transition
+		ExecutionState s1 = flow.getStates().get(0);
+		ExecutionState s2 = flow.getStates().get(1);
+		assertEquals(tsc.s1.getName(), s1.getSimpleName());
+		assertEquals(tsc.s2.getName(), s2.getSimpleName());
+		
+		assertEquals(4, s1.getReactions().size());
+		
+		assertNotNull(s1.getCycle());
+		
+		If _if = (If) s1.getCycle().getSteps().get(0);
+		assertNotNull(_if.getThenStep());
+		assertTrue(_if.getThenStep() instanceof Call);
+		assertNotNull(_if.getElseStep());
+
+		Sequence _seq = (Sequence) _if.getElseStep();
+		assertEquals(3, _seq.getSteps().size());
+		
+		// check first local reaction
+		If _lr1 = (If) _seq.getSteps().get(0);
+		assertTrue(_lr1.getCheck().getCondition() instanceof ElementReferenceExpression);
+		assertSame(s1.getReactions().get(1).getCheck().getCondition(), _lr1.getCheck().getCondition() );
+		Call _lr1_eff_call = (Call) _lr1.getThenStep();
+		assertSame(s1.getReactions().get(1).getEffect(), _lr1_eff_call.getStep() );
+		
+		// check second local reaction
+		If _lr2 = (If) _seq.getSteps().get(1);
+		assertTrue(_lr2.getCheck().getCondition() instanceof LogicalAndExpression);
+		assertSame(s1.getReactions().get(2).getCheck().getCondition(), _lr2.getCheck().getCondition() );
+		Call _lr2_eff_call = (Call) _lr2.getThenStep();
+		assertSame(s1.getReactions().get(2).getEffect(), _lr2_eff_call.getStep() );
+
+		// check the third local reaction
+		If _lr3 = (If) _seq.getSteps().get(2);
+		assertTrue(_lr3.getCheck().getCondition() instanceof LogicalRelationExpression);
+		assertSame(s1.getReactions().get(3).getCheck().getCondition(), _lr3.getCheck().getCondition() );
+		Call _lr3_eff_call = (Call) _lr3.getThenStep();
+		assertSame(s1.getReactions().get(3).getEffect(), _lr3_eff_call.getStep() );
+						
+	}
+	
+	
+	/**
+	 * The cycle sequence of a state that only consists of local reactions includes sequential processing of the 
+	 * local reactions.
+	 */
+	@Test public void testStateCycle_WithLocalReactionsOnly() {
+		MinimalTSC tsc = new MinimalTSC();
+
+		VariableDefinition v1 = _createVariableDefinition("v1", Type.INTEGER, tsc.s_scope);
+
+		// the first local reaction conforms to "e1 / x=42;" 
+		LocalReaction lr1 = _createLocalReaction(tsc.s1, null);
+		_createRegularEventSpec(tsc.e1, (ReactionTrigger) lr1.getTrigger());
+		ReactionEffect lr1_eff = _createReactionEffect(lr1);
+		Assignment assign1 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("42"), lr1_eff); 
+
+		// the secont local reaction conforms to "e1 [x==42] / x=0;" 
+		LocalReaction lr2 = _createLocalReaction(tsc.s1, null);
+		_createRegularEventSpec(tsc.e1, (ReactionTrigger) lr2.getTrigger());
+		LogicalRelationExpression lr2_equals = StextFactory.eINSTANCE.createLogicalRelationExpression();
+		lr2_equals.setOperator(RelationalOperator.EQUALS);
+		ElementReferenceExpression lr2_varRef = StextFactory.eINSTANCE.createElementReferenceExpression();
+		lr2_varRef.setValue(v1);
+		PrimitiveValueExpression lr2_value = _createValue("42");
+		lr2_equals.setLeftOperand(lr2_varRef);
+		lr2_equals.setRightOperand(lr2_value);
+		((ReactionTrigger) lr2.getTrigger()).setGuardExpression(lr2_equals);
+		ReactionEffect lr2_eff = _createReactionEffect(lr2);
+		Assignment assign2 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("0"), lr2_eff); 
+
+		// the third local reaction conforms to: "[x==0] / x=1;"
+		LocalReaction lr3 = _createLocalReaction(tsc.s1, null);
+		LogicalRelationExpression lr3_equals = StextFactory.eINSTANCE.createLogicalRelationExpression();
+		lr3_equals.setOperator(RelationalOperator.EQUALS);
+		ElementReferenceExpression lr3_varRef = StextFactory.eINSTANCE.createElementReferenceExpression();
+		lr3_varRef.setValue(v1);
+		PrimitiveValueExpression lr3_value = _createValue("0");
+		lr3_equals.setLeftOperand(lr3_varRef);
+		lr3_equals.setRightOperand(lr3_value);
+		((ReactionTrigger) lr3.getTrigger()).setGuardExpression(lr3_equals);
+		ReactionEffect lr3_eff = _createReactionEffect(lr3);
+		Assignment assign3 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("1"), lr3_eff); 
+		
+		
+		ExecutionFlow flow = sequencer.transform(tsc.sc);
+
+		// test state with one outgoing transition
+		ExecutionState s1 = flow.getStates().get(0);
+		assertEquals(tsc.s1.getName(), s1.getSimpleName());
+		
+		assertEquals(3, s1.getReactions().size());
+		
+		assertNotNull(s1.getCycle());
+		
+
+		Sequence _seq = (Sequence) s1.getCycle().getSteps().get(0);
+		assertEquals(3, _seq.getSteps().size());
+		
+		// check first local reaction
+		If _lr1 = (If) _seq.getSteps().get(0);
+		assertTrue(_lr1.getCheck().getCondition() instanceof ElementReferenceExpression);
+		assertSame(s1.getReactions().get(0).getCheck().getCondition(), _lr1.getCheck().getCondition() );
+		Call _lr1_eff_call = (Call) _lr1.getThenStep();
+		assertSame(s1.getReactions().get(0).getEffect(), _lr1_eff_call.getStep() );
+		
+		// check second local reaction
+		If _lr2 = (If) _seq.getSteps().get(1);
+		assertTrue(_lr2.getCheck().getCondition() instanceof LogicalAndExpression);
+		assertSame(s1.getReactions().get(1).getCheck().getCondition(), _lr2.getCheck().getCondition() );
+		Call _lr2_eff_call = (Call) _lr2.getThenStep();
+		assertSame(s1.getReactions().get(1).getEffect(), _lr2_eff_call.getStep() );
+
+		// check the third local reaction
+		If _lr3 = (If) _seq.getSteps().get(2);
+		assertTrue(_lr3.getCheck().getCondition() instanceof LogicalRelationExpression);
+		assertSame(s1.getReactions().get(2).getCheck().getCondition(), _lr3.getCheck().getCondition() );
+		Call _lr3_eff_call = (Call) _lr3.getThenStep();
+		assertSame(s1.getReactions().get(2).getEffect(), _lr3_eff_call.getStep() );
+		
+					
+	}
+
+	/** Entry action behaviors are not directly part of the states cycle steps */
+	@Test public void testStateCycle_EntryActionExclusion() {
+		MinimalTSC tsc = new MinimalTSC();
+
+		VariableDefinition v1 = _createVariableDefinition("v1", Type.INTEGER, tsc.s_scope);
+
+		// add a simple entry action: "entry / x=42;" 
+		LocalReaction lr = _createEntryAction(tsc.s1);
+		ReactionEffect lr_eff = _createReactionEffect(lr);
+		Assignment assign1 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("42"), lr_eff); 
+
+		
+		// TRANSFORM
+		ExecutionFlow flow = sequencer.transform(tsc.sc);
+
+		
+		// test state with one outgoing transition
+		ExecutionState s1 = flow.getStates().get(0);
+		
+		assertEquals(0, s1.getReactions().size());		
+		assertNotNull(s1.getCycle());
+		assertEquals(0, s1.getCycle().getSteps().size());		
+	}
+
+	
+	/** Exit action behaviors are not directly part of the states cycle steps */
+	@Test public void testStateCycle_ExitActionExclusion() {
+		MinimalTSC tsc = new MinimalTSC();
+
+		VariableDefinition v1 = _createVariableDefinition("v1", Type.INTEGER, tsc.s_scope);
+
+		// add a simple entry action: "entry / x=42;" 
+		LocalReaction lr = _createExitAction(tsc.s1);
+		ReactionEffect lr_eff = _createReactionEffect(lr);
+		Assignment assign1 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("42"), lr_eff); 
+
+		
+		// TRANSFORM
+		ExecutionFlow flow = sequencer.transform(tsc.sc);
+
+		
+		// test state with one outgoing transition
+		ExecutionState s1 = flow.getStates().get(0);
+		
+		assertEquals(0, s1.getReactions().size());		
+		assertNotNull(s1.getCycle());
+		assertEquals(0, s1.getCycle().getSteps().size());		
+	}
+
+
+	/** Local reactions that define regular and entry triggers side by side must also be part of the cycle steps. */
+	@Test public void testStateCycle_LocalReactionWithMixedRegularAndEntryTrigger() {
+		MinimalTSC tsc = new MinimalTSC();
+
+		VariableDefinition v1 = _createVariableDefinition("v1", Type.INTEGER, tsc.s_scope);
+
+		// add a simple entry action: "entry / x=42;" 
+		LocalReaction lr = _createEntryAction(tsc.s1);
+		_createRegularEventSpec(tsc.e1, (ReactionTrigger) lr.getTrigger());
+		ReactionEffect lr_eff = _createReactionEffect(lr);
+		Assignment assign1 = _createVariableAssignment(v1, AssignmentOperator.ASSIGN, _createValue("42"), lr_eff); 
+
+		
+		// TRANSFORM
+		ExecutionFlow flow = sequencer.transform(tsc.sc);
+
+		
+		// test state with one outgoing transition
+		ExecutionState s1 = flow.getStates().get(0);
+		
+		assertEquals(1, s1.getReactions().size());		
+		assertNotNull(s1.getCycle());
+		assertEquals(1, s1.getCycle().getSteps().size());	
 	
+		Sequence _seq = (Sequence) s1.getCycle().getSteps().get(0);
+		
+		If _lr1 = (If) _seq.getSteps().get(0);
+		assertTrue(_lr1.getCheck().getCondition() instanceof ElementReferenceExpression);
+		assertSame(s1.getReactions().get(0).getCheck().getCondition(), _lr1.getCheck().getCondition() );
+		Call _lr1_eff_call = (Call) _lr1.getThenStep();
+		assertSame(s1.getReactions().get(0).getEffect(), _lr1_eff_call.getStep() );
+
+	}
+
 	
+
 	
 	/**
 	 * Single trigger events of a Reaction Trigger will be converted into a single condition 

+ 25 - 5
test-plugins/org.yakindu.sct.model.sexec.test/src/org/yakindu/sct/model/sexec/transformation/test/SCTTestUtil.java

@@ -39,6 +39,7 @@ public class SCTTestUtil {
 		return e;
 	}
 
+	
 	public static VariableDefinition _createVariableDefinition(String name, Type type, Scope scope) {
 		VariableDefinition v = StextFactory.eINSTANCE.createVariableDefinition();
 		v.setName(name);
@@ -47,6 +48,7 @@ public class SCTTestUtil {
 		return v;
 	}
 
+	
 	public static RegularEventSpec _createRegularEventSpec(EventDefinition e1, ReactionTrigger rt) {
 		RegularEventSpec e1Spec = StextFactory.eINSTANCE.createRegularEventSpec();
 		e1Spec.setEvent(e1);
@@ -54,6 +56,7 @@ public class SCTTestUtil {
 		return e1Spec;
 	}
 
+	
 	public static ReactionTrigger _createReactionTrigger(Reaction reaction) {
 		ReactionTrigger rt = StextFactory.eINSTANCE.createReactionTrigger();
 		if (reaction != null) reaction.setTrigger(rt);
@@ -140,12 +143,12 @@ public class SCTTestUtil {
 
 	
 	public static LocalReaction _createEntryAction(State parent) {
-		return _createLocalRection(parent, StextFactory.eINSTANCE.createEntryEvent() );
+		return _createLocalReaction(parent, StextFactory.eINSTANCE.createEntryEvent() );
 	}
 	
 	
 	public static LocalReaction _createExitAction(State parent) {
-		return _createLocalRection(parent, StextFactory.eINSTANCE.createExitEvent() );
+		return _createLocalReaction(parent, StextFactory.eINSTANCE.createExitEvent() );
 	}
 	
 	public static LocalReaction _createTimeTriggeredReaction(State parent, TimeEventType type, int value, TimeUnit unit) {
@@ -153,16 +156,16 @@ public class SCTTestUtil {
 //		timeTrigger.setType(type);
 //		timeTrigger.setValue(value);
 //		timeTrigger.setUnit(unit);
-		return _createLocalRection(parent, _createTimeEventSpec(type, value, unit, null) );
+		return _createLocalReaction(parent, _createTimeEventSpec(type, value, unit, null) );
 	}
 	
 
-	public static LocalReaction _createLocalRection(State parent, EventSpec triggerEvent) {
+	public static LocalReaction _createLocalReaction(State parent, EventSpec triggerEvent) {
 		LocalReaction reaction = StextFactory.eINSTANCE.createLocalReaction();
 		ReactionTrigger trigger = StextFactory.eINSTANCE.createReactionTrigger();
 		_createReactionEffect(reaction);
 		
-		trigger.getTriggers().add(triggerEvent);
+		if (triggerEvent != null) trigger.getTriggers().add(triggerEvent);
 		reaction.setTrigger(trigger);
 
 		Scope scope = null;
@@ -198,6 +201,23 @@ public class SCTTestUtil {
 		return assignment;
 	}
 	
+
+	
+	public static class MinimalTSC {
+		
+		public Statechart sc = _createStatechart("test");
+		public InterfaceScope s_scope = _createInterfaceScope("Interface", sc);
+		public EventDefinition e1 = _createEventDefinition("e1", s_scope);
+		public Region r = _createRegion("main", sc);
+		public Entry entry = _createEntry(EntryKind.INITIAL, null, r);
+		public State s1 = _createState("S1", r);
+		public Transition t0 = _createTransition(entry, s1);
+		
+		public MinimalTSC() {
+		}
+
+	}
+
 	
 	public static class SimpleFlatTSC {