|
|
@@ -15,7 +15,6 @@ import ua.be.wee.model.ExecutionFlowManager;
|
|
|
import ua.be.wee.model.Token;
|
|
|
import ua.be.wee.model.nodes.Activity;
|
|
|
import ua.be.wee.model.nodes.Artifact;
|
|
|
-import ua.be.wee.model.nodes.AutomatedActivity;
|
|
|
import ua.be.wee.model.nodes.InvokingActivity;
|
|
|
import ua.be.wee.model.nodes.ports.ControlInputPort;
|
|
|
import ua.be.wee.model.nodes.ports.ControlOutputPort;
|
|
|
@@ -28,7 +27,6 @@ import ua.be.wee.model.pt.StartActivityEvent;
|
|
|
import ua.be.wee.model.pt.StartTraceEvent;
|
|
|
import ua.be.wee.model.pt.TraceArtifact;
|
|
|
import ua.be.wee.model.util.DateTimeConverter;
|
|
|
-import ua.be.wee.model.util.Pair;
|
|
|
|
|
|
@Repository
|
|
|
public class PTRepository {
|
|
|
@@ -43,7 +41,7 @@ public class PTRepository {
|
|
|
private ExecutionFlowManager executionFlowManager;
|
|
|
|
|
|
|
|
|
- public PT createTrace(PM pm) throws Exception {
|
|
|
+ public synchronized PT createTrace(PM pm) throws Exception {
|
|
|
int index = getNextIndex(pm);
|
|
|
String traceiri = pm.getIri().split("#")[0] + "/traces#pt_" + index;
|
|
|
String query = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
|
|
|
@@ -52,6 +50,7 @@ public class PTRepository {
|
|
|
+ "> {" + " <" + traceiri
|
|
|
+ "> rdf:type <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#Event> , <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#StartTraceEvent> , owl:Thing , <http://ua.be/sdo2l/vocabulary/base/acyclic#element> , <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#element> ;\n"
|
|
|
+ " tr:relatesTo <" + pm.getIri() + "> ;\n" + " tr:hasTimestamp ?now ; \n"
|
|
|
+ + " tr:belongsToTopLevelTrace <" + traceiri + "> ; \n"
|
|
|
+ " owl:sameAs <" + traceiri + "> .\n" + "}" + "} WHERE {" + " SELECT ?now\n" + " WHERE\n"
|
|
|
+ " {\n" + " BIND(now() AS ?now) .\n" + " }" + "}";
|
|
|
if (FusekiWrapper.getInstance().updateQuery(query)) {
|
|
|
@@ -83,7 +82,7 @@ public class PTRepository {
|
|
|
|
|
|
}
|
|
|
|
|
|
- private int getNextIndex(PM pm) {
|
|
|
+ private synchronized int getNextIndex(PM pm) {
|
|
|
int index = 0;
|
|
|
String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ "SELECT ?pt WHERE {\n" + " ?pt a tr:StartTraceEvent ;\n" + " tr:relatesTo <" + pm.getIri()
|
|
|
@@ -96,7 +95,7 @@ public class PTRepository {
|
|
|
return index;
|
|
|
}
|
|
|
|
|
|
- public String createStartTraceEvent(PT parentPt, PM pm, String eventIri, String parentTraceIri) throws Exception {
|
|
|
+ public synchronized String createStartTraceEvent(PT parentPt, PM pm, String eventIri, String parentTraceIri) throws Exception {
|
|
|
int index = parentPt.getEvents().size();
|
|
|
|
|
|
String[] iriParts = parentPt.getIri().split("#");
|
|
|
@@ -114,6 +113,7 @@ public class PTRepository {
|
|
|
+ " tr:hasTimestamp ?now ; \n"
|
|
|
+ " tr:isPrecededBy <" + eventIri + "> ;\n"
|
|
|
+ " tr:relatesTo <" + pm.getIri() + "> ;\n"
|
|
|
+ + " tr:belongsToTopLevelTrace <" + parentPt.getIri() + "> ; \n"
|
|
|
+ " owl:sameAs <" + newTraceIri + "> .\n";
|
|
|
|
|
|
if (parentTraceIri != null) {
|
|
|
@@ -152,17 +152,18 @@ public class PTRepository {
|
|
|
return ev.getIri();
|
|
|
}
|
|
|
|
|
|
- public String getParentBranchId(String childBranchId) {
|
|
|
- String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n" +
|
|
|
- "SELECT ?parent WHERE { <" + childBranchId + "> tr:parentBranch ?parent . }";
|
|
|
- ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
- if (rs.hasNext()) {
|
|
|
- return rs.nextSolution().getResource("?parent").getURI();
|
|
|
+ public synchronized String getParentBranchId(String childBranchId) {
|
|
|
+ if (childBranchId == null || !childBranchId.contains("/")) {
|
|
|
+ return null;
|
|
|
}
|
|
|
- return null; // Return null if doesn't have a parent
|
|
|
+ int lastSlashIndex = childBranchId.lastIndexOf('/');
|
|
|
+ if (lastSlashIndex > 0) {
|
|
|
+ return childBranchId.substring(0, lastSlashIndex);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- public String generateBranchId(String traceIri, String parentBranchId) {
|
|
|
+ public synchronized String generateBranchId(String traceIri, String parentBranchId) {
|
|
|
String base = parentBranchId != null ? parentBranchId : traceIri + "/branches";
|
|
|
String candidate = base + "/" + UUID.randomUUID().toString().substring(0, 8);
|
|
|
|
|
|
@@ -184,7 +185,7 @@ public class PTRepository {
|
|
|
}
|
|
|
|
|
|
|
|
|
- public String createStartEvent(
|
|
|
+ public synchronized String createStartEvent(
|
|
|
PT pt,
|
|
|
ControlInputPort port,
|
|
|
Activity act,
|
|
|
@@ -196,11 +197,8 @@ public class PTRepository {
|
|
|
String branchId = isHierarchical
|
|
|
? (parentBranchId != null ? parentBranchId : generateBranchId(pt.getIri(), null))
|
|
|
: parentBranchId;
|
|
|
-
|
|
|
- System.out.println("[createStartEvent] Checking if activity already started: " + act.getIri() + " in branch: " + branchId);
|
|
|
|
|
|
if (isActivityAlreadyStarted(pt, act.getIri(), branchId)) {
|
|
|
- System.err.println("[createStartEvent] Tentativa de iniciar atividade duplicada bloqueada: " + act.getName());
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
@@ -210,10 +208,8 @@ public class PTRepository {
|
|
|
|
|
|
if (rsPredecessor.hasNext()) {
|
|
|
preiri = rsPredecessor.nextSolution().get("?predecessor").toString();
|
|
|
- System.out.println("[createStartEvent] Predecessor real encontrado no grafo: " + preiri);
|
|
|
} else {
|
|
|
preiri = pt.getIri();
|
|
|
- System.out.println("[createStartEvent] Nenhum predecessor encontrado, usando o trace como início: " + preiri);
|
|
|
}
|
|
|
|
|
|
int index = (int) pt.getEvents().stream()
|
|
|
@@ -228,8 +224,6 @@ public class PTRepository {
|
|
|
|
|
|
String portiri = port.getIri();
|
|
|
|
|
|
- System.out.println("[LOG] [createStartEvent] Creating StartActivityEvent with IRI: " + iri);
|
|
|
-
|
|
|
StringBuilder query = new StringBuilder();
|
|
|
query.append("PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n")
|
|
|
.append("PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n")
|
|
|
@@ -242,6 +236,7 @@ public class PTRepository {
|
|
|
.append(" tr:hasTimestamp ?now ;\n")
|
|
|
.append(" tr:isPrecededBy <").append(preiri).append("> ;\n")
|
|
|
.append(" tr:relatesTo <").append(portiri).append("> ;\n")
|
|
|
+ .append(" tr:belongsToTopLevelTrace <").append(pt.getIri()).append("> ;\n")
|
|
|
.append(" owl:sameAs <").append(iri).append("> .\n")
|
|
|
.append("<").append(preiri).append("> tr:isFollowedBy <").append(iri).append("> .\n");
|
|
|
|
|
|
@@ -259,7 +254,6 @@ public class PTRepository {
|
|
|
|
|
|
boolean success = FusekiWrapper.getInstance().updateQuery(query.toString());
|
|
|
if (!success) {
|
|
|
- System.err.println("[ERROR] [createStartEvent] Failed to insert event " + iri);
|
|
|
throw new Exception("Failed to insert event " + iri);
|
|
|
}
|
|
|
|
|
|
@@ -268,8 +262,6 @@ public class PTRepository {
|
|
|
ev.setIri(iri);
|
|
|
ev.setRelatesTo(port);
|
|
|
pt.addEvent(ev);
|
|
|
- System.out.println("[createStartEvent] StartActivityEvent added in memory for activity: " + act.getIri());
|
|
|
-
|
|
|
String tsQuery = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
|
|
|
+ "SELECT ?ts WHERE {\n"
|
|
|
@@ -297,7 +289,7 @@ public class PTRepository {
|
|
|
return iri;
|
|
|
}
|
|
|
|
|
|
- public void updatePT(PT pt) throws Exception {
|
|
|
+ public synchronized void updatePT(PT pt) throws Exception {
|
|
|
String transitive = "";
|
|
|
for (Event ev : pt.getEvents()) {
|
|
|
if (ev instanceof StartTraceEvent) {
|
|
|
@@ -306,6 +298,7 @@ public class PTRepository {
|
|
|
transitive += "<" + ev.getIri() + ">,";
|
|
|
}
|
|
|
}
|
|
|
+ if (transitive.isEmpty()) return; // Avoid error on first event
|
|
|
transitive = transitive.substring(0, transitive.length() - 1);
|
|
|
|
|
|
String query = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n"
|
|
|
@@ -328,7 +321,7 @@ public class PTRepository {
|
|
|
|
|
|
}
|
|
|
|
|
|
- public String getPmIriForTrace(String traceIri) {
|
|
|
+ public synchronized String getPmIriForTrace(String traceIri) {
|
|
|
String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ "SELECT ?pm WHERE {\n"
|
|
|
+ " <" + traceIri + "> a tr:StartTraceEvent ;\n"
|
|
|
@@ -341,101 +334,112 @@ public class PTRepository {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- public List<Event> getAllEventsForTrace(String topLevelTraceIri) throws Exception {
|
|
|
- String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
- + "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
|
|
|
- + "SELECT DISTINCT ?event ?type ?timestamp ?port ?branchId WHERE {\n"
|
|
|
- + " GRAPH <" + PT.TRACE_GRAPH_IRI + "> {\n"
|
|
|
- + " ?trace a tr:StartTraceEvent .\n"
|
|
|
- + " ?trace (tr:invokedByTrace)* <" + topLevelTraceIri + "> .\n"
|
|
|
- + " BIND(REPLACE(STR(?trace), '#', '/') AS ?traceEventBase)\n"
|
|
|
- + " ?event a ?type .\n"
|
|
|
- + " FILTER(STRSTARTS(STR(?event), ?traceEventBase) || ?event = ?trace)\n"
|
|
|
- + " ?event tr:hasTimestamp ?timestamp .\n"
|
|
|
- + " FILTER(?type IN (tr:StartTraceEvent, tr:EndTraceEvent, tr:StartActivityEvent, tr:EndActivityEvent))\n"
|
|
|
- + " OPTIONAL { ?event tr:relatesTo ?port . }\n"
|
|
|
- + " OPTIONAL { ?event tr:belongsToBranch ?branchId . }\n"
|
|
|
- + " }\n"
|
|
|
- + "} ORDER BY ?timestamp";
|
|
|
+ public synchronized List<Event> getAllEventsForTrace(String topLevelTraceIri) throws Exception {
|
|
|
+ String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ + "SELECT DISTINCT ?event ?type ?timestamp ?relatesTo ?branchId WHERE {\n"
|
|
|
+ + " GRAPH <" + PT.TRACE_GRAPH_IRI + "> {\n"
|
|
|
+ + " ?event tr:belongsToTopLevelTrace <" + topLevelTraceIri + "> .\n"
|
|
|
+ + " ?event a ?type ;\n"
|
|
|
+ + " tr:hasTimestamp ?timestamp .\n"
|
|
|
+ + " FILTER(?type IN (tr:StartTraceEvent, tr:EndTraceEvent, tr:StartActivityEvent, tr:EndActivityEvent))\n"
|
|
|
+ + " OPTIONAL { ?event tr:relatesTo ?relatesTo . }\n"
|
|
|
+ + " OPTIONAL { ?event tr:belongsToBranch ?branchId . }\n"
|
|
|
+ + " }\n"
|
|
|
+ + "} ORDER BY ?timestamp";
|
|
|
|
|
|
- ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
- List<Event> events = new ArrayList<>();
|
|
|
- List<String> eventIris = new ArrayList<>();
|
|
|
+ ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
+
|
|
|
+ List<Event> events = new ArrayList<>();
|
|
|
+ List<String> eventIris = new ArrayList<>();
|
|
|
|
|
|
- while (rs.hasNext()) {
|
|
|
- QuerySolution sol = rs.next();
|
|
|
- String eventIRI = sol.get("?event").toString();
|
|
|
+ while (rs != null && rs.hasNext()) {
|
|
|
+ QuerySolution sol = rs.next();
|
|
|
+ String eventIRI = sol.get("?event").toString();
|
|
|
|
|
|
- if (eventIris.contains(eventIRI)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- eventIris.add(eventIRI);
|
|
|
-
|
|
|
- String type = sol.get("?type").toString();
|
|
|
- String timestamp = sol.get("?timestamp").toString();
|
|
|
- RDFNode portNode = sol.get("?port");
|
|
|
- RDFNode branchNode = sol.get("?branchId");
|
|
|
- String branchId = (branchNode != null) ? branchNode.toString() : null;
|
|
|
-
|
|
|
- Event ev = null;
|
|
|
- if (type.endsWith("StartTraceEvent")) {
|
|
|
- ev = new StartTraceEvent();
|
|
|
- } else if (type.endsWith("EndTraceEvent")) {
|
|
|
- ev = new EndTraceEvent();
|
|
|
- } else if (type.endsWith("StartActivityEvent")) {
|
|
|
- StartActivityEvent startEv = new StartActivityEvent();
|
|
|
- startEv.setBranchId(branchId);
|
|
|
- if (portNode != null) {
|
|
|
- ControlInputPort port = nodeRepo.getControlInputPort(portNode.toString());
|
|
|
- startEv.setRelatesTo(port);
|
|
|
- }
|
|
|
- ev = startEv;
|
|
|
- } else if (type.endsWith("EndActivityEvent")) {
|
|
|
- EndActivityEvent endEv = new EndActivityEvent();
|
|
|
- endEv.setBranchId(branchId);
|
|
|
- if (portNode != null) {
|
|
|
- ControlOutputPort port = nodeRepo.getControlOutputPort(portNode.toString());
|
|
|
- endEv.setRelatesTo(port);
|
|
|
- }
|
|
|
- ev = endEv;
|
|
|
- }
|
|
|
+ if (eventIris.contains(eventIRI)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ eventIris.add(eventIRI);
|
|
|
|
|
|
- if (ev != null) {
|
|
|
- ev.setIri(eventIRI);
|
|
|
- ev.setTimestamp(DateTimeConverter.convertSPARQLDateTimeToTimestamp(timestamp));
|
|
|
- events.add(ev);
|
|
|
- }
|
|
|
- }
|
|
|
- return events;
|
|
|
+ String type = sol.get("?type").toString();
|
|
|
+ String timestamp = sol.get("?timestamp").toString();
|
|
|
+ RDFNode relatesToNode = sol.get("?relatesTo");
|
|
|
+ RDFNode branchNode = sol.get("?branchId");
|
|
|
+ String branchId = (branchNode != null) ? branchNode.toString() : null;
|
|
|
+
|
|
|
+ Event ev = null;
|
|
|
+
|
|
|
+ if (type.endsWith("StartTraceEvent")) {
|
|
|
+ StartTraceEvent startEv = new StartTraceEvent();
|
|
|
+ if (relatesToNode != null) {
|
|
|
+ startEv.setPmEnacted(pmRepo.getPM(relatesToNode.toString()));
|
|
|
+ }
|
|
|
+ ev = startEv;
|
|
|
+ } else if (type.endsWith("EndTraceEvent")) {
|
|
|
+ EndTraceEvent endEv = new EndTraceEvent();
|
|
|
+ if (relatesToNode != null) {
|
|
|
+ endEv.setPmEnacted(pmRepo.getPM(relatesToNode.toString()));
|
|
|
+ }
|
|
|
+ ev = endEv;
|
|
|
+ } else if (type.endsWith("StartActivityEvent")) {
|
|
|
+ StartActivityEvent startEv = new StartActivityEvent();
|
|
|
+ startEv.setBranchId(branchId);
|
|
|
+ if (relatesToNode != null) {
|
|
|
+ startEv.setRelatesTo(nodeRepo.getControlInputPort(relatesToNode.toString()));
|
|
|
+ }
|
|
|
+ startEv.setConsumedArtifacts(getConsumedArtifactsForEvent(eventIRI));
|
|
|
+ ev = startEv;
|
|
|
+ } else if (type.endsWith("EndActivityEvent")) {
|
|
|
+ EndActivityEvent endEv = new EndActivityEvent();
|
|
|
+ endEv.setBranchId(branchId);
|
|
|
+ if (relatesToNode != null) {
|
|
|
+ endEv.setRelatesTo(nodeRepo.getControlOutputPort(relatesToNode.toString()));
|
|
|
+ }
|
|
|
+ endEv.setProducedArtifacts(getProducedArtifactsForEvent(eventIRI));
|
|
|
+ ev = endEv;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ev != null) {
|
|
|
+ ev.setIri(eventIRI);
|
|
|
+ ev.setTimestamp(DateTimeConverter.convertSPARQLDateTimeToTimestamp(timestamp));
|
|
|
+ events.add(ev);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return events;
|
|
|
}
|
|
|
|
|
|
- public void createEndEvent(PT pt, List<TraceArtifact> arts, ControlOutputPort p, String branchId) throws Exception {
|
|
|
- System.out.println("initializing createEndEvent");
|
|
|
- System.out.println("Branch ID: " + branchId);
|
|
|
- System.out.println("Activity IRI: " + p.getActivity().getIri());
|
|
|
- System.out.println("Port IRI: " + p.getIri());
|
|
|
+ public synchronized void createEndEvent(PT pt, List<TraceArtifact> arts, ControlOutputPort p, String branchId) throws Exception {
|
|
|
+ if (arts != null && !arts.isEmpty()) {
|
|
|
+ for(TraceArtifact art : arts) {
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ }
|
|
|
|
|
|
List<Event> events = pt.getEvents();
|
|
|
- Event source = null;
|
|
|
+ StartActivityEvent source = null;
|
|
|
|
|
|
- for (Event aux : events) {
|
|
|
+ for (int i = events.size() - 1; i >= 0; i--) {
|
|
|
+ Event aux = events.get(i);
|
|
|
if (aux instanceof StartActivityEvent) {
|
|
|
StartActivityEvent startEv = (StartActivityEvent) aux;
|
|
|
- boolean sameBranch = (branchId == null && startEv.getBranchId() == null)
|
|
|
- || (branchId != null && branchId.equals(startEv.getBranchId()));
|
|
|
- boolean sameActivity = p.getActivity().getIri().equals(
|
|
|
- startEv.getRelatesTo().getActivity().getIri());
|
|
|
+ boolean sameBranch = (branchId != null && branchId.equals(startEv.getBranchId()));
|
|
|
+ boolean sameActivity = p.getActivity().getIri().equals(startEv.getRelatesTo().getActivity().getIri());
|
|
|
|
|
|
if (sameBranch && sameActivity) {
|
|
|
- source = startEv;
|
|
|
- System.out.println("StartActivityEvent found in memory: " + startEv.getIri());
|
|
|
- break;
|
|
|
+ String expectedEndIri = startEv.getIri().replace("start_activity", "end_activity");
|
|
|
+ boolean alreadyEnded = events.stream()
|
|
|
+ .filter(e -> e instanceof EndActivityEvent)
|
|
|
+ .anyMatch(e -> e.getIri().equals(expectedEndIri));
|
|
|
+
|
|
|
+ if (!alreadyEnded) {
|
|
|
+ source = startEv;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (source == null) {
|
|
|
- System.out.println("StartActivityEvent isn't in memory. Consulting RDF");
|
|
|
|
|
|
String activityIRI = p.getActivity().getIri();
|
|
|
String pmGraphIRI = activityIRI.split("#")[0];
|
|
|
@@ -452,16 +456,13 @@ public class PTRepository {
|
|
|
" }\n" +
|
|
|
"}";
|
|
|
|
|
|
- System.out.println("[LOG] Query SPARQL:\n" + queryFindStartEvent);
|
|
|
-
|
|
|
ResultSet rs = FusekiWrapper.getInstance().execQuery(queryFindStartEvent);
|
|
|
if (rs.hasNext()) {
|
|
|
String startEventIri = rs.next().getResource("?startEvent").getURI();
|
|
|
- System.out.println("[LOG] StartActivityEvent found on RDF: " + startEventIri);
|
|
|
|
|
|
for (Event aux : pt.getEvents()) {
|
|
|
if (aux.getIri().equals(startEventIri)) {
|
|
|
- source = aux;
|
|
|
+ source = (StartActivityEvent) aux;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -469,19 +470,11 @@ public class PTRepository {
|
|
|
}
|
|
|
|
|
|
if (source == null) {
|
|
|
- System.out.println(" StartActivityEvent not found in memory or RDF");
|
|
|
- throw new Exception("StartActivityEvent not found in branch " + branchId);
|
|
|
+ throw new Exception("StartActivityEvent not found for activity " + p.getActivity().getName() + " in branch " + branchId);
|
|
|
}
|
|
|
|
|
|
String preiri = pt.getLastEvent() != null ? pt.getLastEvent().getIri() : pt.getIri();
|
|
|
- String iri = source.getIri();
|
|
|
- String indexStr = iri.replaceAll("\\D+", "");
|
|
|
- int index = Integer.parseInt(indexStr);
|
|
|
-
|
|
|
- String[] iriParts = pt.getIri().split("#");
|
|
|
- String baseIri = iriParts[0];
|
|
|
- String fragment = iriParts.length > 1 ? iriParts[1] : "";
|
|
|
- String endiri = baseIri.replace("/traces", "/traces/" + fragment) + "#end_activity" + index;
|
|
|
+ String endiri = source.getIri().replace("start_activity", "end_activity");
|
|
|
|
|
|
List<String> artifactsIRI = new ArrayList<>();
|
|
|
for (TraceArtifact art : arts) {
|
|
|
@@ -499,8 +492,9 @@ public class PTRepository {
|
|
|
.append(" tr:isPrecededBy <").append(preiri).append("> ;\n")
|
|
|
.append(" tr:relatesTo <").append(p.getIri()).append("> ;\n")
|
|
|
.append(" tr:hasTimestamp ?now ;\n")
|
|
|
+ .append(" tr:belongsToTopLevelTrace <").append(pt.getIri()).append("> ;\n")
|
|
|
.append(" tr:belongsToBranch <").append(branchId).append("> ;\n")
|
|
|
- .append(" owl:sameAs <").append(endiri).append("> .\n"); // Removido ponto e vírgula extra
|
|
|
+ .append(" owl:sameAs <").append(endiri).append("> .\n");
|
|
|
|
|
|
for (String iris : artifactsIRI) {
|
|
|
queryBuilder.append(" <").append(endiri).append("> tr:produces <").append(iris).append("> .\n");
|
|
|
@@ -549,7 +543,6 @@ public class PTRepository {
|
|
|
token.getCurrentNode().getIri().equals(p.getActivity().getIri()) &&
|
|
|
token.getBranchId().equals(branchId)) {
|
|
|
|
|
|
- System.out.println("[DEBUG] [createEndEvent] Removing token for activity: " + token.getCurrentNode().getIri());
|
|
|
executionFlowManager.removeToken(pt.getIri(), token.getId());
|
|
|
break;
|
|
|
}
|
|
|
@@ -561,10 +554,159 @@ public class PTRepository {
|
|
|
throw new Exception("fail to insert EndActivityEvent on branch " + branchId);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private synchronized List<TraceArtifact> getConsumedArtifactsForEvent(String eventIri) {
|
|
|
+ String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ + "PREFIX base: <http://ua.be/sdo2l/vocabulary/base/base#>\n"
|
|
|
+ + "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n"
|
|
|
+ + "SELECT DISTINCT ?art ?relatesTo ?artName ?artTypeName ?location ?tag ?guid WHERE {\n"
|
|
|
+ + " GRAPH <" + PT.TRACE_GRAPH_IRI + "> {\n"
|
|
|
+ + " <" + eventIri + "> tr:consumes ?art .\n"
|
|
|
+ + " ?art a tr:Artifact ;\n"
|
|
|
+ + " tr:relatesTo ?relatesTo ;\n"
|
|
|
+ + " tr:hasLocation ?location ;\n"
|
|
|
+ + " base:hasTag ?tag ;\n"
|
|
|
+ + " base:hasGUID ?guid .\n"
|
|
|
+ + " }\n"
|
|
|
+ + " OPTIONAL { ?relatesTo pm:hasName ?artName . }\n"
|
|
|
+ + " OPTIONAL { ?relatesTo pm:hasType ?typeResource . ?typeResource base:hasGUID ?artTypeName . }\n"
|
|
|
+ + "}";
|
|
|
+
|
|
|
+ return executeArtifactQuery(query);
|
|
|
+ }
|
|
|
|
|
|
+ private synchronized List<TraceArtifact> getProducedArtifactsForEvent(String eventIri) {
|
|
|
+ String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ + "PREFIX base: <http://ua.be/sdo2l/vocabulary/base/base#>\n"
|
|
|
+ + "PREFIX pm: <http://ua.be/sdo2l/vocabulary/formalisms/pm#>\n"
|
|
|
+ + "SELECT DISTINCT ?art ?relatesTo ?artName ?artTypeName ?location ?tag ?guid WHERE {\n"
|
|
|
+ + " GRAPH <" + PT.TRACE_GRAPH_IRI + "> {\n"
|
|
|
+ + " <" + eventIri + "> tr:produces ?art .\n"
|
|
|
+ + " ?art a tr:Artifact ;\n"
|
|
|
+ + " tr:relatesTo ?relatesTo ;\n"
|
|
|
+ + " tr:hasLocation ?location ;\n"
|
|
|
+ + " base:hasTag ?tag ;\n"
|
|
|
+ + " base:hasGUID ?guid .\n"
|
|
|
+ + " }\n"
|
|
|
+ + " OPTIONAL { ?relatesTo pm:hasName ?artName . }\n"
|
|
|
+ + " OPTIONAL { ?relatesTo pm:hasType ?typeResource . ?typeResource base:hasGUID ?artTypeName . }\n"
|
|
|
+ + "}";
|
|
|
+
|
|
|
+ return executeArtifactQuery(query);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private synchronized List<TraceArtifact> executeArtifactQuery(String query) {
|
|
|
+ List<TraceArtifact> artifacts = new ArrayList<>();
|
|
|
+ java.util.Set<String> seenGuids = new java.util.HashSet<>();
|
|
|
+ ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
+
|
|
|
+ while (rs.hasNext()) {
|
|
|
+ QuerySolution sol = rs.next();
|
|
|
+
|
|
|
+ String guid = sol.getLiteral("?guid").getString();
|
|
|
+ if (seenGuids.contains(guid)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ seenGuids.add(guid);
|
|
|
+
|
|
|
+ TraceArtifact tArt = new TraceArtifact();
|
|
|
+ tArt.setIri(sol.getResource("?art").getURI());
|
|
|
+ tArt.setLocation(sol.getLiteral("?location").getString());
|
|
|
+ tArt.setTag(sol.getLiteral("?tag").getString());
|
|
|
+ tArt.setGUID(guid);
|
|
|
+
|
|
|
+ Artifact artifactDefinition = new Artifact();
|
|
|
+ artifactDefinition.setIri(sol.getResource("?relatesTo").getURI());
|
|
|
+
|
|
|
+ if (sol.contains("?artName")) {
|
|
|
+ artifactDefinition.setName(sol.getLiteral("?artName").getString());
|
|
|
+ } else {
|
|
|
+ artifactDefinition.setName("Unknown Name");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sol.contains("?artTypeName")) {
|
|
|
+ artifactDefinition.setType(sol.getLiteral("?artTypeName").getString());
|
|
|
+ }
|
|
|
+
|
|
|
+ tArt.setRelatesTo(artifactDefinition);
|
|
|
+ artifacts.add(tArt);
|
|
|
+ }
|
|
|
+ return artifacts;
|
|
|
+ }
|
|
|
+
|
|
|
+ private synchronized List<TraceArtifact> getArtifactsForEvent(String eventIri) {
|
|
|
+ List<TraceArtifact> artifacts = new ArrayList<>();
|
|
|
+ String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ + "PREFIX base: <http://ua.be/sdo2l/vocabulary/base/base#>\n"
|
|
|
+ + "SELECT ?art ?relatesTo ?location ?tag ?guid WHERE {\n"
|
|
|
+ + " { <" + eventIri + "> tr:produces ?art . } UNION { <" + eventIri + "> tr:consumes ?art . }\n"
|
|
|
+ + " ?art a tr:Artifact ;\n"
|
|
|
+ + " tr:relatesTo ?relatesTo ;\n"
|
|
|
+ + " tr:hasLocation ?location ;\n"
|
|
|
+ + " base:hasTag ?tag ;\n"
|
|
|
+ + " base:hasGUID ?guid .\n"
|
|
|
+ + "}";
|
|
|
+
|
|
|
+ ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
+ while (rs.hasNext()) {
|
|
|
+ QuerySolution sol = rs.next();
|
|
|
+ TraceArtifact tArt = new TraceArtifact();
|
|
|
+ tArt.setIri(sol.getResource("?art").getURI());
|
|
|
+ tArt.setLocation(sol.getLiteral("?location").getString());
|
|
|
+ tArt.setTag(sol.getLiteral("?tag").getString());
|
|
|
+ tArt.setGUID(sol.getLiteral("?guid").getString());
|
|
|
+
|
|
|
+ Artifact relatedArtifactDef = new Artifact();
|
|
|
+ relatedArtifactDef.setIri(sol.getResource("?relatesTo").getURI());
|
|
|
+ try {
|
|
|
+ Artifact fullDef = (Artifact) nodeRepo.getNodes(relatedArtifactDef.getIri());
|
|
|
+ if(fullDef != null){
|
|
|
+ tArt.setRelatesTo(fullDef);
|
|
|
+ } else {
|
|
|
+ tArt.setRelatesTo(relatedArtifactDef);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ tArt.setRelatesTo(relatedArtifactDef);
|
|
|
+ }
|
|
|
+
|
|
|
+ artifacts.add(tArt);
|
|
|
+ }
|
|
|
+ return artifacts;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized TraceArtifact findLatestTraceArtifactForDefinition(String artifactDefinitionIri, List<Event> allEvents) {
|
|
|
+ List<TraceArtifact> candidates = new ArrayList<>();
|
|
|
+
|
|
|
+ for (Event event : allEvents) {
|
|
|
+ if (event instanceof EndActivityEvent) {
|
|
|
+ EndActivityEvent endEvent = (EndActivityEvent) event;
|
|
|
+ if (endEvent.getProducedArtifacts() != null) {
|
|
|
+ for (TraceArtifact produced : endEvent.getProducedArtifacts()) {
|
|
|
+ if (produced.getRelatesTo() != null && produced.getRelatesTo().getIri().equals(artifactDefinitionIri)) {
|
|
|
+ candidates.add(produced);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (candidates.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ TraceArtifact latest = candidates.stream()
|
|
|
+ .max(java.util.Comparator.comparing(TraceArtifact::getTimestamp))
|
|
|
+ .orElse(null);
|
|
|
+
|
|
|
+ if (latest != null) {
|
|
|
+ }
|
|
|
+
|
|
|
+ return latest;
|
|
|
+ }
|
|
|
|
|
|
|
|
|
- private String createTraceArtifact(String endEvIRI, String startEvIRI, TraceArtifact art, PT pt) throws Exception {
|
|
|
+ private synchronized String createTraceArtifact(String endEvIRI, String startEvIRI, TraceArtifact art, PT pt) throws Exception {
|
|
|
|
|
|
TraceArtifact latest = getLastestVersion(startEvIRI, art);
|
|
|
if (latest != null) {
|
|
|
@@ -643,11 +785,22 @@ public class PTRepository {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public boolean isActivityAlreadyStarted(PT pt, String activityIri, String branchId) {
|
|
|
- System.out.println("[isActivityAlreadyStarted] Checking activity " + activityIri + " within branch " + branchId);
|
|
|
-
|
|
|
+ public synchronized String findSubTraceIriByInvokerEventIri(String invokerEventIri) {
|
|
|
+ String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n" +
|
|
|
+ "SELECT ?subTrace WHERE { " +
|
|
|
+ " ?subTrace a tr:StartTraceEvent ; " +
|
|
|
+ " tr:isPrecededBy <" + invokerEventIri + "> . " +
|
|
|
+ "}";
|
|
|
+ ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
+ if (rs.hasNext()) {
|
|
|
+ return rs.nextSolution().getResource("?subTrace").getURI();
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public synchronized boolean isActivityAlreadyStarted(PT pt, String activityIri, String branchId) {
|
|
|
List<Event> branchEvents = pt.getEvents().stream()
|
|
|
- .filter(e -> e.getBranchId() != null && e.getBranchId().equals(branchId))
|
|
|
+ .filter(e -> branchId.equals(e.getBranchId()))
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
List<StartActivityEvent> startEventsForActivity = branchEvents.stream()
|
|
|
@@ -657,30 +810,24 @@ public class PTRepository {
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
if (startEventsForActivity.isEmpty()) {
|
|
|
- System.out.println("[isActivityAlreadyStarted] Result: false (no start events found in this branch)");
|
|
|
- return false;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
for (StartActivityEvent startEvent : startEventsForActivity) {
|
|
|
+ String expectedEndIri = startEvent.getIri().replace("start_activity", "end_activity");
|
|
|
boolean hasMatchingEndEvent = branchEvents.stream()
|
|
|
.filter(e -> e instanceof EndActivityEvent)
|
|
|
- .map(e -> (EndActivityEvent) e)
|
|
|
- .anyMatch(ee -> {
|
|
|
- String expectedEndIri = startEvent.getIri().replace("start_activity", "end_activity");
|
|
|
- return ee.getIri().equals(expectedEndIri);
|
|
|
- });
|
|
|
+ .anyMatch(ee -> ee.getIri().equals(expectedEndIri));
|
|
|
|
|
|
if (!hasMatchingEndEvent) {
|
|
|
- System.out.println("[isActivityAlreadyStarted] Result: true (start event without matching end event found in this branch)");
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- System.out.println("[isActivityAlreadyStarted] Result: false (all start events have a matching end event in this branch)");
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- private TraceArtifact getLastestVersion(String startEvIRI, TraceArtifact art) {
|
|
|
+ private synchronized TraceArtifact getLastestVersion(String startEvIRI, TraceArtifact art) {
|
|
|
String query = "PREFIX pt: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ "PREFIX base: <http://ua.be/sdo2l/vocabulary/base/base#>\n" + "SELECT DISTINCT ?art ?version\n"
|
|
|
+ "WHERE { \n" + " ?art a pt:Artifact .\n" + " ?art pt:relatesTo <" + art.getRelatesTo().getIri()
|
|
|
@@ -704,16 +851,20 @@ public class PTRepository {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- public Event createEndTraceEvent(String ptIRI, String previous, String pmIRI) throws Exception {
|
|
|
+ public synchronized Event createEndTraceEvent(String ptIRI, String previous, String pmIRI) throws Exception {
|
|
|
String traceiri = ptIRI + "_end";
|
|
|
|
|
|
+ String topLevelTraceIri = findTopLevelTrace(ptIRI);
|
|
|
+
|
|
|
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 {\n" + "GRAPH <" + PT.TRACE_GRAPH_IRI
|
|
|
+ "> {" + " <" + traceiri
|
|
|
+ "> rdf:type <http://ua.be/sdo2l/vocabulary/base/acyclic#element> , <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#EndTraceEvent> , <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#Event> , <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#element> , owl:Thing ;\n"
|
|
|
+ " tr:isPrecededBy <" + previous + "> ;\n" + " tr:relatesTo <" + pmIRI + "> ;\n"
|
|
|
- + " tr:hasTimestamp ?now ; \n" + " owl:sameAs <" + traceiri + "> .\n" + " <" + previous
|
|
|
+ + " tr:hasTimestamp ?now ; \n"
|
|
|
+ + " tr:belongsToTopLevelTrace <" + topLevelTraceIri + "> ; \n"
|
|
|
+ + " owl:sameAs <" + traceiri + "> .\n" + " <" + previous
|
|
|
+ "> tr:isFollowedBy <" + traceiri + "> .\n" + "}" + "} WHERE {" + " SELECT ?now\n" + " WHERE\n"
|
|
|
+ " {\n" + " BIND(now() AS ?now) .\n" + " }" + "}";
|
|
|
|
|
|
@@ -737,10 +888,22 @@ public class PTRepository {
|
|
|
} else {
|
|
|
throw new Exception("Error inserting data.");
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
+ private synchronized String findTopLevelTrace(String traceIri) {
|
|
|
+ String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ + "SELECT ?topLevelTrace WHERE { "
|
|
|
+ + " <" + traceIri + "> (tr:invokedByTrace)* ?topLevelTrace . "
|
|
|
+ + " FILTER NOT EXISTS { ?topLevelTrace tr:invokedByTrace ?anotherTrace . }"
|
|
|
+ + "}";
|
|
|
+ ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
+ if (rs.hasNext()) {
|
|
|
+ return rs.nextSolution().getResource("?topLevelTrace").getURI();
|
|
|
+ }
|
|
|
+ return traceIri;
|
|
|
}
|
|
|
|
|
|
- public List<StartTraceEvent> getStartTraceEvents() throws Exception {
|
|
|
+ public synchronized List<StartTraceEvent> getStartTraceEvents() throws Exception {
|
|
|
List<StartTraceEvent> list = new ArrayList<StartTraceEvent>();
|
|
|
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"
|
|
|
@@ -762,7 +925,7 @@ public class PTRepository {
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
- public List<Event> getEvents(String traceIri, String branchId) throws Exception {
|
|
|
+ public synchronized List<Event> getEvents(String traceIri, String branchId) throws Exception {
|
|
|
String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
|
|
|
+ "SELECT ?event ?type ?timestamp ?port WHERE {\n"
|
|
|
@@ -820,51 +983,7 @@ public class PTRepository {
|
|
|
return events;
|
|
|
}
|
|
|
|
|
|
- private List<TraceArtifact> getArtifacts(Event ev, PM pm, List<TraceArtifact> artifacts) {
|
|
|
- List<TraceArtifact> arts = new ArrayList<TraceArtifact>();
|
|
|
- String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
- + "PREFIX base: <http://ua.be/sdo2l/vocabulary/base/base#>\n"
|
|
|
- + "PREFIX owl: <http://www.w3.org/2002/07/owl#>\n"
|
|
|
- + "SELECT ?art ?ts ?guid ?location ?tag ?pmArt ?next WHERE {\n" + " ?art a tr:Artifact .\n"
|
|
|
- + (ev instanceof StartActivityEvent ? " <" + ev.getIri() + "> tr:consumes ?art .\n"
|
|
|
- : " <" + ev.getIri() + "> tr:produces ?art .\n")
|
|
|
- + " ?art tr:addedAt ?ts .\n" + " ?art base:hasGUID ?guid .\n"
|
|
|
- + " ?art tr:hasLocation ?location .\n" + " ?art base:hasTag ?tag .\n"
|
|
|
- + " ?art tr:relatesTo ?pmArt .\n" + " OPTIONAL {\n"
|
|
|
- + " ?art base:nextVersionOf ?next \n" + " }" + "}";
|
|
|
- ResultSet rs = FusekiWrapper.getInstance().execQuery(query);
|
|
|
- while (rs.hasNext()) {
|
|
|
- QuerySolution next = rs.next();
|
|
|
- RDFNode art = next.get("?art");
|
|
|
- RDFNode guid = next.get("?guid");
|
|
|
- RDFNode ts = next.get("?ts");
|
|
|
- RDFNode location = next.get("?location");
|
|
|
- RDFNode tag = next.get("?tag");
|
|
|
- RDFNode pmArt = next.get("?pmArt");
|
|
|
- RDFNode nextArt = next.get("?next");
|
|
|
- TraceArtifact tArt = new TraceArtifact();
|
|
|
- tArt.setIri(art.toString());
|
|
|
- tArt.setTimestamp(DateTimeConverter.convertSPARQLDateTimeToTimestamp(ts.toString()));
|
|
|
- tArt.setRelatesTo((Artifact) pm.getNode(pmArt.toString()));
|
|
|
- tArt.setGUID(guid.toString());
|
|
|
- tArt.setLocation(location.toString());
|
|
|
- tArt.setTag(tag.toString());
|
|
|
- arts.add(tArt);
|
|
|
-
|
|
|
- if (nextArt != null && !nextArt.toString().equals("")) {
|
|
|
- for (TraceArtifact traceArtifact : artifacts) {
|
|
|
- if (traceArtifact.getIri().equals(nextArt.toString())) {
|
|
|
- traceArtifact.setNextVersion(tArt);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- artifacts.add(tArt);
|
|
|
- }
|
|
|
- return arts;
|
|
|
- }
|
|
|
-
|
|
|
- public List<StartTraceEvent> getActiveTraces(String pm) {
|
|
|
+ public synchronized List<StartTraceEvent> getActiveTraces(String pm) {
|
|
|
List<StartTraceEvent> list = new ArrayList<StartTraceEvent>();
|
|
|
String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ "SELECT ?trace ?ts ?next WHERE {\n" + " ?trace tr:hasTimestamp ?ts .\n" + " ?trace tr:relatesTo <"
|
|
|
@@ -890,7 +1009,7 @@ public class PTRepository {
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
- public List<StartTraceEvent> getConcludedTraces(String pmiri) {
|
|
|
+ public synchronized List<StartTraceEvent> getConcludedTraces(String pmiri) {
|
|
|
List<StartTraceEvent> list = new ArrayList<StartTraceEvent>();
|
|
|
String query = "PREFIX tr: <http://ua.be/sdo2l/vocabulary/formalisms/processtraces#>\n"
|
|
|
+ "SELECT ?trace ?ts ?next WHERE {\n" + " ?trace a tr:StartTraceEvent .\n"
|