1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.sumaris.rdf.util;
24
25 import net.sumaris.core.model.referential.Status;
26 import net.sumaris.core.model.referential.taxon.TaxonName;
27 import net.sumaris.core.model.referential.taxon.TaxonomicLevel;
28 import org.apache.jena.ontology.OntClass;
29 import org.apache.jena.ontology.OntResource;
30 import org.apache.jena.rdf.model.RDFNode;
31 import org.apache.jena.rdf.model.Resource;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import javax.persistence.EntityManager;
36 import javax.persistence.Id;
37 import java.lang.annotation.Annotation;
38 import java.lang.reflect.Field;
39 import java.lang.reflect.Method;
40 import java.util.*;
41 import static net.sumaris.rdf.util.OwlUtils.*;
42
43 public abstract class Owl2Bean {
44
45
46
47 private static Logger log = LoggerFactory.getLogger(Owl2Bean.class);
48
49 private EntityManager entityManager;
50
51 private String modelPrefix;
52
53 public Owl2Bean(EntityManager entityManager, String modelPrefix) {
54 this.entityManager = entityManager;
55 this.modelPrefix = modelPrefix;
56 }
57
58 protected String getModelPrefix() {
59 return modelPrefix;
60 }
61
62 protected EntityManager getEntityManager() {
63 return entityManager;
64 }
65
66 public Optional<Class> ontToJavaClass(OntClass ontClass, RdfImportContext context) {
67 String uri = ontClass.getURI();
68 if (uri != null) {
69 if (uri.contains("#")) {
70 uri = uri.substring(0, uri.indexOf("#"));
71 log.warn(" tail '#' " + uri);
72 }
73 if (uri.contains("<")) {
74 uri = uri.substring(0, uri.indexOf("<"));
75 log.warn(" tail <parametrized> " + uri);
76 }
77 }
78
79 if (uri == null) {
80 log.error(" uri null for OntClass " + ontClass);
81 return Optional.empty();
82 }
83
84
85 String cName = uri.substring(uri.lastIndexOf("/") + 1);
86 Class clazz = context.URI_2_CLASS.get(cName);
87
88 if (clazz == null) {
89 log.warn(" clazz not mapped for class " + cName);
90 return Optional.empty();
91 }
92
93 if (clazz.isInterface()) {
94 log.warn(" corresponding Type is interface, skip instances " + clazz);
95 return Optional.empty();
96 }
97 return Optional.of(clazz);
98 }
99
100 protected boolean classEquals(Class c, Class<?> d) {
101 return Objects.equals(d.getTypeName(), c.getTypeName());
102 }
103
104 protected abstract List getCacheTL();
105 protected abstract List getCacheStatus();
106
107 protected Object getTranslatedReference(RDFNode val, Class<?> setterParam, Object obj, RdfImportContext context) {
108
109 String identifier = val.toString();
110 String ontClass = null;
111 if (identifier.contains("#")) {
112 ontClass = identifier.substring(0, identifier.indexOf("#"));
113 identifier = identifier.substring(identifier.indexOf("#") + 1);
114 }
115 if (setterParam == TaxonomicLevel.class) {
116
117 for (Object ctl : getCacheTL()) {
118 String lab = ((TaxonomicLevel) ctl).getLabel();
119 if (identifier.endsWith(lab)) {
120 return ctl;
121 }
122 }
123
124
125
126 TaxonomicLevelxonomicLevel./../../net/sumaris/core/model/referential/taxon/TaxonomicLevel.html#TaxonomicLevel">TaxonomicLevel tl = (TaxonomicLevelxonomicLevel) context.URI_2_OBJ_REF.getOrDefault(val.toString(), new TaxonomicLevel());
127 tl.setLabel(identifier);
128 tl.setCreationDate(new Date());
129 tl.setName("");
130 tl.setRankOrder(1);
131 tl.setStatus((Status) getCacheStatus().get(0));
132
133 getEntityManager().persist(tl);
134 log.warn("getEntityManager().persist( TaxonomicLevel ) " + tl);
135
136
137
138 return context.URI_2_OBJ_REF.putIfAbsent(val.toString(), tl);
139 }
140
141
142
143 log.warn("getTranslatedReference " + identifier + " - " + val + " - " + obj);
144 Object ref;
145 try {
146 Integer asInt = Integer.parseInt(identifier);
147 ref = getEntityManager().getReference(setterParam, asInt);
148 } catch (NumberFormatException e) {
149 ref = getEntityManager().getReference(setterParam, identifier);
150 }
151 return ref;
152 }
153
154 protected String attributeOf(String pred) {
155 String fName = pred.substring(pred.indexOf("#") + 1);
156 fName = fName.substring(0, 1).toLowerCase() + fName.substring(1);
157 return fName;
158 }
159
160 protected void fillObjectWithStdAttribute(Method setter, Object obj, RDFNode val) {
161 String value = val.isURIResource() ? val.toString().substring(val.toString().lastIndexOf("#") + 1) : val.toString();
162 Class<?> setterParam = setter.getParameterTypes()[0];
163 try {
164 if (classEquals(setterParam, String.class)) {
165 setter.invoke(obj, val.asLiteral().getString());
166 }
167 if (classEquals(setterParam, Long.class) || classEquals(setterParam, long.class)) {
168 setter.invoke(obj, val.asLiteral().getLong());
169 } else if (classEquals(setterParam, Integer.class) || classEquals(setterParam, int.class)) {
170 setter.invoke(obj, Integer.parseInt(value));
171 } else if (classEquals(setterParam, Date.class)) {
172 setter.invoke(obj, OwlUtils.SIMPLE_DATE_FORMAT.parse(val.asLiteral().getString()));
173 } else if (classEquals(setterParam, Boolean.class) || classEquals(setterParam, boolean.class)) {
174 setter.invoke(obj, val.asLiteral().getBoolean());
175 }
176 } catch (Exception e) {
177 log.warn("fillObjectWithStdAttribute could not reconstruct attribute "
178 + setter.getDeclaringClass().getSimpleName() + "." + setter.getName() + "(" + setterParam.getSimpleName() + ") for val " + val, e);
179 }
180 }
181
182 public Optional<Object> owl2Bean(Resource ont, OntResource ontResource, Class clazz, RdfImportContext context) {
183 log.info("processing ont Instance " + ontResource + " - " +
184 ontResource
185 .asIndividual()
186 .listProperties().toList().size());
187
188 try {
189 Object obj = clazz.newInstance();
190
191 ontResource
192 .asIndividual()
193 .listProperties()
194 .toList()
195 .forEach(stmt -> {
196 String pred = stmt.getPredicate().getURI();
197 RDFNode val = stmt.getObject();
198 if ((pred.startsWith(getModelPrefix()) || pred.startsWith(OwlUtils.ADAGIO_PREFIX)) && pred.contains("#")) {
199 String fName = attributeOf(pred);
200 try {
201
202 Optional<Method> setter;
203 if ("setId".equals(fName)) {
204 setter = findSetterAnnotatedID(ont, clazz, context);
205 } else {
206 setter = setterOfField(ont, clazz, fName, context);
207 }
208
209 if (setter.isPresent()) {
210 Class<?> setterParam = setter.get().getParameterTypes()[0];
211
212 if (log.isTraceEnabled()) log.trace("Trying to insert " + fName + " => " + val + " using method ??");
213
214 if (isJavaType(setterParam)) {
215 fillObjectWithStdAttribute(setter.get(), obj, val);
216 } else {
217
218 setter.get().invoke(obj, getTranslatedReference(val, setterParam, obj, context));
219 }
220 }
221
222 } catch (Exception e) {
223 log.error(String.format("%s on field %s => %s using class %s using method %s %s",
224 e.getClass().getSimpleName(), fName, val, clazz, setterOfField(ont, clazz, fName, context), e.getMessage()), e);
225 }
226
227
228 }
229
230 });
231 if (obj instanceof TaxonName) {
232 TaxonName"../../../../net/sumaris/core/model/referential/taxon/TaxonName.html#TaxonName">TaxonName tn = (TaxonName) obj;
233
234 tn.setReferenceTaxon(null);
235 getEntityManager().merge(tn);
236 }
237
238 log.info(" - created object " + ontResource + " - " + " of class " + ontResource.getClass() + " - ");
239 return Optional.of(obj);
240 } catch (Exception e) {
241 log.error(" processing individual " + ontResource + " - " + clazz, e);
242 }
243 return Optional.empty();
244 }
245
246
247 protected Optional<Method> findSetterAnnotatedID(Resource ont, Class clazz, RdfImportContext context) {
248 for (Field f : clazz.getDeclaredFields())
249 for (Annotation an : f.getDeclaredAnnotations())
250 if (an instanceof Id) {
251 return setterOfField(ont, clazz, f.getName(), context);
252
253 }
254 return Optional.empty();
255 }
256
257 }