浏览代码

Merge pull request #402 from Yakindu/issue_207_Cyclebased_statemachine_wrapper

Issue 207 cyclebased statemachine wrapper
Markus Mühlbrandt 9 年之前
父节点
当前提交
2e1054bdba
共有 26 个文件被更改,包括 2684 次插入193 次删除
  1. 10 2
      plugins/org.yakindu.sct.doc.user/help/05_reference/reference.textile
  2. 9 0
      plugins/org.yakindu.sct.generator.java/library/FeatureTypeLibrary.xmi
  3. 107 130
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/RunnableWrapper.xtend
  4. 170 0
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/EventBasedRunnableWrapper.xtend
  5. 12 4
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/JavaGenerator.xtend
  6. 0 46
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/RunnableFeature.xtend
  7. 3 3
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/Statemachine.xtend
  8. 10 0
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/TimerService.xtend
  9. 55 0
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/CycleBasedWrapperFeature.xtend
  10. 49 0
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/EventBasedRunnableFeature.xtend
  11. 10 3
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/IJavaFeatureConstants.java
  12. 12 4
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/JavaFeatureValueProvider.java
  13. 36 0
      test-plugins/org.yakindu.sct.generator.java.test/model/model.sgen
  14. 10 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/TimerService.java
  15. 35 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/IRunnableTestStatemachine.java
  16. 576 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/RunnableTestStatemachine.java
  17. 79 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/RunnableTestStatemachineRunnable.java
  18. 231 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/SynchronizedRunnableTestStatemachine.java
  19. 32 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/wrappertest/IWrapperTestStatemachine.java
  20. 214 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/wrappertest/SynchronizedWrapperTestStatemachine.java
  21. 474 0
      test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/wrappertest/WrapperTestStatemachine.java
  22. 1 1
      test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/AllTestsTestCustom.java
  23. 113 0
      test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/CustomTimerService.java
  24. 91 0
      test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/WrapperTest.java
  25. 202 0
      test-plugins/org.yakindu.sct.test.models/testmodels/SCTUnit/RunnableTest.sct
  26. 143 0
      test-plugins/org.yakindu.sct.test.models/testmodels/SCTUnit/WrapperTest.sct

+ 10 - 2
plugins/org.yakindu.sct.doc.user/help/05_reference/reference.textile

@@ -576,6 +576,14 @@ feature Naming {
 }
 p. ==<!-- End sgen_feature_naming -->==	
 
+==<!-- Start sgen_feature_synchronizedwrapper -->==
+
+h4. SynchronizedWrapper
+
+Add documentation for synchronized wrapper here.
+
+p. ==<!-- End sgen_feature_synchronizedwrapper -->==
+
 ==<!-- Start sgen_feature_runnablewrapper -->==
 
 h4. RunnableWrapper
@@ -593,8 +601,8 @@ Sample configuration:
 
 bc(prettyprint).. 
 feature RunnableWrapper {
-	namePrefix = "org.yakindu.sct"
-	nameSuffix = "Impl"
+	namePrefix = ""
+	nameSuffix = "Runnable"
 }
 p. ==<!-- End sgen_feature_runnablewrapper -->==
 

+ 9 - 0
plugins/org.yakindu.sct.generator.java/library/FeatureTypeLibrary.xmi

@@ -45,4 +45,13 @@
         comment="Name suffix"
         optional="true"/>
   </types>
+  <types name="SynchronizedWrapper"
+      optional="true">
+    <parameters
+        name="namePrefix"
+        optional="true"/>
+    <parameters
+        name="nameSuffix"
+        optional="true"/>
+  </types>
 </sgen:FeatureTypeLibrary>

+ 107 - 130
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/RunnableWrapper.xtend

@@ -1,71 +1,70 @@
 /**
-  Copyright (c) 2015 committers of YAKINDU and others.
-  All rights reserved. This program and the accompanying materials
-  are made available under the terms of the Eclipse Public License v1.0
-  which accompanies this distribution, and is available at
-  http://www.eclipse.org/legal/epl-v10.html
-  Contributors:
-  	Axel Terfloth - Initial contribution and API
-*/
+ *   Copyright (c) 2015 committers of YAKINDU and others.
+ *   All rights reserved. This program and the accompanying materials
+ *   are made available under the terms of the Eclipse Public License v1.0
+ *   which accompanies this distribution, and is available at
+ *   http://www.eclipse.org/legal/epl-v10.html
+ *   Contributors:
+ *   	Markus Mühlbrandt - Initial contribution and API
+ */
 
 package org.yakindu.sct.generator.java
 
-import org.yakindu.sct.model.sexec.ExecutionFlow
-import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.eclipse.xtext.generator.IFileSystemAccess
 import com.google.inject.Inject
-import org.yakindu.sct.model.stext.stext.InterfaceScope
-import org.yakindu.base.types.typesystem.ITypeSystem
+import org.eclipse.xtext.generator.IFileSystemAccess
 import org.yakindu.base.types.Direction
 import org.yakindu.base.types.typesystem.GenericTypeSystem
+import org.yakindu.base.types.typesystem.ITypeSystem
 import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
+import org.yakindu.sct.generator.java.features.CycleBasedWrapperFeature
+import org.yakindu.sct.model.sexec.ExecutionFlow
+import org.yakindu.sct.model.sgen.GeneratorEntry
+import org.yakindu.sct.model.stext.stext.InterfaceScope
+
+import static org.eclipse.xtext.util.Strings.*
 
 /**
- * Generates the runnable wrapper for the state machine. This wrapper implies event based execution semantics. 
+ * Generates the cycle bases synchronized wrapper for the state machine.
  */
