From f4fdf7b888f615ec0a4a735676250b7db7472ce6 Mon Sep 17 00:00:00 2001
From: SebastianEbert <sebastian.ebert@tu-dresden.de>
Date: Wed, 2 Jun 2021 15:09:05 +0200
Subject: [PATCH] (untested) deep copy by serialization + (untested) split for
 ros-topic containing nets

---
 README.md                                     |   1 +
 src/main/jastadd/Navigation.jrag              |   4 +
 .../tudresden/inf/st/export/PnmlExporter.java | 199 +++++++++++++++++-
 .../st/export/PrimitiveElementsConverter.java |   4 +-
 .../java/de/tudresden/inf/st/pnml/Main.java   |   5 +-
 5 files changed, 204 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index d6fd34c..bc523cb 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
 # pnml-relast-splitter
 
+* Currently not supported: reference-places and reference transitions
\ No newline at end of file
diff --git a/src/main/jastadd/Navigation.jrag b/src/main/jastadd/Navigation.jrag
index 1818d4e..14d2e5e 100644
--- a/src/main/jastadd/Navigation.jrag
+++ b/src/main/jastadd/Navigation.jrag
@@ -68,4 +68,8 @@ aspect Navigation {
     to PetriNet.allArcs()
     for petriNet();
 
+  coll java.util.Set<Page> PetriNet.allPages() [new java.util.HashSet()] root PetriNet;
+  Page contributes this
+    to PetriNet.allPages()
+    for petriNet();
 }
diff --git a/src/main/java/de/tudresden/inf/st/export/PnmlExporter.java b/src/main/java/de/tudresden/inf/st/export/PnmlExporter.java
index a6e4617..66f13d9 100644
--- a/src/main/java/de/tudresden/inf/st/export/PnmlExporter.java
+++ b/src/main/java/de/tudresden/inf/st/export/PnmlExporter.java
@@ -1,18 +1,205 @@
 package de.tudresden.inf.st.export;
 
-import de.tudresden.inf.st.pnml.jastadd.model.PetriNet;
+import de.tudresden.inf.st.pnml.jastadd.model.*;
+import fr.lip6.move.pnml.framework.general.PnmlExport;
 import fr.lip6.move.pnml.framework.utils.ModelRepository;
