1 package de.tud.plt.r43ples.core;
2
3 import de.tud.plt.r43ples.exception.InternalErrorException;
4 import de.tud.plt.r43ples.exception.QueryErrorException;
5 import de.tud.plt.r43ples.existentobjects.ChangeSet;
6 import de.tud.plt.r43ples.existentobjects.RevisionGraph;
7 import de.tud.plt.r43ples.existentobjects.SemanticChange;
8 import de.tud.plt.r43ples.iohelper.Helper;
9 import de.tud.plt.r43ples.iohelper.JenaModelManagement;
10 import de.tud.plt.r43ples.management.Config;
11 import de.tud.plt.r43ples.management.R43plesRequest;
12 import de.tud.plt.r43ples.triplestoreInterface.TripleStoreInterface;
13 import de.tud.plt.r43ples.triplestoreInterface.TripleStoreInterfaceSingleton;
14 import de.tud.plt.r43ples.webservice.Endpoint;
15 import org.apache.jena.query.QuerySolution;
16 import org.apache.jena.query.ResultSet;
17 import org.apache.jena.query.ResultSetFactory;
18 import org.apache.jena.rdf.model.Model;
19 import org.apache.jena.rdf.model.Statement;
20 import org.apache.jena.rdf.model.StmtIterator;
21 import org.apache.logging.log4j.LogManager;
22 import org.apache.logging.log4j.Logger;
23
24 import java.io.ByteArrayInputStream;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.LinkedList;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31
32
33
34
35
36
37
38
39
40 public class AggregationDraft {
41
42
43 private Logger logger = LogManager.getLogger(SelectConstructAskQuery.class);
44
45
46 private final int patternModifier = Pattern.DOTALL + Pattern.MULTILINE + Pattern.CASE_INSENSITIVE;
47
48 private final Pattern patternAggQuery = Pattern.compile(
49 "AGG\\s*GRAPH\\s*<(?<graph>[^>]*?)>\\s*REVISION\\s*\"(?<startRevisionIdentifier>[^\"]*?)\"\\s*TO\\s*REVISION\\s*\"(?<endRevisionIdentifier>[^\"]*?)\"\\s*",
50 patternModifier);
51
52
53 private R43plesRequest request;
54
55 private String startRevisionIdentifier;
56
57 private String endRevisionIdentifier;
58
59 private ChangeSet changeSetStartToEnd;
60
61 private String graphName;
62
63 private RevisionGraph revisionGraph;
64
65
66
67 private TripleStoreInterface tripleStoreInterface;
68
69 private URICalculator uriCalculator;
70
71 private Endpoint ep = new Endpoint();
72
73
74
75
76
77
78
79
80 protected AggregationDraft(R43plesRequest request) throws InternalErrorException {
81
82 this.tripleStoreInterface = TripleStoreInterfaceSingleton.get();
83 this.uriCalculator = new URICalculator();
84
85 this.request = request;
86
87 this.extractRequestInformation();
88 }
89
90
91
92
93
94
95
96
97 protected AggregationDraft(RevisionGraph revisionGraph, ChangeSet changeSetStartToEnd) {
98
99 this.tripleStoreInterface = TripleStoreInterfaceSingleton.get();
100 this.uriCalculator = new URICalculator();
101
102 this.revisionGraph = revisionGraph;
103 this.graphName = revisionGraph.getGraphName();
104 this.changeSetStartToEnd = changeSetStartToEnd;
105 this.startRevisionIdentifier = changeSetStartToEnd.getPriorRevision().getRevisionIdentifier();
106 this.endRevisionIdentifier = changeSetStartToEnd.getSucceedingRevision().getRevisionIdentifier();
107 }
108
109
110
111
112
113
114
115 protected LinkedList<SemanticChange> aggregate() throws InternalErrorException {
116
117
118 LinkedList<SemanticChange> semanticChangesLinkedList = new LinkedList<>();
119
120
121 String queryAggRules = String.format(
122 Config.prefixes
123 + "SELECT ?aggrule %n"
124 + "WHERE { GRAPH <%s> { %n"
125 + " ?aggrule a aero:HLCAggRule . %n"
126 + "} } %n", Config.rules_graph);
127
128
129 ResultSet resultSetAggRules = tripleStoreInterface.executeSelectQuery(queryAggRules);
130 while (resultSetAggRules.hasNext()) {
131 QuerySolution qs = resultSetAggRules.next();
132
133 String aggRuleURI = qs.getResource("?aggrule").toString();
134
135
136 String querySpinQuery = String.format(
137 Config.prefixes
138 + "SELECT ?query %n"
139 + "WHERE { GRAPH <%s> { %n"
140 + " <%s> a aero:HLCAggRule ; %n"
141 + " aero:spinQuery ?query ."
142 + "} } %n", Config.rules_graph, aggRuleURI);
143 ResultSet resultSetSpinRule = tripleStoreInterface.executeSelectQuery(querySpinQuery);
144 String spinURI = null;
145 while (resultSetSpinRule.hasNext()) {
146 QuerySolution qsSpin = resultSetSpinRule.next();
147 spinURI = qsSpin.getResource("?query").toString();
148 }
149 String spinQueryN3 = Helper.getAllRelatedElementsToURI(Config.rules_graph, spinURI);
150
151
152 String sparqlAggQuery = Helper.getSparqlSelectQueryFromSpin(spinQueryN3, spinURI);
153
154
155 sparqlAggQuery = sparqlAggQuery.replace("<http://NAMEDGRAPH#ADDSET-1-2>", "<" + changeSetStartToEnd.getAddSetURI() + ">");
156 sparqlAggQuery = sparqlAggQuery.replace("<http://NAMEDGRAPH#DELETESET-1-2>", "<" + changeSetStartToEnd.getDeleteSetURI() + ">");
157 sparqlAggQuery = sparqlAggQuery.replace("<http://NAMEDGRAPH#rev1>", "<" + graphName + "> REVISION \"" + startRevisionIdentifier + "\"");
158 sparqlAggQuery = sparqlAggQuery.replace("<http://NAMEDGRAPH#rev2>", "<" + graphName + "> REVISION \"" + endRevisionIdentifier + "\"");
159
160 String sparqlResult = ep.sparql(sparqlAggQuery).getEntity().toString();
161
162 ResultSet resultSet = ResultSetFactory.fromXML(new ByteArrayInputStream(sparqlResult.getBytes()));
163
164 while (resultSet.hasNext()) {
165 QuerySolution qsResult = resultSet.next();
166 semanticChangesLinkedList.add(addMetaInformation(aggRuleURI, spinQueryN3, spinURI, qsResult));
167 }
168
169 }
170
171 return semanticChangesLinkedList;
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185 private SemanticChange addMetaInformation(String aggRuleURI, String spinQueryN3, String spinURI, QuerySolution qsResult) throws InternalErrorException {
186
187 String semanticChangeURI = uriCalculator.getRandomURI(revisionGraph);
188 String additionsURI = uriCalculator.getRandomURI(revisionGraph);
189 String deletionsURI = uriCalculator.getRandomURI(revisionGraph);
190
191 StringBuilder sb = new StringBuilder();
192 sb.append(String.format(
193 "<%s> a rmo:SemanticChange ; %n"
194 + " rmo:additions <%s> ; %n"
195 + " rmo:deletions <%s> ; %n"
196 + " aero:usedRule <%s> . %n",
197 semanticChangeURI, additionsURI, deletionsURI, aggRuleURI));
198
199
200 HashMap<String,String> variableMap = Helper.getVariableMapFromSpin(spinQueryN3, spinURI);
201 HashMap<String,String> variableResultMap = new HashMap<>();
202
203 Iterator ite = qsResult.varNames();
204 while (ite.hasNext()) {
205 String sparqlVariableURI = uriCalculator.getRandomURI(revisionGraph);
206 String varName = ite.next().toString();
207 String value;
208 try {
209 value = "<" + qsResult.getResource("?" + varName).toString() + ">";
210 } catch (Exception e) {
211 value = "\"" + qsResult.getLiteral("?" + varName).toString() + "\"";
212 }
213 variableResultMap.put(varName,value);
214 sb.append(String.format(
215 "<%s> aero:hasVariables <%s> . %n" +
216 "<%s> a aero:SPARQLVariable ; %n"
217 + " sp:varName \"%s\" ; %n"
218 + " aero:value %s ; %n"
219 + " aero:spinResource <%s> . %n",
220 semanticChangeURI, sparqlVariableURI, sparqlVariableURI, varName, value, variableMap.get(varName)));
221
222 }
223
224
225
226
227 String queryAddDelSpinQueries = String.format(
228 Config.prefixes
229 + "SELECT ?queryAdd ?queryDel %n"
230 + "WHERE { GRAPH <%s> { %n"
231 + " <%s> a aero:HLCAggRule ; %n"
232 + " aero:addSetDetectionQuery ?subQueryAdd ; %n"
233 + " aero:deleteSetDetectionQuery ?subQueryDel . %n"
234 + " ?subQueryAdd <http://spinrdf.org/sp#query> ?queryAdd. %n"
235 + " ?subQueryDel <http://spinrdf.org/sp#query> ?queryDel. %n"
236 + "} } %n", Config.rules_graph, aggRuleURI);
237 ResultSet resultSetAddDelQueries = tripleStoreInterface.executeSelectQuery(queryAddDelSpinQueries);
238 String spinAddURI = null;
239 String spinDelURI = null;
240 while (resultSetAddDelQueries.hasNext()) {
241 QuerySolution qsSpin = resultSetAddDelQueries.next();
242 spinAddURI = qsSpin.getResource("?queryAdd").toString();
243 spinDelURI = qsSpin.getResource("?queryDel").toString();
244 }
245
246 String sparqlAddQuery = Helper.getSparqlSelectQueryFromSpin(spinQueryN3, spinAddURI);
247 String sparqlDelQuery = Helper.getSparqlSelectQueryFromSpin(spinQueryN3, spinDelURI);
248
249
250 Pattern patternWherePart = Pattern.compile(
251 "(?s:.)*WHERE\\s*\\{\\s*GRAPH(?s:.)*\\{(?<where>(?s:.)*)?\\}\\s*\\}",
252 patternModifier);
253
254 assert sparqlAddQuery != null;
255 Matcher mAdd = patternWherePart.matcher(sparqlAddQuery);
256 assert sparqlDelQuery != null;
257 Matcher mDel = patternWherePart.matcher(sparqlDelQuery);
258
259 mAdd.find();
260 mDel.find();
261
262 String triplesAdd = mAdd.group("where").trim();
263 String triplesDel = mDel.group("where").trim();
264
265 if (!triplesAdd.endsWith("."))
266 triplesAdd = triplesAdd.concat(".");
267 if (!triplesDel.endsWith("."))
268 triplesDel = triplesDel.concat(".");
269
270 for (String currentKey : variableResultMap.keySet()) {
271 triplesAdd = triplesAdd.replaceAll("\\?" + currentKey, variableResultMap.get(currentKey));
272 triplesDel = triplesDel.replaceAll("\\?" + currentKey, variableResultMap.get(currentKey));
273 }
274
275 Model modelAdd = JenaModelManagement.readTurtleStringToJenaModel(triplesAdd);
276
277 sb.append(String.format("<%s> a rmo:Set . %n", additionsURI));
278
279 StmtIterator iteStmtAdd = modelAdd.listStatements();
280 while (iteStmtAdd.hasNext()) {
281 Statement statement = iteStmtAdd.next();
282 String statementURI = uriCalculator.getRandomURI(revisionGraph);
283 sb.append(String.format(
284 "<%s> rmo:statements <%s> . %n" +
285 "<%s> a rdf:Statement ; %n"
286 + " rdf:subject <%s> ; %n"
287 + " rdf:predicate <%s> ; %n"
288 + " rdf:object <%s> . %n",
289 additionsURI, statementURI, statementURI, statement.getSubject().toString(), statement.getPredicate(), statement.getObject()));
290 }
291
292 Model modelDel = JenaModelManagement.readTurtleStringToJenaModel(triplesDel);
293
294 sb.append(String.format("<%s> a rmo:Set . %n", deletionsURI));
295
296 StmtIterator iteStmtDel = modelDel.listStatements();
297 while (iteStmtDel.hasNext()) {
298 Statement statement = iteStmtDel.next();
299 String statementURI = uriCalculator.getRandomURI(revisionGraph);
300 sb.append(String.format(
301 "<%s> rmo:statements <%s> . %n" +
302 "<%s> a rdf:Statement ; %n"
303 + " rdf:subject <%s> ; %n"
304 + " rdf:predicate <%s> ; %n"
305 + " rdf:object <%s> . %n",
306 deletionsURI, statementURI, statementURI, statement.getSubject().toString(), statement.getPredicate(), statement.getObject()));
307 }
308
309 String queryRevision = Config.prefixes + String.format("INSERT DATA { GRAPH <%s> {%s} }", revisionGraph.getRevisionGraphUri(), sb.toString());
310
311 tripleStoreInterface.executeUpdateQuery(queryRevision);
312
313 return new SemanticChange(revisionGraph, semanticChangeURI);
314
315 }
316
317
318
319
320
321
322 private void extractRequestInformation() throws InternalErrorException {
323 Matcher m = patternAggQuery.matcher(this.request.query_sparql);
324
325 boolean foundEntry = false;
326
327 while (m.find()) {
328 foundEntry = true;
329
330 graphName = m.group("graph");
331 revisionGraph = new RevisionGraph(graphName);
332
333 startRevisionIdentifier = m.group("startRevisionIdentifier");
334 endRevisionIdentifier = m.group("endRevisionIdentifier");
335
336 logger.debug("graph: " + graphName);
337 logger.debug("startRevisionIdentifier: " + startRevisionIdentifier);
338 logger.debug("endRevisionIdentifier: " + endRevisionIdentifier);
339 }
340 if (!foundEntry) {
341 throw new QueryErrorException("Error in query: " + this.request.query_sparql);
342 }
343
344 ArrayList<ChangeSet> changeSets = revisionGraph.getRevision(endRevisionIdentifier).getChangeSets();
345 for (ChangeSet changeSet : changeSets) {
346 if (changeSet.getPriorRevision().getRevisionIdentifier().equals(startRevisionIdentifier)) {
347 changeSetStartToEnd = changeSet;
348 }
349 }
350
351 }
352
353 }