From 2e1a8a3a485514d428ef4fee433e4db076d66451 Mon Sep 17 00:00:00 2001
From: SebastianEbert <sebastian.ebert@tu-dresden.de>
Date: Thu, 22 Jun 2023 17:42:36 +0200
Subject: [PATCH] implemented service instance and topic channel flattening
 based on new transforms-pattern

---
 build.gradle                                  | 14 +++-
 .../flatter/rewrites/ServiceRewrites.jadd     | 58 -------------
 .../flatter/rewrites/SignalRewrites.jadd      |  4 -
 .../ServicePrototypeTransforms.jadd           | 53 ++++++++++++
 .../flatter/transforms/SignalTransforms.jadd  |  0
 .../TopicTransforms.jadd}                     | 26 +++---
 .../tudresden/inf/st/pnml/flatter/Main.java   | 72 +++++++++-------
 .../flatter/template/TemplateConstants.java   |  1 +
 .../transform/TransformationUtils.java        | 84 ++++++++++++++++---
 src/main/resources/elements/DinerosPlace.pnml |  4 +-
 .../resources/elements/DinerosTransition.pnml |  4 +-
 src/main/resources/templates/InputSignal.pnml |  4 +-
 .../templates/ServiceConnectionTemplate.pnml  |  4 +-
 .../templates/ServiceQueueTemplate.pnml       |  4 +-
 .../templates/TopicPublisherTemplate.pnml     |  6 +-
 .../TopicSubCallbackQueueTemplate.pnml        | 14 ++--
 .../templates/TopicSubDispatcherTemplate.pnml | 12 +--
 17 files changed, 223 insertions(+), 141 deletions(-)
 delete mode 100644 src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd
 delete mode 100644 src/main/jastadd/flatter/rewrites/SignalRewrites.jadd
 create mode 100644 src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd
 create mode 100644 src/main/jastadd/flatter/transforms/SignalTransforms.jadd
 rename src/main/jastadd/flatter/{rewrites/TopicRewrites.jadd => transforms/TopicTransforms.jadd} (82%)

diff --git a/build.gradle b/build.gradle
index 869d073..65181fa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,8 +17,15 @@ apply plugin: "idea"
 
 apply from: 'beaver.gradle'
 
