From c83abc312fbc348db55540d6b9e165b730d2aaf9 Mon Sep 17 00:00:00 2001
From: SebastianEbert <sebastian.ebert@tu-dresden.de>
Date: Mon, 23 Oct 2023 16:28:02 +0200
Subject: [PATCH] feature: orphan-place service calls

---
 .../balloonMarking/BalloonExecution.jadd      | 20 +++++++-
 .../de/tudresden/inf/st/pnml/engine/Main.java | 28 +++++++----
 .../inf/st/pnml/engine/example/Server.java    | 34 --------------
 .../Client.java => fake/FakeClientNode.java}  |  6 +--
 .../st/pnml/engine/fake/FakeServerNode.java   | 44 ++++++++++++++++++
 .../inf/st/pnml/engine/ros/DiNeRosNode.java   | 46 +++++++++++--------
 6 files changed, 110 insertions(+), 68 deletions(-)
 delete mode 100644 src/main/java/de/tudresden/inf/st/pnml/engine/example/Server.java
 rename src/main/java/de/tudresden/inf/st/pnml/engine/{example/Client.java => fake/FakeClientNode.java} (94%)
 create mode 100644 src/main/java/de/tudresden/inf/st/pnml/engine/fake/FakeServerNode.java

diff --git a/src/main/jastadd/engine/balloonMarking/BalloonExecution.jadd b/src/main/jastadd/engine/balloonMarking/BalloonExecution.jadd
index e0397f7..f934af4 100644
--- a/src/main/jastadd/engine/balloonMarking/BalloonExecution.jadd
+++ b/src/main/jastadd/engine/balloonMarking/BalloonExecution.jadd
@@ -1,5 +1,6 @@
 import de.tudresden.inf.st.pnml.engine.event.*;
 import de.tudresden.inf.st.pnml.engine.execution.TransitionHandlerService;
+import de.tudresden.inf.st.pnml.engine.ros.DiNeRosNode;
 
 import java.util.function.Function;
 