-class RunnableWrapper {
+class CycleBasedSynchronizedWrapper {
 
 	@Inject protected extension GenmodelEntries
-	@Inject protected extension RunnableFeature
+	@Inject protected extension CycleBasedWrapperFeature
 
 	@Inject protected extension Naming
 	@Inject protected extension Navigation
 	@Inject protected extension ITypeSystem
 	@Inject protected extension ICodegenTypeSystemAccess
-	
-	
-	@Inject Beautifier beautifier
-	
-	
-	def generateRunnableWrapper(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
-		
-		var filename = flow.getImplementationPackagePath(entry) + '/' + flow.runnableWrapperClassName(entry).java
+
+	def generateCycleWrapper(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
+
+		var filename = flow.getImplementationPackagePath(entry) + '/' + flow.cycleWrapperClassName(entry).java
 		var content = content(flow, entry)
-//		var content = beautifier.format(filename, content(flow, entry))
 		fsa.generateFile(filename, content)
 	}
-	
-	
+
 	def protected content(ExecutionFlow flow, GeneratorEntry entry) '''
 		«entry.licenseText»
 		package «flow.getImplementationPackageName(entry)»;
 		«flow.createImports(entry)»
 		
 		/**
-		 * Runnable wrapper of «flow.statemachineClassName». This wrapper provides a thread-safe, runnable instance of the state machine.
-		 * The wrapper implements the {@link Runnable} interface and can be started in a thread by the client code. 
-		 * The run method then starts the main event processing loop for this state machine.
-		 * 
-		 * This feature is in beta state. Currently not supported are
-		 * - interface observer
-		 * - operation callbacks
+		 * Runnable wrapper of «flow.statemachineClassName». This wrapper provides a thread-safe
+		 * instance of the state machine.
 		 * 
-		 * Please report bugs and issues... 
+		 * Please report bugs and issues...
 		 */
 		
-		public class «flow.runnableWrapperClassName(entry)» implements «flow.statemachineInterfaceName», Runnable {
+		public class «flow.cycleWrapperClassName(entry)» implements «flow.statemachineInterfaceName» {
 			
 			«flow.createFieldDeclarations(entry)»
+			
+			public «flow.cycleWrapperClassName(entry)»() {
+				«FOR scope : flow.interfaceScopes»
+					«scope.interfaceName.asEscapedIdentifier» = new «scope.wrapperInterfaceName(entry)»();
+				«ENDFOR»
+			}
+			
 			«flow.interfaceAccessors»
 			«flow.timingFunctions(entry)»
 			
@@ -114,6 +113,14 @@ class RunnableWrapper {
 				}
 			}
 			
+			/**
+			 * isStateActive() will be delegated thread-safely to the wrapped state machine.  
+			 */
+			public boolean isStateActive(State state) {
+				synchronized(statemachine) {
+					return statemachine.isStateActive(state);
+				}
+			}
 			
 			/**
 			 * runCycle() will be delegated thread-safely to the wrapped state machine.  
@@ -124,105 +131,67 @@ class RunnableWrapper {
 					statemachine.runCycle();
 				}
 			}
-
-			/**
-			 * This method will start the main execution loop for the state machine. 
-			 * First it will init and enter the state machine implicitly and then will start processing events 
-			 * from the event queue until the thread is interrupted. 
-			 */
-			@Override
-			public void run() {
-			
-				boolean terminate = false;
-				
-				while(!(terminate || Thread.currentThread().isInterrupted())) {
-			
-					try {
-						
-						Runnable eventProcessor = eventQueue.take();
-						eventProcessor.run();
-						
-					} catch (InterruptedException e) {
-						terminate = true;
-					}
-				}			
-			}
-
-			
 		}
 	'''
-	
-	def protected createImports(ExecutionFlow flow, GeneratorEntry entry) '''
-		import java.util.concurrent.BlockingQueue;
-		import java.util.concurrent.LinkedBlockingQueue;
 
+	def protected createImports(ExecutionFlow flow, GeneratorEntry entry) '''
 		«IF entry.createInterfaceObserver && flow.hasOutgoingEvents»
-		import java.util.LinkedList;
-		import java.util.List;
+			import java.util.List;
+			
 		«ENDIF»
 		«IF flow.timed»
 			import «entry.getBasePackageName()».ITimer;
 			import «entry.getBasePackageName()».ITimerCallback;
 		«ENDIF»
+		import «flow.getImplementationPackageName(entry)».«flow.statemachineClassName».State;
 	'''
-	
-	def protected createFieldDeclarations(ExecutionFlow flow, GeneratorEntry entry) '''
-		
-		/** 
-		 * The events are queued using a blocking queue without capacity restriction. This queue holds
-		 * Runnable instances that process the events. 
-		 */
-		protected BlockingQueue<Runnable> eventQueue = new LinkedBlockingQueue<Runnable>();
 
+	def protected createFieldDeclarations(ExecutionFlow flow, GeneratorEntry entry) '''
 		/**
-		 * The core state machine is simply wrapped and the event processing will be delegated to that state machine instance.
-		 * This instance will be created implicitly.
+		 * The core state machine is simply wrapped and the event processing will be
+		 * delegated to that state machine instance. This instance will be created
+		 * implicitly.
 		 */
 		protected «flow.statemachineClassName» statemachine = new «flow.statemachineClassName»();
 		
-		«FOR scope : flow.interfaceScopes»
-		/**
-		 * Interface object for «scope.interfaceName»
-		 */		
-		protected «scope.interfaceName» «scope.interfaceName.asEscapedIdentifier» = new «scope.interfaceName»() {
-			«scope.toImplementation(entry)»
-		};
-		
+		«FOR scope : flow.interfaceScopes SEPARATOR newLine»
+			/**
+			 * Interface object for «scope.interfaceName»
+			 */		
+			protected class «scope.wrapperInterfaceName(entry)» implements «scope.interfaceName» {
+				«scope.toImplementation(entry)»
+			};
+			
+			protected «scope.interfaceName» «scope.interfaceName.asEscapedIdentifier»;
 		«ENDFOR»
-		
 	'''
-	
-	
-	def protected toImplementation(InterfaceScope scope, GeneratorEntry entry) '''				
+
+	def protected toImplementation(InterfaceScope scope, GeneratorEntry entry) '''
+		
+		«IF entry.createInterfaceObserver && scope.hasOutgoingEvents»
+			«scope.generateListeners»
+		«ENDIF»
+		«IF scope.hasOperations»
+			«scope.generateOperationCallback»
+		«ENDIF»
 		«FOR event : scope.eventDefinitions»
 			«IF event.direction == Direction::IN»
 				«IF event.type != null && !isSame(event.type, getType(GenericTypeSystem.VOID))»
 					public void raise«event.name.asName»(final «event.type.targetLanguageName» value) {
 						
-						eventQueue.add( new Runnable() {
-							
-							@Override
-							public void run() {
-								synchronized (statemachine) {
-									statemachine.get«scope.interfaceName»().raise«event.name.asName»(value);
-									statemachine.runCycle();
-								}
-							}
-						});
+						synchronized (statemachine) {
+							statemachine.get«scope.interfaceName»().raise«event.name.asName»(value);
+							statemachine.runCycle();
+						}
 					}
 					
 				«ELSE»
 					public void raise«event.name.asName»() {
-						eventQueue.add( new Runnable() {
-							
-							@Override
-							public void run() {
-								synchronized (statemachine) {
-									statemachine.get«scope.interfaceName»().raise«event.name.asName»();
-									statemachine.runCycle();
-								}
-							}
-						});
+						
+						synchronized (statemachine) {
+							statemachine.get«scope.interfaceName»().raise«event.name.asName»();
+							statemachine.runCycle();
+						}
 					}
 					
 				«ENDIF»
@@ -260,19 +229,36 @@ class RunnableWrapper {
 			«ENDIF»
 		«ENDFOR»
 	'''
-
+	
+	protected def generateListeners(InterfaceScope scope) '''
+		public List<«scope.getInterfaceListenerName»> getListeners() {
+			synchronized(statemachine) {
+				return statemachine.get«scope.interfaceName»().getListeners();
+			}
+		}
+		
+	'''
+	
+	protected def generateOperationCallback(InterfaceScope scope) '''
+		public void set«scope.getInterfaceOperationCallbackName»(«scope.getInterfaceOperationCallbackName» operationCallback) {
+			synchronized(statemachine) {
+				statemachine.get«scope.interfaceName»().set«scope.getInterfaceOperationCallbackName»(operationCallback);
+			}
+		}
+		
+	'''
+	
 	def protected interfaceAccessors(ExecutionFlow flow) '''
 		«FOR scope : flow.interfaceScopes»
-			public «scope.interfaceName» get«scope.interfaceName»() {
+			public synchronized «scope.interfaceName» get«scope.interfaceName»() {
 				return «scope.interfaceName.asEscapedIdentifier»;
 			}
 		«ENDFOR»
 	'''
 
-
 	def protected timingFunctions(ExecutionFlow flow, GeneratorEntry entry) '''
 		«IF flow.timed»
-			/*========== TIME EVENT HANDLING ================
+			/*================ TIME EVENT HANDLING ================
 			
 			/** An external timer instance is required. */
 			protected ITimer externalTimer;
@@ -283,19 +269,18 @@ class RunnableWrapper {
 				@Override
 				public void setTimer(ITimerCallback callback, int eventID, long time,
 						boolean isPeriodic) {
-					externalTimer.setTimer(«flow.runnableWrapperClassName(entry)».this, eventID, time, isPeriodic);
+					externalTimer.setTimer(«flow.cycleWrapperClassName(entry)».this, eventID, time, isPeriodic);
 				}
 				
 				@Override
 				public void unsetTimer(ITimerCallback callback, int eventID) {
-					externalTimer.unsetTimer(«flow.runnableWrapperClassName(entry)».this, eventID);
+					externalTimer.unsetTimer(«flow.cycleWrapperClassName(entry)».this, eventID);
 				}
 			};
 			
 			/**
-			 * Set the {@link ITimer} for the state machine. It must be set
-			 * externally on a timed state machine before a run cycle can be correct
-			 * executed.
+			 * Set the {@link ITimer} for the state machine. It must be set externally
+			 * on a timed state machine before a run cycle can be correct executed.
 			 * 
 			 * @param timer
 			 */
@@ -317,19 +302,11 @@ class RunnableWrapper {
 			}
 			
 			public void timeElapsed(int eventID) {
-				eventQueue.add(new Runnable() {
-
-					@Override
-					public void run() {
-						synchronized (statemachine) {
-							statemachine.timeElapsed(eventID);
-							statemachine.runCycle();
-						}
-					}
-				});
+				synchronized (statemachine) {
+					statemachine.timeElapsed(eventID);
+				}
 			}
-			
 		«ENDIF»
 	'''
-	
+
 }

+ 170 - 0
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/EventBasedRunnableWrapper.xtend

@@ -0,0 +1,170 @@
+/**
+  Copyright (c) 2015 committers of YAKINDU and others.
+  All rights reserved. This program and the accompanying materials
+  are made available under the terms of the Eclipse Public License v1.0
+  which accompanies this distribution, and is available at
+  http://www.eclipse.org/legal/epl-v10.html
+  Contributors:
+  	Axel Terfloth - Initial contribution and API
+  	Markus Mühlbrandt - Additions
+  	
+*/
+
+package org.yakindu.sct.generator.java
+
+import org.yakindu.sct.model.sexec.ExecutionFlow
+import org.yakindu.sct.model.sgen.GeneratorEntry
+import org.eclipse.xtext.generator.IFileSystemAccess
+import com.google.inject.Inject
+import org.yakindu.sct.model.stext.stext.InterfaceScope
+import org.yakindu.base.types.typesystem.ITypeSystem
+import org.yakindu.base.types.Direction
+import org.yakindu.base.types.typesystem.GenericTypeSystem
+import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
+import org.yakindu.sct.generator.java.features.EventBasedRunnableFeature
+import org.yakindu.sct.generator.java.features.CycleBasedWrapperFeature
+
+/**
+ * Generates the runnable wrapper for the state machine. This wrapper implies event based execution semantics. 
+ */
+class EventBasedRunnableWrapper {
+
+	@Inject protected extension GenmodelEntries
+	@Inject protected extension EventBasedRunnableFeature
+	@Inject protected extension CycleBasedWrapperFeature
+
+	@Inject protected extension Naming
+	@Inject protected extension Navigation
+	@Inject protected extension ITypeSystem
+	@Inject protected extension ICodegenTypeSystemAccess
+	
+	def generateEventBasedRunnableWrapper(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
+		
+		var filename = flow.getImplementationPackagePath(entry) + '/' + flow.eventBasedWrapperClassName(entry).java
+		var content = content(flow, entry)
+		fsa.generateFile(filename, content)
+	}
+	
+	def protected content(ExecutionFlow flow, GeneratorEntry entry) '''
+		«entry.licenseText»
+		package «flow.getImplementationPackageName(entry)»;
+		«flow.createImports(entry)»
+		
+		/**
+		 * Runnable wrapper of «flow.statemachineClassName». This wrapper provides a
+		 * thread-safe, runnable instance of the state machine. The wrapper implements
+		 * the {@link Runnable} interface and can be started in a thread by the client
+		 * code. The run method then starts the main event processing loop for this
+		 * state machine.
+		 * 
+		 * Please report bugs and issues...
+		 */
+		
+		public class «flow.eventBasedWrapperClassName(entry)» extends «flow.cycleWrapperClassName(entry)» implements Runnable {
+			
+			«flow.createFieldDeclarations(entry)»
+			«flow.timingFunctions(entry)»
+			
+			/**
+			 * This method will start the main execution loop for the state machine.
+			 * First it will init and enter the state machine implicitly and then will
+			 * start processing events from the event queue until the thread is
+			 * interrupted.
+			 */
+			@Override
+			public void run() {
+			
+				boolean terminate = false;
+				
+				while(!(terminate || Thread.currentThread().isInterrupted())) {
+			
+					try {
+						
+						Runnable eventProcessor = eventQueue.take();
+						eventProcessor.run();
+						
+					} catch (InterruptedException e) {
+						terminate = true;
+					}
+				}
+			}
+		}
+	'''
+	
+	def protected createImports(ExecutionFlow flow, GeneratorEntry entry) '''
+		import java.util.concurrent.BlockingQueue;
+		import java.util.concurrent.LinkedBlockingQueue;
+	'''
+	
+	def protected createFieldDeclarations(ExecutionFlow flow, GeneratorEntry entry) '''
+		/**
+		 * The events are queued using a blocking queue without capacity
+		 * restriction. This queue holds Runnable instances that process the events.
+		 */
+		protected BlockingQueue<Runnable> eventQueue = new LinkedBlockingQueue<Runnable>();
+		
+		«FOR scope : flow.interfaceScopes»
+		/**
+		 * Interface object for «scope.interfaceName»
+		 */		
+		protected «scope.interfaceName» «scope.interfaceName.asEscapedIdentifier» = new «scope.wrapperInterfaceName(entry)»() {
+			«scope.toImplementation(entry)»
+		};
+		
+		«ENDFOR»
+	'''
+	
+	def protected toImplementation(InterfaceScope scope, GeneratorEntry entry) '''				
+		«FOR event : scope.eventDefinitions»
+			«IF event.direction == Direction::IN»
+				«IF event.type != null && !isSame(event.type, getType(GenericTypeSystem.VOID))»
+					public void raise«event.name.asName»(final «event.type.targetLanguageName» value) {
+						
+						eventQueue.add( new Runnable() {
+							
+							@Override
+							public void run() {
+								synchronized (statemachine) {
+									statemachine.get«scope.interfaceName»().raise«event.name.asName»(value);
+									statemachine.runCycle();
+								}
+							}
+						});
+					}
+					
+				«ELSE»
+					public void raise«event.name.asName»() {
+						eventQueue.add( new Runnable() {
+							
+							@Override
+							public void run() {
+								synchronized (statemachine) {
+									statemachine.get«scope.interfaceName»().raise«event.name.asName»();
+									statemachine.runCycle();
+								}
+							}
+						});
+					}
+					
+				«ENDIF»
+			«ENDIF»
+		«ENDFOR»
+	'''
+
+	def protected timingFunctions(ExecutionFlow flow, GeneratorEntry entry) '''
+		«IF flow.timed»
+			public void timeElapsed(final int eventID) {
+				eventQueue.add(new Runnable() {
+
+					@Override
+					public void run() {
+						synchronized (statemachine) {
+							statemachine.timeElapsed(eventID);
+							statemachine.runCycle();
+						}
+					}
+				});
+			}
+		«ENDIF»
+	'''
+}

+ 12 - 4
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/JavaGenerator.xtend

@@ -14,6 +14,8 @@ import org.eclipse.xtext.generator.IFileSystemAccess
 import org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator
 import org.yakindu.sct.model.sexec.ExecutionFlow
 import org.yakindu.sct.model.sgen.GeneratorEntry
+import org.yakindu.sct.generator.java.features.EventBasedRunnableFeature
+import org.yakindu.sct.generator.java.features.CycleBasedWrapperFeature
 
 /**
  * This is the Java code generators main class. 
@@ -24,7 +26,8 @@ import org.yakindu.sct.model.sgen.GeneratorEntry
 class JavaGenerator implements IExecutionFlowGenerator {
 
 	@Inject extension GenmodelEntries
-	@Inject extension RunnableFeature
+	@Inject extension EventBasedRunnableFeature
+	@Inject extension CycleBasedWrapperFeature
 
 	@Inject extension Navigation
 	@Inject extension IStatemachine
@@ -34,7 +37,8 @@ class JavaGenerator implements IExecutionFlowGenerator {
 	@Inject extension RuntimeService
 	@Inject extension StatemachineInterface
 	@Inject extension Statemachine
-	@Inject extension RunnableWrapper
+	@Inject extension EventBasedRunnableWrapper
+	@Inject extension CycleBasedSynchronizedWrapper
  	
 	override generate(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
 
@@ -55,8 +59,12 @@ class JavaGenerator implements IExecutionFlowGenerator {
 		flow.generateStatemachineInterface(entry, fsa)
 		flow.generateStatemachine(entry, fsa)
 		
-		if (entry.hasFeatureRunnable) {
-			flow.generateRunnableWrapper(entry, fsa)
+		if (entry.hasFeatureCycleWrapper || entry.hasFeatureEventRunnable) {
+			flow.generateCycleWrapper(entry, fsa)
+		}
+		
+		if (entry.hasFeatureEventRunnable) {
+			flow.generateEventBasedRunnableWrapper(entry, fsa)
 		}
 	}
 }

+ 0 - 46
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/RunnableFeature.xtend

@@ -1,46 +0,0 @@
-/** 
- * Copyright (c) 2015 committers of YAKINDU and others. 
- * All rights reserved. This program and the accompanying materials 
- * are made available under the terms of the Eclipse Public License v1.0 
- * which accompanies this distribution, and is available at 
- * http://www.eclipse.org/legal/epl-v10.html 
- * Contributors:
- * committers of YAKINDU - initial API and implementation
- *
-*/
-package org.yakindu.sct.generator.java
-
-import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.yakindu.sct.generator.java.features.IJavaFeatureConstants
-import org.yakindu.sct.model.sexec.ExecutionFlow
-import com.google.inject.Inject
-
-class RunnableFeature {
-	
-	@Inject extension Naming
-	
-	
-	def getFeatureRunnable(GeneratorEntry it) {
-		getFeatureConfiguration(IJavaFeatureConstants::RUNNABLE_WRAPPER);
-	}
-	
-	def hasFeatureRunnable(GeneratorEntry it) {
-		featureRunnable != null
-	}
-	
-	def getNamePrefix(GeneratorEntry it) {
-		if (featureRunnable != null) featureRunnable.getParameterValue(IJavaFeatureConstants::NAME_PREFIX).stringValue
-		else ""	
-	}
-	
-	def getNameSuffix(GeneratorEntry it) {
-		if (featureRunnable != null) featureRunnable.getParameterValue(IJavaFeatureConstants::NAME_SUFFIX).stringValue
-		else ""	
-	}
-	
-	
-	def runnableWrapperClassName(ExecutionFlow it, GeneratorEntry entry) {
-		 entry.namePrefix + statemachineName + entry.nameSuffix 
-	}
-	
-}

+ 3 - 3
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/Statemachine.xtend

@@ -240,7 +240,7 @@ class Statemachine {
 		/**
 		* Returns true if the given state is currently active otherwise false.
 		*/
-		public boolean isStateActive(State state){
+		public boolean isStateActive(State state) {
 			switch (state) {
 				«FOR s : flow.states»
 				case «s.stateName.asEscapedIdentifier» : 
@@ -341,7 +341,7 @@ class Statemachine {
 		protected class «scope.getInterfaceImplName» implements «scope.getInterfaceName» {
 		
 		«IF entry.createInterfaceObserver && scope.hasOutgoingEvents»
-			«scope.generateListeners»
+			«scope.generateListenerSupport»
 		«ENDIF»
 		
 		«IF scope.hasOperations»
@@ -489,7 +489,7 @@ class Statemachine {
 	'''
 	
 	
-	protected def generateListeners(InterfaceScope scope) '''
+	protected def generateListenerSupport(InterfaceScope scope) '''
 		private List<«scope.getInterfaceListenerName»> listeners = new LinkedList<«scope.getInterfaceListenerName»>();
 		
 		public List<«scope.getInterfaceListenerName»> getListeners() {

+ 10 - 0
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/TimerService.xtend

@@ -34,6 +34,8 @@ class TimerService {
 		import java.util.List;
 		import java.util.Timer;
 		import java.util.TimerTask;
+		import java.util.concurrent.locks.Lock;
+		import java.util.concurrent.locks.ReentrantLock;
 		
 		/**
 		 * Default timer service implementation.
@@ -45,6 +47,8 @@ class TimerService {
 			
 			private final List<TimeEventTask> timerTaskList = new ArrayList<TimeEventTask>();
 			
+			private final Lock lock = new ReentrantLock();
+			
 			/**
 			 * Timer task that reflects a time event. It's internally used by
 			 * {@link TimerService}.
@@ -90,6 +94,7 @@ class TimerService {
 			
 				// Create a new TimerTask for given event and store it.
 				TimeEventTask timerTask = new TimeEventTask(callback, eventID);
+				lock.lock();
 				timerTaskList.add(timerTask);
 			
 				// start scheduling the timer
@@ -98,15 +103,18 @@ class TimerService {
 				} else {
 					timer.schedule(timerTask, time);
 				}
+				lock.unlock();
 			}
 			
 			public void unsetTimer(ITimerCallback callback, int eventID) {
+				lock.lock();
 				int index = timerTaskList.indexOf(new TimeEventTask(callback, eventID));
 				if (index != -1) {
 					timerTaskList.get(index).cancel();
 					timer.purge();
 					timerTaskList.remove(index);
 				}
+				lock.unlock();
 			}
 			
 			/**
@@ -114,8 +122,10 @@ class TimerService {
 			 * memory resources.
 			 */
 			public void cancel() {
+				lock.lock();
 				timer.cancel();
 				timer.purge();
+				lock.unlock();
 			}
 		}
 

+ 55 - 0
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/CycleBasedWrapperFeature.xtend

@@ -0,0 +1,55 @@
+/** 
+ * Copyright (c) 2015 committers of YAKINDU and others. 
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution, and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ * Contributors:
+ * committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.generator.java.features
+
+import org.yakindu.sct.model.sgen.GeneratorEntry
+import org.yakindu.sct.generator.java.features.IJavaFeatureConstants
+import org.yakindu.sct.model.sexec.ExecutionFlow
+import com.google.inject.Inject
+import org.yakindu.sct.generator.java.Naming
+import org.yakindu.sct.model.stext.stext.InterfaceScope
+
+class CycleBasedWrapperFeature {
+
+	@Inject extension Naming
+
+	def getFeatureCycleWrapper(GeneratorEntry it) {
+		getFeatureConfiguration(IJavaFeatureConstants::FEATURE_SYCHRONIZED_WRAPPER);
+	}
+
+	def hasFeatureCycleWrapper(GeneratorEntry it) {
+		featureCycleWrapper != null
+	}
+
+	def getNamePrefix(GeneratorEntry it) {
+		if (featureCycleWrapper != null &&
+			featureCycleWrapper.getParameterValue(IJavaFeatureConstants::VALUE_NAME_PREFIX) != null)
+			featureCycleWrapper.getParameterValue(IJavaFeatureConstants::VALUE_NAME_PREFIX).stringValue
+		else
+			IJavaFeatureConstants::SYCHRONIZED_WRAPPER_NAME_PREFIX_DEFAULT
+	}
+
+	def getNameSuffix(GeneratorEntry it) {
+		if (featureCycleWrapper != null &&
+			featureCycleWrapper.getParameterValue(IJavaFeatureConstants::VALUE_NAME_PREFIX) != null)
+			featureCycleWrapper.getParameterValue(IJavaFeatureConstants::VALUE_NAME_SUFFIX).stringValue
+		else
+			IJavaFeatureConstants::SYCHRONIZED_WRAPPER_NAME_SUFFIX_DEFAULT
+	}
+
+	def cycleWrapperClassName(ExecutionFlow it, GeneratorEntry entry) {
+		entry.namePrefix + statemachineClassName + entry.nameSuffix
+	}
+	
+	def wrapperInterfaceName(InterfaceScope it, GeneratorEntry entry) {
+		entry.namePrefix + interfaceName + entry.nameSuffix
+	}
+}

+ 49 - 0
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/EventBasedRunnableFeature.xtend

@@ -0,0 +1,49 @@
+/** 
+ * Copyright (c) 2015 committers of YAKINDU and others. 
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Eclipse Public License v1.0 
+ * which accompanies this distribution, and is available at 
+ * http://www.eclipse.org/legal/epl-v10.html 
+ * Contributors:
+ * committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.generator.java.features
+
+import org.yakindu.sct.model.sgen.GeneratorEntry
+import org.yakindu.sct.generator.java.features.IJavaFeatureConstants
+import org.yakindu.sct.model.sexec.ExecutionFlow
+import com.google.inject.Inject
+import org.yakindu.sct.generator.java.Naming
+
+class EventBasedRunnableFeature {
+
+	@Inject extension Naming
+
+	def getFeatureEventRunnable(GeneratorEntry it) {
+		getFeatureConfiguration(IJavaFeatureConstants::FEATURE_RUNNABLE_WRAPPER);
+	}
+
+	def hasFeatureEventRunnable(GeneratorEntry it) {
+		featureEventRunnable != null
+	}
+
+	def getNamePrefix(GeneratorEntry it) {
+		if (featureEventRunnable != null &&
+			featureEventRunnable.getParameterValue(IJavaFeatureConstants::VALUE_NAME_PREFIX) != null)
+			featureEventRunnable.getParameterValue(IJavaFeatureConstants::VALUE_NAME_PREFIX).stringValue
+		else
+			IJavaFeatureConstants::RUNNABLE_WRAPPER_NAME_PREFIX_DEFAULT
+	}
+
+	def getNameSuffix(GeneratorEntry it) {
+		if (featureEventRunnable != null)
+			featureEventRunnable.getParameterValue(IJavaFeatureConstants::VALUE_NAME_SUFFIX).stringValue
+		else
+			IJavaFeatureConstants::RUNNABLE_WRAPPER_NAME_SUFFIX_DEFAULT
+	}
+
+	def eventBasedWrapperClassName(ExecutionFlow it, GeneratorEntry entry) {
+		entry.namePrefix + statemachineClassName + entry.nameSuffix
+	}
+}

+ 10 - 3
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/IJavaFeatureConstants.java

@@ -44,14 +44,21 @@ public interface IJavaFeatureConstants {
 	
 	/* Constants related to the RunnableWrapper feature */
 	
-	public static final String RUNNABLE_WRAPPER = "RunnableWrapper";
+	public static final String FEATURE_RUNNABLE_WRAPPER = "RunnableWrapper";
 	
-	public static final String NAME_PREFIX = "namePrefix";
+	public static final String RUNNABLE_WRAPPER_NAME_PREFIX_DEFAULT = "";
 	
-	public static final String NAME_SUFFIX = "nameSuffix";
+	public static final String RUNNABLE_WRAPPER_NAME_SUFFIX_DEFAULT = "Runnable";
 	
+	public static final String FEATURE_SYCHRONIZED_WRAPPER = "SynchronizedWrapper";
 	
+	public static final String SYCHRONIZED_WRAPPER_NAME_PREFIX_DEFAULT = "Synchronized";
 	
+	public static final String SYCHRONIZED_WRAPPER_NAME_SUFFIX_DEFAULT = "";
+	
+	public static final String VALUE_NAME_PREFIX = "namePrefix";
+	
+	public static final String VALUE_NAME_SUFFIX = "nameSuffix";
 	
 	public static final String[] JAVA_KEYWORDS = { "abstract", "assert",
 		"boolean", "break", "byte", "case", "catch", "char", "class",

+ 12 - 4
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/features/JavaFeatureValueProvider.java

@@ -42,10 +42,18 @@ public class JavaFeatureValueProvider extends AbstractDefaultFeatureValueProvide
 			parameterValue.setValue("org.yakindu.sct");
 		} else if (parameterValue.getParameter().getName().equals(IMPLEMENTATION_SUFFIX)) {
 			parameterValue.setValue("impl");
-		} else if (parameterValue.getParameter().getName().equals(NAME_PREFIX)) {
-			parameterValue.setValue("Runnable");
-		} else if (parameterValue.getParameter().getName().equals(NAME_SUFFIX)) {
-			parameterValue.setValue("");
+		} else if (featureType.getName().equals(FEATURE_RUNNABLE_WRAPPER)) {
+			if (parameterValue.getParameter().getName().equals(VALUE_NAME_PREFIX)) {
+				parameterValue.setValue(RUNNABLE_WRAPPER_NAME_PREFIX_DEFAULT);
+			} else if (parameterValue.getParameter().getName().equals(VALUE_NAME_SUFFIX)) {
+				parameterValue.setValue(RUNNABLE_WRAPPER_NAME_SUFFIX_DEFAULT);
+			}
+		} else if (featureType.getName().equals(FEATURE_SYCHRONIZED_WRAPPER)) {
+			if (parameterValue.getParameter().getName().equals(VALUE_NAME_PREFIX)) {
+				parameterValue.setValue(SYCHRONIZED_WRAPPER_NAME_PREFIX_DEFAULT);
+			} else if (parameterValue.getParameter().getName().equals(VALUE_NAME_SUFFIX)) {
+				parameterValue.setValue(SYCHRONIZED_WRAPPER_NAME_SUFFIX_DEFAULT);
+			}
 		}
 	}
 

+ 36 - 0
test-plugins/org.yakindu.sct.generator.java.test/model/model.sgen

@@ -1519,5 +1519,41 @@ GeneratorModel for yakindu::java {
 			inlineExitRegion = false
 			inlineEntries = false
 		}
+	}
+	
+	statechart WrapperTest {
+
+		feature Outlet {
+			targetProject = "org.yakindu.sct.generator.java.test"
+			targetFolder = "src-gen"
+		}
+
+		feature GeneralFeatures {
+			RuntimeService = true
+			InterfaceObserverSupport = true
+		}
+		
+		feature SynchronizedWrapper {
+			namePrefix =  "Synchronized" 
+			nameSuffix =  "" 
+		}
+	}
+	
+	statechart RunnableTest {
+
+		feature Outlet {
+			targetProject = "org.yakindu.sct.generator.java.test"
+			targetFolder = "src-gen"
+		}
+
+		feature GeneralFeatures {
+			RuntimeService = true
+			InterfaceObserverSupport = true
+		}
+		
+		feature RunnableWrapper {
+			namePrefix =  "" 
+			nameSuffix =  "Runnable" 
+		}
 	}	
 }

+ 10 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/TimerService.java

@@ -4,6 +4,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * Default timer service implementation.
@@ -15,6 +17,8 @@ public class TimerService implements ITimer {
 	
 	private final List<TimeEventTask> timerTaskList = new ArrayList<TimeEventTask>();
 	
+	private final Lock lock = new ReentrantLock();
+	
 	/**
 	 * Timer task that reflects a time event. It's internally used by
 	 * {@link TimerService}.
@@ -60,6 +64,7 @@ public class TimerService implements ITimer {
 	
 		// Create a new TimerTask for given event and store it.
 		TimeEventTask timerTask = new TimeEventTask(callback, eventID);
+		lock.lock();
 		timerTaskList.add(timerTask);
 	
 		// start scheduling the timer
@@ -68,15 +73,18 @@ public class TimerService implements ITimer {
 		} else {
 			timer.schedule(timerTask, time);
 		}
+		lock.unlock();
 	}
 	
 	public void unsetTimer(ITimerCallback callback, int eventID) {
+		lock.lock();
 		int index = timerTaskList.indexOf(new TimeEventTask(callback, eventID));
 		if (index != -1) {
 			timerTaskList.get(index).cancel();
 			timer.purge();
 			timerTaskList.remove(index);
 		}
+		lock.unlock();
 	}
 	
 	/**
@@ -84,8 +92,10 @@ public class TimerService implements ITimer {
 	 * memory resources.
 	 */
 	public void cancel() {
+		lock.lock();
 		timer.cancel();
 		timer.purge();
+		lock.unlock();
 	}
 }
 

+ 35 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/IRunnableTestStatemachine.java

@@ -0,0 +1,35 @@
+package org.yakindu.scr.runnabletest;
+import java.util.List;
+import org.yakindu.scr.IStatemachine;
+import org.yakindu.scr.ITimerCallback;
+
+public interface IRunnableTestStatemachine extends ITimerCallback, IStatemachine {
+
+	public interface SCInterface {
+		public boolean isRaisedEv_out();
+		public long getEv_outValue();
+		public void raiseEv_in(long value);
+		public long getMyVar();
+		public void setMyVar(long value);
+		public long getAfterCalls();
+		public void setAfterCalls(long value);
+		public long getCycles();
+		public void setCycles(long value);
+		public long getS2_entered();
+		public void setS2_entered(long value);
+		public List<SCInterfaceListener> getListeners();
+
+		public void setSCInterfaceOperationCallback(SCInterfaceOperationCallback operationCallback);
+	}
+
+	public interface SCInterfaceListener {
+		public void onEv_outRaised(long value);
+	}
+
+	public interface SCInterfaceOperationCallback {
+		public void displayTime();
+	}
+
+	public SCInterface getSCInterface();
+
+}

+ 576 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/RunnableTestStatemachine.java

@@ -0,0 +1,576 @@
+package org.yakindu.scr.runnabletest;
+import java.util.LinkedList;
+import java.util.List;
+import org.yakindu.scr.ITimer;
+
+public class RunnableTestStatemachine implements IRunnableTestStatemachine {
+
+	protected class SCInterfaceImpl implements SCInterface {
+
+		private List<SCInterfaceListener> listeners = new LinkedList<SCInterfaceListener>();
+
+		public List<SCInterfaceListener> getListeners() {
+			return listeners;
+		}
+
+		private SCInterfaceOperationCallback operationCallback;
+
+		public void setSCInterfaceOperationCallback(SCInterfaceOperationCallback operationCallback) {
+			this.operationCallback = operationCallback;
+		}
+
+		private boolean ev_out;
+
+		private long ev_outValue;
+
+		public boolean isRaisedEv_out() {
+			return ev_out;
+		}
+
+		protected void raiseEv_out(long value) {
+			ev_out = true;
+			ev_outValue = value;
+			for (SCInterfaceListener listener : listeners) {
+				listener.onEv_outRaised(value);
+			}
+		}
+
+		public long getEv_outValue() {
+			if (!ev_out)
+				throw new IllegalStateException("Illegal event value acces. Event Ev_out is not raised!");
+			return ev_outValue;
+		}
+
+		private boolean ev_in;
+
+		private long ev_inValue;
+
+		public void raiseEv_in(long value) {
+			ev_in = true;
+			ev_inValue = value;
+		}
+
+		protected long getEv_inValue() {
+			if (!ev_in)
+				throw new IllegalStateException("Illegal event value acces. Event Ev_in is not raised!");
+			return ev_inValue;
+		}
+
+		private long myVar;
+
+		public long getMyVar() {
+			return myVar;
+		}
+
+		public void setMyVar(long value) {
+			this.myVar = value;
+		}
+
+		private long afterCalls;
+
+		public long getAfterCalls() {
+			return afterCalls;
+		}
+
+		public void setAfterCalls(long value) {
+			this.afterCalls = value;
+		}
+
+		private long cycles;
+
+		public long getCycles() {
+			return cycles;
+		}
+
+		public void setCycles(long value) {
+			this.cycles = value;
+		}
+
+		private long s2_entered;
+
+		public long getS2_entered() {
+			return s2_entered;
+		}
+
+		public void setS2_entered(long value) {
+			this.s2_entered = value;
+		}
+
+		protected void clearEvents() {
+			ev_in = false;
+		}
+
+		protected void clearOutEvents() {
+			ev_out = false;
+		}
+	}
+
+	protected SCInterfaceImpl sCInterface;
+
+	private boolean initialized = false;
+
+	public enum State {
+		main_region__final_, main_region_Composite_s1_s2, main_region_Composite_s1_s2_inner_region_s1, main_region_Composite_s1_s2_inner_region_s2, $NullState$
+	};
+
+	private final State[] stateVector = new State[1];
+
+	private int nextStateIndex;
+
+	private ITimer timer;
+
+	private final boolean[] timeEvents = new boolean[3];
+
+	public RunnableTestStatemachine() {
+
+		sCInterface = new SCInterfaceImpl();
+	}
+
+	public void init() {
+		this.initialized = true;
+		if (timer == null) {
+			throw new IllegalStateException("timer not set.");
+		}
+		for (int i = 0; i < 1; i++) {
+			stateVector[i] = State.$NullState$;
+		}
+
+		clearEvents();
+		clearOutEvents();
+
+		sCInterface.setMyVar(0);
+
+		sCInterface.setAfterCalls(0);
+
+		sCInterface.setCycles(0);
+
+		sCInterface.setS2_entered(0);
+	}
+
+	public void enter() {
+		if (!initialized)
+			throw new IllegalStateException(
+					"The state machine needs to be initialized first by calling the init() function.");
+
+		if (timer == null) {
+			throw new IllegalStateException("timer not set.");
+		}
+		entryAction();
+
+		enterSequence_main_region_default();
+	}
+
+	public void exit() {
+		exitSequence_main_region();
+
+		exitAction();
+	}
+
+	/**
+	 * @see IStatemachine#isActive()
+	 */
+	public boolean isActive() {
+
+		return stateVector[0] != State.$NullState$;
+	}
+
+	/** 
+	 * @see IStatemachine#isFinal() 
+	 */
+	public boolean isFinal() {
+		return (stateVector[0] == State.main_region__final_);
+	}
+
+	/**
+	* This method resets the incoming events (time events included).
+	*/
+	protected void clearEvents() {
+		sCInterface.clearEvents();
+
+		for (int i = 0; i < timeEvents.length; i++) {
+			timeEvents[i] = false;
+		}
+	}
+
+	/**
+	* This method resets the outgoing events.
+	*/
+	protected void clearOutEvents() {
+		sCInterface.clearOutEvents();
+	}
+
+	/**
+	* Returns true if the given state is currently active otherwise false.
+	*/
+	public boolean isStateActive(State state) {
+		switch (state) {
+			case main_region__final_ :
+				return stateVector[0] == State.main_region__final_;
+			case main_region_Composite_s1_s2 :
+				return stateVector[0].ordinal() >= State.main_region_Composite_s1_s2.ordinal()
+						&& stateVector[0].ordinal() <= State.main_region_Composite_s1_s2_inner_region_s2.ordinal();
+			case main_region_Composite_s1_s2_inner_region_s1 :
+				return stateVector[0] == State.main_region_Composite_s1_s2_inner_region_s1;
+			case main_region_Composite_s1_s2_inner_region_s2 :
+				return stateVector[0] == State.main_region_Composite_s1_s2_inner_region_s2;
+			default :
+				return false;
+		}
+	}
+
+	/**
+	* Set the {@link ITimer} for the state machine. It must be set
+	* externally on a timed state machine before a run cycle can be correct
+	* executed.
+	* 
+	* @param timer
+	*/
+	public void setTimer(ITimer timer) {
+		this.timer = timer;
+	}
+
+	/**
+	* Returns the currently used timer.
+	* 
+	* @return {@link ITimer}
+	*/
+	public ITimer getTimer() {
+		return timer;
+	}
+
+	public void timeElapsed(int eventID) {
+		timeEvents[eventID] = true;
+	}
+
+	public SCInterface getSCInterface() {
+		return sCInterface;
+	}
+
+	public boolean isRaisedEv_out() {
+		return sCInterface.isRaisedEv_out();
+	}
+	public long getEv_outValue() {
+		return sCInterface.getEv_outValue();
+	}
+	public void raiseEv_in(long value) {
+		sCInterface.raiseEv_in(value);
+	}
+
+	public long getMyVar() {
+		return sCInterface.getMyVar();
+	}
+
+	public void setMyVar(long value) {
+		sCInterface.setMyVar(value);
+	}
+	public long getAfterCalls() {
+		return sCInterface.getAfterCalls();
+	}
+
+	public void setAfterCalls(long value) {
+		sCInterface.setAfterCalls(value);
+	}
+	public long getCycles() {
+		return sCInterface.getCycles();
+	}
+
+	public void setCycles(long value) {
+		sCInterface.setCycles(value);
+	}
+	public long getS2_entered() {
+		return sCInterface.getS2_entered();
+	}
+
+	public void setS2_entered(long value) {
+		sCInterface.setS2_entered(value);
+	}
+
+	private boolean check__lr0() {
+		return timeEvents[2];
+	}
+
+	private boolean check__lr1() {
+		return true;
+	}
+
+	private boolean check_main_region_Composite_s1_s2_tr0_tr0() {
+		return timeEvents[0];
+	}
+
+	private boolean check_main_region_Composite_s1_s2_inner_region_s1_tr0_tr0() {
+		return sCInterface.ev_in;
+	}
+
+	private boolean check_main_region_Composite_s1_s2_inner_region_s1_tr1_tr1() {
+		return timeEvents[1];
+	}
+
+	private boolean check_main_region_Composite_s1_s2_inner_region_s2_tr0_tr0() {
+		return sCInterface.ev_in;
+	}
+
+	private void effect__lr0() {
+		sCInterface.operationCallback.displayTime();
+	}
+
+	private void effect__lr1() {
+		sCInterface.setCycles(sCInterface.getCycles() + 1);
+	}
+
+	private void effect_main_region_Composite_s1_s2_tr0() {
+		exitSequence_main_region_Composite_s1_s2();
+
+		enterSequence_main_region__final__default();
+	}
+
+	private void effect_main_region_Composite_s1_s2_inner_region_s1_tr0() {
+		exitSequence_main_region_Composite_s1_s2_inner_region_s1();
+
+		enterSequence_main_region_Composite_s1_s2_inner_region_s2_default();
+	}
+
+	private void effect_main_region_Composite_s1_s2_inner_region_s1_tr1() {
+		exitSequence_main_region_Composite_s1_s2_inner_region_s1();
+
+		sCInterface.setAfterCalls(sCInterface.getAfterCalls() + 1);
+
+		enterSequence_main_region_Composite_s1_s2_inner_region_s1_default();
+	}
+
+	private void effect_main_region_Composite_s1_s2_inner_region_s2_tr0() {
+		exitSequence_main_region_Composite_s1_s2_inner_region_s2();
+
+		enterSequence_main_region_Composite_s1_s2_inner_region_s1_default();
+	}
+
+	/* Entry action for statechart 'RunnableTest'. */
+	private void entryAction() {
+
+		timer.setTimer(this, 2, 1 * 1000, true);
+	}
+
+	/* Entry action for state 'Composite_s1_s2'. */
+	private void entryAction_main_region_Composite_s1_s2() {
+
+		timer.setTimer(this, 0, 10 * 1000, false);
+	}
+
+	/* Entry action for state 's1'. */
+	private void entryAction_main_region_Composite_s1_s2_inner_region_s1() {
+
+		timer.setTimer(this, 1, 500, false);
+
+		sCInterface.raiseEv_out(2);
+	}
+
+	/* Entry action for state 's2'. */
+	private void entryAction_main_region_Composite_s1_s2_inner_region_s2() {
+		sCInterface.setS2_entered(sCInterface.getS2_entered() + 1);
+	}
+
+	/* Exit action for state 'RunnableTest'. */
+	private void exitAction() {
+		timer.unsetTimer(this, 2);
+	}
+
+	/* Exit action for state 'Composite_s1_s2'. */
+	private void exitAction_main_region_Composite_s1_s2() {
+		timer.unsetTimer(this, 0);
+	}
+
+	/* Exit action for state 's1'. */
+	private void exitAction_main_region_Composite_s1_s2_inner_region_s1() {
+		timer.unsetTimer(this, 1);
+	}
+
+	/* Default enter sequence for state null */
+	private void enterSequence_main_region__final__default() {
+		nextStateIndex = 0;
+		stateVector[0] = State.main_region__final_;
+	}
+
+	/* 'default' enter sequence for state Composite_s1_s2 */
+	private void enterSequence_main_region_Composite_s1_s2_default() {
+		entryAction_main_region_Composite_s1_s2();
+
+		enterSequence_main_region_Composite_s1_s2_inner_region_default();
+	}
+
+	/* 'default' enter sequence for state s1 */
+	private void enterSequence_main_region_Composite_s1_s2_inner_region_s1_default() {
+		entryAction_main_region_Composite_s1_s2_inner_region_s1();
+
+		nextStateIndex = 0;
+		stateVector[0] = State.main_region_Composite_s1_s2_inner_region_s1;
+	}
+
+	/* 'default' enter sequence for state s2 */
+	private void enterSequence_main_region_Composite_s1_s2_inner_region_s2_default() {
+		entryAction_main_region_Composite_s1_s2_inner_region_s2();
+
+		nextStateIndex = 0;
+		stateVector[0] = State.main_region_Composite_s1_s2_inner_region_s2;
+	}
+
+	/* 'default' enter sequence for region main region */
+	private void enterSequence_main_region_default() {
+		react_main_region__entry_Default();
+	}
+
+	/* 'default' enter sequence for region inner region */
+	private void enterSequence_main_region_Composite_s1_s2_inner_region_default() {
+		react_main_region_Composite_s1_s2_inner_region__entry_Default();
+	}
+
+	/* Default exit sequence for final state. */
+	private void exitSequence_main_region__final_() {
+		nextStateIndex = 0;
+		stateVector[0] = State.$NullState$;
+	}
+
+	/* Default exit sequence for state Composite_s1_s2 */
+	private void exitSequence_main_region_Composite_s1_s2() {
+		exitSequence_main_region_Composite_s1_s2_inner_region();
+
+		exitAction_main_region_Composite_s1_s2();
+	}
+
+	/* Default exit sequence for state s1 */
+	private void exitSequence_main_region_Composite_s1_s2_inner_region_s1() {
+		nextStateIndex = 0;
+		stateVector[0] = State.$NullState$;
+
+		exitAction_main_region_Composite_s1_s2_inner_region_s1();
+	}
+
+	/* Default exit sequence for state s2 */
+	private void exitSequence_main_region_Composite_s1_s2_inner_region_s2() {
+		nextStateIndex = 0;
+		stateVector[0] = State.$NullState$;
+	}
+
+	/* Default exit sequence for region main region */
+	private void exitSequence_main_region() {
+		switch (stateVector[0]) {
+			case main_region__final_ :
+				exitSequence_main_region__final_();
+				break;
+
+			case main_region_Composite_s1_s2_inner_region_s1 :
+				exitSequence_main_region_Composite_s1_s2_inner_region_s1();
+
+				exitAction_main_region_Composite_s1_s2();
+				break;
+
+			case main_region_Composite_s1_s2_inner_region_s2 :
+				exitSequence_main_region_Composite_s1_s2_inner_region_s2();
+
+				exitAction_main_region_Composite_s1_s2();
+				break;
+
+			default :
+				break;
+		}
+	}
+
+	/* Default exit sequence for region inner region */
+	private void exitSequence_main_region_Composite_s1_s2_inner_region() {
+		switch (stateVector[0]) {
+			case main_region_Composite_s1_s2_inner_region_s1 :
+				exitSequence_main_region_Composite_s1_s2_inner_region_s1();
+				break;
+
+			case main_region_Composite_s1_s2_inner_region_s2 :
+				exitSequence_main_region_Composite_s1_s2_inner_region_s2();
+				break;
+
+			default :
+				break;
+		}
+	}
+
+	/* The reactions of state null. */
+	private void react_main_region__final_() {
+		if (check__lr0()) {
+			effect__lr0();
+		}
+
+		effect__lr1();
+
+	}
+
+	/* The reactions of state s1. */
+	private void react_main_region_Composite_s1_s2_inner_region_s1() {
+		if (check__lr0()) {
+			effect__lr0();
+		}
+
+		effect__lr1();
+
+		if (check_main_region_Composite_s1_s2_tr0_tr0()) {
+			effect_main_region_Composite_s1_s2_tr0();
+		} else {
+			if (check_main_region_Composite_s1_s2_inner_region_s1_tr0_tr0()) {
+				effect_main_region_Composite_s1_s2_inner_region_s1_tr0();
+			} else {
+				if (check_main_region_Composite_s1_s2_inner_region_s1_tr1_tr1()) {
+					effect_main_region_Composite_s1_s2_inner_region_s1_tr1();
+				}
+			}
+		}
+	}
+
+	/* The reactions of state s2. */
+	private void react_main_region_Composite_s1_s2_inner_region_s2() {
+		if (check__lr0()) {
+			effect__lr0();
+		}
+
+		effect__lr1();
+
+		if (check_main_region_Composite_s1_s2_tr0_tr0()) {
+			effect_main_region_Composite_s1_s2_tr0();
+		} else {
+			if (check_main_region_Composite_s1_s2_inner_region_s2_tr0_tr0()) {
+				effect_main_region_Composite_s1_s2_inner_region_s2_tr0();
+			}
+		}
+	}
+
+	/* Default react sequence for initial entry  */
+	private void react_main_region__entry_Default() {
+		enterSequence_main_region_Composite_s1_s2_default();
+	}
+
+	/* Default react sequence for initial entry  */
+	private void react_main_region_Composite_s1_s2_inner_region__entry_Default() {
+		enterSequence_main_region_Composite_s1_s2_inner_region_s1_default();
+	}
+
+	public void runCycle() {
+		if (!initialized)
+			throw new IllegalStateException(
+					"The state machine needs to be initialized first by calling the init() function.");
+
+		clearOutEvents();
+
+		for (nextStateIndex = 0; nextStateIndex < stateVector.length; nextStateIndex++) {
+
+			switch (stateVector[nextStateIndex]) {
+				case main_region__final_ :
+					react_main_region__final_();
+					break;
+				case main_region_Composite_s1_s2_inner_region_s1 :
+					react_main_region_Composite_s1_s2_inner_region_s1();
+					break;
+				case main_region_Composite_s1_s2_inner_region_s2 :
+					react_main_region_Composite_s1_s2_inner_region_s2();
+					break;
+				default :
+					// $NullState$
+			}
+		}
+
+		clearEvents();
+	}
+}

+ 79 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/RunnableTestStatemachineRunnable.java

@@ -0,0 +1,79 @@
+package org.yakindu.scr.runnabletest;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Runnable wrapper of RunnableTestStatemachine. This wrapper provides a
+ * thread-safe, runnable instance of the state machine. The wrapper implements
+ * the {@link Runnable} interface and can be started in a thread by the client
+ * code. The run method then starts the main event processing loop for this
+ * state machine.
+ * 
+ * Please report bugs and issues...
+ */
+
+public class RunnableTestStatemachineRunnable extends SynchronizedRunnableTestStatemachine implements Runnable {
+	
+	/**
+	 * The events are queued using a blocking queue without capacity
+	 * restriction. This queue holds Runnable instances that process the events.
+	 */
+	protected BlockingQueue<Runnable> eventQueue = new LinkedBlockingQueue<Runnable>();
+	
+	/**
+	 * Interface object for SCInterface
+	 */		
+	protected SCInterface sCInterface = new SynchronizedSCInterface() {
+		public void raiseEv_in(final long value) {
+			
+			eventQueue.add( new Runnable() {
+				
+				@Override
+				public void run() {
+					synchronized (statemachine) {
+						statemachine.getSCInterface().raiseEv_in(value);
+						statemachine.runCycle();
+					}
+				}
+			});
+		}
+		
+	};
+	
+	public void timeElapsed(final int eventID) {
+		eventQueue.add(new Runnable() {
+	
+			@Override
+			public void run() {
+				synchronized (statemachine) {
+					statemachine.timeElapsed(eventID);
+					statemachine.runCycle();
+				}
+			}
+		});
+	}
+	
+	/**
+	 * This method will start the main execution loop for the state machine.
+	 * First it will init and enter the state machine implicitly and then will
+	 * start processing events from the event queue until the thread is
+	 * interrupted.
+	 */
+	@Override
+	public void run() {
+	
+		boolean terminate = false;
+		
+		while(!(terminate || Thread.currentThread().isInterrupted())) {
+	
+			try {
+				
+				Runnable eventProcessor = eventQueue.take();
+				eventProcessor.run();
+				
+			} catch (InterruptedException e) {
+				terminate = true;
+			}
+		}
+	}
+}

+ 231 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/runnabletest/SynchronizedRunnableTestStatemachine.java

@@ -0,0 +1,231 @@
+package org.yakindu.scr.runnabletest;
+import java.util.List;
+
+import org.yakindu.scr.ITimer;
+import org.yakindu.scr.ITimerCallback;
+import org.yakindu.scr.runnabletest.RunnableTestStatemachine.State;
+
+/**
+ * Runnable wrapper of RunnableTestStatemachine. This wrapper provides a thread-safe
+ * instance of the state machine.
+ * 
+ * Please report bugs and issues...
+ */
+
+public class SynchronizedRunnableTestStatemachine implements IRunnableTestStatemachine {
+	
+	/**
+	 * The core state machine is simply wrapped and the event processing will be
+	 * delegated to that state machine instance. This instance will be created
+	 * implicitly.
+	 */
+	protected RunnableTestStatemachine statemachine = new RunnableTestStatemachine();
+	
+	/**
+	 * Interface object for SCInterface
+	 */		
+	protected class SynchronizedSCInterface implements SCInterface {
+		
+		public List<SCInterfaceListener> getListeners() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getListeners();
+			}
+		}
+		
+		public void setSCInterfaceOperationCallback(SCInterfaceOperationCallback operationCallback) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setSCInterfaceOperationCallback(operationCallback);
+			}
+		}
+		
+		public boolean isRaisedEv_out() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().isRaisedEv_out();
+			}
+		}
+		
+		public long getEv_outValue() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getEv_outValue();
+			}
+		}
+		public void raiseEv_in(final long value) {
+			
+			synchronized (statemachine) {
+				statemachine.getSCInterface().raiseEv_in(value);
+				statemachine.runCycle();
+			}
+		}
+		
+		public long getMyVar() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getMyVar();
+			}
+		}
+		
+		public void setMyVar(final long value) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setMyVar(value);
+			}
+		}
+		
+		public long getAfterCalls() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getAfterCalls();
+			}
+		}
+		
+		public void setAfterCalls(final long value) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setAfterCalls(value);
+			}
+		}
+		
+		public long getCycles() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getCycles();
+			}
+		}
+		
+		public void setCycles(final long value) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setCycles(value);
+			}
+		}
+		
+		public long getS2_entered() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getS2_entered();
+			}
+		}
+		
+		public void setS2_entered(final long value) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setS2_entered(value);
+			}
+		}
+		
+	};
+	
+	protected SCInterface sCInterface;
+	
+	public SynchronizedRunnableTestStatemachine() {
+		sCInterface = new SynchronizedSCInterface();
+	}
+	
+	public synchronized SCInterface getSCInterface() {
+		return sCInterface;
+	}
+	/*================ TIME EVENT HANDLING ================
+	
+	/** An external timer instance is required. */
+	protected ITimer externalTimer;
+	
+	/** Internally we use a timer proxy that queues time events together with other input events. */
+	protected ITimer timerProxy = new ITimer() {
+		/** Simply delegate to external timer with a modified callback. */
+		@Override
+		public void setTimer(ITimerCallback callback, int eventID, long time,
+				boolean isPeriodic) {
+			externalTimer.setTimer(SynchronizedRunnableTestStatemachine.this, eventID, time, isPeriodic);
+		}
+		
+		@Override
+		public void unsetTimer(ITimerCallback callback, int eventID) {
+			externalTimer.unsetTimer(SynchronizedRunnableTestStatemachine.this, eventID);
+		}
+	};
+	
+	/**
+	 * Set the {@link ITimer} for the state machine. It must be set externally
+	 * on a timed state machine before a run cycle can be correct executed.
+	 * 
+	 * @param timer
+	 */
+	public void setTimer(ITimer timer) {
+		synchronized(statemachine) {
+			this.externalTimer = timer;
+			/* the wrapped state machine uses timer proxy as timer */
+			statemachine.setTimer(timerProxy);
+		}
+	}
+	
+	/**
+	* Returns the currently used timer.
+	* 
+	* @return {@link ITimer}
+	*/
+	public ITimer getTimer() {
+		return externalTimer;
+	}
+	
+	public void timeElapsed(int eventID) {
+		synchronized (statemachine) {
+			statemachine.timeElapsed(eventID);
+		}
+	}
+	
+	/**
+	 * init() will be delegated thread-safely to the wrapped state machine. 
+	 */ 
+	public void init() {
+		synchronized(statemachine) {
+			statemachine.init();
+		}
+	}
+	
+	/**
+	 * enter() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public void enter() {
+		synchronized(statemachine) {
+			statemachine.enter();
+		}
+	}
+	
+	/**
+	 * exit() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public void exit() {
+		synchronized(statemachine) {
+			statemachine.exit();
+		}
+	}
+	
+	/**
+	 * isActive() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public boolean isActive() {
+		synchronized(statemachine) {
+			return statemachine.isActive();
+		}
+	}
+	
+	/**
+	 * isFinal() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public boolean isFinal() {
+		synchronized(statemachine) {
+			return statemachine.isFinal();
+		}
+	}
+	
+	/**
+	 * isStateActive() will be delegated thread-safely to the wrapped state machine.  
+	 */
+	public boolean isStateActive(State state) {
+		synchronized(statemachine) {
+			return statemachine.isStateActive(state);
+		}
+	}
+	
+	/**
+	 * runCycle() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	@Override
+	public void runCycle() {
+		synchronized (statemachine) {
+			statemachine.runCycle();
+		}
+	}
+}

+ 32 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/wrappertest/IWrapperTestStatemachine.java

@@ -0,0 +1,32 @@
+package org.yakindu.scr.wrappertest;
+import java.util.List;
+import org.yakindu.scr.IStatemachine;
+import org.yakindu.scr.ITimerCallback;
+
+public interface IWrapperTestStatemachine extends ITimerCallback, IStatemachine {
+
+	public interface SCInterface {
+		public boolean isRaisedEv_out();
+		public void raiseEv_in();
+		public long getAfterCalls();
+		public void setAfterCalls(long value);
+		public long getCycles();
+		public void setCycles(long value);
+		public long getS2_entered();
+		public void setS2_entered(long value);
+		public List<SCInterfaceListener> getListeners();
+
+		public void setSCInterfaceOperationCallback(SCInterfaceOperationCallback operationCallback);
+	}
+
+	public interface SCInterfaceListener {
+		public void onEv_outRaised();
+	}
+
+	public interface SCInterfaceOperationCallback {
+		public void displayTime();
+	}
+
+	public SCInterface getSCInterface();
+
+}

+ 214 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/wrappertest/SynchronizedWrapperTestStatemachine.java

@@ -0,0 +1,214 @@
+package org.yakindu.scr.wrappertest;
+import java.util.List;
+
+import org.yakindu.scr.ITimer;
+import org.yakindu.scr.ITimerCallback;
+import org.yakindu.scr.wrappertest.WrapperTestStatemachine.State;
+
+/**
+ * Runnable wrapper of WrapperTestStatemachine. This wrapper provides a thread-safe
+ * instance of the state machine.
+ * 
+ * Please report bugs and issues...
+ */
+
+public class SynchronizedWrapperTestStatemachine implements IWrapperTestStatemachine {
+	
+	/**
+	 * The core state machine is simply wrapped and the event processing will be
+	 * delegated to that state machine instance. This instance will be created
+	 * implicitly.
+	 */
+	protected WrapperTestStatemachine statemachine = new WrapperTestStatemachine();
+	
+	/**
+	 * Interface object for SCInterface
+	 */		
+	protected class SynchronizedSCInterface implements SCInterface {
+		
+		public List<SCInterfaceListener> getListeners() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getListeners();
+			}
+		}
+		
+		public void setSCInterfaceOperationCallback(SCInterfaceOperationCallback operationCallback) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setSCInterfaceOperationCallback(operationCallback);
+			}
+		}
+		
+		public boolean isRaisedEv_out() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().isRaisedEv_out();
+			}
+		}
+		
+		public void raiseEv_in() {
+			
+			synchronized (statemachine) {
+				statemachine.getSCInterface().raiseEv_in();
+				statemachine.runCycle();
+			}
+		}
+		
+		public long getAfterCalls() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getAfterCalls();
+			}
+		}
+		
+		public void setAfterCalls(final long value) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setAfterCalls(value);
+			}
+		}
+		
+		public long getCycles() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getCycles();
+			}
+		}
+		
+		public void setCycles(final long value) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setCycles(value);
+			}
+		}
+		
+		public long getS2_entered() {
+			synchronized(statemachine) {
+				return statemachine.getSCInterface().getS2_entered();
+			}
+		}
+		
+		public void setS2_entered(final long value) {
+			synchronized(statemachine) {
+				statemachine.getSCInterface().setS2_entered(value);
+			}
+		}
+		
+	};
+	
+	protected SCInterface sCInterface;
+	
+	public SynchronizedWrapperTestStatemachine() {
+		sCInterface = new SynchronizedSCInterface();
+	}
+	
+	public synchronized SCInterface getSCInterface() {
+		return sCInterface;
+	}
+	/*================ TIME EVENT HANDLING ================
+	
+	/** An external timer instance is required. */
+	protected ITimer externalTimer;
+	
+	/** Internally we use a timer proxy that queues time events together with other input events. */
+	protected ITimer timerProxy = new ITimer() {
+		/** Simply delegate to external timer with a modified callback. */
+		@Override
+		public void setTimer(ITimerCallback callback, int eventID, long time,
+				boolean isPeriodic) {
+			externalTimer.setTimer(SynchronizedWrapperTestStatemachine.this, eventID, time, isPeriodic);
+		}
+		
+		@Override
+		public void unsetTimer(ITimerCallback callback, int eventID) {
+			externalTimer.unsetTimer(SynchronizedWrapperTestStatemachine.this, eventID);
+		}
+	};
+	
+	/**
+	 * Set the {@link ITimer} for the state machine. It must be set externally
+	 * on a timed state machine before a run cycle can be correct executed.
+	 * 
+	 * @param timer
+	 */
+	public void setTimer(ITimer timer) {
+		synchronized(statemachine) {
+			this.externalTimer = timer;
+			/* the wrapped state machine uses timer proxy as timer */
+			statemachine.setTimer(timerProxy);
+		}
+	}
+	
+	/**
+	* Returns the currently used timer.
+	* 
+	* @return {@link ITimer}
+	*/
+	public ITimer getTimer() {
+		return externalTimer;
+	}
+	
+	public void timeElapsed(int eventID) {
+		synchronized (statemachine) {
+			statemachine.timeElapsed(eventID);
+		}
+	}
+	
+	/**
+	 * init() will be delegated thread-safely to the wrapped state machine. 
+	 */ 
+	public void init() {
+		synchronized(statemachine) {
+			statemachine.init();
+		}
+	}
+	
+	/**
+	 * enter() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public void enter() {
+		synchronized(statemachine) {
+			statemachine.enter();
+		}
+	}
+	
+	/**
+	 * exit() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public void exit() {
+		synchronized(statemachine) {
+			statemachine.exit();
+		}
+	}
+	
+	/**
+	 * isActive() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public boolean isActive() {
+		synchronized(statemachine) {
+			return statemachine.isActive();
+		}
+	}
+	
+	/**
+	 * isFinal() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	public boolean isFinal() {
+		synchronized(statemachine) {
+			return statemachine.isFinal();
+		}
+	}
+	
+	/**
+	 * isStateActive() will be delegated thread-safely to the wrapped state machine.  
+	 */
+	public boolean isStateActive(State state) {
+		synchronized(statemachine) {
+			return statemachine.isStateActive(state);
+		}
+	}
+	
+	/**
+	 * runCycle() will be delegated thread-safely to the wrapped state machine.  
+	 */ 
+	@Override
+	public void runCycle() {
+		synchronized (statemachine) {
+			statemachine.runCycle();
+		}
+	}
+}

