From 664c0f434cf32fac90f099c61f359d5ff1ed4890 Mon Sep 17 00:00:00 2001
From: Paul Bartetzky <paul.bartetzky@mailbox.tu-dresden.de>
Date: Tue, 8 Oct 2024 22:04:42 +0200
Subject: [PATCH] fix references

---
 glsp-client/tasklist-glsp/css/diagram.css     | 21 ++++-
 .../src/ui-extensions/active-pages-overlay.ts |  6 +-
 .../Simulation/FireTransitionExecutor.java    | 87 +++++++++++++++----
 .../javaemf/TaskListDiagramModule.java        | 10 ++-
 .../javaemf/TinaMenu/PNMLFlattener.java       |  1 +
 .../TinaMenu/RunTinaActionHandler.java        |  1 -
 .../CreateReferenceHandler.java               | 17 +++-
 .../javaemf/model/ModelAccessUtil.java        | 28 ++++++
 .../javaemf/model/TaskListGModelFactory.java  |  4 +-
 .../model/TaskListSourceModelStorage.java     | 62 -------------
 .../validators/CyclicReferencesValidator.java | 35 ++++++++
 11 files changed, 181 insertions(+), 91 deletions(-)
 create mode 100644 glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/validators/CyclicReferencesValidator.java

diff --git a/glsp-client/tasklist-glsp/css/diagram.css b/glsp-client/tasklist-glsp/css/diagram.css
index e308899..42befd8 100644
--- a/glsp-client/tasklist-glsp/css/diagram.css
+++ b/glsp-client/tasklist-glsp/css/diagram.css
@@ -58,6 +58,21 @@ svg {
     outline-color: #000000;
 }
 
+.place {
+    fill: #f1bd6c;
+    outline-style: solid;
+    outline-width: 1px;
+    outline-color: #000000;
+    border-radius: 1000px;
+}
+
+.transition {
+    fill: #f1bd6c;
+    outline-style: solid;
+    outline-width: 1px;
+    outline-color: #000000;
+}
+
 .ref-place {
     fill: #f1bd6c;
     outline-style: dashed;
@@ -86,7 +101,7 @@ svg {
 }
 
 .topic-node {
-    fill: #4787e0;
+    fill: #83b6dd;
 }
 
 .topic-link {
@@ -94,11 +109,11 @@ svg {
 }
 
 .service-node {
-    fill: #34cd1c;
+    fill: #89d681;
 }
 
 .service-channel {
-    fill: #299d17;
+    fill: #58cb47;
 }
 
 .service-channel-link {
diff --git a/glsp-client/tasklist-glsp/src/ui-extensions/active-pages-overlay.ts b/glsp-client/tasklist-glsp/src/ui-extensions/active-pages-overlay.ts
index dd3a75c..ab2ff1d 100644
--- a/glsp-client/tasklist-glsp/src/ui-extensions/active-pages-overlay.ts
+++ b/glsp-client/tasklist-glsp/src/ui-extensions/active-pages-overlay.ts
@@ -73,8 +73,12 @@ export class ActivePagesOverlay extends AbstractUIExtension implements IDiagramS
             if (pageNode.children[0] instanceof GLabel) {
                 text = pageNode.children[0].text;
             }
+            let icon = 'chrome-minimize';
+            if (hasArgs(pageNode) && pageNode.args.hidden) {
+                icon = 'add';
+            }
 
-            buttonContainer.appendChild(this.createPageButton('btn_center_diagram', text, 'screen-normal', pageNode));
+            buttonContainer.appendChild(this.createPageButton('btn_center_diagram', text, icon, pageNode));
         });
         return buttonContainer;
     }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/Simulation/FireTransitionExecutor.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/Simulation/FireTransitionExecutor.java
index f1979f0..83f3012 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/Simulation/FireTransitionExecutor.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/Simulation/FireTransitionExecutor.java
@@ -7,9 +7,7 @@ import org.eclipse.glsp.example.javaemf.operation.AddDiNeROSTokenOperation;
 import org.eclipse.glsp.example.javaemf.operation.DeleteDiNeROSTokenOperation;
 import org.eclipse.glsp.example.javaemf.validators.InputSignalValidator;
 import org.eclipse.glsp.server.actions.ActionDispatcher;
-import org.pnml.emf.ptnet.Arc;
-import org.pnml.emf.ptnet.Place;
-import org.pnml.emf.ptnet.Transition;
+import org.pnml.emf.ptnet.*;
 
 import java.util.Map;
 
