소스 검색

Merge branch 'master' of https://github.com/Yakindu/statecharts.git

Andreas Muelder 9 년 전
부모
커밋
85615b4855
17개의 변경된 파일229개의 추가작업 그리고 114개의 파일을 삭제
  1. 1 0
      plugins/org.yakindu.sct.doc.user/.settings/org.eclipse.core.resources.prefs
  2. 0 1
      plugins/org.yakindu.sct.doc.user/contexts.xml
  3. 4 2
      plugins/org.yakindu.sct.doc.user/help/05_reference/reference.textile
  4. 20 10
      plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/Types.xtend
  5. 17 7
      plugins/org.yakindu.sct.generator.core/library/CoreFeatureTypeLibrary.xmi
  6. 4 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/AbstractWorkspaceGenerator.java
  7. 2 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/IGeneratorBridge.java
  8. 1 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/features/ICoreFeatureConstants.java
  9. 9 3
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/features/impl/CoreLibraryDefaultFeatureValueProvider.java
  10. 4 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/AbstractSGraphModelGenerator.java
  11. 22 6
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/AbstractXpandBasedCodeGenerator.java
  12. 47 51
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/GenericJavaBasedGenerator.java
  13. 19 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/IExecutionFlowGenerator.java
  14. 11 0
      plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/util/GeneratorUtils.java
  15. 14 3
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/IStatemachine.xtend
  16. 14 3
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/ITimer.xtend
  17. 40 28
      plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/ITimerCallback.xtend

+ 1 - 0
plugins/org.yakindu.sct.doc.user/.settings/org.eclipse.core.resources.prefs

@@ -1,2 +1,3 @@
 eclipse.preferences.version=1
+encoding//help/05_reference/reference.html=UTF-8
 encoding/<project>=UTF-8

+ 0 - 1
plugins/org.yakindu.sct.doc.user/contexts.xml

@@ -18,7 +18,6 @@
    <context id="sc_properties_transition_expression" title="YAKINDU Statechart Element Properties">
       <description>A transition is the transfer of one state to another. Transitions are diagrammed as arrows and can carry events and actions but must not.</description>
       <topic href="help/05_reference/reference.html#Transitions" label="Transitions reference"/>
- 	     
    </context>
    <context id="sgen_feature" title="Genmodel Features">
       <topic href="help/05_reference/reference.html" label="Help_Topic"/>

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

