diff --git a/contract/src/test/java/org/obolibrary/oboformat/LoadAnonymousTestCase.java b/contract/src/test/java/org/obolibrary/oboformat/LoadAnonymousTestCase.java index 997e045fd9..c0d0af2f80 100644 --- a/contract/src/test/java/org/obolibrary/oboformat/LoadAnonymousTestCase.java +++ b/contract/src/test/java/org/obolibrary/oboformat/LoadAnonymousTestCase.java @@ -5,6 +5,7 @@ import static org.semanticweb.owlapi.vocab.OWL2Datatype.XSD_STRING; import java.util.Set; +import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.semanticweb.owlapi.api.test.baseclasses.TestBase; @@ -94,7 +95,10 @@ void shouldLoad() { AnnotationAssertion(Annotation(hasDbXref, literal), iao0000115, uo0.getIRI(), literal("A unit of measurement is a standardized quantity of a physical quality.")), AnnotationAssertion(Annotation(hasDbXref, literal), iao0000115, uo1.getIRI(), - literal("A unit which is a standard measure of the distance between two points."))); - assertEquals(expected, asUnorderedSet(ontology.axioms())); + literal("A unit which is a standard measure of the distance between two points.")), + AnnotationAssertion(RDFSLabel(), createdBy.getIRI(), literal("created by")), + AnnotationAssertion(RDFSLabel(), id.getIRI(), literal("id"))); + + assertEquals(expected.stream().map(Object::toString).sorted().collect(Collectors.joining("\n")), ontology.axioms().map(Object::toString).sorted().collect(Collectors.joining("\n"))); } } diff --git a/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestBasics.java b/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestBasics.java index 23508414b5..b71a7cf331 100644 --- a/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestBasics.java +++ b/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestBasics.java @@ -12,6 +12,7 @@ import org.obolibrary.oboformat.diff.OBODocDiffer; import org.obolibrary.oboformat.model.FrameStructureException; import org.obolibrary.oboformat.model.OBODoc; +import org.semanticweb.owlapi.formats.OBODocumentFormat; import org.semanticweb.owlapi.io.StringDocumentTarget; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLOntology; @@ -43,14 +44,19 @@ public List roundTripOBODoc(OBODoc obodoc, boolean isExpectRoundtrip) OWLOntology oo = convert(obodoc); StringDocumentTarget oo1 = saveOntology(oo); OBODoc obodoc2 = convert(oo); - StringDocumentTarget oo2 = saveOntology(convert(obodoc2)); + OWLOntology o2 = convert(obodoc2); + StringDocumentTarget oo2 = saveOntology(o2); String s1 = oo1.toString(); String s2 = oo2.toString(); assertEquals(s1, s2); obodoc2.check(); List diffs = OBODocDiffer.getDiffs(obodoc, obodoc2); if (isExpectRoundtrip) { - assertEquals(0, diffs.size(), "Expected no diffs but " + diffs); + if (diffs.size() > 0) { + StringDocumentTarget out1 = saveOntology(oo, new OBODocumentFormat()); + StringDocumentTarget out2 = saveOntology(o2, new OBODocumentFormat()); + assertEquals(out1.toString(), out2.toString()); + } } return diffs; } diff --git a/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestCase.java b/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestCase.java index 5e13eedda1..330e8d82b7 100644 --- a/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestCase.java +++ b/contract/src/test/java/org/obolibrary/oboformat/RoundTripTestCase.java @@ -229,7 +229,7 @@ void testRoundTripOWLRO() { Collection values = clause.getQualifierValues(); assertEquals(1, values.size()); QualifierValue value = values.iterator().next(); - assertEquals("http://purl.obolibrary.org/obo/IAO_0000116", value.getQualifier()); + assertEquals("IAO:0000116", value.getQualifier()); assertEquals("From Allen terminology", value.getValue()); found = true; } diff --git a/contract/src/test/java/org/obolibrary/oboformat/TagIRIsTest.java b/contract/src/test/java/org/obolibrary/oboformat/TagIRIsTest.java new file mode 100644 index 0000000000..a6e01aa218 --- /dev/null +++ b/contract/src/test/java/org/obolibrary/oboformat/TagIRIsTest.java @@ -0,0 +1,69 @@ +package org.obolibrary.oboformat; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.semanticweb.owlapi.api.test.baseclasses.TestBase; +import org.semanticweb.owlapi.model.IRI; +import org.semanticweb.owlapi.model.OWLAnnotation; +import org.semanticweb.owlapi.model.OWLAnnotationProperty; +import org.semanticweb.owlapi.model.OWLAxiom; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.vocab.OWL2Datatype; + +class TagIRIsTest extends TestBase { + + @Test + void testTagIRIMapping() { + OWLAnnotationProperty definition = + df.getOWLAnnotationProperty(IRI.create("http://purl.obolibrary.org/obo/IAO_0000115")); + OWLAnnotationProperty oioCreatedBy = df.getOWLAnnotationProperty( + IRI.create("http://www.geneontology.org/formats/oboInOwl#created_by")); + OWLAnnotationProperty oioInventedBy = df.getOWLAnnotationProperty( + IRI.create("http://www.geneontology.org/formats/oboInOwl#invented_by")); + OWLAnnotationProperty source = + df.getOWLAnnotationProperty(IRI.create("http://purl.obolibrary.org/obo/MYONT_20")); + OWLOntology ont = load("obo/tag_iris.obo", m); + Set axioms = ont.getAxioms(); + OWLClass term1 = df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/MYONT_1")); + OWLClass term2 = df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/MYONT_2")); + OWLClass term3 = df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/MYONT_3")); + OWLClass term4 = df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/MYONT_4")); + Set annotations = Stream + .of(df.getOWLAnnotation(df.getRDFSComment(), string("Here is a sub-annotation.")), + df.getOWLAnnotation(df.getRDFSSeeAlso(), string("A nested see also value."))) + .collect(Collectors.toSet()); + assertTrue(axioms.contains(df.getOWLAnnotationAssertionAxiom(definition, term1.getIRI(), + string("Definition of term one."), annotations))); + assertTrue(axioms.contains(df.getOWLAnnotationAssertionAxiom(df.getRDFSSeeAlso(), + term1.getIRI(), string("See also value.")))); + assertTrue(axioms.contains(df.getOWLAnnotationAssertionAxiom(definition, term2.getIRI(), + string("Definition of term two."), Collections + .singleton(df.getOWLAnnotation(source, string("A nested annotation value.")))))); + assertTrue(axioms.contains(df.getOWLAnnotationAssertionAxiom(definition, term3.getIRI(), + string("Definition of term three."), Collections + .singleton(df.getOWLAnnotation(source, string("A definition source value.")))))); + assertTrue( + axioms.contains( + df.getOWLAnnotationAssertionAxiom(oioCreatedBy, term3.getIRI(), string("goc:bro"))), + "created_by is built in and should not be overridden by a typedef"); + assertTrue( + axioms.contains(df.getOWLAnnotationAssertionAxiom(definition, term4.getIRI(), + string("Definition of term four."), + Collections + .singleton(df.getOWLAnnotation(oioInventedBy, string("An inventor value."))))), + "An undeclared tag should have oio namespace"); + + } + + protected OWLLiteral string(String l) { + return df.getOWLLiteral(l, OWL2Datatype.XSD_STRING); + } +} diff --git a/contract/src/test/java/org/semanticweb/owlapi/api/test/syntax/rdf/BOMSafeInputStreamAndParseTestCase.java b/contract/src/test/java/org/semanticweb/owlapi/api/test/syntax/rdf/BOMSafeInputStreamAndParseTestCase.java index 12d3a4d6d5..d3f5c9a21a 100644 --- a/contract/src/test/java/org/semanticweb/owlapi/api/test/syntax/rdf/BOMSafeInputStreamAndParseTestCase.java +++ b/contract/src/test/java/org/semanticweb/owlapi/api/test/syntax/rdf/BOMSafeInputStreamAndParseTestCase.java @@ -6,6 +6,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -13,8 +14,10 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.semanticweb.owlapi.api.test.baseclasses.TestBase; +import org.semanticweb.owlapi.formats.*; import org.semanticweb.owlapi.io.ReaderDocumentSource; import org.semanticweb.owlapi.model.IRI; +import org.semanticweb.owlapi.model.OWLDocumentFormat; import org.semanticweb.owlapi.model.OWLOntologyCreationException; class BOMSafeInputStreamAndParseTestCase extends TestBase { @@ -39,13 +42,20 @@ static Collection data() { "" //@formatter:on ); + List formats = Arrays.asList(new OWLXMLDocumentFormat(), + new ManchesterSyntaxDocumentFormat(), + new FunctionalSyntaxDocumentFormat(), + new RioTurtleDocumentFormat(), + new RDFXMLDocumentFormat()); + List prefixes = l(new int[] {0x00, 0x00, 0xFE, 0xFF}, new int[] {0xFF, 0xFE, 0x00, 0x00}, new int[] {0xFF, 0xFE}, new int[] {0xFE, 0xFF}, new int[] {0xEF, 0xBB, 0xBF}); for (int[] p : prefixes) { - for (String onto : list) { - toReturn.add(Arguments.of(p, onto)); - } + for (int i = 0; i < list.size(); i++) { + toReturn.add(Arguments.of(p, list.get(i), formats.get(i))); + + } } return toReturn; } @@ -72,18 +82,9 @@ private static InputStream in(int[] b, String content) throws IOException { // EF BB BF |UTF-8 @ParameterizedTest @MethodSource("data") - void testBOMError32big(int[] b, String input) throws IOException { + void testBOMError32big(int[] b, String input, OWLDocumentFormat format) throws IOException { try (InputStream in = in(b, input)) { loadFrom(in); } } - - @ParameterizedTest - @MethodSource("data") - void testBOMError32bigReader(int[] b, String input) - throws OWLOntologyCreationException, IOException { - try (InputStream in = in(b, input); InputStreamReader r = new InputStreamReader(in)) { - m.loadOntologyFromOntologyDocument(new ReaderDocumentSource(r)); - } - } } diff --git a/contract/src/test/resources/obo/tag_iris.obo b/contract/src/test/resources/obo/tag_iris.obo new file mode 100644 index 0000000000..9e463e4faa --- /dev/null +++ b/contract/src/test/resources/obo/tag_iris.obo @@ -0,0 +1,56 @@ +format-version: 1.2 +ontology: myont + +[Term] +id: MYONT:1 +name: term one +def: "Definition of term one." [] {comment="Here is a sub-annotation.", seeAlso="A nested see also value."} +property_value: seeAlso "See also value." xsd:string + +[Term] +id: MYONT:2 +name: term two +def: "Definition of term two." [] {MYONT:20="A nested annotation value."} +property_value: MYONT:21 "A top level annotation value." xsd:string + +[Term] +id: MYONT:3 +name: term three +def: "Definition of term three." [] {source="A definition source value."} +intersection_of: MYONT:2 ! term two +intersection_of: results_in_transport_across GO:0005739 ! mitochondrion +created_by: goc:bro + +[Term] +id: MYONT:4 +name: term four +def: "Definition of term four." [] {invented_by="An inventor value."} + +[Typedef] +id: source +name: source +xref: MYONT:20 +is_metadata_tag: true + +[Typedef] +id: MYONT:21 +name: source2 +is_metadata_tag: true + +[Typedef] +id: seeAlso +name: see also +xref: http://www.w3.org/2000/01/rdf-schema#seeAlso +is_metadata_tag: true + +[Typedef] +id: results_in_transport_across +name: results in transport across +namespace: external +xref: RO:0002342 + +[Typedef] +id: created_by +name: created by +namespace: external +xref: http://purl.org/dc/terms/creator diff --git a/impl/src/test/java/uk/ac/manchester/cs/owl/owlapi/concurrent/ConcurrentOWLOntologyImpl_TestCase.java b/impl/src/test/java/uk/ac/manchester/cs/owl/owlapi/concurrent/ConcurrentOWLOntologyImpl_TestCase.java index 69292cc41f..cdaced137c 100644 --- a/impl/src/test/java/uk/ac/manchester/cs/owl/owlapi/concurrent/ConcurrentOWLOntologyImpl_TestCase.java +++ b/impl/src/test/java/uk/ac/manchester/cs/owl/owlapi/concurrent/ConcurrentOWLOntologyImpl_TestCase.java @@ -1,6 +1,6 @@ package uk.ac.manchester.cs.owl.owlapi.concurrent; -import static org.mockito.ArgumentMatchers.anyListOf; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -84,7 +84,7 @@ class ConcurrentOWLOntologyImpl_TestCase { void setUp() { when(readWriteLock.readLock()).thenReturn(readLock); when(readWriteLock.writeLock()).thenReturn(writeLock); - when(delegate.applyChangesAndGetDetails(anyListOf(OWLOntologyChange.class))) + when(delegate.applyChangesAndGetDetails(anyList())) .thenReturn(new ChangeDetails(ChangeApplied.NO_OPERATION, Collections.emptyList())); ontology = spy(new ConcurrentOWLOntologyImpl(delegate, readWriteLock)); } diff --git a/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIObo2Owl.java b/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIObo2Owl.java index 8db29ac5b7..3501203aed 100644 --- a/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIObo2Owl.java +++ b/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIObo2Owl.java @@ -1,6 +1,7 @@ package org.obolibrary.obo2owl; import static org.obolibrary.obo2owl.Obo2OWLConstants.DEFAULT_IRI_PREFIX; +import static org.obolibrary.obo2owl.Obo2OWLConstants.OIOVOCAB_IRI_PREFIX; import static org.semanticweb.owlapi.util.OWLAPIPreconditions.checkNotNull; import static org.semanticweb.owlapi.util.OWLAPIPreconditions.emptyOptional; import static org.semanticweb.owlapi.util.OWLAPIPreconditions.optional; @@ -1373,21 +1374,29 @@ protected OWLIndividual trIndividual(String instId) { return fac.getOWLNamedIndividual(iri); } + private IRI trTagToIRIIncludingTypedefs(String tag) { + IRI iri = ANNOTATIONPROPERTYMAP.get(tag); + if (iri == null) { + iri = oboIdToIRI(tag, true); + } + return iri; + } + /** * Translate tag to annotation prop. - * + * * @param tag the tag * @return the OWL annotation property */ protected OWLAnnotationProperty trTagToAnnotationProp(String tag) { - IRI iri = trTagToIRI(tag); + IRI iri = trTagToIRIIncludingTypedefs(tag); OWLAnnotationProperty ap = fac.getOWLAnnotationProperty(iri); if (!apToDeclare.contains(ap)) { apToDeclare.add(ap); add(fac.getOWLDeclarationAxiom(ap)); Obo2OWLVocabulary vocab = Obo2OWLConstants.getVocabularyObj(tag); if (vocab != null) { - add(fac.getOWLAnnotationAssertionAxiom(iri, fac.getRDFSLabel(vocab.getLabel()))); + add(fac.getOWLAnnotationAssertionAxiom(iri, fac.getRDFSLabel(trLiteral(vocab.getLabel())))); } } return ap; @@ -1469,9 +1478,19 @@ protected OWLAnnotationValue trLiteral(Object inputValue) { * @return the iri */ public IRI oboIdToIRI(String id) { + return oboIdToIRI(id, false); + } + + /** + * Obo id to iri. + * + * @param id the id + * @return the iri + */ + public IRI oboIdToIRI(String id, boolean oboInOwlDefault) { IRI iri = idToIRICache.get(id); if (iri == null) { - iri = loadOboToIRI(id); + iri = loadOboToIRI(id, oboInOwlDefault); idToIRICache.put(id, iri); } return iri; @@ -1484,6 +1503,16 @@ public IRI oboIdToIRI(String id) { * @return the iri */ public IRI loadOboToIRI(String id) { + return loadOboToIRI(id, false); + } + + /** + * Obo id to iri. + * + * @param id the id + * @return the iri + */ + public IRI loadOboToIRI(String id, boolean oboInOwlDefault) { if (id.contains(" ")) { LOG.error("id contains space: \"{}\"", id); throw new OWLParserException("spaces not allowed: '" + id + '\''); @@ -1547,9 +1576,14 @@ public IRI loadOboToIRI(String id) { db = getDefaultIDSpace() + '#'; localId = idParts[0]; } - String uriPrefix = DEFAULT_IRI_PREFIX + db; - if (idSpaceMap.containsKey(db)) { - uriPrefix = idSpaceMap.get(db); + String uriPrefix; + if (oboInOwlDefault) { + uriPrefix = OIOVOCAB_IRI_PREFIX; + } else { + uriPrefix = DEFAULT_IRI_PREFIX + db; + if (idSpaceMap.containsKey(db)) { + uriPrefix = idSpaceMap.get(db); + } } String safeId; try { @@ -1570,10 +1604,9 @@ public IRI loadOboToIRI(String id) { } // 5.9.3. Special Rules for Relations - /** * Translate shorthand id to expanded id. - * + * * @param id the id * @return the string */ diff --git a/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIOwl2Obo.java b/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIOwl2Obo.java index fcac3ee467..4988d86541 100644 --- a/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIOwl2Obo.java +++ b/oboformat/src/main/java/org/obolibrary/obo2owl/OWLAPIOwl2Obo.java @@ -479,6 +479,8 @@ public static String owlObjectToTag(OWLObject obj) { String prefix = Obo2OWLConstants.OIOVOCAB_IRI_PREFIX; if (iri.startsWith(prefix)) { tag = iri.substring(prefix.length()); + } else { + tag = getIdentifier(iriObj); } } return tag; diff --git a/oboformat/src/main/java/org/obolibrary/obo2owl/Obo2OWLConstants.java b/oboformat/src/main/java/org/obolibrary/obo2owl/Obo2OWLConstants.java index 93746aa2af..04507cc53c 100644 --- a/oboformat/src/main/java/org/obolibrary/obo2owl/Obo2OWLConstants.java +++ b/oboformat/src/main/java/org/obolibrary/obo2owl/Obo2OWLConstants.java @@ -52,6 +52,9 @@ public enum Obo2OWLVocabulary implements HasIRI { /**IRI_IAO_0100001. */ IRI_IAO_0100001(DEFAULT_IRI_PREFIX, "IAO_0100001", "term replaced by", OboFormatTag.TAG_REPLACED_BY.getTag()), /**IRI_OIO_shorthand. */ IRI_OIO_shorthand(OIOVOCAB_IRI_PREFIX, "shorthand", "shorthand", "shorthand"), /**IRI_OIO_consider. */ IRI_OIO_consider(OIOVOCAB_IRI_PREFIX, "consider", "consider", OboFormatTag.TAG_CONSIDER.getTag()), + /**IRI_OIO_id*/ IRI_OIO_id(OIOVOCAB_IRI_PREFIX, "id", "id", OboFormatTag.TAG_ID.getTag()), + /**IRI_OIO_created_by*/ IRI_OIO_created_by(OIOVOCAB_IRI_PREFIX, "created_by", "created by", OboFormatTag.TAG_CREATED_BY.getTag()), + /**IRI_OIO_creation_date*/ IRI_OIO_creation_date(OIOVOCAB_IRI_PREFIX, "creation_date", "creation date", OboFormatTag.TAG_CREATION_DATE.getTag()), /**IRI_OIO_hasOBOFormatVersion. */ IRI_OIO_hasOBOFormatVersion(OIOVOCAB_IRI_PREFIX, "hasOBOFormatVersion", "has_obo_format_version", OboFormatTag.TAG_FORMAT_VERSION.getTag()), /**IRI_OIO_treatXrefsAsIsA. */ IRI_OIO_treatXrefsAsIsA(OIOVOCAB_IRI_PREFIX, "treat-xrefs-as-is_a", "treat-xrefs-as-is_a", OboFormatTag.TAG_TREAT_XREFS_AS_IS_A.getTag()), /**IRI_OIO_treatXrefsAsHasSubClass. */ IRI_OIO_treatXrefsAsHasSubClass(OIOVOCAB_IRI_PREFIX, "treat-xrefs-as-has-subclass", "treat-xrefs-as-has-subclass", OboFormatTag.TAG_TREAT_XREFS_AS_HAS_SUBCLASS.getTag()),