1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package cz.zcu.mre.service.data;
23
24 import cz.zcu.mre.data.core.MREData;
25 import cz.zcu.mre.data.core.MREStringLang;
26 import cz.zcu.mre.mrelib.util.DateUtil;
27 import java.time.LocalDate;
28 import java.time.LocalDateTime;
29 import java.util.Date;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Set;
33 import org.apache.jena.datatypes.xsd.XSDDatatype;
34 import org.apache.jena.datatypes.xsd.impl.XSDDateType;
35 import org.apache.jena.ontology.Individual;
36 import org.apache.jena.rdf.model.Literal;
37 import org.apache.jena.rdf.model.Resource;
38 import org.apache.jena.rdf.model.ResourceFactory;
39 import org.apache.jena.vocabulary.RDF;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43
44
45
46
47
48
49 public class SPARQLBuilderStringImpl implements SPARQLBuilderString {
50
51 private static final Logger LOG = LoggerFactory.getLogger(SPARQLBuilderStringImpl.class);
52 private static final String EMPTY_STRING = "";
53 private static final String GRAPH_BEGIN = "{ GRAPH ";
54 private static final String GRAPH_NAME = "<NAME>";
55 private static final String GRAPH_END = "}";
56
57 private static final String TEMPLATE_ASK = "ASK { TRIPLES }";
58 private static final String TEMPLATE_INSERT = "INSERT DATA GRAPH_BEGIN { TRIPLES } GRAPH_END";
59 private static final String TEMPLATE_DELETE = "DELETE DATA GRAPH_BEGIN { TRIPLES } GRAPH_END";
60 private static final String TEMPLATE_SELECT = "SELECT DISTINCT ATTRIBUTES WHERE {\nTRIPLES}";
61
62 private String graph = null;
63
64
65 private MREDataService dataService;
66
67
68
69
70 public SPARQLBuilderStringImpl() {
71 }
72
73 public SPARQLBuilderStringImpl(MREDataService dataService) {
74 this.dataService = dataService;
75 }
76
77 @Override
78 public String ask(Object instance) {
79 return buildQuery(QUERY.ASK, instance, false);
80 }
81
82 @Override
83 public String ask(String queryTriples) {
84
85 String ask = TEMPLATE_ASK.replace("TRIPLES", queryTriples);
86 return ask;
87 }
88
89 @Override
90 public String insert(Object instance) {
91 return buildQuery(QUERY.INSERT, instance, false);
92 }
93
94 @Override
95 public String insertAll(Object instance) {
96 return buildQuery(QUERY.INSERT, instance, true);
97 }
98
99 @Override
100 public String delete(Object instance) {
101 return buildQuery(QUERY.DELETE, instance, false);
102 }
103
104 @Override
105 public String deleteAll(Object instance) {
106 return buildQuery(QUERY.DELETE, instance, true);
107 }
108
109 @Override
110 public String update(Object instanceOld, Object instanceNew) {
111 StringBuilder sb = new StringBuilder();
112
113 sb.append(buildQuery(QUERY.DELETE, instanceOld, false));
114 sb.append(buildQuery(QUERY.INSERT, instanceNew, false));
115
116 return sb.toString();
117 }
118
119 @Override
120 public String updateAll(Object instanceOld, Object instanceNew) {
121 StringBuilder sb = new StringBuilder();
122
123 sb.append(buildQuery(QUERY.DELETE, instanceOld, true));
124 sb.append(buildQuery(QUERY.INSERT, instanceNew, true));
125
126 return sb.toString();
127 }
128
129
130
131
132
133
134
135
136
137
138
139 @Override
140 public String select(Object instance) {
141
142 return buildQuery(QUERY.SELECT, instance, false);
143 }
144
145 private String buildQuery(QUERY type, Object instance, boolean deep) {
146
147 StringBuilder query = new StringBuilder();
148
149 switch (type) {
150 case INSERT:
151 query.append(TEMPLATE_INSERT);
152 break;
153 case DELETE:
154 query.append(TEMPLATE_DELETE);
155 break;
156 case SELECT:
157 query.append(TEMPLATE_SELECT);
158 break;
159 case ASK:
160 query.append(TEMPLATE_ASK);
161 break;
162 default:
163 break;
164 }
165
166 String result = query.toString();
167
168 if (graph != null) {
169 result = result.replace("GRAPH_BEGIN", GRAPH_BEGIN);
170 String graphName = GRAPH_NAME.replace("NAME", graph);
171 result = result.replace("GRAPH", "GRAPH " + graphName);
172 result = result.replace("GRAPH_END", GRAPH_END);
173 } else {
174 result = result.replace("GRAPH_BEGIN", "");
175 result = result.replace("GRAPH_END", "");
176 }
177
178 String queryWherePart = buildTriples(type, instance, deep);
179
180 if (type == QUERY.SELECT) {
181
182 queryWherePart = queryWherePart.concat(getSelectWhereVariables(instance));
183
184
185 String uri = getInstanceURI(instance);
186 if (uri != null) {
187
188 queryWherePart = queryWherePart.replaceAll("<" + uri + ">", SELECT_VARIABLE_URI);
189
190
191 queryWherePart = queryWherePart.replaceFirst(SELECT_VARIABLE_URI.replace("?", "\\?"), " VALUES " + SELECT_VARIABLE_URI + " { <" + uri + "> }\n " + SELECT_VARIABLE_URI);
192 }
193
194 result = result.replace("ATTRIBUTES", getSelectVariables(instance));
195 }
196
197 result = result.replace("TRIPLES", queryWherePart);
198
199 return result;
200 }
201
202 private String buildTriples(QUERY type, Object instance, boolean deep) {
203
204 if (type == null) {
205 return "";
206 }
207
208 StringBuilder sb = new StringBuilder();
209
210 MREDataFieldValue[] fields = dataService.builderValuesGet(instance);
211 for (int i = 0; i < fields.length; i++) {
212
213 Set<Object> fieldValues = fields[i].getValue();
214
215
216 if (fieldValues.isEmpty()) {
217 continue;
218 }
219
220
221 if (i == 0) {
222 buildTripleRDFType(sb, fields, i, instance);
223 sb.append("\n");
224 }
225
226
227 Iterator<Object> it = fieldValues.iterator();
228 while (it.hasNext()) {
229 Object object = it.next();
230
231
232 if (object == null) {
233 continue;
234 }
235
236 if (object instanceof List) {
237
238
239 List list = (List) object;
240 for (Object o : list) {
241 LOG.debug("Build triples - {}, List field '{}'", o.getClass(), fields[i].getName());
242 sb.append(buildTriple(type, fields[i], o, deep));
243 if (deep) {
244 sb.append(buildTriples(type, o, deep));
245 }
246 }
247
248 } else if (object instanceof Set) {
249
250
251 Set set = (Set) object;
252 for (Object o : set) {
253 LOG.debug("Build triples - {}, Set field '{}'", o.getClass(), fields[i].getName());
254 sb.append(buildTriple(type, fields[i], o, deep));
255 if (deep) {
256 sb.append(buildTriples(type, o, deep));
257 }
258 }
259
260 } else if (object instanceof MREData
261 || object instanceof Individual) {
262
263 LOG.debug("Build triples - {}, MREData field '{}', type {}", instance.getClass(), fields[i].getName(), object.getClass());
264 sb.append(buildTripleObject(type, fields[i], object, deep));
265
266 } else {
267 LOG.debug("Build triples - {}, primitive type field '{}', type {}", instance.getClass(), fields[i].getName(), object.getClass());
268 sb.append(buildTriple(type, fields[i], object, deep));
269 }
270 }
271 }
272
273
274 String query = sb.toString();
275
276
277 return query;
278 }
279
280 private void buildTripleRDFType(StringBuilder sb, MREDataFieldValue[] fields, int i, Object instance) {
281
282 sb.append(" <").append(fields[i].getSubject()).append("> ");
283 sb.append("<").append(RDF.type).append("> ");
284 if (fields[i].getConfig().getTypeRDF() == null) {
285 sb.append("<").append(fields[i].getConfig().getOntology().concat(instance.getClass().getSimpleName())).append("> .");
286 } else {
287 sb.append("<").append(fields[i].getConfig().getTypeRDF()).append("> .");
288 }
289 }
290
291
292
293
294
295
296
297 private String getSelectVariables(Object instance) {
298
299 StringBuilder variables = new StringBuilder();
300 MREDataFieldValue[] fields = dataService.builderValuesGet(instance);
301 variables.append(SELECT_VARIABLE_URI);
302 variables.append(" ");
303 variables.append(SELECT_VARIABLE_TYPE).append(" ");
304 for (MREDataFieldValue field : fields) {
305 variables.append("?");
306 variables.append(field.getName());
307 variables.append(" ");
308 }
309
310 return variables.toString();
311 }
312
313
314
315
316
317
318
319
320
321 private String getSelectWhereVariables(Object instance) {
322
323 MREDataFieldValue[] fields = dataService.builderValuesGet(instance);
324
325 StringBuilder variables = new StringBuilder();
326
327
328 variables.append(" ");
329 variables.append(SELECT_VARIABLE_URI);
330 variables.append(" <");
331 variables.append(RDF.type);
332 variables.append("> ");
333 variables.append(SELECT_VARIABLE_TYPE);
334 variables.append(" .");
335 variables.append("\n");
336
337 for (MREDataFieldValue field : fields) {
338
339 variables.append(" OPTIONAL {");
340 variables.append(" ");
341 variables.append(SELECT_VARIABLE_URI);
342 variables.append(" <");
343 variables.append(field.getProperty());
344 variables.append("> ?");
345 variables.append(field.getName());
346 variables.append(" .");
347 variables.append(" }");
348 variables.append("\n");
349 }
350
351 return variables.toString();
352 }
353
354
355
356
357
358
359
360 private String getInstanceURI(Object instance) {
361
362 if (instance instanceof MREData) {
363 MREData data = (MREData) instance;
364 if (data.hasURI()) {
365 return data.getUri();
366 }
367 }
368
369 return null;
370 }
371
372 private String buildTriple(QUERY type, MREDataFieldValue field, Object object, boolean deep) {
373
374 if (object == null) {
375 return EMPTY_STRING;
376 }
377
378
379 if (object instanceof List) {
380 return buildTriples(type, object, deep);
381 } else if (object instanceof Set) {
382 return buildTriples(type, object, deep);
383 }
384
385 if (object instanceof Individual) {
386 return buildTripleObject(type, field, ((Individual) object).getURI(), deep);
387 } else if (object instanceof MREData) {
388 return buildTripleObject(type, field, ((MREData) object).getUri(), deep);
389 } else {
390 return buildTripleDatatype(type, field, object);
391 }
392 }
393
394 private String buildTripleObject(QUERY type, MREDataFieldValue field, Object object, boolean deep) {
395
396 if (object == null) {
397 return EMPTY_STRING;
398 }
399
400 StringBuilder sb = new StringBuilder();
401
402 sb.append(" <").append(field.getSubject()).append("> ");
403 sb.append("<").append(field.getProperty().toString()).append("> ");
404
405 sb.append("<");
406 if (object instanceof MREData) {
407
408 sb.append(((MREData) object).getResource().getURI());
409 } else if (object instanceof Individual) {
410 sb.append(((Individual) object).getURI());
411 } else if (object instanceof String) {
412 sb.append(((String) object));
413 } else {
414 LOG.warn("Unsupported Java {} value {}. Using toString() method.", object.getClass(), object);
415
416 sb.append(object.toString());
417 }
418
419 sb.append("> .");
420 sb.append("\n");
421 return sb.toString();
422 }
423
424 private String buildTripleDatatype(QUERY type, MREDataFieldValue field, Object value) {
425 StringBuilder sb = new StringBuilder();
426
427 sb.append(" <").append(field.getSubject()).append("> ");
428 sb.append("<").append(field.getProperty().toString()).append("> ");
429
430 Literal literalValue;
431 if (value instanceof Date) {
432
433 String date = DateUtil.xsdDate((Date) value);
434 literalValue = ResourceFactory.createTypedLiteral(date);
435
436 } else if (value instanceof LocalDate) {
437
438 LocalDate localDate = (LocalDate) value;
439 String date = localDate.toString();
440 literalValue = ResourceFactory.createTypedLiteral(date, XSDDateType.XSDdate);
441
442 } else if (value instanceof LocalDateTime) {
443
444 LocalDateTime localDateTime = (LocalDateTime) value;
445 String dateTime = localDateTime.toString();
446
447
448 literalValue = ResourceFactory.createTypedLiteral(dateTime, XSDDateType.XSDdateTime);
449
450 } else {
451
452 literalValue = buildTripleDatatypeValue(type, field, value);
453 }
454
455
456 if (literalValue != null) {
457
458 if (literalValue.getLanguage() != null
459 && !literalValue.getLanguage().isEmpty()) {
460
461 sb.append("\"").append(literalValue.getString()).append("\"@").append(literalValue.getLanguage());
462 } else if (literalValue.getDatatype() != null
463 && !literalValue.getDatatype().equals(XSDDatatype.XSDstring)) {
464
465 sb.append("\"").append(makeValidString(literalValue.getString())).append("\"^^<").append(literalValue.getDatatypeURI()).append(">");
466 } else {
467 sb.append("\"").append(makeValidString(literalValue.getString())).append("\"");
468
469 }
470 }
471
472 sb.append(" .");
473 sb.append("\n");
474 return sb.toString();
475 }
476
477 private String makeValidString(String textContent) {
478
479 String result = textContent;
480
481 if (textContent.contains("\"")) {
482 result = textContent.replace("\"", "\\\"");
483 }
484
485 return result;
486 }
487
488 private Literal buildTripleDatatypeValue(QUERY type, MREDataFieldValue field, Object instance) {
489
490 if (instance == null) {
491 return null;
492 }
493
494 if (instance instanceof String) {
495
496 return ResourceFactory.createPlainLiteral((String) instance);
497
498 } else if (instance instanceof MREStringLang) {
499
500
501 if (((MREStringLang) instance).getLang() == null) {
502 return ResourceFactory.createPlainLiteral(((MREStringLang) instance).getString());
503 }
504
505
506 return ResourceFactory.createLangLiteral(((MREStringLang) instance).getString(), ((MREStringLang) instance).getLang());
507 }
508
509
510 return ResourceFactory.createTypedLiteral(instance);
511 }
512
513
514
515
516
517
518
519
520 @Override
521 public String askExist(MREData instance) {
522
523 StringBuilder sb = new StringBuilder();
524 MREDataFieldValue[] fields = dataService.builderValuesGet(instance);
525 int i = 0;
526
527
528 buildTripleRDFType(sb, fields, i, instance);
529
530 String ask = TEMPLATE_ASK.replace("TRIPLES", sb.toString());
531
532 return ask;
533 }
534
535 @Override
536 public String selectType(String resourceURI) {
537
538 StringBuilder sb = new StringBuilder();
539 sb.append("SELECT DISTINCT ?type WHERE { ");
540 sb.append("<").append(resourceURI).append("> ");
541 sb.append("<").append(RDF.type).append("> ");
542 sb.append("?type . } ");
543
544 return sb.toString();
545 }
546
547 @Override
548 public String selectType(Resource resource) {
549
550 return selectType(resource.getURI());
551 }
552
553 @Override
554 public String getGraph() {
555 return graph;
556 }
557
558 @Override
559 public void setGraph(String graph) {
560 this.graph = graph;
561 }
562
563 }