From eb7a7b734db79b7a7966d06eec8e52711770e467 Mon Sep 17 00:00:00 2001 From: Becky Jackson Date: Fri, 30 Sep 2022 10:15:15 -0700 Subject: [PATCH 1/5] Add input-format option --- docs/global.md | 5 + .../obolibrary/robot/CommandLineHelper.java | 72 +++++++++- .../java/org/obolibrary/robot/IOHelper.java | 126 +++++++++++++++--- 3 files changed, 182 insertions(+), 21 deletions(-) diff --git a/docs/global.md b/docs/global.md index c5f560c81..ec0d9853f 100644 --- a/docs/global.md +++ b/docs/global.md @@ -8,6 +8,7 @@ 4. [Logging (`-v`, `-vv`, `-vvv`)](#logging) 5. [XML Entities (`--xml-entities`)](#xml-entities) 6. [Strict Parsing (`--strict`)](#strict-parsing) +7. [Input Format (`--input-format`)](#input-format) ## Java Options @@ -131,6 +132,10 @@ _:blank rdf:type rdf:Statement . _:blank rdf:type owl:Axiom . ``` +## Input Format + +When loading an ontology, OWLAPI will attempt to load with a variety of ontology format parsers. When all parsers fail, many error logs are printed (when using verbose mode). Finding the cause of the error based on parser can be difficult due to number of messages. For debugging purposes, you can specify the `--input-format` of the ontology as one of: `owl`, `obo`, `owx`, `ofn`, `omn`, `ttl`, or `json`. + --- ## Error Messages diff --git a/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java b/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java index 4c63a4793..c16d03f71 100644 --- a/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java +++ b/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java @@ -3,6 +3,7 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import com.github.jsonldjava.core.Context; +import com.google.common.collect.Sets; import java.io.*; import java.net.URI; import java.net.URISyntaxException; @@ -21,8 +22,20 @@ import org.geneontology.reasoner.ExpressionMaterializingReasonerFactory; import org.geneontology.whelk.owlapi.WhelkOWLReasonerFactory; import org.semanticweb.elk.owlapi.ElkReasonerFactory; +import org.semanticweb.owlapi.apibinding.OWLManager; +import org.semanticweb.owlapi.functional.parser.OWLFunctionalSyntaxOWLParserFactory; +import org.semanticweb.owlapi.io.OWLParserFactory; +import org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntaxOntologyParserFactory; import org.semanticweb.owlapi.model.*; +import org.semanticweb.owlapi.oboformat.OBOFormatOWLAPIParserFactory; +import org.semanticweb.owlapi.owlxml.parser.OWLXMLParserFactory; +import org.semanticweb.owlapi.rdf.rdfxml.parser.RDFXMLParserFactory; +import org.semanticweb.owlapi.rdf.turtle.parser.TurtleOntologyParserFactory; import org.semanticweb.owlapi.reasoner.OWLReasonerFactory; +import org.semanticweb.owlapi.rio.RioJsonLDParserFactory; +import org.semanticweb.owlapi.rio.RioJsonParserFactory; +import org.semanticweb.owlapi.rio.RioRDFXMLParserFactory; +import org.semanticweb.owlapi.rio.RioTurtleParserFactory; import org.slf4j.LoggerFactory; import uk.ac.manchester.cs.jfact.JFactFactory; @@ -66,7 +79,11 @@ public class CommandLineHelper { /** Error message when more than one --input is specified, excluding merge and unmerge. */ private static final String multipleInputsError = - NS + "MULITPLE INPUTS ERROR only one --input is allowed"; + NS + "MULTIPLE INPUTS ERROR only one --input is allowed"; + + private static final String unknownInputFormatError = + NS + + "UNKNOWN INPUT FORMAT ERROR --input-format must be one of: owl, ofn, owx, omn, obo, ttl, or json"; /** Error message when the --inputs pattern does not include * or ?, or is not quoted */ private static final String wildcardError = @@ -462,7 +479,7 @@ public static OWLOntology getInputOntology(IOHelper ioHelper, CommandLine line) * @param line the command line to use * @param catalogPath the catalog to use to load imports * @return the input ontology - * @throws IllegalArgumentException if requires options are missing + * @throws IllegalArgumentException if required options are missing * @throws IOException if the ontology cannot be loaded */ public static OWLOntology getInputOntology( @@ -476,17 +493,26 @@ public static OWLOntology getInputOntology( throw new IllegalArgumentException(multipleInputsError); } + // Create a manager to load ontology and maybe set parsers + // Otherwise, all parsers will be tried + OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); + String inputFormat = getOptionalValue(line, "input-format"); + if (inputFormat != null) { + Set parsers = getParsersByFormat(inputFormat); + manager.setOntologyParsers(parsers); + } + if (!inputOntologyPaths.isEmpty()) { if (catalogPath != null) { - return ioHelper.loadOntology(inputOntologyPaths.get(0), catalogPath); + return ioHelper.loadOntology(manager, inputOntologyPaths.get(0), catalogPath); } else { - return ioHelper.loadOntology(inputOntologyPaths.get(0)); + return ioHelper.loadOntology(manager, inputOntologyPaths.get(0)); } } else if (!inputOntologyIRIs.isEmpty()) { if (catalogPath != null) { - return ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0)), catalogPath); + return ioHelper.loadOntology(manager, IRI.create(inputOntologyIRIs.get(0)), catalogPath); } else { - return ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0))); + return ioHelper.loadOntology(manager, IRI.create(inputOntologyIRIs.get(0))); } } else { // Both input options are empty @@ -908,6 +934,11 @@ public static Options getCommonOptions() { o.addOption("v", "verbose", false, "increased logging"); o.addOption("vv", "very-verbose", false, "high logging"); o.addOption("vvv", "very-very-verbose", false, "maximum logging, including stack traces"); + o.addOption( + null, + "input-format", + true, + "format of the input ontology: obo, owl, ttl, owx, omn, ofn, json"); o.addOption(null, "catalog", true, "use catalog from provided file"); o.addOption("p", "prefix", true, "add a prefix 'foo: http://bar'"); o.addOption("P", "prefixes", true, "use prefixes from JSON-LD file"); @@ -1055,6 +1086,35 @@ private static File[] getFilesByPattern(String pattern) throws IllegalArgumentEx return files; } + /** + * Get a set of parsers for a given ontology format. + * + * @param format ontology file format as string + * @return set of OWLParserFactories + * @throws IllegalArgumentException on bad format + */ + private static Set getParsersByFormat(String format) + throws IllegalArgumentException { + switch (format) { + case "omn": + return Sets.newHashSet(new ManchesterOWLSyntaxOntologyParserFactory()); + case "obo": + return Sets.newHashSet(new OBOFormatOWLAPIParserFactory()); + case "ofn": + return Sets.newHashSet(new OWLFunctionalSyntaxOWLParserFactory()); + case "owx": + return Sets.newHashSet(new OWLXMLParserFactory()); + case "owl": + return Sets.newHashSet(new RDFXMLParserFactory(), new RioRDFXMLParserFactory()); + case "ttl": + return Sets.newHashSet(new RioTurtleParserFactory(), new TurtleOntologyParserFactory()); + case "json": + return Sets.newHashSet(new RioJsonParserFactory(), new RioJsonLDParserFactory()); + default: + throw new IllegalArgumentException(unknownInputFormatError); + } + } + /** * Given an IOHelper and a command line, check input options and return a list of loaded input * ontologies. diff --git a/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java b/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java index b8b10d240..6c5acd696 100644 --- a/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java +++ b/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java @@ -306,6 +306,25 @@ public OWLOntology loadOntology(String ontologyPath) throws IOException { return loadOntology(ontologyFile, catalogFile); } + /** + * Load an ontology using a manager from a String path, using a catalog file if available. + * + * @param manager OWLOntologyManager to use to load ontology + * @param ontologyPath the path to the ontology file + * @return a new ontology object + * @throws IOException on any problem + */ + public OWLOntology loadOntology(OWLOntologyManager manager, String ontologyPath) + throws IOException { + File ontologyFile = new File(ontologyPath); + File catalogFile = guessCatalogFile(ontologyFile); + if (!catalogFile.isFile()) { + // If the catalog file does not exist, do not use catalog + catalogFile = null; + } + return loadOntology(manager, ontologyFile, catalogFile); + } + /** * Load an ontology from a String path, with option to use catalog file. * @@ -337,6 +356,22 @@ public OWLOntology loadOntology(String ontologyPath, String catalogPath) throws return loadOntology(ontologyFile, catalogFile); } + /** + * Load an ontology using a manager from a String path, with optional catalog file. + * + * @param manager OWLOntology manager to use + * @param ontologyPath the path to the ontology file + * @param catalogPath the path to the catalog file + * @return a new ontology object + * @throws IOException on any problem + */ + public OWLOntology loadOntology( + OWLOntologyManager manager, String ontologyPath, String catalogPath) throws IOException { + File ontologyFile = new File(ontologyPath); + File catalogFile = new File(catalogPath); + return loadOntology(manager, ontologyFile, catalogFile); + } + /** * Load an ontology from a File, using a catalog file if available. * @@ -378,9 +413,23 @@ public OWLOntology loadOntology(File ontologyFile, boolean useCatalog) throws IO * @throws IOException on any problem */ public OWLOntology loadOntology(File ontologyFile, File catalogFile) throws IOException { + OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); + return loadOntology(manager, ontologyFile, catalogFile); + } + + /** + * Load an ontology using a manager from a File, with optional catalog File. + * + * @param manager OWLOntologyManager to load ontology + * @param ontologyFile the ontology file to load + * @param catalogFile the catalog file to use + * @return a new ontology object, with a new OWLManager + * @throws IOException on any problem + */ + public OWLOntology loadOntology(OWLOntologyManager manager, File ontologyFile, File catalogFile) + throws IOException { logger.debug("Loading ontology {} with catalog file {}", ontologyFile, catalogFile); Object jsonObject = null; - OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); try { String extension = FilenameUtils.getExtension(ontologyFile.getName()); @@ -415,9 +464,9 @@ public OWLOntology loadOntology(File ontologyFile, File catalogFile) throws IOEx // Maybe unzip if (ontologyFile.getPath().endsWith(".gz")) { if (catalogFile == null) { - return loadCompressedOntology(ontologyFile, null); + return loadCompressedOntology(manager, ontologyFile, null); } else { - return loadCompressedOntology(ontologyFile, catalogFile.getAbsolutePath()); + return loadCompressedOntology(manager, ontologyFile, catalogFile.getAbsolutePath()); } } @@ -449,6 +498,22 @@ public OWLOntology loadOntology(InputStream ontologyStream) throws IOException { */ public OWLOntology loadOntology(InputStream ontologyStream, String catalogPath) throws IOException { + OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); + return loadOntology(manager, ontologyStream, catalogPath); + } + + /** + * Load an ontology using a manager from an InputStream with a catalog file. + * + * @param manager OWLOntologyManager to load ontology + * @param ontologyStream the ontology stream to load + * @param catalogPath the catalog file to use or null + * @return a new ontology object + * @throws IOException on any problem + */ + public OWLOntology loadOntology( + OWLOntologyManager manager, InputStream ontologyStream, String catalogPath) + throws IOException { OWLOntology ontology; // Maybe load a catalog file File catalogFile = null; @@ -459,7 +524,6 @@ public OWLOntology loadOntology(InputStream ontologyStream, String catalogPath) } } try { - OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); if (catalogFile != null) { manager.setIRIMappers(Sets.newHashSet(new CatalogXmlIRIMapper(catalogFile))); } @@ -481,6 +545,18 @@ public OWLOntology loadOntology(IRI ontologyIRI) throws IOException { return loadOntology(ontologyIRI, null); } + /** + * Given an ontology manager and ontology IRI, load the ontology from the IRI using the manager. + * + * @param manager OWLOntologyManager to load ontology + * @param ontologyIRI the ontology IRI to load + * @return a new ontology object + * @throws IOException on any problem + */ + public OWLOntology loadOntology(OWLOntologyManager manager, IRI ontologyIRI) throws IOException { + return loadOntology(manager, ontologyIRI, null); + } + /** * Given an IRI and a path to a catalog file, load the ontology from the IRI with the catalog. * @@ -490,6 +566,22 @@ public OWLOntology loadOntology(IRI ontologyIRI) throws IOException { * @throws IOException on any problem */ public OWLOntology loadOntology(IRI ontologyIRI, String catalogPath) throws IOException { + OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); + return loadOntology(manager, ontologyIRI, catalogPath); + } + + /** + * Given a manager, an IRI, and a path to a catalog file, load the ontology from the IRI with the + * catalog using the manager. + * + * @param manager OWLOntologyManager to load ontology + * @param ontologyIRI the ontology IRI to load + * @param catalogPath the catalog file to use or null + * @return a new ontology object, with a new OWLManager + * @throws IOException on any problem + */ + public OWLOntology loadOntology(OWLOntologyManager manager, IRI ontologyIRI, String catalogPath) + throws IOException { OWLOntology ontology; // Maybe load a catalog file File catalogFile = null; @@ -500,14 +592,13 @@ public OWLOntology loadOntology(IRI ontologyIRI, String catalogPath) throws IOEx } } try { - OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); // If a catalog file was loaded, set IRI mappers if (catalogFile != null) { manager.setIRIMappers(Sets.newHashSet(new CatalogXmlIRIMapper(catalogFile))); } // Maybe load a zipped ontology if (ontologyIRI.toString().endsWith(".gz")) { - ontology = loadCompressedOntology(new URL(ontologyIRI.toString()), catalogPath); + ontology = loadCompressedOntology(manager, new URL(ontologyIRI.toString()), catalogPath); } else { // Otherwise load ontology as normal ontology = loadOntology(manager, new IRIDocumentSource(ontologyIRI)); @@ -1659,29 +1750,34 @@ private static Set getUndeclaredPredicates( } /** - * Given a gzipped ontology file and a catalog path, load the ontology from a zip input stream. + * Given an ontology manager, a gzipped ontology file, and a catalog path, load the ontology from + * a zip input stream using the manager. * + * @param manager OWLOntologyManager to load ontology * @param gzipFile compressed File to load ontology from * @param catalogPath the path to the catalog file or null - * @return a new ontology object with a new OWLManager + * @return a new ontology object * @throws IOException on any problem */ - private OWLOntology loadCompressedOntology(File gzipFile, String catalogPath) throws IOException { + private OWLOntology loadCompressedOntology( + OWLOntologyManager manager, File gzipFile, String catalogPath) throws IOException { FileInputStream fis = new FileInputStream(gzipFile); GZIPInputStream gis = new GZIPInputStream(fis); - return loadOntology(gis, catalogPath); + return loadOntology(manager, gis, catalogPath); } /** - * Given the URL to a gzipped ontology and a catalog path, load the ontology from a zip input - * stream. + * Given an ontology manager, a URL to a gzipped ontology, and a catalog path, load the ontology + * from a zip input stream using the manager. * + * @param manager OWLOntologyManager to load ontology * @param url URL to load from * @param catalogPath the path to the catalog file or null - * @return a new ontology object with a new OWLManager + * @return a new ontology object * @throws IOException on any problem */ - private OWLOntology loadCompressedOntology(URL url, String catalogPath) throws IOException { + private OWLOntology loadCompressedOntology( + OWLOntologyManager manager, URL url, String catalogPath) throws IOException { // Check for redirects url = followRedirects(url); @@ -1693,7 +1789,7 @@ private OWLOntology loadCompressedOntology(URL url, String catalogPath) throws I throw new IOException(String.format(invalidOntologyIRIError, url)); } GZIPInputStream gis = new GZIPInputStream(is); - return loadOntology(gis, catalogPath); + return loadOntology(manager, gis, catalogPath); } /** From d055d73d31024374ac06a6b5499b68f811ba6c1c Mon Sep 17 00:00:00 2001 From: Becky Jackson Date: Fri, 30 Sep 2022 10:47:10 -0700 Subject: [PATCH 2/5] Add tests --- docs/reason.md | 12 ++--- docs/template.md | 6 +-- .../obolibrary/robot/CommandLineHelper.java | 46 ++----------------- .../java/org/obolibrary/robot/IOHelper.java | 38 +++++++++++++++ .../org/obolibrary/robot/IOHelperTest.java | 36 +++++++++++++++ robot-core/src/test/resources/simple.ttl | 26 +++++++++++ 6 files changed, 114 insertions(+), 50 deletions(-) create mode 100644 robot-core/src/test/resources/simple.ttl diff --git a/docs/reason.md b/docs/reason.md index 9db0bcef3..8232438ac 100644 --- a/docs/reason.md +++ b/docs/reason.md @@ -65,9 +65,9 @@ If the input module contains at least one import, axioms in the debug module wil ## Equivalent Class Axioms -By default, ROBOT ignores one-to-one equivalent classes (e.g. `A EquivalentTo B`). But, in many cases, inferring equivalence between two classes is usually a sign that something has gone wrong. +By default, ROBOT ignores one-to-one equivalent classes (e.g. `A EquivalentTo B`). But, in many cases, inferring equivalence between two classes is usually a sign that something has gone wrong. -Sometimes we want to avoid equivalence between named classes at all (in the case of OBO, where we strive for orthogonality). This can be done through `--equivalent-classes-allowed ` (shorthand `-e`). +Sometimes we want to avoid equivalence between named classes at all (in the case of OBO, where we strive for orthogonality). This can be done through `--equivalent-classes-allowed ` (shorthand `-e`). The `` options are: @@ -77,8 +77,8 @@ The `` options are: ## Excluding tautologies -A **tautology** is an axiom that would be true in any ontology, i.e., it's just a given due to the semantics of OWL. For example, every class is a subclass -of `owl:Thing`; it is not generally useful for an ontology to explicitly state this. Some reasoners may however include these kinds of statements as part +A **tautology** is an axiom that would be true in any ontology, i.e., it's just a given due to the semantics of OWL. For example, every class is a subclass +of `owl:Thing`; it is not generally useful for an ontology to explicitly state this. Some reasoners may however include these kinds of statements as part of their output. The ROBOT `reason` command provides an option for filtering out tautologies generated by the reasoning process: `--exclude-tautologies `. The options for `` are: @@ -86,7 +86,7 @@ The options for `` are: * `false` (default): allow any generated tautologies in the output. * `all` (recommended): use the HermiT reasoner to exclude any inferred axioms that would be entailed by an empty ontology. * `structural` (fast): exclude axioms matching a hard-coded set of tautological patterns (e.g., `X SubClassOf owl:Thing`, `owl:Nothing SubClassOf X`, `X SubClassOf X`). Much faster than `all`. - + ## Generated Axioms By default, the `reason` operation will only assert inferred subclass axioms. This can be configured with the `--axiom-generators` option. OWLAPI provides the following inferred axiom generators: @@ -124,7 +124,7 @@ to get meaningful results: robot reason --input ro-base.owl --reasoner hermit --axiom-generators "ObjectPropertyRange ObjectPropertyDomain" - --output ro-base-reasoned.owl + --output results/ro-base-reasoned.owl If you are only passing one axiom generator, it does not need to be surrounded by double quotes. diff --git a/docs/template.md b/docs/template.md index 6862894f0..0d0ae8094 100644 --- a/docs/template.md +++ b/docs/template.md @@ -151,7 +151,7 @@ If the `TYPE` is a defined class, `owl:Individual`, or `owl:NamedIndividual`, an #### Example of Individual Template Strings -| Label | Entity Type | Individual Role | Property Assertions | Different Individuals | +| Label | Entity Type | Individual Role | Property Assertions | Different Individuals | | ------------ | ----------- | -------------------- | ------------------- | --------------------- | | LABEL | TYPE | TI 'has role' some % | I part_of | DI % | | Individual 1 | Class 1 | Role Class 1 | Individual 2 | | @@ -188,7 +188,7 @@ If the command includes `--ancestors`, the result ontology will include the ance Create an output ontology that includes the input ontology and the terms defined in the template: robot template --merge-before --input edit.owl \ - --template part_of_template.csv --output part_of_uberon.owl + --template part_of_template.csv --output results/part_of_uberon.owl Create two outputs -- the templated terms ([`uberon_template.owl`](/examples/uberon_template.owl)) and the input ontology merged with the output ontology with an annotation ([`uberon_v2.owl`](/examples/uberon_v2)): @@ -311,7 +311,7 @@ AL rdfs:label@en The provided value cannot be parsed and may not be in proper Manchester syntax. See [Manchester Syntax](http://www.w3.org/2007/OWL/wiki/ManchesterSyntax) for more details. If you are using labels, make sure the labels are defined in the `--input` ontology or using the `LABEL` column. Also ensure that all properties use a label instead of a CURIE or IRI. -When using a restriction (`some`, `only`, `min`, `max`, `exactly`, or `value`) the term that preceeds the restriction must be a property. +When using a restriction (`some`, `only`, `min`, `max`, `exactly`, or `value`) the term that preceeds the restriction must be a property. Terms joined using `and` or `or` must be of the same entity type, e.g., you cannot join an object property and a class in an expression. diff --git a/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java b/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java index c16d03f71..a7b9e9e08 100644 --- a/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java +++ b/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java @@ -3,7 +3,6 @@ import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import com.github.jsonldjava.core.Context; -import com.google.common.collect.Sets; import java.io.*; import java.net.URI; import java.net.URISyntaxException; @@ -23,19 +22,9 @@ import org.geneontology.whelk.owlapi.WhelkOWLReasonerFactory; import org.semanticweb.elk.owlapi.ElkReasonerFactory; import org.semanticweb.owlapi.apibinding.OWLManager; -import org.semanticweb.owlapi.functional.parser.OWLFunctionalSyntaxOWLParserFactory; import org.semanticweb.owlapi.io.OWLParserFactory; -import org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntaxOntologyParserFactory; import org.semanticweb.owlapi.model.*; -import org.semanticweb.owlapi.oboformat.OBOFormatOWLAPIParserFactory; -import org.semanticweb.owlapi.owlxml.parser.OWLXMLParserFactory; -import org.semanticweb.owlapi.rdf.rdfxml.parser.RDFXMLParserFactory; -import org.semanticweb.owlapi.rdf.turtle.parser.TurtleOntologyParserFactory; import org.semanticweb.owlapi.reasoner.OWLReasonerFactory; -import org.semanticweb.owlapi.rio.RioJsonLDParserFactory; -import org.semanticweb.owlapi.rio.RioJsonParserFactory; -import org.semanticweb.owlapi.rio.RioRDFXMLParserFactory; -import org.semanticweb.owlapi.rio.RioTurtleParserFactory; import org.slf4j.LoggerFactory; import uk.ac.manchester.cs.jfact.JFactFactory; @@ -81,6 +70,7 @@ public class CommandLineHelper { private static final String multipleInputsError = NS + "MULTIPLE INPUTS ERROR only one --input is allowed"; + /** Error message when --input-format is invalid. */ private static final String unknownInputFormatError = NS + "UNKNOWN INPUT FORMAT ERROR --input-format must be one of: owl, ofn, owx, omn, obo, ttl, or json"; @@ -498,7 +488,10 @@ public static OWLOntology getInputOntology( OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); String inputFormat = getOptionalValue(line, "input-format"); if (inputFormat != null) { - Set parsers = getParsersByFormat(inputFormat); + Set parsers = IOHelper.getParsersByFormat(inputFormat); + if (parsers == null) { + throw new IllegalArgumentException(unknownInputFormatError); + } manager.setOntologyParsers(parsers); } @@ -1086,35 +1079,6 @@ private static File[] getFilesByPattern(String pattern) throws IllegalArgumentEx return files; } - /** - * Get a set of parsers for a given ontology format. - * - * @param format ontology file format as string - * @return set of OWLParserFactories - * @throws IllegalArgumentException on bad format - */ - private static Set getParsersByFormat(String format) - throws IllegalArgumentException { - switch (format) { - case "omn": - return Sets.newHashSet(new ManchesterOWLSyntaxOntologyParserFactory()); - case "obo": - return Sets.newHashSet(new OBOFormatOWLAPIParserFactory()); - case "ofn": - return Sets.newHashSet(new OWLFunctionalSyntaxOWLParserFactory()); - case "owx": - return Sets.newHashSet(new OWLXMLParserFactory()); - case "owl": - return Sets.newHashSet(new RDFXMLParserFactory(), new RioRDFXMLParserFactory()); - case "ttl": - return Sets.newHashSet(new RioTurtleParserFactory(), new TurtleOntologyParserFactory()); - case "json": - return Sets.newHashSet(new RioJsonParserFactory(), new RioJsonLDParserFactory()); - default: - throw new IllegalArgumentException(unknownInputFormatError); - } - } - /** * Given an IOHelper and a command line, check input options and return a list of loaded input * ontologies. diff --git a/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java b/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java index 6c5acd696..56777ed62 100644 --- a/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java +++ b/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java @@ -39,11 +39,21 @@ import org.obolibrary.oboformat.writer.OBOFormatWriter; import org.semanticweb.owlapi.apibinding.OWLManager; import org.semanticweb.owlapi.formats.*; +import org.semanticweb.owlapi.functional.parser.OWLFunctionalSyntaxOWLParserFactory; import org.semanticweb.owlapi.io.*; import org.semanticweb.owlapi.io.XMLUtils; +import org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntaxOntologyParserFactory; import org.semanticweb.owlapi.model.*; +import org.semanticweb.owlapi.oboformat.OBOFormatOWLAPIParserFactory; +import org.semanticweb.owlapi.owlxml.parser.OWLXMLParserFactory; +import org.semanticweb.owlapi.rdf.rdfxml.parser.RDFXMLParserFactory; import org.semanticweb.owlapi.rdf.rdfxml.renderer.IllegalElementNameException; import org.semanticweb.owlapi.rdf.rdfxml.renderer.XMLWriterPreferences; +import org.semanticweb.owlapi.rdf.turtle.parser.TurtleOntologyParserFactory; +import org.semanticweb.owlapi.rio.RioJsonLDParserFactory; +import org.semanticweb.owlapi.rio.RioJsonParserFactory; +import org.semanticweb.owlapi.rio.RioRDFXMLParserFactory; +import org.semanticweb.owlapi.rio.RioTurtleParserFactory; import org.semanticweb.owlapi.util.DefaultPrefixManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -273,6 +283,34 @@ protected static boolean cleanTDB(String tdbDir) { return success; } + /** + * Get a set of parsers for a given ontology format. + * + * @param format ontology file format as string + * @return set of OWLParserFactories + * @throws IllegalArgumentException on bad format + */ + public static Set getParsersByFormat(String format) { + switch (format) { + case "omn": + return Sets.newHashSet(new ManchesterOWLSyntaxOntologyParserFactory()); + case "obo": + return Sets.newHashSet(new OBOFormatOWLAPIParserFactory()); + case "ofn": + return Sets.newHashSet(new OWLFunctionalSyntaxOWLParserFactory()); + case "owx": + return Sets.newHashSet(new OWLXMLParserFactory()); + case "owl": + return Sets.newHashSet(new RDFXMLParserFactory(), new RioRDFXMLParserFactory()); + case "ttl": + return Sets.newHashSet(new RioTurtleParserFactory(), new TurtleOntologyParserFactory()); + case "json": + return Sets.newHashSet(new RioJsonParserFactory(), new RioJsonLDParserFactory()); + default: + return null; + } + } + /** * Try to guess the location of the catalog.xml file. Looks in the directory of the given ontology * file for a catalog file. diff --git a/robot-core/src/test/java/org/obolibrary/robot/IOHelperTest.java b/robot-core/src/test/java/org/obolibrary/robot/IOHelperTest.java index 1550b0b48..e1819a791 100644 --- a/robot-core/src/test/java/org/obolibrary/robot/IOHelperTest.java +++ b/robot-core/src/test/java/org/obolibrary/robot/IOHelperTest.java @@ -15,10 +15,12 @@ import java.util.Set; import org.geneontology.obographs.owlapi.OboGraphJsonDocumentFormat; import org.junit.Test; +import org.semanticweb.owlapi.apibinding.OWLManager; import org.semanticweb.owlapi.formats.RDFXMLDocumentFormat; import org.semanticweb.owlapi.model.IRI; import org.semanticweb.owlapi.model.OWLLiteral; import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyManager; import org.semanticweb.owlapi.util.DefaultPrefixManager; /** Tests for IOHelper. */ @@ -149,6 +151,40 @@ public void testContextHandling() throws IOException { assertEquals("Check JSON prefixes", expected, ioh.getPrefixes()); } + /** + * Test loading an ontology in RDF/XML format with a manager. + * + * @throws IOException on any problem + */ + @Test + public void testLoadOWLOntologyWithManager() throws IOException { + IOHelper ioHelper = new IOHelper(); + OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); + manager.setOntologyParsers(IOHelper.getParsersByFormat("owl")); + + InputStream inputOntology = this.getClass().getResourceAsStream("/simple.owl"); + OWLOntology o = ioHelper.loadOntology(manager, inputOntology, null); + // Loading will throw error on parse issue, but just make sure loaded ontology has contents + assert !o.getSignature().isEmpty(); + } + + /** + * Test loading an ontology in TTL format with a manager. + * + * @throws IOException on any problem + */ + @Test + public void testLoadTTLOntologyWithManager() throws IOException { + IOHelper ioHelper = new IOHelper(); + OWLOntologyManager manager = OWLManager.createOWLOntologyManager(); + manager.setOntologyParsers(IOHelper.getParsersByFormat("ttl")); + + InputStream inputOntology = this.getClass().getResourceAsStream("/simple.ttl"); + OWLOntology o = ioHelper.loadOntology(manager, inputOntology, null); + // Loading will throw error on parse issue, but just make sure loaded ontology has contents + assert !o.getSignature().isEmpty(); + } + /** * Test prefix maps. * diff --git a/robot-core/src/test/resources/simple.ttl b/robot-core/src/test/resources/simple.ttl new file mode 100644 index 000000000..e1ad65b57 --- /dev/null +++ b/robot-core/src/test/resources/simple.ttl @@ -0,0 +1,26 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@base . + + rdf:type owl:Ontology . + +################################################################# +# Classes +################################################################# + +### https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test1 +:test1 rdf:type owl:Class ; + rdfs:label "Test 1" , + "test one" . + + +### https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test2 +:test2 rdf:type owl:Class ; + rdfs:subClassOf :test1 . + + +### Generated by the OWL API (version 4.5.6) https://github.com/owlcs/owlapi From 05de1614bdba6f94530f26a0255d84b2f15cf75f Mon Sep 17 00:00:00 2001 From: Becky Jackson Date: Fri, 30 Sep 2022 10:58:05 -0700 Subject: [PATCH 3/5] Fix reason tests --- docs/examples/ro-base-reasoned.owl | 11 +---------- docs/examples/ro-base.owl | 9 --------- docs/reason.md | 16 ++++++++-------- 3 files changed, 9 insertions(+), 27 deletions(-) diff --git a/docs/examples/ro-base-reasoned.owl b/docs/examples/ro-base-reasoned.owl index 9a1d7f21b..efae6e8ed 100644 --- a/docs/examples/ro-base-reasoned.owl +++ b/docs/examples/ro-base-reasoned.owl @@ -3687,15 +3687,6 @@ For example, protein A (transcription factor) indirectly increases by expression - - - - - - - - - + diff --git a/docs/examples/ro-base.owl b/docs/examples/ro-base.owl index 4a077a86a..07e4234f2 100644 --- a/docs/examples/ro-base.owl +++ b/docs/examples/ro-base.owl @@ -3553,15 +3553,6 @@ For example, protein A (transcription factor) indirectly increases by expression - - - - - - - - -