-import fr.lip6.move.pnml.framework.utils.exception.InvalidIDException;
-import fr.lip6.move.pnml.ptnet.hlapi.PetriNetDocHLAPI;
+import fr.lip6.move.pnml.framework.utils.exception.*;
+import fr.lip6.move.pnml.ptnet.hlapi.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.*;
 
 public class PnmlExporter {
 
+    private static final Logger logger = LoggerFactory.getLogger(PnmlExporter.class);
+
     public static String serializeToPnmlFile(PetriNet petriNet) throws InvalidIDException {
 
-        ModelRepository.getInstance().createDocumentWorkspace("void");
+        ModelRepository.getInstance().createDocumentWorkspace("pnml-split-pre-purge");
 
+        // build basic document and net
         PetriNetDocHLAPI doc = new PetriNetDocHLAPI();
+        PetriNetHLAPI net = ComplexElementsConverter.convertPetriNetContainerToPnmlObject(petriNet, doc);
+
+        // setup the page trees
+        Set<PageHLAPI> convertedPages = buildPageTrees(petriNet, net);
+
+        // convert and include places
+        Set<PlaceHLAPI> convertedPlaces = convertAndIncludePlaces(petriNet, convertedPages);
+
+        // convert and include transitions
+        Set<TransitionHLAPI> convertedTransitions = convertAndIncludeTransitions(petriNet, convertedPages);
+
+        // convert and include arcs
+        Set<ArcHLAPI> convertedArcs = convertAndIncludeArcs(petriNet, convertedPages, convertedPlaces, convertedTransitions);
+
+        // export the created objects to pnml
+        String targetPath = "src/main/gen/serialization/" + UUID.randomUUID().toString() + "-pres-plit.pnml";
+        boolean hasFailed = false;
+
+        try {
+            PnmlExport pex = new PnmlExport();
+            pex.exportObject(doc, targetPath);
+        } catch (UnhandledNetType | OCLValidationFailed unhandledNetType) {
+            logger.error("EXCEPTION: " + Arrays.toString(unhandledNetType.getStackTrace()));
+            hasFailed = true;
+        } catch (IOException | ValidationFailedException | BadFileFormatException | OtherException e) {
+            logger.error(Arrays.toString(e.getStackTrace()));
+            hasFailed = true;
+        }
+
+        // ctor of the workspace
+        try {
+            ModelRepository.getInstance().destroyCurrentWorkspace();
+        } catch (VoidRepositoryException e) {
+            logger.error("EXCEPTION: " + Arrays.toString(e.getStackTrace()));
+            hasFailed = true;
+        }
+
+        return hasFailed ? null : targetPath;
+    }
+
+    private static Set<PlaceHLAPI> convertAndIncludePlaces(PetriNet petriNet, Set<PageHLAPI> convertedPages) {
+
+        Set<PlaceHLAPI> convertedPlaces = new HashSet<>();
+
+        for (Place p : petriNet.allPlaces()) {
+            PlaceHLAPI convertedPlace =  PrimitiveElementsConverter.convertPlaceToPnmlObject(p.asOutputSignalPlace());
+            Page containingPage = p.ContainingPage();
+
+            for(PageHLAPI pageHLAPI : convertedPages){
+                if(pageHLAPI.getId().equals(containingPage.getId())){
+                    assert convertedPlace != null;
+                    convertedPlace.setContainerPageHLAPI(pageHLAPI);
+                    break;
+                }
+            }
+            convertedPlaces.add(convertedPlace);
+        }
+        return convertedPlaces;
+    }
+
+    private static Set<TransitionHLAPI> convertAndIncludeTransitions(PetriNet petriNet, Set<PageHLAPI> convertedPages) {
+
+        Set<TransitionHLAPI> convertedTransitions = new HashSet<>();
+
+        for(Transition t: petriNet.allTransitions()){
+            TransitionHLAPI convertedTransition = PrimitiveElementsConverter.convertTransitionToPnmlObject(t.asInputSignalTransition());
+            Page containingPage = t.ContainingPage();
+
+            for(PageHLAPI pageHLAPI : convertedPages){
+                if(pageHLAPI.getId().equals(containingPage.getId())){
+                    assert convertedTransition != null;
+                    convertedTransition.setContainerPageHLAPI(pageHLAPI);
+                    break;
+                }
+            }
+            convertedTransitions.add(convertedTransition);
+        }
+        return convertedTransitions;
+    }
+
+    private static Set<ArcHLAPI> convertAndIncludeArcs(PetriNet petriNet, Set<PageHLAPI> convertedPages, Set<PlaceHLAPI> convertedPlaces, Set<TransitionHLAPI> convertedTransitions) {
+
+        Set<ArcHLAPI> convertedArcs = new HashSet<>();
+        for(Arc a : petriNet.allArcs()){
+
+            NodeHLAPI source = null;
+            NodeHLAPI target = null;
+
+            for(TransitionHLAPI th : convertedTransitions){
+                if(th.getId().equals(a.getSource().getId())){
+                    source = th;
+                    break;
+                }
+                if(th.getId().equals(a.getTarget().getId())){
+                    target = th;
+                    break;
+                }
+            }
+
+            for(PlaceHLAPI ph : convertedPlaces){
+                if(ph.getId().equals(a.getSource().getId())){
+                    source = ph;
+                    break;
+                }
+                if(ph.getId().equals(a.getTarget().getId())){
+                    target = ph;
+                    break;
+                }
+            }
+
+            ArcHLAPI convertedArc = PrimitiveElementsConverter.convertArcToPnmlObject(a, source, target);
+
+            Page containingPage = a.ContainingPage();
+
+            for(PageHLAPI pageHLAPI : convertedPages){
+                if(pageHLAPI.getId().equals(containingPage.getId())){
+                    assert convertedArc != null;
+                    convertedArc.setContainerPageHLAPI(pageHLAPI);
+                    break;
+                }
+            }
+
+            convertedArcs.add(convertedArc);
+        }
+
+        return convertedArcs;
+    }
+
+    private static Set<PageHLAPI> buildPageTrees(PetriNet petriNet, PetriNetHLAPI net) {
+
+        Set<PageHLAPI> convertedPages = new HashSet<>();
+
+        getTopLevelPages(petriNet).forEach(page -> convertedPages.add(ComplexElementsConverter.convertTopLevelPageContainerToPnmlObject(page, net)));
+
+        List<Page> nonTopLevelPages = getNonTopLevelPages(petriNet);
+        Set<String> processedPageIds = new HashSet<>();
+
+        for (int i = 0; i < nonTopLevelPages.size(); i++) {
+            Page parent = nonTopLevelPages.get(i).ContainingPage();
+
+            for (PageHLAPI convertedPage : convertedPages) {
+                if (parent.getId().equals(convertedPage.getId()) && !processedPageIds.contains(convertedPage.getId())) {
+                    processedPageIds.add(convertedPage.getId());
+                    convertedPages.add(ComplexElementsConverter.convertNonTopLevelPageContainerToPnmlObject(nonTopLevelPages.get(i), convertedPage));
+                    break;
+                }
+            }
+
+            if ((processedPageIds.size() != nonTopLevelPages.size()) && (i == (nonTopLevelPages.size() - 1))) {
+                i = -1;
+            }
+        }
+
+        return convertedPages;
+    }
+
+    private static List<Page> getTopLevelPages(PetriNet petriNet) {
+
+        List<Page> topLevelPages = new ArrayList<>();
+
+        for (Page page : petriNet.allPages()) {
+            if (page.ContainingPage() == null) {
+                topLevelPages.add(page);
+            }
+        }
+
+        return topLevelPages;
+    }
+
+    private static List<Page> getNonTopLevelPages(PetriNet petriNet) {
+
+        List<Page> nonTopLevelPages = new ArrayList<>();
+
+        for (Page page : petriNet.allPages()) {
+            if (page.ContainingPage() != null) {
+                nonTopLevelPages.add(page);
+            }
+        }
 
-        return null;
+        return nonTopLevelPages;
     }
-}
+}
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/export/PrimitiveElementsConverter.java b/src/main/java/de/tudresden/inf/st/export/PrimitiveElementsConverter.java
index 99dc728..25371c3 100644
--- a/src/main/java/de/tudresden/inf/st/export/PrimitiveElementsConverter.java
+++ b/src/main/java/de/tudresden/inf/st/export/PrimitiveElementsConverter.java
@@ -53,10 +53,10 @@ public class PrimitiveElementsConverter {
         return null;
     }
 
