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.util;
23  
24  import cz.zcu.mre.annotation.data.MREDataOntology;
25  import cz.zcu.mre.data.core.MREData;
26  import java.lang.reflect.Field;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Objects;
31  import java.util.Set;
32  import java.util.stream.Collectors;
33  import org.apache.jena.ontology.Individual;
34  import org.apache.jena.rdf.model.Resource;
35  import org.reflections.Reflections;
36  import org.reflections.scanners.Scanners;
37  import org.reflections.util.ClasspathHelper;
38  import org.reflections.util.ConfigurationBuilder;
39  import org.reflections.util.FilterBuilder;
40  import org.slf4j.Logger;
41  import org.slf4j.LoggerFactory;
42  
43  /**
44   * Reflections Utilities.
45   *
46   * @author Petr Vcelak (vcelak@kiv.zcu.cz)
47   */
48  public class ReflectionsUtil {
49  
50      private static final Logger LOG = LoggerFactory.getLogger(ReflectionsUtil.class);
51  
52      /**
53       * Map of annotated MREData classes.
54       */
55      private static final Map<String, Class<? extends MREData>> annotatedJavaClasses = new HashMap<>();
56      private static final Map<Resource, Individual> individuals = new HashMap<>();
57  
58      public static final Class<? extends MREData> lookForAnnotatedJavaClass(final Resource type) {
59  
60          if (type == null) {
61              throw new IllegalArgumentException("Cannot look for null type.");
62          }
63  
64          if (annotatedJavaClasses.containsKey(type.getURI())) {
65              return annotatedJavaClasses.get(type.getURI());
66          }
67  
68          /* Have to do look up using Reflections. */
69          final String pkg = "cz.zcu.mre";
70          final FilterBuilder filterBuilder = new FilterBuilder();
71          filterBuilder.includePackage(pkg);
72  
73          final ConfigurationBuilder confBuilder = new ConfigurationBuilder();
74          confBuilder.addUrls(ClasspathHelper.forPackage(pkg));
75          confBuilder.filterInputsBy(filterBuilder).setScanners(Scanners.SubTypes, Scanners.TypesAnnotated);
76  
77          Reflections reflections = new Reflections(confBuilder);
78          Set<Class<? extends MREData>> classes = reflections.getSubTypesOf(MREData.class);
79          for (Class<? extends MREData> clazz : classes) {
80              LOG.debug("Check class {}", clazz);
81  
82              if (clazz.isAnnotationPresent(MREDataOntology.class)) {
83                  String namespace = clazz.getAnnotation(MREDataOntology.class).namespace();
84                  String name = clazz.getSimpleName();
85                  String uri = namespace.concat(name);
86                  if (type.getURI().equals(uri)) {
87  
88                      // found, save to hash map
89                      annotatedJavaClasses.put(uri, clazz);
90                      return clazz;
91                  }
92              }
93          }
94  
95          return null;
96      }
97  
98      public static final Individual lookupIndividual(final Resource resource) {
99  
100         if (resource == null) {
101             throw new IllegalArgumentException("Cannot look for null resource.");
102         }
103         LOG.debug("Lookup for Individual for {}", resource.getURI());
104 
105         if (individuals.containsKey(resource)) {
106             return individuals.get(resource);
107         }
108 
109         /* Have to do look up using Reflections. */
110         final String pkg = "cz.zcu.mre.vocab";
111         Reflections reflections = new Reflections(pkg, Scanners.SubTypes.filterResultsBy(c -> true));
112         Set<Class<? extends Object>> allClasses = reflections.getSubTypesOf(Object.class);
113 
114         List<Individual> fields = allClasses.stream().map(cls -> {
115             Individual individual;
116             for (Field f : cls.getDeclaredFields()) {
117                 if (f.getType() == Individual.class) {
118                     // field has Individual type
119                     try {
120                         individual = (Individual) f.get(null);
121                         if (resource.getURI().equals(individual.getURI())) {
122                             // individual is defined by the same URI as required
123 
124                             // save to hash map
125                             individuals.put(resource, individual);
126                             return individual;
127                         }
128                     } catch (IllegalArgumentException | IllegalAccessException ex) {
129                         LOG.error(null, ex);
130                     }
131                 }
132             }
133 
134             return null;
135         }).filter(Objects::nonNull).collect(Collectors.toList());
136 
137         if (fields.isEmpty()) {
138             return null;
139         }
140         return fields.get(0);
141     }
142 }