Skip to content

Package: JavaTransformer

JavaTransformer

nameinstructionbranchcomplexitylinemethod
JavaTransformer(TransformationConfiguration)
M: 0 C: 16
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
addCommonClassFields(JCodeModel, JDefinedClass, PropertiesType)
M: 2 C: 119
98%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 23
100%
M: 0 C: 1
100%
addField(String, JDefinedClass, JType)
M: 6 C: 61
91%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 11
92%
M: 0 C: 1
100%
createEntityClass(String, JCodeModel, OWLClass, OWLOntology)
M: 10 C: 34
77%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 3 C: 7
70%
M: 0 C: 1
100%
createVocabularyClass(JCodeModel)
M: 0 C: 20
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
ensureEntityClassExists(String, JCodeModel, OWLClass, OWLOntology)
M: 0 C: 22
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
ensureVocabularyItemUniqueIdentifier(String)
M: 0 C: 20
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
fqn(String, String)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
generateAuthorshipDoc(JDocCommentable)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
generateClassJavadoc(OWLOntology, OWLEntity, JDocCommentable)
M: 0 C: 16
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
generateDataProperty(OWLOntology, JCodeModel, ContextDefinition, OWLClass, JDefinedClass, OWLDataProperty)
M: 17 C: 93
85%
M: 3 C: 6
67%
M: 3 C: 3
50%
M: 3 C: 18
86%
M: 0 C: 1
100%
generateFieldName(OWLEntity, OWLOntologyManager, Set)
M: 0 C: 58
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 11
100%
M: 0 C: 1
100%
generateJavadoc(OWLOntology, OWLEntity, JDocCommentable)
M: 0 C: 50
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 16
100%
M: 0 C: 1
100%
generateModel(OWLOntology, ContextDefinition)
M: 7 C: 38
84%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 2 C: 6
75%
M: 0 C: 1
100%
generateModelImpl(OWLOntology, JCodeModel, ContextDefinition, String)
M: 0 C: 112
100%
M: 0 C: 10
100%
M: 0 C: 6
100%
M: 0 C: 20
100%
M: 0 C: 1
100%
generateObjectProperty(OWLOntology, JCodeModel, ContextDefinition, String, OWLClass, JDefinedClass, OWLObjectProperty)
M: 14 C: 106
88%
M: 3 C: 8
73%
M: 3 C: 4
57%
M: 3 C: 20
87%
M: 0 C: 1
100%
generateOntologyIrisConstants(OWLOntologyManager)
M: 0 C: 21
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
generateToStringMethod(JDefinedClass, JFieldVar, JFieldVar)
M: 0 C: 47
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 10
100%
M: 0 C: 1
100%
generateVocabulary(OWLOntology, ContextDefinition)
M: 7 C: 31
82%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 2 C: 5
71%
M: 0 C: 1
100%
generateVocabulary(OWLOntology, JCodeModel, ContextDefinition)
M: 0 C: 120
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 23
100%
M: 0 C: 1
100%
isClassNameUnique(String, String, JCodeModel)
M: 0 C: 10
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
isJavaClassNameAnnotation(OWLAnnotation)
M: 1 C: 18
95%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 4
100%
M: 0 C: 1
100%
isPrefixedVersionRequired(OWLOntologyID)
M: 0 C: 19
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
javaClassId(OWLOntology, OWLClass, String, JCodeModel)
M: 4 C: 52
93%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 1 C: 9
90%
M: 0 C: 1
100%
lambda$generateJavadoc$10(JDocCommentable, OWLLiteral)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$generateJavadoc$5(OWLAnnotation)
M: 0 C: 12
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 2
100%
M: 0 C: 1
100%
lambda$generateJavadoc$6(OWLLiteral)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$generateJavadoc$7(OWLAnnotation)
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
lambda$generateJavadoc$8(OWLAnnotation)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$generateJavadoc$9(JDocCommentable, OWLLiteral)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$generateModelImpl$11(IntegrityConstraint)
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$generateModelImpl$12(JDefinedClass, String, JCodeModel, OWLOntology, AtomicBoolean, IntegrityConstraint)
M: 0 C: 17
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
lambda$generateOntologyIrisConstants$0(OWLOntology)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$generateOntologyIrisConstants$1(IRI)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$generateOntologyIrisConstants$2(IRI)
M: 0 C: 26
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
lambda$javaClassId$13(OWLClass)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$resolveContainingOntology$3(OWLOntology)
M: 0 C: 8
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$resolveContainingOntology$4(OWLEntity, OWLOntology)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
lambda$resolveExplicitClassName$14(OWLAnnotation)
M: 0 C: 12
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 2
100%
M: 0 C: 1
100%
lambda$resolveExplicitClassName$15(OWLAnnotation)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
modelPackageName()
M: 0 C: 23
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
resolveContainingOntology(OWLEntity, OWLOntologyManager)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
resolveExplicitClassName(OWLOntology, OWLClass)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
resolveFieldPrefix(OWLEntity, Set)
M: 6 C: 44
88%
M: 2 C: 12
86%
M: 2 C: 6
75%
M: 2 C: 11
85%
M: 0 C: 1
100%
resolveFieldType(OWLDatatype)
M: 0 C: 15
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
setParticipationConstraintCardinality(JAnnotationUse, ParticipationConstraint)
M: 0 C: 20
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 5
100%
M: 0 C: 1
100%
static {...}
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * JOPA
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.jopa.owl2java;
19:
20: import com.sun.codemodel.JAnnotationArrayMember;
21: import com.sun.codemodel.JAnnotationUse;
22: import com.sun.codemodel.JBlock;
23: import com.sun.codemodel.JClass;
24: import com.sun.codemodel.JClassAlreadyExistsException;
25: import com.sun.codemodel.JCodeModel;
26: import com.sun.codemodel.JDefinedClass;
27: import com.sun.codemodel.JDocCommentable;
28: import com.sun.codemodel.JExpr;
29: import com.sun.codemodel.JExpression;
30: import com.sun.codemodel.JFieldRef;
31: import com.sun.codemodel.JFieldVar;
32: import com.sun.codemodel.JMethod;
33: import com.sun.codemodel.JMod;
34: import com.sun.codemodel.JType;
35: import com.sun.codemodel.JVar;
36: import cz.cvut.kbss.jopa.ic.api.AtomicSubClassConstraint;
37: import cz.cvut.kbss.jopa.ic.api.DataParticipationConstraint;
38: import cz.cvut.kbss.jopa.ic.api.ObjectParticipationConstraint;
39: import cz.cvut.kbss.jopa.model.MultilingualString;
40: import cz.cvut.kbss.jopa.model.annotations.Id;
41: import cz.cvut.kbss.jopa.model.annotations.OWLAnnotationProperty;
42: import cz.cvut.kbss.jopa.model.annotations.OWLDataProperty;
43: import cz.cvut.kbss.jopa.model.annotations.OWLObjectProperty;
44: import cz.cvut.kbss.jopa.model.annotations.ParticipationConstraint;
45: import cz.cvut.kbss.jopa.model.annotations.ParticipationConstraints;
46: import cz.cvut.kbss.jopa.model.annotations.Properties;
47: import cz.cvut.kbss.jopa.model.annotations.Sequence;
48: import cz.cvut.kbss.jopa.model.annotations.SequenceType;
49: import cz.cvut.kbss.jopa.model.annotations.Types;
50: import cz.cvut.kbss.jopa.owl2java.cli.Option;
51: import cz.cvut.kbss.jopa.owl2java.cli.PropertiesType;
52: import cz.cvut.kbss.jopa.owl2java.config.TransformationConfiguration;
53: import cz.cvut.kbss.jopa.owl2java.exception.OWL2JavaException;
54: import cz.cvut.kbss.jopa.owl2java.prefix.PrefixMap;
55: import cz.cvut.kbss.jopa.owlapi.DatatypeTransformer;
56: import cz.cvut.kbss.jopa.vocabulary.DC;
57: import cz.cvut.kbss.jopa.vocabulary.RDFS;
58: import org.semanticweb.owlapi.model.IRI;
59: import org.semanticweb.owlapi.model.OWLAnnotation;
60: import org.semanticweb.owlapi.model.OWLClass;
61: import org.semanticweb.owlapi.model.OWLDatatype;
62: import org.semanticweb.owlapi.model.OWLEntity;
63: import org.semanticweb.owlapi.model.OWLOntology;
64: import org.semanticweb.owlapi.model.OWLOntologyID;
65: import org.semanticweb.owlapi.model.OWLOntologyManager;
66: import org.semanticweb.owlapi.search.EntitySearcher;
67: import org.slf4j.Logger;
68: import org.slf4j.LoggerFactory;
69:
70: import java.io.Serializable;
71: import java.util.Collection;
72: import java.util.Comparator;
73: import java.util.HashMap;
74: import java.util.HashSet;
75: import java.util.LinkedHashSet;
76: import java.util.List;
77: import java.util.Map;
78: import java.util.Optional;
79: import java.util.Set;
80: import java.util.concurrent.atomic.AtomicBoolean;
81: import java.util.stream.Collectors;
82:
83: import static cz.cvut.kbss.jopa.owl2java.Constants.DESCRIPTION_FIELD_NAME;
84: import static cz.cvut.kbss.jopa.owl2java.Constants.ID_FIELD_NAME;
85: import static cz.cvut.kbss.jopa.owl2java.Constants.LABEL_FIELD_NAME;
86: import static cz.cvut.kbss.jopa.owl2java.Constants.LANGUAGE;
87: import static cz.cvut.kbss.jopa.owl2java.Constants.MODEL_PACKAGE;
88: import static cz.cvut.kbss.jopa.owl2java.Constants.PACKAGE_SEPARATOR;
89: import static cz.cvut.kbss.jopa.owl2java.Constants.PROPERTIES_FIELD_NAME;
90: import static cz.cvut.kbss.jopa.owl2java.Constants.TYPES_FIELD_NAME;
91: import static cz.cvut.kbss.jopa.owl2java.Constants.VERSION;
92: import static cz.cvut.kbss.jopa.owl2java.Constants.VOCABULARY_CLASS;
93:
94: public class JavaTransformer {
95:
96: private static final Logger LOG = LoggerFactory.getLogger(OWL2JavaTransformer.class);
97:
98: private static final String PREFIX_STRING = "s_";
99: private static final String PREFIX_CLASS = "c_";
100: private static final String PREFIX_PROPERTY = "p_";
101: private static final String PREFIX_INDIVIDUAL = "i_";
102: private static final String PREFIX_DATATYPE = "d_";
103: private static final String DISAMBIGUATION_SUFFIX = "_A";
104:
105: private JDefinedClass voc;
106: private final Map<OWLEntity, JFieldRef> entities = new HashMap<>();
107:
108: private final Map<OWLClass, JDefinedClass> classes = new HashMap<>();
109:
110: private JavaNameGenerator nameGenerator;
111:
112: private final TransformationConfiguration configuration;
113:
114: JavaTransformer(TransformationConfiguration configuration) {
115: this.configuration = configuration;
116: }
117:
118: /**
119: * Generates an object model consisting of JOPA entity classes and a vocabulary file from the specified ontology and
120: * context definition.
121: *
122: * @param ontology Ontology from which the model is generated
123: * @param context Context information
124: * @return The generated object model
125: */
126: public ObjectModel generateModel(final OWLOntology ontology, final ContextDefinition context) {
127: try {
128: this.nameGenerator = new JavaNameGenerator(new PrefixMap(ontology.getOWLOntologyManager(), configuration));
129: final JCodeModel cm = new JCodeModel();
130: voc = createVocabularyClass(cm);
131: generateVocabulary(ontology, cm, context);
132: generateModelImpl(ontology, cm, context, modelPackageName());
133: return new ObjectModel(cm);
134: } catch (JClassAlreadyExistsException e) {
135: throw new OWL2JavaException("Transformation FAILED.", e);
136: }
137: }
138:
139: private String modelPackageName() {
140: final String packageConfig = configuration.getPackageName();
141: final StringBuilder sb = new StringBuilder(packageConfig);
142:• if (!packageConfig.isEmpty()) {
143: sb.append(PACKAGE_SEPARATOR);
144: }
145: sb.append(MODEL_PACKAGE);
146: return sb.toString();
147: }
148:
149: private JDefinedClass createVocabularyClass(JCodeModel codeModel)
150: throws JClassAlreadyExistsException {
151: final String packageName = configuration.getPackageName();
152: final String className =
153:• packageName.isEmpty() ? VOCABULARY_CLASS : packageName + PACKAGE_SEPARATOR + VOCABULARY_CLASS;
154: final JDefinedClass cls = codeModel._class(className);
155: generateAuthorshipDoc(cls);
156: return cls;
157: }
158:
159: private static void generateAuthorshipDoc(JDocCommentable javaElem) {
160: javaElem.javadoc().add("This class was generated by OWL2Java " + VERSION);
161: }
162:
163: /**
164: * Generates only vocabulary of the loaded ontology.
165: *
166: * @param ontology Ontology from which the vocabulary should be generated
167: * @param context Integrity constraints context, if null is supplied, the whole ontology is interpreted as
168: * integrity constraints.
169: * @return The generated object model
170: */
171: public ObjectModel generateVocabulary(final OWLOntology ontology, ContextDefinition context) {
172: try {
173: this.nameGenerator = new JavaNameGenerator(new PrefixMap(ontology.getOWLOntologyManager(), configuration));
174: final JCodeModel cm = new JCodeModel();
175: this.voc = createVocabularyClass(cm);
176: generateVocabulary(ontology, cm, context);
177: return new ObjectModel(cm);
178: } catch (JClassAlreadyExistsException e) {
179: throw new OWL2JavaException("Vocabulary generation FAILED, because the Vocabulary class already exists.",
180: e);
181: }
182: }
183:
184: private void generateVocabulary(final OWLOntology o, final JCodeModel cm, ContextDefinition context) {
185: final Collection<OWLEntity> col = new LinkedHashSet<>();
186: col.add(o.getOWLOntologyManager().getOWLDataFactory().getOWLThing());
187: col.addAll(context.classes);
188: col.addAll(context.objectProperties);
189: col.addAll(context.dataProperties);
190: col.addAll(context.annotationProperties);
191: col.addAll(context.individuals);
192:
193: generateOntologyIrisConstants(o.getOWLOntologyManager());
194:
195: final Set<IRI> visitedProperties = new HashSet<>(col.size());
196:
197:• for (final OWLEntity c : col) {
198: final Optional<String> sFieldName = generateFieldName(c, o.getOWLOntologyManager(), visitedProperties);
199:• if (sFieldName.isEmpty()) {
200: continue;
201: }
202:
203: final JFieldVar fv1 = voc.field(JMod.PUBLIC | JMod.STATIC
204: | JMod.FINAL, String.class, sFieldName.get(), JExpr.lit(c.getIRI().toString()));
205:• if (configuration.shouldGenerateOwlapiIris()) {
206: voc.field(JMod.PUBLIC | JMod.STATIC | JMod.FINAL, IRI.class,
207: sFieldName.get().substring(PREFIX_STRING.length()),
208: cm.ref(IRI.class).staticInvoke("create").arg(fv1));
209: }
210: generateJavadoc(o, c, fv1);
211: entities.put(c, voc.staticRef(fv1));
212: }
213: }
214:
215: private void generateOntologyIrisConstants(OWLOntologyManager ontologyManager) {
216: // Get only unique ontology IRIs sorted
217: final List<IRI> ontologyIris = ontologyManager.ontologies().map(o -> o.getOntologyID().getOntologyIRI())
218: .filter(Optional::isPresent).map(Optional::get).distinct()
219: .sorted(Comparator.comparing(IRI::getIRIString))
220: .collect(Collectors.toList());
221: ontologyIris.forEach(iri -> {
222: final String fieldName = ensureVocabularyItemUniqueIdentifier("ONTOLOGY_IRI_" + JavaNameGenerator.makeNameValidJava(nameGenerator.getOntologyPrefix(iri)
223: .orElseGet(() -> nameGenerator.generateJavaNameForIri(iri)))
224: .toUpperCase());
225: voc.field(JMod.PUBLIC | JMod.STATIC | JMod.FINAL, String.class, fieldName, JExpr.lit(iri.toString()));
226: });
227: }
228:
229: private Optional<String> generateFieldName(OWLEntity c, OWLOntologyManager ontologyManager,
230: Set<IRI> visitedProperties) {
231: final Optional<String> prefix = resolveFieldPrefix(c, visitedProperties);
232:• if (prefix.isEmpty()) {
233: return prefix;
234: }
235: final Optional<OWLOntology> containingOntology = resolveContainingOntology(c, ontologyManager);
236: String fieldName = PREFIX_STRING + prefix.get() + nameGenerator.generateJavaNameForIri(c.getIRI());
237:• if (voc.fields().containsKey(fieldName) || (
238:• containingOntology.isPresent() && isPrefixedVersionRequired(containingOntology.get()
239: .getOntologyID()))) {
240: fieldName = PREFIX_STRING + prefix.get() + nameGenerator.generatePrefixedJavaNameForIri(c.getIRI(), containingOntology.get()
241: .getOntologyID());
242: }
243: return Optional.of(ensureVocabularyItemUniqueIdentifier(fieldName));
244: }
245:
246: private static Optional<OWLOntology> resolveContainingOntology(OWLEntity c, OWLOntologyManager ontologyManager) {
247: return ontologyManager.getOntologies().stream()
248:• .filter(o -> !o.getOntologyID().isAnonymous())
249: .filter(o -> o.containsEntityInSignature(c))
250: .findFirst();
251: }
252:
253: private static Optional<String> resolveFieldPrefix(OWLEntity c, Set<IRI> visitedProperties) {
254:• if (c.isOWLClass()) {
255: return Optional.of(PREFIX_CLASS);
256:• } else if (c.isOWLDatatype()) {
257: return Optional.of(PREFIX_DATATYPE);
258:• } else if (c.isOWLDataProperty() || c.isOWLObjectProperty() || c.isOWLAnnotationProperty()) {
259:• if (visitedProperties.contains(c.getIRI())) {
260: LOG.debug("Property with IRI {} already processed. Skipping.", c.getIRI());
261: return Optional.empty();
262: }
263: visitedProperties.add(c.getIRI());
264: return Optional.of(PREFIX_PROPERTY);
265:• } else if (c.isOWLNamedIndividual()) {
266: return Optional.of(PREFIX_INDIVIDUAL);
267: }
268: return Optional.of("");
269: }
270:
271: private String ensureVocabularyItemUniqueIdentifier(String id) {
272: final StringBuilder sb = new StringBuilder(id);
273:• while (voc.fields().containsKey(sb.toString())) {
274: sb.append(DISAMBIGUATION_SUFFIX);
275: }
276: return sb.toString();
277: }
278:
279: /**
280: * Generates Javadoc from rdfs:comment annotation (if present).
281: *
282: * @param ontology Ontology from which the model/vocabulary is being generated
283: * @param owlEntity Annotated entity
284: * @param javaElem Element to document with Javadoc
285: * @return Whether the javadoc comment has been generated
286: */
287: private boolean generateJavadoc(OWLOntology ontology, OWLEntity owlEntity, JDocCommentable javaElem) {
288:• if (!configuration.shouldGenerateJavadoc()) {
289: return false;
290: }
291: final List<OWLAnnotation> comments = EntitySearcher.getAnnotations(owlEntity, ontology)
292:• .filter(a -> a.getProperty().isComment() && a.getValue()
293:• .isLiteral())
294: .collect(Collectors.toList());
295: final Optional<OWLAnnotation> langComment = comments.stream().filter(a -> a.getValue().asLiteral()
296: .map(l -> l.hasLang(LANGUAGE))
297: .orElse(false)).findFirst();
298: // First try finding a comment with a matching language tag
299:• if (langComment.isPresent()) {
300: langComment.flatMap(a -> a.getValue().asLiteral())
301: .ifPresent(lit -> javaElem.javadoc().add(lit.getLiteral()));
302: return true;
303: }
304: // If there is none such, just use the first available one
305:• if (!comments.isEmpty()) {
306: OWLAnnotation anyComment = comments.get(0);
307: anyComment.getValue().asLiteral().ifPresent(lit -> javaElem.javadoc().add(lit.getLiteral()));
308: return true;
309: }
310: return false;
311: }
312:
313: private void generateModelImpl(final OWLOntology ontology, final JCodeModel cm,
314: final ContextDefinition context, final String pkg) {
315: LOG.info("Generating model ...");
316: final PropertiesType propertiesType = configuration.getPropertiesType();
317:
318:• if (configuration.shouldGenerateThing()) {
319: context.classes.add(ontology.getOWLOntologyManager().getOWLDataFactory().getOWLThing());
320: }
321:
322:• for (final OWLClass clazz : context.classes) {
323: LOG.info(" Generating entity class for '{}'.", clazz);
324: final JDefinedClass subj = ensureEntityClassExists(pkg, cm, clazz, ontology);
325:
326:
327: final AtomicBoolean extendClass = new AtomicBoolean(false);
328: context.set.getClassIntegrityConstraints(clazz).stream()
329: .filter(ic -> ic instanceof AtomicSubClassConstraint).forEach(ic -> {
330: final AtomicSubClassConstraint icc = (AtomicSubClassConstraint) ic;
331: subj._extends(ensureEntityClassExists(pkg, cm, icc.getSupClass(), ontology));
332: extendClass.set(true);
333: });
334:
335:• if (!extendClass.get()) {
336: addCommonClassFields(cm, subj, propertiesType);
337: }
338:• for (final org.semanticweb.owlapi.model.OWLObjectProperty prop : context.objectProperties) {
339: generateObjectProperty(ontology, cm, context, pkg, clazz, subj, prop);
340: }
341:
342:• for (org.semanticweb.owlapi.model.OWLDataProperty prop : context.dataProperties) {
343: generateDataProperty(ontology, cm, context, clazz, subj, prop);
344: }
345: }
346: }
347:
348: private void generateObjectProperty(final OWLOntology ontology,
349: final JCodeModel cm,
350: final ContextDefinition context,
351: final String pkg,
352: final OWLClass clazz,
353: final JDefinedClass subj,
354: final org.semanticweb.owlapi.model.OWLObjectProperty prop) {
355: final ClassObjectPropertyComputer comp = new ClassObjectPropertyComputer(
356: clazz,
357: prop,
358: context.set,
359: ontology
360: );
361:
362:• if (Card.NO != comp.getCard()) {
363: JClass filler = ensureEntityClassExists(pkg, cm, comp.getFiller(), ontology);
364: final String fieldName = nameGenerator.generateJavaNameForIri(prop.getIRI());
365:
366:• switch (comp.getCard()) {
367: case MULTIPLE:
368: filler = cm.ref(java.util.Set.class).narrow(filler);
369: break;
370: case SIMPLELIST:
371: case LIST:
372: filler = cm.ref(java.util.List.class).narrow(filler);
373: break;
374: default:
375: break;
376: }
377:
378: final JFieldVar fv = addField(fieldName, subj, filler);
379: generateJavadoc(ontology, prop, fv);
380:
381:• if (comp.getCard().equals(Card.SIMPLELIST)) {
382: fv.annotate(Sequence.class).param("type", SequenceType.simple);
383: }
384:
385:
386: fv.annotate(OWLObjectProperty.class).param("iri", entities.get(prop));
387:
388: JAnnotationArrayMember use = null;
389:• for (ObjectParticipationConstraint ic : comp.getParticipationConstraints()) {
390:• if (use == null) {
391: use = fv.annotate(ParticipationConstraints.class).paramArray("value");
392: }
393: JAnnotationUse u = use.annotate(ParticipationConstraint.class)
394: .param("owlObjectIRI", entities.get(ic.getObject()));
395: setParticipationConstraintCardinality(u, ic);
396: }
397: }
398: }
399:
400: private static JFieldVar addField(final String name, final JDefinedClass cls,
401: final JType fieldType) {
402: String newName = name;
403:
404: int i = 0;
405:• while (cls.fields().containsKey(newName)) {
406: newName = name + "" + (++i);
407: }
408:
409: final JFieldVar fvId = cls.field(JMod.PROTECTED, fieldType, newName);
410: final String fieldName = fvId.name().substring(0, 1).toUpperCase() + fvId.name().substring(1);
411: final JMethod mSetId = cls.method(JMod.PUBLIC, void.class, "set" + fieldName);
412: final JVar v = mSetId.param(fieldType, fvId.name());
413: mSetId.body().assign(JExpr._this().ref(fvId), v);
414: final JMethod mGetId = cls.method(JMod.PUBLIC, fieldType, "get" + fieldName);
415: mGetId.body()._return(fvId);
416: return fvId;
417: }
418:
419: private static void setParticipationConstraintCardinality(JAnnotationUse u,
420: cz.cvut.kbss.jopa.ic.api.ParticipationConstraint<?, ?> ic) {
421:• if (ic.getMin() != 0) {
422: u.param("min", ic.getMin());
423: }
424:• if (ic.getMin() != -1) {
425: u.param("max", ic.getMax());
426: }
427: }
428:
429: private void generateDataProperty(final OWLOntology ontology,
430: final JCodeModel cm,
431: final ContextDefinition context,
432: final OWLClass clazz,
433: final JDefinedClass subj,
434: final org.semanticweb.owlapi.model.OWLDataProperty prop) {
435: final ClassDataPropertyComputer comp = new ClassDataPropertyComputer(
436: clazz,
437: prop,
438: context.set,
439: ontology
440: );
441:
442:• if (Card.NO != comp.getCard()) {
443:
444: final JType obj = cm._ref(resolveFieldType(comp.getFiller()));
445:
446: final String fieldName = nameGenerator.generateJavaNameForIri(prop.getIRI());
447:
448: JFieldVar fv;
449:
450:• switch (comp.getCard()) {
451: case MULTIPLE:
452: fv = addField(fieldName, subj, cm.ref(java.util.Set.class).narrow(obj));
453: break;
454: case ONE:
455: fv = addField(fieldName, subj, obj);
456: break;
457: default:
458: throw new OWL2JavaException("Unsupported data property cardinality type " + comp.getCard());
459: }
460: generateJavadoc(ontology, prop, fv);
461:
462: fv.annotate(OWLDataProperty.class).param("iri", entities.get(prop));
463:
464: JAnnotationArrayMember use = null;
465:• for (DataParticipationConstraint ic : comp.getParticipationConstraints()) {
466:• if (use == null) {
467: use = fv.annotate(ParticipationConstraints.class).paramArray("value");
468: }
469:
470: JAnnotationUse u = use.annotate(ParticipationConstraint.class)
471: .param("owlObjectIRI", comp.getFiller().getIRI().toString());
472:
473: setParticipationConstraintCardinality(u, ic);
474: }
475: }
476: }
477:
478: private Class<?> resolveFieldType(OWLDatatype datatype) {
479: final Class<?> cls = DatatypeTransformer.transformOWLType(datatype);
480:• if (MultilingualString.class.equals(cls) && !configuration.shouldPreferMultilingualStrings()) {
481: return String.class;
482: }
483: return cls;
484: }
485:
486: private JDefinedClass ensureEntityClassExists(final String pkg, final JCodeModel cm, final OWLClass clazz,
487: final OWLOntology ontology) {
488:• if (!classes.containsKey(clazz)) {
489: classes.put(clazz, createEntityClass(pkg, cm, clazz, ontology));
490: }
491: return classes.get(clazz);
492: }
493:
494: private JDefinedClass createEntityClass(final String pkg, final JCodeModel cm, final OWLClass clazz,
495: final OWLOntology ontology) {
496: JDefinedClass cls;
497:
498: String name = javaClassId(ontology, clazz, pkg, cm);
499:
500: try {
501: cls = cm._class(name);
502:
503: cls.annotate(cz.cvut.kbss.jopa.model.annotations.OWLClass.class).param("iri", entities.get(clazz));
504: cls._implements(Serializable.class);
505:
506: generateClassJavadoc(ontology, clazz, cls);
507: } catch (JClassAlreadyExistsException e) {
508: LOG.trace("Class already exists. Using the existing version. {}", e.getMessage());
509: cls = cm._getClass(name);
510: }
511: return cls;
512: }
513:
514: private String javaClassId(OWLOntology rootOntology, OWLClass owlClass, String pkg,
515: JCodeModel codeModel) {
516: final Optional<OWLOntology> containingOntology = resolveContainingOntology(owlClass, rootOntology.getOWLOntologyManager());
517: final OWLOntology onto = containingOntology.orElse(rootOntology);
518: String className = resolveExplicitClassName(rootOntology, owlClass)
519: .orElseGet(() -> JavaNameGenerator.toCamelCaseNotation(nameGenerator.generateJavaNameForIri(owlClass.getIRI())));
520:
521:• if (isClassNameUnique(pkg, className, codeModel) && !isPrefixedVersionRequired(onto.getOntologyID())) {
522: return fqn(pkg, className);
523: }
524: className = JavaNameGenerator.toCamelCaseNotation(nameGenerator.generatePrefixedJavaNameForIri(owlClass.getIRI(), onto.getOntologyID()));
525:• while (!isClassNameUnique(pkg, className, codeModel)) {
526: className += DISAMBIGUATION_SUFFIX;
527: }
528: return fqn(pkg, className);
529: }
530:
531: private Optional<String> resolveExplicitClassName(OWLOntology ontology, OWLClass owlClass) {
532: return EntitySearcher.getAnnotations(owlClass, ontology)
533:• .filter(a -> isJavaClassNameAnnotation(a) &&
534:• a.getValue().isLiteral()).findFirst()
535: .map(a -> a.getValue().asLiteral().get().getLiteral());
536: }
537:
538: private boolean isJavaClassNameAnnotation(OWLAnnotation a) {
539: final String classNameProperty = (String) configuration.getCliParams()
540: .valueOf(Option.JAVA_CLASSNAME_ANNOTATION.arg);
541: return a.getProperty().getIRI()
542:• .equals(IRI.create(classNameProperty != null ? classNameProperty : Constants.P_CLASS_NAME));
543: }
544:
545: private static boolean isClassNameUnique(String pkg, String simpleName, JCodeModel cm) {
546:• return cm._getClass(fqn(pkg, simpleName)) == null;
547: }
548:
549: private static String fqn(String pkg, String simpleName) {
550: return pkg + PACKAGE_SEPARATOR + simpleName;
551: }
552:
553: private boolean isPrefixedVersionRequired(OWLOntologyID ontologyId) {
554:• return configuration.shouldAlwaysUseOntologyPrefix()
555:• && (ontologyId.isAnonymous() || nameGenerator.hasPrefix(ontologyId.getOntologyIRI().get()));
556: }
557:
558: private void generateClassJavadoc(OWLOntology ontology, OWLEntity owlEntity, JDocCommentable javaElem) {
559: final boolean generated = generateJavadoc(ontology, owlEntity, javaElem);
560:• if (generated) {
561: javaElem.javadoc().add("\n\n");
562: }
563: generateAuthorshipDoc(javaElem);
564: }
565:
566: /**
567: * Add common properties such as id and type
568: */
569: private void addCommonClassFields(final JCodeModel cm, final JDefinedClass cls,
570: final PropertiesType propertiesType) {
571: // @Id(generated = true) protected String id;
572: final JClass ftId = cm.ref(String.class);
573: final JFieldVar fvId = addField(ID_FIELD_NAME, cls, ftId);
574: JAnnotationUse a = fvId.annotate(Id.class);
575: a.param("generated", true);
576:
577: JFieldVar fvLabel = null;
578:• if (configuration.shouldGenerateAnnotationFields()) {
579: // @OWLAnnotationProperty(iri = RDFS.LABEL) String name;
580: final JClass ftLabel = cm.ref(String.class);
581: fvLabel = addField(LABEL_FIELD_NAME, cls, ftLabel);
582: fvLabel.annotate(OWLAnnotationProperty.class).param("iri", cm.ref(RDFS.class).staticRef("LABEL"));
583:
584: // @OWLAnnotationProperty(iri = DC.Terms.DESCRIPTION) String description;
585: final JClass ftDescription = cm.ref(String.class);
586: final JFieldVar fvDescription = addField(DESCRIPTION_FIELD_NAME, cls, ftDescription);
587: fvDescription.annotate(OWLAnnotationProperty.class)
588: .param("iri", cm.ref(DC.Elements.class).staticRef("DESCRIPTION"));
589: }
590:
591: // @Types Set<String> types;
592: final JClass ftTypes = cm.ref(Set.class).narrow(String.class);
593: final JFieldVar fvTypes = addField(TYPES_FIELD_NAME, cls, ftTypes);
594: fvTypes.annotate(Types.class);
595:
596: // @Properties public final Map<String,Set<String>> properties;
597:• final Class<?> propertiesTypeC = (propertiesType == PropertiesType.object ? Object.class : String.class);
598: final JClass ftProperties = cm.ref(Map.class)
599: .narrow(cm.ref(String.class), cm.ref(Set.class).narrow(propertiesTypeC));
600: final JFieldVar fvProperties = addField(PROPERTIES_FIELD_NAME, cls, ftProperties);
601: fvProperties.annotate(Properties.class);
602:
603: generateToStringMethod(cls, fvId, fvLabel);
604: }
605:
606: private static void generateToStringMethod(JDefinedClass cls, JFieldVar idField, JFieldVar labelField) {
607: final JMethod toString = cls.method(JMod.PUBLIC, String.class, "toString");
608: toString.annotate(Override.class);
609: final JBlock body = toString.body();
610: JExpression expression = JExpr.lit(cls.name() + " {");
611:• if (labelField != null) {
612: expression = expression.plus(JExpr.ref(labelField.name()));
613: }
614: expression = expression.plus(JExpr.lit("<")).plus(JExpr.ref(idField.name())).plus(JExpr.lit(">"));
615: expression = expression.plus(JExpr.lit("}"));
616:
617: body._return(expression);
618: }
619: }