-sourceCompatibility = 1.8
-targetCompatibility = 1.8
+//sourceCompatibility = 1.8
+//targetCompatibility = 1.8
+
+java {
+    toolchain {
+        languageVersion.set(JavaLanguageVersion.of(11))
+    }
+}
+
 
 repositories {
     jcenter()
@@ -77,6 +84,7 @@ dependencies {
 
     testImplementation('org.junit.jupiter:junit-jupiter:5.8.2')
 
+    implementation group: 'de.tudresden.inf.st', name: 'dumpAst', version: '3.0.1'
 }
 
 run {
@@ -202,7 +210,7 @@ jastadd {
     parser.genDir = "src/gen/java/de/tudresden/inf/st/pnml/jastadd/parser"
 
 //  default options are: '--rewrite=cnta', '--safeLazy', '--visitCheck=false', '--cacheCycle=false'
-    extraJastAddOptions = ['--List=JastAddList'] // '--incremental=param'
+    extraJastAddOptions = ['--List=JastAddList', '--rewrite=cnta', '--visitCheck=true', '--safeLazy'] // '--incremental=param'
 }
 
 // Workflow configuration for phases
diff --git a/src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd b/src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd
deleted file mode 100644
index 739554d..0000000
--- a/src/main/jastadd/flatter/rewrites/ServiceRewrites.jadd
+++ /dev/null
@@ -1,58 +0,0 @@
-aspect ServiceRewrites {
-
-    syn boolean PetriNet.hasServerPrototypePages() {
-
-        for(Page p : this.allPages()){
-            if(p.getType().equals(PnmlConstants.PAGE_TYPE_SERVER)){
-                return false;
-            }
-        }
-        return true;
-    }
-
-     rewrite Page {
-     when ( getType() != null && getType().equals(PnmlConstants.PAGE_TYPE_SERVER) && !getId().endsWith(PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX) )
-        to Page {
-
-
-              int serverCapacity = 0;
-              String serviceName = this.getServiceName();
-              DinerosTransition serviceTransition = null;
-
-              for(DinerosTransition dt : petriNet().allDinerosTransitions()){
-                if(dt.getStaticTransitionInformation().isServiceTransitionInformation()){
-                  serverCapacity = dt.getStaticTransitionInformation().asServiceTransitionInformation().getServerChannel().getCapacity();
-                }
-                if(dt.getStaticTransitionInformation().isServiceTransitionInformation()){
-                  if(dt.getStaticTransitionInformation().asServiceTransitionInformation().getServiceName().equals(serviceName)){
-                    serviceTransition = dt;
-                  }
-                }
-
-                if(serverCapacity != 0 && serviceTransition != null){
-                  break;
-                }
-              }
-
-              de.tudresden.inf.st.pnml.flatter.transform.ToolspecificsTransformer
-                    .updateTransitionToolspecifics(petriNet(), serverCapacity, this);
-
-              Page containerPage = new Page();
-              containerPage.setId(this.getId() + "-" + PnmlConstants.PAGE_SERVER_CONTAINER_SUFFIX);
-
-              for( int i = 0; i < serverCapacity; i++){
-                Page serverInstancePage = this.treeCopyNoTransform();
-                serverInstancePage.setId(serverInstancePage.getId() + "-" + i + "-" + PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX);
-
-                for(PnObject pnObject : serverInstancePage.getObjectList()){
-                  pnObject.setId(pnObject.getId() + "-" + i + "-" + PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX);
-                  pnObject.getName().setText(pnObject.getId());
-                }
-
-                containerPage.addObject(serverInstancePage);
-              }
-
-              return containerPage;
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/main/jastadd/flatter/rewrites/SignalRewrites.jadd b/src/main/jastadd/flatter/rewrites/SignalRewrites.jadd
deleted file mode 100644
index 497b748..0000000
--- a/src/main/jastadd/flatter/rewrites/SignalRewrites.jadd
+++ /dev/null
@@ -1,4 +0,0 @@
-aspect SignalRewrites {
-
-
-}
\ No newline at end of file
diff --git a/src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd b/src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd
new file mode 100644
index 0000000..2f3b562
--- /dev/null
+++ b/src/main/jastadd/flatter/transforms/ServicePrototypeTransforms.jadd
@@ -0,0 +1,53 @@
+import de.tudresden.inf.st.pnml.flatter.transform.*;
+
+aspect ServicePrototypeTransforms {
+
+    syn boolean Page.canTransformPrototypePage(){
+        return (( getType() !=null )
+            && (getType().equals(PnmlConstants.PAGE_TYPE_SERVER))
+            && (!getId().endsWith(PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX)));
+    }
+
+    syn Page Page.transformPrototypePage() {
+
+        int serverCapacity = 0;
+        String serviceName = this.getServiceName();
+        DinerosTransition serviceTransition = null;
+
+        for(DinerosTransition dt : petriNet().allDinerosTransitions()){
+            if(dt.getStaticTransitionInformation().isServiceTransitionInformation()){
+                serverCapacity = dt.getStaticTransitionInformation().asServiceTransitionInformation().getServerChannel().getCapacity();
+            }
+            if(dt.getStaticTransitionInformation().isServiceTransitionInformation()){
+                if(dt.getStaticTransitionInformation().asServiceTransitionInformation().getServiceName().equals(serviceName)){
+                    serviceTransition = dt;
+                }
+            }
+
+            if(serverCapacity != 0 && serviceTransition != null){
+                break;
+            }
+        }
+
+        ToolspecificsTransformer.updateTransitionToolspecifics(petriNet(), serverCapacity, this);
+
+        Page containerPage = new Page();
+        containerPage.setId(this.getId() + "-" + PnmlConstants.PAGE_SERVER_CONTAINER_SUFFIX);
+
+        for( int i = 0; i < serverCapacity; i++){
+            Page serverInstancePage = this.treeCopyNoTransform();
+            serverInstancePage.setId(serverInstancePage.getId() + "-" + i + "-" + PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX);
+
+            for(PnObject pnObject : serverInstancePage.getObjectList()){
+                pnObject.setId(pnObject.getId() + "-" + i + "-" + PnmlConstants.PAGE_SERVER_INSTANCE_SUFFIX);
+                pnObject.getName().setText(pnObject.getId());
+            }
+
+            containerPage.addObject(serverInstancePage);
+        }
+
+        return containerPage;
+
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/jastadd/flatter/transforms/SignalTransforms.jadd b/src/main/jastadd/flatter/transforms/SignalTransforms.jadd
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/jastadd/flatter/rewrites/TopicRewrites.jadd b/src/main/jastadd/flatter/transforms/TopicTransforms.jadd
similarity index 82%
rename from src/main/jastadd/flatter/rewrites/TopicRewrites.jadd
rename to src/main/jastadd/flatter/transforms/TopicTransforms.jadd
index 046f15e..493a394 100644
--- a/src/main/jastadd/flatter/rewrites/TopicRewrites.jadd
+++ b/src/main/jastadd/flatter/transforms/TopicTransforms.jadd
@@ -1,15 +1,20 @@
 import de.tudresden.inf.st.pnml.flatter.template.*;
 import de.tudresden.inf.st.pnml.flatter.transform.*;
 
-aspect TopicRewrites {
+aspect TopicTransforms {
 
-    rewrite DinerosTransition {
-    when ( !petriNet().hasServerPrototypePages() && getStaticTransitionInformation().isTopicTransitionInformation() )
-        to Page {
+    syn boolean DinerosTransition.canTransformTopicTransition() {
+        return this.getStaticTransitionInformation().isTopicTransitionInformation();
+    }
 
-            Page res = new Page();
+    syn Page DinerosTransition.transformTopicElement() {
+
+            System.out.println("Transforming topic transition: " + this.getId());
             TopicTransitionInformation tti = this.getStaticTransitionInformation().asTopicTransitionInformation();
 
+            Page res = new Page();
+            res.setId(TemplateConstants.CHANNEL_TOPIC_PAGE_PREFIX + "-" + tti.getTopic());
+
             // apply rule T1
             DinerosPlace pTopic = PrimitiveTemplates.getDinerosPlace();
             pTopic.setId(TemplateConstants.CHANNEL_TOPIC_PLACE + "-" + tti.getTopic());
@@ -38,12 +43,12 @@ aspect TopicRewrites {
             TransformationUtils.createAndIncludeArc(res, pTopic.getId() + "-to-" + tTopic.getId(), pTopic, tTopic);
 
             // apply rule T2
-            int i = 0;
+           int i = 0;
             for(PublisherPort pp : tti.getPublisherPorts()){
                 Map<String, Node> pubMap = new HashMap<>();
                 pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_REF + "-" + tti.getTopic() + "-" + i, petriNet().getPlaceById(pp.getPlaceId()));
                 pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + i, pTopic);
-                PetriNet pubNet = TopicTemplates.getTopicPublisherPetriNet("-" + tti.getTopic() + "-" + i, pp.getLimit());
+                PetriNet pubNet = TopicTemplates.getTopicPublisherPetriNet(tti.getTopic() + "-" + i, pp.getLimit());
                 TransformationUtils.includeTemplateInstance(res, petriNet(), pubNet, "channel", "channel", pubMap);
                 i++;
             }
@@ -63,12 +68,12 @@ aspect TopicRewrites {
 
             // apply rule T3
             int j = 0;
-            for(Map.Entry<String, List<SubscriberPort>> entry : nodePortMap.entrySet()){
+           for(Map.Entry<String, List<SubscriberPort>> entry : nodePortMap.entrySet()){
                 Map<String, Node> dispatchMap = new HashMap<>();
                 dispatchMap.put(TemplateConstants.TRANSITION_TOPIC_DISPATCHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + j, tTopic);
                 // TODO: make capacity configurable
                 PetriNet dispatchNet = TopicTemplates.getTopicDispatcherPetriNet(tti.getTopic() + "-" + j, 16);
-                TransformationUtils.includeTemplateInstance(res, petriNet(), dispatchNet, "channel", "channel", dispatchMap);
+                Map<String, PnObject> addedObjects = TransformationUtils.includeTemplateInstance(res, petriNet(), dispatchNet, "channel", "channel", dispatchMap);
 
                 // apply rule T4
                 int k = 0;
@@ -76,7 +81,7 @@ aspect TopicRewrites {
                     Map<String, Node> subMap = new HashMap<>();
                     subMap.put(TemplateConstants.PLACE_TOPIC_CALLBACK_REF + "-" + tti.getTopic() + "-" + j + "-" + k, petriNet().getPlaceById(sp.getPlaceId()));
                     subMap.put(TemplateConstants.TRANSITION_TOPIC_CALLBACK_INPUT_REF + "-" + tti.getTopic() + "-" + j + "-" + k,
-                    petriNet().getPlaceById(TemplateConstants.DISPATCHER_OUTPUT_TRANSITION + "-" + tti.getTopic() + "-" + j));
+                            addedObjects.get(TemplateConstants.DISPATCHER_OUTPUT_TRANSITION + "-" + tti.getTopic() + "-" + j).asNode());
                     PetriNet callbackNet = TopicTemplates.getTopicCallbackQueuePetriNet(tti.getTopic() + "-" + j + "-" + k, sp.getLimit());
                     TransformationUtils.includeTemplateInstance(res, petriNet(), callbackNet, "channel", "channel", subMap);
                     k++;
@@ -84,6 +89,5 @@ aspect TopicRewrites {
                 j++;
             }
             return res;
-        }
     }
 }
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
index 8af6b0f..3cdc3b8 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
@@ -1,9 +1,14 @@
 package de.tudresden.inf.st.pnml.flatter;
 
+import de.tudresden.inf.st.jastadd.dumpAst.ast.DumpBuilder;
+import de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper;
+import de.tudresden.inf.st.jastadd.dumpAst.ast.SkinParamBooleanSetting;
+import de.tudresden.inf.st.jastadd.dumpAst.ast.TransformationException;
 import de.tudresden.inf.st.pnml.flatter.config.ConfigReader;
 import de.tudresden.inf.st.pnml.flatter.tina.KtzioProxy;
 import de.tudresden.inf.st.pnml.flatter.tina.SiftProxy;
 import de.tudresden.inf.st.pnml.flatter.tina.TinaProxy;
+import de.tudresden.inf.st.pnml.flatter.transform.TransformationUtils;
 import de.tudresden.inf.st.pnml.jastadd.model.*;
 import de.tudresden.inf.st.pnml.jastadd.model.PnmlParser;
 import fr.lip6.move.pnml.framework.utils.exception.InvalidIDException;
@@ -11,28 +16,59 @@ import fr.lip6.move.pnml.framework.utils.exception.InvalidIDException;
 import de.tudresden.inf.st.pnml.flatter.tina.NdrioProxy;
 import de.tudresden.inf.st.pnml.jastadd.model.PetriNet;
 
+import java.awt.*;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Paths;
+import java.util.HashSet;
 import java.util.UUID;
 
 public class Main {
 
-    public static void main(String[] args) throws IOException, InvalidIDException, InterruptedException {
+    public static void main(String[] args) throws IOException, InvalidIDException, TransformationException {
 
-       /* String configPath = (args.length > 1) ? args[1] : null;
+        String configPath = (args.length > 1) ? args[1] : null;
         String pnmlPath = (args.length > 0) ? args[0] : null;
-
+/*
         if (pnmlPath == null || configPath == null) {
             System.out.println("No model found on given input path.");
             return;
         }*/
 
         // parse the global not flatted petri net
-        String pnmlPath = "/home/sebastian/git/dineros/dineros-v2/dineros/pnml-relast-base/src/main/resources/nets/TestNet2.pnml";
-        // configPath = "src/main/config/siftConfig.json";
+        pnmlPath = "/home/sebastian/git/dineros/dineros-v2/dineros/pnml-relast-base/src/main/resources/nets/TestNet1.pnml";
+        configPath = "src/main/config/siftConfig.json";
         PetriNet petriNet = PnmlParser.parsePnml(pnmlPath).get(0);
 
+        // [STAGE 1] Resolve service prototype pages
+        TransformationUtils.transformPrototypePagesRecursive(petriNet.getPage(0), null, petriNet);
+        petriNet.flushTreeCache();
+
+        // [STAGE 2] Transform topic transitions
+        for(DinerosTransition dt : petriNet.allDinerosTransitions()){
+            if(dt.canTransformTopicTransition()){
+                Page topicTransformedPage = dt.transformTopicElement();
+                for ( int i = 0; i < dt.ContainingPage().getNumObject(); i++ ){
+                    if(dt.ContainingPage().getObject(i).getId().equals(dt.getId())){
+                        dt.ContainingPage().setObject(topicTransformedPage, i);
+                    }
+                }
+                petriNet.flushTreeCache();
+            }
+        }
+
+        // [STAGE 3] Transform service transitions
+        // TODO
+
+        // [STAGE 4] Transform signals
+        // TODO
+
+     //   DumpBuilder builder = Dumper.read(petriNet).skinParam(SkinParamBooleanSetting.Shadowing, false);
+     //   builder.dumpAsPNG(Paths.get("net.png"));
+     //   builder.dumpAsSVG(Paths.get("net.svg"));
+
         // read config for analyzer from file
-    /*    ConfigReader cr = new ConfigReader(configPath);
+    /*  ConfigReader cr = new ConfigReader(configPath);
         String[] tinaConfig = cr.getTinaConfigParams();
         String[] siftConfig = cr.getSiftConfigParams();*/
 
@@ -51,20 +87,7 @@ public class Main {
         // remove references / pages
         System.out.println("[FLATTER] Breaking references and pages.");
         ReferenceFlatter.flatReferencesAndPages(petriNet);
-
-        // flat topic publishers / subscribers to instance based semantics
-        System.out.println("[FLATTER] Breaking down topic channels.");
-        PetriNet topicFlattedPetriNet = ChannelFlatter.flatTopicChannels(petriNet);
-
-        // flat service clients / servers to instance based semantics
-        System.out.println("[FLATTER] Breaking down service channels.");
-        PetriNet serviceFlattedPetriNet = ChannelFlatter.flatServiceChannels(topicFlattedPetriNet);
-
-        // flat input signals
-        System.out.println("[FLATTER] Breaking down signals.");
-        PetriNet signalFlattedPetriNet = SignalFlatter.flatSignals(serviceFlattedPetriNet);
-        printNet(signalFlattedPetriNet);*/
-
+*/
         // export flatted net to pnml
         printNet(petriNet, true, false);
         System.out.println("[FLATTER] Exporting to pnml.");
@@ -105,15 +128,6 @@ public class Main {
             ktzioProxy.convertBinaryToText(siftTargetPath, ktzioPath);
         }*/
 
-        // insert into struct
-        // TODO in v2
-
-        // insert into pathto
-        // TODO in v2
-
-        // combine results and generate report in html/md/xml/json? format
-        // TODO for v2
-
         System.out.println("Finished.");
 
     }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
index bd2eeaa..b7f30d5 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
@@ -37,6 +37,7 @@ public final class TemplateConstants {
     // channel elements
     public static final String CHANNEL_TOPIC_PLACE = "ChannelConnectorPlace";
     public static final String CHANNEL_TOPIC_TRANSITION = "ChannelConnectorTransition";
+    public static final String CHANNEL_TOPIC_PAGE_PREFIX = "ChannelTopicPage";
 
     // signal elements
     public static final String INPUT_SIGNAL_TEMPLATE_PAGE = "InputSignalTemplatePage";
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
index fba99bc..cbf962e 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
@@ -2,7 +2,10 @@ package de.tudresden.inf.st.pnml.flatter.transform;
 
 import de.tudresden.inf.st.pnml.jastadd.model.*;
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 public class TransformationUtils {
 
@@ -37,14 +40,16 @@ public class TransformationUtils {
         return a;
     }
 
-    public static void includeTemplateInstance(Page page, PetriNet petriNet, PetriNet templateInstance, String subnet, String node, Map<String, Node> refs) {
+    public static Map<String, PnObject> includeTemplateInstance(Page page, PetriNet petriNet, PetriNet templateInstance, String subnet, String node, Map<String, Node> refs) {
+
+        Map<String, PnObject> addedObjects = new HashMap<>();
 
         for(RefTransition rt : templateInstance.allRefTransitions()){
             if(refs.containsKey(rt.getId())){
                 rt.setRef(refs.get(rt.getId()).asTransitionNode());
             }
             page.addObject(rt);
-
+            addedObjects.put(rt.getId(), rt);
         }
 
         for(RefPlace rp : templateInstance.allRefPlaces()){
@@ -52,6 +57,7 @@ public class TransformationUtils {
                 rp.setRef(refs.get(rp.getId()).asPlaceNode());
             }
             page.addObject(rp);
+            addedObjects.put(rp.getId(), rp);
         }
 
         // include places, transitions
@@ -62,7 +68,9 @@ public class TransformationUtils {
             newTi.setSubNet(subnet);
             t.asDinerosTransition().setMutableTransitionInformation(newTi);
 
+            //System.out.println("Adding T: " + t.getId());
             page.addObject(t);
+            addedObjects.put(t.getId(), t);
         }
 
         for (Place p : templateInstance.allPlaces()) {
@@ -72,17 +80,20 @@ public class TransformationUtils {
             newPi.setSubNet(subnet);
             p.asDinerosPlace().setMutablePlaceInformation(newPi);
 
+            //System.out.println("Adding P: " + p.getId());
             page.addObject(p);
+            addedObjects.put(p.getId(), p);
         }
 
         petriNet.flushTreeCache();
+        petriNet.flushCollectionCache();
 
         // connect elements by arcs
         for (Arc a : templateInstance.allArcs()) {
             Arc newArc = new Arc();
             newArc.setId("arc-" + a.getSource().getId() + "-" + a.getTarget().getId());
-            newArc.setTarget((Node) getPnObjectByID(petriNet, a.getTarget().getId()));
-            newArc.setSource((Node) getPnObjectByID(petriNet, a.getSource().getId()));
+            newArc.setTarget((Node) getPnObjectByID(templateInstance, a.getTarget().getId()));
+            newArc.setSource((Node) getPnObjectByID(templateInstance, a.getSource().getId()));
 
             if (a.getNumToolspecific() > 0) {
                 ToolInfo ti = new ToolInfo();
@@ -93,20 +104,73 @@ public class TransformationUtils {
             }
 
             page.addObject(newArc);
+            addedObjects.put(newArc.getId(), newArc);
         }
 
-        petriNet.flushTreeCache();
+        petriNet.flushAttrAndCollectionCache();
+        return addedObjects;
     }
 
-    public static Place getPlaceByID(PetriNet petriNet, String Id) {
+    /**
+     * @param page starting point
+     * @param pages the filled set
+     * @return
+     */
+    public static void getPagesRecursive(Page page, Set<Page> pages){
 
-        for (Place p : petriNet.allPlaces()) {
-            if (p.getId().equals(Id)) {
-                return p;
+        pages.add(page);
+        Set<Page> subPages = new HashSet<>();
+
+        for(PnObject po : page.getObjectsNoTransform()){
+            if(po.isPageNode()){
+                subPages.add(po.asPage());
             }
         }
 
-        return null;
+        if(subPages.size() == 0){
+            return;
+        }
+
+        for(Page iterPage : subPages){
+            getPagesRecursive(iterPage, pages);
+        }
+    }
+
+    public static void transformPrototypePagesRecursive(Page page, Page parentPage, PetriNet petriNet){
+
+        if(page.canTransformPrototypePage()){
+            System.out.println("Transforming page: " + page.getId());
+            Page transformedPage = page.transformPrototypePage();
+
+            if(parentPage == null){
+                for(int i = 0; i < petriNet.getNumPage(); i++){
+                    if(petriNet.getPage(i).getId().equals(page.getId())){
+                        petriNet.setPage(transformedPage, i);
+                    }
+                }
+            } else {
+                for(int i = 0; i < parentPage.getNumObject(); i++){
+                    if(parentPage.getObject(i).getId().equals(page.getId())){
+                        parentPage.setObject(transformedPage, i);
+                    }
+                }
+            }
+        }
+
+        Set<Page> subPages = new HashSet<>();
+        for(PnObject po : page.getObjectsNoTransform()){
+            if(po.isPageNode()){
+                subPages.add(po.asPage());
+            }
+        }
+
+        if(subPages.size() == 0){
+            return;
+        }
+
+        for(Page iterPage : subPages){
+            transformPrototypePagesRecursive(iterPage, page, petriNet);
+        }
     }
 
     public static Transition getTransitionByID(PetriNet petriNet, String Id) {
diff --git a/src/main/resources/elements/DinerosPlace.pnml b/src/main/resources/elements/DinerosPlace.pnml
index 31985f2..a01c8dd 100644
--- a/src/main/resources/elements/DinerosPlace.pnml
+++ b/src/main/resources/elements/DinerosPlace.pnml
@@ -1,7 +1,7 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>OutputSignalPlaceNet</text>
+            <text>DinerosTemplate</text>
         </name>
         <page id="DinerosPlacePage">
             <place id="DinerosPlace">
diff --git a/src/main/resources/elements/DinerosTransition.pnml b/src/main/resources/elements/DinerosTransition.pnml
index 02e0d36..b773295 100644
--- a/src/main/resources/elements/DinerosTransition.pnml
+++ b/src/main/resources/elements/DinerosTransition.pnml
@@ -1,7 +1,7 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>InputSignalTransitionNet</text>
+            <text>DinerosTemplate</text>
         </name>
         <page id="DinerosTransitionPage">
             <transition id="DinerosTransition">
diff --git a/src/main/resources/templates/InputSignal.pnml b/src/main/resources/templates/InputSignal.pnml
index ca4f3a2..81eec34 100644
--- a/src/main/resources/templates/InputSignal.pnml
+++ b/src/main/resources/templates/InputSignal.pnml
@@ -1,7 +1,7 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>InputSignalTemplate</text>
+            <text>DinerosTemplate</text>
         </name>
         <page id="InputSignalTemplatePage">
             <place id="InputSignalActivePlace">
diff --git a/src/main/resources/templates/ServiceConnectionTemplate.pnml b/src/main/resources/templates/ServiceConnectionTemplate.pnml
index e3e4f23..a798dcb 100644
--- a/src/main/resources/templates/ServiceConnectionTemplate.pnml
+++ b/src/main/resources/templates/ServiceConnectionTemplate.pnml
@@ -1,7 +1,7 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>ServiceConnectionTemplate</text>
+            <text>DinerosTemplate</text>
         </name>
         <page id="ServiceTemplatePage">
             <place id="ServiceTogglePlace">
diff --git a/src/main/resources/templates/ServiceQueueTemplate.pnml b/src/main/resources/templates/ServiceQueueTemplate.pnml
index a0ad3fc..d81b46e 100644
--- a/src/main/resources/templates/ServiceQueueTemplate.pnml
+++ b/src/main/resources/templates/ServiceQueueTemplate.pnml
@@ -1,7 +1,7 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>ServiceQueueConnectionTemplate</text>
+            <text>DinerosTemplate</text>
         </name>
         <page id="ServiceQueueTemplatePage">
             <place id="ServiceQueueCapacityPlace">
diff --git a/src/main/resources/templates/TopicPublisherTemplate.pnml b/src/main/resources/templates/TopicPublisherTemplate.pnml
index 53f7e10..176cd01 100644
--- a/src/main/resources/templates/TopicPublisherTemplate.pnml
+++ b/src/main/resources/templates/TopicPublisherTemplate.pnml
@@ -1,8 +1,9 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>TopicPublisherTemplate</text>
+            <text>DinerosTemplate</text>
         </name>
+        <page id="DinerosTemplatePage">
 
         <!-- the reference target is just used here, because pnml does not allow dangling refs -->
         <referencePlace id="PublisherPlaceRef" ref="PublisherCapacityPlace">
@@ -45,7 +46,6 @@
         <arc id="arc-8" source="PublisherOutputTransition" target="PublisherChannelPlaceRef">
         </arc>
 
-        <page id="PublisherTemplatePage">
             <place id="PublisherCapacityPlace">
                 <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
                     <location>none</location>
diff --git a/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml b/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml
index f8775f8..0b43d61 100644
--- a/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml
+++ b/src/main/resources/templates/TopicSubCallbackQueueTemplate.pnml
@@ -1,11 +1,11 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>TopicSubCallbackTemplate</text>
+            <text>DinerosTemplate</text>
         </name>
-        <page id="TopicSubCallbackTemplatePage">
+        <page id="DinerosTemplatePage">
 
-            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+             <!-- the reference target is just used here, because pnml does not allow dangling refs -->
             <referenceTransition id="CallbackInputRefTransition" ref="CallbackInputTransition">
                 <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
                     <location>channel</location>
@@ -176,6 +176,6 @@
             </arc>
             <arc id="arc-7" source="CallbackInputPlace" target="CallbackOverflowTransition">
             </arc>
-        </page>
-    </net>
-</pnml>
+         </page>
+        </net>
+    </pnml>
diff --git a/src/main/resources/templates/TopicSubDispatcherTemplate.pnml b/src/main/resources/templates/TopicSubDispatcherTemplate.pnml
index 431fece..d5025a8 100644
--- a/src/main/resources/templates/TopicSubDispatcherTemplate.pnml
+++ b/src/main/resources/templates/TopicSubDispatcherTemplate.pnml
@@ -1,10 +1,10 @@
 <pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
-    <net id="TopicPublisherTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
         <name>
-            <text>TopicSubDispatcherTemplate</text>
+            <text>DinerosTemplate</text>
         </name>
 
-        <page id="TopicSubDispatcherTemplatePage">
+        <page id="DinerosTemplatePage">
 
             <!-- the reference target is just used here, because pnml does not allow dangling refs -->
             <referenceTransition id="DispatcherChannelTransitionRef" ref="DispatcherInputTransition">
@@ -156,6 +156,6 @@
             </arc>
             <arc id="arc-8" source="DispatcherChannelTransitionRef" target="DispatcherInputPlace">
             </arc>
-        </page>
-    </net>
-</pnml>
+          </page>
+      </net>
+  </pnml>
-- 
GitLab