Browse Source

Merge branch 'master' into dev

Arkadiusz Ryś 1 year ago
parent
commit
7e6eb25df7

+ 13 - 58
flake.lock

@@ -5,11 +5,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1681202837,
-        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
         "type": "github"
       },
       "original": {
@@ -20,8 +20,12 @@
     },
     "mvn2nix": {
       "inputs": {
-        "nixpkgs": "nixpkgs",
-        "utils": "utils"
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "utils": [
+          "flake-utils"
+        ]
       },
       "locked": {
         "lastModified": 1629170129,
@@ -39,27 +43,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1684049129,
-        "narHash": "sha256-7WB9LpnPNAS8oI7hMoHeKLNhRX7k3CI9uWBRSfmOCCE=",
+        "lastModified": 1692084312,
+        "narHash": "sha256-Za++qKVK6ovjNL9poQZtLKRM/re663pxzbJ+9M4Pgwg=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "0470f36b02ef01d4f43c641bbf07020bcab71bf1",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-21.05",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_2": {
-      "locked": {
-        "lastModified": 1684049129,
-        "narHash": "sha256-7WB9LpnPNAS8oI7hMoHeKLNhRX7k3CI9uWBRSfmOCCE=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "0470f36b02ef01d4f43c641bbf07020bcab71bf1",
+        "rev": "8353344d3236d3fda429bb471c1ee008857d3b7c",
         "type": "github"
       },
       "original": {
@@ -73,7 +61,7 @@
       "inputs": {
         "flake-utils": "flake-utils",
         "mvn2nix": "mvn2nix",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs"
       }
     },
     "systems": {
@@ -90,39 +78,6 @@
         "repo": "default",
         "type": "github"
       }
-    },
-    "systems_2": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "utils": {
-      "inputs": {
-        "systems": "systems_2"
-      },
-      "locked": {
-        "lastModified": 1681202837,
-        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
     }
   },
   "root": "root",

+ 6 - 2
flake.nix

@@ -2,8 +2,12 @@
   inputs = rec {
     nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
     flake-utils.url = "github:numtide/flake-utils";
-    mvn2nix.url = "github:fzakaria/mvn2nix";
-    mvn2nix.inputs = { inherit nixpkgs; utils = flake-utils; };
+
+    mvn2nix = {
+      url = "github:fzakaria/mvn2nix";
+      inputs.nixpkgs.follows = "nixpkgs";
+      inputs.utils.follows = "flake-utils";
+    };
   };
 
   outputs = { nixpkgs, mvn2nix, flake-utils, ... }:

+ 81 - 9
src/main/java/ua/be/wee/controller/EnactmentControllerMVC.java

@@ -4,6 +4,7 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.sql.Timestamp;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
@@ -25,6 +26,7 @@ import ua.be.wee.model.EnactmentController;
 import ua.be.wee.model.nodes.Activity;
 import ua.be.wee.model.nodes.Artifact;
 import ua.be.wee.model.nodes.FinalNode;
+import ua.be.wee.model.nodes.ForkJoinNode;
 import ua.be.wee.model.nodes.Node;
 import ua.be.wee.model.nodes.ports.ControlInputPort;
 import ua.be.wee.model.nodes.ports.ControlOutputPort;
@@ -114,7 +116,7 @@ public class EnactmentControllerMVC {
 		} else {
 			PM pm = controller.getPM(pmiri);			
 			PT trace = controller.createTrace(pm);
-			List<Pair<String,String>> iris = controller.findNextNodes(pm.getInitial().getIri());
+			List<Pair<String,String>> iris = controller.findNextNodes(pm.getInitial().getIri(), trace.getIri());
 			List<PMTrigger> acts = findElements(pm, iris);
 			model.addAttribute("error", false);
 			request.getSession().setAttribute("pm", pm);
@@ -144,17 +146,17 @@ public class EnactmentControllerMVC {
 			trace.setPmEnacted(pm);
 			List <Node> endActs = new ArrayList<Node>();
 			if (events.size() == 1) {
-				List<Pair<String,String>> iris = controller.findNextNodes(pm.getInitial().getIri());
+				List<Pair<String,String>> iris = controller.findNextNodes(pm.getInitial().getIri(), trace.getIri());
 				List<PMTrigger> acts = findElements(pm, iris);
 				request.getSession().setAttribute("acts",acts);
 				
 			} else {
 				endActs = findEndActs(events);
-				List<PMTrigger> acts = new ArrayList<PMTrigger>();
+				List<PMTrigger> acts = findStartActs(trace);
 				if (events.get(events.size()-1) instanceof EndActivityEvent) {
 					EndActivityEvent last = (EndActivityEvent)events.get(events.size()-1);
-					List<Pair<String,String>> iris = controller.findNextNodes(last.getRelatesTo().getIri());
-					acts = findElements(pm, iris);
+					List<Pair<String,String>> iris = controller.findNextNodes(last.getRelatesTo().getIri(), trace.getIri());
+					acts.addAll(findElements(pm, iris));
 				}
 				
 				request.getSession().setAttribute("acts",acts);
@@ -171,6 +173,77 @@ public class EnactmentControllerMVC {
     }
     
 
+	private List<PMTrigger> findStartActs(PT trace) throws Exception {
+		PM pmEnacted = trace.getPmEnacted();
+		List<Node> nodes = pmEnacted.getNodes();
+		List<PMTrigger> result = new ArrayList<PMTrigger>();
+		for (Node node : nodes) {
+			if (node instanceof ForkJoinNode) {
+				ForkJoinNode fj = ((ForkJoinNode)node);
+				if (fj.getNextNodes().size() > 1) {
+					List<Pair<String,String>> findNextNodes = controller.findNextNodes(fj.getIri(), trace.getIri());
+					List<String> actIris = new ArrayList<String>();
+					for (Pair<String,String> pair : findNextNodes) {
+						if (pair.getSnd() != null) {
+							actIris.add(pair.getSnd());
+						}
+					}
+					List<String> consider = checkTrace(trace,actIris);
+						
+					for (Iterator<Pair<String,String>> iterator = findNextNodes.iterator(); iterator.hasNext();) {
+						Pair<String,String> pair = iterator.next();
+						
+						if (pair.getSnd() == null) {
+							findNextNodes.remove(pair);
+						} else {
+							boolean found = false;
+							for (String str : consider) {
+								if (str.equals(pair.getSnd())) {
+									found = true;
+									break;
+								}
+							}
+							if (!found) {
+								iterator.remove();
+							}
+						}
+					}
+					
+					result.addAll(findElements(trace.getPmEnacted(), findNextNodes));
+					
+				}
+			}
+		}
+		return result;
+	}
+
+
+	private List<String> checkTrace(PT trace, List<String> actIris) {
+		List<Pair<String,Integer>> pairs = new ArrayList<Pair<String,Integer>>();
+		int max = 0;
+		for (String iri : actIris) {
+			int count = 0;
+			for (Event ev : trace.getEvents()) {
+				if (ev instanceof StartActivityEvent && ((StartActivityEvent)ev).getRelatesTo().getActivity().getIri().equals(iri)) {
+					count++;
+				}
+			}
+			if (count > max) {
+				max = count;
+			}
+			pairs.add(new Pair<String, Integer>(iri, count));
+		}
+		
+		List<String> result = new ArrayList<String>();
+		for (Pair<String, Integer> pair : pairs) {
+			if (pair.getSnd() < max) {
+				result.add(pair.getFst());
+			}
+		}
+		return result;
+		
+	}
+
 	private List<Node> findEndActs(List<Event> events) {
 		List<Node> result = new ArrayList<Node>();
 		for (Event event : events) {
@@ -200,10 +273,10 @@ public class EnactmentControllerMVC {
     	List<PMTrigger> acts = (List<PMTrigger>) request.getSession().getAttribute("acts");
     	List<Node> endacts = (List<Node>) request.getSession().getAttribute("endacts");
     	PMTrigger element = findPMTrigger(acts,iri);
-    	Object arts = request.getSession().getAttribute("arts");
+    	List<TraceArtifact> arts = (List<TraceArtifact>)request.getSession().getAttribute("arts");
     	if (element.getPort() != null) {
     		ControlInputPort port = (ControlInputPort)element.getPort();
-        	controller.addStartEvent(pt,port, port.getActivity(),((List<TraceArtifact>)arts));
+        	controller.addStartEvent(pt,port, port.getActivity(),arts);
         	removeElement(acts,iri);
         	endacts.add(port.getActivity());
         	request.getSession().removeAttribute("arts");
@@ -261,7 +334,7 @@ public class EnactmentControllerMVC {
 			}
 		}	
 
-    	List<Pair<String,String>> iris = controller.findNextNodes(p.getIri());
+    	List<Pair<String,String>> iris = controller.findNextNodes(p.getIri(), pt.getIri());
         acts.addAll(findElements(pm, iris));
 
     	request.getSession().setAttribute("trace", pt);
@@ -292,7 +365,6 @@ public class EnactmentControllerMVC {
     
     @RequestMapping("/inarts")
     public String selectActivity(Model model, @RequestParam String iri, HttpServletRequest request) throws Exception {
-    	PM pm = (PM)request.getSession().getAttribute("pm");
     	PT pt = (PT)request.getSession().getAttribute("trace");
     	List<PMTrigger> acts = (List<PMTrigger>) request.getSession().getAttribute("acts");
     	if (!iri.equals("1")) {

+ 3 - 3
src/main/java/ua/be/wee/model/EnactmentController.java

@@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import ua.be.wee.model.nodes.Activity;
-import ua.be.wee.model.nodes.Artifact;
 import ua.be.wee.model.nodes.ports.ControlInputPort;
 import ua.be.wee.model.nodes.ports.ControlOutputPort;
 import ua.be.wee.model.pm.PM;
@@ -40,8 +39,8 @@ public class EnactmentController {
 		return pm;
 	}
 
-	public List<Pair<String,String>> findNextNodes(String iri) {
-		return pmRepo.findNextNodes(iri); 
+	public List<Pair<String,String>> findNextNodes(String iri, String trace) throws Exception {
+		return pmRepo.findNextNodes(iri, trace); 
 	}
 
 	public PT createTrace(PM pm) throws Exception {
@@ -50,6 +49,7 @@ public class EnactmentController {
 
 	public void addStartEvent(PT pt, ControlInputPort port, Activity act, List<TraceArtifact> arts) throws Exception {
 		traceRepo.createStartEvent(pt,port,act,arts);
+		pmRepo.checkJoinSync(port.getIri(),pt.getIri());
 	}
 
 	public void addEndEvent(PT pt, List<TraceArtifact> arts, ControlOutputPort p) throws Exception {

+ 7 - 9
src/main/java/ua/be/wee/model/nodes/ForkNode.java

@@ -2,26 +2,24 @@ package ua.be.wee.model.nodes;
 
 import java.util.List;
 
-import javax.persistence.CascadeType;
 import javax.persistence.Entity;
 import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
 
 @Entity
-public class ForkNode extends Node {
+public class ForkJoinNode extends Node {
 
-	@OneToOne(cascade = CascadeType.ALL)
-	private Node previous;
+	@OneToMany
+	private List<Node> previousNodes;
 	
 	@OneToMany
 	private List<Node> nextNodes;
 
-	public Node getPrevious() {
-		return previous;
+	public List<Node> getPrevious() {
+		return previousNodes;
 	}
 
-	public void setPrevious(Node previous) {
-		this.previous = previous;
+	public void setPrevious(List<Node> previous) {
+		this.previousNodes = previous;
 	}
 
 	public List<Node> getNextNodes() {

+ 0 - 35
src/main/java/ua/be/wee/model/nodes/JoinNode.java

@@ -1,35 +0,0 @@
-package ua.be.wee.model.nodes;
-
-import java.util.List;
-
-import javax.persistence.CascadeType;
-import javax.persistence.Entity;
-import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
-
-@Entity
-public class JoinNode extends Node {
-	
-	@OneToMany
-	private List<Node> previousNodes;
-	
-	@OneToOne(cascade = CascadeType.ALL)
-	private Node next;
-
-	public List<Node> getPreviousNodes() {
-		return previousNodes;
-	}
-
-	public void setPreviousNodes(List<Node> previousNodes) {
-		this.previousNodes = previousNodes;
-	}
-
-	public Node getNext() {
-		return next;
-	}
-
-	public void setNext(Node next) {
-		this.next = next;
-	}
-
-}

+ 1 - 2
src/main/java/ua/be/wee/model/nodes/Node.java

@@ -17,9 +17,8 @@ import ua.be.wee.model.NamedElement;
 		  @Type(value = Activity.class), 
 		  @Type(value = Artifact.class),
 		  @Type(value = FinalNode.class),
-		  @Type(value = ForkNode.class),
+		  @Type(value = ForkJoinNode.class),
 		  @Type(value = InitialNode.class),
-		  @Type(value = JoinNode.class)
 		})
 @Entity
 public abstract class Node implements NamedElement {

+ 14 - 73
src/main/java/ua/be/wee/model/repository/NodeRespository.java

@@ -12,9 +12,8 @@ import org.springframework.stereotype.Repository;
 import ua.be.wee.model.nodes.Activity;
 import ua.be.wee.model.nodes.Artifact;
 import ua.be.wee.model.nodes.FinalNode;
-import ua.be.wee.model.nodes.ForkNode;
+import ua.be.wee.model.nodes.ForkJoinNode;
 import ua.be.wee.model.nodes.InitialNode;
-import ua.be.wee.model.nodes.JoinNode;
 import ua.be.wee.model.nodes.Node;
 import ua.be.wee.model.nodes.ports.ControlInputPort;
 import ua.be.wee.model.nodes.ports.ControlOutputPort;
@@ -38,7 +37,7 @@ public class NodeRespository {
 				+ "PREFIX ob: <http://ua.be/sdo2l/vocabulary/formalisms/object_diagram#>\n"
 				+ "SELECT ?node ?nodetype WHERE {\n" + "  ?pm a pm:Model ;\n" + "  	ob:hasName ?pmName ;\n"
 				+ "  	owl:sameAs <" + pm.getIri() + "> ;\n" + "  	ob:hasObject ?node .\n" + "  ?node a ?nodetype .\n"
-				+ "  FILTER (?nodetype in (pm:Initial, pm:Activity, pm:Final, pm:Join, pm:Fork, pm:Artifact)) .      \n"
+				+ "  FILTER (?nodetype in (pm:Initial, pm:Activity, pm:Final, pm:ForkJoin, pm:Artifact)) .      \n"
 				+ "}";
 		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
 		while (results.hasNext()) {
@@ -64,83 +63,25 @@ public class NodeRespository {
 				updateInitialNode(nodes, (InitialNode) node);
 			} else if (node instanceof FinalNode) {
 				updateFinalNode(nodes, (FinalNode) node);
-			} else if (node instanceof ForkNode) {
-				updateForkNode(nodes, (ForkNode) node);
-			} else if (node instanceof JoinNode) {
-				updateJoinNode(nodes, (JoinNode) node);
+			} else if (node instanceof ForkJoinNode) {
+				updateForkJoinNode(nodes, (ForkJoinNode) node);
 			}
 		}
 
 	}
 
-	private void updateJoinNode(List<Node> nodes, JoinNode node) {
-		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
-				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n" + "SELECT ?next ?nodetype ?act\n"
-				+ "WHERE { \n" + "  ?node owl:sameAs<" + node.getIri() + ">.\n" + "  ?node pm:ctrlTo ?next.\n"
-				+ "  ?next a ?nodetype ;\n"
-				+ "	FILTER (?nodetype in (pm:CtrlOutputPort, pm:Initial, pm:Final,pm:Fork, pm:Join)) \n"
-				+ "	OPTIONAL {\n" + "		?next pm:ofActivity ?act .\n" + "	}\n" + "}";
-		List<Node> list = new ArrayList<Node>();
-		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
-		while (results.hasNext()) {
-			QuerySolution soln = results.nextSolution();
-			RDFNode type = soln.get("?nodetype");
-			String nextIri;
-			if (type.toString().equals(Node.CTRL_OUTPUT_PORT_IRI)) {
-				nextIri = soln.get("?act").toString();
-			} else {
-				nextIri = soln.get("?next").toString();
-			}
-			for (Node node2 : nodes) {
-				if (node2.getIri().equals(nextIri)) {
-					list.add(node2);
-				}
-			}
-		}
-		node.setPreviousNodes(list);
-		
-		
-		query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
-				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n" 
-				+ "SELECT ?next ?nodetype ?act\n"
-				+ "WHERE { \n" + "  ?node owl:sameAs<" + node.getIri() + ">.\n" 
-				+ "  ?node pm:ctrlFrom ?next.\n"
-				+ "  ?next a ?nodetype ;\n"
-				+ "	FILTER (?nodetype in (pm:CtrlOutputPort,pm:Fork, pm:Join, pm:Initial)) \n" 
-				+ "	OPTIONAL {\n"
-				+ "		?next pm:ofActivity ?act .\n" + "	}\n" + "}";
-		results = FusekiWrapper.getInstance().execQuery(query);
-		while (results.hasNext()) {
-			QuerySolution soln = results.nextSolution();
-			RDFNode type = soln.get("?nodetype");
-			String nextIri;
-			if (type.toString().equals(Node.CTRL_OUTPUT_PORT_IRI)) {
-				nextIri = soln.get("?act").toString();
-			} else {
-				nextIri = soln.get("?next").toString();
-			}
-			for (Node node2 : nodes) {
-				if (node2.getIri().equals(nextIri)) {
-					node.setNext(node2);
-					break;
-				}
-			}
-		}
-
-		
-	}
-
-	private void updateForkNode(List<Node> nodes, ForkNode node) {
+	private void updateForkJoinNode(List<Node> nodes, ForkJoinNode node) {
 		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
 				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n" 
 				+ "SELECT ?next ?nodetype ?act\n"
 				+ "WHERE { \n" + "  ?node owl:sameAs<" + node.getIri() + ">.\n" 
 				+ "  ?node pm:ctrlFrom ?next.\n"
 				+ "  ?next a ?nodetype ;\n"
-				+ "	FILTER (?nodetype in (pm:CtrlOutputPort,pm:Fork, pm:Join, pm:Initial)) \n" 
+				+ "	FILTER (?nodetype in (pm:CtrlOutputPort,pm:ForkJoin, pm:Initial)) \n" 
 				+ "	OPTIONAL {\n"
 				+ "		?next pm:ofActivity ?act .\n" + "	}\n" + "}";
 		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
+		List<Node> list = new ArrayList<Node>();
 		while (results.hasNext()) {
 			QuerySolution soln = results.nextSolution();
 			RDFNode type = soln.get("?nodetype");
@@ -152,19 +93,19 @@ public class NodeRespository {
 			}
 			for (Node node2 : nodes) {
 				if (node2.getIri().equals(nextIri)) {
-					node.setPrevious(node2);
-					break;
+					list.add(node2);
 				}
 			}
 		}
+		node.setPrevious(list);
 
 		query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
 				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n" + "SELECT ?next ?nodetype ?act\n"
 				+ "WHERE { \n" + "  ?node owl:sameAs<" + node.getIri() + ">.\n" + "  ?node pm:ctrlTo ?next.\n"
 				+ "  ?next a ?nodetype ;\n"
-				+ "	FILTER (?nodetype in (pm:CtrlInputPort, pm:Initial, pm:Final,pm:Fork, pm:Join)) \n"
+				+ "	FILTER (?nodetype in (pm:CtrlInputPort, pm:Initial, pm:Final,pm:ForkJoin)) \n"
 				+ "	OPTIONAL {\n" + "		?next pm:ofActivity ?act .\n" + "	}\n" + "}";
-		List<Node> list = new ArrayList<Node>();
+		list.clear();
 		results = FusekiWrapper.getInstance().execQuery(query);
 		while (results.hasNext()) {
 			QuerySolution soln = results.nextSolution();
@@ -190,7 +131,7 @@ public class NodeRespository {
 				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n" + "SELECT ?next ?nodetype ?act\n"
 				+ "WHERE { \n" + "  ?node owl:sameAs<" + node.getIri() + ">.\n" + "  ?node pm:ctrlFrom ?next.\n"
 				+ "  ?next a ?nodetype ;\n"
-				+ "	FILTER (?nodetype in (pm:CtrlOutputPort, pm:Initial, pm:Final,pm:Fork, pm:Join)) \n"
+				+ "	FILTER (?nodetype in (pm:CtrlOutputPort, pm:Initial, pm:Final,pm:ForkJoin)) \n"
 				+ "	OPTIONAL {\n" + "		?next pm:ofActivity ?act .\n" + "	}\n" + "}";
 		List<Node> list = new ArrayList<Node>();
 		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
@@ -216,7 +157,7 @@ public class NodeRespository {
 		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
 				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n" + "SELECT ?next ?nodetype ?act\n"
 				+ "WHERE { \n" + "  ?node owl:sameAs<" + node.getIri() + ">.\n" + "  ?node pm:ctrlTo ?next.\n"
-				+ "  ?next a ?nodetype ;\n" + "	FILTER (?nodetype in (pm:CtrlInputPort, pm:Final,pm:Fork, pm:Join)) \n"
+				+ "  ?next a ?nodetype ;\n" + "	FILTER (?nodetype in (pm:CtrlInputPort, pm:Final,pm:ForkJoin)) \n"
 				+ "	OPTIONAL {\n" + "		?next pm:ofActivity ?act .\n" + "	}\n" + "}";
 		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
 		while (results.hasNext()) {
@@ -297,7 +238,7 @@ public class NodeRespository {
 			break;
 		case Node.FORKJOIN_IRI:
 			// addlogic for fork join
-			node = new JoinNode();
+			node = new ForkJoinNode();
 			break;
 		case Node.ARTIFACT_IRI:
 			// addlogic for fork join

+ 166 - 7
src/main/java/ua/be/wee/model/repository/PMRepository.java

@@ -10,6 +10,7 @@ import org.springframework.stereotype.Repository;
 
 import ua.be.wee.model.nodes.Node;
 import ua.be.wee.model.pm.PM;
+import ua.be.wee.model.pt.PT;
 import ua.be.wee.model.util.Pair;
 
 @Repository
@@ -62,15 +63,15 @@ public class PMRepository {
 		
 	}
 
-	public List<Pair<String,String>> findNextNodes(String iri) {
+	public List<Pair<String,String>> findNextNodes(String iri, String trace) throws Exception {
 		List<Pair<String,String>> list = new ArrayList<Pair<String,String>>();
 		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
 				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n"
 				+ "SELECT ?e ?nodetype ?act WHERE {\n"
 				+ "  ?node owl:sameAs <" + iri + "> .\n"
-				+ "  ?node pm:ctrlTo+ ?e .\n"
+				+ "  ?node pm:ctrlTo ?e .\n"
 				+ "  ?e a ?nodetype ;\n"
-				+ "  FILTER (?nodetype in (pm:CtrlInputPort, pm:Final)) \n"
+				+ "  FILTER (?nodetype in (pm:CtrlInputPort, pm:Final, pm:ForkJoin)) \n"
 				+ "	 OPTIONAL {\n"
 				+ "		?e pm:ofActivity ?act .\n"
 				+ "	 }\n"
@@ -79,16 +80,174 @@ public class PMRepository {
 		while (results.hasNext()) {
 			QuerySolution soln = results.nextSolution();
 			RDFNode type = soln.get("?nodetype");
-			Pair<String,String> pair;
+			Pair<String,String> pair = null;
 			if (type.toString().equals(Node.CTRL_INPUT_PORT_IRI)) {
 				pair = new Pair<String,String>(soln.get("?e").toString(),soln.get("?act").toString());
+			} else if (type.toString().equals(Node.FORKJOIN_IRI)) {
+				if (isJoin(soln.get("?e").toString())) {
+					if (checkJoin(soln.get("?e").toString(), trace, iri)) {
+						list.addAll(findNextNodes(soln.get("?e").toString(), trace));
+					}
+				} else {
+					list.addAll(findNextNodes(soln.get("?e").toString(), trace));
+				}
 			} else {
 				pair = new Pair<String,String>(soln.get("?e").toString(), null);
 			}
-			list.add(pair);
-			
+			if (pair != null) {
+				list.add(pair);
+			}
 		}
 		return list;
-	}	
+	}
+
+	private boolean checkJoin(String node, String trace, String input) throws Exception {
+		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
+				+ "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
+				+ "SELECT ?sync WHERE {\n"
+				+ "  ?sync a tr:JoinSync .\n"
+				+ "  ?sync tr:nodeIRI <" + node + "> .\n"
+				+ "  ?sync tr:trace <" + trace + "> .\n"
+				+ "}";
+		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
+		if (results.hasNext()) {
+			QuerySolution soln = results.nextSolution();
+			String sync = soln.get("?sync").toString();
+			return checkInputs(sync,node,trace,input);
+		} else {
+			createJoinSync(node,trace,input);
+			return false;
+		}
+	}
+
+	private boolean checkInputs(String sync, String node, String trace, String input) throws Exception {
+		List<String> list = new ArrayList<String>();
+		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
+				+ "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
+				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n"
+				+ "SELECT ?inCtrl WHERE {\n"
+				+ "  ?sync owl:sameAs  <" + sync + "> .\n"
+				+ "  ?sync tr:nodeIRI ?node .\n"
+				+ "  ?inCtrl pm:ctrlTo ?node .\n"
+				+ "  FILTER NOT EXISTS { ?sync tr:input ?inCtrl } \n"
+				+ "}";
+		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
+		while (results.hasNext()) {
+			QuerySolution soln = results.nextSolution();
+			String inCtrl = soln.get("?inCtrl").toString();
+			list.add(inCtrl);
+		}
+		if (list.size() == 1 && list.get(0).equals(input)) {
+			insertRealizedInputInJoinSync(sync,input);
+			return true; 
+		} else if (list.size() == 1 && !list.get(0).equals(input)) {
+			return false;
+		} else if (list.size() > 1) {
+			for (String inCtrl : list) {
+				if (inCtrl.equals(input)) {
+					insertRealizedInputInJoinSync(sync,input);
+				}
+			}
+		} else if (list.isEmpty()) {
+			return true;
+		}
+		return false;
+		
+	}
+
+	private void insertRealizedInputInJoinSync(String sync, String input) throws Exception {
+		String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
+				+ "INSERT DATA {\n"
+				+ "GRAPH <"+ PT.TRACE_GRAPH_IRI + "> {"
+				+ "	<"+ sync + "> tr:input <" + input + "> .\n"
+				+ "	}"
+				+ "} ";
+		if (!FusekiWrapper.getInstance().updateQuery(query) ) {
+			throw new Exception("Error inserting data.");
+		}
+	}
+
+	private void deleteJoinSync(String sync) throws Exception {
+		String query = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
+				+ "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
+				+ "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
+				+ "PREFIX base: <http://ua.be/sdo2l/vocabulary/base/acyclic#>\n"
+				+ "DELETE { "
+				+ "GRAPH <"+ PT.TRACE_GRAPH_IRI + "> {"
+				+ "	?sync ?p ?v . }\n"
+				+ "}"
+				+ "WHERE { \n"
+				+ "  ?sync a tr:JoinSync .\n"
+				+ "  ?sync owl:sameAs <" + sync + "> .\n"
+				+ "  ?sync ?p ?v .\n"
+				+ "};\n";	
+		if (!FusekiWrapper.getInstance().updateQuery(query) ) {
+			throw new Exception("Error inserting data.");
+		}
+	}
+
+	private void createJoinSync(String node, String trace, String input) throws Exception {
+		String sync = trace + "_" + node.split("#")[1];
+		String query = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
+				+ "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
+				+ "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
+				+ "INSERT DATA {\n"
+				+ "GRAPH <"+ PT.TRACE_GRAPH_IRI + "> {"
+				+ "	<"+ sync + "> rdf:type <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#JoinSync> , owl:Thing ;\n"
+				+ "    	tr:nodeIRI <" + node + "> ;\n"
+				+ " 	tr:trace <" + trace + "> ;\n"
+				+ " 	tr:input <" + input + "> ;\n"
+				+ "     owl:sameAs  <" + sync + "> .\n"
+				+ "	} \n"
+				+ "}; ";
+		if (!FusekiWrapper.getInstance().updateQuery(query) ) {
+			throw new Exception("Error inserting data.");
+		}
+	}
+
+	private boolean isJoin(String iri) {
+		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
+				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n"
+				+ "SELECT ?input WHERE {\n"
+				+ "  ?node owl:sameAs <" + iri + "> .\n"
+				+ "  ?input pm:ctrlTo ?node .\n"
+				+ "}";
+		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
+		results.next();
+		return results.hasNext();
+	}
+
+	public void checkJoinSync(String portiri, String traceiri) throws Exception {
+		List<String> list = new ArrayList<String>();
+		String query = "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
+				+ "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
+				+ "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n"
+				+ "SELECT DISTINCT ?sync WHERE {\n"
+				+ "  ?inCtrl owl:sameAs <" + portiri + "> .\n"
+				+ "  {?node pm:ctrlTo ?inCtrl .}\n"
+				+ "  UNION\n"
+				+ "  {?inCtrl pm:ctrlFrom+ ?node . }\n"
+				+ "  ?node a pm:ForkJoin .\n"
+				+ "  ?sync tr:nodeIRI ?node .\n"
+				+ "  ?sync tr:trace <" + traceiri +"> .\n"
+				+ "  FILTER NOT EXISTS { \n"
+				+ "  	?in pm:ctrlTo ?node . \n"
+				+ "    FILTER NOT EXISTS {\n"
+				+ "   		?sync tr:input ?in .\n"
+				+ "    }\n"
+				+ "  }\n"
+				+ "}";
+		ResultSet results = FusekiWrapper.getInstance().execQuery(query);
+		while (results.hasNext()) {
+			QuerySolution soln = results.nextSolution();
+			String sync = soln.get("?sync").toString();
+			list.add(sync);
+		}
+		
+		for (String sync : list) {
+			deleteJoinSync(sync);
+		}
+		
+	}
 	
 }