@@ -489,8 +489,9 @@ The following section describes the *Core Features* which are available for all
 h4(#Outlet). Outlet
 
 The *Outlet* feature specifies target project and target folder for the generated artifacts. It is a _required_ feature and has the following parameters:
-# __targetProject__ (String, required): The project to store the generated artifacts  
-# __targetFolder__ (String, required): The folder to store the generated artifacts
+# __targetProject__ (String, required): The project to store the generated artifacts to. 
+# __targetFolder__ (String, required): The folder to store the generated artifacts to. If a library folder is given, only the dynamic (i.e. model dependent artifacts) are generated into the target folder, if not all generated artifacts will be generated into it. All artifacts in this folder will be overwritten during re-generation.
+# __libraryTargetFolder__ (String, optional): The folder to store the static (i.e. model independent artifacts) to. In case this is not specified, all artifacts will be generated into the target folder. All artifacts in this folder will be preserved during re-generation.
 
 Sample configuration:
 
@@ -498,6 +499,7 @@ bc(prettyprint)..
 feature Outlet {
 	targetProject = "SampleProject"
 	targetFolder = "src-gen"
+	libraryTargetFolder = "src"
 }
 p. ==<!-- End sgen_feature_outlet -->==
 ==<!-- Start sgen_feature_licenseheader -->==

+ 20 - 10
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/Types.xtend

@@ -10,14 +10,17 @@
  */
 package org.yakindu.sct.generator.c
 
-import org.yakindu.sct.model.sexec.ExecutionFlow
-import org.yakindu.sct.model.sgraph.Statechart
-import org.eclipse.xtext.generator.IFileSystemAccess
 import com.google.inject.Inject
-import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.yakindu.sct.generator.core.impl.SimpleResourceFileSystemAccess
 import org.eclipse.core.resources.ResourcesPlugin
 import org.eclipse.core.runtime.Path
+import org.eclipse.xtext.generator.IFileSystemAccess
+import org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator
+import org.yakindu.sct.generator.core.impl.SimpleResourceFileSystemAccess
+import org.yakindu.sct.generator.core.util.GeneratorUtils
+import org.yakindu.sct.model.sexec.ExecutionFlow
+import org.yakindu.sct.model.sgen.GeneratorEntry
+import org.yakindu.sct.model.sgraph.Statechart
+import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER
 
 class Types {
 
@@ -25,16 +28,23 @@ class Types {
 	@Inject extension GenmodelEntries
 
 	def generateTypesH(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
-		if (fsa instanceof SimpleResourceFileSystemAccess &&
-			!exists(flow.typesModule.h, fsa as SimpleResourceFileSystemAccess)) {
-			fsa.generateFile(flow.typesModule.h, flow.typesHContent(entry))
+		if (GeneratorUtils.getOutletFeatureConfiguration(entry).getParameterValue(
+			OUTLET_FEATURE_LIBRARY_TARGET_FOLDER) != null) {
+			// sc_types.h is static, so we use the library target folder in case its configured
+			fsa.generateFile(flow.typesModule.h, IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT,
+				flow.typesHContent(entry))
+		} else {
+			// use default target folder path in case no library target folder is specified (the file will be overwritten there)
+			if (fsa instanceof SimpleResourceFileSystemAccess &&
+				!exists(flow.typesModule.h, fsa as SimpleResourceFileSystemAccess)) {
+				fsa.generateFile(flow.typesModule.h, flow.typesHContent(entry))
+			}
 		}
 	}
 
 	def protected exists(String filename, SimpleResourceFileSystemAccess fsa) {
 		val uri = fsa.getURI(filename);
-		val file = ResourcesPlugin.getWorkspace().getRoot()
-					.getFile(new Path(uri.toPlatformString(true)));
+		val file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true)));
 		return file.exists;
 	}
 

+ 17 - 7
plugins/org.yakindu.sct.generator.core/library/CoreFeatureTypeLibrary.xmi

@@ -1,12 +1,22 @@
 <?xml version="1.0" encoding="ASCII"?>
-<sgen:FeatureTypeLibrary xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:sgen="http://www.yakindu.org/sct/statechart/SGen" name="Core">
+<sgen:FeatureTypeLibrary
+    xmi:version="2.0"
+    xmlns:xmi="http://www.omg.org/XMI"
+    xmlns:sgen="http://www.yakindu.org/sct/statechart/SGen"
+    name="Core">
   <types name="Outlet">
-    <parameters name="targetProject"/>
-    <parameters name="targetFolder"/>
+    <parameters
+        name="targetProject"/>
+    <parameters
+        name="targetFolder"/>
+    <parameters
+        name="libraryTargetFolder"
+        comment="A distinct output folder for static code artifacts (which are independent of concrete statechart models). It will not be cleaned or overwritten in succeeding generation passes. If not specified, the code will be generated into the target folder as well."
+        optional="true"/>
   </types>
-
-  <types name="LicenseHeader" optional="true">
-    <parameters name="licenseText"/>
+  <types name="LicenseHeader"
+      optional="true">
+    <parameters
+        name="licenseText"/>
   </types>
-
 </sgen:FeatureTypeLibrary>

+ 4 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/AbstractWorkspaceGenerator.java

@@ -52,5 +52,9 @@ public abstract class AbstractWorkspaceGenerator implements IGeneratorBridge {
 	public final File getTargetFolder(GeneratorEntry entry) {
 		return bridge.getTargetFolder(entry);
 	}
+	
+	public final File getLibraryTargetFolder(GeneratorEntry entry) {
+		return bridge.getLibraryTargetFolder(entry);
+	}
 
 }

+ 2 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/IGeneratorBridge.java

@@ -34,4 +34,6 @@ public interface IGeneratorBridge {
 	File getTargetProject(GeneratorEntry entry);
 
 	File getTargetFolder(GeneratorEntry entry);
+	
+	File getLibraryTargetFolder(GeneratorEntry entry);
 }

+ 1 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/features/ICoreFeatureConstants.java

@@ -24,6 +24,7 @@ public interface ICoreFeatureConstants {
 	public static final String OUTLET_FEATURE = "Outlet";
 	public static final String OUTLET_FEATURE_TARGET_PROJECT = "targetProject";
 	public static final String OUTLET_FEATURE_TARGET_FOLDER = "targetFolder";
+	public static final String OUTLET_FEATURE_LIBRARY_TARGET_FOLDER = "libraryTargetFolder";
 	
 	public static final String LICENSE_HEADER = "LicenseHeader";
 	public static final String LICENSE_TEXT = "licenseText";

+ 9 - 3
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/features/impl/CoreLibraryDefaultFeatureValueProvider.java

@@ -14,6 +14,7 @@ import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.LIBR
 import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.LICENSE_TEXT;
 import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_TARGET_FOLDER;
 import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_TARGET_PROJECT;
+import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER;
 
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
@@ -24,7 +25,8 @@ import org.yakindu.sct.model.sgen.FeatureTypeLibrary;
 
 /**
  * 
- * @author holger willebrandt - Initial contribution and API
+ * @author Holger Willebrandt - Initial contribution and API
+ * @author Alexander Nyßen - Additions for issue #191.
  */
 public class CoreLibraryDefaultFeatureValueProvider extends AbstractDefaultFeatureValueProvider {
 
@@ -37,7 +39,11 @@ public class CoreLibraryDefaultFeatureValueProvider extends AbstractDefaultFeatu
 		String parameterName = parameterValue.getParameter().getName();
 		if (OUTLET_FEATURE_TARGET_FOLDER.equals(parameterName)) {
 			parameterValue.setValue("src-gen");
-		} else if (OUTLET_FEATURE_TARGET_PROJECT.equals(parameterName)) {
+		} 
+		else if (OUTLET_FEATURE_LIBRARY_TARGET_FOLDER.equals(parameterName)){
+			parameterValue.setValue("src");
+		}
+		else if (OUTLET_FEATURE_TARGET_PROJECT.equals(parameterName)) {
 			parameterValue.setValue(getProject(contextElement).getName());
 		} else if (LICENSE_TEXT.equals(parameterName)) {
 			parameterValue.setValue("Enter license text here");
@@ -51,7 +57,7 @@ public class CoreLibraryDefaultFeatureValueProvider extends AbstractDefaultFeatu
 		if (OUTLET_FEATURE_TARGET_PROJECT.equals(parameterName) && projectExists(parameterValue.getStringValue())
 				&& !projectOpened(parameterValue.getStringValue()))
 			return error(String.format("The Project %s is not open.", parameterValue.getExpression()));
-		if (OUTLET_FEATURE_TARGET_FOLDER.equals(parameterName)) {
+		if (OUTLET_FEATURE_TARGET_FOLDER.equals(parameterName) || OUTLET_FEATURE_LIBRARY_TARGET_FOLDER.equals(parameterName)) {
 			FeatureParameterValue targetProjectParam = parameterValue.getFeatureConfiguration()
 					.getParameterValue(OUTLET_FEATURE_TARGET_PROJECT);
 			String targetProjectName = targetProjectParam != null ? targetProjectParam.getStringValue() : null;

+ 4 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/AbstractSGraphModelGenerator.java

@@ -73,6 +73,10 @@ public abstract class AbstractSGraphModelGenerator implements ISCTGenerator {
 		public File getTargetFolder(GeneratorEntry entry) {
 			return GeneratorUtils.getTargetFolder(entry);
 		}
+		
+		public File getLibraryTargetFolder(GeneratorEntry entry) {
+			return GeneratorUtils.getLibraryTargetFolder(entry);
+		}
 	};
 
 	protected void runGenerator(Statechart statechart, GeneratorEntry entry) {

+ 22 - 6
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/AbstractXpandBasedCodeGenerator.java

@@ -11,6 +11,7 @@
 package org.yakindu.sct.generator.core.impl;
 
 import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_TARGET_FOLDER;
+import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER;
 import static org.yakindu.sct.generator.core.util.GeneratorUtils.getOutletFeatureConfiguration;
 import static org.yakindu.sct.generator.core.util.GeneratorUtils.isDumpSexec;
 import static org.yakindu.sct.generator.core.util.GeneratorUtils.refreshTargetProject;
@@ -55,6 +56,8 @@ public abstract class AbstractXpandBasedCodeGenerator extends
 
 	public static final String CONTEXT_INJECTOR_PROPERTY_NAME = "AbstractXpandBasedCodeGenerator.Injector";
 
+	public static final String LIBRARY_TARGET_FOLDER_OUTLET = "LIBRARY_TARGET_FOLDER";
+
 	public abstract String getTemplatePath();
 
 	/**
@@ -119,18 +122,31 @@ public abstract class AbstractXpandBasedCodeGenerator extends
 
 	protected Output createOutput(GeneratorEntry entry) {
 		FeatureConfiguration outletConfig = getOutletFeatureConfiguration(entry);
-		FeatureParameterValue targetFolder = outletConfig
+		
+		FeatureParameterValue targetFolderValue = outletConfig
 				.getParameterValue(OUTLET_FEATURE_TARGET_FOLDER);
+		FeatureParameterValue libraryTargetFolderValue = outletConfig
+				.getParameterValue(OUTLET_FEATURE_LIBRARY_TARGET_FOLDER);
 
 		String absoluteTargetFolder = getTargetProject(entry).getLocation()
-				.toOSString() + File.separator + targetFolder.getExpression().toString();
+				.toOSString() + File.separator + targetFolderValue.getExpression().toString();
+
 		Output output = new OutputImpl();
-		Outlet outlet = new Outlet(absoluteTargetFolder);
+		
+		Outlet targetFolderOutlet = new Outlet(absoluteTargetFolder);
 		for (PostProcessor postProcessor : getPostProcessors()) {
-			outlet.addPostprocessor(postProcessor);
+			targetFolderOutlet.addPostprocessor(postProcessor);
+		}
+		targetFolderOutlet.setOverwrite(true);
+		output.addOutlet(targetFolderOutlet);
+
+		if(libraryTargetFolderValue != null){
+			String absoluteLibraryTargetFolder = getTargetProject(entry).getLocation()
+					.toOSString() + File.separator + libraryTargetFolderValue.getExpression().toString();
+			Outlet libraryTargetFolderOutlet = new Outlet(false, null, LIBRARY_TARGET_FOLDER_OUTLET, false, absoluteLibraryTargetFolder);
+			output.addOutlet(libraryTargetFolderOutlet);
 		}
-		outlet.setOverwrite(true);
-		output.addOutlet(outlet);
+		
 		return output;
 	}
 

+ 47 - 51
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/GenericJavaBasedGenerator.java

@@ -11,6 +11,7 @@
 package org.yakindu.sct.generator.core.impl;
 
 import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_TARGET_FOLDER;
+import static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER;
 import static org.yakindu.sct.generator.core.features.impl.IGenericJavaFeatureConstants.CONFIGURATION_MODULE;
 import static org.yakindu.sct.generator.core.features.impl.IGenericJavaFeatureConstants.GENERATOR_CLASS;
 import static org.yakindu.sct.generator.core.features.impl.IGenericJavaFeatureConstants.GENERATOR_PROJECT;
@@ -23,6 +24,7 @@ import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.xtext.generator.IFileSystemAccess;
+import org.eclipse.xtext.generator.OutputConfiguration;
 import org.eclipse.xtext.util.Strings;
 import org.yakindu.sct.commons.WorkspaceClassLoaderFactory;
 import org.yakindu.sct.generator.core.AbstractWorkspaceGenerator;
@@ -47,28 +49,23 @@ public class GenericJavaBasedGenerator extends AbstractSExecModelGenerator {
 		Module defaultModule = super.getChildInjectorModule(entry);
 
 		String overridingModuleClass = null;
-		FeatureConfiguration featureConfiguration = entry
-				.getFeatureConfiguration(TEMPLATE_FEATURE);
+		FeatureConfiguration featureConfiguration = entry.getFeatureConfiguration(TEMPLATE_FEATURE);
 		if (featureConfiguration != null) {
-			FeatureParameterValue parameterValue = featureConfiguration
-					.getParameterValue(CONFIGURATION_MODULE);
+			FeatureParameterValue parameterValue = featureConfiguration.getParameterValue(CONFIGURATION_MODULE);
 			if (parameterValue != null) {
 				overridingModuleClass = parameterValue.getStringValue();
 			}
 		}
 		if (!Strings.isEmpty(overridingModuleClass)) {
 			try {
-				Class<?> moduleClass = getClassLoader(entry).loadClass(
-						overridingModuleClass);
+				Class<?> moduleClass = getClassLoader(entry).loadClass(overridingModuleClass);
 				if (Module.class.isAssignableFrom(moduleClass)) {
 					Module module = (Module) moduleClass.newInstance();
-					defaultModule = Modules.override(defaultModule)
-							.with(module);
+					defaultModule = Modules.override(defaultModule).with(module);
 				}
 			} catch (Exception e) {
 				e.printStackTrace();
-				writeToConsole("Overriding module not found: "
-						+ overridingModuleClass);
+				writeToConsole("Overriding module not found: " + overridingModuleClass);
 			}
 		}
 		return defaultModule;
@@ -76,8 +73,8 @@ public class GenericJavaBasedGenerator extends AbstractSExecModelGenerator {
 
 	protected ClassLoader getClassLoader(GeneratorEntry entry) {
 		IProject project = getLookupRoot(entry);
-		final ClassLoader classLoader = new WorkspaceClassLoaderFactory()
-				.createClassLoader(project, getClass().getClassLoader());
+		final ClassLoader classLoader = new WorkspaceClassLoaderFactory().createClassLoader(project,
+				getClass().getClassLoader());
 		return classLoader;
 	}
 
@@ -87,38 +84,32 @@ public class GenericJavaBasedGenerator extends AbstractSExecModelGenerator {
 		final ClassLoader classLoader = getClassLoader(entry);
 		IFileSystemAccess fsa = getFileSystemAccess(entry);
 		try {
-			Class<?> delegateGeneratorClass = (Class<?>) classLoader
-					.loadClass(templateClass);
-			Object delegate = getInjector(entry).getInstance(
-					delegateGeneratorClass);
-
-			Class<?> iType_ = (Class<?>) getClass()
-					.getClassLoader()
-					.loadClass(
-							"org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator");
+			Class<?> delegateGeneratorClass = (Class<?>) classLoader.loadClass(templateClass);
+			Object delegate = getInjector(entry).getInstance(delegateGeneratorClass);
+
+			Class<?> iType_ = (Class<?>) getClass().getClassLoader()
+					.loadClass("org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator");
 			Class<?> iType__ = IExecutionFlowGenerator.class;
 			Class<?> iType = (Class<?>) classLoader
 					.loadClass("org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator");
-			
+
 			ExecutionFlow flow = createExecutionFlow(statechart, entry);
-			
+
 			if (isDumpSexec(entry)) {
 				dumpSexec(entry, flow);
 			}
-			
+
 			if (delegate instanceof AbstractWorkspaceGenerator) {
 				((AbstractWorkspaceGenerator) delegate).setBridge(bridge);
 			}
-			
+
 			if (delegate instanceof IExecutionFlowGenerator) {
 				IExecutionFlowGenerator flowGenerator = (IExecutionFlowGenerator) delegate;
-				flowGenerator.generate(flow, entry,
-						fsa);
+				flowGenerator.generate(flow, entry, fsa);
 			}
 			if (iType.isInstance(delegate)) {
 				IExecutionFlowGenerator flowGenerator = (IExecutionFlowGenerator) delegate;
-				flowGenerator.generate(flow, entry,
-						fsa);
+				flowGenerator.generate(flow, entry, fsa);
 			}
 			if (delegate instanceof ISGraphGenerator) {
 				ISGraphGenerator graphGenerator = (ISGraphGenerator) delegate;
@@ -131,8 +122,7 @@ public class GenericJavaBasedGenerator extends AbstractSExecModelGenerator {
 	}
 
 	protected String getTemplateClassName(GeneratorEntry entry) {
-		return entry.getFeatureConfiguration(TEMPLATE_FEATURE)
-				.getParameterValue(GENERATOR_CLASS).getStringValue();
+		return entry.getFeatureConfiguration(TEMPLATE_FEATURE).getParameterValue(GENERATOR_CLASS).getStringValue();
 	}
 
 	/**
@@ -141,17 +131,14 @@ public class GenericJavaBasedGenerator extends AbstractSExecModelGenerator {
 	 */
 	protected IProject getLookupRoot(GeneratorEntry entry) {
 		IProject project = null;
-		FeatureConfiguration templateConfig = entry
-				.getFeatureConfiguration(TEMPLATE_FEATURE);
-		FeatureParameterValue projectName = templateConfig
-				.getParameterValue(GENERATOR_PROJECT);
+		FeatureConfiguration templateConfig = entry.getFeatureConfiguration(TEMPLATE_FEATURE);
+		FeatureParameterValue projectName = templateConfig.getParameterValue(GENERATOR_PROJECT);
 		if (projectName != null) {
-			project = ResourcesPlugin.getWorkspace().getRoot()
-					.getProject(projectName.getStringValue());
+			project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName.getStringValue());
 		} else {
 			URI uri = entry.getElementRef().eResource().getURI();
-			project = ResourcesPlugin.getWorkspace().getRoot()
-					.getFile(new Path(uri.toPlatformString(true))).getProject();
+			project = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true)))
+					.getProject();
 		}
 		return project;
 	}
@@ -165,19 +152,28 @@ public class GenericJavaBasedGenerator extends AbstractSExecModelGenerator {
 		fileSystemAccess.setProject(getTargetProject(entry));
 
 		FeatureConfiguration outletConfig = getOutletFeatureConfiguration(entry);
-		String targetFolder = outletConfig
-				.getParameterValue(OUTLET_FEATURE_TARGET_FOLDER)
-				.getExpression().toString();
-
-		fileSystemAccess.setOutputPath(IFileSystemAccess.DEFAULT_OUTPUT,
-				targetFolder);
-		
-		if (fileSystemAccess.getOutputConfigurations().get(
-				IFileSystemAccess.DEFAULT_OUTPUT) != null) {
-			fileSystemAccess.getOutputConfigurations()
-					.get(IFileSystemAccess.DEFAULT_OUTPUT)
-					.setCreateOutputDirectory(true);
+
+		String targetFolder = outletConfig.getParameterValue(OUTLET_FEATURE_TARGET_FOLDER).getExpression().toString();
+		fileSystemAccess.setOutputPath(IFileSystemAccess.DEFAULT_OUTPUT, targetFolder);
+
+		FeatureParameterValue libraryTargetFolderValue = outletConfig
+				.getParameterValue(OUTLET_FEATURE_LIBRARY_TARGET_FOLDER);
+		if (libraryTargetFolderValue != null) {
+			fileSystemAccess.setOutputPath(IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT,
+					libraryTargetFolderValue.getExpression().toString());
 		}
+
+		fileSystemAccess.getOutputConfigurations().get(IFileSystemAccess.DEFAULT_OUTPUT).setCreateOutputDirectory(true);
+		OutputConfiguration librarytargetFolderOutputConfiguration = fileSystemAccess.getOutputConfigurations()
+				.get(IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT);
+		if (librarytargetFolderOutputConfiguration != null) {
+			librarytargetFolderOutputConfiguration.setCreateOutputDirectory(true);
+			// do not overwrite existing resources and ensure the folder is not
+			// cleaned.
+			librarytargetFolderOutputConfiguration.setCanClearOutputDirectory(false);
+			librarytargetFolderOutputConfiguration.setOverrideExistingResources(false);
+		}
+
 		return fileSystemAccess;
 	}
 

+ 19 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/impl/IExecutionFlowGenerator.java

@@ -6,5 +6,24 @@ import org.yakindu.sct.model.sgen.GeneratorEntry;
 
 public interface IExecutionFlowGenerator {
 
+	String TARGET_FOLDER_OUTPUT = IFileSystemAccess.DEFAULT_OUTPUT;
+	String LIBRARY_TARGET_FOLDER_OUTPUT = "LIBRARY_TARGET_FOLDER";
+
+	/**
+	 * 
+	 * @param flow
+	 *            The {@link ExecutionFlow} to generate.
+	 * @param entry
+	 *            The {@link GeneratorEntry} that contains the configuration for
+	 *            the generation.
+	 * @param fsa
+	 *            A file system access that should be used for the generated
+	 *            artifacts. In case a separate libraryTargetFolder is specified
+	 *            in the Outlet feature of the generator entry, the file system
+	 *            access will not only provide a configuration for
+	 *            {@link #TARGET_FOLDER_OUTPUT}, but also for
+	 *            {@link #LIBRARY_TARGET_FOLDER_OUTPUT}.
+	 * 
+	 */
 	abstract void generate(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa);
 }

+ 11 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/util/GeneratorUtils.java

@@ -95,6 +95,17 @@ public class GeneratorUtils {
 				.getPath()
 				+ File.separator + targetFolder);
 	}
+	
+	/** Gets the target folder path as a File that includes the project location */
+	public static File getLibraryTargetFolder(GeneratorEntry entry) {
+		String targetFolder = getOutletFeatureConfiguration(entry)
+				.getParameterValue(
+						ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER)
+				.getStringValue();
+		return new File(getTargetProject(entry).getLocation().toFile()
+				.getPath()
+				+ File.separator + targetFolder);
+	}
 
 	public static FeatureConfiguration getOutletFeatureConfiguration(
 			GeneratorEntry entry) {

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

@@ -9,10 +9,14 @@
  */
 package org.yakindu.sct.generator.java
 
+import com.google.inject.Inject
+import org.eclipse.xtext.generator.IFileSystemAccess
+import org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator
+import org.yakindu.sct.generator.core.util.GeneratorUtils
 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 static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER
 
 class IStatemachine {
 	
@@ -23,7 +27,14 @@ class IStatemachine {
 	extension GenmodelEntries
 	
 	def generateIStatemachine(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
-		fsa.generateFile(entry.basePackagePath + '/' + iStatemachine.java, content(entry))
+		if (GeneratorUtils.getOutletFeatureConfiguration(entry).getParameterValue(
+			OUTLET_FEATURE_LIBRARY_TARGET_FOLDER) != null) {	
+			// generate into library target folder in case one is specified, as the contents are static
+			fsa.generateFile(entry.basePackagePath + '/' + iStatemachine.java, IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT, content(entry))
+		} else {
+			// use default target folder path in case no library target folder is specified (the file will be overwritten there)
+			fsa.generateFile(entry.basePackagePath + '/' + iStatemachine.java, content(entry))
+		}
 	}
 	
 	def private content(GeneratorEntry entry) {

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

@@ -9,10 +9,14 @@
  */
 package org.yakindu.sct.generator.java
 
+import com.google.inject.Inject
+import org.eclipse.xtext.generator.IFileSystemAccess
+import org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator
+import org.yakindu.sct.generator.core.util.GeneratorUtils
 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 static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER
 
 class ITimer {
 	
@@ -23,7 +27,14 @@ class ITimer {
 	extension GenmodelEntries
 	
 	def generateITimer(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
-		fsa.generateFile(entry.basePackagePath + '/' + iTimer.java, content(entry))
+		if (GeneratorUtils.getOutletFeatureConfiguration(entry).getParameterValue(
+			OUTLET_FEATURE_LIBRARY_TARGET_FOLDER) != null) {	
+			// generate into library target folder in case one is specified, as the contents are static
+			fsa.generateFile(entry.basePackagePath + '/' + iTimer.java, IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT, content(entry))
+		} else {
+			// use default target folder path in case no library target folder is specified (the file will be overwritten there)
+			fsa.generateFile(entry.basePackagePath + '/' + iTimer.java, content(entry))
+		}
 	}
 	
 	def private content(GeneratorEntry entry) {

+ 40 - 28
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/ITimerCallback.xtend

@@ -1,49 +1,61 @@
 /**
-  Copyright (c) 2012 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 Muehlbrandt - Initial contribution and API
+ *   Copyright (c) 2012 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 Muehlbrandt - Initial contribution and API
  */
 package org.yakindu.sct.generator.java
 
+import com.google.inject.Inject
+import org.eclipse.xtext.generator.IFileSystemAccess
+import org.yakindu.sct.generator.core.impl.IExecutionFlowGenerator
+import org.yakindu.sct.generator.core.util.GeneratorUtils
 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 static org.yakindu.sct.generator.core.features.ICoreFeatureConstants.OUTLET_FEATURE_LIBRARY_TARGET_FOLDER
 
 class ITimerCallback {
-	
+
 	@Inject
-	extension Naming 
-	
+	extension Naming
+
 	@Inject
 	extension GenmodelEntries
-	
+
 	def generateITimerCallback(ExecutionFlow flow, GeneratorEntry entry, IFileSystemAccess fsa) {
-		fsa.generateFile(entry.basePackagePath + '/' + iTimerCallback.java, content(entry))
+		if (GeneratorUtils.getOutletFeatureConfiguration(entry).getParameterValue(
+			OUTLET_FEATURE_LIBRARY_TARGET_FOLDER) != null) {
+			// generate into library target folder in case one is specified, as the contents are static
+			fsa.generateFile(entry.basePackagePath + '/' + iTimerCallback.java,
+				IExecutionFlowGenerator.LIBRARY_TARGET_FOLDER_OUTPUT, content(entry))
+		} else {
+			// use default target folder path in case no library target folder is specified (the file will be overwritten there)
+			fsa.generateFile(entry.basePackagePath + '/' + iTimerCallback.java, content(entry))
+		}
 	}
-	
+
 	def private content(GeneratorEntry entry) {
 		'''
-		«entry.licenseText»
-		package «entry.getBasePackageName()»;
-
-		/**
-		* Interface for state machines which use timed event triggers.
-		*/
-		public interface ITimerCallback {
+			«entry.licenseText»
+			package «entry.getBasePackageName()»;
 			
 			/**
-			* Callback method if a time event occurred.
-			* 
-			* @param eventID
-			* 			:The id of the occurred event.
+			* Interface for state machines which use timed event triggers.
 			*/
-			public void timeElapsed(int eventID);
-		}
+			public interface ITimerCallback {
+				
+				/**
+				* Callback method if a time event occurred.
+				* 
+				* @param eventID
+				* 			:The id of the occurred event.
+				*/
+				public void timeElapsed(int eventID);
+			}
 		'''
 	}
 }