+ 474 - 0
test-plugins/org.yakindu.sct.generator.java.test/src-gen/org/yakindu/scr/wrappertest/WrapperTestStatemachine.java

@@ -0,0 +1,474 @@
+package org.yakindu.scr.wrappertest;
+import java.util.LinkedList;
+import java.util.List;
+import org.yakindu.scr.ITimer;
+
+public class WrapperTestStatemachine implements IWrapperTestStatemachine {
+
+	protected class SCInterfaceImpl implements SCInterface {
+
+		private List<SCInterfaceListener> listeners = new LinkedList<SCInterfaceListener>();
+
+		public List<SCInterfaceListener> getListeners() {
+			return listeners;
+		}
+
+		private SCInterfaceOperationCallback operationCallback;
+
+		public void setSCInterfaceOperationCallback(SCInterfaceOperationCallback operationCallback) {
+			this.operationCallback = operationCallback;
+		}
+
+		private boolean ev_out;
+
+		public boolean isRaisedEv_out() {
+			return ev_out;
+		}
+
+		protected void raiseEv_out() {
+			ev_out = true;
+			for (SCInterfaceListener listener : listeners) {
+				listener.onEv_outRaised();
+			}
+		}
+
+		private boolean ev_in;
+
+		public void raiseEv_in() {
+			ev_in = true;
+		}
+
+		private long afterCalls;
+
+		public long getAfterCalls() {
+			return afterCalls;
+		}
+
+		public void setAfterCalls(long value) {
+			this.afterCalls = value;
+		}
+
+		private long cycles;
+
+		public long getCycles() {
+			return cycles;
+		}
+
+		public void setCycles(long value) {
+			this.cycles = value;
+		}
+
+		private long s2_entered;
+
+		public long getS2_entered() {
+			return s2_entered;
+		}
+
+		public void setS2_entered(long value) {
+			this.s2_entered = value;
+		}
+
+		protected void clearEvents() {
+			ev_in = false;
+		}
+
+		protected void clearOutEvents() {
+			ev_out = false;
+		}
+	}
+
+	protected SCInterfaceImpl sCInterface;
+
+	private boolean initialized = false;
+
+	public enum State {
+		main_region_s1, main_region_s2, main_region__final_, $NullState$
+	};
+
+	private final State[] stateVector = new State[1];
+
+	private int nextStateIndex;
+
+	private ITimer timer;
+
+	private final boolean[] timeEvents = new boolean[2];
+
+	public WrapperTestStatemachine() {
+
+		sCInterface = new SCInterfaceImpl();
+	}
+
+	public void init() {
+		this.initialized = true;
+		if (timer == null) {
+			throw new IllegalStateException("timer not set.");
+		}
+		for (int i = 0; i < 1; i++) {
+			stateVector[i] = State.$NullState$;
+		}
+
+		clearEvents();
+		clearOutEvents();
+
+		sCInterface.setAfterCalls(0);
+
+		sCInterface.setCycles(0);
+
+		sCInterface.setS2_entered(0);
+	}
+
+	public void enter() {
+		if (!initialized)
+			throw new IllegalStateException(
+					"The state machine needs to be initialized first by calling the init() function.");
+
+		if (timer == null) {
+			throw new IllegalStateException("timer not set.");
+		}
+		entryAction();
+
+		enterSequence_main_region_default();
+	}
+
+	public void exit() {
+		exitSequence_main_region();
+
+		exitAction();
+	}
+
+	/**
+	 * @see IStatemachine#isActive()
+	 */
+	public boolean isActive() {
+
+		return stateVector[0] != State.$NullState$;
+	}
+
+	/** 
+	 * @see IStatemachine#isFinal() 
+	 */
+	public boolean isFinal() {
+		return (stateVector[0] == State.main_region__final_);
+	}
+
+	/**
+	* This method resets the incoming events (time events included).
+	*/
+	protected void clearEvents() {
+		sCInterface.clearEvents();
+
+		for (int i = 0; i < timeEvents.length; i++) {
+			timeEvents[i] = false;
+		}
+	}
+
+	/**
+	* This method resets the outgoing events.
+	*/
+	protected void clearOutEvents() {
+		sCInterface.clearOutEvents();
+	}
+
+	/**
+	* Returns true if the given state is currently active otherwise false.
+	*/
+	public boolean isStateActive(State state) {
+		switch (state) {
+			case main_region_s1 :
+				return stateVector[0] == State.main_region_s1;
+			case main_region_s2 :
+				return stateVector[0] == State.main_region_s2;
+			case main_region__final_ :
+				return stateVector[0] == State.main_region__final_;
+			default :
+				return false;
+		}
+	}
+
+	/**
+	* Set the {@link ITimer} for the state machine. It must be set
+	* externally on a timed state machine before a run cycle can be correct
+	* executed.
+	* 
+	* @param timer
+	*/
+	public void setTimer(ITimer timer) {
+		this.timer = timer;
+	}
+
+	/**
+	* Returns the currently used timer.
+	* 
+	* @return {@link ITimer}
+	*/
+	public ITimer getTimer() {
+		return timer;
+	}
+
+	public void timeElapsed(int eventID) {
+		timeEvents[eventID] = true;
+	}
+
+	public SCInterface getSCInterface() {
+		return sCInterface;
+	}
+
+	public boolean isRaisedEv_out() {
+		return sCInterface.isRaisedEv_out();
+	}
+	public void raiseEv_in() {
+		sCInterface.raiseEv_in();
+	}
+
+	public long getAfterCalls() {
+		return sCInterface.getAfterCalls();
+	}
+
+	public void setAfterCalls(long value) {
+		sCInterface.setAfterCalls(value);
+	}
+	public long getCycles() {
+		return sCInterface.getCycles();
+	}
+
+	public void setCycles(long value) {
+		sCInterface.setCycles(value);
+	}
+	public long getS2_entered() {
+		return sCInterface.getS2_entered();
+	}
+
+	public void setS2_entered(long value) {
+		sCInterface.setS2_entered(value);
+	}
+
+	private boolean check__lr0() {
+		return timeEvents[1];
+	}
+
+	private boolean check__lr1() {
+		return true;
+	}
+
+	private boolean check_main_region_s1_tr0_tr0() {
+		return sCInterface.getCycles() == 40;
+	}
+
+	private boolean check_main_region_s1_tr1_tr1() {
+		return sCInterface.ev_in;
+	}
+
+	private boolean check_main_region_s1_tr2_tr2() {
+		return timeEvents[0];
+	}
+
+	private boolean check_main_region_s2_tr0_tr0() {
+		return sCInterface.ev_in;
+	}
+
+	private void effect__lr0() {
+		sCInterface.operationCallback.displayTime();
+	}
+
+	private void effect__lr1() {
+		sCInterface.setCycles(sCInterface.getCycles() + 1);
+	}
+
+	private void effect_main_region_s1_tr0() {
+		exitSequence_main_region_s1();
+
+		enterSequence_main_region__final__default();
+	}
+
+	private void effect_main_region_s1_tr1() {
+		exitSequence_main_region_s1();
+
+		enterSequence_main_region_s2_default();
+	}
+
+	private void effect_main_region_s1_tr2() {
+		exitSequence_main_region_s1();
+
+		sCInterface.setAfterCalls(sCInterface.getAfterCalls() + 1);
+
+		enterSequence_main_region_s1_default();
+	}
+
+	private void effect_main_region_s2_tr0() {
+		exitSequence_main_region_s2();
+
+		enterSequence_main_region_s1_default();
+	}
+
+	/* Entry action for statechart 'WrapperTest'. */
+	private void entryAction() {
+
+		timer.setTimer(this, 1, 1 * 1000, true);
+	}
+
+	/* Entry action for state 's1'. */
+	private void entryAction_main_region_s1() {
+
+		timer.setTimer(this, 0, 500, false);
+
+		sCInterface.raiseEv_out();
+	}
+
+	/* Entry action for state 's2'. */
+	private void entryAction_main_region_s2() {
+		sCInterface.setS2_entered(sCInterface.getS2_entered() + 1);
+	}
+
+	/* Exit action for state 'WrapperTest'. */
+	private void exitAction() {
+		timer.unsetTimer(this, 1);
+	}
+
+	/* Exit action for state 's1'. */
+	private void exitAction_main_region_s1() {
+		timer.unsetTimer(this, 0);
+	}
+
+	/* 'default' enter sequence for state s1 */
+	private void enterSequence_main_region_s1_default() {
+		entryAction_main_region_s1();
+
+		nextStateIndex = 0;
+		stateVector[0] = State.main_region_s1;
+	}
+
+	/* 'default' enter sequence for state s2 */
+	private void enterSequence_main_region_s2_default() {
+		entryAction_main_region_s2();
+
+		nextStateIndex = 0;
+		stateVector[0] = State.main_region_s2;
+	}
+
+	/* Default enter sequence for state null */
+	private void enterSequence_main_region__final__default() {
+		nextStateIndex = 0;
+		stateVector[0] = State.main_region__final_;
+	}
+
+	/* 'default' enter sequence for region main region */
+	private void enterSequence_main_region_default() {
+		react_main_region__entry_Default();
+	}
+
+	/* Default exit sequence for state s1 */
+	private void exitSequence_main_region_s1() {
+		nextStateIndex = 0;
+		stateVector[0] = State.$NullState$;
+
+		exitAction_main_region_s1();
+	}
+
+	/* Default exit sequence for state s2 */
+	private void exitSequence_main_region_s2() {
+		nextStateIndex = 0;
+		stateVector[0] = State.$NullState$;
+	}
+
+	/* Default exit sequence for final state. */
+	private void exitSequence_main_region__final_() {
+		nextStateIndex = 0;
+		stateVector[0] = State.$NullState$;
+	}
+
+	/* Default exit sequence for region main region */
+	private void exitSequence_main_region() {
+		switch (stateVector[0]) {
+			case main_region_s1 :
+				exitSequence_main_region_s1();
+				break;
+
+			case main_region_s2 :
+				exitSequence_main_region_s2();
+				break;
+
+			case main_region__final_ :
+				exitSequence_main_region__final_();
+				break;
+
+			default :
+				break;
+		}
+	}
+
+	/* The reactions of state s1. */
+	private void react_main_region_s1() {
+		if (check__lr0()) {
+			effect__lr0();
+		}
+
+		effect__lr1();
+
+		if (check_main_region_s1_tr0_tr0()) {
+			effect_main_region_s1_tr0();
+		} else {
+			if (check_main_region_s1_tr1_tr1()) {
+				effect_main_region_s1_tr1();
+			} else {
+				if (check_main_region_s1_tr2_tr2()) {
+					effect_main_region_s1_tr2();
+				}
+			}
+		}
+	}
+
+	/* The reactions of state s2. */
+	private void react_main_region_s2() {
+		if (check__lr0()) {
+			effect__lr0();
+		}
+
+		effect__lr1();
+
+		if (check_main_region_s2_tr0_tr0()) {
+			effect_main_region_s2_tr0();
+		}
+	}
+
+	/* The reactions of state null. */
+	private void react_main_region__final_() {
+		if (check__lr0()) {
+			effect__lr0();
+		}
+
+		effect__lr1();
+
+	}
+
+	/* Default react sequence for initial entry  */
+	private void react_main_region__entry_Default() {
+		enterSequence_main_region_s1_default();
+	}
+
+	public void runCycle() {
+		if (!initialized)
+			throw new IllegalStateException(
+					"The state machine needs to be initialized first by calling the init() function.");
+
+		clearOutEvents();
+
+		for (nextStateIndex = 0; nextStateIndex < stateVector.length; nextStateIndex++) {
+
+			switch (stateVector[nextStateIndex]) {
+				case main_region_s1 :
+					react_main_region_s1();
+					break;
+				case main_region_s2 :
+					react_main_region_s2();
+					break;
+				case main_region__final_ :
+					react_main_region__final_();
+					break;
+				default :
+					// $NullState$
+			}
+		}
+
+		clearEvents();
+	}
+}