@@ -30,9 +28,14 @@ public class FireTransitionExecutor {
         return isSignalActive(transition) && enoughTokensInPlaces(transition);
     }
 
-    public boolean enoughTokensInPlaces(Transition transition) {
+    public boolean enoughTokensInPlaces(TransitionNode transition) {
         for(Arc arc : transition.getInArcs()){
-            Place place = (Place) arc.getSource();
+            PlaceNode sourceNode = (PlaceNode) arc.getSource();
+            Place place = modelAccessUtil.resolveReferencePlace(sourceNode);
+            if (place == null){
+                // the refPlace has no reference and is therefore ignored
+                continue;
+            }
             int tokensInPlace = modelAccessUtil.getTokensInPlace(place);
             int arcWeight = modelAccessUtil.getArcWeight(arc);
             if(modelAccessUtil.isInhibitorArc(arc)){
@@ -46,6 +49,12 @@ public class FireTransitionExecutor {
             }
 
         }
+
+        for (RefTransition refTransition : transition.getReferencingTransitions()){
+            if (!enoughTokensInPlaces(refTransition)){
+                return false;
+            }
+        }
         return true;
     }
 
@@ -65,18 +74,26 @@ public class FireTransitionExecutor {
     }
 
     public boolean isSignalActive(Transition transition) {
-        System.out.println(inputSignalValidator.evaluateCNF(modelAccessUtil.getInputSignalClause(transition)));
         return inputSignalValidator.evaluateCNF(modelAccessUtil.getInputSignalClause(transition));
     }
 
-    public void fireTransition(Transition transition) {
-        if(!isFireable(transition)) {
+    // takes a place or a refplace and returns the place or the place the redplace references
+
+
+    public void fireTransition(TransitionNode transition) {
+        if(transition instanceof Transition transition1 && !isFireable(transition1)) {
             return;
         }
 
         transition.getInArcs().forEach(arc -> {
             if(!modelAccessUtil.isInhibitorArc(arc) && !modelAccessUtil.isReadArc(arc)){
-                Place place = (Place) arc.getSource();
+                PlaceNode sourceNode = (PlaceNode) arc.getSource();
+                Place place = modelAccessUtil.resolveReferencePlace(sourceNode);
+                if (place == null){
+                    // the refPlace has no reference and is therefore ignored
+                    return; //only returns the lambda
+                }
+
                 int tokensInPlace = modelAccessUtil.getTokensInPlace(place);
                 int arcWeight = modelAccessUtil.getArcWeight(arc);
 
@@ -86,16 +103,25 @@ public class FireTransitionExecutor {
 
         transition.getOutArcs().forEach(arc -> {
             if(!modelAccessUtil.isInhibitorArc(arc) && !modelAccessUtil.isReadArc(arc)){
-                Place place = (Place) arc.getTarget();
+                PlaceNode sourceNode = (PlaceNode) arc.getTarget();
+                Place place = modelAccessUtil.resolveReferencePlace(sourceNode);
+                if (place == null){
+                    // the refPlace has no reference and is therefore ignored
+                    return; //only returns the lambda
+                }
+
                 int tokensInPlace = modelAccessUtil.getTokensInPlace(place);
                 int arcWeight = modelAccessUtil.getArcWeight(arc);
 
                 modelState.getSimulationMarking().put(place.getId(), tokensInPlace + arcWeight);
             }
-
         });
+        for (RefTransition refTransition : transition.getReferencingTransitions()) {
+            fireTransition(refTransition);
+        }
     }
 
+
     public void fireTransitionWithBalloonToken(Transition transition, Map<String, String[]> placeTokensMap) {
         if(!isFireable(transition)) {
             return;
@@ -103,9 +129,21 @@ public class FireTransitionExecutor {
 
         StringBuilder newToken = new StringBuilder();
 
+        gatherAndRemoveTokens(transition, placeTokensMap, newToken);
+
+        placeTokens(transition, newToken);
+    }
+
+    protected void gatherAndRemoveTokens(TransitionNode transition, Map<String, String[]> placeTokensMap, StringBuilder newToken){
         for (Arc arc : transition.getInArcs()){
             if(!modelAccessUtil.isInhibitorArc(arc) && !modelAccessUtil.isReadArc(arc)){
-                Place place = (Place) arc.getSource();
+                PlaceNode sourceNode = (PlaceNode) arc.getSource();
+                Place place = modelAccessUtil.resolveReferencePlace(sourceNode);
+                if (place == null){
+                    // the refPlace has no reference and is therefore ignored
+                    continue;
+                }
+
                 String[] tokens = placeTokensMap.get(place.getId());
                 if(tokens == null){
                     tokens = new String[0];
@@ -124,19 +162,36 @@ public class FireTransitionExecutor {
                     i++;
                 }
             }
+        }
+        for (RefTransition refTransition : transition.getReferencingTransitions()){
+            // recursively calls this method for all referencing transitions
+            gatherAndRemoveTokens(refTransition, placeTokensMap, newToken);
+        }
+    }
 
-        };
-
+    protected void placeTokens(TransitionNode transition, StringBuilder newToken){
         for (Arc arc : transition.getOutArcs()){
             if(!modelAccessUtil.isInhibitorArc(arc) && !modelAccessUtil.isReadArc(arc)){
-                Place place = (Place) arc.getTarget();
+                PlaceNode sourceNode = (PlaceNode) arc.getTarget();
+                Place place = modelAccessUtil.resolveReferencePlace(sourceNode);
+                if (place == null){
+                    // the refPlace has no reference and is therefore ignored
+                    continue;
+                }
+
                 int arcWeight = modelAccessUtil.getArcWeight(arc);
 
                 for (int i = 0; i < arcWeight; i++){
                     actionDispatcher.dispatch(new AddDiNeROSTokenOperation(place.getId(), newToken.toString()));
                 }
             }
-        };
+        }
+        for (RefTransition refTransition : transition.getReferencingTransitions()){
+            // recursively calls this method for all referencing transitions
+            placeTokens(refTransition, newToken);
+        }
     }
 
+
+
 }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java
index a80877d..2aa5041 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TaskListDiagramModule.java
@@ -28,12 +28,9 @@ import org.eclipse.glsp.example.javaemf.handler.DiNeROS.ElementCreation.*;
 import org.eclipse.glsp.example.javaemf.handler.EdgeAndRefCreation.*;
 import org.eclipse.glsp.example.javaemf.handler.NodeCreation.*;
 import org.eclipse.glsp.example.javaemf.Simulation.FireTransitionExecutor;
-import org.eclipse.glsp.example.javaemf.validators.PnmlLabelEditValidator;
+import org.eclipse.glsp.example.javaemf.validators.*;
 import org.eclipse.glsp.example.javaemf.model.*;
 import org.eclipse.glsp.example.javaemf.palette.TaskListToolPaletteItemProvider;
-import org.eclipse.glsp.example.javaemf.validators.InputSignalValidator;
-import org.eclipse.glsp.example.javaemf.validators.PNMLEdgeCreationChecker;
-import org.eclipse.glsp.example.javaemf.validators.SignalClauseMenuValidator;
 import org.eclipse.glsp.server.actions.ActionDispatcher;
 import org.eclipse.glsp.server.actions.ActionHandler;
 import org.eclipse.glsp.server.di.MultiBinding;
@@ -189,4 +186,9 @@ public class TaskListDiagramModule extends EMFNotationDiagramModule {
       return PNMLFlattener.class;
    }
 
+   protected Class<? extends CyclicReferencesValidator> bindCyclicReferencesValidator() {
+      return CyclicReferencesValidator.class;
+   }
+
+
 }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/PNMLFlattener.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/PNMLFlattener.java
index f85a3dc..159e8bb 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/PNMLFlattener.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/PNMLFlattener.java
@@ -188,6 +188,7 @@ public class PNMLFlattener {
             reverseArc.setSource(arc.getTarget());
             reverseArc.setTarget(arc.getSource());
             reverseArc.setInscription(arc.getInscription());
+            reverseArc.setId(arc.getId() + "_reverse");
             mainPage.getArc().add(reverseArc);
         });
     }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/RunTinaActionHandler.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/RunTinaActionHandler.java
index f114be7..2a430a9 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/RunTinaActionHandler.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/TinaMenu/RunTinaActionHandler.java
@@ -67,7 +67,6 @@ public class RunTinaActionHandler extends AbstractActionHandler<RunTinaAction> {
         URL location = RunTinaActionHandler.class.getProtectionDomain().getCodeSource().getLocation();
         String tinaLocation = location.getFile()  + "/../../../libs/tina-3.8.0/bin";
 
-        System.out.println(tinaLocation);
 
         ProcessBuilder processBuilder = new ProcessBuilder();
 
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/EdgeAndRefCreation/CreateReferenceHandler.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/EdgeAndRefCreation/CreateReferenceHandler.java
index 66d321a..36546e9 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/EdgeAndRefCreation/CreateReferenceHandler.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/handler/EdgeAndRefCreation/CreateReferenceHandler.java
@@ -6,11 +6,11 @@ import org.eclipse.emf.ecore.EReference;
 import org.eclipse.emf.edit.command.SetCommand;
 import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.glsp.example.javaemf.PNMLModelTypes;
+import org.eclipse.glsp.example.javaemf.validators.CyclicReferencesValidator;
 import org.eclipse.glsp.server.emf.EMFCreateOperationHandler;
 import org.eclipse.glsp.server.emf.EMFIdGenerator;
 import org.eclipse.glsp.server.operations.CreateEdgeOperation;
-import org.pnml.emf.ptnet.Node;
-import org.pnml.emf.ptnet.PtnetPackage;
+import org.pnml.emf.ptnet.*;
 
 import java.util.Optional;
 
@@ -20,6 +20,9 @@ public class CreateReferenceHandler extends EMFCreateOperationHandler<CreateEdge
     @Inject
     protected EMFIdGenerator idGenerator;
 
+    @Inject
+    protected CyclicReferencesValidator cyclicReferencesValidator;
+
     public CreateReferenceHandler() {
         super(PNMLModelTypes.REFERENCE);
     }
@@ -40,12 +43,22 @@ public class CreateReferenceHandler extends EMFCreateOperationHandler<CreateEdge
 
         if(source.eClass().equals(PtnetPackage.Literals.REF_PLACE)){
             featureLiteral = PtnetPackage.Literals.REF_PLACE__REF;
+            if(cyclicReferencesValidator.wouldBeCyclicReference((RefPlace) source, (PlaceNode) target)){
+                //would be a cyclic reference
+                return Optional.empty();
+            }
         } else if (source.eClass().equals(PtnetPackage.Literals.REF_TRANSITION)){
             featureLiteral = PtnetPackage.Literals.REF_TRANSITION__REF;
+            if(cyclicReferencesValidator.wouldBeCyclicReference((RefTransition) source, (TransitionNode) target)){
+                //would be a cyclic reference
+                return Optional.empty();
+            }
         } else {
             return Optional.empty();
         }
 
+
+
         return Optional.of(createReference(source, target, featureLiteral));
     }
 
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java
index 5384271..1a51793 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/ModelAccessUtil.java
@@ -61,6 +61,34 @@ public class ModelAccessUtil {
         return  element.getName().getText();
     }
 
+    public Place resolveReferencePlace (PlaceNode placeNode){
+        if (placeNode instanceof Place place){
+            return place;
+        }
+
+        while (placeNode instanceof RefPlace refPlace){
+            placeNode = refPlace.getRef();
+        }
+        if (placeNode instanceof Place place){
+            return place;
+        }
+        return null;
+    }
+
+    public Transition resolveReferenceTransition (TransitionNode transitionNode){
+        if (transitionNode instanceof Transition transition){
+            return transition;
+        }
+
+        while (transitionNode instanceof RefTransition refTransition){
+            transitionNode = refTransition.getRef();
+        }
+        if (transitionNode instanceof Transition transition){
+            return transition;
+        }
+        return null;
+    }
+
     public boolean isTopicTransition(Transition transition){
         if(transition.getToolspecific() == null || transition.getToolspecific().isEmpty()){
             return false;
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java
index a2a46e6..bff28b8 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListGModelFactory.java
@@ -76,7 +76,7 @@ public class TaskListGModelFactory extends EMFNotationGModelFactory {
 
       GNodeBuilder placeNodeBuilder = new GNodeBuilder(PNMLModelTypes.PLACE)
           .id(idGenerator.getOrCreateId(place))
-          .addCssClass("pnml-node")
+          .addCssClass("place")
           .add(new GLabelBuilder(PNMLModelTypes.MARKING_LABEL)
               .text(Integer.toString(marking))
               .id(place.getId() + "_marking")
@@ -143,7 +143,7 @@ public class TaskListGModelFactory extends EMFNotationGModelFactory {
 
       GNodeBuilder transitionNodeBuilder = new GNodeBuilder(PNMLModelTypes.TRANSITION)
           .id(idGenerator.getOrCreateId(transition))
-          .addCssClass("pnml-node")
+          .addCssClass("transition")
           .layout(GConstants.Layout.HBOX, Map.of(GLayoutOptions.KEY_PADDING_LEFT, 5));
 
       applyNodeShape(transition, PNMLModelTypes.DefaultSizes.TransitionWidth, PNMLModelTypes.DefaultSizes.TransitionHeight, transitionNodeBuilder);
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListSourceModelStorage.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListSourceModelStorage.java
index f885063..638418d 100644
--- a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListSourceModelStorage.java
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/model/TaskListSourceModelStorage.java
@@ -40,68 +40,6 @@ public class TaskListSourceModelStorage extends EMFNotationSourceModelStorage {
    protected void doLoadSourceModel(final ResourceSet resourceSet, final URI sourceURI,
                                     final RequestModelAction action) {
       loadSemanticModel(resourceSet, sourceURI, action);
-      //loadNotationModel(resourceSet, sourceURI, action);
-
-      //startMQTTClient();
-   }
-
-
-   /*
-   protected void addNodeGraphicsToModel() {
-      TreeIterator<EObject> modelIterator = modelState.getSemanticModel().eAllContents();
-
-      while(modelIterator.hasNext()) {
-         EObject modelElement = modelIterator.next();
-
-         if(PtnetPackage.eINSTANCE.getNode().isSuperTypeOf(modelElement.eClass())){
-            addNodeGraphicsToNode((Node) modelElement);
-         } else if (PtnetPackage.eINSTANCE.getPage().isSuperTypeOf(modelElement.eClass())) {
-            addNodeGraphicsToPage((Page) modelElement);
-         }
-      }
    }
 
-   protected void addNodeGraphicsToNode(Node node) {
-
-
-      if(node.getNodegraphics() == null) {
-         NodeGraphics nodeGraphics = PtnetFactory.eINSTANCE.createNodeGraphics();
-
-         Position pos = PtnetFactory.eINSTANCE.createPosition();
-         pos.setX(0);
-         pos.setY(0);
-         nodeGraphics.setPosition(pos);
-
-         Dimension dim = PtnetFactory.eINSTANCE.createDimension();
-         dim.setX(70);
-         dim.setY(70);
-         nodeGraphics.setDimension(dim);
-
-         node.setNodegraphics(nodeGraphics);
-
-      }
-   }
-
-   protected void addNodeGraphicsToPage(Page node) {
-
-   }
-
-
-
-*/
-
-
-
-   /*
-   // Empty method body prevents attempt to load notation model file
-   // If a notation file should be used, the empty method can be removed thus restoring the behavior of the super class
-   @Override
-   protected void loadNotationModel(final ResourceSet resourceSet, final URI sourceURI,
-                                    final RequestModelAction action) {
-
-   }
-   */
-
-
-
 }
diff --git a/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/validators/CyclicReferencesValidator.java b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/validators/CyclicReferencesValidator.java
new file mode 100644
index 0000000..85d1aaf
--- /dev/null
+++ b/glsp-server/src/main/java/org/eclipse/glsp/example/javaemf/validators/CyclicReferencesValidator.java
@@ -0,0 +1,35 @@
+package org.eclipse.glsp.example.javaemf.validators;
+
+import com.google.inject.Inject;
+import org.eclipse.glsp.example.javaemf.model.ExtendedModelState;
+import org.eclipse.glsp.example.javaemf.model.ModelAccessUtil;
+import org.pnml.emf.ptnet.*;
+
+import java.util.Objects;
+
+public class CyclicReferencesValidator {
+    @Inject
+    protected ExtendedModelState modelState;
+
+    public boolean wouldBeCyclicReference(RefPlace source, PlaceNode target){
+        PlaceNode refedPlace = target;
+        while (refedPlace instanceof RefPlace refPlace){
+            if(Objects.equals(refPlace, source)){
+                return true;
+            }
+            refedPlace = refPlace.getRef();
+        }
+        return false;
+    }
+
+    public boolean wouldBeCyclicReference(RefTransition source, TransitionNode target){
+        TransitionNode refedTransition = target;
+        while (refedTransition instanceof RefTransition refTransition){
+            if(Objects.equals(refTransition, source)){
+                return true;
+            }
+            refedTransition = refTransition.getRef();
+        }
+        return false;
+    }
+}
-- 
GitLab