From f6e709e3ba2dc627bcd593a435074133148eb76a Mon Sep 17 00:00:00 2001
From: SebastianEbert <sebastian.ebert@tu-dresden.de>
Date: Thu, 4 Aug 2022 18:33:00 +0200
Subject: [PATCH] base mustache generation

---
 src/main/jastadd/gen/Package.jadd             |  13 ++
 src/main/jastadd/gen/Package.relast           |   4 +-
 .../de/tudresden/inf/st/pnml/gen/Main.java    |   6 +-
 .../pnml/gen/data/MainExecutionContext.java   |  48 ++++++++
 .../inf/st/pnml/gen/data/MapperContext.java   |  18 +++
 .../inf/st/pnml/gen/data/MapperInfo.java      |  18 +++
 .../inf/st/pnml/gen/data/NodeContext.java     |  28 +++++
 .../inf/st/pnml/gen/data/NodeInfo.java        |  48 ++++++++
 .../inf/st/pnml/gen/data/ServerContext.java   |  28 +++++
 .../inf/st/pnml/gen/data/ServerInfo.java      |  40 +++++++
 .../st/pnml/gen/data/SubscriberContext.java   |  28 +++++
 .../inf/st/pnml/gen/data/SubscriberInfo.java  |  38 ++++++
 .../inf/st/pnml/gen/data/TokenContext.java    |  18 +++
 .../pnml/gen/generators/AbstractGenUtil.java  |  28 +++++
 .../st/pnml/gen/generators/GradleGenUtil.java |  25 ++--
 .../pnml/gen/generators/JavaClassGenUtil.java | 104 +++++++++++++++-
 .../st/pnml/gen/generators/TokenGenUtil.java  |   2 +-
 .../mustache/JavaCallbackMapper.mustache      |  27 +++++
 src/main/resources/mustache/JavaMain.mustache | 111 ++++++++++++++++++
 src/main/resources/mustache/JavaNode.mustache |  26 ++++
 .../resources/mustache/JavaServer.mustache    |  15 +++
 .../mustache/JavaSubscriber.mustache          |  18 +++
 .../resources/mustache/JavaToken.mustache     |   9 ++
 23 files changed, 681 insertions(+), 19 deletions(-)
 create mode 100644 src/main/jastadd/gen/Package.jadd
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/MainExecutionContext.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperContext.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperInfo.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeContext.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeInfo.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerContext.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerInfo.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberContext.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberInfo.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/data/TokenContext.java
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/gen/generators/AbstractGenUtil.java
 create mode 100644 src/main/resources/mustache/JavaCallbackMapper.mustache
 create mode 100644 src/main/resources/mustache/JavaMain.mustache
 create mode 100644 src/main/resources/mustache/JavaNode.mustache
 create mode 100644 src/main/resources/mustache/JavaServer.mustache
 create mode 100644 src/main/resources/mustache/JavaSubscriber.mustache
 create mode 100644 src/main/resources/mustache/JavaToken.mustache

