From 68868b942da845d910b1acf2e40b48bc96d165ee Mon Sep 17 00:00:00 2001 From: ignazio Date: Sun, 3 Mar 2019 22:32:34 +0000 Subject: [PATCH] Fix Cyclic imports and missing declarations cause parsing error #798 Ontology A imports ontology B, ontology B imports ontoloy A and ontology C, ontology C provides declaration for property P, ontology A uses property P. When loading A through its IRI, an ontology rename failure exception is raised. the reason is that A is parsed twice, once before and once after ontology C is parsed. However, when ontology C has yet to be parsed, there is no declaration available for P. This means that P is assumed to be an annotation property (only possible assumption, as the alternative is to throw a parsing error), and when the parsing of A completes, its id needs to be set with the value read from the ontology. However, at this point the two ontologies have the same id but not the same content - P has one guessed type and one parsed type, and the corresponding axioms differ. Hence, the api interprets this as two diffrent ontologies with the same id - which cannot coexist in the same manager. The full solution for this is for the parsers to work on two levels: ontology imports closure and entity declarations parsing, and axiom parsing. The ontologies to import and the declarations in each ontology would be parsed first, and once the closure has been computed, each ontology can be parsed with full knowledge of the entities declared - this removes the source of the error, in that there won't be any more cases of entities being used when their declaration has not been processed yet due to imports resolution and cycles. (This is how parsing is outlined in the specs, but it's not working exactly this way in practice and it's a considerable refactor for the current parsers.) (Other root issue: cycles in imports, this is not an indicator of a healthy ontology structure. It's allowed in OWL 2, but I cannot think of a scenario where the ontolgies wouldn't be easier to work with with imports refactored to not be cyclic). Luckily, when loading by IRIs, it's easy to avoid double parsing by adding the root ontology used at load time to the map of ontologies being imported, which is currently used to skip ultiple imports in the imports closure. The root was not included in this mechanism, for some reason - it should have been. Removing double parsing removes both issues, however the problem remains for root ontologies loaded from file or stream. --- .../owlapi6/impl/OWLOntologyManagerImpl.java | 293 +++++++++++------- 1 file changed, 174 insertions(+), 119 deletions(-) diff --git a/impl/src/main/java/org/semanticweb/owlapi6/impl/OWLOntologyManagerImpl.java b/impl/src/main/java/org/semanticweb/owlapi6/impl/OWLOntologyManagerImpl.java index 9f639fe04f..5b35c69404 100644 --- a/impl/src/main/java/org/semanticweb/owlapi6/impl/OWLOntologyManagerImpl.java +++ b/impl/src/main/java/org/semanticweb/owlapi6/impl/OWLOntologyManagerImpl.java @@ -15,6 +15,7 @@ import static org.semanticweb.owlapi6.utilities.OWLAPIPreconditions.checkNotNull; import static org.semanticweb.owlapi6.utilities.OWLAPIPreconditions.verifyNotNull; import static org.semanticweb.owlapi6.utilities.OWLAPIStreamUtils.asList; +import static org.semanticweb.owlapi6.utilities.OWLAPIStreamUtils.asUnorderedSet; import static org.semanticweb.owlapi6.utility.CollectionFactory.createSyncMap; import java.io.File; @@ -74,6 +75,7 @@ import org.semanticweb.owlapi6.model.OWLDocumentFormat; import org.semanticweb.owlapi6.model.OWLEntity; import org.semanticweb.owlapi6.model.OWLImportsDeclaration; +import org.semanticweb.owlapi6.model.OWLLogicalAxiom; import org.semanticweb.owlapi6.model.OWLMutableOntology; import org.semanticweb.owlapi6.model.OWLOntology; import org.semanticweb.owlapi6.model.OWLOntologyAlreadyExistsException; @@ -108,8 +110,7 @@ import org.slf4j.LoggerFactory; /** - * @author Matthew Horridge, The University Of Manchester, Bio-Health - * Informatics Group + * @author Matthew Horridge, The University Of Manchester, Bio-Health Informatics Group * @since 2.0.0 */ public class OWLOntologyManagerImpl @@ -119,23 +120,31 @@ public class OWLOntologyManagerImpl private static final Logger LOGGER = LoggerFactory.getLogger(OWLOntologyManagerImpl.class); protected final Map ontologiesByID = createSyncMap(); protected final Map documentIRIsByID = createSyncMap(); - protected final Map ontologyFormatsByOntology = createSyncMap(); - protected final Map ontologyIDsByImportsDeclaration = createSyncMap(); + protected final Map ontologyFormatsByOntology = + createSyncMap(); + protected final Map ontologyIDsByImportsDeclaration = + createSyncMap(); protected final AtomicInteger loadCount = new AtomicInteger(0); protected final AtomicInteger importsLoadCount = new AtomicInteger(0); protected final Map importedIRIs = createSyncMap(); protected final OWLDataFactory dataFactory; protected final Map> importsClosureCache = createSyncMap(); // XXX not covered by write lock - protected final List missingImportsListeners = new CopyOnWriteArrayList<>(); + protected final List missingImportsListeners = + new CopyOnWriteArrayList<>(); protected final List loaderListeners = new CopyOnWriteArrayList<>(); - protected final List progressListeners = new CopyOnWriteArrayList<>(); + protected final List progressListeners = + new CopyOnWriteArrayList<>(); protected final AtomicLong autoGeneratedURICounter = new AtomicLong(); private final AtomicBoolean broadcastChanges = new AtomicBoolean(true); - protected OWLOntologyChangeBroadcastStrategy defaultChangeBroadcastStrategy = new DefaultChangeBroadcastStrategy(); - protected ImpendingOWLOntologyChangeBroadcastStrategy defaultImpendingChangeBroadcastStrategy = new DefaultImpendingChangeBroadcastStrategy(); - private transient Map listenerMap = createSyncMap(); - private transient Map impendingChangeListenerMap = createSyncMap(); + protected OWLOntologyChangeBroadcastStrategy defaultChangeBroadcastStrategy = + new DefaultChangeBroadcastStrategy(); + protected ImpendingOWLOntologyChangeBroadcastStrategy defaultImpendingChangeBroadcastStrategy = + new DefaultImpendingChangeBroadcastStrategy(); + private transient Map listenerMap = + createSyncMap(); + private transient Map impendingChangeListenerMap = + createSyncMap(); private transient List vetoListeners = new ArrayList<>(); private OntologyConfigurator configProvider = new OntologyConfigurator(); protected final PriorityCollection documentMappers; @@ -147,10 +156,8 @@ public class OWLOntologyManagerImpl private final ReadWriteLock lock; /** - * @param dataFactory - * data factory - * @param readWriteLock - * lock + * @param dataFactory data factory + * @param readWriteLock lock */ @Inject public OWLOntologyManagerImpl(OWLDataFactory dataFactory, ReadWriteLock readWriteLock) { @@ -158,12 +165,9 @@ public OWLOntologyManagerImpl(OWLDataFactory dataFactory, ReadWriteLock readWrit } /** - * @param dataFactory - * data factory - * @param readWriteLock - * lock - * @param sorting - * sorting option + * @param dataFactory data factory + * @param readWriteLock lock + * @param sorting sorting option */ public OWLOntologyManagerImpl(OWLDataFactory dataFactory, ReadWriteLock readWriteLock, PriorityCollectionSorting sorting) { @@ -322,15 +326,16 @@ public Stream ontologyIDsByVersion(IRI iri) { @Override @Nullable public OWLOntology getOntology(IRI iri) { - OWLOntologyID ontologyID = getOWLDataFactory().getOWLOntologyID(Optional.ofNullable(iri), Optional.empty()); + OWLOntologyID ontologyID = + getOWLDataFactory().getOWLOntologyID(Optional.ofNullable(iri), Optional.empty()); readLock.lock(); try { OWLOntology result = ontologiesByID.get(ontologyID); if (result != null) { return result; } - java.util.Optional> findAny = ontologiesByID.entrySet().stream() - .filter(o -> o.getKey().match(iri)).findAny(); + java.util.Optional> findAny = + ontologiesByID.entrySet().stream().filter(o -> o.getKey().match(iri)).findAny(); return findAny.isPresent() ? findAny.get().getValue() : null; } finally { readLock.unlock(); @@ -344,8 +349,8 @@ public OWLOntology getOntology(OWLOntologyID id) { try { OWLOntology result = ontologiesByID.get(id); if (result == null && id.isNamed()) { - Optional findAny = ids().filter(o -> o.matchOntology(id.getOntologyIRI().get())) - .findAny(); + Optional findAny = + ids().filter(o -> o.matchOntology(id.getOntologyIRI().get())).findAny(); if (findAny.isPresent()) { result = ontologiesByID.get(findAny.get()); } @@ -366,7 +371,8 @@ public OWLOntology getOntology(OWLOntologyID id) { protected void checkDocumentIRI(OWLOntologyID id) { IRI documentIRI = getDocumentIRIFromMappers(id); if (documentIRI != null && documentIRIsByID.values().contains(documentIRI)) { - throw new OWLRuntimeException(new OWLOntologyDocumentAlreadyExistsException(documentIRI)); + throw new OWLRuntimeException( + new OWLOntologyDocumentAlreadyExistsException(documentIRI)); } } @@ -413,7 +419,8 @@ public Stream directImports(OWLOntology ontology) { if (!contains(ontology)) { throw new UnknownOWLOntologyException(ontology.getOntologyID()); } - return ontology.importsDeclarations().map(this::getImportedOntology).filter(Objects::nonNull); + return ontology.importsDeclarations().map(this::getImportedOntology) + .filter(Objects::nonNull); } finally { readLock.unlock(); } @@ -433,11 +440,9 @@ public Stream imports(OWLOntology ontology) { /** * A method that gets the imports of a given ontology. * - * @param ont - * The ontology whose (transitive) imports are to be retrieved. - * @param result - * A place to store the result - the transitive closure of the - * imports will be stored in this result set. + * @param ont The ontology whose (transitive) imports are to be retrieved. + * @param result A place to store the result - the transitive closure of the imports will be + * stored in this result set. * @return modified result */ private Set getImports(OWLOntology ont, Set result) { @@ -455,7 +460,8 @@ public Stream importsClosure(OWLOntology ontology) { readLock.lock(); try { OWLOntologyID id = ontology.getOntologyID(); - return importsClosureCache.computeIfAbsent(id, i -> getImportsClosure(ontology, new LinkedHashSet<>())) + return importsClosureCache + .computeIfAbsent(id, i -> getImportsClosure(ontology, new LinkedHashSet<>())) .stream(); } finally { readLock.unlock(); @@ -463,20 +469,19 @@ public Stream importsClosure(OWLOntology ontology) { } /** - * A recursive method that gets the reflexive transitive closure of the - * ontologies that are imported by this ontology. + * A recursive method that gets the reflexive transitive closure of the ontologies that are + * imported by this ontology. * - * @param ontology - * The ontology whose reflexive transitive closure is to be retrieved - * @param ontologies - * a place to store the result + * @param ontology The ontology whose reflexive transitive closure is to be retrieved + * @param ontologies a place to store the result * @return modified ontologies */ private Set getImportsClosure(OWLOntology ontology, Set ontologies) { readLock.lock(); try { ontologies.add(ontology); - directImports(ontology).filter(o -> !ontologies.contains(o)).forEach(o -> getImportsClosure(o, ontologies)); + directImports(ontology).filter(o -> !ontologies.contains(o)) + .forEach(o -> getImportsClosure(o, ontologies)); return ontologies; } finally { readLock.unlock(); @@ -526,7 +531,8 @@ public OWLDocumentFormat getOntologyFormat(OWLOntology ontology) { } @Override - public OWLOntology createOntology(OWLOntologyID ontologyID) throws OWLOntologyCreationException { + public OWLOntology createOntology(OWLOntologyID ontologyID) + throws OWLOntologyCreationException { writeLock.lock(); try { OWLOntology ontology = ontologiesByID.get(ontologyID); @@ -541,7 +547,8 @@ public OWLOntology createOntology(OWLOntologyID ontologyID) throws OWLOntologyCr if (factory.canCreateFromDocumentIRI(documentIRI)) { documentIRIsByID.put(ontologyID, documentIRI); factory.setLock(lock); - return factory.createOWLOntology(this, ontologyID, documentIRI, this, configProvider); + return factory.createOWLOntology(this, ontologyID, documentIRI, this, + configProvider); } } throw new OWLOntologyFactoryNotFoundException(documentIRI.toString()); @@ -563,15 +570,17 @@ protected IRI computeDocumentIRI(OWLOntologyID ontologyID) { } @Override - public OWLOntology createOntology(IRI ontologyIRI, Stream ontologies, boolean copyLogicalAxiomsOnly) - throws OWLOntologyCreationException { + public OWLOntology createOntology(IRI ontologyIRI, Stream ontologies, + boolean copyLogicalAxiomsOnly) throws OWLOntologyCreationException { writeLock.lock(); try { if (contains(ontologyIRI)) { - throw new OWLOntologyAlreadyExistsException(dataFactory.getOWLOntologyID(ontologyIRI)); + throw new OWLOntologyAlreadyExistsException( + dataFactory.getOWLOntologyID(ontologyIRI)); } OWLOntology ont = createOntology(ontologyIRI); - ont.addAxioms(ontologies.flatMap(o -> copyLogicalAxiomsOnly ? o.logicalAxioms() : o.axioms())); + ont.addAxioms( + ontologies.flatMap(o -> copyLogicalAxiomsOnly ? o.logicalAxioms() : o.axioms())); return ont; } finally { writeLock.unlock(); @@ -579,11 +588,13 @@ public OWLOntology createOntology(IRI ontologyIRI, Stream ontologie } @Override - public OWLOntology createOntology(Stream axioms, IRI ontologyIRI) throws OWLOntologyCreationException { + public OWLOntology createOntology(Stream axioms, IRI ontologyIRI) + throws OWLOntologyCreationException { writeLock.lock(); try { if (contains(ontologyIRI)) { - throw new OWLOntologyAlreadyExistsException(dataFactory.getOWLOntologyID(ontologyIRI)); + throw new OWLOntologyAlreadyExistsException( + dataFactory.getOWLOntologyID(ontologyIRI)); } OWLOntology ont = createOntology(ontologyIRI); ont.addAxioms(axioms); @@ -594,7 +605,8 @@ public OWLOntology createOntology(Stream axioms, IRI ontologyIRI) thro } @Override - public OWLOntology copyOntology(OWLOntology toCopy, OntologyCopy settings) throws OWLOntologyCreationException { + public OWLOntology copyOntology(OWLOntology toCopy, OntologyCopy settings) + throws OWLOntologyCreationException { writeLock.lock(); try { checkNotNull(toCopy); @@ -609,7 +621,8 @@ public OWLOntology copyOntology(OWLOntology toCopy, OntologyCopy settings) throw case DEEP: OWLOntology o = createOntology(toCopy.getOntologyID()); AxiomType.AXIOM_TYPES.forEach(t -> o.addAxioms(toCopy.axioms(t))); - toCopy.annotations().forEach(a -> o.applyChange(new AddOntologyAnnotation(o, a))); + toCopy.annotations() + .forEach(a -> o.applyChange(new AddOntologyAnnotation(o, a))); toCopy.importsDeclarations().forEach(a -> o.applyChange(new AddImport(o, a))); toReturn = o; break; @@ -643,11 +656,20 @@ public OWLOntology copyOntology(OWLOntology toCopy, OntologyCopy settings) throw @Override public OWLOntology loadOntology(IRI ontologyIRI) throws OWLOntologyCreationException { - return loadOntology(ontologyIRI, false, configProvider); + // if an ontology cyclically imports itself, the manager should not try to download from the + // same URL twice. + Object value = new Object(); + if (!importedIRIs.containsKey(ontologyIRI)) { + importedIRIs.put(ontologyIRI, value); + } + OWLOntology loadOntology = loadOntology(ontologyIRI, false, configProvider); + importedIRIs.remove(ontologyIRI, value); + return loadOntology; + } - protected OWLOntology loadOntology(IRI iri, boolean allowExists, OntologyConfigurator configuration) - throws OWLOntologyCreationException { + protected OWLOntology loadOntology(IRI iri, boolean allowExists, + OntologyConfigurator configuration) throws OWLOntologyCreationException { writeLock.lock(); try { OWLOntology ontByID = null; @@ -685,7 +707,8 @@ protected OWLOntology loadOntology(IRI iri, boolean allowExists, OntologyConfigu if (ontByDocumentIRI != null) { return ontByDocumentIRI; } - return loadOntology(iri, new IRIDocumentSource(documentIRI.toString(), null, null), configuration); + return loadOntology(iri, new IRIDocumentSource(documentIRI.toString(), null, null), + configuration); } finally { writeLock.unlock(); } @@ -695,8 +718,8 @@ protected OWLOntology loadOntology(IRI iri, boolean allowExists, OntologyConfigu private OWLOntology loadOntologyByDocumentIRI(IRI iri) { readLock.lock(); try { - java.util.Optional> findAny = documentIRIsByID.entrySet().stream() - .filter(o -> iri.equals(o.getValue())).findAny(); + java.util.Optional> findAny = documentIRIsByID.entrySet() + .stream().filter(o -> iri.equals(o.getValue())).findAny(); if (findAny.isPresent()) { return getOntology(findAny.get().getKey()); } @@ -710,8 +733,8 @@ private OWLOntology loadOntologyByDocumentIRI(IRI iri) { private OWLOntology getOntologyByDocumentIRI(IRI documentIRI) { readLock.lock(); try { - java.util.Optional> findAny = documentIRIsByID.entrySet().stream() - .filter(o -> documentIRI.equals(o.getValue())).findAny(); + java.util.Optional> findAny = documentIRIsByID.entrySet() + .stream().filter(o -> documentIRI.equals(o.getValue())).findAny(); if (findAny.isPresent()) { return ontologiesByID.get(findAny.get().getKey()); } @@ -722,10 +745,12 @@ private OWLOntology getOntologyByDocumentIRI(IRI documentIRI) { } @Override - public OWLOntology loadOntologyFromOntologyDocument(IRI documentIRI) throws OWLOntologyCreationException { + public OWLOntology loadOntologyFromOntologyDocument(IRI documentIRI) + throws OWLOntologyCreationException { // XXX check default // Ontology URI not known in advance - return loadOntology(null, new IRIDocumentSource(documentIRI.toString(), null, null), configProvider); + return loadOntology(null, new IRIDocumentSource(documentIRI.toString(), null, null), + configProvider); } @Override @@ -743,13 +768,15 @@ public OWLOntology loadOntologyFromOntologyDocument(OWLOntologyDocumentSource do } @Override - public OWLOntology loadOntologyFromOntologyDocument(File file) throws OWLOntologyCreationException { + public OWLOntology loadOntologyFromOntologyDocument(File file) + throws OWLOntologyCreationException { // XXX check default return loadOntologyFromOntologyDocument(new FileDocumentSource(file)); } @Override - public OWLOntology loadOntologyFromOntologyDocument(InputStream inputStream) throws OWLOntologyCreationException { + public OWLOntology loadOntologyFromOntologyDocument(InputStream inputStream) + throws OWLOntologyCreationException { // XXX check default return loadOntologyFromOntologyDocument(new StreamDocumentSource(inputStream)); } @@ -757,20 +784,17 @@ public OWLOntology loadOntologyFromOntologyDocument(InputStream inputStream) thr /** * This is the method that all the other load method delegate to. * - * @param ontologyIRI - * The URI of the ontology to be loaded. This is only used to report - * to listeners and may be {@code null} - * @param documentSource - * The input source that specifies where the ontology should be - * loaded from. - * @param configuration - * load configuration + * @param ontologyIRI The URI of the ontology to be loaded. This is only used to report to + * listeners and may be {@code null} + * @param documentSource The input source that specifies where the ontology should be loaded + * from. + * @param configuration load configuration * @return The ontology that was loaded. - * @throws OWLOntologyCreationException - * If the ontology could not be loaded. + * @throws OWLOntologyCreationException If the ontology could not be loaded. */ - protected OWLOntology loadOntology(@Nullable IRI ontologyIRI, OWLOntologyDocumentSource documentSource, - OntologyConfigurator configuration) throws OWLOntologyCreationException { + protected OWLOntology loadOntology(@Nullable IRI ontologyIRI, + OWLOntologyDocumentSource documentSource, OntologyConfigurator configuration) + throws OWLOntologyCreationException { writeLock.lock(); try { if (loadCount.get() != importsLoadCount.get()) { @@ -813,9 +837,20 @@ protected OWLOntology loadOntology(@Nullable IRI ontologyIRI, OWLOntologyDocumen } @Nullable - protected OWLOntology load(OWLOntologyDocumentSource documentSource, OntologyConfigurator configuration) - throws OWLOntologyCreationException { + protected OWLOntology load(OWLOntologyDocumentSource documentSource, + OntologyConfigurator configuration) throws OWLOntologyCreationException { IRI documentIRI = dataFactory.getIRI(documentSource.getDocumentIRI()); + // Check if this is an IRI source and the IRI has already been loaded - this will stop + // ontologies + // that cyclically import themselves from being loaded twice. + if (documentSource instanceof IRIDocumentSource) { + IRIDocumentSource source = (IRIDocumentSource) documentSource; + Optional> findAny = documentIRIsByID.entrySet().stream() + .filter(v -> Objects.equals(source.getDocumentIRI(), v.getValue())).findAny(); + if (findAny.isPresent()) { + return getOntology(findAny.get().getKey()); + } + } for (OWLOntologyFactory factory : ontologyFactories) { if (factory.canAttemptLoading(documentSource)) { try { @@ -823,7 +858,8 @@ protected OWLOntology load(OWLOntologyDocumentSource documentSource, OntologyCon // because it will be added // when the ontology is created. factory.setLock(lock); - OWLOntology ontology = factory.loadOWLOntology(this, documentSource, this, configuration); + OWLOntology ontology = + factory.loadOWLOntology(this, documentSource, this, configuration); if (configuration.shouldRepairIllegalPunnings()) { fixIllegalPunnings(ontology); } @@ -847,8 +883,9 @@ protected OWLOntology load(OWLOntologyDocumentSource documentSource, OntologyCon protected void fixIllegalPunnings(OWLOntology o) { Collection illegals = o.determineIllegalPunnings(true); Map> illegalDeclarations = new HashMap<>(); - o.axioms(AxiomType.DECLARATION, Imports.INCLUDED).filter(d -> illegals.contains(d.getEntity().getIRI())) - .forEach(d -> illegalDeclarations.computeIfAbsent(d.getEntity().getIRI(), x -> new HashSet<>()).add(d)); + o.axioms(AxiomType.DECLARATION, Imports.INCLUDED) + .filter(d -> illegals.contains(d.getEntity().getIRI())).forEach(d -> illegalDeclarations + .computeIfAbsent(d.getEntity().getIRI(), x -> new HashSet<>()).add(d)); Map replacementMap = new HashMap<>(); for (Map.Entry> e : illegalDeclarations.entrySet()) { if (e.getValue().size() == 1) { @@ -859,17 +896,20 @@ protected void fixIllegalPunnings(OWLOntology o) { // properties to annotation properties OWLEntity entity = correctDeclaration.getEntity(); if (entity.isOWLDataProperty() || entity.isOWLObjectProperty()) { - OWLAnnotationProperty wrongProperty = dataFactory.getOWLAnnotationProperty(entity.getIRI()); + OWLAnnotationProperty wrongProperty = + dataFactory.getOWLAnnotationProperty(entity.getIRI()); replacementMap.put(wrongProperty, entity); } } else { // Multiple declarations: bad data. Cannot be repaired // automatically. - String errorMessage = "Illegal redeclarations of entities: reuse of entity {} in punning not allowed {}"; + String errorMessage = + "Illegal redeclarations of entities: reuse of entity {} in punning not allowed {}"; LOGGER.warn(errorMessage, e.getKey(), e.getValue()); } } - OWLAnnotationPropertyTransformer changer = new OWLAnnotationPropertyTransformer(replacementMap, dataFactory); + OWLAnnotationPropertyTransformer changer = + new OWLAnnotationPropertyTransformer(replacementMap, dataFactory); List list = new ArrayList<>(); o.importsClosure().forEach(ont -> { for (OWLEntity e : replacementMap.keySet()) { @@ -915,7 +955,8 @@ public void removeOntology(OWLOntologyID ontologyID) { } protected void removeValue(Map map, S id) { - List keys = asList(map.entrySet().stream().filter(e -> e.getValue().equals(id)).map(Map.Entry::getKey)); + List keys = asList( + map.entrySet().stream().filter(e -> e.getValue().equals(id)).map(Map.Entry::getKey)); keys.forEach(map::remove); } @@ -956,13 +997,11 @@ public void setOntologyDocumentIRI(OWLOntology ontology, IRI documentIRI) { } /** - * Handles a rename of an ontology. This method should only be called - * *after* the change has been applied + * Handles a rename of an ontology. This method should only be called *after* the change has + * been applied * - * @param oldID - * The original ID of the ontology - * @param newID - * The new ID of the ontology + * @param oldID The original ID of the ontology + * @param newID The new ID of the ontology */ private void renameOntology(OWLOntologyID oldID, OWLOntologyID newID) { OWLOntology ont = ontologiesByID.get(oldID); @@ -1044,13 +1083,11 @@ public void setOntologyFactories(Set factories) { } /** - * Uses the mapper mechanism to obtain an ontology document IRI from an - * ontology IRI. + * Uses the mapper mechanism to obtain an ontology document IRI from an ontology IRI. * - * @param ontologyID - * The ontology ID for which a document IRI is to be retrieved - * @return The document IRI that corresponds to the ontology IRI, or - * {@code null} if no physical URI can be found. + * @param ontologyID The ontology ID for which a document IRI is to be retrieved + * @return The document IRI that corresponds to the ontology IRI, or {@code null} if no physical + * URI can be found. */ @Nullable private IRI getDocumentIRIFromMappers(OWLOntologyID ontologyID) { @@ -1068,7 +1105,8 @@ private IRI getDocumentIRIFromMappers(OWLOntologyID ontologyID) { } // Listener stuff - methods to add/remove listeners - private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + private void readObject(java.io.ObjectInputStream stream) + throws IOException, ClassNotFoundException { stream.defaultReadObject(); configProvider = (OntologyConfigurator) stream.readObject(); listenerMap = new ConcurrentHashMap<>(); @@ -1128,8 +1166,10 @@ public void broadcastImpendingChanges(Collection ch if (!broadcastChanges.get()) { return; } - for (ImpendingOWLOntologyChangeListener listener : new ArrayList<>(impendingChangeListenerMap.keySet())) { - ImpendingOWLOntologyChangeBroadcastStrategy strategy = impendingChangeListenerMap.get(listener); + for (ImpendingOWLOntologyChangeListener listener : new ArrayList<>( + impendingChangeListenerMap.keySet())) { + ImpendingOWLOntologyChangeBroadcastStrategy strategy = + impendingChangeListenerMap.get(listener); if (strategy != null) { strategy.broadcastChanges(listener, changes); } @@ -1223,8 +1263,8 @@ public void broadcastOntologyChangesVetoed(Collection(loaderListeners)) { - listener.startedLoadingOntology( - new OWLOntologyLoaderListener.LoadingStartedEvent(ontologyID, documentIRI, imported)); + listener.startedLoadingOntology(new OWLOntologyLoaderListener.LoadingStartedEvent( + ontologyID, documentIRI, imported)); } } finally { writeLock.unlock(); } } - protected void fireFinishedLoadingEvent(OWLOntologyID ontologyID, IRI documentIRI, boolean imported, - @Nullable Exception ex) { + protected void fireFinishedLoadingEvent(OWLOntologyID ontologyID, IRI documentIRI, + boolean imported, @Nullable Exception ex) { writeLock.lock(); try { for (OWLOntologyLoaderListener listener : new ArrayList<>(loaderListeners)) { - listener.finishedLoadingOntology( - new OWLOntologyLoaderListener.LoadingFinishedEvent(ontologyID, documentIRI, imported, ex)); + listener.finishedLoadingOntology(new OWLOntologyLoaderListener.LoadingFinishedEvent( + ontologyID, documentIRI, imported, ex)); } } finally { writeLock.unlock(); @@ -1447,21 +1490,25 @@ public void handleImportsChange(OWLOntologyChange change) { if (change.isImportChange()) { resetImportsClosureCache(); if (change instanceof AddImport) { - OWLImportsDeclaration addImportDeclaration = ((AddImport) change).getImportDeclaration(); + OWLImportsDeclaration addImportDeclaration = + ((AddImport) change).getImportDeclaration(); IRI iri = addImportDeclaration.getIRI(); - java.util.Optional findFirst = ids().filter(o -> o.match(iri) || o.matchDocument(iri)) - .findFirst(); - findFirst.ifPresent(o -> ontologyIDsByImportsDeclaration.put(addImportDeclaration, o)); + java.util.Optional findFirst = + ids().filter(o -> o.match(iri) || o.matchDocument(iri)).findFirst(); + findFirst + .ifPresent(o -> ontologyIDsByImportsDeclaration.put(addImportDeclaration, o)); if (!findFirst.isPresent()) { // then the import does not refer to a known IRI for // ontologies; check for a document IRI to find the ontology // id corresponding to the file location - documentIRIsByID.entrySet().stream().filter(o -> o.getValue().equals(iri)).findAny() - .ifPresent(o -> ontologyIDsByImportsDeclaration.put(addImportDeclaration, o.getKey())); + documentIRIsByID.entrySet().stream().filter(o -> o.getValue().equals(iri)) + .findAny().ifPresent(o -> ontologyIDsByImportsDeclaration + .put(addImportDeclaration, o.getKey())); } } else { // Remove the mapping from declaration to ontology - OWLImportsDeclaration importDeclaration = ((RemoveImport) change).getImportDeclaration(); + OWLImportsDeclaration importDeclaration = + ((RemoveImport) change).getImportDeclaration(); ontologyIDsByImportsDeclaration.remove(importDeclaration); importedIRIs.remove(importDeclaration.getIRI()); } @@ -1476,9 +1523,17 @@ public void handleOntologyIDChange(OWLOntologyChange change) { SetOntologyID setID = (SetOntologyID) change; OWLOntology existingOntology = ontologiesByID.get(setID.getNewOntologyID()); OWLOntology o = setID.getOntology(); - if (existingOntology != null && !o.equals(existingOntology) && !o.equalAxioms(existingOntology)) { - LOGGER.error("OWLOntologyManagerImpl.checkForOntologyIDChange() existing:{}", existingOntology); - LOGGER.error("OWLOntologyManagerImpl.checkForOntologyIDChange() new:{}", o); + if (existingOntology != null && !o.equals(existingOntology) + && !o.equalAxioms(existingOntology)) { + String location = "OWLOntologyManagerImpl.checkForOntologyIDChange()"; + LOGGER.error(location + " existing:{}", existingOntology); + LOGGER.error(location + " new:{}", o); + Set diff1 = asUnorderedSet(o.logicalAxioms()); + Set diff2 = asUnorderedSet(existingOntology.logicalAxioms()); + existingOntology.logicalAxioms().forEach(diff1::remove); + o.logicalAxioms().forEach(diff2::remove); + LOGGER.error(location + " only in existing:{}", diff2); + LOGGER.error(location + " only in new:{}", diff1); throw new OWLOntologyRenameException(setID.getChangeData(), setID.getNewOntologyID()); } renameOntology(setID.getOriginalOntologyID(), setID.getNewOntologyID());