+ 1 - 1
test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/AllTestsTestCustom.java

@@ -16,6 +16,6 @@ import org.junit.runners.Suite.SuiteClasses;
 import org.yakindu.sct.generator.java.JavaSCTGeneratorTest;
 
 @RunWith(Suite.class)
-@SuiteClasses({ OperationsTestCustom.class, OperationsWithoutBracesCustom.class, JavaSCTGeneratorTest.class })
+@SuiteClasses({ OperationsTestCustom.class, OperationsWithoutBracesCustom.class, JavaSCTGeneratorTest.class, WrapperTest.class })
 public class AllTestsTestCustom {
 }

+ 113 - 0
test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/CustomTimerService.java

@@ -0,0 +1,113 @@
+package org.yakindu.sct.generator.java.test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.yakindu.scr.ITimer;
+import org.yakindu.scr.ITimerCallback;
+
+/**
+ * Default timer service implementation.
+ * 
+ */
+public class CustomTimerService implements ITimer {
+
+	private final Timer timer = new Timer();
+
+	private final List<TimeEventTask> timerTaskList = new ArrayList<TimeEventTask>();
+
+	private final Lock lock = new ReentrantLock();
+
+	public List<Integer> timerCallbacks = new ArrayList<>();
+
+	/**
+	 * Timer task that reflects a time event. It's internally used by
+	 * {@link CustomTimerService}.
+	 * 
+	 */
+	private class TimeEventTask extends TimerTask {
+
+		private ITimerCallback callback;
+
+		int eventID;
+
+		/**
+		 * Constructor for a time event.
+		 * 
+		 * @param callback
+		 *            : Set to {@code true} if event should be repeated
+		 *            periodically.
+		 * 
+		 * @param eventID
+		 *            : Index position within the state machine's timeEvent
+		 *            array.
+		 */
+		public TimeEventTask(ITimerCallback callback, int eventID) {
+			this.callback = callback;
+			this.eventID = eventID;
+		}
+
+		public void run() {
+			timerCallbacks.add(new Integer(eventID));
+			callback.timeElapsed(eventID);
+		}
+
+		public boolean equals(Object obj) {
+			if (obj instanceof TimeEventTask) {
+				return ((TimeEventTask) obj).callback.equals(callback) && ((TimeEventTask) obj).eventID == eventID;
+			}
+			return super.equals(obj);
+		}
+	}
+
+	public void setTimer(final ITimerCallback callback, final int eventID, long time, boolean isPeriodic) {
+
+		// Create a new TimerTask for given event and store it.
+		TimeEventTask timerTask = new TimeEventTask(callback, eventID);
+		lock.lock();
+		timerTaskList.add(timerTask);
+
+		// start scheduling the timer
+		if (isPeriodic) {
+			timer.scheduleAtFixedRate(timerTask, time, time);
+		} else {
+			timer.schedule(timerTask, time);
+		}
+		lock.unlock();
+	}
+
+	public void unsetTimer(ITimerCallback callback, int eventID) {
+		lock.lock();
+		int index = timerTaskList.indexOf(new TimeEventTask(callback, eventID));
+		if (index != -1) {
+			timerTaskList.get(index).cancel();
+			timer.purge();
+			timerTaskList.remove(index);
+		}
+		lock.unlock();
+	}
+
+	public int getTimerCallbackCount(int eventID) {
+		int i = 0;
+		for (Integer event : timerCallbacks) {
+			if (event.intValue() == eventID)
+				i++;
+		}
+		return i;
+	}
+
+	/**
+	 * Cancel timer service. Use this to end possible timing threads and free
+	 * memory resources.
+	 */
+	public void cancel() {
+		lock.lock();
+		timer.cancel();
+		timer.purge();
+		lock.unlock();
+	}
+}

