From 21e9692413709f1bd82fb4bc8b48c6f923e0acf3 Mon Sep 17 00:00:00 2001
From: SebastianEbert <sebastian.ebert@tu-dresden.de>
Date: Tue, 29 Nov 2022 15:29:38 +0100
Subject: [PATCH] fixed flattening of inhibitor arc, updated gitignore

---
 .gitignore                                    |   1 +
 .../tudresden/inf/st/pnml/flatter/Main.java   | 102 ++++-----
 .../pnml/flatter/template/PnmlTemplate.java   |  12 ++
 .../flatter/template/ServiceTemplates.java    |  10 +-
 .../flatter/template/SignalTemplates.java     |   5 +-
 .../pnml/flatter/template/TopicTemplates.java |  17 +-
 .../inf/st/pnml/flatter/tina/NdrioProxy.java  |  62 +++++-
 .../flatter/transform/ChannelFlatter.java     | 199 +++++++++++++-----
 .../resources/elements/OutputSignalPlace.pnml |   2 +-
 9 files changed, 276 insertions(+), 134 deletions(-)

diff --git a/.gitignore b/.gitignore
index ccfb92b..5bba8cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ src/gen-res
 build/
 out/
 logs/
+temp/
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 68c2c41..d921f79 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
@@ -22,18 +22,19 @@ public class Main {
 
     public static void main(String[] args) throws IOException, InvalidIDException {
 
-        String pnmlPath = (args.length > 0) ? args[0] : null;
         String configPath = (args.length > 1) ? args[1] : null;
-
+        String pnmlPath = (args.length > 0) ? args[0] : null;
 
         if (pnmlPath == null || configPath == null) {
-            logger.error("No model found on given input path.");
+            System.out.println("No model found on given input path.");
             return;
         }
 
         // parse the global not flatted petri net
-        // pnmlPath = "/home/sebastian/git/dineros/pnml-relast-tools/pnml-relast-nets/src/main/resources/useCaseNets/RoboticUseCase-TopLayer.pnml";
-        //String pnmlPath = "../pnml-relast-nets/src/main/resources/serviceTestNets/structureTestNets/service-structure-correct.pnml";
+        // String pnmlPath = "../pnml-relast-nets/src/main/resources/topicTestNets/structureTestNets/topic-structure-correct.pnml";
+        // String pnmlPath = "../pnml-relast-nets/src/main/resources/useCaseNets/RoboticUseCase-TopLayer.pnml";
+        // String pnmlPath = "../pnml-relast-nets/src/main/resources/useCaseNets/RoboticUseCase-AllLayers.pnml";
+        // String pnmlPath = "../pnml-relast-nets/src/main/resources/serviceTestNets/structureTestNets/service-structure-correct.pnml";
         configPath = "src/main/config/config.json";
         PetriNet petriNet = PnmlParser.parsePnml(pnmlPath).get(0);
 
@@ -42,10 +43,10 @@ public class Main {
         String[] tinaConfig = cr.getTinaConfigParams();
 
         // make sure that we have a valid marking
-        logger.error("[FLATTER] Checking marking.");
+        System.out.println("[FLATTER] Checking marking.");
         for(Place p : petriNet.allPlaces()){
             if(p.getInitialMarking() == null){
-                logger.error("[FLATTER] Found NULL-marking. Falling back to 0 ...");
+                System.out.println("[FLATTER] Found NULL-marking. Falling back to 0 ...");
                 PTMarking marking = new PTMarking();
                 marking.setText(0);
                 p.setInitialMarking(marking);
@@ -53,41 +54,48 @@ public class Main {
         }
 
         // remove references / pages
-        logger.error("[FLATTER] Breaking references and pages.");
+        System.out.println("[FLATTER] Breaking references and pages.");
         ReferenceFlatter.flatReferencesAndPages(petriNet);
-        //   printNet(petriNet);
+        // printNet(petriNet);
 
         // flat topic publishers / subscribers to instance based semantics
-        logger.error("[FLATTER] Breaking down topic channels.");
+        System.out.println("[FLATTER] Breaking down topic channels.");
         PetriNet topicFlattedPetriNet = ChannelFlatter.flatTopicChannels(petriNet);
+        printNet(petriNet);
 
         // flat service clients / servers to instance based semantics
-        logger.error("[FLATTER] Breaking down service channels.");
+        System.out.println("[FLATTER] Breaking down service channels.");
         PetriNet serviceFlattedPetriNet = ChannelFlatter.flatServiceChannels(topicFlattedPetriNet);
         // printNet(serviceFlattedPetriNet);
 
         // flat input signals
-        logger.error("[FLATTER] Breaking down signals.");
+        System.out.println("[FLATTER] Breaking down signals.");
         PetriNet signalFlattedPetriNet = ChannelFlatter.flatSignals(serviceFlattedPetriNet);
-        printNet(signalFlattedPetriNet);
+        // printNet(signalFlattedPetriNet);
 
         // export flatted net to pnml
-        logger.error("[FLATTER] Exporting to pnml.");
+        System.out.println("[FLATTER] Exporting to pnml.");
         String exportId = UUID.randomUUID().toString();
         String pnmlExportPath = PnmlExporter.serializeToPnmlFile(petriNet, "flatted-" + exportId);
 
         //  convert and add inhibitor arcs
-        logger.error("[FLATTER] Converting to net format.");
+        System.out.println("[FLATTER] Converting to net format.");
         NdrioProxy ndrioProxy = new NdrioProxy();
         String homeDirectory = System.getProperty("user.dir");
-        String ndrioTargetPath = homeDirectory + "/temp/net/" + UUID.randomUUID() + "flatted-" + exportId + ".net";
+        String fid = UUID.randomUUID().toString();
+        String ndrioTargetPath = homeDirectory + "/temp/net/" + fid + "flatted-" + exportId + ".net";
+
+        // resolve inhibitor arcs
+        System.out.println("[FLATTER] Including inhibitor arcs into net format.");
+        String inhibitorTargetPath = homeDirectory + "/temp/net/" + fid + "flatted-inh-" + exportId + ".net";
         ndrioProxy.pnml2net(pnmlExportPath, ndrioTargetPath);
+        ndrioProxy.includeInhibitorArcs(petriNet, ndrioTargetPath, inhibitorTargetPath);
 
         // insert into tina
-        logger.error("[FLATTER] Inserting into tina.");
+        System.out.println("[FLATTER] Inserting into tina.");
         TinaProxy tinaProxy = new TinaProxy();
         String tinaTargetPath = homeDirectory + "/temp/tina/" + "tina-result-" + exportId + ".txt";
-        tinaProxy.analyzePetriNet(ndrioTargetPath, tinaTargetPath, tinaConfig);
+        tinaProxy.analyzePetriNet(inhibitorTargetPath, tinaTargetPath, tinaConfig);
 
         // insert into pathto
         // TODO v2
@@ -105,106 +113,106 @@ public class Main {
 
     public static void printNet(PetriNet petriNet) {
 
-        logger.error("--------------- STRUCTURE ---------------");
-        logger.error("----------------- PLACES ----------------");
+        System.out.println("--------------- STRUCTURE ---------------");
+        System.out.println("----------------- PLACES ----------------");
 
         for (Place p : petriNet.allPlaces()) {
-            //logger.error("id: " + p.getId());
-            logger.error("Place " + p.asOutputSignalPlace().getId() + " -- " + p.asOutputSignalPlace().getStaticPlaceInformation().getSubNet());
+            //System.out.println("id: " + p.getId());
+            System.out.println("Place " + p.asOutputSignalPlace().getId() + " -- " + p.asOutputSignalPlace().getStaticPlaceInformation().getSubNet());
             if (p.getInitialMarking() != null) {
-                logger.error("--- Marking: " + p.getInitialMarking().getText());
+                System.out.println("--- Marking: " + p.getInitialMarking().getText());
             }else {
-                logger.error("--- Marking: NULL");
+                System.out.println("--- Marking: NULL");
             }
         }
 
-        logger.error("-------------- TRANSITIONS --------------");
+        System.out.println("-------------- TRANSITIONS --------------");
 
         for (Transition t : petriNet.allTransitions()) {
-            logger.error("Transition " + t.getId());
+            System.out.println("Transition " + t.getId());
         }
 
-        logger.error("-------------- TRANSITION DETAILS --------------");
+        System.out.println("-------------- TRANSITION DETAILS --------------");
 
         for (Transition t : petriNet.allTransitions()) {
 
             if (t.asInputSignalTransition().getStaticTransitionInformation().isServiceTransitionInformation()) {
-                logger.error("--- Transition: " + t.getId() + " subnet: " + t.asInputSignalTransition().getStaticTransitionInformation().getSubNet()
+                System.out.println("--- Transition: " + t.getId() + " subnet: " + t.asInputSignalTransition().getStaticTransitionInformation().getSubNet()
                         + " service: " + t.asInputSignalTransition().getStaticTransitionInformation().asServiceTransitionInformation().getServiceName() + " ---------");
             } else if(t.asInputSignalTransition().getStaticTransitionInformation().isTopicTransitionInformation()){
-                logger.error("--- Transition: " + t.getId() + " subnet: " + t.asInputSignalTransition().getStaticTransitionInformation().getSubNet()
+                System.out.println("--- Transition: " + t.getId() + " subnet: " + t.asInputSignalTransition().getStaticTransitionInformation().getSubNet()
                         + " topic: " + t.asInputSignalTransition().getStaticTransitionInformation().asTopicTransitionInformation().getTopic() + " ---------");
             }else{
-                logger.error("--- Transition: " + t.getId() + " subnet: " + t.asInputSignalTransition().getStaticTransitionInformation().getSubNet());
+                System.out.println("--- Transition: " + t.getId() + " subnet: " + t.asInputSignalTransition().getStaticTransitionInformation().getSubNet() + " --- name: " + t.getName().getText());
             }
 
        //     for(Arc a : t.getInArcs()){
           //      System.out.println("incomming arc: " + a.getId());
        //     }
       //      if(t.asInputSignalTransition().getInputSignalClause() != null && t.asInputSignalTransition().getInputSignalClause().getNumChild() > 0){
-      //          logger.error("------ Clause: " + t.asInputSignalTransition().getInputSignalClause().printExp());
+      //          System.out.println("------ Clause: " + t.asInputSignalTransition().getInputSignalClause().printExp());
       //      }
 
             for (Place p : t.asInputSignalTransition().incomingPlaces()) {
 
-                logger.error("------ Inputplace:  " + p.getId() + " subnet: " + p.asOutputSignalPlace().getStaticPlaceInformation().getSubNet() + " ---------");
+                System.out.println("------ Inputplace:  " + p.getId() + " subnet: " + p.asOutputSignalPlace().getStaticPlaceInformation().getSubNet() + " ---------");
             }
 
             for (Place p : t.asInputSignalTransition().outgoingPlaces()) {
 
-                logger.error("------ Outputplace: " + p.getId() + " subnet: " + p.asOutputSignalPlace().getStaticPlaceInformation().getSubNet() + " ---------");
+                System.out.println("------ Outputplace: " + p.getId() + " subnet: " + p.asOutputSignalPlace().getStaticPlaceInformation().getSubNet() + " ---------");
             }
         }
 
-        logger.error("----------------- REF PLACES -----------------");
+        System.out.println("----------------- REF PLACES -----------------");
 
         for (RefPlace rp : petriNet.allRefPlaces()){
-            logger.error("--- RefPlace: " + rp.getId());
+            System.out.println("--- RefPlace: " + rp.getId());
         }
 
-        logger.error("----------------- REF TRANSITIONS -----------------");
+        System.out.println("----------------- REF TRANSITIONS -----------------");
 
         for (RefTransition rt : petriNet.allRefTransitions()){
-            logger.error("--- RefTransition: " + rt.getId());
+            System.out.println("--- RefTransition: " + rt.getId());
         }
 
-        logger.error("----------------- ARCS -----------------");
+        System.out.println("----------------- ARCS -----------------");
 
         for (Arc a : petriNet.allArcs()) {
-            logger.error("Arc: " + a.getId());
-            logger.error("Arc: " + a.getId() + " -- source: " + a.getSource().getId() + " -- target: " + a.getTarget().getId());
+            System.out.println("Arc: " + a.getId());
+            System.out.println("Arc: " + a.getId() + " -- source: " + a.getSource().getId() + " -- target: " + a.getTarget().getId());
 
             if(a.getNumToolspecific() > 0){
-      //          logger.error("--- toolspecifics: " + a.getToolspecific(0).getFormattedXMLBuffer());
+      //          System.out.println("--- toolspecifics: " + a.getToolspecific(0).getFormattedXMLBuffer());
             }
         }
 
-        logger.error("--------------- T SIGNALS (STATIC)---------------");
+        System.out.println("--------------- T SIGNALS (STATIC)---------------");
 
         for (Transition t : petriNet.allTransitions()) {
             InputSignalTransition ist = t.asInputSignalTransition();
 
             if (ist != null && ist.getStaticInputSignalBindingList() != null) {
-                ist.getStaticInputSignalBindingList().forEach(inputSignalBinding -> logger.error(" (" + t.getName().getText() + ") Signal: " + inputSignalBinding.getInputSignalID()));
+                ist.getStaticInputSignalBindingList().forEach(inputSignalBinding -> System.out.println(" (" + t.getName().getText() + ") Signal: " + inputSignalBinding.getInputSignalID()));
             }
         }
 
-        logger.error("--------------- T SIGNALS (MUTUAL)---------------");
+        System.out.println("--------------- T SIGNALS (MUTUAL)---------------");
 
         for (Transition t : petriNet.allTransitions()) {
             InputSignalTransition ist = t.asInputSignalTransition();
 
             if (ist != null && ist.getMutualInputSignalBindingList() != null) {
-                ist.getMutualInputSignalBindingList().forEach(inputSignalBinding -> logger.error(" (" + t.getName().getText() + ") Signal: " + inputSignalBinding.getInputSignalID()));
+                ist.getMutualInputSignalBindingList().forEach(inputSignalBinding -> System.out.println(" (" + t.getName().getText() + ") Signal: " + inputSignalBinding.getInputSignalID()));
             }
         }
 
-   //     logger.error("--------------- TOOL SPECIFIC ---------------");
+   //     System.out.println("--------------- TOOL SPECIFIC ---------------");
 
         for (Transition t : petriNet.allTransitions()) {
             InputSignalTransition ist = t.asInputSignalTransition();
             if(ist != null && ist.getNumToolspecific() > 0) {
-       //         logger.error("ToolSpecific: (" + ist.getName().getText() + ") " + ist.getToolspecific(0).getFormattedXMLBuffer().toString());
+       //         System.out.println("ToolSpecific: (" + ist.getName().getText() + ") " + ist.getToolspecific(0).getFormattedXMLBuffer().toString());
             }
         }
     }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/PnmlTemplate.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/PnmlTemplate.java
index 136a569..7eab635 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/PnmlTemplate.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/PnmlTemplate.java
@@ -1,6 +1,18 @@
 package de.tudresden.inf.st.pnml.flatter.template;
 
+import de.tudresden.inf.st.pnml.jastadd.model.Name;
+import de.tudresden.inf.st.pnml.jastadd.model.PnObject;
+
 public abstract class PnmlTemplate {
 
     protected static String homeDirectory = System.getProperty("user.dir");
+
+    protected static void updatePnObjectIdAndName(PnObject po, String idSuffix){
+
+        String oldId = po.getId();
+        po.setId(oldId + "-" + idSuffix);
+        Name name = new Name();
+        name.setText(oldId + "-" + idSuffix);
+        po.setName(name);
+    }
 }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/ServiceTemplates.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/ServiceTemplates.java
index 565de71..6a77a7c 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/ServiceTemplates.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/ServiceTemplates.java
@@ -13,10 +13,7 @@ public class ServiceTemplates extends PnmlTemplate{
 
         for(PnObject po : templateNet.allObjects()){
             if(!po.getId().equals(TemplateConstants.SERVICE_TEMPLATE_PAGE)){
-                po.setId(po.getId() + "-" + idSuffix);
-                Name name = new Name();
-                name.setText(po.getId() + "-" + idSuffix);
-                po.setName(name);
+                updatePnObjectIdAndName(po, idSuffix);
             }
         }
 
@@ -29,10 +26,7 @@ public class ServiceTemplates extends PnmlTemplate{
 
         for(PnObject po : templateNet.allObjects()){
             if(!po.getId().equals(TemplateConstants.SERVICE_QUEUE_TEMPLATE_PAGE)){
-                po.setId(po.getId() + "-" + idSuffix);
-                Name name = new Name();
-                name.setText(po.getId() + "-" + idSuffix);
-                po.setName(name);
+                updatePnObjectIdAndName(po, idSuffix);
             }
         }
 
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/SignalTemplates.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/SignalTemplates.java
index 4a4ad3e..baf688b 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/SignalTemplates.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/SignalTemplates.java
@@ -13,10 +13,7 @@ public class SignalTemplates extends PnmlTemplate{
 
         for(PnObject po : templateNet.allObjects()){
             if(!po.getId().equals(TemplateConstants.INPUT_SIGNAL_TEMPLATE_PAGE)){
-                po.setId(po.getId() + "-" + idSuffix);
-                Name name = new Name();
-                name.setText(po.getId() + "-" + idSuffix);
-                po.setName(name);
+                updatePnObjectIdAndName(po, idSuffix);
             }
         }
 
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java
index 49e4b36..38a1f06 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java
@@ -16,10 +16,7 @@ public class TopicTemplates extends PnmlTemplate {
 
         for(PnObject po : templateNet.allObjects()){
             if(!po.getId().equals(TemplateConstants.PUBLISHER_TEMPLATE_PAGE)){
-                po.setId(po.getId() + "-" + idSuffix);
-                Name name = new Name();
-                name.setText(po.getId() + "-" + idSuffix);
-                po.setName(name);
+                updatePnObjectIdAndName(po, idSuffix);
             }
         }
 
@@ -28,6 +25,8 @@ public class TopicTemplates extends PnmlTemplate {
 
     public static PetriNet getTopicDispatcherPetriNet(String idSuffix, int capacity){
 
+        System.out.println("New dispatcher with suffix: " + idSuffix);
+
         PetriNet templateNet = PnmlParser.parsePnml(homeDirectory + "/src/main/resources/templates/TopicSubDispatcherTemplate.pnml").get(0);
 
         for(Place p : templateNet.allPlaces()){
@@ -38,10 +37,7 @@ public class TopicTemplates extends PnmlTemplate {
 
         for(PnObject po : templateNet.allObjects()){
             if(!po.getId().equals(TemplateConstants.DISPATCHER_TEMPLATE_PAGE)){
-                po.setId(po.getId() + "-" + idSuffix);
-                Name name = new Name();
-                name.setText(po.getId() + "-" + idSuffix);
-                po.setName(name);
+                updatePnObjectIdAndName(po, idSuffix);
             }
         }
 
@@ -60,10 +56,7 @@ public class TopicTemplates extends PnmlTemplate {
 
         for(PnObject po : templateNet.allObjects()){
             if(!po.getId().equals(TemplateConstants.CALLBACK_QUEUE_TEMPLATE_PAGE)){
-                po.setId(po.getId() + "-" + idSuffix);
-                Name name = new Name();
-                name.setText(po.getId() + "-" + idSuffix);
-                po.setName(name);
+                updatePnObjectIdAndName(po, idSuffix);
             }
         }
 
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
index d3b138e..3e6023e 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
@@ -3,9 +3,11 @@ package de.tudresden.inf.st.pnml.flatter.tina;
 import de.tudresden.inf.st.pnml.base.constants.PnmlConstants;
 import de.tudresden.inf.st.pnml.jastadd.model.Arc;
 import de.tudresden.inf.st.pnml.jastadd.model.PetriNet;
+import de.tudresden.inf.st.pnml.jastadd.model.Transition;
 
 import java.io.*;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 public class NdrioProxy extends AbstractTinaProxy{
@@ -46,6 +48,27 @@ public class NdrioProxy extends AbstractTinaProxy{
         }
     }
 
+    /**
+     *
+     * Includes inhibitor arcs which are not part of the .pnml format into the .net format. The inhibitor arc
+     * information in .pnml is currently attached to arcs via ToolSpecifics in DiNeROS.
+     *
+     * Example of an inhibitor arc net within .net:
+     *
+     * net TestNet
+     * tr {t1} {p3} {p1}?-1 -> {p2}
+     *
+     * pl {p1} (0)
+     * pl {p2} (0)
+     * pl {p3} (1)
+     *
+     * Where the curved brackets are escaping special signs within element names. Thus, these brackets are not always
+     * part of the .net to be patched "patched".
+     *
+     * @param petriNet The flatted petri net.
+     * @param inputPath The path of the flatted nets pnml.
+     * @param outputPath The path to generate the resulting .net file to.
+     */
     public void includeInhibitorArcs(PetriNet petriNet, String inputPath, String outputPath) {
 
         final String NET_INHIBITOR_ARC = "?-1";
@@ -53,7 +76,8 @@ public class NdrioProxy extends AbstractTinaProxy{
         List<Arc> inhibitorArcs = new ArrayList<>();
 
         for(Arc a : petriNet.allArcs()){
-            if(a.getType().equals(PnmlConstants.INHIBITOR_ARC)){
+            if(a.getNumToolspecific() > 0 && a.getType().equals(PnmlConstants.INHIBITOR_ARC)){
+                System.out.println("[FLATTER] Found inh arc: " + a.getId());
                 inhibitorArcs.add(a);
             }
         }
@@ -65,30 +89,50 @@ public class NdrioProxy extends AbstractTinaProxy{
             while ((line = br.readLine()) != null) {
                 // process line by line
                 if(line.startsWith("tr")){
+
                     String[] splitLine = line.split(" ");
+                    boolean matched = false;
+
                     for(Arc a : inhibitorArcs){
-                        if(a.getId().equals(splitLine[1])){
+                        if(a.getTarget().getId().equals(splitLine[1].
+                                replace("{", "").
+                                replace("}", "").
+                                replace(" ", ""))){
+
                             StringBuilder finalLineContent = new StringBuilder();
                             for(int i = 0; i < splitLine.length; i++){
 
-                                finalLineContent.append(splitLine[i]);
+                                if(a.getSource().getId().equals(splitLine[i].
+                                        replace("{", "").
+                                        replace("}", "").
+                                        replace(" ", ""))){
 
-                                if(i == 2){
                                     finalLineContent.append(" ");
+                                    finalLineContent.append(splitLine[i]);
                                     finalLineContent.append(NET_INHIBITOR_ARC);
-                                }
 
-                                finalLineContent.append(" ");
+                                } else {
+                                    if ( i != 0){
+                                        finalLineContent.append(" ");
+                                    }
+                                    finalLineContent.append(splitLine[i]);
+                                }
                             }
 
                             finalContent.append(finalLineContent);
-
-                        } else {
-                            finalContent.append(line);
+                            finalContent.append("\n");
+                            matched = true;
+                            break;
                         }
                     }
+
+                    if(!matched) {
+                        finalContent.append(line);
+                        finalContent.append("\n");
+                    }
                 }else {
                     finalContent.append(line);
+                    finalContent.append("\n");
                 }
             }
 
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ChannelFlatter.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ChannelFlatter.java
index 18a7d18..cece534 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ChannelFlatter.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/ChannelFlatter.java
@@ -26,7 +26,7 @@ public class ChannelFlatter {
         // construct signal-id to transition mapping
         for (Transition t : petriNet.allTransitions()) {
 
-            if(t.asInputSignalTransition().getStaticInputSignalBindingList() != null) {
+            if (t.asInputSignalTransition().getStaticInputSignalBindingList() != null) {
                 for (InputSignalBinding isb : t.asInputSignalTransition().getStaticInputSignalBindingList()) {
 
                     if (signalMap.containsKey(isb.getInputSignalID())) {
@@ -52,12 +52,12 @@ public class ChannelFlatter {
             String targetId2 = TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + entry.getKey() + "-base";
             Place coreInPlace = getPlaceByID(petriNet, targetId);
 
-            for(InputSignalBinding isb : entry.getValue().get(0).getStaticInputSignalBindingList()){
-                if(isb.getInputSignalID().equals(entry.getKey())){
+            for (InputSignalBinding isb : entry.getValue().get(0).getStaticInputSignalBindingList()) {
+                if (isb.getInputSignalID().equals(entry.getKey())) {
 
-                    if(isb.getInputSignalValue() == 1){
+                    if (isb.getInputSignalValue() == 1) {
                         getPlaceByID(petriNet, targetId).getInitialMarking().setText(1);
-                    }else {
+                    } else {
                         getPlaceByID(petriNet, targetId2).getInitialMarking().setText(1);
                     }
                 }
@@ -71,8 +71,8 @@ public class ChannelFlatter {
                 String inActToActId = TemplateConstants.INPUT_SIGNAL_TRANSITION_TO_ACTIVE + "-" + entry.getKey() + "-base";
 
                 boolean isActiveSignal = false;
-                for(InputSignalBinding isb : entry.getValue().get(i).getStaticInputSignalBindingList()){
-                    if(isb.getInputSignalID().equals(entry.getKey())){
+                for (InputSignalBinding isb : entry.getValue().get(i).getStaticInputSignalBindingList()) {
+                    if (isb.getInputSignalID().equals(entry.getKey())) {
                         isActiveSignal = isb.getInputSignalValue() == 1;
                         break;
                     }
@@ -81,7 +81,7 @@ public class ChannelFlatter {
                 // build AND-based clauses
                 if (!entry.getValue().get(i).getInputSignalClause().printExp().contains("OR")) {
 
-                    if(andCount == 0){
+                    if (andCount == 0) {
                         createAndIncludeArc(topPage, "IoTransitionToSignal-" + entry.getKey() + "-base", entry.getValue().get(i), coreInPlace);
                         createAndIncludeArc(topPage, "IoTransitionFromSignal-" + entry.getKey() + "-base", coreInPlace, entry.getValue().get(i));
                         petriNet.flushTreeCache();
@@ -95,24 +95,24 @@ public class ChannelFlatter {
                 }
 
                 // build OR-based clauses
-                if(entry.getValue().get(i).getInputSignalClause().printExp().contains("OR")){
+                if (entry.getValue().get(i).getInputSignalClause().printExp().contains("OR")) {
                     // has already connected or signal connecting place?
                     Place orPlace = null;
-                    for(Place p : entry.getValue().get(i).incomingPlaces()){
-                        if (p.getId().contains(TemplateConstants.INPUT_SIGNAL_PLACE_OR_CONNECTION)){
+                    for (Place p : entry.getValue().get(i).incomingPlaces()) {
+                        if (p.getId().contains(TemplateConstants.INPUT_SIGNAL_PLACE_OR_CONNECTION)) {
                             orPlace = p;
                             break;
                         }
                     }
 
-                    if(orPlace == null){
+                    if (orPlace == null) {
                         orPlace = buildOrBaseNetElements(petriNet, topPage, signalCount, i, entry.getValue().get(i));
                     }
 
                     InputSignalTransition activeToOrConnector = PrimitiveTemplates.getInputSignalTransition();
                     activeToOrConnector.setId(TemplateConstants.INPUT_SIGNAL_TO_OR + "-" + entry.getKey() + "-" + i);
                     Name nameT = new Name();
-                    nameT.setText(TemplateConstants.INPUT_SIGNAL_TO_OR + "-" + entry.getKey()  + "-" + i);
+                    nameT.setText(TemplateConstants.INPUT_SIGNAL_TO_OR + "-" + entry.getKey() + "-" + i);
                     activeToOrConnector.setName(nameT);
                     TransitionInformation pi3 = new DefaultTransitionInformation();
                     pi3.setLocation("signal");
@@ -122,7 +122,7 @@ public class ChannelFlatter {
                     topPage.addObject(activeToOrConnector);
                     petriNet.flushTreeCache();
 
-                    if(andCount == 0 && orCount == 0){
+                    if (andCount == 0 && orCount == 0) {
                         attachORSignalNetToBaseSignalNet(petriNet, getTransitionByID(petriNet, actToInActId).asInputSignalTransition(),
                                 getTransitionByID(petriNet, inActToActId).asInputSignalTransition(), activeToOrConnector,
                                 orPlace.asOutputSignalPlace(), i, entry.getKey(), true, isActiveSignal);
@@ -185,7 +185,7 @@ public class ChannelFlatter {
         OutputSignalPlace aOsp = getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-base").asOutputSignalPlace();
         OutputSignalPlace iOsp = getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + signalId + "-base").asOutputSignalPlace();
 
-        if(!isBase) {
+        if (!isBase) {
             aOsp = getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-base").asOutputSignalPlace().treeCopy();
             iOsp = getPlaceByID(petriNet, TemplateConstants.INPUT_SIGNAL_PLACE_INACTIVE + "-" + signalId + "-base").asOutputSignalPlace().treeCopy();
             aOsp.setId(TemplateConstants.INPUT_SIGNAL_PLACE_ACTIVE + "-" + signalId + "-" + count);
@@ -193,16 +193,16 @@ public class ChannelFlatter {
         }
 
         // marking
-        if(isActive){
+        if (isActive) {
             aOsp.getInitialMarking().setText(1);
-        }else {
+        } else {
             iOsp.getInitialMarking().setText(1);
         }
 
         InputSignalTransition resetTransition = null;
 
-        for(Arc a: orPlace.getOutArcList()){
-            if(a.getTarget().getId().contains(TemplateConstants.INPUT_SIGNAL_PLACE_OR_RESET)){
+        for (Arc a : orPlace.getOutArcList()) {
+            if (a.getTarget().getId().contains(TemplateConstants.INPUT_SIGNAL_PLACE_OR_RESET)) {
                 resetTransition = a.getTarget().asTransitionNode().asTransition().asInputSignalTransition();
                 break;
             }
@@ -213,7 +213,7 @@ public class ChannelFlatter {
         createAndIncludeInhibitorArc(topPage, TemplateConstants.ARC_OR_TO_PLACE + "-" + signalId + "-" + count, orPlace, activeToOrConnector);
         createAndIncludeArc(topPage, TemplateConstants.ARC_PLACE_TO_OR + "-" + signalId + "-" + count, activeToOrConnector, orPlace);
 
-        if(!isBase) {
+        if (!isBase) {
             createAndIncludeArc(topPage, "arc-or-1-" + signalId + "-" + count, aOsp, inactiveT);
             createAndIncludeArc(topPage, "arc-or-2-" + signalId + "-" + count, inactiveT, iOsp);
             createAndIncludeArc(topPage, "arc-or-3-" + signalId + "-" + count, iOsp, activeT);
@@ -239,16 +239,16 @@ public class ChannelFlatter {
         createAndIncludeArc(topPage, "arc-and-3-" + signalId + "-" + count, iOsp, activeT);
         createAndIncludeArc(topPage, "arc-and-4-" + signalId + "-" + count, activeT, aOsp);
 
-        createAndIncludeArc(topPage,"IoTransitionToSignal-" + signalId + "-" + count, transition, aOsp);
-        createAndIncludeArc(topPage,"IoTransitionFromSignal-" + signalId + "-" + count, aOsp, transition);
+        createAndIncludeArc(topPage, "IoTransitionToSignal-" + signalId + "-" + count, transition, aOsp);
+        createAndIncludeArc(topPage, "IoTransitionFromSignal-" + signalId + "-" + count, aOsp, transition);
 
         topPage.addObject(aOsp);
         topPage.addObject(iOsp);
 
         // marking
-        if(isActive){
+        if (isActive) {
             aOsp.getInitialMarking().setText(1);
-        }else {
+        } else {
             iOsp.getInitialMarking().setText(1);
         }
 
@@ -440,14 +440,20 @@ public class ChannelFlatter {
         return petriNet;
     }
 
-    private static void insertChannelElements(PetriNet petriNet, int channelCount) {
+    private static PlaceInformation generateChannelPlaceInformation() {
 
-        OutputSignalPlace channelPlace = new OutputSignalPlace();
         PlaceInformation newPi = new PlaceInformation();
         newPi.setLocation("channel");
         newPi.setSubNet("channel");
         newPi.setType(PnmlConstants.PLACE_TYPE_DISCRETE);
-        channelPlace.setMutualPlaceInformation(newPi);
+
+        return newPi;
+    }
+
+    private static void insertChannelElements(PetriNet petriNet, int channelCount) {
+
+        OutputSignalPlace channelPlace = new OutputSignalPlace();
+        channelPlace.setMutualPlaceInformation(generateChannelPlaceInformation());
 
         InputSignalTransition channelTransition = new InputSignalTransition();
         TransitionInformation newTi = new DefaultTransitionInformation();
@@ -542,15 +548,17 @@ public class ChannelFlatter {
     public static PetriNet flatServiceChannels(PetriNet petriNet) {
 
         Set<String> resolvedSubnets = new HashSet<>();
+        Set<String> reconnectedClients = new HashSet<>();
 
         Set<InputSignalTransition> unflattedLeaves = getUnflattedServiceCallLeaves(petriNet, resolvedSubnets);
 
         int serverInstanceCount = 0;
 
+        // flat everything but the final service calls
         while (unflattedLeaves.size() > 0) {
 
             for (InputSignalTransition t : unflattedLeaves) {
-                flatServiceChannelsInternal(petriNet, serverInstanceCount, t);
+                flatServiceChannelsInternal(petriNet, serverInstanceCount, t, reconnectedClients);
 
                 for (Place p : t.outgoingPlaces()) {
                     resolvedSubnets.add(p.asOutputSignalPlace().getStaticPlaceInformation().getSubNet());
@@ -564,15 +572,24 @@ public class ChannelFlatter {
             }
         }
 
+        // flat the final service calls
+        for(Transition t : petriNet.allTransitions()){
+            if(t.asInputSignalTransition().getStaticTransitionInformation().getType().equals(PnmlConstants.TRANSITION_TYPE_SERVICE_REQUEST)){
+                System.out.println("Flatting a root service transition: " + t.getId());
+                flatServiceChannelsInternal(petriNet, serverInstanceCount, t.asInputSignalTransition(), reconnectedClients);
+                serverInstanceCount++;
+            }
+        }
+
         return petriNet;
     }
 
-    private static PetriNet flatServiceChannelsInternal(PetriNet petriNet, int serverInstanceCount, InputSignalTransition t) {
+    private static PetriNet flatServiceChannelsInternal(PetriNet petriNet, int serverInstanceCount, InputSignalTransition requestTransitionPnObject, Set<String> reconnectedClients) {
 
         Page topPage = petriNet.getPage(0);
 
         // get response and request transition
-        InputSignalTransition requestTransition = t.asInputSignalTransition();
+        InputSignalTransition requestTransition = requestTransitionPnObject.asInputSignalTransition();
         InputSignalTransition responseTransition = getResponseTransition(petriNet, requestTransition).asInputSignalTransition();
 
         // get elements of server subnet
@@ -608,6 +625,9 @@ public class ChannelFlatter {
         pi.setType(PnmlConstants.PLACE_TYPE_DISCRETE);
         queueCapacityPlace.setMutualPlaceInformation(pi);
         queueCapacityPlace.getInitialMarking().setText(16);
+        Name qCapName = new Name();
+        qCapName.setText(TemplateConstants.SERVICE_QUEUE_CAPACITY_PLACE + "-" + queue_suffix);
+        queueCapacityPlace.setName(qCapName);
         topPage.addObject(queueCapacityPlace);
 
         int clientCount = 0;
@@ -617,6 +637,7 @@ public class ChannelFlatter {
             // create clone for each client
             Set<OutputSignalPlace> topicInputPlaces = new HashSet<>();
 
+           System.out.println(">>>>>>>>>>>>>> Copying server net: " + serverSubnet);
             Pair<OutputSignalPlace, OutputSignalPlace> ioPlacePair = copyServerNet(petriNet, serverPlaces, serverTransitions, topicInputPlaces,
                     serverInstanceCount + "-" + clientCount, serverSubnet, copiedObjects);
 
@@ -628,9 +649,9 @@ public class ChannelFlatter {
                 String suffix = "serverInstance-" + serverInstanceCount + "-clientCount-" + clientCount + "-topicInput-" + topicInputPlaceCount;
 
                 int capacity = 0;
-                for(Arc a : topicInputPlace.getOutArcList()){
-                    for(Place p : a.getTarget().asTransitionNode().asTransition().incomingPlaces()){
-                        if(p.getId().contains(TemplateConstants.PUBLISHER_CAPACITY_PLACE)){
+                for (Arc a : topicInputPlace.getOutArcList()) {
+                    for (Place p : a.getTarget().asTransitionNode().asTransition().incomingPlaces()) {
+                        if (p.getId().contains(TemplateConstants.PUBLISHER_CAPACITY_PLACE)) {
                             capacity = p.getInitialMarking().getText();
                         }
                     }
@@ -666,10 +687,36 @@ public class ChannelFlatter {
 
             // link the template instance to the net via arcs
 
-            createAndIncludeArc(topPage, "channel-client-input-arc-" + channel_suffix, incomingPlace,
-                    getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_INPUT_TRANSITION + "-" + channel_suffix));
-            createAndIncludeArc(topPage, "channel-client-output-arc-" + channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_OUTPUT_TRANSITION + "-" + channel_suffix),
-                    responseTransition.getOutArcs().get(clientCount).getTarget());
+            if(getPlaceByID(petriNet, incomingPlace.getId()) == null){
+
+                for(Place p : petriNet.allPlaces()){
+                    if(p.getId().startsWith(incomingPlace.getId()) && !reconnectedClients.contains(p.getId())){
+                        System.out.println("Reconnecting client to server: " + p.getId() + " --> " + TemplateConstants.SERVICE_CLIENT_INPUT_TRANSITION + "-" + channel_suffix);
+                        createAndIncludeArc(topPage, "channel-client-input-arc-" + channel_suffix,  p,
+                                getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_INPUT_TRANSITION + "-" + channel_suffix));
+                        reconnectedClients.add(p.getId());
+                    }
+                }
+            } else {
+                createAndIncludeArc(topPage, "channel-client-input-arc-" + channel_suffix,  incomingPlace,
+                        getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_INPUT_TRANSITION + "-" + channel_suffix));
+            }
+
+            if(getPlaceByID(petriNet, responseTransition.getOutArcs().get(clientCount).getTarget().getId()) == null){
+
+                for(Place p : petriNet.allPlaces()){
+                    if(p.getId().startsWith(responseTransition.getOutArcs().get(clientCount).getTarget().getId()) && !reconnectedClients.contains(p.getId())){
+                        System.out.println("Reconnecting server to client: " + TemplateConstants.SERVICE_CLIENT_OUTPUT_TRANSITION + "-" + channel_suffix + " --> " + p.getId());
+
+                        createAndIncludeArc(topPage, "channel-client-output-arc-" +
+                                channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_OUTPUT_TRANSITION + "-" + channel_suffix), p);
+                        reconnectedClients.add(p.getId());
+                    }
+                }
+            } else {
+                createAndIncludeArc(topPage, "channel-client-output-arc-" + channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_OUTPUT_TRANSITION + "-" + channel_suffix),
+                        responseTransition.getOutArcs().get(clientCount).getTarget());
+            }
 
             // service instance input transition -> service input place
             createAndIncludeArc(topPage, "channel-server-input-arc-" + channel_suffix,
@@ -681,11 +728,11 @@ public class ChannelFlatter {
 
             createAndIncludeArc(topPage, "queue-to-server-place-arc-" + channel_suffix, getPlaceByID(petriNet, TemplateConstants.SERVICE_QUEUE_TO_SERVER_PLACE + "-" + channel_suffix),
                     getTransitionByID(petriNet, TemplateConstants.SERVICE_SERVER_INPUT_TRANSITION + "-" + channel_suffix));
-            createAndIncludeArc(topPage,"client-to-server-input" + channel_suffix, getPlaceByID(petriNet, TemplateConstants.SERVICE_TO_QUEUE_PLACE + "-" + channel_suffix),
+            createAndIncludeArc(topPage, "client-to-server-input" + channel_suffix, getPlaceByID(petriNet, TemplateConstants.SERVICE_TO_QUEUE_PLACE + "-" + channel_suffix),
                     getTransitionByID(petriNet, TemplateConstants.SERVICE_SERVER_INPUT_TRANSITION + "-" + channel_suffix));
             createAndIncludeArc(topPage, "server-output-to-queue-cap-arc-" + channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_SERVER_OUTPUT_TRANSITION + "-" + channel_suffix),
                     getPlaceByID(petriNet, TemplateConstants.SERVICE_QUEUE_CAPACITY_PLACE + "-" + queue_suffix));
-            createAndIncludeArc(topPage, "client-connector-to-serviceToqueue-arc-" + channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_CONNECTOR_TRANSITION + "-" + channel_suffix),
+            createAndIncludeArc(topPage, "client-connector-to-service-to-queue-arc-" + channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_CLIENT_CONNECTOR_TRANSITION + "-" + channel_suffix),
                     getPlaceByID(petriNet, TemplateConstants.SERVICE_TO_QUEUE_PLACE + "-" + channel_suffix));
 
             // Arcs integrating the capacity place
@@ -693,7 +740,7 @@ public class ChannelFlatter {
                     queueCapacityPlace, getTransitionByID(petriNet, TemplateConstants.SERVICE_QUEUE_OVERFLOW_TRANSITION + "-" + channel_suffix));
             createAndIncludeArc(topPage, "server-to-queue-arc-" + channel_suffix,
                     queueCapacityPlace, getTransitionByID(petriNet, TemplateConstants.SERVICE_QUEUE_CONNECTOR_TRANSITION + "-" + channel_suffix));
-            createAndIncludeArc(topPage,"serveroutput-to-capacity-arc-" + channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_SERVER_OUTPUT_TRANSITION + "-" + channel_suffix),
+            createAndIncludeArc(topPage, "serveroutput-to-capacity-arc-" + channel_suffix, getTransitionByID(petriNet, TemplateConstants.SERVICE_SERVER_OUTPUT_TRANSITION + "-" + channel_suffix),
                     queueCapacityPlace);
 
             serverOutTransitions.add(getTransitionByID(petriNet, TemplateConstants.SERVICE_SERVER_OUTPUT_TRANSITION + "-" + channel_suffix));
@@ -707,6 +754,10 @@ public class ChannelFlatter {
             serverFeedbackPlace.getName().setText(TemplateConstants.SERVICE_FEEDBACK_PLACE + "-" + channel_suffix);
             serverFeedbackPlace.setNodeGraphics(capPlace.getNodeGraphics().treeCopy());
             serverFeedbackPlace.getInitialMarking().setText(1);
+
+            Name sFeedbackPlaceName = new Name();
+            sFeedbackPlaceName.setText(TemplateConstants.SERVICE_FEEDBACK_PLACE + "-" + channel_suffix);
+            serverFeedbackPlace.setName(sFeedbackPlaceName);
             topPage.addObject(serverFeedbackPlace);
 
             createAndIncludeArc(topPage, "feedbackplace-to-inputtransition-arc-" + channel_suffix, serverFeedbackPlace,
@@ -721,7 +772,7 @@ public class ChannelFlatter {
 
         petriNet.flushTreeCache();
 
-        for(PnObject po : copiedObjects){
+        for (PnObject po : copiedObjects) {
             po.removeSelf();
         }
 
@@ -730,6 +781,7 @@ public class ChannelFlatter {
         }
 
         for (PnObject po : serverObjectsWithoutArcs) {
+        //    System.out.println("Removing server objects without arcs: " + po.getId());
             po.removeSelf();
         }
 
@@ -737,22 +789,28 @@ public class ChannelFlatter {
         serverInstanceCount++;
 
         for (Arc a : requestTransition.getOutArcs()) {
+            System.out.println("REMOVING ARC: " + a.getId());
             a.removeSelf();
         }
 
         for (Arc a : requestTransition.getInArcs()) {
+            System.out.println("REMOVING ARC: " + a.getId());
             a.removeSelf();
         }
 
         for (Arc a : responseTransition.getOutArcs()) {
+            System.out.println("REMOVING ARC: " + a.getId());
             a.removeSelf();
         }
 
         for (Arc a : responseTransition.getInArcs()) {
+            System.out.println("REMOVING ARC: " + a.getId());
             a.removeSelf();
         }
 
+        System.out.println("REMOVING REQ: " + requestTransition.getId());
         requestTransition.removeSelf();
+        System.out.println("REMOVING RES: " + responseTransition.getId());
         responseTransition.removeSelf();
 
         petriNet.flushTreeCache();
@@ -776,8 +834,12 @@ public class ChannelFlatter {
         for (Place p : serverPlaces) {
             OutputSignalPlace copy = PrimitiveTemplates.getOutputSignalPlace();
             copy.setId(p.getId() + "-" + suffix);
+            Name copyName = new Name();
+            copyName.setText(copy.getId());
+            copy.setName(copyName);
+
             copy.setToolspecificList(p.getToolspecificList().treeCopy());
-            copy.getName().setText(p.getName().getText());
+            copy.getName().setText(p.getName().getText() + "-" + suffix);
             copy.setNodeGraphics(p.getNodeGraphics().treeCopy());
 
             // copy initial marking of places
@@ -799,12 +861,13 @@ public class ChannelFlatter {
                 if (!a.getTarget().getSubnet().equals(serverSubnet)) {
 
                     if (!a.getTarget().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getType().equals(PnmlConstants.TRANSITION_TYPE_SERVICE_RESPONSE)
-                            && !a.getTarget().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getSubNet().equals("channel")) {
+                            && !a.getTarget().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getLocation().equals("channel")) {
                         logger.error("Found topic input place which needs to be re-flatted: " + copy.getId());
                         topicInputPlaces.add(petriNet.getPlaceFromPlaceNode(copy.asPlaceNode()).asOutputSignalPlace());
                     }
                 }
 
+      //          System.out.println(">>>> Target: " + a.getTarget().getId());
                 if (petriNet.getTransitionFromTransitionNode(a.getTarget().asTransitionNode()).
                         asInputSignalTransition().getStaticTransitionInformation().getType().equals(PnmlConstants.TRANSITION_TYPE_SERVICE_RESPONSE)) {
                     serverOutPlace = copy.asOutputSignalPlace();
@@ -826,7 +889,7 @@ public class ChannelFlatter {
             copy.setId(t.getId() + "-" + suffix);
             copy.getName().setText(t.getName().getText());
             copy.setMutualInputSignalBindingList(t.asInputSignalTransition().getMutualInputSignalBindingList().treeCopy());
-            copy.getName().setText(t.getName().getText());
+            copy.getName().setText(t.getName().getText() + "-" + suffix);
             copy.setToolspecificList(t.getToolspecificList().treeCopy());
             copy.setNodeGraphics(t.getNodeGraphics().treeCopy());
 
@@ -871,16 +934,16 @@ public class ChannelFlatter {
 
         for (Arc a : petriNet.allArcs()) {
 
-            if(a.getTarget().isTransitionNode() && a.getSource().isPlaceNode()){
+            if (a.getTarget().isTransitionNode() && a.getSource().isPlaceNode()) {
 
-                if(a.getTarget().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getSubNet().equals(subnet) &&
-                    a.getSource().asPlaceNode().asPlace().asOutputSignalPlace().getStaticPlaceInformation().getSubNet().equals(subnet)){
+                if (a.getTarget().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getSubNet().equals(subnet) &&
+                        a.getSource().asPlaceNode().asPlace().asOutputSignalPlace().getStaticPlaceInformation().getSubNet().equals(subnet)) {
                     arcs.add(a);
                 }
 
             } else {
-                if(a.getSource().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getSubNet().equals(subnet) &&
-                        a.getTarget().asPlaceNode().asPlace().asOutputSignalPlace().getStaticPlaceInformation().getSubNet().equals(subnet)){
+                if (a.getSource().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getSubNet().equals(subnet) &&
+                        a.getTarget().asPlaceNode().asPlace().asOutputSignalPlace().getStaticPlaceInformation().getSubNet().equals(subnet)) {
                     arcs.add(a);
                 }
             }
@@ -894,9 +957,11 @@ public class ChannelFlatter {
         Set<Arc> arcs = new HashSet<>();
 
         for (Arc a : petriNet.allArcs()) {
-            if (a.getTarget().getSubnet().equals(subnet) && a.getSource().getSubnet().equals(subnet)) {
+            // System.out.println(">>>> Arc target: " + a.getTarget().getId());
+
+            if (getArcTargetSubnet(a).equals(subnet) && getArcSourceSubnet(a).equals(subnet)) {
                 arcs.add(a);
-            } else if (a.getSource().getSubnet().equals(subnet) && !a.getTarget().getSubnet().equals(subnet)) {
+            } else if (getArcSourceSubnet(a).equals(subnet) && !getArcTargetSubnet(a).equals(subnet)) {
                 arcs.add(a);
             }
         }
@@ -904,14 +969,42 @@ public class ChannelFlatter {
         return arcs;
     }
 
+    private static String getArcTargetSubnet(Arc arc) {
+
+        if (arc.getTarget().isTransitionNode()) {
+            return arc.getTarget().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getSubNet();
+        } else {
+            return arc.getTarget().asPlaceNode().asPlace().asOutputSignalPlace().getStaticPlaceInformation().getSubNet();
+        }
+    }
+
+    private static String getArcSourceSubnet(Arc arc) {
+
+        if (arc.getSource().isTransitionNode()) {
+            return arc.getSource().asTransitionNode().asTransition().asInputSignalTransition().getStaticTransitionInformation().getSubNet();
+        } else {
+            return arc.getSource().asPlaceNode().asPlace().asOutputSignalPlace().getStaticPlaceInformation().getSubNet();
+        }
+    }
+
     private static Transition getResponseTransition(PetriNet petriNet, Transition requestTransition) {
 
         for (Transition t : petriNet.allTransitions()) {
 
             if (t.asInputSignalTransition().getStaticTransitionInformation().isServiceTransitionInformation()
-                    && t.asInputSignalTransition().getStaticTransitionInformation().getSubNet().equals(requestTransition.asInputSignalTransition().getStaticTransitionInformation().getSubNet())
                     && t.asInputSignalTransition().getStaticTransitionInformation().getType().equals(PnmlConstants.TRANSITION_TYPE_SERVICE_RESPONSE)) {
-                return t;
+                for (Place p1 : t.outgoingPlaces()) {
+                    String subnetOut = p1.asOutputSignalPlace().getStaticPlaceInformation().getSubNet();
+
+                    for (Place p2 : requestTransition.incomingPlaces()) {
+                        String subnetIn = p2.asOutputSignalPlace().getStaticPlaceInformation().getSubNet();
+
+                        if(subnetIn.equals(subnetOut)){
+                            // System.out.println("FOUND PAIR: " + t.getId() + " -- " + requestTransition.getId());
+                            return t;
+                        }
+                    }
+                }
             }
         }
 
diff --git a/src/main/resources/elements/OutputSignalPlace.pnml b/src/main/resources/elements/OutputSignalPlace.pnml
index a9ab44b..fad5346 100644
--- a/src/main/resources/elements/OutputSignalPlace.pnml
+++ b/src/main/resources/elements/OutputSignalPlace.pnml
@@ -13,7 +13,7 @@
                     </outputsignalbindings>
                 </toolspecific>
                 <name>
-                    <text>ServiceTogglePlace</text>
+                    <text>REPLACE</text>
                     <graphics>
                         <offset x="0" y="0" />
                     </graphics>
-- 
GitLab