Skip to contentMethod: ignoreMissingImports(boolean)
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 cz.cvut.kbss.jopa.owl2java.config.TransformationConfiguration;
21: import cz.cvut.kbss.jopa.owl2java.exception.OWL2JavaException;
22: import cz.cvut.kbss.jopa.util.MappingFileParser;
23: import org.semanticweb.owlapi.apibinding.OWLManager;
24: import org.semanticweb.owlapi.model.*;
25: import org.semanticweb.owlapi.search.EntitySearcher;
26: import org.semanticweb.owlapi.util.OWLOntologyMerger;
27: import org.slf4j.Logger;
28: import org.slf4j.LoggerFactory;
29:
30: import javax.annotation.Nonnull;
31: import java.io.File;
32: import java.net.URI;
33: import java.util.*;
34: import java.util.function.Consumer;
35: import java.util.stream.Stream;
36:
37: public class OWL2JavaTransformer {
38:
39: private static final Logger LOG = LoggerFactory.getLogger(OWL2JavaTransformer.class);
40:
41: private OWLOntology ontology;
42:
43: private final ValidContextAnnotationValueVisitor v = new ValidContextAnnotationValueVisitor();
44:
45: private final ContextDefinition defaultContext = new ContextDefinition();
46: private final Map<String, ContextDefinition> contexts = new HashMap<>();
47:
48: private boolean ignoreMissingImports;
49:
50: public Collection<String> listContexts() {
51: return contexts.keySet();
52: }
53:
54: public void ignoreMissingImports(boolean ignore) {
55: this.ignoreMissingImports = ignore;
56: }
57:
58: private OWLOntology getWholeOntology(final String owlOntologyName, final String mappingFile) {
59: // reader
60: final OWLOntologyManager m = OWLManager.createOWLOntologyManager();
61:
62: if (mappingFile != null) {
63: LOG.info("Using mapping file '{}'.", mappingFile);
64:
65: final Map<URI, URI> map = MappingFileParser.getMappings(new File(mappingFile));
66: m.getIRIMappers().add(ontologyIRI -> {
67: final URI value = map.get(ontologyIRI.toURI());
68:
69: if (value == null) {
70: return null;
71: } else {
72: return IRI.create(value);
73: }
74: });
75: LOG.info("Mapping file successfully parsed.");
76: }
77:
78: LOG.info("Loading ontology {}... ", owlOntologyName);
79: if (ignoreMissingImports) {
80: m.getOntologyConfigurator().setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT);
81: m.addMissingImportListener(e -> {
82: LOG.warn("Unable to import ontology {}.", e.getImportedOntologyURI());
83: LOG.debug("Error: {}", e.getCreationException().getMessage());
84: });
85: }
86:
87: try {
88: m.loadOntology(IRI.create(owlOntologyName));
89: return new OWLOntologyMerger(m).createMergedOntology(m, null);
90: } catch (OWLException | OWLRuntimeException e) {
91: LOG.error(e.getMessage(), e);
92: throw new OWL2JavaException("Unable to load ontology " + owlOntologyName, e);
93: }
94: }
95:
96: public void setOntology(final String owlOntologyName, final String mappingFile) {
97: this.ontology = getWholeOntology(owlOntologyName, mappingFile);
98:
99: LOG.debug("Parsing integrity constraints");
100:
101: ontology.axioms().forEach(a -> {
102: defaultContext.addAxiom(a);
103: for (final String icContextName : getContexts(a)) {
104: ContextDefinition ctx = getContextDefinition(icContextName);
105: ctx.addAxiom(a);
106: }
107: });
108: registerEntitiesInContexts();
109:
110: defaultContext.parse();
111: for (final ContextDefinition ctx : contexts.values()) {
112: ctx.parse();
113: }
114:
115: LOG.debug("Integrity constraints successfully parsed.");
116: }
117:
118: private void registerEntitiesInContexts() {
119: final Consumer<Stream<? extends OWLEntity>> consumer = stream -> stream.forEach(e -> {
120: defaultContext.add(e);
121: for (final String context : getContexts(e)) {
122: getContextDefinition(context).add(e);
123: }
124: });
125: consumer.accept(ontology.classesInSignature());
126: consumer.accept(ontology.objectPropertiesInSignature());
127: consumer.accept(ontology.dataPropertiesInSignature());
128: consumer.accept(ontology.annotationPropertiesInSignature());
129: }
130:
131: private ContextDefinition getContextDefinition(String icContextName) {
132: return contexts.computeIfAbsent(icContextName, name -> new ContextDefinition());
133: }
134:
135: private List<String> getContexts(final OWLAxiom a) {
136: final List<String> icContexts = new ArrayList<>();
137: a.annotations().filter(p -> p.getProperty().getIRI().toString().equals(Constants.P_IS_INTEGRITY_CONSTRAINT_FOR))
138: .forEach(p -> {
139: LOG.trace("Processing annotation : " + p);
140: p.getValue().accept(v);
141: final String icContextName = v.getName();
142: LOG.trace("CONTEXT:" + icContextName);
143: if (icContextName == null) {
144: return;
145: }
146: LOG.debug("Found IC {} for context {}", a, icContextName);
147: icContexts.add(icContextName);
148: });
149: return icContexts;
150: }
151:
152: private List<String> getContexts(final OWLEntity entity) {
153: final List<String> icContexts = new ArrayList<>();
154: EntitySearcher.getAnnotations(entity, ontology)
155: .filter(p -> p.getProperty().getIRI().toString().equals(Constants.P_IS_INTEGRITY_CONSTRAINT_FOR))
156: .forEach(p -> {
157: LOG.trace("Processing annotation : " + p);
158: p.getValue().accept(v);
159: final String icContextName = v.getName();
160: LOG.trace("CONTEXT:" + icContextName);
161: if (icContextName == null) {
162: return;
163: }
164: LOG.debug("Found OWLEntity declaration {} for context {}", entity, icContextName);
165: icContexts.add(icContextName);
166: });
167: return icContexts;
168: }
169:
170: private void verifyContextExistence(String context) {
171: if (!contexts.containsKey(context)) {
172: throw new IllegalArgumentException(
173: "Context " + context + " not found. Existing contexts: " + listContexts());
174: }
175: }
176:
177: public void transform(TransformationConfiguration transformConfig) {
178: final ContextDefinition def = getValidContext(transformConfig);
179: LOG.info("Transforming context ...");
180: final ObjectModel result = new JavaTransformer(transformConfig).generateModel(ontology, def);
181: result.writeModel(transformConfig.getTargetDir());
182: LOG.info("Transformation SUCCESSFUL.");
183: }
184:
185: private ContextDefinition getValidContext(TransformationConfiguration configuration) {
186: if (configuration.areAllAxiomsIntegrityConstraints()) {
187: LOG.info(" - for all axioms");
188: return defaultContext;
189: }
190: final String context = configuration.getContext();
191: verifyContextExistence(context);
192: LOG.info(" - for context '{}'.", context);
193: return contexts.get(context);
194: }
195:
196: /**
197: * Generates only vocabulary of the loaded ontology.
198: *
199: * @param transformConfig Configuration of the generation process
200: */
201: public void generateVocabulary(TransformationConfiguration transformConfig) {
202: LOG.info("Generating vocabulary ...");
203:
204: ContextDefinition def = getValidContext(transformConfig);
205: final ObjectModel result = new JavaTransformer(transformConfig).generateVocabulary(ontology, def);
206: result.writeModel(transformConfig.getTargetDir());
207: }
208:
209: private static class ValidContextAnnotationValueVisitor implements OWLAnnotationValueVisitor {
210:
211: private String name;
212:
213: String getName() {
214: return name;
215: }
216:
217: @Override
218: public void visit(@Nonnull OWLLiteral literal) {
219: this.name = literal.getLiteral();
220: }
221: }
222: }