+ 91 - 0
test-plugins/org.yakindu.sct.generator.java.test/src/org/yakindu/sct/generator/java/test/WrapperTest.java

@@ -0,0 +1,91 @@
+package org.yakindu.sct.generator.java.test;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.yakindu.scr.RuntimeService;
+import org.yakindu.scr.runnabletest.RunnableTestStatemachineRunnable;
+import org.yakindu.scr.wrappertest.IWrapperTestStatemachine.SCInterfaceOperationCallback;
+import org.yakindu.scr.wrappertest.SynchronizedWrapperTestStatemachine;
+import org.yakindu.scr.wrappertest.WrapperTestStatemachine.State;
+
+public class WrapperTest {
+
+	private static final int CYCLE_TIME = 250;
+
+	protected int operationCallbacks;
+
+	@Before
+	public void setup() {
+		operationCallbacks = 0;
+	}
+
+	@Test
+	public void synchronizedStatemachineWrapperTest() throws InterruptedException {
+
+		int waitTimeSeconds = 10;
+		SynchronizedWrapperTestStatemachine sm = new SynchronizedWrapperTestStatemachine();
+
+		sm.getSCInterface().setSCInterfaceOperationCallback(new SCInterfaceOperationCallback() {
+
+			@Override
+			public void displayTime() {
+				operationCallbacks++;
+			}
+		});
+
+		CustomTimerService timer = new CustomTimerService();
+		sm.setTimer(timer);
+		sm.init();
+		sm.enter();
+		RuntimeService.getInstance().registerStatemachine(sm, CYCLE_TIME);
+
+		sleep(waitTimeSeconds);
+		RuntimeService.getInstance().cancelTimer();
+		assertTrue(sm.isStateActive(State.main_region__final_));
+		assertTrue(sm.getSCInterface().getCycles() >= waitTimeSeconds * 1000 / CYCLE_TIME);
+		assertTrue((waitTimeSeconds - operationCallbacks) <= 1);
+		assertTrue((timer.getTimerCallbackCount(0) - sm.getSCInterface().getAfterCalls()) <= 1);
+	}
+
+	@Test
+	public void runnableStatemachineWrapperTest() throws InterruptedException {
+		
+		int waitTimeSeconds = 11;
+		
+		RunnableTestStatemachineRunnable sm = new RunnableTestStatemachineRunnable();
+
+		sm.getSCInterface().setSCInterfaceOperationCallback(
+				new org.yakindu.scr.runnabletest.IRunnableTestStatemachine.SCInterfaceOperationCallback() {
+
+					@Override
+					public void displayTime() {
+						operationCallbacks++;
+					}
+				});
+
+		CustomTimerService timer = new CustomTimerService();
+		sm.setTimer(timer);
+		sm.init();
+		sm.enter();
+		Thread thread = new Thread(sm);
+		thread.start();
+		sleep(waitTimeSeconds);
+		thread.interrupt();
+		assertTrue(sm.isStateActive(org.yakindu.scr.runnabletest.RunnableTestStatemachine.State.main_region__final_));
+		sm.exit();
+		assertTrue((waitTimeSeconds - operationCallbacks) <= 1);
+		assertTrue((timer.getTimerCallbackCount(1) - sm.getSCInterface().getAfterCalls()) <= 1);
+	}
+
+	@After
+	public void tearDown() {
+		RuntimeService.getInstance().cancelTimer();
+	}
+
+	private void sleep(long time) throws InterruptedException {
+		Thread.sleep(time * 1000);
+	}
+}