diff --git a/src/main/jastadd/gen/Package.jadd b/src/main/jastadd/gen/Package.jadd
new file mode 100644
index 0000000..0da8e36
--- /dev/null
+++ b/src/main/jastadd/gen/Package.jadd
@@ -0,0 +1,13 @@
+aspect PackageGen {
+
+    syn String GradleFile.generateSettingsGradle(String rootProjectName){
+
+        return de.tudresden.inf.st.pnml.gen.generators.GradleGenUtil.generateGradleSettings(rootProjectName);
+    }
+
+    syn String GradleFile.generateBuildGradle(String mainClass, String archiveBaseName, String version, String pnmlRelastersion){
+
+        return de.tudresden.inf.st.pnml.gen.generators.GradleGenUtil.generateBuildGradle(mainClass, archiveBaseName, version, pnmlRelastersion);
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/jastadd/gen/Package.relast b/src/main/jastadd/gen/Package.relast
index 8752bd8..b592026 100644
--- a/src/main/jastadd/gen/Package.relast
+++ b/src/main/jastadd/gen/Package.relast
@@ -2,12 +2,14 @@ DinerosPackage ::= Dir:PackageDirectory* File:PackageFile* <Name:String> <TokenC
 
 abstract PackageFile ::= <Name:String>  ;
 
-TemplateFile:PackageFile ;
+abstract TemplateFile:PackageFile ;
 StaticFile:PackageFile ;
 
 NodeFile:TemplateFile ;
 SubscriberFile:TemplateFile ;
 ServerFile:TemplateFile ;
 MapperFile:TemplateFile;
+GradleFile:TemplateFile ;
+MainFile:TemplateFile ;
 
 PackageDirectory ::= <Name:String> ;
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 affb607..e95c6f0 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,10 +1,14 @@
 package de.tudresden.inf.st.pnml.gen;
 
+import de.tudresden.inf.st.pnml.jastadd.model.GradleFile;
+
 public class Main {
 
     public static void main(java.lang.String[] args){
 
-        // TODO
+        GradleFile gf = new GradleFile();
+        gf.setName("TestFile");
+        System.out.println(gf.generateSettingsGradle("test-project-name"));
 
     }
 }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/MainExecutionContext.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/MainExecutionContext.java
new file mode 100644
index 0000000..b4322c6
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/MainExecutionContext.java
@@ -0,0 +1,48 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class MainExecutionContext {
+
+    private String rosHost;
+    private String rostMasterUri;
+    private String mqttHost;
+    private String packageNamespace;
+
+    public MainExecutionContext(String rosHost, String rostMasterUri, String mqttHost, String packageNamespace) {
+        this.rosHost = rosHost;
+        this.rostMasterUri = rostMasterUri;
+        this.mqttHost = mqttHost;
+        this.packageNamespace = packageNamespace;
+    }
+
+    public String getRosHost() {
+        return rosHost;
+    }
+
+    public void setRosHost(String rosHost) {
+        this.rosHost = rosHost;
+    }
+
+    public String getRostMasterUri() {
+        return rostMasterUri;
+    }
+
+    public void setRostMasterUri(String rostMasterUri) {
+        this.rostMasterUri = rostMasterUri;
+    }
+
+    public String getMqttHost() {
+        return mqttHost;
+    }
+
+    public void setMqttHost(String mqttHost) {
+        this.mqttHost = mqttHost;
+    }
+
+    public String getPackageNamespace() {
+        return packageNamespace;
+    }
+
+    public void setPackageNamespace(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperContext.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperContext.java
new file mode 100644
index 0000000..b158191
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperContext.java
@@ -0,0 +1,18 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class MapperContext {
+
+    private String packageNamespace;
+
+    public MapperContext(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+
+    public String getPackageNamespace() {
+        return packageNamespace;
+    }
+
+    public void setPackageNamespace(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperInfo.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperInfo.java
new file mode 100644
index 0000000..bb397fd
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/MapperInfo.java
@@ -0,0 +1,18 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class MapperInfo {
+
+    private String nodeName;
+
+    public MapperInfo(String nodeName) {
+        this.nodeName = nodeName;
+    }
+
+    public String getNodeName() {
+        return nodeName;
+    }
+
+    public void setNodeName(String nodeName) {
+        this.nodeName = nodeName;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeContext.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeContext.java
new file mode 100644
index 0000000..1f72ffc
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeContext.java
@@ -0,0 +1,28 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class NodeContext {
+
+    private String packageNamespace;
+    private String nodeClassName;
+
+    public NodeContext(String packageNamespace, String nodeClassName) {
+        this.packageNamespace = packageNamespace;
+        this.nodeClassName = nodeClassName;
+    }
+
+    public String getPackageNamespace() {
+        return packageNamespace;
+    }
+
+    public void setPackageNamespace(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+
+    public String getNodeClassName() {
+        return nodeClassName;
+    }
+
+    public void setNodeClassName(String nodeClassName) {
+        this.nodeClassName = nodeClassName;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeInfo.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeInfo.java
new file mode 100644
index 0000000..ab006ef
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/NodeInfo.java
@@ -0,0 +1,48 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class NodeInfo {
+
+    private String netName;
+    private String nodeName;
+    private String nodeIndex;
+    private String nodeClassName;
+
+    public NodeInfo(String netName, String nodeName, String nodeIndex, String nodeClassName) {
+        this.netName = netName;
+        this.nodeName = nodeName;
+        this.nodeIndex = nodeIndex;
+        this.nodeClassName = nodeClassName;
+    }
+
+    public String getNetName() {
+        return netName;
+    }
+
+    public void setNetName(String netName) {
+        this.netName = netName;
+    }
+
+    public String getNodeName() {
+        return nodeName;
+    }
+
+    public void setNodeName(String nodeName) {
+        this.nodeName = nodeName;
+    }
+
+    public String getNodeIndex() {
+        return nodeIndex;
+    }
+
+    public void setNodeIndex(String nodeIndex) {
+        this.nodeIndex = nodeIndex;
+    }
+
+    public String getNodeClassName() {
+        return nodeClassName;
+    }
+
+    public void setNodeClassName(String nodeClassName) {
+        this.nodeClassName = nodeClassName;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerContext.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerContext.java
new file mode 100644
index 0000000..c13e56e
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerContext.java
@@ -0,0 +1,28 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class ServerContext {
+
+    private String packageNamespace;
+    private String serverClassName;
+
+    public String getPackageNamespace() {
+        return packageNamespace;
+    }
+
+    public void setPackageNamespace(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+
+    public String getServerClassName() {
+        return serverClassName;
+    }
+
+    public void setServerClassName(String serverClassName) {
+        this.serverClassName = serverClassName;
+    }
+
+    public ServerContext(String packageNamespace, String serverClassName) {
+        this.packageNamespace = packageNamespace;
+        this.serverClassName = serverClassName;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerInfo.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerInfo.java
new file mode 100644
index 0000000..eb5f20f
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/ServerInfo.java
@@ -0,0 +1,40 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class ServerInfo {
+
+    private String serverNodeName;
+    private String serverSubnet;
+    private String serverClassName;
+
+    public ServerInfo(String serverNodeName, String serverSubnet, String serverClassName) {
+        this.serverNodeName = serverNodeName;
+        this.serverSubnet = serverSubnet;
+        this.serverClassName = serverClassName;
+    }
+
+    public String getServerNodeName() {
+        return serverNodeName;
+    }
+
+    public void setServerNodeName(String serverNodeName) {
+        this.serverNodeName = serverNodeName;
+    }
+
+    public String getServerSubnet() {
+        return serverSubnet;
+    }
+
+    public void setServerSubnet(String serverSubnet) {
+        this.serverSubnet = serverSubnet;
+    }
+
+    public String getServerClassName() {
+        return serverClassName;
+    }
+
+    public void setServerClassName(String serverClassName) {
+        this.serverClassName = serverClassName;
+    }
+
+
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberContext.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberContext.java
new file mode 100644
index 0000000..e48c5ca
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberContext.java
@@ -0,0 +1,28 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class SubscriberContext {
+
+    private String packageNamespace;
+    private String subscriberClassName;
+
+    public SubscriberContext(String packageNamespace, String subscriberClassName) {
+        this.packageNamespace = packageNamespace;
+        this.subscriberClassName = subscriberClassName;
+    }
+
+    public String getPackageNamespace() {
+        return packageNamespace;
+    }
+
+    public void setPackageNamespace(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+
+    public String getSubscriberClassName() {
+        return subscriberClassName;
+    }
+
+    public void setSubscriberClassName(String subscriberClassName) {
+        this.subscriberClassName = subscriberClassName;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberInfo.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberInfo.java
new file mode 100644
index 0000000..6a4aafe
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/SubscriberInfo.java
@@ -0,0 +1,38 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class SubscriberInfo {
+
+    private String subscriberNodeName;
+    private String subscriberSubnet;
+    private String subscriberClassName;
+
+    public SubscriberInfo(String subscriberNodeName, String subscriberSubnet, String subscriberClassName) {
+        this.subscriberNodeName = subscriberNodeName;
+        this.subscriberSubnet = subscriberSubnet;
+        this.subscriberClassName = subscriberClassName;
+    }
+
+    public String getSubscriberNodeName() {
+        return subscriberNodeName;
+    }
+
+    public void setSubscriberNodeName(String subscriberNodeName) {
+        this.subscriberNodeName = subscriberNodeName;
+    }
+
+    public String getSubscriberSubnet() {
+        return subscriberSubnet;
+    }
+
+    public void setSubscriberSubnet(String subscriberSubnet) {
+        this.subscriberSubnet = subscriberSubnet;
+    }
+
+    public String getSubscriberClassName() {
+        return subscriberClassName;
+    }
+
+    public void setSubscriberClassName(String subscriberClassName) {
+        this.subscriberClassName = subscriberClassName;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/data/TokenContext.java b/src/main/java/de/tudresden/inf/st/pnml/gen/data/TokenContext.java
new file mode 100644
index 0000000..4496f52
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/data/TokenContext.java
@@ -0,0 +1,18 @@
+package de.tudresden.inf.st.pnml.gen.data;
+
+public class TokenContext {
+
+    private String packageNamespace;
+
+    public TokenContext(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+
+    public String getPackageNamespace() {
+        return packageNamespace;
+    }
+
+    public void setPackageNamespace(String packageNamespace) {
+        this.packageNamespace = packageNamespace;
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/generators/AbstractGenUtil.java b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/AbstractGenUtil.java
new file mode 100644
index 0000000..fef8fad
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/AbstractGenUtil.java
@@ -0,0 +1,28 @@
+package de.tudresden.inf.st.pnml.gen.generators;
+
+import com.github.mustachejava.DefaultMustacheFactory;
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheFactory;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Map;
+
+public class AbstractGenUtil {
+
+    protected static final String TEMPLATE_PATH = "../pnml-relast-pkg-gen/src/main/resources/mustache/";
+
+    protected static String generate(Map<String, Object> context, String fileName) {
+        MustacheFactory mf = new DefaultMustacheFactory();
+        Mustache m = mf.compile(TEMPLATE_PATH + fileName);
+
+        StringWriter writer = new StringWriter();
+        try {
+            m.execute(writer, context).flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return writer.toString();
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/generators/GradleGenUtil.java b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/GradleGenUtil.java
index 42ece8c..06d17b6 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/gen/generators/GradleGenUtil.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/GradleGenUtil.java
@@ -6,33 +6,28 @@ import com.github.mustachejava.MustacheFactory;
 import de.tudresden.inf.st.pnml.gen.data.GradleBuildContext;
 import de.tudresden.inf.st.pnml.gen.data.SettingsGradleContext;
 
+import java.io.IOException;
 import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
 
-public class GradleGenUtil {
+public class GradleGenUtil extends AbstractGenUtil{
 
     public static String generateBuildGradle(String mainClass, String archiveBaseName, String version, String pnmlRelastersion){
 
         GradleBuildContext gradleBuildContext = new GradleBuildContext(mainClass, archiveBaseName, version, pnmlRelastersion);
+        Map<String, Object> context = new HashMap<>();
+        context.put("gradleBuildContext", gradleBuildContext);
 
-        MustacheFactory mf = new DefaultMustacheFactory();
-        Mustache m = mf.compile("/main/resources/mustache/build.mustache");
-
-        StringWriter writer = new StringWriter();
-        m.execute(writer, gradleBuildContext);
-
-        return writer.toString();
+        return generate(context, "build.mustache");
     }
 
     public static String generateGradleSettings(String rootProjectName){
 
         SettingsGradleContext settingsGradleContext = new SettingsGradleContext(rootProjectName);
+        Map<String, Object> context = new HashMap<>();
+        context.put("settingsGradleContext", settingsGradleContext);
 
-        MustacheFactory mf = new DefaultMustacheFactory();
-        Mustache m = mf.compile("/main/resources/mustache/settings.mustache");
-
-        StringWriter writer = new StringWriter();
-        m.execute(writer, settingsGradleContext);
-
-        return writer.toString();
+        return generate(context, "settings.mustache");
     }
 }
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 fd7dc63..21fe80e 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
@@ -1,4 +1,106 @@
 package de.tudresden.inf.st.pnml.gen.generators;
 
-public class JavaClassGenUtil {
+import de.tudresden.inf.st.pnml.base.constants.PnmlConstants;
+import de.tudresden.inf.st.pnml.gen.data.*;
+import de.tudresden.inf.st.pnml.jastadd.model.PetriNet;
+import de.tudresden.inf.st.pnml.jastadd.model.Transition;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class JavaClassGenUtil extends AbstractGenUtil{
+
+    public static String generateMain(List<PetriNet> petriNetList, List<String> petriNetFiles,
+                                      String rosHost, String rosMasterUri, String mqttHost, String packageNamespace){
+
+        Map<String, Object> context = new HashMap<>();
+
+        MainExecutionContext mainExecutionContext = new MainExecutionContext(rosHost, rosMasterUri, mqttHost, packageNamespace);
+        context.put("mainExecutionContext", mainExecutionContext);
+
+        List<NodeInfo> nodeInfos = new ArrayList<>();
+        List<ServerInfo> serverInfos = new ArrayList<>();
+        List<SubscriberInfo> subscriberInfos = new ArrayList<>();
+
+        for(int i = 0; i < petriNetList.size(); i++){
+
+            NodeInfo nodeInfo = new NodeInfo(petriNetFiles.get(i), "node" + i,
+                    String.valueOf(i), "Node" + i);
+            nodeInfos.add(nodeInfo);
+
+            int serverCount = 0;
+
+            for(Transition t : petriNetList.get(i).allTransitions()){
+
+                String transitionType = t.asInputSignalTransition().getStaticTransitionInformation().getType();
+                String subnet = t.asInputSignalTransition().getStaticTransitionInformation().getSubNet();
+
+                if(transitionType.equals(PnmlConstants.TRANSITION_TYPE_SERVICE_REQUEST_OUT)){
+                    serverInfos.add(new ServerInfo("node" + i, subnet,"Node" + i + "Server" + serverCount));
+                    serverCount++;
+                }
+                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));
+                }
+            }
+        }
+
+        context.put("nodeInfos", nodeInfos);
+        context.put("serverInfos", serverInfos);
+        context.put("subscriberInfos", subscriberInfos);
+
+        return generate(context, "JavaMain.mustache");
+    }
+
+    public static String generateSubscriberClass(String packageNamespace, String className){
+
+        Map<String, Object> context = new HashMap<>();
+        SubscriberContext subscriberContext = new SubscriberContext(packageNamespace, className);
+        context.put("subscriberContext", subscriberContext);
+        return generate(context, "JavaSubscriber.mustache");
+    }
+
+    public static String generateNodeClass(String packageNamespace, String className){
+
+        Map<String, Object> context = new HashMap<>();
+        NodeContext nodeContext = new NodeContext(packageNamespace, className);
+        context.put("nodeContext", nodeContext);
+        return generate(context, "JavaNode.mustache");
+    }
+
+    public static String generateServerClass(String packageNamespace, String className){
+
+        Map<String, Object> context = new HashMap<>();
+        ServerContext serverContext = new ServerContext(packageNamespace, className);
+        context.put("serverContext", serverContext);
+        return generate(context, "JavaServer.mustache");
+    }
+
+    public static String generateMapperClass(String packageNamespace, PetriNet petriNet){
+
+        Map<String, Object> context = new HashMap<>();
+        MapperContext mapperContext = new MapperContext(packageNamespace);
+        context.put("serverContext", mapperContext);
+
+        List<MapperInfo> mapperInfos = new ArrayList<>();
+
+        for(int i = 1; i < petriNet.allTransitions().size(); i++){
+            MapperInfo mapperInfo = new MapperInfo("Node" + i);
+            mapperInfos.add(mapperInfo);
+        }
+
+        context.put("mapperInfos", mapperInfos);
+        return generate(context, "JavaCallbackMapper.mustache");
+    }
+
+    public static String generateTokenClass(String packageNamespace){
+
+        Map<String, Object> context = new HashMap<>();
+        TokenContext tokenContext = new TokenContext(packageNamespace);
+        context.put("tokenContext", tokenContext);
+        return generate(context, "JavaToken.mustache");
+    }
 }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/gen/generators/TokenGenUtil.java b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/TokenGenUtil.java
index 6201d5f..6677d85 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/gen/generators/TokenGenUtil.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/gen/generators/TokenGenUtil.java
@@ -1,4 +1,4 @@
 package de.tudresden.inf.st.pnml.gen.generators;
 
-public class TokenGenUtil {
+public class TokenGenUtil extends AbstractGenUtil{
 }
diff --git a/src/main/resources/mustache/JavaCallbackMapper.mustache b/src/main/resources/mustache/JavaCallbackMapper.mustache
new file mode 100644
index 0000000..04ca4cd
--- /dev/null
+++ b/src/main/resources/mustache/JavaCallbackMapper.mustache
@@ -0,0 +1,27 @@
+{{#mapperContext}}
+package de.tudresden.inf.st.{{{packageNamespace}}}.callback;
+
+import de.tudresden.inf.st.pnml.engine.execution.DefaultTransitionCallback;
+import de.tudresden.inf.st.pnml.engine.execution.TransitionCallback;
+import de.tudresden.inf.st.pnml.jastadd.model.PetriNet;
+import de.tudresden.inf.st.pnml.jastadd.model.Transition;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CallbackMapper {
+{{#mapperInfos}}
+
+    public static final Map<String, List<AbstractNetCallback>> initCallbacksFor{{{nodeName}}}(PetriNet petriNet){
+
+        Map<String, List<AbstractNetCallback>> callbackMap = new HashMap<>();
+
+        // TODO: implementation by user
+
+        return callbackMap;
+    }
+{{/mapperInfos}}
+}
+{{/mapperContext}}
\ No newline at end of file
diff --git a/src/main/resources/mustache/JavaMain.mustache b/src/main/resources/mustache/JavaMain.mustache
new file mode 100644
index 0000000..5905e30
--- /dev/null
+++ b/src/main/resources/mustache/JavaMain.mustache
@@ -0,0 +1,111 @@
+{{#mainContext}}
+package de.tudresden.inf.st.{{{packageNamespace}}};
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import de.tudresden.inf.st.pnml.engine.execution.TransitionCallback;
+import de.tudresden.inf.st.pnml.engine.execution.TransitionCallbackService;
+import de.tudresden.inf.st.pnml.engine.ros.DiNeRosNode;
+import de.tudresden.inf.st.pnml.engine.transform.PetriNetInitializer;
+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;
+import de.tudresden.inf.st.pnml.jastadd.model.PnmlParser;
+import de.tudresden.inf.st.sample.balloon.Token;
+import de.tudresden.inf.st.sample.callback.AbstractNetCallback;
+import de.tudresden.inf.st.sample.callback.CallbackMapper;
+import de.tudresden.inf.st.sample.communication.Node2Subscriber1;
+import de.tudresden.inf.st.sample.nodes.Node1;
+import de.tudresden.inf.st.sample.nodes.Node2;
+import org.ros.node.DefaultNodeMainExecutor;
+import org.ros.node.NodeConfiguration;
+import org.ros.node.NodeMainExecutor;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class Main {
+
+    // actual ros / mqtt host url is inserted based on configuration
+    private static final String ROS_HOST = "{{{rosHost}}}";
+    private static final String ROS_MASTER_URI = "{{{rosMasterUri}}}";
+    private static final String MQTT_HOST = "{{{mqttHost}}}";
+
+    private static final NodeConfiguration nodeConfiguration = NodeConfiguration.newPublic(ROS_HOST);
+    private static final NodeMainExecutor nodeMainExecutor = DefaultNodeMainExecutor.newDefault();
+
+    public static void main(java.lang.String[] args) throws IOException, ParserConfigurationException, SAXException {
+
+        /*
+         * Petri Net base data initialization
+         */
+
+        // actual petri net paths are generated
+        List<String> petriNetPaths = new ArrayList<>();
+        {{#nodeInfos}}
+        petriNetPaths.add("src/main/resources/nets/{{{netName}}}.pnml");
+        {{/nodeInfos}}
+
+        List<PetriNet> petriNets = new ArrayList<>();
+        Map<String, BalloonMarking> markings = new HashMap<>();
+        Map<String, BalloonCallbackStorage> callbackStorages = new HashMap<>();
+
+        for(String petriNetPath : petriNetPaths){
+            petriNets.add(PnmlParser.parsePnml(petriNetPath).get(0));
+        }
+
+        TransitionCallbackService transitionCallbackService = TransitionCallbackService.getInstance();
+
+        for(PetriNet petriNet : petriNets){
+            markings.put(petriNet.getId(), petriNet.initializeBalloonMarking());
+            BalloonCallbackStorage storage = petriNet.initializeCallbackStorage();
+            transitionCallbackService.init(petriNet.getId(), storage);
+            callbackStorages.put(petriNet.getId(), storage);
+            PetriNetInitializer.initInputSignalConnections(petriNet, MQTT_HOST, "mqtt");
+            PetriNetInitializer.initOutputSignalConnections(petriNet, MQTT_HOST, "mqtt");
+        }
+
+        /*
+         * Callback and token integration
+         */
+
+         {{#nodeInfos}}
+         Map<String, List<AbstractNetCallback>> callbackMap{{{nodeName}}} = CallbackMapper.initCallbacksFor{{{nodeName}}}(petriNets.get({{{nodeIndex}}}));
+
+         for (Map.Entry<String, List<AbstractNetCallback>> entry : callbackMap{{{nodeName}}}.entrySet()) {
+             for(AbstractNetCallback anc : entry.getValue()){
+                transitionCallbackService.registerCallback(petriNets.get({{{nodeIndex}}}), entry.getKey(), anc);
+             }
+         }
+         {{/nodeInfos}}
+
+         /*
+          * Start of the Dineros NodescallbackMap1
+          */
+
+          nodeConfiguration.setMasterUri(URI.create(ROS_MASTER_URI));
+
+          {{#nodeInfos}}
+          DiNeRosNode {{{nodeName}}} = new {{{nodeClassName}}}("{{{nodeName}}}", petriNets.get({{{nodeIndex}}}), markings.get(petriNets.get({{{nodeIndex}}}).getId()),
+                                    callbackStorages.get(petriNets.get({{{nodeIndex}}}).getId()));
+          {{/nodeInfos}}
+
+          {{#serverInfos}}
+              {{{serverNodeName}}}.getDinerosServiceServers().put("{{{serverSubnet}}}", new {{{serverClassName}}}());
+          {{/serverInfos}}
+
+          {{#subscriberInfos}}
+              {{{subscriberNodeName}}}.getDinerosSubscribers().put("{{{subscriberSubnet}}}", new {{{subscriberClassName}}}());
+          {{/subscriberInfos}}
+
+          {{#nodeInfos}}
+              new Thread(() -> nodeMainExecutor.execute({{{nodeName}}}, nodeConfiguration)) { {
+                  start();
+              } };
+          {{/nodeInfos}}
+{{/mainContext}}
\ No newline at end of file
diff --git a/src/main/resources/mustache/JavaNode.mustache b/src/main/resources/mustache/JavaNode.mustache
new file mode 100644
index 0000000..a34c6b8
--- /dev/null
+++ b/src/main/resources/mustache/JavaNode.mustache
@@ -0,0 +1,26 @@
+{{#nodeContext}}
+package de.tudresden.inf.st.{{{packageNamespace}}}.nodes;
+
+import de.tudresden.inf.st.pnml.engine.ros.DiNeRosNode;
+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 class {{{nodeClassName}}} extends DiNeRosNode {
+
+    public {{{nodeClassName}}}(String nodeName, PetriNet petriNet) {
+        super(nodeName, petriNet);
+    }
+
+    public {{{nodeClassName}}}(String nodeName, PetriNet petriNet, BalloonMarking marking, BalloonCallbackStorage callbackStorage) {
+        super(nodeName, petriNet, marking, callbackStorage);
+    }
+
+    @Override
+    protected void nodeLoop() {
+
+        // TODO: Implementation by user
+
+    }
+}
+{{/nodeContext}}
\ No newline at end of file
diff --git a/src/main/resources/mustache/JavaServer.mustache b/src/main/resources/mustache/JavaServer.mustache
new file mode 100644
index 0000000..f75d6ce
--- /dev/null
+++ b/src/main/resources/mustache/JavaServer.mustache
@@ -0,0 +1,15 @@
+{{#serverContext}}
+package de.tudresden.inf.st.{{{packageNamespace}}}.communication;
+
+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 class {{{serverClassName}}} extends AbstractDinerosServer{
+
+    @Override
+    public boolean serve(BalloonMarking balloonMarking, BalloonCallbackStorage balloonCallbackStorage, PetriNet petriNet, String subnet) {
+        return false;
+    }
+}
+{{/serverContext}}
\ No newline at end of file
diff --git a/src/main/resources/mustache/JavaSubscriber.mustache b/src/main/resources/mustache/JavaSubscriber.mustache
new file mode 100644
index 0000000..5d7ab2e
--- /dev/null
+++ b/src/main/resources/mustache/JavaSubscriber.mustache
@@ -0,0 +1,18 @@
+{{#subscriberContext}}
+package de.tudresden.inf.st.{{{packageNamespace}}}.communication;
+
+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 class {{{subscriberClassName}}} extends AbstractDinerosSubscriber {
+
+    @Override
+    public boolean subscribe(BalloonMarking balloonMarking, BalloonCallbackStorage balloonCallbackStorage, PetriNet petriNet, String subnet) {
+
+        // TODO: Implementation by user
+
+        return true;
+    }
+}
+{{/subscriberContext}}
diff --git a/src/main/resources/mustache/JavaToken.mustache b/src/main/resources/mustache/JavaToken.mustache
new file mode 100644
index 0000000..e3837ae
--- /dev/null
+++ b/src/main/resources/mustache/JavaToken.mustache
@@ -0,0 +1,9 @@
+{{#tokenContext}}
+package de.tudresden.inf.st.{{{packageNamespace}}}.balloon;
+
+public class Token {
+
+    // TODO: implement Java Pojo for the token format
+
+}
+{{/tokenContext}}
\ No newline at end of file
-- 
GitLab