1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package cz.zcu.mre.sparkle.data;
21
22 import cz.zcu.mre.sparkle.data.dataAgentFactory.DataAgentFactory;
23 import cz.zcu.mre.sparkle.data.dataAgentFactory.SparqlEndpointDataAgent;
24 import cz.zcu.mre.sparkle.tools.CancellableConsumer;
25 import cz.zcu.mre.sparkle.tools.CancellableConsumer.State;
26 import cz.zcu.mre.sparkle.tools.Changeable;
27 import javafx.beans.Observable;
28 import javafx.beans.property.SimpleBooleanProperty;
29 import javafx.beans.value.ChangeListener;
30 import org.apache.jena.query.*;
31 import org.apache.jena.rdf.model.*;
32 import org.apache.jena.update.UpdateAction;
33 import org.apache.jena.update.UpdateRequest;
34 import org.apache.jena.util.FileManager;
35 import org.apache.jena.vocabulary.RDF;
36 import org.apache.jena.vocabulary.RDFS;
37 import java.io.File;
38 import java.sql.SQLException;
39 import java.util.AbstractMap.SimpleEntry;
40 import java.util.*;
41 import org.apache.jena.sparql.exec.http.QueryExecutionHTTPBuilder;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45
46
47
48
49
50
51
52
53 public abstract class DataAgent implements Observable, Changeable {
54
55 private static final Logger LOG = LoggerFactory.getLogger(DataAgent.class);
56
57 protected DataAgent() {
58
59 }
60
61 public abstract SimpleBooleanProperty isNullProperty();
62
63
64
65
66 protected abstract Model getModel();
67
68
69
70
71 public abstract String getStorageName();
72
73
74
75
76
77
78
79
80 public static Query createQuery(final String query) {
81 return QueryFactory.create(query);
82 }
83
84
85
86
87
88
89
90
91
92
93 private QueryExecution getQueryExecution(Query query) {
94
95
96 if (getModel() == null) {
97 QueryExecutionHTTPBuilder builder = QueryExecution.service(getStorageName());
98 builder.httpClient(SparqlEndpointDataAgent.getHttpClient());
99 builder.query(query);
100 return builder.build();
101 } else {
102 return QueryExecution.create(query, getModel());
103 }
104 }
105
106
107
108
109
110
111
112
113 public void select(final String query, final CancellableConsumer<? super QuerySolution> consumer) {
114 select(QueryFactory.create(query), consumer);
115 }
116
117
118
119
120
121
122
123
124 public void selectVisual(final String query, final CancellableConsumer<? super QuerySolution> consumer) {
125 select(QueryFactory.create(query), consumer);
126 }
127
128
129
130
131
132
133
134
135 public void select(final Query query, final CancellableConsumer<? super QuerySolution> consumer) {
136
137 final QueryExecution queryExecution = getQueryExecution(query);
138
139 if (consumer == null) {
140
141
142 try {
143 queryExecution.close();
144 } catch (final Exception e) {
145
146 LOG.error("Exception: ", e);
147 }
148 } else {
149
150 final ChangeListener<State> cancellationListener = createStateListener(queryExecution);
151
152 consumer.addListener(cancellationListener);
153
154 try {
155 final Iterator<QuerySolution> iter = queryExecution.execSelect();
156 final Model model = getModel();
157
158 while (iter.hasNext()) {
159 if (consumer.isCancelled() || model != null && model.isClosed()) {
160 break;
161 }
162 consumer.accept(iter.next());
163 if (consumer.isCancelled() || model != null && model.isClosed()) {
164 break;
165 }
166 }
167 } finally {
168 consumer.removeListener(cancellationListener);
169 consumer.notifyFinished();
170 try {
171
172 queryExecution.close();
173 } catch (final Exception e) {
174 LOG.error("Exception: ", e);
175 }
176 }
177 }
178 }
179
180
181
182
183
184
185
186
187 public void ask(final String query, final CancellableConsumer<? super Boolean> consumer) {
188 ask(QueryFactory.create(query), consumer);
189 }
190
191
192
193
194
195
196
197
198 public void ask(final Query query, final CancellableConsumer<? super Boolean> consumer) {
199 final QueryExecution queryExecution = getQueryExecution(query);
200
201 if (consumer == null) {
202
203
204 try {
205 queryExecution.close();
206 } catch (final Exception e) {
207 LOG.error("Exception: ", e);
208 }
209 } else {
210
211 final ChangeListener<State> cancellationListener = createStateListener(queryExecution);
212 consumer.addListener(cancellationListener);
213
214 try {
215 consumer.accept(queryExecution.execAsk());
216 } finally {
217 consumer.removeListener(cancellationListener);
218 consumer.notifyFinished();
219 try {
220 queryExecution.close();
221 } catch (final Exception e) {
222 LOG.error("Exception: ", e);
223 }
224 }
225 }
226 }
227
228
229
230
231
232
233
234
235 public void construct(final String query, final CancellableConsumer<? super Model> consumer) {
236 construct(QueryFactory.create(query), consumer);
237 }
238
239
240
241
242
243
244
245
246 public void construct(final Query query, final CancellableConsumer<? super Model> consumer) {
247
248 final QueryExecution queryExecution = getQueryExecution(query);
249
250 if (consumer == null) {
251 queryExecution.execConstruct().write(System.out);
252
253 try {
254 queryExecution.close();
255 } catch (final Exception e) {
256 LOG.error("Exception: ", e);
257 }
258 } else {
259
260 final ChangeListener<State> cancellationListener = createStateListener(queryExecution);
261 consumer.addListener(cancellationListener);
262
263 try {
264 consumer.accept(queryExecution.execConstruct());
265 } finally {
266 consumer.removeListener(cancellationListener);
267 consumer.notifyFinished();
268
269 try {
270 queryExecution.close();
271 } catch (final Exception e) {
272 LOG.error("Exception: ", e);
273 }
274 }
275 }
276 }
277
278
279
280
281
282
283
284
285 public void describe(final String query, final CancellableConsumer<? super Model> consumer) {
286 describe(QueryFactory.create(query), consumer);
287 }
288
289
290
291
292
293
294
295
296 public void describe(final Query query, final CancellableConsumer<? super Model> consumer) {
297 final QueryExecution queryExecution = getQueryExecution(query);
298
299 if (consumer == null) {
300 queryExecution.execDescribe().write(System.out);
301
302 try {
303 queryExecution.close();
304 } catch (final Exception e) {
305 LOG.error("Exception: ", e);
306 }
307 } else {
308
309 final ChangeListener<State> cancellationListener = createStateListener(queryExecution);
310 consumer.addListener(cancellationListener);
311
312 try {
313 consumer.accept(queryExecution.execDescribe());
314 } finally {
315 consumer.removeListener(cancellationListener);
316 consumer.notifyFinished();
317
318 try {
319 queryExecution.close();
320 } catch (final Exception e) {
321 LOG.error("Exception: ", e);
322 }
323 }
324 }
325 }
326
327
328
329
330
331
332
333
334
335 private static ChangeListener<State> createStateListener(final QueryExecution queryExecution) {
336 return (observable, oldValue, newValue) -> {
337 if (newValue == State.Cancelled) {
338 queryExecution.abort();
339 }
340 };
341 }
342
343
344
345
346
347
348
349
350 public void updateAction(final UpdateRequest request, final CancellableConsumer<? super Boolean> consumer)
351 throws UnsupportedOperationException {
352
353
354 if (getModel() == null) {
355 throw new UnsupportedOperationException();
356 }
357
358 try {
359 UpdateAction.execute(request, getModel());
360
361 consumer.accept(true);
362 consumer.notifyFinished();
363
364 } catch (final Exception e) {
365 consumer.accept(false);
366 LOG.error("Exception: ", e);
367 }
368 }
369
370
371
372
373
374
375
376 public void addToModel(final File file) {
377
378 FileManager.get().readModel(getModel(), file.getAbsolutePath());
379 }
380
381 public Model getFullModel() {
382 return getModel();
383 }
384
385
386
387
388 public void clearModel() {
389 final Model model = getModel();
390 model.removeAll();
391 }
392
393
394
395
396
397
398 public abstract void close() throws SQLException;
399
400
401
402
403
404
405
406
407
408 public LinkedList<Resource> findForwardOntologyPath(Resource start, Resource end) {
409 if (start.getModel() == null) {
410 start = inModel(start);
411 }
412 if (end.getModel() == null) {
413 end = inModel(end);
414 }
415
416
417 final LinkedHashMap<Resource, Resource> visited = new LinkedHashMap<>();
418
419 final LinkedList<SimpleEntry<Resource, Resource>> queue = new LinkedList<>();
420
421
422 final boolean endIsProperty = end.hasProperty(RDF.type, RDF.Property);
423 final LinkedHashSet<String> endSubClassesOrSubPropertiesIRIs = new LinkedHashSet<>();
424 final StmtIterator si = end.listProperties(endIsProperty ? RDFS.subPropertyOf : RDFS.subClassOf);
425
426 while (si.hasNext()) {
427 final RDFNode objectNode = si.next().getObject();
428 if (objectNode.isURIResource()) {
429 endSubClassesOrSubPropertiesIRIs.add(objectNode.asResource().getURI());
430 }
431 }
432 si.close();
433
434
435 queue.add(new SimpleEntry<>(start, null));
436
437
438 boolean found = false;
439
440
441 Resource parent = start;
442
443 while (!queue.isEmpty()) {
444 final SimpleEntry<Resource, Resource> entry = queue.pollFirst();
445 if (entry == null) {
446 continue;
447 }
448 final Resource resource = entry.getKey();
449 parent = entry.getValue();
450
451
452 visited.put(resource, parent);
453
454
455 if (resource.equals(end)
456 || (resource.isURIResource() && endSubClassesOrSubPropertiesIRIs.contains(resource.getURI()))) {
457 found = true;
458 break;
459 }
460
461 final Set<? extends Resource> _toVisit;
462
463
464 if (resource.hasProperty(RDF.type, RDF.Property)) {
465 final Property property = resource.as(Property.class);
466 final Set<Resource> toVisit = DataHelper.getResourcesInRange(property);
467 DataHelper.eliminateParentTypes(toVisit);
468 _toVisit = toVisit;
469 } else {
470 final Set<Property> toVisit = DataHelper.getPropertiesWithResourceInDomain(resource);
471 toVisit.addAll(DataHelper.getResourceKeys(resource));
472 _toVisit = toVisit;
473 }
474
475
476
477 _toVisit.stream().filter((resourceToVisit) -> (!visited.containsKey(resourceToVisit)))
478 .forEach((resourceToVisit) -> queue.addLast(new SimpleEntry<>(resourceToVisit, resource)));
479 }
480
481 if (!found) {
482 return null;
483 }
484
485
486 final LinkedList<Resource> path = new LinkedList<>();
487 path.addFirst(end);
488 Resource pathItem = parent;
489
490 while (pathItem != start) {
491 path.addFirst(pathItem);
492 pathItem = visited.get(pathItem);
493 }
494 path.addFirst(pathItem);
495
496 return path;
497 }
498
499
500
501
502
503
504
505
506
507 @SuppressWarnings("unchecked")
508 public <T extends Resource> T inModel(final Resource resource) {
509 final Class<? extends Resource> classOfResource = resource.getClass();
510 return (T) resource.inModel(getModel()).as(classOfResource);
511 }
512
513
514
515
516
517
518
519
520 public abstract List<String> getImportedFiles();
521 }