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 com.google.common.collect.ImmutableMap;
26 import org.apache.jena.ontology.OntClass;
27 import org.apache.jena.ontology.OntModel;
28 import org.apache.jena.ontology.OntProperty;
29 import org.apache.jena.rdf.model.Model;
30 import org.apache.jena.rdf.model.Resource;
31 import org.apache.jena.vocabulary.*;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import javax.persistence.Id;
36 import javax.persistence.ManyToOne;
37 import java.io.ByteArrayOutputStream;
38 import java.io.IOException;
39 import java.lang.annotation.Annotation;
40 import java.lang.reflect.Field;
41 import java.lang.reflect.Method;
42 import java.lang.reflect.ParameterizedType;
43 import java.lang.reflect.Type;
44 import java.sql.Timestamp;
45 import java.text.SimpleDateFormat;
46 import java.time.Instant;
47 import java.time.LocalDate;
48 import java.time.LocalDateTime;
49 import java.time.ZoneId;
50 import java.time.format.DateTimeFormatter;
51 import java.util.*;
52 import java.util.stream.Collectors;
53 import java.util.stream.Stream;
54
55 public abstract class OwlUtils {
56
57 private static Logger log = LoggerFactory.getLogger(OwlUtils.class);
58
59 public static String ADAGIO_PREFIX = "http://www.e-is.pro/2019/03/adagio/";
60 public static ZoneId ZONE_ID = ZoneId.systemDefault();
61 public static DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
62 public static SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
63
64 public static Method getterOfField(Class t, String field) {
65 try {
66 Method res = t.getMethod("get" + field.substring(0, 1).toUpperCase() + field.substring(1));
67 return res;
68 } catch (NoSuchMethodException e) {
69 log.error("error in the declaration of allowed ManyToOne " + e.getMessage());
70 }
71 return null;
72 }
73
74 public static Optional<Method> setterOfField(Resource schema, Class t, String field, RdfImportContext context) {
75 try {
76 Optional<Field> f = fieldOf(schema, t, field, context);
77 if (f.isPresent()) {
78 String setterName = "set" + f.get().getName().substring(0, 1).toUpperCase() + f.get().getName().substring(1);
79
80 Method met = t.getMethod(setterName, f.get().getType());
81 return Optional.of(met);
82 }
83
84 } catch (NoSuchMethodException e) {
85 log.warn("NoSuchMethodException setterOfField " + field);
86 } catch (NullPointerException e) {
87 log.warn("NullPointerException setterOfField " + field);
88 }
89 return Optional.empty();
90 }
91
92 public static Map<Class, Resource> Class2Resources = ImmutableMap.<Class, Resource>builder()
93 .put(Date.class, XSD.date)
94 .put(LocalDateTime.class, XSD.dateTime)
95 .put(Timestamp.class, XSD.dateTimeStamp)
96 .put(Integer.class, XSD.integer)
97 .put(Short.class, XSD.xshort)
98 .put(Long.class, XSD.xlong)
99 .put(Double.class, XSD.xdouble)
100 .put(Float.class, XSD.xfloat)
101 .put(Boolean.class, XSD.xboolean)
102 .put(long.class, XSD.xlong)
103 .put(int.class, XSD.integer)
104 .put(float.class, XSD.xfloat)
105 .put(double.class, XSD.xdouble)
106 .put(short.class, XSD.xshort)
107 .put(boolean.class, XSD.xboolean)
108 .put(String.class, XSD.xstring)
109 .put(void.class, RDFS.Literal)
110 .build();
111
112 public static Map<Resource, Class> Resource2Classes = Class2Resources.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey, (x, y) -> x));
113
114 public static List<Class> ACCEPTED_LIST_CLASS = Arrays.asList(List.class, ArrayList.class, Set.class);
115
116
117 public static Optional<Field> fieldOf(Resource schema, Class t, String name, RdfImportContext context) {
118 try {
119
120 Class ret = context.URI_2_CLASS.get(t.getSimpleName());
121 if (ret == null) {
122 log.error("error fieldOf " + classToURI(schema, t) + " " + name);
123 return Optional.empty();
124 } else {
125 return Optional.of(ret.getDeclaredField(name));
126
127 }
128 } catch (NoSuchFieldException e) {
129 log.error("error fieldOf " + t.getSimpleName() + " " + name + " - " + e.getMessage());
130 }
131 return null;
132 }
133
134
135 public static String classToURI(Resource ont, Class c) {
136 String uri = ont + c.getSimpleName();
137 if (uri.substring(1).contains("<")) {
138 uri = uri.substring(0, uri.indexOf("<"));
139 }
140
141
142
143
144 if (uri.contains("$")) {
145 log.error("Inner classes not handled " + uri);
146 }
147
148 return uri;
149 }
150
151
152 public static boolean isJavaType(Type type) {
153 return Class2Resources.keySet().stream().anyMatch(type::equals);
154 }
155
156 public static boolean isJavaType(Method getter) {
157 return isJavaType(getter.getGenericReturnType());
158 }
159
160 public static boolean isJavaType(Field field) {
161 return isJavaType(field.getType());
162 }
163
164
165
166
167
168
169
170
171 public static boolean isId(Method met) {
172 return "getId".equals(met.getName())
173 && Stream.concat(annotsOfField(getFieldOfGetter(met)), Stream.of(met.getAnnotations()))
174 .anyMatch(annot -> annot instanceof Id || annot instanceof org.springframework.data.annotation.Id);
175 }
176
177 public static boolean isManyToOne(Method met) {
178 return annotsOfField(getFieldOfGetter(met)).anyMatch(annot -> annot instanceof ManyToOne)
179 ||
180 Stream.of(met.getAnnotations()).anyMatch(annot -> annot instanceof ManyToOne)
181 ;
182 }
183
184 public static Stream<Annotation> annotsOfField(Optional<Field> field) {
185 return field.map(field1 -> Stream.of(field1.getAnnotations())).orElseGet(Stream::empty);
186 }
187
188 public static boolean isGetter(Method met) {
189 return met.getName().startsWith("get")
190 && !"getBytes".equals(met.getName())
191 && met.getParameterCount() == 0
192 && getFieldOfGetter(met).isPresent()
193 ;
194 }
195
196
197 public static boolean isSetter(Method met) {
198 return met.getName().startsWith("set");
199 }
200
201 public static Field getFieldOfGetteR(Method getter) {
202 String fieldName = getter.getName().substring(3, 4).toLowerCase() + getter.getName().substring(4);
203 try {
204 return getter.getDeclaringClass().getDeclaredField(fieldName);
205 } catch (NoSuchFieldException e) {
206 return null;
207 }
208 }
209
210
211 public static Optional<Field> getFieldOfGetter(Method getter) {
212
213 String fieldName = getter.getName().substring(3, 4).toLowerCase() + getter.getName().substring(4);
214
215 try {
216 return Optional.of(getter.getDeclaringClass().getDeclaredField(fieldName));
217 } catch (Exception e) {
218
219 return Optional.empty();
220 }
221 }
222
223 public static Resource getStdType(Field f) {
224 return Class2Resources.getOrDefault(f.getType(), RDFS.Literal);
225
226
227
228
229
230 }
231
232 public static Resource getStdType(Type type) {
233 return Class2Resources.getOrDefault(type, RDFS.Literal);
234
235
236
237
238
239 }
240
241
242
243
244
245 public static boolean isListType(Type type) {
246 if (type instanceof ParameterizedType) {
247 ParameterizedType parameterized = (ParameterizedType) type;
248 Type raw = parameterized.getRawType();
249
250 return (ACCEPTED_LIST_CLASS.stream()
251 .anyMatch(x -> x.getCanonicalName().equals(raw.getTypeName())));
252 }
253
254 return false;
255
256 }
257
258 public static Type getListType(Type type) {
259 if (type instanceof ParameterizedType) {
260 ParameterizedType parameterized = (ParameterizedType) type;
261 Type raw = parameterized.getRawType();
262 Type own = parameterized.getOwnerType();
263 Type[] typeArgs = parameterized.getActualTypeArguments();
264
265 if (ACCEPTED_LIST_CLASS.stream()
266 .anyMatch(x -> x.getCanonicalName().equals(raw.getTypeName()))) {
267 return typeArgs[0];
268 }
269 }
270 return null;
271 }
272
273
274
275
276 public static void createOneToMany(OntModel ontoModel, OntClass ontoClass, OntProperty prop, Resource resource) {
277 OntClass minCardinalityRestriction = ontoModel.createMinCardinalityRestriction(null, prop, 1);
278 ontoClass.addSuperClass(minCardinalityRestriction);
279 }
280
281 public static void createZeroToMany(OntModel ontoModel, OntClass ontoClass, OntProperty prop, Resource resource) {
282 OntClass minCardinalityRestriction = ontoModel.createMinCardinalityRestriction(null, prop, 0);
283 ontoClass.addSuperClass(minCardinalityRestriction);
284 }
285
286 public static void createZeroToOne(OntModel ontoModel, OntClass ontoClass1, OntProperty prop, OntClass ontoClass2) {
287 OntClass maxCardinalityRestriction = ontoModel.createMaxCardinalityRestriction(null, prop, 1);
288 ontoClass1.addSuperClass(maxCardinalityRestriction);
289 }
290
291 public static void createOneToOne(OntModel ontoModel, OntClass ontoClass1, OntProperty prop, OntClass ontoClass2) {
292 OntClass maxCardinalityRestriction = ontoModel.createMaxCardinalityRestriction(null, prop, 1);
293 ontoClass1.addSuperClass(maxCardinalityRestriction);
294 }
295
296
297
298
299
300
301
302
303
304 public static String toString(Model model, String format) {
305
306 try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) {
307 if (format == null) {
308 model.write(os);
309 } else {
310 model.write(os, format);
311 }
312 os.flush();
313 os.close();
314 return new String(os.toByteArray(), "UTF8");
315 } catch (IOException e) {
316 log.error("doWrite ", e);
317 }
318 return "there was an error writing the model ";
319 }
320
321
322
323 public static LocalDate convertToLocalDateViaMilisecond(Date dateToConvert) {
324 return Instant.ofEpochMilli(dateToConvert.getTime())
325 .atZone(ZONE_ID)
326 .toLocalDate();
327 }
328
329 public static LocalDate convertToLocalDateViaInstant(Date dateToConvert) {
330 return dateToConvert.toInstant()
331 .atZone(ZONE_ID)
332 .toLocalDate();
333 }
334
335 public static Date convertToDateViaInstant(LocalDateTime dateToConvert) {
336 return java.util.Date
337 .from(dateToConvert.atZone(ZONE_ID)
338 .toInstant());
339 }
340
341
342 }