View Javadoc
1   /*
2    * Copyright 2018-2022 Medical Information Systems Research Group (https://medical.zcu.cz),
3    * Department of Computer Science and Engineering, University of West Bohemia.
4    * Address: Univerzitni 8, 306 14 Plzen, Czech Republic.
5    *
6    * Author Petr Vcelak (vcelak@kiv.zcu.cz).
7    *
8    * This file is part of MRECore project.
9    *
10   * MRECore is free software: you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation, either version 3 of the License.
13   *
14   * MRECore is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with MRECore. If not, see <http://www.gnu.org/licenses/>.
21   */
22  package cz.zcu.mre.data.core;
23  
24  import cz.zcu.mre.mrelib.util.HashGenerator;
25  import cz.zcu.mre.vocab.NS;
26  import java.util.ArrayList;
27  import java.util.HashSet;
28  import java.util.List;
29  import java.util.Set;
30  import org.apache.jena.rdf.model.Literal;
31  import org.apache.jena.rdf.model.Model;
32  import org.apache.jena.rdf.model.ModelFactory;
33  import org.apache.jena.rdf.model.Property;
34  import org.apache.jena.rdf.model.Resource;
35  import org.apache.jena.rdf.model.Statement;
36  import org.apache.jena.rdf.model.StmtIterator;
37  import org.apache.jena.vocabulary.RDFS;
38  import org.apache.jena.vocabulary.SKOS;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  /**
43   * Main implementation for MREData interface.
44   *
45   * @author Petr Vcelak (vcelak@kiv.zcu.cz)
46   */
47  public class MREDataImpl implements MREData {
48  
49      private static final Logger LOG = LoggerFactory.getLogger(MREDataImpl.class);
50  
51      private Resource resource = null;
52  
53      /**
54       * Default instance privateModel.
55       */
56      protected static final Model privateModel = ModelFactory.createDefaultModel();
57  
58      public MREDataImpl() {
59      }
60  
61      public MREDataImpl(Resource resource) {
62          setResource(resource);
63      }
64  
65      public MREDataImpl(String uri) {
66          setResource(uri);
67      }
68  
69      @Override
70      public Resource generateNewResource() {
71          setResource(NS.ID.concat(HashGenerator.sha1Random()));
72  
73          return getResource();
74      }
75  
76      @Override
77      public Resource getResource() {
78  
79          if (resource == null) {
80              LOG.warn("MREData resource is null. Still not initialized? First, use generateNewResource() or setResource() methods.");
81          }
82  
83          return resource;
84      }
85  
86      @Override
87      public final void setResource(Resource resource) {
88  
89          if (resource == null) {
90              generateNewResource();
91          } else {
92              this.resource = privateModel.createResource(resource.getURI());
93          }
94      }
95  
96      @Override
97      public final void setResource(String uri) {
98  
99          if (uri == null || uri.isEmpty()) {
100             generateNewResource();
101             LOG.warn("Empty or null resource not allowed. New resource were auto-generated: {}", getResource());
102         } else {
103             this.resource = privateModel.createResource(uri);
104         }
105     }
106 
107     @Override
108     public boolean hasURI() {
109         return resource != null && resource.isResource();
110     }
111 
112     @Override
113     public boolean isEmpty() {
114         return !hasURI();
115     }
116 
117     @Override
118     public String getUri() {
119 
120         if (hasURI()) {
121             return getResource().getURI();
122         }
123 
124         return null;
125     }
126 
127     @Override
128     public String getId() {
129 
130         if (hasURI()) {
131 
132             String localName = getResource().getLocalName();
133 
134             /**
135              * FIXED - It is not possible to get a local name when URI without
136              * hash mark occurs. In that case, test and remove MRE-ID.
137              */
138             if (localName == null) {
139                 String uri = getResource().getURI();
140 
141                 if (uri.toLowerCase().startsWith(NS.ID)) {
142                     localName = uri.replace(NS.ID, "");
143                 }
144             }
145 
146             return localName;
147         }
148 
149         return null;
150     }
151 
152     @Override
153     public void setId(String id) {
154 
155         if (id == null || id.isEmpty()) {
156             generateNewResource();
157             LOG.warn("Empty or null ID not allowed. New resource were auto-generated: {}", getResource());
158         } else {
159             setResource(MREDataAnnotation.NS.concat(id));
160         }
161     }
162 
163     @Override
164     public Set<Resource> getType() {
165 
166         Set<Resource> result = new HashSet<>();
167 
168         if (isEmpty()) {
169             LOG.warn("No rdf:type because resource is null.");
170             return result;
171         }
172 
173         StmtIterator it = resource.listProperties(MREDataAnnotation.TYPE);
174         while (it.hasNext()) {
175             Resource type = it.next().getResource();
176             result.add(type);
177         }
178 
179         return result;
180     }
181 
182     @Override
183     public boolean hasType() {
184         return !getType().isEmpty();
185     }
186 
187     @Override
188     public boolean hasType(Resource type) {
189 
190         Set<Resource> types = getType();
191 
192         return types.contains(type);
193     }
194 
195     @Override
196     public List<? extends Resource> getTypeList() {
197 
198         List<Resource> result = new ArrayList<>();
199         Set<Resource> types = getType();
200 
201         result.addAll(types);
202 
203         return result;
204     }
205 
206     @Override
207     public void setType(Resource type) {
208 
209         if (type == null) {
210             return;
211         }
212 
213         if (isEmpty()) {
214             LOG.warn("Cannot set type because resource is null.");
215             return;
216         }
217 
218         resource.addProperty(MREDataAnnotation.TYPE, type);
219     }
220 
221     @Override
222     public void setTypeList(List<Resource> types) {
223 
224         types.forEach((r) -> {
225             setType(r);
226         });
227     }
228 
229     @Override
230     public String getLabel() {
231 
232         if (isEmpty()) {
233             LOG.warn("Cannot get rdfs:label because resource is null.");
234             return null;
235         }
236 
237         Statement s = resource.getProperty(RDFS.label);
238         if (s != null) {
239             return s.getString();
240         }
241 
242         return null;
243     }
244 
245     @Override
246     public void setLabel(String label) {
247 
248         if (isEmpty()) {
249             LOG.warn("Cannot set rdfs:label because resource is null.");
250             return;
251         }
252 
253         resource.addProperty(RDFS.label, label);
254     }
255 
256     @Override
257     public void setLabel(String label, String lang) {
258 
259         if (isEmpty()) {
260             LOG.warn("Cannot set rdfs:label because resource is null.");
261             return;
262         }
263 
264         resource.addProperty(RDFS.label, label, lang);
265     }
266 
267     @Override
268     public String getTitle() {
269 
270         if (isEmpty()) {
271             LOG.warn("Cannot get title because resource is null.");
272             return null;
273         }
274 
275         // TODO improve by using the list of preferred languages (user-defined),
276         // not only list of preffered titles.
277         for (Property titleVariant : MREDataTitles.TITLES) {
278 
279             Statement s = resource.getProperty(titleVariant);
280             if (s != null) {
281                 return s.getString();
282             }
283 
284         }
285 
286         return null;
287     }
288 
289     @Override
290     public String getTitle(String lang) {
291 
292         if (isEmpty()) {
293             LOG.warn("Cannot get title because resource is null.");
294             return null;
295         }
296 
297         for (Property titleVariant : MREDataTitles.TITLES) {
298 
299             Statement s = resource.getProperty(titleVariant, lang);
300             if (s != null) {
301                 return s.getString();
302             }
303 
304         }
305 
306         return null;
307     }
308 
309     @Override
310     public void setTitle(String title) {
311 
312         if (isEmpty()) {
313             LOG.warn("Cannot set title because resource is null.");
314             return;
315         }
316         resource.addProperty(MREDataTitles.TITLES[1], title);
317     }
318 
319     @Override
320     public void setTitle(String title, String lang) {
321 
322         if (isEmpty()) {
323             LOG.warn("Cannot get title because resource is null.");
324             return;
325         }
326 
327         resource.addProperty(MREDataTitles.TITLES[1], title, lang);
328     }
329 
330     @Override
331     public String getLabelPreferred() {
332 
333         if (isEmpty()) {
334             LOG.warn("Cannot get skos:prefLabel because resource is null.");
335             return null;
336         }
337 
338         Statement s = resource.getProperty(SKOS.prefLabel);
339         if (s != null) {
340             return s.getString();
341         }
342 
343         return null;
344     }
345 
346     @Override
347     public void setLabelPreferred(String prefLabel) {
348 
349         if (isEmpty()) {
350             LOG.warn("Cannot set skos:prefLabel because resource is null.");
351             return;
352         }
353         resource.addProperty(SKOS.prefLabel, prefLabel);
354     }
355 
356     @Override
357     public void setLabelPreferred(String prefLabel, String lang) {
358 
359         if (isEmpty()) {
360             LOG.warn("Cannot set skos:prefLabel because resource is null.");
361             return;
362         }
363 
364         resource.addProperty(SKOS.prefLabel, prefLabel, lang);
365     }
366 
367     @Override
368     public void addValue(Property property, String string) {
369 
370         if (isEmpty()) {
371             LOG.warn("Cannot add value because resource is null.");
372             return;
373         }
374 
375         resource.addLiteral(property, string);
376     }
377 
378     @Override
379     public void addValue(Property property, String string, String lang) {
380 
381         if (isEmpty()) {
382             LOG.warn("Cannot add value because resource is null.");
383             return;
384         }
385 
386         resource.addProperty(property, string, lang);
387     }
388 
389     @Override
390     public void addValue(Property property, Resource res) {
391 
392         if (isEmpty()) {
393             LOG.warn("Cannot add value because resource is null.");
394             return;
395         }
396 
397         resource.addProperty(property, res);
398     }
399 
400     /**
401      * This implementation does no difference between methods hasProperty and
402      * hasValue.
403      *
404      * @param property The property.
405      * @return True if property exist.
406      */
407     @Override
408     public boolean hasProperty(Property property) {
409 
410         return hasValue(property);
411     }
412 
413     @Override
414     public void removeValues(Property property) {
415 
416         if (isEmpty()) {
417             LOG.warn("Cannot remove value(s) because resource is null.");
418             return;
419         }
420 
421         resource.removeAll(property);
422     }
423 
424     @Override
425     public Set<Resource> getValuesResource(Property property) {
426 
427         Set<Resource> result = new HashSet<>();
428 
429         if (isEmpty()) {
430             LOG.warn("Cannot get values(s) because resource is null.");
431             return result;
432         }
433 
434         StmtIterator it = resource.listProperties(property);
435 
436         while (it.hasNext()) {
437             Statement statement = it.next();
438 
439             if (statement != null && statement.getObject().isResource()) {
440                 Resource r = statement.getResource();
441                 result.add(r);
442             } else {
443                 LOG.warn("Null statement or statement is not a literal: {}", statement);
444             }
445         }
446 
447         return result;
448     }
449 
450     @Override
451     public Set<Literal> getValuesLiteral(Property property) {
452 
453         Set<Literal> result = new HashSet<>();
454 
455         if (isEmpty()) {
456             LOG.warn("Cannot get values(s) because resource is null.");
457             return result;
458         }
459 
460         StmtIterator it = resource.listProperties(property);
461 
462         while (it.hasNext()) {
463             Statement statement = it.next();
464 
465             if (statement != null && statement.getObject().isLiteral()) {
466                 Literal l = statement.getLiteral();
467                 result.add(l);
468             } else {
469                 LOG.warn("Null statement or statement is not a literal: {}", statement);
470             }
471         }
472 
473         return result;
474     }
475 
476     @Override
477     public Set<String> getValuesString(Property property) {
478 
479         Set<String> result = new HashSet<>();
480         Set<Literal> set = getValuesLiteral(property);
481         if (set.isEmpty()) {
482             LOG.warn("Cannot get values(s) because resource is null.");
483             return result;
484         }
485 
486         set.stream().map((l) -> l.getString()).forEachOrdered((string) -> {
487             result.add(string);
488         });
489 
490         return result;
491     }
492 
493     @Override
494     public Set<Object> getValuesObject(Property property) {
495 
496         Set<Object> result = new HashSet<>();
497 
498         if (isEmpty()) {
499             LOG.warn("Cannot get values(s) because resource is null.");
500             return result;
501         }
502 
503         StmtIterator it = resource.listProperties(property);
504 
505         while (it.hasNext()) {
506             Statement statement = it.next();
507 
508             if (statement == null) {
509                 LOG.warn("Null statement for property {}", property.getURI());
510                 continue;
511             }
512 
513             if (statement.getObject().isResource()) {
514                 Resource r = statement.getResource();
515                 result.add(r);
516             } else if (statement.getObject().isLiteral()) {
517                 Literal l = statement.getLiteral();
518                 result.add(l);
519             } else {
520                 LOG.warn("Statement {} has not supported type.", statement);
521             }
522         }
523 
524         return result;
525     }
526 
527     @Override
528     public boolean hasValue(Property property) {
529 
530         if (isEmpty()) {
531             LOG.warn("Cannot check for property value because resource is null.");
532             return false;
533         }
534 
535         return resource.hasProperty(property);
536     }
537 
538     @Override
539     public boolean hasValue(Property property, Object value) {
540 
541         Set<Object> values = getValuesObject(property);
542         return values.stream().anyMatch((o) -> (o.equals(value)));
543     }
544 
545 }