diff --git a/build.gradle b/build.gradle
index abad454662cd1bb7541260a074f8b699ff859938..519f4412c0b83b3ddf06dbca49b1de20cf73bf40 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,8 +17,7 @@ apply plugin: "idea"
 
 apply from: 'beaver.gradle'
 
-sourceCompatibility = 1.8
-targetCompatibility = 1.8
+java.toolchain.languageVersion.set(JavaLanguageVersion.of(11))
 
 repositories {
     jcenter()
diff --git a/src/main/jastadd/gen/Package.jadd b/src/main/jastadd/gen/Package.jadd
index 7218e844616c6c7f925a53f80f23ab3d928241f6..25c6841c07db435a4f6ea113c0eb932d09926843 100644
--- a/src/main/jastadd/gen/Package.jadd
+++ b/src/main/jastadd/gen/Package.jadd
@@ -30,9 +30,9 @@ aspect PackageGen {
         return de.tudresden.inf.st.pnml.gen.generators.JavaClassGenUtil.generateServerClass(dinerosPackage().getNamespace(), getName());
     }
 
-    syn String MapperFile.generate(PetriNet petriNet){
+    syn String MapperFile.generate(List<PetriNet> petriNets){
 
-        return de.tudresden.inf.st.pnml.gen.generators.JavaClassGenUtil.generateMapperClass(dinerosPackage().getNamespace(), petriNet);
+        return de.tudresden.inf.st.pnml.gen.generators.JavaClassGenUtil.generateMapperClass(dinerosPackage().getNamespace(), petriNets);
     }
 
     syn String DinerosPackage.generateTokenClass(){
diff --git a/src/main/jastadd/gen/Package.relast b/src/main/jastadd/gen/Package.relast
index 5cd0957b3a1bdd6fea581ed31fcad8662bef8fc6..8f04aff91d9052601cdaf8172f09a09efb6b2f68 100644
--- a/src/main/jastadd/gen/Package.relast
+++ b/src/main/jastadd/gen/Package.relast
@@ -2,7 +2,7 @@ DinerosPackage ::= Dir:PackageDirectory* File:PackageFile* <Name:String> <RootNa
 
 abstract PackageElement;
 
-abstract PackageFile:PackageElement ::= <Name:String>  ;
+abstract PackageFile:PackageElement ::= <Name:String> <FileID:String> ;
 StaticFile:PackageFile ;
 
 abstract TemplateFile:PackageFile ;
@@ -12,8 +12,8 @@ abstract JavaFile:TemplateFile ;
 NodeFile:JavaFile ;
 SubscriberFile:JavaFile ;
 ServerFile:JavaFile ;
-petriNet:JavaFile;
 MainFile:JavaFile ;
 MapperFile:JavaFile ;
+TokenFile:JavaFile ;
 
 PackageDirectory:PackageElement ::= Dir:PackageDirectory* File:PackageFile* <Name:String> ;
diff --git a/src/main/jastadd/gen/PackageNav.jadd b/src/main/jastadd/gen/PackageNav.jadd
index df7fda25cd1188b5023ccea718395dd5bcbc6b54..7fadba9f2b31f7ce57a48f2218fe9e56dfad8268 100644
--- a/src/main/jastadd/gen/PackageNav.jadd
+++ b/src/main/jastadd/gen/PackageNav.jadd
@@ -1,17 +1,71 @@
 aspect PackageNav {
 
-    inh DinerosPackage PackageElement.dinerosPackage();
-    eq DinerosPackage.getChild().dinerosPackage() = this;
+        inh DinerosPackage PackageElement.dinerosPackage();
+        eq DinerosPackage.getChild().dinerosPackage() = this;
 
-    syn boolean PackageFile.isStaticFile() = false;
-    eq StaticFile.isStaticFile() = true;
+        syn boolean PackageFile.isStaticFile() = false;
+        eq StaticFile.isStaticFile() = true;
 
-    syn StaticFile PackageFile.asStaticFile() = null;
-    eq StaticFile.asStaticFile() = this;
+        syn StaticFile PackageFile.asStaticFile() = null;
+        eq StaticFile.asStaticFile() = this;
 
-    coll java.util.Set<PackageDirectory> DinerosPackage.allDirectories() [new java.util.HashSet()] root DinerosPackage;
-        PackageDirectory contributes this
-        to DinerosPackage.allDirectories()
-        for dinerosPackage();
+        // -----
 
+        syn boolean PackageFile.isNodeFile() = false;
+        eq NodeFile.isNodeFile() = true;
+
+        syn NodeFile PackageFile.asNodeFile() = null;
+        eq NodeFile.asNodeFile() = this;
+
+
+        syn boolean PackageFile.isSubscriberFile() = false;
+        eq SubscriberFile.isSubscriberFile() = true;
+
+        syn SubscriberFile PackageFile.asSubscriberFile() = null;
+        eq SubscriberFile.asSubscriberFile() = this;
+
+
+        syn boolean PackageFile.isServerFile() = false;
+        eq ServerFile.isServerFile() = true;
+
+        syn ServerFile PackageFile.asServerFile() = null;
+        eq ServerFile.asServerFile() = this;
+
+
+        syn boolean PackageFile.isMainFile() = false;
+        eq MainFile.isMainFile() = true;
+
+        syn MainFile PackageFile.asMainFile() = null;
+        eq MainFile.asMainFile() = this;
+
+
+        syn boolean PackageFile.isMapperFile() = false;
+        eq MapperFile.isMapperFile() = true;
+
+        syn MapperFile PackageFile.asMapperFile() = null;
+        eq MapperFile.asMapperFile() = this;
+
+
+        syn boolean PackageFile.isTokenFile() = false;
+        eq TokenFile.isTokenFile() = true;
+
+        syn TokenFile PackageFile.asTokenFile() = null;
+        eq TokenFile.asTokenFile() = this;
+
+        syn boolean PackageFile.isGradleFile() = false;
+        eq GradleFile.isGradleFile() = true;
+
+        syn GradleFile PackageFile.asGradleFile() = null;
+        eq GradleFile.asGradleFile() = this;
+
+
+        coll java.util.Set<PackageDirectory> DinerosPackage.allDirectories() [new java.util.HashSet()] root DinerosPackage;
+            PackageDirectory contributes this
+            to DinerosPackage.allDirectories()
+            for dinerosPackage();
+
+        coll java.util.Set<PackageFile> DinerosPackage.allPackageFiles() [new java.util.HashSet()] root DinerosPackage;
+            PackageFile contributes this
+            to DinerosPackage.allPackageFiles()
+            for dinerosPackage();
 }
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/Main.java b/src/main/java/de/tudresden/inf/st/pnml/gen/Main.java
index 4228a90236248285eb4aaedb667b271c0959e108..fc87537452a89cbd7637ff1383d319d70216f14e 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/gen/Main.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/Main.java
@@ -1,6 +1,9 @@
 package de.tudresden.inf.st.pnml.gen;
 
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import de.tudresden.inf.st.pnml.gen.builders.PackageStructureBuilder;
+import de.tudresden.inf.st.pnml.gen.json.NetInfo;
 import de.tudresden.inf.st.pnml.jastadd.model.DinerosPackage;
 import de.tudresden.inf.st.pnml.jastadd.model.GradleFile;
 import de.tudresden.inf.st.pnml.jastadd.model.PackageDirectory;
@@ -8,6 +11,8 @@ import de.tudresden.inf.st.pnml.jastadd.model.PackageDirectory;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
 
 public class Main {
 
@@ -36,20 +41,21 @@ public class Main {
         String namespace = "sample";
         String version = "0.1";
         String engineVersion = "0.1";
+        String configFile = "/home/sebastian/Desktop/EngineConfig.json";
 
 
         DinerosPackage dp = new DinerosPackage();
         dp.setName(packageName);
         dp.setRootName(rootName);
         dp.setNamespace(namespace);
-        dp.setTokenClass(Files.readString(Path.of(tokenClassPath)));
+        dp.setTokenClass(Files.readString(Paths.get(tokenClassPath)));
         dp.setVersion(version);
 
-        PackageStructureBuilder.buildDinerosPackageStructure(rootName, namespace, dp);
+        String configString = Files.readString(Paths.get(configFile));
+        ObjectMapper objectMapper = new ObjectMapper();
+        List<NetInfo> petriNetFilePaths = objectMapper.readValue(configString, new TypeReference<List<NetInfo>>(){});
 
-        PackageStructureBuilder.build("/home/sebastian/Desktop", dp, "sample", null, engineVersion);
+        PackageStructureBuilder.build("/home/sebastian/Desktop", dp, "sample-pkg", petriNetFilePaths, engineVersion);
 
     }
-
-
 }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/builders/PackageStructureBuilder.java b/src/main/java/de/tudresden/inf/st/pnml/gen/builders/PackageStructureBuilder.java
index 14160cbfd8940c5b2136e4ae3073b1ec7db8e7c0..a1cb13846ff8e2c7dad5d120e3f6c43073f07ddf 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/gen/builders/PackageStructureBuilder.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/builders/PackageStructureBuilder.java
@@ -1,34 +1,49 @@
 package de.tudresden.inf.st.pnml.gen.builders;
 
-import de.tudresden.inf.st.pnml.jastadd.model.DinerosPackage;
-import de.tudresden.inf.st.pnml.jastadd.model.PackageDirectory;
-import de.tudresden.inf.st.pnml.jastadd.model.PackageFile;
-import de.tudresden.inf.st.pnml.jastadd.model.StaticFile;
+import de.tudresden.inf.st.pnml.base.constants.PnmlConstants;
+import de.tudresden.inf.st.pnml.gen.json.NetInfo;
+import de.tudresden.inf.st.pnml.jastadd.model.*;
 
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
-import java.util.List;
+import java.util.*;
 
 public class PackageStructureBuilder {
 
     private static final String FILE_PATH = "../pnml-relast-pkg-gen/src/main/resources/static/";
 
-    public static boolean build(String targetPath, DinerosPackage dinerosPackage, String javaBasePackageName, List<String> petriNetFilePaths, String engineVersion){
+    public static boolean build(String targetPath, DinerosPackage dinerosPackage, String javaBasePackageName, List<NetInfo> petriNetFilePaths, String engineVersion) {
 
         String packagePath = targetPath + "/" + dinerosPackage.getRootName();
 
+        List<PetriNet> nets = new ArrayList<>();
+
+        for (NetInfo n : petriNetFilePaths) {
+            nets.add(PnmlParser.parsePnml(n.getNet()).get(0));
+        }
+
         try {
             Files.createDirectories(Paths.get(packagePath));
-            buildDirectoriesRecursive(dinerosPackage.getDir(0), packagePath);
+
+            buildDinerosPackageStructure(dinerosPackage.getRootName(), dinerosPackage.getNamespace(), dinerosPackage);
+            buildDinerosGeneratedFilesStructure(dinerosPackage, nets);
+            buildStaticFilesIntoDinerosPackage(dinerosPackage, engineVersion);
+
+            includeDirectoriesRecursive(dinerosPackage.getDir(0), packagePath);
+            includeTemplateFiles(dinerosPackage, nets, javaBasePackageName, engineVersion);
+            includeFilesInPackageRecursive(dinerosPackage.getDir(0), packagePath);
+
+            // TODO: include pnml files
+
+            // TODO: include token class
 
         } catch (IOException e) {
             System.out.println(e.getMessage() + " caused by: " + e.getCause());
         }
 
-
         return false;
     }
 
@@ -36,39 +51,137 @@ public class PackageStructureBuilder {
     // TREE GEN /////////////////////////
     /////////////////////////////////////
 
-    private static void includeStaticFilesInDinerosPackage(String targetPath, DinerosPackage dinerosPackage, String engineVersion){
+    private static void buildDinerosGeneratedFilesStructure(DinerosPackage dinerosPackage, List<PetriNet> nets) {
+
+        GradleFile buildGradle = new GradleFile();
+        buildGradle.setName("build.gradle");
+        buildGradle.setFileID(UUID.randomUUID().toString());
+        dinerosPackage.addFile(buildGradle);
+
+        GradleFile gradleProbs = new GradleFile();
+        gradleProbs.setName("gradle.properties");
+        gradleProbs.setFileID(UUID.randomUUID().toString());
 
-        for(PackageDirectory pd : dinerosPackage.allDirectories()){
+        for (PackageDirectory pd : dinerosPackage.allDirectories()) {
 
-            if(pd.getName().equals("wrapper")){
+            if (pd.getName().equals(dinerosPackage.getNamespace())) {
+                MainFile mainFile = new MainFile();
+                mainFile.setName("Main");
+                mainFile.setFileID(UUID.randomUUID().toString());
+                pd.addFile(mainFile);
+            }
+
+            if (pd.getName().equals("nodes")) {
+                for (int i = 0; i < nets.size(); i++) {
+                    NodeFile nodeFile = new NodeFile();
+                    nodeFile.setName("Node" + i);
+                    nodeFile.setFileID(UUID.randomUUID().toString());
+                    pd.addFile(nodeFile);
+                }
+            }
+
+            if (pd.getName().equals("communication")) {
+                for (int i = 0; i < nets.size(); i++) {
+
+                    int serverCount = 0;
+                    int subscriberCount = 0;
+
+                    for (Transition t : nets.get(i).allTransitions()) {
+
+                        String transitionType = t.asInputSignalTransition().getStaticTransitionInformation().getType();
+
+                        if (transitionType.equals(PnmlConstants.TRANSITION_TYPE_SERVICE_REQUEST_OUT)) {
+                            ServerFile server = new ServerFile();
+                            server.setName("Node" + i + "Server" + serverCount);
+                            server.setFileID(UUID.randomUUID().toString());
+                            pd.addFile(server);
+                            serverCount++;
+                        }
+                        if (transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_LIMITED_IN)
+                                || transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_UNLIMITED_IN)) {
+                            SubscriberFile subscriber = new SubscriberFile();
+                            subscriber.setName("Node" + i + "Subscriber" + subscriberCount);
+                            subscriber.setFileID(UUID.randomUUID().toString());
+                            pd.addFile(subscriber);
+                            subscriberCount++;
+                        }
+                    }
+                }
+            }
+
+            if (pd.getName().equals("callback")) {
+                MapperFile callbackMapper = new MapperFile();
+                callbackMapper.setName("CallbackMapper.java");
+                callbackMapper.setFileID(UUID.randomUUID().toString());
+                pd.addFile(callbackMapper);
+            }
+
+            if (pd.getName().equals("balloon")) {
+                TokenFile tokenFile = new TokenFile();
+                tokenFile.setName("Token.java");
+                tokenFile.setFileID(UUID.randomUUID().toString());
+                pd.addFile(tokenFile);
+            }
+        }
+    }
+
+    private static void buildStaticFilesIntoDinerosPackage(DinerosPackage dinerosPackage, String engineVersion) {
+
+        for (PackageDirectory pd : dinerosPackage.allDirectories()) {
+
+            if (pd.getName().equals("wrapper")) {
                 StaticFile wrapperJar = new StaticFile();
                 wrapperJar.setName("gradle-wrapper.jar");
+                wrapperJar.setFileID(UUID.randomUUID().toString());
                 pd.addFile(wrapperJar);
 
                 StaticFile wrapperProperties = new StaticFile();
                 wrapperProperties.setName("gradle-wrapper.properties");
+                wrapperProperties.setFileID(UUID.randomUUID().toString());
                 pd.addFile(wrapperProperties);
             }
 
-            if(pd.getName().equals(dinerosPackage.getRootName())) {
+            if (pd.getName().equals(dinerosPackage.getRootName())) {
                 StaticFile gradlew = new StaticFile();
                 gradlew.setName("gradlew");
+                gradlew.setFileID(UUID.randomUUID().toString());
                 pd.addFile(gradlew);
 
                 StaticFile gradlewBat = new StaticFile();
                 gradlewBat.setName("gradlew.bat");
+                gradlewBat.setFileID(UUID.randomUUID().toString());
                 pd.addFile(gradlewBat);
             }
 
-            if(pd.getName().equals("libs")) {
+            if (pd.getName().equals("libs")) {
                 StaticFile engineJar = new StaticFile();
                 engineJar.setName("pnml-relast-engine-fatjar-" + engineVersion + ".jar");
+                engineJar.setFileID(UUID.randomUUID().toString());
                 pd.addFile(engineJar);
             }
+
+            if (pd.getName().equals("communication")) {
+                StaticFile server = new StaticFile();
+                server.setName("AbstractDinerosServer.java");
+                server.setFileID(UUID.randomUUID().toString());
+                pd.addFile(server);
+
+                StaticFile subscriber = new StaticFile();
+                subscriber.setName("AbstractDinerosSubscriber.java");
+                subscriber.setFileID(UUID.randomUUID().toString());
+                pd.addFile(subscriber);
+            }
+
+            if (pd.getName().equals("callback")) {
+                StaticFile cb = new StaticFile();
+                cb.setName("AbstractNetCallback.java");
+                cb.setFileID(UUID.randomUUID().toString());
+                pd.addFile(cb);
+            }
         }
     }
 
-    public static void buildDinerosPackageStructure(String rootName, String namespace, DinerosPackage dp) {
+    private static void buildDinerosPackageStructure(String rootName, String namespace, DinerosPackage dp) {
         PackageDirectory root = new PackageDirectory();
         root.setName(rootName);
         dp.addDir(root);
@@ -146,13 +259,114 @@ public class PackageStructureBuilder {
     // TREE TO FILE TREE ////////////////
     /////////////////////////////////////
 
-    private static void buildDirectoriesRecursive(PackageDirectory packageDirectory, String packagePath) throws IOException {
+    // TODO: javaBasePackageName
+    private static void includeTemplateFiles(DinerosPackage dinerosPackage, List<PetriNet> nets, String javaBasePackageName, String engineVersion) {
+
+        Set<String> visitedPackageFileIDs = new HashSet<>();
+        Map<String, Integer> subscriberCountMap = initSubscriberCountMap(nets);
+        Map<String, Integer> serviceCountMap = initServiceCountMap(nets);
+
+        for (PackageFile pf : dinerosPackage.allPackageFiles()) {
+            if (pf.isMapperFile()) {
+                pf.asMapperFile().generate(nets);
+            }
+        }
+
+        for (int i = 0; i < nets.size(); i++) {
+            for (PackageFile pf : dinerosPackage.allPackageFiles()) {
+
+                if (!visitedPackageFileIDs.contains(pf.getFileID())) {
+                    visitedPackageFileIDs.add(pf.getFileID());
 
-        for(PackageDirectory d : packageDirectory.getDirList()){
-            buildDirectoriesRecursive(d, packagePath + "/" + packageDirectory.getName());
+                    if (pf.isNodeFile()) {
+                        pf.setName("Node" + i);
+                        pf.asNodeFile().generate();
+                    }
+
+                    if (pf.isSubscriberFile()) {
+
+                        for (Transition t : nets.get(i).allTransitions()) {
+
+                            String transitionType = t.asInputSignalTransition().getStaticTransitionInformation().getType();
+
+                            if (transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_LIMITED_IN)
+                                    || transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_UNLIMITED_IN)) {
+                                pf.setName("Node" + i + "Subscriber" + subscriberCountMap.get(nets.get(i).getId()));
+                                pf.asSubscriberFile().generate();
+                                subscriberCountMap.put(nets.get(i).getId(), subscriberCountMap.get(nets.get(i).getId()) + 1);
+                            }
+                        }
+                    }
+
+                    if (pf.isServerFile()) {
+
+                        for (Transition t : nets.get(i).allTransitions()) {
+
+                            String transitionType = t.asInputSignalTransition().getStaticTransitionInformation().getType();
+
+                            if (transitionType.equals(PnmlConstants.TRANSITION_TYPE_SERVICE_REQUEST_OUT)) {
+                                pf.setName("Node" + i + "Server" + serviceCountMap.get(nets.get(i).getId()));
+                                pf.asSubscriberFile().generate();
+                                serviceCountMap.put(nets.get(i).getId(), serviceCountMap.get(nets.get(i).getId()) + 1);
+                            }
+                        }
+                    }
+
+                    if (pf.getName().equals("build.gradle")) {
+                        String mainClassName = "de.tudresden.inf.st." + dinerosPackage.getNamespace() + ".Main.java";
+                        pf.asGradleFile().generateBuildGradle(mainClassName, dinerosPackage.getName(), dinerosPackage.getVersion(), engineVersion);
+                    }
+
+                    if (pf.getName().equals("settings.gradle")) {
+                        pf.asGradleFile().generateSettingsGradle(dinerosPackage.getRootName());
+                    }
+                }
+            }
         }
+    }
+
+    private static Map<String, Integer> initServiceCountMap(List<PetriNet> nets) {
+
+        Map<String, Integer> countMap = new HashMap<>();
 
-        if(packageDirectory.getNumDir() == 0){
+        for (int i = 0; i < nets.size(); i++) {
+            for (Transition t : nets.get(i).allTransitions()) {
+
+                String transitionType = t.asInputSignalTransition().getStaticTransitionInformation().getType();
+
+                if (transitionType.equals(PnmlConstants.TRANSITION_TYPE_SERVICE_REQUEST_OUT)) {
+                    countMap.put(nets.get(i).getId(), 1);
+                }
+            }
+        }
+        return countMap;
+    }
+
+    private static Map<String, Integer> initSubscriberCountMap(List<PetriNet> nets) {
+
+        Map<String, Integer> countMap = new HashMap<>();
+
+        for (int i = 0; i < nets.size(); i++) {
+            for (Transition t : nets.get(i).allTransitions()) {
+
+                String transitionType = t.asInputSignalTransition().getStaticTransitionInformation().getType();
+
+                if (transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_LIMITED_IN)
+                        || transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_UNLIMITED_IN)) {
+                    countMap.put(nets.get(i).getId(), 1);
+                }
+            }
+        }
+        return countMap;
+    }
+
+    private static void includeDirectoriesRecursive(PackageDirectory packageDirectory, String packagePath) throws IOException {
+
+        for (PackageDirectory d : packageDirectory.getDirList()) {
+            includeDirectoriesRecursive(d, packagePath + "/" + packageDirectory.getName());
+        }
+
+        if (packageDirectory.getNumDir() == 0) {
             Files.createDirectories(Paths.get(packagePath + "/" + packageDirectory.getName()));
             return;
         }
@@ -160,16 +374,25 @@ public class PackageStructureBuilder {
 
     private static void includeFilesInPackageRecursive(PackageDirectory packageDirectory, String packagePath) throws IOException {
 
-        for(PackageDirectory d : packageDirectory.getDirList()){
+        for (PackageDirectory d : packageDirectory.getDirList()) {
             includeFilesInPackageRecursive(d, packagePath + "/" + packageDirectory.getName());
         }
 
-        if(packageDirectory.getNumFile() > 0){
-            for(PackageFile pf : packageDirectory.getFileList()){
-                if(pf.isStaticFile()){
-                    Path copied = Paths.get(packagePath + "/" + pf.getName());
-                    Path originalPath = Paths.get(FILE_PATH + "/" + pf.getName());
+        if (packageDirectory.getNumFile() > 0) {
+            for (PackageFile pf : packageDirectory.getFileList()) {
+                if (pf.isStaticFile()) {
+
+                    Path copied = Paths.get(packagePath + "/" + packageDirectory.getName() + "/" + pf.getName());
+                    Path originalPath = null;
+
+                    if (pf.getName().contains(".java")) {
+                        originalPath = Paths.get(FILE_PATH + "/" + pf.getName().split("\\.")[0]);
+                    } else {
+                        originalPath = Paths.get(FILE_PATH + "/" + pf.getName());
+                    }
+
                     Files.copy(originalPath, copied, StandardCopyOption.REPLACE_EXISTING);
+                    System.out.println("Copy:" + originalPath + " --> " + copied);
                 }
             }
             return;
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/generators/JavaClassGenUtil.java b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/JavaClassGenUtil.java
index 21fe80eb24426c40cbd4e472af4293d2d98fe6ee..05ea871426c81e5fd11b8690605b77ede6cc7f1a 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/gen/generators/JavaClassGenUtil.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/JavaClassGenUtil.java
@@ -31,6 +31,7 @@ public class JavaClassGenUtil extends AbstractGenUtil{
             nodeInfos.add(nodeInfo);
 
             int serverCount = 0;
+            int subscriberCount = 0;
 
             for(Transition t : petriNetList.get(i).allTransitions()){
 
@@ -43,7 +44,8 @@ public class JavaClassGenUtil extends AbstractGenUtil{
                 }
                 if(transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_LIMITED_IN)
                         || transitionType.equals(PnmlConstants.TRANSITION_TYPE_TOPIC_UNLIMITED_IN) ){
-                    subscriberInfos.add(new SubscriberInfo("node" + i, subnet, "Node" + i + "Subscriber" + serverCount));
+                    subscriberInfos.add(new SubscriberInfo("node" + i, subnet, "Node" + i + "Subscriber" + subscriberCount));
+                    subscriberCount++;
                 }
             }
         }
@@ -79,7 +81,7 @@ public class JavaClassGenUtil extends AbstractGenUtil{
         return generate(context, "JavaServer.mustache");
     }
 
-    public static String generateMapperClass(String packageNamespace, PetriNet petriNet){
+    public static String generateMapperClass(String packageNamespace, List<PetriNet> petriNets){
 
         Map<String, Object> context = new HashMap<>();
         MapperContext mapperContext = new MapperContext(packageNamespace);
@@ -87,7 +89,7 @@ public class JavaClassGenUtil extends AbstractGenUtil{
 
         List<MapperInfo> mapperInfos = new ArrayList<>();
 
-        for(int i = 1; i < petriNet.allTransitions().size(); i++){
+        for(int i = 1; i < petriNets.size(); i++){
             MapperInfo mapperInfo = new MapperInfo("Node" + i);
             mapperInfos.add(mapperInfo);
         }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/json/NetInfo.java b/src/main/java/de/tudresden/inf/st/pnml/gen/json/NetInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..09c7ed660904ad0fc2a0bd711d2a7be64eee12e4
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/json/NetInfo.java
@@ -0,0 +1,18 @@
+package de.tudresden.inf.st.pnml.gen.json;
+
+public class NetInfo {
+
+    private String net;
+
+    public NetInfo(String net) {
+        this.net = net;
+    }
+
+    public String getNet() {
+        return net;
+    }
+
+    public void setNet(String net) {
+        this.net = net;
+    }
+}
diff --git a/src/main/resources/static/AbstractDinerosServer b/src/main/resources/static/AbstractDinerosServer
new file mode 100644
index 0000000000000000000000000000000000000000..f62980758f63624cc93a6d1c25f118a15e5689a3
--- /dev/null
+++ b/src/main/resources/static/AbstractDinerosServer
@@ -0,0 +1,25 @@
+package de.tudresden.inf.st.sample.communication;
+
+import de.tudresden.inf.st.pnml.engine.ros.DiNeRosNodeUtil;
+import de.tudresden.inf.st.pnml.engine.ros.DiNeRosServer;
+import de.tudresden.inf.st.pnml.jastadd.model.BalloonCallbackStorage;
+import de.tudresden.inf.st.pnml.jastadd.model.BalloonMarking;
+import de.tudresden.inf.st.pnml.jastadd.model.PetriNet;
+
+public abstract class AbstractDinerosServer implements DiNeRosServer {
+
+    @Override
+    public final boolean execute(BalloonMarking balloonMarking, BalloonCallbackStorage balloonCallbackStorage, PetriNet petriNet, String s) {
+
+        boolean success = false;
+
+        // this mechanism enforces the user to leave a server instance with a clean state (see server def)
+        while (DiNeRosNodeUtil.hasEnabledTransition(petriNet, s, balloonMarking)) {
+            success = serve(balloonMarking, balloonCallbackStorage, petriNet, s);
+        }
+
+        return success;
+    }
+
+    public abstract boolean serve(BalloonMarking balloonMarking, BalloonCallbackStorage balloonCallbackStorage, PetriNet petriNet, String subnet);
+}
diff --git a/src/main/resources/static/AbstractDinerosSubscriber b/src/main/resources/static/AbstractDinerosSubscriber
new file mode 100644
index 0000000000000000000000000000000000000000..fef2e51ed54351c78fb5c976b3613fdcc979ea6c
--- /dev/null
+++ b/src/main/resources/static/AbstractDinerosSubscriber
@@ -0,0 +1,24 @@
+package de.tudresden.inf.st.sample.communication;
+
+import de.tudresden.inf.st.pnml.engine.ros.DiNeRosNodeUtil;
+import de.tudresden.inf.st.pnml.engine.ros.DiNeRosSubscriber;
+import de.tudresden.inf.st.pnml.jastadd.model.BalloonCallbackStorage;
+import de.tudresden.inf.st.pnml.jastadd.model.BalloonMarking;
+import de.tudresden.inf.st.pnml.jastadd.model.PetriNet;
+
+public abstract class AbstractDinerosSubscriber implements DiNeRosSubscriber {
+
+    public final boolean execute(BalloonMarking balloonMarking, BalloonCallbackStorage balloonCallbackStorage, PetriNet petriNet, String subnet) {
+
+        boolean success = false;
+
+        // this mechanism enforces the user to leave a server instance with a clean state (see server def)
+        while (DiNeRosNodeUtil.hasEnabledTransition(petriNet, subnet, balloonMarking)) {
+            success = subscribe(balloonMarking, balloonCallbackStorage, petriNet, subnet);
+        }
+
+        return  success;
+    }
+
+    public abstract boolean subscribe(BalloonMarking balloonMarking, BalloonCallbackStorage balloonCallbackStorage, PetriNet petriNet, String subnet);
+}
diff --git a/src/main/resources/static/AbstractNetCallback b/src/main/resources/static/AbstractNetCallback
new file mode 100644
index 0000000000000000000000000000000000000000..96804024fc4b51c98d915e71786432e5b818aa8b
--- /dev/null
+++ b/src/main/resources/static/AbstractNetCallback
@@ -0,0 +1,63 @@
+package de.tudresden.inf.st.sample.callback;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.tudresden.inf.st.pnml.engine.execution.TransitionCallback;
+import de.tudresden.inf.st.pnml.jastadd.model.BalloonToken;
+import de.tudresden.inf.st.sample.balloon.Token;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+// only the token class is generated, this is a static class
+// this class gets extended by the user for concrete callbacks
+// this class hides (de-)serialisation of the tokens
+public abstract class AbstractNetCallback extends TransitionCallback {
+
+    public AbstractNetCallback(String id, int priority, List<String> params) {
+        super(id, priority, params);
+    }
+
+    public AbstractNetCallback(String id, int priority) {
+        super(id, priority);
+    }
+
+    private Token parseToken(String s) throws IOException {
+        ObjectMapper mapper = new ObjectMapper();
+        return mapper.readValue(s, Token.class);
+    }
+
+    public abstract void processTokenCallback(List<Token> tokens);
+
+    @Override
+    public final List<BalloonToken> processToken(List<BalloonToken> tokens) {
+
+        List<Token> resultTokens = new ArrayList<>();
+        List<BalloonToken> resultBalloonTokens = new ArrayList<>();
+        ObjectMapper mapper = new ObjectMapper();
+
+        for(BalloonToken bt : tokens){
+            try {
+                Token t = parseToken(bt.getValue());
+                resultTokens.add(t);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+        processTokenCallback(resultTokens);
+
+        for(Token t : resultTokens){
+            BalloonToken newBt = new BalloonToken();
+            try {
+                newBt.setValue(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(t));
+                resultBalloonTokens.add(newBt);
+            } catch (JsonProcessingException e) {
+                e.printStackTrace();
+            }
+        }
+
+        return resultBalloonTokens;
+    }
+}