+ 202 - 0
test-plugins/org.yakindu.sct.test.models/testmodels/SCTUnit/RunnableTest.sct

@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:sgraph="http://www.yakindu.org/sct/sgraph/2.0.0">
+  <sgraph:Statechart xmi:id="_c4qVUJpjEeWXkOTCWHzaSw" specification="interface:&#xA;out event ev_out:integer&#xA;in event ev_in:integer&#xA;var myVar:integer&#xA;operation displayTime()&#xA;&#xA;var afterCalls:integer=0&#xA;var cycles:integer = 0&#xA;var s2_entered:integer = 0&#xA;&#xA;internal:&#xA;every 1s / displayTime()&#xA;oncycle / cycles += 1" name="RunnableTest">
+    <regions xmi:id="_c4sKgppjEeWXkOTCWHzaSw" name="main region">
+      <vertices xsi:type="sgraph:Entry" xmi:id="_c4xqEJpjEeWXkOTCWHzaSw">
+        <outgoingTransitions xmi:id="_c4zfQppjEeWXkOTCWHzaSw" target="_5l5RUNGDEeW7UJ0cPg0J-Q"/>
+      </vertices>
+      <vertices xsi:type="sgraph:FinalState" xmi:id="_Hsdb4NCeEeWFO75CgJFf1g" incomingTransitions="_JBzeMNCeEeWFO75CgJFf1g"/>
+      <vertices xsi:type="sgraph:State" xmi:id="_5l5RUNGDEeW7UJ0cPg0J-Q" specification="" name="Composite_s1_s2" incomingTransitions="_c4zfQppjEeWXkOTCWHzaSw">
+        <outgoingTransitions xmi:id="_JBzeMNCeEeWFO75CgJFf1g" specification="after 10 s" target="_Hsdb4NCeEeWFO75CgJFf1g"/>
+        <regions xmi:id="_5m4IwNGDEeW7UJ0cPg0J-Q" name="inner region">
+          <vertices xsi:type="sgraph:State" xmi:id="_c4yRJJpjEeWXkOTCWHzaSw" specification="entry / raise ev_out:2" name="s1" incomingTransitions="_AWDNcMZ2EeWX2I-CIBP2Cw _CFOf4NCZEeWFO75CgJFf1g _GpayANGEEeW7UJ0cPg0J-Q">
+            <outgoingTransitions xmi:id="_UgX9gMDrEeWLXPYSPFoy-Q" specification="ev_in" target="_NmkNEMDrEeWLXPYSPFoy-Q"/>
+            <outgoingTransitions xmi:id="_AWDNcMZ2EeWX2I-CIBP2Cw" specification="after 500 ms / afterCalls += 1" target="_c4yRJJpjEeWXkOTCWHzaSw"/>
+          </vertices>
+          <vertices xsi:type="sgraph:State" xmi:id="_NmkNEMDrEeWLXPYSPFoy-Q" specification="entry / s2_entered += 1" name="s2" incomingTransitions="_UgX9gMDrEeWLXPYSPFoy-Q">
+            <outgoingTransitions xmi:id="_CFOf4NCZEeWFO75CgJFf1g" specification="ev_in" target="_c4yRJJpjEeWXkOTCWHzaSw"/>
+          </vertices>
+          <vertices xsi:type="sgraph:Entry" xmi:id="_FxazANGEEeW7UJ0cPg0J-Q">
+            <outgoingTransitions xmi:id="_GpayANGEEeW7UJ0cPg0J-Q" specification="" target="_c4yRJJpjEeWXkOTCWHzaSw"/>
+          </vertices>
+        </regions>
+      </vertices>
+    </regions>
+  </sgraph:Statechart>
+  <notation:Diagram xmi:id="_c4sKgJpjEeWXkOTCWHzaSw" type="org.yakindu.sct.ui.editor.editor.StatechartDiagramEditor" element="_c4qVUJpjEeWXkOTCWHzaSw" measurementUnit="Pixel">
+    <children xmi:id="_c4umwJpjEeWXkOTCWHzaSw" type="Region" element="_c4sKgppjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_c4wb8JpjEeWXkOTCWHzaSw" type="RegionName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_c4wb8ZpjEeWXkOTCWHzaSw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_c4wb8ppjEeWXkOTCWHzaSw"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_c4xDAJpjEeWXkOTCWHzaSw" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+        <children xmi:id="_c4xqEZpjEeWXkOTCWHzaSw" type="Entry" element="_c4xqEJpjEeWXkOTCWHzaSw">
+          <children xmi:id="_c4xqFZpjEeWXkOTCWHzaSw" type="BorderItemLabelContainer">
+            <children xsi:type="notation:DecorationNode" xmi:id="_c4yRIJpjEeWXkOTCWHzaSw" type="BorderItemLabel">
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_c4yRIZpjEeWXkOTCWHzaSw"/>
+              <layoutConstraint xsi:type="notation:Location" xmi:id="_c4yRIppjEeWXkOTCWHzaSw"/>
+            </children>
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_c4xqFppjEeWXkOTCWHzaSw" fontName="Verdana" lineColor="4210752"/>
+            <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4xqF5pjEeWXkOTCWHzaSw"/>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_c4xqEppjEeWXkOTCWHzaSw" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+          <styles xsi:type="notation:NamedStyle" xmi:id="_c4xqE5pjEeWXkOTCWHzaSw" name="allowColors"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4yRI5pjEeWXkOTCWHzaSw" x="214" y="25" width="15" height="15"/>
+        </children>
+        <children xsi:type="notation:Shape" xmi:id="_HsgfMNCeEeWFO75CgJFf1g" type="FinalState" element="_Hsdb4NCeEeWFO75CgJFf1g" fontName="Verdana" lineColor="4210752">
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_HsgfMdCeEeWFO75CgJFf1g" x="198" y="685" width="15" height="15"/>
+        </children>
+        <children xmi:id="_5nU0sNGDEeW7UJ0cPg0J-Q" type="State" element="_5l5RUNGDEeW7UJ0cPg0J-Q">
+          <children xsi:type="notation:DecorationNode" xmi:id="_5nU0tNGDEeW7UJ0cPg0J-Q" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_5nU0tdGDEeW7UJ0cPg0J-Q"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_5nU0ttGDEeW7UJ0cPg0J-Q"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_5nU0t9GDEeW7UJ0cPg0J-Q" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_5nU0uNGDEeW7UJ0cPg0J-Q" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_5nU0udGDEeW7UJ0cPg0J-Q"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_5nVbwNGDEeW7UJ0cPg0J-Q" type="StateFigureCompartment">
+            <children xmi:id="_5nWC0NGDEeW7UJ0cPg0J-Q" type="Region" element="_5m4IwNGDEeW7UJ0cPg0J-Q">
+              <children xsi:type="notation:DecorationNode" xmi:id="_5nWC09GDEeW7UJ0cPg0J-Q" type="RegionName">
+                <styles xsi:type="notation:ShapeStyle" xmi:id="_5nWC1NGDEeW7UJ0cPg0J-Q"/>
+                <layoutConstraint xsi:type="notation:Location" xmi:id="_5nWC1dGDEeW7UJ0cPg0J-Q"/>
+              </children>
+              <children xsi:type="notation:Shape" xmi:id="_5nWC1tGDEeW7UJ0cPg0J-Q" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+                <children xmi:id="_c4yRJ5pjEeWXkOTCWHzaSw" type="State" element="_c4yRJJpjEeWXkOTCWHzaSw">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_c4y4MJpjEeWXkOTCWHzaSw" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_c4y4MZpjEeWXkOTCWHzaSw"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_c4y4MppjEeWXkOTCWHzaSw"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_c4y4M5pjEeWXkOTCWHzaSw" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_c4y4NJpjEeWXkOTCWHzaSw" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4y4NZpjEeWXkOTCWHzaSw"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_c4y4NppjEeWXkOTCWHzaSw" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_c4yRKJpjEeWXkOTCWHzaSw" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_c4yRKZpjEeWXkOTCWHzaSw"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_c4zfQJpjEeWXkOTCWHzaSw" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_5nWp4NGDEeW7UJ0cPg0J-Q" x="48" y="29"/>
+                </children>
+                <children xmi:id="_NmnQYMDrEeWLXPYSPFoy-Q" type="State" element="_NmkNEMDrEeWLXPYSPFoy-Q">
+                  <children xsi:type="notation:DecorationNode" xmi:id="_NmpsoMDrEeWLXPYSPFoy-Q" type="StateName">
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_NmpsocDrEeWLXPYSPFoy-Q"/>
+                    <layoutConstraint xsi:type="notation:Location" xmi:id="_NmqTsMDrEeWLXPYSPFoy-Q"/>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_NmqTscDrEeWLXPYSPFoy-Q" type="StateTextCompartment">
+                    <children xsi:type="notation:Shape" xmi:id="_NmqTssDrEeWLXPYSPFoy-Q" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+                      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_NmqTs8DrEeWLXPYSPFoy-Q"/>
+                    </children>
+                  </children>
+                  <children xsi:type="notation:Compartment" xmi:id="_Nmq6wMDrEeWLXPYSPFoy-Q" type="StateFigureCompartment"/>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_NmnQYcDrEeWLXPYSPFoy-Q" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+                  <styles xsi:type="notation:FontStyle" xmi:id="_NmnQYsDrEeWLXPYSPFoy-Q"/>
+                  <styles xsi:type="notation:BooleanValueStyle" xmi:id="_Nmq6wcDrEeWLXPYSPFoy-Q" name="isHorizontal" booleanValue="true"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_5nWp4dGDEeW7UJ0cPg0J-Q" x="473" y="21"/>
+                </children>
+                <children xmi:id="_FxbaENGEEeW7UJ0cPg0J-Q" type="Entry" element="_FxazANGEEeW7UJ0cPg0J-Q">
+                  <children xmi:id="_FxcBINGEEeW7UJ0cPg0J-Q" type="BorderItemLabelContainer">
+                    <children xsi:type="notation:DecorationNode" xmi:id="_FxcBI9GEEeW7UJ0cPg0J-Q" type="BorderItemLabel">
+                      <styles xsi:type="notation:ShapeStyle" xmi:id="_FxcBJNGEEeW7UJ0cPg0J-Q"/>
+                      <layoutConstraint xsi:type="notation:Location" xmi:id="_FxcBJdGEEeW7UJ0cPg0J-Q"/>
+                    </children>
+                    <styles xsi:type="notation:ShapeStyle" xmi:id="_FxcBIdGEEeW7UJ0cPg0J-Q" fontName="Verdana" lineColor="4210752"/>
+                    <layoutConstraint xsi:type="notation:Bounds" xmi:id="_FxcBItGEEeW7UJ0cPg0J-Q"/>
+                  </children>
+                  <styles xsi:type="notation:ShapeStyle" xmi:id="_FxbaEdGEEeW7UJ0cPg0J-Q" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+                  <styles xsi:type="notation:NamedStyle" xmi:id="_FxbaEtGEEeW7UJ0cPg0J-Q" name="allowColors"/>
+                  <layoutConstraint xsi:type="notation:Bounds" xmi:id="_FxbaE9GEEeW7UJ0cPg0J-Q" x="105" y="154"/>
+                </children>
+                <layoutConstraint xsi:type="notation:Bounds" xmi:id="_5nWC19GDEeW7UJ0cPg0J-Q"/>
+              </children>
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_5nWC0dGDEeW7UJ0cPg0J-Q" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_5nWC0tGDEeW7UJ0cPg0J-Q"/>
+            </children>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_5nU0sdGDEeW7UJ0cPg0J-Q" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_5nU0stGDEeW7UJ0cPg0J-Q"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_5nVbwdGDEeW7UJ0cPg0J-Q" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_5nVbwtGDEeW7UJ0cPg0J-Q" x="39" y="80" width="846" height="477"/>
+        </children>
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4xDAZpjEeWXkOTCWHzaSw"/>
+      </children>
+      <styles xsi:type="notation:ShapeStyle" xmi:id="_c4umwZpjEeWXkOTCWHzaSw" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4xDAppjEeWXkOTCWHzaSw" x="400" y="10" width="1280" height="896"/>
+    </children>
+    <children xsi:type="notation:Shape" xmi:id="_c41UcJpjEeWXkOTCWHzaSw" type="StatechartText" fontName="Verdana" lineColor="4210752">
+      <children xsi:type="notation:DecorationNode" xmi:id="_c41UcppjEeWXkOTCWHzaSw" type="StatechartName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_c41Uc5pjEeWXkOTCWHzaSw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_c41UdJpjEeWXkOTCWHzaSw"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_c41UdZpjEeWXkOTCWHzaSw" type="StatechartTextExpression" fontName="Verdana" lineColor="4210752">
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c41UdppjEeWXkOTCWHzaSw"/>
+      </children>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c41Ud5pjEeWXkOTCWHzaSw" x="10" y="10" width="391" height="466"/>
+    </children>
+    <styles xsi:type="notation:DiagramStyle" xmi:id="_c4sKgZpjEeWXkOTCWHzaSw"/>
+    <edges xmi:id="_c40GUJpjEeWXkOTCWHzaSw" type="Transition" element="_c4zfQppjEeWXkOTCWHzaSw" source="_c4xqEZpjEeWXkOTCWHzaSw" target="_5nU0sNGDEeW7UJ0cPg0J-Q">
+      <children xsi:type="notation:DecorationNode" xmi:id="_c40tYZpjEeWXkOTCWHzaSw" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_c40tYppjEeWXkOTCWHzaSw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_c40tY5pjEeWXkOTCWHzaSw" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_c40GUZpjEeWXkOTCWHzaSw" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_c40tYJpjEeWXkOTCWHzaSw" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_c40GUppjEeWXkOTCWHzaSw" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_HJGXoNGEEeW7UJ0cPg0J-Q" id="(0.21749408983451538,0.06708595387840671)"/>
+    </edges>
+    <edges xmi:id="_UgZLoMDrEeWLXPYSPFoy-Q" type="Transition" element="_UgX9gMDrEeWLXPYSPFoy-Q" source="_c4yRJ5pjEeWXkOTCWHzaSw" target="_NmnQYMDrEeWLXPYSPFoy-Q">
+      <children xsi:type="notation:DecorationNode" xmi:id="_UgZysMDrEeWLXPYSPFoy-Q" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_UgZyscDrEeWLXPYSPFoy-Q"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_UgZyssDrEeWLXPYSPFoy-Q" x="7" y="-18"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_UgZLocDrEeWLXPYSPFoy-Q" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_UgZLo8DrEeWLXPYSPFoy-Q" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_UgZLosDrEeWLXPYSPFoy-Q" points="[3, 4, -326, 2]$[330, -21, 1, -23]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_UgbA0MDrEeWLXPYSPFoy-Q" id="(0.8809523809523809,0.16455696202531644)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_UgbA0cDrEeWLXPYSPFoy-Q" id="(0.09734513274336283,0.27906976744186046)"/>
+    </edges>
+    <edges xmi:id="_AWFCoMZ2EeWX2I-CIBP2Cw" type="Transition" element="_AWDNcMZ2EeWX2I-CIBP2Cw" source="_c4yRJ5pjEeWXkOTCWHzaSw" target="_c4yRJ5pjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_AWFpsMZ2EeWX2I-CIBP2Cw" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_AWFpscZ2EeWX2I-CIBP2Cw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_AWFpssZ2EeWX2I-CIBP2Cw" x="-146" y="-23"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_AWFCocZ2EeWX2I-CIBP2Cw" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_AWFCo8Z2EeWX2I-CIBP2Cw" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_AWFCosZ2EeWX2I-CIBP2Cw" points="[-37, 32, 1, 8]$[-33, 32, 5, 8]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_AWHe4MZ2EeWX2I-CIBP2Cw" id="(1.0,0.6826923076923077)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_AWHe4cZ2EeWX2I-CIBP2Cw" id="(0.7666666666666667,0.7848101265822784)"/>
+    </edges>
+    <edges xmi:id="_CFUmgNCZEeWFO75CgJFf1g" type="Transition" element="_CFOf4NCZEeWFO75CgJFf1g" source="_NmnQYMDrEeWLXPYSPFoy-Q" target="_c4yRJ5pjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_CFb7QNCZEeWFO75CgJFf1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_CFb7QdCZEeWFO75CgJFf1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_CFb7QtCZEeWFO75CgJFf1g" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_CFUmgdCZEeWFO75CgJFf1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_CFatINCZEeWFO75CgJFf1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_CFUmgtCZEeWFO75CgJFf1g" points="[-4, -5, 264, 4]$[-263, 21, 5, 30]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_CFe-kNCZEeWFO75CgJFf1g" id="(0.022123893805309734,0.6627906976744186)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_CFe-kdCZEeWFO75CgJFf1g" id="(0.8142857142857143,0.6075949367088608)"/>
+    </edges>
+    <edges xmi:id="_JB0sUNCeEeWFO75CgJFf1g" type="Transition" element="_JBzeMNCeEeWFO75CgJFf1g" source="_5nU0sNGDEeW7UJ0cPg0J-Q" target="_HsgfMNCeEeWFO75CgJFf1g">
+      <children xsi:type="notation:DecorationNode" xmi:id="_JB0sVNCeEeWFO75CgJFf1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_JB0sVdCeEeWFO75CgJFf1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_JB0sVtCeEeWFO75CgJFf1g" x="3" y="-65"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_JB0sUdCeEeWFO75CgJFf1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_JB0sU9CeEeWFO75CgJFf1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_JB0sUtCeEeWFO75CgJFf1g" points="[7, 9, -2, -166]$[2, 172, -7, -3]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_JB16cNCeEeWFO75CgJFf1g" id="(0.197196261682243,0.9853249475890985)"/>
+    </edges>
+    <edges xmi:id="_GpcAINGEEeW7UJ0cPg0J-Q" type="Transition" element="_GpayANGEEeW7UJ0cPg0J-Q" source="_FxbaENGEEeW7UJ0cPg0J-Q" target="_c4yRJ5pjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_GpcnMdGEEeW7UJ0cPg0J-Q" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_GpcnMtGEEeW7UJ0cPg0J-Q"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_GpcnM9GEEeW7UJ0cPg0J-Q" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_GpcAIdGEEeW7UJ0cPg0J-Q" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_GpcnMNGEEeW7UJ0cPg0J-Q" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_GpcAItGEEeW7UJ0cPg0J-Q" points="[0, -7, -5, 81]$[7, -58, 2, 30]"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_GpecYNGEEeW7UJ0cPg0J-Q" id="(0.23282442748091603,0.6075949367088608)"/>
+    </edges>
+  </notation:Diagram>
+</xmi:XMI>

