Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- Add `--input-format` global option [#1038]

### Fixed
- Inherit OWLDocumentFormat when performing SPARQL update [#1267]
- Updated obographs to [version 0.3.2](https://github.com/geneontology/obographs/releases/tag/v0.3.2)
Expand Down
16 changes: 16 additions & 0 deletions docs/global.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ For example, you may want to [`merge`](/merge) a set of edited import ontologies

If a catalog file is specified and cannot be located, the ontology will be loaded without a catalog file. Similarly, if you do not provide a `--catalog` and the `catalog-v001.xml` file does not exist in your working directory, the ontology will be loaded without a catalog file. Finally, if the catalog specifies an import file that does not exist, the command will fail.

## Input format

When loading an ontology, the OWLAPI will normally attempt to parse it using all the available parsers, until it finds one that can successfully load the ontology. If the format of the ontology is known, it can be explicitly specified to ROBOT using the `--input-format` option, so that only the appropriate parsers for that format will be used.

The `--input-format` option accepts the following values:

| Option value | Ontology format |
| ------------ | --------------------------------------------------------------------------------- |
| owl | [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/) |
| obo | [OBO Flat File](https://owlcollab.github.io/oboformat/doc/GO.format.obo-1_4.html) |
| owx | [OWL/XML](https://www.w3.org/TR/owl-xmlsyntax/) |
| ofn | [OWL Functional](https://www.w3.org/TR/owl2-syntax/) |
| omn | [OWL Manchester](https://www.w3.org/TR/owl2-manchester-syntax/) |
| ttl | [Turtle](https://www.w3.org/TR/turtle/) |
| json | [OBO Graphs JSON](https://github.com/geneontology/obographs/) |

## Logging

ROBOT logs a variety of messages that are typically hidden from the user. When something goes wrong, a detailed exception message is thrown. If the exception message does not provide enough details, you can run the command again with the `-vvv` (very-very-verbose) flag to see the stack trace.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,24 +470,17 @@ public static OWLOntology getInputOntology(
throws IllegalArgumentException, IOException {
List<String> inputOntologyPaths = getOptionalValues(line, "input");
List<String> inputOntologyIRIs = getOptionalValues(line, "input-iri");
String inputFormat = getOptionalValue(line, "input-format");

int check = inputOntologyPaths.size() + inputOntologyIRIs.size();
if (check > 1) {
throw new IllegalArgumentException(multipleInputsError);
}

if (!inputOntologyPaths.isEmpty()) {
if (catalogPath != null) {
return ioHelper.loadOntology(inputOntologyPaths.get(0), catalogPath);
} else {
return ioHelper.loadOntology(inputOntologyPaths.get(0));
}
return ioHelper.loadOntology(inputOntologyPaths.get(0), catalogPath, inputFormat);
} else if (!inputOntologyIRIs.isEmpty()) {
if (catalogPath != null) {
return ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0)), catalogPath);
} else {
return ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0)));
}
return ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0)), catalogPath, inputFormat);
} else {
// Both input options are empty
throw new IllegalArgumentException(missingInputError);
Expand Down Expand Up @@ -913,6 +906,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");
Expand Down Expand Up @@ -1073,21 +1071,22 @@ private static File[] getFilesByPattern(String pattern) throws IllegalArgumentEx
public static List<OWLOntology> getInputOntologies(IOHelper ioHelper, CommandLine line)
throws IllegalArgumentException, IOException {
List<OWLOntology> inputOntologies = new ArrayList<>();
String inputFormat = getOptionalValue(line, "input-format");
// Check for input files
List<String> inputOntologyPaths = getOptionalValues(line, "input");
for (String inputOntologyPath : inputOntologyPaths) {
inputOntologies.add(ioHelper.loadOntology(inputOntologyPath));
inputOntologies.add(ioHelper.loadOntology(inputOntologyPath, true, inputFormat));
}
// Check for input IRIs
List<String> inputOntologyIRIs = getOptionalValues(line, "input-iri");
for (String inputOntologyIRI : inputOntologyIRIs) {
inputOntologies.add(ioHelper.loadOntology(IRI.create(inputOntologyIRI)));
inputOntologies.add(ioHelper.loadOntology(IRI.create(inputOntologyIRI), null, inputFormat));
}
// Check for input patterns (wildcard)
String pattern = getOptionalValue(line, "inputs");
if (pattern != null) {
for (File inputOntologyFile : getFilesByPattern(pattern)) {
inputOntologies.add(ioHelper.loadOntology(inputOntologyFile));
inputOntologies.add(ioHelper.loadOntology(inputOntologyFile, true, inputFormat));
}
}
return inputOntologies;
Expand All @@ -1106,22 +1105,24 @@ public static List<OWLOntology> getInputOntologies(IOHelper ioHelper, CommandLin
public static List<OWLOntology> getInputOntologies(
IOHelper ioHelper, CommandLine line, String catalogPath) throws IOException {
List<OWLOntology> inputOntologies = new ArrayList<>();
String inputFormat = getOptionalValue(line, "input-format");
// Check for input files
List<String> inputOntologyPaths = getOptionalValues(line, "input");
for (String inputOntologyPath : inputOntologyPaths) {
inputOntologies.add(ioHelper.loadOntology(inputOntologyPath, catalogPath));
inputOntologies.add(ioHelper.loadOntology(inputOntologyPath, catalogPath, inputFormat));
}
// Check for input IRIs
List<String> inputOntologyIRIs = getOptionalValues(line, "input-iri");
for (String inputOntologyIRI : inputOntologyIRIs) {
inputOntologies.add(ioHelper.loadOntology(IRI.create(inputOntologyIRI), catalogPath));
inputOntologies.add(
ioHelper.loadOntology(IRI.create(inputOntologyIRI), catalogPath, inputFormat));
}
// Check for input patterns (wildcard)
String pattern = getOptionalValue(line, "inputs");
if (pattern != null) {
File catalogFile = new File(catalogPath);
for (File inputOntologyFile : getFilesByPattern(pattern)) {
inputOntologies.add(ioHelper.loadOntology(inputOntologyFile, catalogFile));
inputOntologies.add(ioHelper.loadOntology(inputOntologyFile, catalogFile, inputFormat));
}
}
return inputOntologies;
Expand Down
137 changes: 124 additions & 13 deletions robot-core/src/main/java/org/obolibrary/robot/IOHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,27 @@ public OWLOntology loadOntology(String ontologyPath) throws IOException {
* @throws IOException on any problem
*/
public OWLOntology loadOntology(String ontologyPath, boolean useCatalog) throws IOException {
return loadOntology(ontologyPath, useCatalog, null);
}

/**
* Load an ontology from a String path, optionally using a catalog file if available and with an
* explicit input format.
*
* @param ontologyPath the path to the ontology file
* @param useCatalog if true, a catalog file will be used if one is found
* @param inputFormat the expected format of the ontology or null
* @return a new ontology object, with a new OWLManager
* @throws IOException on any problem
*/
public OWLOntology loadOntology(String ontologyPath, boolean useCatalog, String inputFormat)
throws IOException {
File ontologyFile = new File(ontologyPath);
File catalogFile = null;
if (useCatalog) {
catalogFile = guessCatalogFile(ontologyFile);
}
return loadOntology(ontologyFile, catalogFile);
return loadOntology(ontologyFile, catalogFile, inputFormat);
}

/**
Expand All @@ -339,6 +354,22 @@ public OWLOntology loadOntology(String ontologyPath, String catalogPath) throws
return loadOntology(ontologyFile, catalogFile);
}

/**
* Load an ontology from a String path, with optional catalog file and explicit document format.
*
* @param ontologyPath the path to the ontology file
* @param catalogPath the path to the catalog file or null
* @param inputFormat the expected input format of the ontology or null
* @return a new ontology object, with a new OWLManager
* @throws IOException on any problem
*/
public OWLOntology loadOntology(String ontologyPath, String catalogPath, String inputFormat)
throws IOException {
File ontologyFile = new File(ontologyPath);
File catalogFile = catalogPath != null ? new File(catalogPath) : null;
return loadOntology(ontologyFile, catalogFile, inputFormat);
}

/**
* Load an ontology from a File, using a catalog file if available.
*
Expand All @@ -364,11 +395,26 @@ public OWLOntology loadOntology(File ontologyFile) throws IOException {
* @throws IOException on any problem
*/
public OWLOntology loadOntology(File ontologyFile, boolean useCatalog) throws IOException {
return loadOntology(ontologyFile, useCatalog, null);
}

/**
* Load an ontology from a File, with option to use a catalog file and to expect an explicit
* format.
*
* @param ontologyFile the ontology file to load
* @param useCatalog when true, a catalog file will be used if one is found
* @param inputFormat the expected format of the ontology or null
* @return a new ontology object, with a new OWLManager
* @throws IOException on any problem
*/
public OWLOntology loadOntology(File ontologyFile, boolean useCatalog, String inputFormat)
throws IOException {
File catalogFile = null;
if (useCatalog) {
catalogFile = guessCatalogFile(ontologyFile);
}
return loadOntology(ontologyFile, catalogFile);
return loadOntology(ontologyFile, catalogFile, inputFormat);
}

/**
Expand All @@ -380,6 +426,20 @@ public OWLOntology loadOntology(File ontologyFile, boolean useCatalog) throws IO
* @throws IOException on any problem
*/
public OWLOntology loadOntology(File ontologyFile, File catalogFile) throws IOException {
return loadOntology(ontologyFile, catalogFile, null);
}

/**
* Load an ontology from a File, with optional catalog File and input format.
*
* @param ontologyFile the ontology file to load
* @param catalogFile the catalog file to use
* @param inputFormat the expected format of the ontology or null
* @return a new ontology object, with a new OWLManager
* @throws IOException on any problem
*/
public OWLOntology loadOntology(File ontologyFile, File catalogFile, String inputFormat)
throws IOException {
logger.debug("Loading ontology {} with catalog file {}", ontologyFile, catalogFile);
Object jsonObject = null;
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
Expand Down Expand Up @@ -417,14 +477,15 @@ 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(ontologyFile, null, inputFormat);
} else {
return loadCompressedOntology(ontologyFile, catalogFile.getAbsolutePath());
return loadCompressedOntology(ontologyFile, catalogFile.getAbsolutePath(), inputFormat);
}
}

// Otherwise load from file using default method
return loadOntology(manager, new FileDocumentSource(ontologyFile));
OWLDocumentFormat fmt = inputFormat != null ? getFormat(inputFormat) : null;
return loadOntology(manager, new FileDocumentSource(ontologyFile, fmt));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to next reviewer: I expect that FileDocumentSource(,) handles the case where fmt is null by trying to "guess" the format as usual. This is the most important assumption in this PR as it basically ensures that the old functionality prevails when no --input-format is supplied.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Calling the FileDocumentSource constructor with a null argument for the document format is basically the same thing as calling the 1-argument constructor. In fact the 1-argument constructor does nothing else but calling another constructor with a null argument for the format.

} catch (JsonLdError | OWLOntologyCreationException e) {
throw new IOException(String.format(invalidOntologyFileError, ontologyFile.getName()), e);
}
Expand All @@ -442,7 +503,7 @@ public OWLOntology loadOntology(InputStream ontologyStream) throws IOException {
}

/**
* Load an ontology from an InputStream with a catalog file.
* Load an ontology from an InputStream with an optional catalog file.
*
* @param ontologyStream the ontology stream to load
* @param catalogPath the catalog file to use or null
Expand All @@ -451,6 +512,20 @@ public OWLOntology loadOntology(InputStream ontologyStream) throws IOException {
*/
public OWLOntology loadOntology(InputStream ontologyStream, String catalogPath)
throws IOException {
return loadOntology(ontologyStream, catalogPath, null);
}

/**
* Load an ontology from an InputStream with an optional catalog file and input format.
*
* @param ontologyStream the ontology stream to load
* @param catalogPath the catalog file to use or null
* @param inputFormat the expected format of the ontology or null
* @return a new ontology object, with a new OWLManager
* @throws IOException on any problem
*/
public OWLOntology loadOntology(
InputStream ontologyStream, String catalogPath, String inputFormat) throws IOException {
OWLOntology ontology;
// Maybe load a catalog file
File catalogFile = null;
Expand All @@ -465,7 +540,18 @@ public OWLOntology loadOntology(InputStream ontologyStream, String catalogPath)
if (catalogFile != null) {
manager.setIRIMappers(Sets.newHashSet(new CatalogXmlIRIMapper(catalogFile)));
}
ontology = loadOntology(manager, new StreamDocumentSource(ontologyStream));
OWLOntologyDocumentSource source = null;
if (inputFormat != null) {
source =
new StreamDocumentSource(
ontologyStream,
StreamDocumentSource.getNextDocumentIRI("inputstream:ontology"),
getFormat(inputFormat),
null);
} else {
source = new StreamDocumentSource(ontologyStream);
}
ontology = loadOntology(manager, source);
} catch (OWLOntologyCreationException e) {
throw new IOException(invalidOntologyStreamError, e);
}
Expand All @@ -492,6 +578,20 @@ public OWLOntology loadOntology(IRI ontologyIRI) throws IOException {
* @throws IOException on any problem
*/
public OWLOntology loadOntology(IRI ontologyIRI, String catalogPath) throws IOException {
return loadOntology(ontologyIRI, catalogPath, null);
}

/**
* Load an ontology from an IRI with an optional catalog file and input format.
*
* @param ontologyIRI the ontology IRI to load
* @param catalogPath the catalog file to use or null
* @param inputFormat the expected format of the ontology or null
* @return a new ontology object, with a new OWLManager
* @throws IOException on any problem
*/
public OWLOntology loadOntology(IRI ontologyIRI, String catalogPath, String inputFormat)
throws IOException {
OWLOntology ontology;
// Maybe load a catalog file
File catalogFile = null;
Expand All @@ -509,11 +609,18 @@ public OWLOntology loadOntology(IRI ontologyIRI, String catalogPath) throws IOEx
}
// Maybe load a zipped ontology
if (ontologyIRI.toString().endsWith(".gz")) {
ontology = loadCompressedOntology(new URL(ontologyIRI.toString()), catalogPath);
ontology =
loadCompressedOntology(new URL(ontologyIRI.toString()), catalogPath, inputFormat);
} else {
// Otherwise load ontology as normal
IRI documentIRI = getDocumentIRIFromMappers(manager, ontologyIRI);
ontology = loadOntology(manager, new IRIDocumentSource(documentIRI));
OWLOntologyDocumentSource source = null;
if (inputFormat != null) {
source = new IRIDocumentSource(documentIRI, getFormat(inputFormat), null);
} else {
source = new IRIDocumentSource(documentIRI);
}
ontology = loadOntology(manager, source);
}
} catch (OWLOntologyCreationException e) {
throw new IOException(e);
Expand Down Expand Up @@ -1724,13 +1831,15 @@ private static Set<IRI> getUndeclaredPredicates(
*
* @param gzipFile compressed File to load ontology from
* @param catalogPath the path to the catalog file or null
* @param inputFormat the expected format of the ontology or null
* @return a new ontology object with a new OWLManager
* @throws IOException on any problem
*/
private OWLOntology loadCompressedOntology(File gzipFile, String catalogPath) throws IOException {
private OWLOntology loadCompressedOntology(File gzipFile, String catalogPath, String inputFormat)
throws IOException {
FileInputStream fis = new FileInputStream(gzipFile);
GZIPInputStream gis = new GZIPInputStream(fis);
return loadOntology(gis, catalogPath);
return loadOntology(gis, catalogPath, inputFormat);
}

/**
Expand All @@ -1739,10 +1848,12 @@ private OWLOntology loadCompressedOntology(File gzipFile, String catalogPath) th
*
* @param url URL to load from
* @param catalogPath the path to the catalog file or null
* @param inputFormat the expected format of the ontology or null
* @return a new ontology object with a new OWLManager
* @throws IOException on any problem
*/
private OWLOntology loadCompressedOntology(URL url, String catalogPath) throws IOException {
private OWLOntology loadCompressedOntology(URL url, String catalogPath, String inputFormat)
throws IOException {
// Check for redirects
url = followRedirects(url);

Expand All @@ -1754,7 +1865,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(gis, catalogPath, inputFormat);
}

/**
Expand Down
Loading