Skip to content

Package: DatatypeTransformer

DatatypeTransformer

nameinstructionbranchcomplexitylinemethod
DatatypeTransformer()
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
isSupportedJavaType(Class)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 0 C: 130
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 27
100%
M: 0 C: 1
100%
transform(OWLLiteral)
M: 51 C: 58
53%
M: 6 C: 10
63%
M: 6 C: 8
57%
M: 8 C: 11
58%
M: 0 C: 1
100%
transform(Object, String)
M: 39 C: 105
73%
M: 5 C: 19
79%
M: 4 C: 9
69%
M: 5 C: 23
82%
M: 0 C: 1
100%
transformOWLType(OWLDatatype)
M: 12 C: 15
56%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 1 C: 5
83%
M: 0 C: 1
100%

Coverage

1: /**
2: * Copyright (C) 2020 Czech Technical University in Prague
3: * <p>
4: * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5: * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6: * version.
7: * <p>
8: * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10: * details. You should have received a copy of the GNU General Public License along with this program. If not, see
11: * <http://www.gnu.org/licenses/>.
12: */
13: package cz.cvut.kbss.jopa.owlapi;
14:
15: import cz.cvut.kbss.jopa.model.MultilingualString;
16: import cz.cvut.kbss.ontodriver.model.LangString;
17: import org.semanticweb.owlapi.model.OWLDataFactory;
18: import org.semanticweb.owlapi.model.OWLDatatype;
19: import org.semanticweb.owlapi.model.OWLLiteral;
20: import org.semanticweb.owlapi.vocab.OWL2Datatype;
21: import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl;
22:
23: import java.math.BigDecimal;
24: import java.math.BigInteger;
25: import java.net.URI;
26: import java.text.ParseException;
27: import java.text.SimpleDateFormat;
28: import java.util.Date;
29: import java.util.EnumMap;
30: import java.util.Map;
31: import java.util.Objects;
32:
33: /**
34: * Contains utility functions for transformations between OWL2 datatypes (usually based on XSD types) and Java types.
35: * <p>
36: * Mostly based on <a href="https://xmlbeans.apache.org/docs/3.0.0/guide/conXMLBeansSupportBuiltInSchemaTypes.html">https://xmlbeans.apache.org/docs/3.0.0/guide/conXMLBeansSupportBuiltInSchemaTypes.html</a>
37: */
38: public class DatatypeTransformer {
39:
40: private static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";
41:
42: private static final Map<OWL2Datatype, Class<?>> DATATYPE_MAP = new EnumMap<>(OWL2Datatype.class);
43:
44: private static final OWLDataFactory DATA_FACTORY = new OWLDataFactoryImpl();
45:
46: static {
47: DATATYPE_MAP.put(OWL2Datatype.RDF_PLAIN_LITERAL, String.class);
48: DATATYPE_MAP.put(OWL2Datatype.XSD_STRING, String.class);
49: DATATYPE_MAP.put(OWL2Datatype.RDF_XML_LITERAL, String.class);
50: DATATYPE_MAP.put(OWL2Datatype.RDF_LANG_STRING, MultilingualString.class);
51: DATATYPE_MAP.put(OWL2Datatype.XSD_INT, Integer.class);
52: // technically, this is not correct, as XSD integer should be mapped to BigInteger, because it is unbound
53: // But OWL API maps it to integer, so we have to keep it this way too
54: DATATYPE_MAP.put(OWL2Datatype.XSD_INTEGER, Integer.class);
55: DATATYPE_MAP.put(OWL2Datatype.XSD_NON_NEGATIVE_INTEGER, Integer.class);
56: DATATYPE_MAP.put(OWL2Datatype.XSD_POSITIVE_INTEGER, Integer.class);
57: DATATYPE_MAP.put(OWL2Datatype.XSD_NON_POSITIVE_INTEGER, Integer.class);
58: DATATYPE_MAP.put(OWL2Datatype.XSD_NEGATIVE_INTEGER, Integer.class);
59: DATATYPE_MAP.put(OWL2Datatype.XSD_UNSIGNED_INT, Long.class);
60: DATATYPE_MAP.put(OWL2Datatype.XSD_DOUBLE, Double.class);
61: DATATYPE_MAP.put(OWL2Datatype.XSD_FLOAT, Float.class);
62: DATATYPE_MAP.put(OWL2Datatype.XSD_BOOLEAN, Boolean.class);
63: DATATYPE_MAP.put(OWL2Datatype.XSD_DATE_TIME, Date.class);
64: DATATYPE_MAP.put(OWL2Datatype.XSD_DATE_TIME_STAMP, Date.class);
65: DATATYPE_MAP.put(OWL2Datatype.XSD_SHORT, Short.class);
66: DATATYPE_MAP.put(OWL2Datatype.XSD_UNSIGNED_SHORT, Integer.class);
67: DATATYPE_MAP.put(OWL2Datatype.XSD_LONG, Long.class);
68: DATATYPE_MAP.put(OWL2Datatype.XSD_UNSIGNED_LONG, BigInteger.class);
69: DATATYPE_MAP.put(OWL2Datatype.XSD_BYTE, Byte.class);
70: DATATYPE_MAP.put(OWL2Datatype.XSD_UNSIGNED_BYTE, Short.class);
71: DATATYPE_MAP.put(OWL2Datatype.XSD_ANY_URI, URI.class);
72: DATATYPE_MAP.put(OWL2Datatype.XSD_DECIMAL, BigDecimal.class);
73: }
74:
75: private DatatypeTransformer() {
76: throw new AssertionError();
77: }
78:
79: public static Class<?> transformOWLType(final OWLDatatype dt) {
80: Class<?> type = null;
81:
82:• if (dt.isBuiltIn()) {
83: type = DATATYPE_MAP.get(dt.getBuiltInDatatype());
84: }
85:
86:• if (type == null) {
87: throw new IllegalArgumentException("Unsupported datatype: " + dt);
88: }
89:
90: return type;
91: }
92:
93: public static boolean isSupportedJavaType(Class<?> dt) {
94: return DATATYPE_MAP.containsValue(dt);
95: }
96:
97: /**
98: * Transforms the specified {@link OWLLiteral} to the corresponding Java type (if possible).
99: * <p>
100: * For instance, literals of type {@code xsd:int} are transformed to Java {@link Integer}s.
101: *
102: * @param literal Literal to transform
103: * @return Java object corresponding to the literal
104: */
105: public static Object transform(final OWLLiteral literal) {
106:• if (literal.isRDFPlainLiteral()) {
107: return literal.getLiteral();
108:• } else if (literal.getDatatype().isBuiltIn()) {
109:• switch (literal.getDatatype().getBuiltInDatatype()) {
110: case XSD_SHORT:
111: case XSD_UNSIGNED_BYTE:
112: return Short.parseShort(literal.getLiteral());
113: case XSD_LONG:
114: case XSD_UNSIGNED_INT:
115: return Long.parseLong(literal.getLiteral());
116: case XSD_INT:
117: case XSD_INTEGER:
118: case XSD_NON_NEGATIVE_INTEGER:
119: case XSD_NON_POSITIVE_INTEGER:
120: case XSD_POSITIVE_INTEGER:
121: case XSD_NEGATIVE_INTEGER:
122: case XSD_UNSIGNED_SHORT:
123: return Integer.parseInt(literal.getLiteral());
124: case XSD_DOUBLE:
125: return Double.parseDouble(literal.getLiteral());
126: case XSD_FLOAT:
127: return Float.parseFloat(literal.getLiteral());
128: case XSD_DECIMAL:
129: return new BigDecimal(literal.getLiteral());
130: case XSD_STRING:
131: case RDF_XML_LITERAL:
132: return literal.getLiteral();
133: case RDF_LANG_STRING:
134: return new LangString(literal.getLiteral(), literal.getLang());
135: case XSD_BOOLEAN:
136: return Boolean.parseBoolean(literal.getLiteral());
137: case XSD_ANY_URI:
138: return URI.create(literal.getLiteral());
139: case XSD_DATE_TIME_STAMP:
140: case XSD_DATE_TIME:
141: try {
142: return new SimpleDateFormat(DATE_TIME_FORMAT).parse(literal.getLiteral());
143: } catch (ParseException e) {
144: throw new IllegalArgumentException(
145: "The date time '" + literal.getLiteral() + "' cannot be parsed using format " +
146: DATE_TIME_FORMAT + ".");
147: }
148: default:
149: break;
150: }
151: }
152: throw new IllegalArgumentException("Unsupported datatype: " + literal.getDatatype());
153: }
154:
155: /**
156: * Transforms the specified Java object to an {@link OWLLiteral}.
157: * <p>
158: * The datatype is determined from the object's type.
159: *
160: * @param value Value to transform
161: * @param lang Optional language for string literals
162: * @return {@code OWLiteral}
163: */
164: public static OWLLiteral transform(Object value, String lang) {
165: Objects.requireNonNull(value);
166:• if (value instanceof Integer) {
167: // Java implementations map int/Integer to xsd:int, because xsd:integer is unbounded, whereas xsd:int is 32-bit signed, same as Java
168: return DATA_FACTORY.getOWLLiteral(value.toString(), OWL2Datatype.XSD_INT);
169:• } else if (value instanceof BigInteger) {
170: return DATA_FACTORY.getOWLLiteral(value.toString(), OWL2Datatype.XSD_INTEGER);
171:• } else if (value instanceof Long) {
172: return DATA_FACTORY.getOWLLiteral(value.toString(), OWL2Datatype.XSD_LONG);
173:• } else if (value instanceof Boolean) {
174: return DATA_FACTORY.getOWLLiteral((Boolean) value);
175:• } else if (value instanceof Double) {
176: return DATA_FACTORY.getOWLLiteral((Double) value);
177:• } else if (value instanceof Float) {
178: return DATA_FACTORY.getOWLLiteral((Float) value);
179:• } else if (value instanceof BigDecimal) {
180: return DATA_FACTORY.getOWLLiteral(((BigDecimal) value).toPlainString(), OWL2Datatype.XSD_DECIMAL);
181:• } else if (value instanceof LangString) {
182: final LangString ls = (LangString) value;
183: return DATA_FACTORY.getOWLLiteral(ls.getValue(), ls.getLanguage().orElse(null));
184:• } else if (value instanceof String) {
185:• return lang != null ? DATA_FACTORY.getOWLLiteral(value.toString(), lang) :
186: DATA_FACTORY.getOWLLiteral(value.toString());
187:• } else if (value instanceof Date) {
188: SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT);
189: return DATA_FACTORY.getOWLLiteral(sdf.format((Date) value),
190: DATA_FACTORY.getOWLDatatype(OWL2Datatype.XSD_DATE_TIME.getIRI()));
191:• } else if (value.getClass().isEnum()) {
192: return DATA_FACTORY.getOWLLiteral(value.toString());
193: } else {
194: throw new IllegalArgumentException("Unsupported value " + value + " of type " + value.getClass());
195: }
196: }
197: }