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.config.ApplicationConfiguration;
25 import cz.zcu.mre.data.rdf.ResourceWrapperComparator;
26 import cz.zcu.mre.data.rdf.VocabularyWrapper;
27 import cz.zcu.mre.vocab.FORM;
28 import cz.zcu.mre.vocab.IBDT;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.concurrent.ConcurrentHashMap;
34 import jakarta.servlet.ServletContext;
35 import org.apache.jena.ontology.Individual;
36 import org.apache.jena.ontology.OntClass;
37 import org.apache.jena.ontology.OntResource;
38 import org.apache.jena.rdf.model.RDFNode;
39 import org.apache.jena.rdf.model.Resource;
40 import org.apache.jena.rdf.model.ResourceFactory;
41 import org.apache.jena.util.iterator.ExtendedIterator;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.beans.factory.annotation.Autowired;
45 import org.springframework.context.annotation.Scope;
46 import org.springframework.context.annotation.ScopedProxyMode;
47 import org.springframework.context.event.ContextRefreshedEvent;
48 import org.springframework.context.event.EventListener;
49
50
51
52
53
54
55
56
57 @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
58 public class VocabularyServiceImpl implements VocabularyService {
59
60 private static final Logger LOG = LoggerFactory.getLogger(VocabularyServiceImpl.class);
61
62 private static final String WARN_MSG = "Missing label for property {}";
63
64
65
66
67 private static final ResourceWrapperComparator resourceWraperComparator = new ResourceWrapperComparator();
68
69
70
71
72 private final Map<Resource, List<VocabularyWrapper>> vocabularyMap = new ConcurrentHashMap<>();
73
74
75
76 private final Map<String, VocabularyWrapper> individualMap = new ConcurrentHashMap<>();
77
78 @Autowired
79 private OntologyService ontologyService;
80
81 @Autowired
82 private ServletContext servletContext;
83
84
85
86
87
88
89
90
91
92
93
94 @EventListener
95 protected void handleContextRefresh(ContextRefreshedEvent e) {
96 LOG.info("Add VocabularyService on the event ContextRefreshedEvent.");
97
98
99 servletContext.setAttribute("vocab", this);
100 }
101
102 @Override
103 public void afterPropertiesSet() throws Exception {
104 LOG.info("VocabularyService - prepare");
105 loadVocabularies();
106 LOG.info("VocabularyService - prepare - done.");
107 }
108
109 private void loadVocabularies() {
110
111 List<OntClass> ontClassList = ontologyService.getVocabularyList();
112 ontClassList.forEach((ontClass) -> {
113 List<VocabularyWrapper> vwList = new ArrayList<>();
114 ExtendedIterator<? extends OntResource> it = ontClass.listInstances();
115 while (it.hasNext()) {
116 OntResource ontResource = it.next();
117 LOG.debug("Loaded vocabulary {} instance {}.", ontClass.getURI(), ontResource.getURI());
118 VocabularyWrapper vw = createVocabularyWrapper(ontClass, ontResource);
119
120
121 vwList.add(vw);
122
123
124 individualMap.put(ontResource.getURI(), vw);
125 }
126
127
128 if (vwList.isEmpty()) {
129
130 vocabularyMap.put(ontClass, Collections.EMPTY_LIST);
131 } else {
132
133
134 LOG.debug("Sort vocabulary {} items ({}).", ontClass.getURI(), vwList.size());
135 vwList.sort(resourceWraperComparator);
136
137
138 vocabularyMap.put(ontClass, vwList);
139 }
140 });
141 }
142
143 private VocabularyWrapper createVocabularyWrapper(OntClass ontClazz, OntResource ontResource) {
144
145 LOG.debug("Create VocabularyWrapper for vocabulary {} and instance {}", ontClazz.getURI(), ontResource.getURI());
146 VocabularyWrapper vw = new VocabularyWrapper(ontResource);
147
148
149 String label = ontResource.getLabel(ApplicationConfiguration.DEFAULT_LANGUAGE);
150 if (label == null || label.isEmpty()) {
151 label = ontResource.getLabel(null);
152 }
153 vw.setLabel(label);
154
155
156 if (ontResource.hasProperty(FORM.CODE)) {
157 String code = ontResource.getProperty(FORM.CODE).getString();
158 if (code == null || code.isEmpty()) {
159 code = label;
160 }
161 vw.setItemCode(code);
162 }
163
164
165 RDFNode node = ontResource.getPropertyValue(FORM.VOCABULARY_ITEM_ID);
166 if (node != null && node.asLiteral() != null) {
167 int order = node.asLiteral().getInt();
168 vw.setIntOrder(order);
169 } else {
170
171
172 node = ontResource.getPropertyValue(FORM.VOCABULARY_LINE_NUMBER);
173 if (node != null && node.asLiteral() != null) {
174 int order = node.asLiteral().getInt();
175 vw.setIntOrder(order);
176 }
177 }
178
179 return vw;
180 }
181
182 @Override
183 public List<VocabularyWrapper> itemsList(String rdfClass) {
184
185 LOG.debug("List items of class {}", rdfClass);
186 return itemsList(ResourceFactory.createResource(rdfClass));
187 }
188
189 @Override
190 public List<VocabularyWrapper> itemsList(Resource rdfClass) {
191
192 LOG.debug("List items of {}", rdfClass.getURI());
193
194 if (vocabularyMap.containsKey(rdfClass)) {
195 LOG.debug("List items of {} - using hash map.", rdfClass.getURI());
196 return vocabularyMap.get(rdfClass);
197 }
198
199 return Collections.EMPTY_LIST;
200 }
201
202 @Override
203 public VocabularyWrapper item(String uri) {
204
205 return individualMap.get(uri);
206 }
207
208 @Override
209 public String label(Resource resource) {
210
211 if (resource == null) {
212 return "";
213 }
214
215 if (individualMap.containsKey(resource.getURI())) {
216 LOG.debug("Get prepared label for individual {}", resource);
217 return individualMap.get(resource.getURI()).getLabel();
218 }
219
220 LOG.warn(WARN_MSG, resource);
221 return resource.getLocalName();
222 }
223
224 @Override
225 public String code(Resource resource) {
226
227 if (resource == null) {
228 return "";
229 }
230
231 if (individualMap.containsKey(resource.getURI())) {
232 LOG.debug("Get prepared code for resource {}", resource);
233 return individualMap.get(resource.getURI()).getItemCode();
234 }
235
236 LOG.warn(WARN_MSG, resource);
237 return resource.getLocalName();
238 }
239
240 @Override
241 public boolean itemExist(Resource rdfClass) {
242
243 if (vocabularyMap.containsKey(rdfClass)) {
244 return true;
245 }
246
247 return !itemsList(rdfClass).isEmpty();
248 }
249
250 @Override
251 public int itemCount(Resource rdfClass) {
252
253 if (vocabularyMap.containsKey(rdfClass)) {
254 return vocabularyMap.get(rdfClass).size();
255 }
256
257 return itemsList(rdfClass).size();
258 }
259
260 @Override
261 public boolean itemByCodeExist(Resource rdfClass, String itemCode) {
262
263 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
264
265
266 return vocabularyContent.stream().map((vw) -> (Individual) vw.getResource()).map((individual) -> individual.getPropertyValue(FORM.CODE)).anyMatch((node) -> (node != null && node.asLiteral().getString().equals(itemCode)));
267 }
268
269 @Override
270 public VocabularyWrapper itemByCode(Resource rdfClass, String itemCode) {
271
272 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
273
274 for (VocabularyWrapper vw : vocabularyContent) {
275
276 Individual individual = (Individual) vw.getResource();
277
278
279 RDFNode node = individual.getPropertyValue(FORM.CODE);
280 if (node != null && node.asLiteral().getString().equals(itemCode)) {
281 return vw;
282 }
283 }
284 return null;
285 }
286
287 @Override
288 public VocabularyWrapper itemByNumber(Resource rdfClass, int number) {
289
290 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
291
292 for (VocabularyWrapper vw : vocabularyContent) {
293
294 Individual individual = (Individual) vw.getResource();
295
296
297 RDFNode node = individual.getPropertyValue(FORM.CODE);
298 if (node != null && node.asLiteral().getInt() == number) {
299 return vw;
300 }
301 }
302
303 return null;
304 }
305
306 @Override
307 public boolean itemByNumberExist(Resource rdfClass, int number) {
308
309 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
310
311
312 return vocabularyContent.stream().map((vw) -> (Individual) vw.getResource()).map((individual) -> individual.getPropertyValue(FORM.CODE)).anyMatch((node) -> (node != null && node.asLiteral().getInt() == number));
313 }
314
315 @Override
316 public VocabularyWrapper itemDefault(String rdfClass) {
317
318 return itemDefault(ResourceFactory.createResource(rdfClass));
319 }
320
321 @Override
322 public VocabularyWrapper itemDefault(Resource rdfClass) {
323
324 VocabularyWrapper first = null;
325
326 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
327 for (VocabularyWrapper vw : vocabularyContent) {
328 Individual individual = (Individual) vw.getResource();
329
330
331 RDFNode node = individual.getPropertyValue(FORM.VOCABULARY_ITEM_ID);
332 if (first == null && node != null && node.asLiteral().getInt() == 1) {
333 first = vw;
334 }
335
336 node = individual.getPropertyValue(FORM.IS_DEFAULT_VALUE);
337 if (node != null && node.asLiteral().getBoolean()) {
338 return vw;
339 }
340 }
341
342
343 return first;
344 }
345
346 @Override
347 public VocabularyWrapper itemFirst(Resource rdfClass) {
348
349 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
350 if (vocabularyContent.isEmpty()) {
351 return null;
352 }
353
354 return vocabularyContent.get(0);
355
356 }
357
358 @Override
359 public VocabularyWrapper itemLast(Resource rdfClass) {
360
361 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
362 if (vocabularyContent.isEmpty()) {
363 return null;
364 }
365
366 return vocabularyContent.get(vocabularyContent.size() - 1);
367 }
368
369 public float itemScore(Individual individual) {
370
371 RDFNode node = individual.getPropertyValue(FORM.SCORE);
372 if (node != null) {
373 return node.asLiteral().getFloat();
374 }
375
376 return Float.NaN;
377 }
378
379 public float itemCheckScore(Individual individual) {
380
381 RDFNode node = individual.getPropertyValue(FORM.SCORE);
382 if (node != null) {
383 return node.asLiteral().getFloat();
384 }
385
386 return Float.NaN;
387 }
388
389 @Override
390 public List<VocabularyWrapper> itemsFilteredByAgeSex(Resource rdfClass, int age, String sex) {
391
392 List<VocabularyWrapper> filteredList = new ArrayList<>();
393 List<VocabularyWrapper> vocabularyContent = itemsList(rdfClass);
394 vocabularyContent.forEach((vw) -> {
395 int ageMin = Integer.MIN_VALUE;
396 int ageMax = Integer.MAX_VALUE;
397 Individual individual = (Individual) vw.getResource();
398 RDFNode node = individual.getPropertyValue(IBDT.COND_SEX);
399 if (!(node != null && node.asLiteral().getString().equals(sex))) {
400 node = individual.getPropertyValue(IBDT.AGE_MIN);
401 if (node != null) {
402 ageMin = node.asLiteral().getInt();
403 }
404 node = individual.getPropertyValue(IBDT.AGE_MAX);
405 if (node != null) {
406 ageMax = node.asLiteral().getInt();
407 }
408
409 if (ageMin < age && age < ageMax) {
410 filteredList.add(vw);
411 }
412 }
413 });
414
415 return filteredList;
416 }
417 }