@@ -23,8 +24,25 @@ aspect BalloonExecution{
         syn boolean TransitionSelectionResult.isFiringSelectionNone()=false;
         eq FiringSelectionNone.isFiringSelectionNone()=true;
 
+        public boolean BalloonMarking.callServiceIfRequest(BalloonMarkedPlace bmp, DiNeRosNode node ) {
+
+            HashMap<String, ArrayList<String>> reqMap = getPetriNet().getChannelElemensByKey(PnmlConstants.CHANNEL_PLACE_TYPE_CLIENT_REQ_KEY);
+
+            for(Map.Entry<String, ArrayList<String>> entry : reqMap.entrySet()){
+                for(String s : entry.getValue()){
+                    if(s.equals(bmp.getPlace().getId()) ||
+                        (bmp.getPlace().getId().startsWith(s) && bmp.getPlace().getId().contains("-INSTANCE-"))){
+                        System.out.println("Calling service from orphan request place: " + bmp.getPlace().getId());
+                        node.notify(new DiNeRosEvent(DiNeRosEventTypes.NOTIFICATION_SERVICE_REQ_CLIENT, bmp.getPlace().getId()));
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
         public Optional<BalloonMarking> BalloonMarking.fireTransition(Transition transition, BalloonCallbackStorage callbackStorage,
-            InputSignalConnector inputSignalConnector,de.tudresden.inf.st.pnml.engine.ros.DiNeRosNode node, boolean requireFlush) {
+            InputSignalConnector inputSignalConnector, DiNeRosNode node, boolean requireFlush) {
 
               //if(!transition.asDinerosTransition().getStaticTransitionInformation().isSignalTransitionInformation()) return Optional.empty();
 
diff --git a/src/main/java/de/tudresden/inf/st/pnml/engine/Main.java b/src/main/java/de/tudresden/inf/st/pnml/engine/Main.java
index 3c289d7..48b5da8 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/engine/Main.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/engine/Main.java
@@ -1,7 +1,7 @@
 package de.tudresden.inf.st.pnml.engine;
 
-import de.tudresden.inf.st.pnml.engine.example.Client;
-import de.tudresden.inf.st.pnml.engine.example.Server;
+import de.tudresden.inf.st.pnml.engine.fake.FakeClientNode;
+import de.tudresden.inf.st.pnml.engine.fake.FakeServerNode;
 import org.ros.node.DefaultNodeMainExecutor;
 import org.ros.node.NodeConfiguration;
 import org.ros.node.NodeMainExecutor;
@@ -18,20 +18,28 @@ public class Main {
 
     public static void main(java.lang.String[] args) {
 
-        Server server = new Server();
-        Client client = new Client();
-        nodeConfiguration.setMasterUri(URI.create(ROS_MASTER_URI));
+        //Server server = new Server();
+        // FakeClientNode client = new FakeClientNode();
+        // nodeConfiguration.setMasterUri(URI.create(ROS_MASTER_URI));
 
-        /*System.out.println("---- STARTING SERVER ----");
-        new Thread(() -> nodeMainExecutor.execute(server, nodeConfiguration)) {{start();}};
+        //System.out.println("---- STARTING SERVER ----");
+        //new Thread(() -> nodeMainExecutor.execute(server, nodeConfiguration)) {{start();}};
+
+
+
+     /*   System.out.println("---- STARTING sampleService0 ----");
+        new Thread(() -> nodeMainExecutor.execute(new FakeServerNode("sampleService0", "sampleServiceNode0"), nodeConfiguration)) {{start();}};
 
         try {
             Thread.sleep(3000);
         } catch (InterruptedException e) {
             e.printStackTrace();
-        }*/
+        }
+
+       // System.out.println("---- STARTING CLIENT ----");
+      //  new Thread(() -> nodeMainExecutor.execute(client, nodeConfiguration)) {{start();}};
 
-        System.out.println("---- STARTING CLIENT ----");
-        new Thread(() -> nodeMainExecutor.execute(client, nodeConfiguration)) {{start();}};
+        System.out.println("---- STARTING sampleService1 ----");
+        new Thread(() -> nodeMainExecutor.execute(new FakeServerNode("sampleService1", "sampleServiceNode1"), nodeConfiguration)) {{start();}};*/
     }
 }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/engine/example/Server.java b/src/main/java/de/tudresden/inf/st/pnml/engine/example/Server.java
deleted file mode 100644
index d037ac0..0000000
--- a/src/main/java/de/tudresden/inf/st/pnml/engine/example/Server.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.tudresden.inf.st.pnml.engine.example;
-
-import org.ros.namespace.GraphName;
-import org.ros.node.AbstractNodeMain;
-import org.ros.node.ConnectedNode;
-import org.ros.node.service.ServiceResponseBuilder;
-import rosjava_srv.StringService;
-import rosjava_srv.StringServiceRequest;
-import rosjava_srv.StringServiceResponse;
-
-public class Server extends AbstractNodeMain {
-
-    @Override
-    public GraphName getDefaultNodeName() {
-        return GraphName.of("rosjava_srv_test/server");
-    }
-
-    @Override
-    public void onStart(final ConnectedNode connectedNode) {
-        connectedNode.newServiceServer("sampleService", StringService._TYPE,
-                (ServiceResponseBuilder<StringServiceRequest, StringServiceResponse>) (request, response) -> {
-
-                    System.out.println("Service Input: \"" + request.getInput() + "\"");
-                    try {
-                        Thread.sleep(10000);
-                    } catch (InterruptedException e) {
-                        e.printStackTrace();
-                    }
-                    System.out.println("Finished sleep.");
-                    response.setOutput("...");
-
-                });
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/pnml/engine/example/Client.java b/src/main/java/de/tudresden/inf/st/pnml/engine/fake/FakeClientNode.java
similarity index 94%
rename from src/main/java/de/tudresden/inf/st/pnml/engine/example/Client.java
rename to src/main/java/de/tudresden/inf/st/pnml/engine/fake/FakeClientNode.java
index 754b0fc..98a0242 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/engine/example/Client.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/engine/fake/FakeClientNode.java
@@ -1,4 +1,4 @@
-package de.tudresden.inf.st.pnml.engine.example;
+package de.tudresden.inf.st.pnml.engine.fake;
 
 import org.ros.exception.RemoteException;
 import org.ros.exception.RosRuntimeException;
@@ -12,7 +12,7 @@ import rosjava_srv.StringService;
 import rosjava_srv.StringServiceRequest;
 import rosjava_srv.StringServiceResponse;
 
-public class Client extends AbstractNodeMain {
+public class FakeClientNode extends AbstractNodeMain {
 
     @Override
     public GraphName getDefaultNodeName() {
@@ -30,7 +30,7 @@ public class Client extends AbstractNodeMain {
 
         ServiceClient<StringServiceRequest, StringServiceResponse> serviceClient;
         try {
-            serviceClient = connectedNode.newServiceClient("sampleService", StringService._TYPE);
+            serviceClient = connectedNode.newServiceClient("sampleService0", StringService._TYPE);
         } catch (ServiceNotFoundException e) {
             throw new RosRuntimeException(e);
         }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/engine/fake/FakeServerNode.java b/src/main/java/de/tudresden/inf/st/pnml/engine/fake/FakeServerNode.java
new file mode 100644
index 0000000..214ec08
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/engine/fake/FakeServerNode.java
@@ -0,0 +1,44 @@
+package de.tudresden.inf.st.pnml.engine.fake;
+
+import org.ros.namespace.GraphName;
+import org.ros.node.AbstractNodeMain;
+import org.ros.node.ConnectedNode;
+import org.ros.node.service.ServiceResponseBuilder;
+import rosjava_srv.StringService;
+import rosjava_srv.StringServiceRequest;
+import rosjava_srv.StringServiceResponse;
+
+public class FakeServerNode extends AbstractNodeMain {
+
+    private java.lang.String serviceName;
+    private java.lang.String nodeName;
+
+    public FakeServerNode(String serviceName, String nodeName) {
+        this.serviceName = serviceName;
+        this.nodeName = nodeName;
+    }
+
+    @Override
+    public GraphName getDefaultNodeName() {
+        return GraphName.of("fake/" + nodeName);
+    }
+
+    @Override
+    public void onStart(final ConnectedNode connectedNode) {
+
+        System.out.println("[" + nodeName + "] Starting node.");
+
+        connectedNode.newServiceServer(serviceName, StringService._TYPE,
+                (ServiceResponseBuilder<StringServiceRequest, StringServiceResponse>) (request, response) -> {
+
+                    System.out.println("[" + nodeName + "] Service Input: \"" + request.getInput() + "\"");
+                    try {
+                        Thread.sleep(4000);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                    System.out.println("[" + nodeName + "] Finished sleep.");
+                    response.setOutput(request.getInput());
+                });
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/engine/ros/DiNeRosNode.java b/src/main/java/de/tudresden/inf/st/pnml/engine/ros/DiNeRosNode.java
index fa4e3e8..262fa78 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/engine/ros/DiNeRosNode.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/engine/ros/DiNeRosNode.java
@@ -63,7 +63,17 @@ public abstract class DiNeRosNode extends AbstractNodeMain {
                                         List<Map<java.lang.String, Object>>> processTokenFunction) {
 
         TransitionHandler transitionHandler = new TransitionHandler(priority, processTokenFunction);
+
+        if(petriNet.getTransitionById(transitionId) == null){
+            return;
+        }
+
         BalloonTransition balloonTransition = callbackStorage.resolveBalloonTransition(petriNet.getTransitionById(transitionId));
+
+        if(balloonTransition == null){
+            return;
+        }
+
         balloonTransition.getTransitionHandlers().add(transitionHandler);
     }
 
@@ -164,13 +174,23 @@ public abstract class DiNeRosNode extends AbstractNodeMain {
 
 
         java.lang.String serviceName = petriNet.getPortNameByPlaceId(originalId);
-        java.lang.String cResPlaceId = petriNet.getServiceClientResponsePlaceId(originalId) + "-INSTANCE-" + placeId.split("-")[split.length - 1];
+        java.lang.String cResPlaceId;
+
+        if(split.length > 1){
+            cResPlaceId = petriNet.getServiceClientResponsePlaceId(originalId) + "-INSTANCE-" + placeId.split("-")[split.length - 1];
+        } else {
+            cResPlaceId = petriNet.getServiceClientResponsePlaceId(originalId);
+        }
+
         Place targetPlace = petriNet.getPlaceById(cResPlaceId);
         Place sourcePlace = petriNet.getPlaceById(placeId);
         BalloonMarkedPlace bmpSource = this.marking.resolveBalloonPlace(sourcePlace);
         BalloonMarkedPlace bmpTarget = this.marking.resolveBalloonPlace(targetPlace);
 
+        DiNeRosNode self = this;
+
         try {
+            System.out.println("[DiNeROS-Node] [" + nodeName + "] Creating client for service: " + serviceName);
             serviceClient = connectedNode.newServiceClient(serviceName, StringService._TYPE);
             final StringServiceRequest request = serviceClient.newMessage();
             request.setInput(bmpSource.getBalloonMarking(0).getValue());
@@ -181,19 +201,20 @@ public abstract class DiNeRosNode extends AbstractNodeMain {
                 public void onSuccess(StringServiceResponse stringServiceResponse) {
                     bmpSource.getBalloonMarking(0).removeSelf();
                     bmpTarget.addBalloonMarking(new BalloonToken(stringServiceResponse.getOutput(), System.currentTimeMillis()));
+                    marking.callServiceIfRequest(bmpTarget, self);
+                    self.notify(new DiNeRosEvent(DiNeRosEventTypes.NOTIFICATION_MARKING_CHANGE));
+                    serviceClient.shutdown();
                 }
 
                 @Override
                 public void onFailure(RemoteException e) {
                     System.err.println("Error while calling: token will not be removed!");
+                    serviceClient.shutdown();
                 }
             });
 
-            serviceClient.shutdown();
-            this.notify(new DiNeRosEvent(DiNeRosEventTypes.NOTIFICATION_MARKING_CHANGE));
-
         } catch (ServiceNotFoundException e) {
-            System.err.println("Error while calling service. ");
+            System.err.println("Error while calling service.");
         }
     }
 
@@ -338,20 +359,6 @@ public abstract class DiNeRosNode extends AbstractNodeMain {
                         }
                     }
 
-                   /* for(Transition t : petriNet.allTransitions()){
-                        System.out.println("Checking Transition: " + t.getId());
-                        for(Arc a : petriNet.allArcs()){
-                            if(a.getTarget().getId().equals(t.getId())){
-                                System.out.println(">> Match: " + a.getSource().getId());
-                            }
-                        }
-
-                        for(Place p1 : t.incomingPlaces()){
-                            System.out.println(">> Checking incoming place: " + p1.getId());
-
-                        }
-                    }*/
-
                     connectedNode.newServiceServer(key, StringService._TYPE,
                             (ServiceResponseBuilder<StringServiceRequest, StringServiceResponse>) (request, response) -> {
 
@@ -436,7 +443,6 @@ public abstract class DiNeRosNode extends AbstractNodeMain {
                     this.notify(new DiNeRosEvent(DiNeRosEventTypes.NOTIFICATION_MARKING_CHANGE));
 
                 }, petriNet.getChannelElementLimitById(placeId));
-                //dinerosSubscribers.put(targetPlace, subscriber);
             }
         }
 
-- 
GitLab