+ 143 - 0
test-plugins/org.yakindu.sct.test.models/testmodels/SCTUnit/WrapperTest.sct

@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:sgraph="http://www.yakindu.org/sct/sgraph/2.0.0">
+  <sgraph:Statechart xmi:id="_c4qVUJpjEeWXkOTCWHzaSw" specification="interface:&#xA;out event ev_out&#xA;in event ev_in&#xA;operation displayTime()&#xA;&#xA;var afterCalls:integer=0&#xA;var cycles:integer = 0&#xA;var s2_entered:integer = 0&#xA;&#xA;internal:&#xA;every 1s / displayTime()&#xA;oncycle / cycles += 1" name="WrapperTest">
+    <regions xmi:id="_c4sKgppjEeWXkOTCWHzaSw" name="main region">
+      <vertices xsi:type="sgraph:Entry" xmi:id="_c4xqEJpjEeWXkOTCWHzaSw">
+        <outgoingTransitions xmi:id="_c4zfQppjEeWXkOTCWHzaSw" target="_c4yRJJpjEeWXkOTCWHzaSw"/>
+      </vertices>
+      <vertices xsi:type="sgraph:State" xmi:id="_c4yRJJpjEeWXkOTCWHzaSw" specification="entry / raise ev_out" name="s1" incomingTransitions="_c4zfQppjEeWXkOTCWHzaSw _AWDNcMZ2EeWX2I-CIBP2Cw _CFOf4NCZEeWFO75CgJFf1g">
+        <outgoingTransitions xmi:id="_JBzeMNCeEeWFO75CgJFf1g" specification="[cycles == 40]" target="_Hsdb4NCeEeWFO75CgJFf1g"/>
+        <outgoingTransitions xmi:id="_UgX9gMDrEeWLXPYSPFoy-Q" specification="ev_in" target="_NmkNEMDrEeWLXPYSPFoy-Q"/>
+        <outgoingTransitions xmi:id="_AWDNcMZ2EeWX2I-CIBP2Cw" specification="after 500 ms / afterCalls += 1" target="_c4yRJJpjEeWXkOTCWHzaSw"/>
+      </vertices>
+      <vertices xsi:type="sgraph:State" xmi:id="_NmkNEMDrEeWLXPYSPFoy-Q" specification="entry/s2_entered += 1" name="s2" incomingTransitions="_UgX9gMDrEeWLXPYSPFoy-Q">
+        <outgoingTransitions xmi:id="_CFOf4NCZEeWFO75CgJFf1g" specification="ev_in" target="_c4yRJJpjEeWXkOTCWHzaSw"/>
+      </vertices>
+      <vertices xsi:type="sgraph:FinalState" xmi:id="_Hsdb4NCeEeWFO75CgJFf1g" incomingTransitions="_JBzeMNCeEeWFO75CgJFf1g"/>
+    </regions>
+  </sgraph:Statechart>
+  <notation:Diagram xmi:id="_c4sKgJpjEeWXkOTCWHzaSw" type="org.yakindu.sct.ui.editor.editor.StatechartDiagramEditor" element="_c4qVUJpjEeWXkOTCWHzaSw" measurementUnit="Pixel">
+    <children xmi:id="_c4umwJpjEeWXkOTCWHzaSw" type="Region" element="_c4sKgppjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_c4wb8JpjEeWXkOTCWHzaSw" type="RegionName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_c4wb8ZpjEeWXkOTCWHzaSw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_c4wb8ppjEeWXkOTCWHzaSw"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_c4xDAJpjEeWXkOTCWHzaSw" type="RegionCompartment" fontName="Verdana" lineColor="4210752">
+        <children xmi:id="_c4xqEZpjEeWXkOTCWHzaSw" type="Entry" element="_c4xqEJpjEeWXkOTCWHzaSw">
+          <children xmi:id="_c4xqFZpjEeWXkOTCWHzaSw" type="BorderItemLabelContainer">
+            <children xsi:type="notation:DecorationNode" xmi:id="_c4yRIJpjEeWXkOTCWHzaSw" type="BorderItemLabel">
+              <styles xsi:type="notation:ShapeStyle" xmi:id="_c4yRIZpjEeWXkOTCWHzaSw"/>
+              <layoutConstraint xsi:type="notation:Location" xmi:id="_c4yRIppjEeWXkOTCWHzaSw"/>
+            </children>
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_c4xqFppjEeWXkOTCWHzaSw" fontName="Verdana" lineColor="4210752"/>
+            <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4xqF5pjEeWXkOTCWHzaSw"/>
+          </children>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_c4xqEppjEeWXkOTCWHzaSw" fontName="Verdana" fillColor="0" lineColor="16777215"/>
+          <styles xsi:type="notation:NamedStyle" xmi:id="_c4xqE5pjEeWXkOTCWHzaSw" name="allowColors"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4yRI5pjEeWXkOTCWHzaSw" x="125" y="15"/>
+        </children>
+        <children xmi:id="_c4yRJ5pjEeWXkOTCWHzaSw" type="State" element="_c4yRJJpjEeWXkOTCWHzaSw">
+          <children xsi:type="notation:DecorationNode" xmi:id="_c4y4MJpjEeWXkOTCWHzaSw" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_c4y4MZpjEeWXkOTCWHzaSw"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_c4y4MppjEeWXkOTCWHzaSw"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_c4y4M5pjEeWXkOTCWHzaSw" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_c4y4NJpjEeWXkOTCWHzaSw" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4y4NZpjEeWXkOTCWHzaSw"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_c4y4NppjEeWXkOTCWHzaSw" type="StateFigureCompartment"/>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_c4yRKJpjEeWXkOTCWHzaSw" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_c4yRKZpjEeWXkOTCWHzaSw"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_c4zfQJpjEeWXkOTCWHzaSw" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4zfQZpjEeWXkOTCWHzaSw" x="4" y="77"/>
+        </children>
+        <children xmi:id="_NmnQYMDrEeWLXPYSPFoy-Q" type="State" element="_NmkNEMDrEeWLXPYSPFoy-Q">
+          <children xsi:type="notation:DecorationNode" xmi:id="_NmpsoMDrEeWLXPYSPFoy-Q" type="StateName">
+            <styles xsi:type="notation:ShapeStyle" xmi:id="_NmpsocDrEeWLXPYSPFoy-Q"/>
+            <layoutConstraint xsi:type="notation:Location" xmi:id="_NmqTsMDrEeWLXPYSPFoy-Q"/>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_NmqTscDrEeWLXPYSPFoy-Q" type="StateTextCompartment">
+            <children xsi:type="notation:Shape" xmi:id="_NmqTssDrEeWLXPYSPFoy-Q" type="StateTextCompartmentExpression" fontName="Verdana" lineColor="4210752">
+              <layoutConstraint xsi:type="notation:Bounds" xmi:id="_NmqTs8DrEeWLXPYSPFoy-Q"/>
+            </children>
+          </children>
+          <children xsi:type="notation:Compartment" xmi:id="_Nmq6wMDrEeWLXPYSPFoy-Q" type="StateFigureCompartment"/>
+          <styles xsi:type="notation:ShapeStyle" xmi:id="_NmnQYcDrEeWLXPYSPFoy-Q" fontName="Verdana" fillColor="15981773" lineColor="12632256"/>
+          <styles xsi:type="notation:FontStyle" xmi:id="_NmnQYsDrEeWLXPYSPFoy-Q"/>
+          <styles xsi:type="notation:BooleanValueStyle" xmi:id="_Nmq6wcDrEeWLXPYSPFoy-Q" name="isHorizontal" booleanValue="true"/>
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_NmnQY8DrEeWLXPYSPFoy-Q" x="429" y="69" width="303" height="94"/>
+        </children>
+        <children xsi:type="notation:Shape" xmi:id="_HsgfMNCeEeWFO75CgJFf1g" type="FinalState" element="_Hsdb4NCeEeWFO75CgJFf1g" fontName="Verdana" lineColor="4210752">
+          <layoutConstraint xsi:type="notation:Bounds" xmi:id="_HsgfMdCeEeWFO75CgJFf1g" x="123" y="310"/>
+        </children>
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4xDAZpjEeWXkOTCWHzaSw"/>
+      </children>
+      <styles xsi:type="notation:ShapeStyle" xmi:id="_c4umwZpjEeWXkOTCWHzaSw" fontName="Verdana" fillColor="15790320" lineColor="12632256"/>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c4xDAppjEeWXkOTCWHzaSw" x="405" y="10" width="956" height="466"/>
+    </children>
+    <children xsi:type="notation:Shape" xmi:id="_c41UcJpjEeWXkOTCWHzaSw" type="StatechartText" fontName="Verdana" lineColor="4210752">
+      <children xsi:type="notation:DecorationNode" xmi:id="_c41UcppjEeWXkOTCWHzaSw" type="StatechartName">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_c41Uc5pjEeWXkOTCWHzaSw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_c41UdJpjEeWXkOTCWHzaSw"/>
+      </children>
+      <children xsi:type="notation:Shape" xmi:id="_c41UdZpjEeWXkOTCWHzaSw" type="StatechartTextExpression" fontName="Verdana" lineColor="4210752">
+        <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c41UdppjEeWXkOTCWHzaSw"/>
+      </children>
+      <layoutConstraint xsi:type="notation:Bounds" xmi:id="_c41Ud5pjEeWXkOTCWHzaSw" x="10" y="10" width="391" height="466"/>
+    </children>
+    <styles xsi:type="notation:DiagramStyle" xmi:id="_c4sKgZpjEeWXkOTCWHzaSw"/>
+    <edges xmi:id="_c40GUJpjEeWXkOTCWHzaSw" type="Transition" element="_c4zfQppjEeWXkOTCWHzaSw" source="_c4xqEZpjEeWXkOTCWHzaSw" target="_c4yRJ5pjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_c40tYZpjEeWXkOTCWHzaSw" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_c40tYppjEeWXkOTCWHzaSw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_c40tY5pjEeWXkOTCWHzaSw" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_c40GUZpjEeWXkOTCWHzaSw" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_c40tYJpjEeWXkOTCWHzaSw" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_c40GUppjEeWXkOTCWHzaSw" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+    </edges>
+    <edges xmi:id="_UgZLoMDrEeWLXPYSPFoy-Q" type="Transition" element="_UgX9gMDrEeWLXPYSPFoy-Q" source="_c4yRJ5pjEeWXkOTCWHzaSw" target="_NmnQYMDrEeWLXPYSPFoy-Q">
+      <children xsi:type="notation:DecorationNode" xmi:id="_UgZysMDrEeWLXPYSPFoy-Q" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_UgZyscDrEeWLXPYSPFoy-Q"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_UgZyssDrEeWLXPYSPFoy-Q" x="7" y="-18"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_UgZLocDrEeWLXPYSPFoy-Q" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_UgZLo8DrEeWLXPYSPFoy-Q" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_UgZLosDrEeWLXPYSPFoy-Q" points="[3, 4, -326, 2]$[330, -21, 1, -23]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_UgbA0MDrEeWLXPYSPFoy-Q" id="(0.8809523809523809,0.16455696202531644)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_UgbA0cDrEeWLXPYSPFoy-Q" id="(0.09734513274336283,0.27906976744186046)"/>
+    </edges>
+    <edges xmi:id="_AWFCoMZ2EeWX2I-CIBP2Cw" type="Transition" element="_AWDNcMZ2EeWX2I-CIBP2Cw" source="_c4yRJ5pjEeWXkOTCWHzaSw" target="_c4yRJ5pjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_AWFpsMZ2EeWX2I-CIBP2Cw" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_AWFpscZ2EeWX2I-CIBP2Cw"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_AWFpssZ2EeWX2I-CIBP2Cw" x="-146" y="-23"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_AWFCocZ2EeWX2I-CIBP2Cw" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_AWFCo8Z2EeWX2I-CIBP2Cw" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_AWFCosZ2EeWX2I-CIBP2Cw" points="[-37, 32, 1, 8]$[-33, 32, 5, 8]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_AWHe4MZ2EeWX2I-CIBP2Cw" id="(1.0,0.6826923076923077)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_AWHe4cZ2EeWX2I-CIBP2Cw" id="(0.7666666666666667,0.7848101265822784)"/>
+    </edges>
+    <edges xmi:id="_CFUmgNCZEeWFO75CgJFf1g" type="Transition" element="_CFOf4NCZEeWFO75CgJFf1g" source="_NmnQYMDrEeWLXPYSPFoy-Q" target="_c4yRJ5pjEeWXkOTCWHzaSw">
+      <children xsi:type="notation:DecorationNode" xmi:id="_CFb7QNCZEeWFO75CgJFf1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_CFb7QdCZEeWFO75CgJFf1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_CFb7QtCZEeWFO75CgJFf1g" y="10"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_CFUmgdCZEeWFO75CgJFf1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_CFatINCZEeWFO75CgJFf1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_CFUmgtCZEeWFO75CgJFf1g" points="[-4, -5, 264, 4]$[-263, 21, 5, 30]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_CFe-kNCZEeWFO75CgJFf1g" id="(0.022123893805309734,0.6627906976744186)"/>
+      <targetAnchor xsi:type="notation:IdentityAnchor" xmi:id="_CFe-kdCZEeWFO75CgJFf1g" id="(0.8142857142857143,0.6075949367088608)"/>
+    </edges>
+    <edges xmi:id="_JB0sUNCeEeWFO75CgJFf1g" type="Transition" element="_JBzeMNCeEeWFO75CgJFf1g" source="_c4yRJ5pjEeWXkOTCWHzaSw" target="_HsgfMNCeEeWFO75CgJFf1g">
+      <children xsi:type="notation:DecorationNode" xmi:id="_JB0sVNCeEeWFO75CgJFf1g" type="TransitionExpression">
+        <styles xsi:type="notation:ShapeStyle" xmi:id="_JB0sVdCeEeWFO75CgJFf1g"/>
+        <layoutConstraint xsi:type="notation:Location" xmi:id="_JB0sVtCeEeWFO75CgJFf1g" x="21" y="4"/>
+      </children>
+      <styles xsi:type="notation:ConnectorStyle" xmi:id="_JB0sUdCeEeWFO75CgJFf1g" lineColor="4210752"/>
+      <styles xsi:type="notation:FontStyle" xmi:id="_JB0sU9CeEeWFO75CgJFf1g" fontName="Verdana"/>
+      <bendpoints xsi:type="notation:RelativeBendpoints" xmi:id="_JB0sUtCeEeWFO75CgJFf1g" points="[7, 9, -2, -166]$[2, 172, -7, -3]"/>
+      <sourceAnchor xsi:type="notation:IdentityAnchor" xmi:id="_JB16cNCeEeWFO75CgJFf1g" id="(0.4580152671755725,0.8860759493670886)"/>
+    </edges>
+  </notation:Diagram>
+</xmi:XMI>