-    public static ArcHLAPI convertArcToPnmlObject(Arc arc, PageHLAPI containingPage, NodeHLAPI source, NodeHLAPI target) {
+    public static ArcHLAPI convertArcToPnmlObject(Arc arc, NodeHLAPI source, NodeHLAPI target) {
 
         try {
-            ArcHLAPI a = new ArcHLAPI(arc.getId(), source, target, containingPage);
+            ArcHLAPI a = new ArcHLAPI(arc.getId(), source, target);
 
             if (arc.getNumToolspecific() > 0) {
                 arc.getToolspecificList().forEach(toolInfo ->
diff --git a/src/main/java/de/tudresden/inf/st/pnml/Main.java b/src/main/java/de/tudresden/inf/st/pnml/Main.java
index a7f6355..82656a4 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/Main.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/Main.java
@@ -5,6 +5,7 @@ import de.tudresden.inf.st.postprocessing.GlobalToLocalNetsPostProcessor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class Main {
@@ -14,7 +15,9 @@ public class Main {
     public static void main(String[] args) {
 
         List<PetriNet> petriNets = PnmlParser.parsePnml("src/main/resources/minimal_global.pnml");
-        GlobalToLocalNetsPostProcessor.disconnectNets(petriNets.get(0));
 
+        List<List<PetriNet>> disconnectedPetriNets = new ArrayList<>();
+
+        petriNets.forEach(pn -> disconnectedPetriNets.add(GlobalToLocalNetsPostProcessor.disconnectNets(pn)));
     }
 }
\ No newline at end of file
-- 
GitLab