From 18c845bcae47d794879c64c3198c394f713ae468 Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Fri, 13 May 2022 12:44:04 -0400 Subject: [PATCH 1/3] Ensure pending annotations are cleared after handling triple, in case no axiom was created which used them. --- .../semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java b/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java index 4226c218e2..93da126630 100644 --- a/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java +++ b/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java @@ -436,6 +436,10 @@ protected void handle(IRI s, IRI p, IRI o) { } } } + // Clears pending annotations; if this triple represents an annotated axiom, then if an axiom was created to annotate, + // pending will already be cleared. However, if an axiom was not created (e.g. invalid triple such as misuse of reserved + // vocabulary) if annotations are left they will be placed on an incorrect axiom. + consumer.getPendingAnnotations(); } protected void handle(IRI s, IRI p, OWLLiteral o) { From effe2b7585ae634ce0e19163024abd6ffe0ed1e5 Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Thu, 19 May 2022 10:33:53 -0400 Subject: [PATCH 2/3] Only remove unannotated axiom if it received annotations. --- .../owlapi/rdf/rdfxml/parser/TripleHandlers.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java b/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java index 93da126630..f039df7f6c 100644 --- a/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java +++ b/parsers/src/main/java/org/semanticweb/owlapi/rdf/rdfxml/parser/TripleHandlers.java @@ -2389,8 +2389,10 @@ public void handleTriple(IRI s, IRI p, IRI o) { } if (!annotations.isEmpty()) { OWLAxiom ax = consumer.getLastAddedAxiom(); - consumer.removeAxiom(verifyNotNull(ax, "no axiom added yet by the consumer") - .getAxiomWithoutAnnotations()); + // Only remove unannotated axiom if it received annotations + if (!verifyNotNull(ax, "no axiom added yet by the consumer").getAnnotations().isEmpty()) { + consumer.removeAxiom(ax.getAxiomWithoutAnnotations()); + } } consume(s, p, o); } From c5d64690b198ec838f0436fb48b4d3aab4308598 Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Thu, 19 May 2022 10:37:58 -0400 Subject: [PATCH 3/3] Add axiom annotation parsing test. --- ...ParsingAmongMalformedAxiomAnnotations.java | 33 +++++ ...rdfParserReservedPropertiesAnnotations.ttl | 115 ++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 contract/src/test/java/org/semanticweb/owlapi/rio/TestRDFParsingAmongMalformedAxiomAnnotations.java create mode 100644 contract/src/test/resources/rdfParserReservedPropertiesAnnotations.ttl diff --git a/contract/src/test/java/org/semanticweb/owlapi/rio/TestRDFParsingAmongMalformedAxiomAnnotations.java b/contract/src/test/java/org/semanticweb/owlapi/rio/TestRDFParsingAmongMalformedAxiomAnnotations.java new file mode 100644 index 0000000000..bbb0158676 --- /dev/null +++ b/contract/src/test/java/org/semanticweb/owlapi/rio/TestRDFParsingAmongMalformedAxiomAnnotations.java @@ -0,0 +1,33 @@ +package org.semanticweb.owlapi.rio; + + +import org.junit.jupiter.api.Test; +import org.semanticweb.owlapi.apibinding.OWLManager; +import org.semanticweb.owlapi.model.OWLAnnotation; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyCreationException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class TestRDFParsingAmongMalformedAxiomAnnotations { + + @Test + public void testAxiomParsing() throws OWLOntologyCreationException, IOException { + try (InputStream ttlStream = this.getClass().getResourceAsStream("/rdfParserReservedPropertiesAnnotations.ttl")) { + OWLOntology ontTTL = OWLManager.createOWLOntologyManager().loadOntologyFromOntologyDocument(ttlStream); + assertEquals(14, ontTTL.getAxiomCount(), "Test file should have 14 axioms"); + Optional annotationOpt = ontTTL.getAxioms().stream() + .flatMap(ax -> ax.getAnnotations().stream()) + .filter(ann -> ann.getValue().isLiteral()) + .filter(ann -> ann.getValue().asLiteral().get().getLiteral().equals("This assertion is annotated")) + .findAny(); + assertFalse(annotationOpt.isPresent(), "Annotation should not have been added to any axiom."); + } + } + +} diff --git a/contract/src/test/resources/rdfParserReservedPropertiesAnnotations.ttl b/contract/src/test/resources/rdfParserReservedPropertiesAnnotations.ttl new file mode 100644 index 0000000000..2ab39fea26 --- /dev/null +++ b/contract/src/test/resources/rdfParserReservedPropertiesAnnotations.ttl @@ -0,0 +1,115 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@base . + + rdf:type owl:Ontology . + +################################################################# +# Object Properties +################################################################# + +### http://example.org/contains +:contains rdf:type owl:ObjectProperty . + + +### http://example.org/has_book +:has_book rdf:type owl:ObjectProperty ; + owl:propertyChainAxiom ( :has_books + :contains + ) . + + +### http://example.org/has_books +:has_books rdf:type owl:ObjectProperty . + + +################################################################# +# Classes +################################################################# + +### http://example.org/Book +:Book rdf:type owl:Class . + + +### http://example.org/BookOrLibrary +:BookOrLibrary rdf:type owl:Class ; + owl:equivalentClass [ rdf:type owl:Class ; + owl:unionOf ( :Book + :Library + ) + ] . + +[ rdf:type owl:Axiom ; + owl:annotatedSource :BookOrLibrary ; + owl:annotatedProperty owl:equivalentClass ; + owl:annotatedTarget [ rdf:type owl:Class ; + owl:unionOf ( :Book + :Library + ) + ] ; + rdfs:comment "This equivalence axiom is annotated." + ] . + + +### http://example.org/Library +:Library rdf:type owl:Class ; + rdfs:subClassOf [ rdf:type owl:Restriction ; + owl:onProperty :has_books ; + owl:allValuesFrom [ rdf:type owl:Restriction ; + owl:onProperty :contains ; + owl:allValuesFrom :Book + ] + ] . + + +################################################################# +# Individuals +################################################################# + +### http://example.org/moby_dick +:moby_dick rdf:type owl:NamedIndividual . + + +### http://example.org/the_library +:the_library rdf:type owl:NamedIndividual , + :Library . + +[ rdf:type owl:Axiom ; + owl:annotatedSource :the_library ; + owl:annotatedProperty rdf:type ; + owl:annotatedTarget :Library ; + rdfs:comment "This class assertion is annotated." + ] . + + +### http://example.org/the_republic +:the_republic rdf:type owl:NamedIndividual . + +_:genid42 rdf:type owl:Axiom ; + owl:annotatedSource _:genid8 ; + owl:annotatedProperty rdf:first ; + owl:annotatedTarget :moby_dick ; + rdfs:comment "This assertion is annotated" . + +# These triples should be ignored +_:genid43 rdf:type owl:Axiom ; + owl:annotatedSource _:genid8 ; + owl:annotatedProperty rdfs:first ; #Not a real property but triggers bug + owl:annotatedTarget :moby_dick ; + rdfs:comment "This assertion is annotated" . + +# These triples should be ignored +_:genid44 rdf:type owl:Axiom ; + owl:annotatedSource _:genid8 ; + owl:annotatedProperty rdf:subject ; + owl:annotatedTarget :moby_dick ; + rdfs:comment "This assertion is annotated" . + +_:genid8 :contains :moby_dick . + + +### Generated by the OWL API (version 4.5.9.2019-02-01T07:24:44Z) https://github.com/owlcs/owlapi