Repository: ontodev/robot
Pull request #315 (2018-07-23 15:20:17)

More consistent query
Add `execVerify` and `runVerify` methods, simplify `VerifyCommand`.


Patch:
diff --git a/docs/Makefile b/docs/Makefile
deleted file mode 100644
index 0f8b2ee4..00000000
--- a/docs/Makefile
+++ /dev/null
@@ -1,50 +0,0 @@
-## ROBOT Documentation Makefile
-#
-# This file helps us keep our documentation up-to-date
-# by generating Markdown files form various source files.
-# The goal is DRY: Don't Repeat Yourself!
-
-
-### Jekyll
-#
-# You can test the documentation locall using Jekyll and various GitHub Pages stuff:
-# https://help.github.com/articles/setting-up-your-github-pages-site-locally-with-jekyll/
-
-
-### Configuration
-
-# Collect the list of query files for report.
-REPORT_QUERIES := $(wildcard ../robot-core/src/main/resources/queries/*.rq)
-REPORT_DOCS := $(foreach x, $(REPORT_QUERIES), report_queries/$(notdir $(basename $(x))).md)
-
-
-### Main Tasks
-
-all: $(REPORT_DOCS) report_queries/index.md
-
-
-### Report Tasks
-
-report_queries:
-	mkdir -p $@
-
-# Convert each SPARQL file to a Markdown file.
-report_queries/%.md: ../robot-core/src/main/resources/queries/%.rq | report_queries
-	awk '/^PREFIX/ && !x {print "```sparql"; x=1} 1' $< \
-	| sed 's/^#//' \
-	| sed 's/^ //' \
-	> $@
-	echo '```' >> $@
-
-# Use the master profile to generate a page of links.
-report_queries/index.md: ../robot-core/src/main/resources/report_profile.txt | report_queries
-	echo '# Report Queries' > $@
-	echo '' >> $@
-	echo 'The table below lists all the queries run by the `report` command,' >> $@
-	echo 'with their default severity levels.' >> $@
-	echo 'See [`report`](../report) for more details.' >> $@
-	echo '' >> $@
-	echo '| Name  | Default Severity  ' >> $@
-	echo '|-------|-------------------' >> $@
-	awk -F'	' '{x=$$2; gsub(/_/," ",$$2); print "| [" $$2 "](" x ")  | " $$1}' $< \
-	>> $@
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
index 832f523a..a944d5f7 100644
--- a/docs/_layouts/default.html
+++ b/docs/_layouts/default.html
@@ -25,7 +25,7 @@
           <a href="/">usage</a><br>
           <a href="/errors">common errors</a><br>
           <a href="/chaining">chaining commands</a><br>
-          <a href="/global">global options</a><br>
+          <a href="/prefixes">prefixes</a><br>
           <a href="/make">makefile</a><br>
           - - - - - - - - - -<br>
           <a href="/annotate">annotate</a><br>
@@ -42,7 +42,6 @@
           <a href="/relax">relax</a><br>
           <!--<a href="/remove/remove">remove</a><br>-->
           <a href="/repair">repair</a><br>
-          <a href="/report">report</a><br>
           <a href="/template">template</a><br>
           <a href="/unmerge">unmerge</a><br>
           <a href="/validate">validate</a><br>
@@ -75,4 +74,4 @@
     </script>
   {% endif %}
   </body>
-</html>
+</html>
\ No newline at end of file
diff --git a/docs/examples/catalog.xml b/docs/examples/catalog.xml
deleted file mode 100644
index 53322769..00000000
--- a/docs/examples/catalog.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<catalog prefer="public" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
-  <!-- added mapping -->
-  <uri name="https://github.com/ontodev/robot/examples/edit.owl" uri="./edit.owl"/>
-</catalog>
\ No newline at end of file
diff --git a/docs/examples/edit2.owl b/docs/examples/edit2.owl
index 7f59cda6..8508b6a3 100644
--- a/docs/examples/edit2.owl
+++ b/docs/examples/edit2.owl
@@ -8,7 +8,7 @@
      xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:oboInOwl="http://www.geneontology.org/formats/oboInOwl#">
-    <owl:Ontology rdf:about="https://github.com/ontodev/robot/examples/edit.owl"/>
+    <owl:Ontology rdf:about="https://github.com/ontodev/robot/examples/edit2.owl"/>
 
     <!-- https://github.com/ontodev/robot/examples/foo.owl#test -->
 
diff --git a/docs/examples/imports.owl b/docs/examples/imports.owl
deleted file mode 100644
index 2b62b330..00000000
--- a/docs/examples/imports.owl
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<rdf:RDF xmlns="http://purl.obolibrary.org/robot/imports.owl#"
-     xml:base="http://purl.obolibrary.org/robot/imports.owl"
-     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:owl="http://www.w3.org/2002/07/owl#"
-     xmlns:oboInOwl="http://www.geneontology.org/formats/oboInOwl#"
-     xmlns:xml="http://www.w3.org/XML/1998/namespace"
-     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
-     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
-     xmlns:obo="http://purl.obolibrary.org/obo/"
-     xmlns:foaf="http://xmlns.com/foaf/0.1/">
-    <owl:Ontology rdf:about="http://purl.obolibrary.org/robot/imports.owl">
-        <owl:imports rdf:resource="https://github.com/ontodev/robot/examples/edit.owl"/>
-    </owl:Ontology>
-</rdf:RDF>
-
-
-
-<!-- Generated by the OWL API (version 4.2.8.20170104-2310) https://github.com/owlcs/owlapi -->
-
diff --git a/docs/examples/merged.owl b/docs/examples/merged.owl
index 565173dc..0fee8695 100644
--- a/docs/examples/merged.owl
+++ b/docs/examples/merged.owl
@@ -9,7 +9,7 @@
      xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
      xmlns:obo="http://purl.obolibrary.org/obo/"
      xmlns:foaf="http://xmlns.com/foaf/0.1/">
-    <owl:Ontology rdf:about="https://github.com/ontodev/robot/examples/merged.owl"/>
+    <owl:Ontology rdf:about="https://github.com/ontodev/robot/examples/edit.owl"/>
     
 
 
diff --git a/docs/global.md b/docs/global.md
deleted file mode 100644
index fc707c55..00000000
--- a/docs/global.md
+++ /dev/null
@@ -1,70 +0,0 @@
-# Global Options
-
-## Prefixes
-
-Terms in OBO and OWL are identified using [IRIs](https://en.wikipedia.org/wiki/Internationalized_resource_identifier) (Internationalized Resource Identifiers), which generalize the familiar addresses for web pages. IRIs have many advantages, but one of their disadvantages is that they can be pretty long. So we have standard ways to abbreviate IRIs in a particular context by specifying **prefixes**. For example, Turtle files start with `@prefix` statements, SPARQL queries start with `PREFIX` statements, and JSON-LD data includes a `@context` with prefixes.
-
-For robot we use the JSON-LD format. See [`obo_context.jsonld`](https://github.com/ontodev/robot/blob/master/robot-core/src/main/resources/obo_context.jsonld) for the JSON-LD context that is used by default. It includes common, general linked-data prefixes, and prefixes for all the OBO library projects.
-
-If you do not want to use the defaults, you can use the `--noprefixes` option. If you want to replace the defaults, use the `--prefixes` option and specify your JSON-LD file. Whatever your choice, you can add more prefixes using the `--prefix` option, as many times as you like. Finally, you can print or save the current prefixes using the `export-prefixes` command. Here are some examples:
-
-    robot --noprefixes --prefix "foo: http://foo#" \
-      export-prefixes --output results/foo.json
-
-    robot --prefixes foo.json -p "bar: http://bar#" -p "baz: http://baz#" \
-      export-prefixes
-
-The various prefix options can be used with any command. When chaining commands, you usually want to specify all the prefix options first, so that they are used "globally" by all commands. But you can also use prefix options for single commands. Here's a silly example with a global prefix "foo" and a local prefix "bar". The first export includes both the global and local prefixes, while the second export includes only the global prefix.
-
-    robot --noprefixes --prefix "foo: http://foo#" \
-      export-prefixes --prefix "bar: http://bar#" \
-      export-prefixes
-
-## XML Catalogs
-
-OWLAPI, Protégé, and ROBOT use XML catalogs to specify where import files are located when loading an ontology. By default, this catalog is called `catalog-v001.xml`. ROBOT assumes that a `catalog-v001.xml` file exists in the working directory and attempts to resolve imports based on that. Because Protègè also predicts that catalog, we recommend sticking to this standard. For more details, see [Importing Ontologies in Protègè and OWL 2](https://protegewiki.stanford.edu/wiki/Importing_Ontologies_in_P41).
-
-That said, occasionally, you may want to use different catalog files for different purposes. This is especially useful for automated releases with [Makefiles](/makefile). ROBOT provides an option to specify the catalog location with `--catalog`. 
-
-For example, you may want to [`merge`](/merge) a set of edited import ontologies to create a module. You may have one set of imports for one module, and another set of imports for another module. You can also chain this command with [`annotate`](/annotate) to specify the output ontology's IRI.
-
-    robot merge --catalog catalog.xml\
-     --input imports.owl \
-    annotate --ontology-iri https://github.com/ontodev/robot/examples/merged.owl\
-     --output results/merged.owl
-
-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.
-
-## Verbose
-
-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.
-
-There are three levels of verbosity:
-1. `-v`, `--verbose`: WARN-level logging
-2. `-vv`, `--very-verbose`: INFO-level logging
-3. `-vvv`, `--very-very-verbose`: DEBUG-level logging, including stack traces
-
-## XML Entities
-
-If the `--xml-entities` option is included, entities will be used for namespace abbreviations. For example, in a typical RDF/XML file (OBI, for example), the base prefix may be defined as:
-```
-xml:base="http://purl.obolibrary.org/obo/obi.owl"
-```
-
-If namespace abbreviations are used, the RDF/XML file will include a header with prefix abbreviations (prior to the `rdf:RDF` tag). The `obo` prefix, for example, is:
-```
-<!ENTITY obo "http://purl.obolibrary.org/obo/" >
-```
-
-The `obo` abbreviation would be substituted for any instance of `http://purl.obolibrary.org/obo/` in the rest of the RDF/XML file, as demonstrated by the base prefix:
-```
-xml:base="&obo;obi.owl"
-```
-
----
-
-## Error Messages
-
-### JSON-LD Error
-
-ROBOT encountered a problem while writing the given prefixes to JSON-LD.
diff --git a/docs/merge.md b/docs/merge.md
index 8ef7c8df..54c3e185 100644
--- a/docs/merge.md
+++ b/docs/merge.md
@@ -1,10 +1,8 @@
 # Merge
 
-OWL ontologies are often divided into several `.owl` files, with `owl:imports` statements to bring them together. Sometimes you want to take all those imports and merge them into a single ontology with a single `.owl` file. This can be chained with [`annotate`](/annotate) to specify an IRI for the output ontology.
+OWL ontologies are often divided into several `.owl` files, with `owl:imports` statements to bring them together. Sometimes you want to take all those imports and merge them into a single ontology with a single `.owl` file.
 
-    robot merge --input edit.owl \
-    annotate --ontology-iri https://github.com/ontodev/robot/examples/merged.owl\
-     --output results/merged.owl
+    robot merge --input edit.owl --output results/merged.owl
 
 You don't need `owl:import` statements: you can merge any number of ontologies by using multiple `--input` arguments. All the ontologies and their imports are merged into the first ontology.
 
diff --git a/docs/prefixes.md b/docs/prefixes.md
new file mode 100644
index 00000000..05ac7bb0
--- /dev/null
+++ b/docs/prefixes.md
@@ -0,0 +1,27 @@
+# Prefixes
+
+Terms in OBO and OWL are identified using <a href="https://en.wikipedia.org/wiki/Internationalized_resource_identifier" target="_blank">IRIs</a> (Internationalized Resource Identifiers), which generalize the familiar addresses for web pages. IRIs have many advantages, but one of their disadvantages is that they can be pretty long. So we have standard ways to abbreviate IRIs in a particular context by specifying **prefixes**. For example, Turtle files start with `@prefix` statements, SPARQL queries start with `PREFIX` statements, and JSON-LD data includes a `@context` with prefixes.
+
+For robot we use the JSON-LD format. See <a href="https://github.com/ontodev/robot/blob/master/robot-core/src/main/resources/obo_context.jsonld" target="_blank">`obo_context.jsonld`</a> for the JSON-LD context that is used by default. It includes common, general linked-data prefixes, and prefixes for all the OBO library projects.
+
+If you do not want to use the defaults, you can use the `--noprefixes` option. If you want to replace the defaults, use the `--prefixes` option and specify your JSON-LD file. Whatever your choice, you can add more prefixes using the `--prefix` option, as many times as you like. Finally, you can print or save the current prefixes using the `export-prefixes` command. Here are some examples:
+
+    robot --noprefixes --prefix "foo: http://foo#" \
+      export-prefixes --output results/foo.json
+
+    robot --prefixes foo.json -p "bar: http://bar#" -p "baz: http://baz#" \
+      export-prefixes
+
+The various prefix options can be used with any command. When chaining commands, you usually want to specify all the prefix options first, so that they are used "globally" by all commands. But you can also use prefix options for single commands. Here's a silly example with a global prefix "foo" and a local prefix "bar". The first export includes both the global and local prefixes, while the second export includes only the global prefix.
+
+    robot --noprefixes --prefix "foo: http://foo#" \
+      export-prefixes --prefix "bar: http://bar#" \
+      export-prefixes
+
+---
+
+## Error Messages
+
+### JDON-LD Error
+
+ROBOT encounterd a problem while writing the given prefixes to JSON-LD.
diff --git a/docs/report.md b/docs/report.md
deleted file mode 100644
index 800ce12d..00000000
--- a/docs/report.md
+++ /dev/null
@@ -1,80 +0,0 @@
-# Report
-
-The `report` command runs a series of quality control SPARQL queries over the input ontology and generates a TSV or YAML report file based on the results. Each query has a logging level to define the severity of the issue: ERROR, WARN, or INFO.
-* `ERROR`: Must be fixed before releasing the ontology. These issues will cause problems for users, such as classes with multiple labels.
-* `WARN`: Should be fixed as soon as possible. These will not cause problems for *all* users, but may not be what they expect. For example, a class that is inferred to be equivalent to another named class.
-* `INFO`: Should be fixed if possible. These are for consistency and cleanliness, such as definitions that do not start with an uppercase character.
-<!-- DO NOT TEST -->
-```
-robot report --input edit.owl --output report.tsv
-```
-
-By default, the output is a TSV file. You can also get a YAML output by including `--format YAML`. A summary of the report is also printed to the console:
-```
-Violations: 710
------------------
-ERROR:      109
-WARN:       572
-INFO:       29
-```
-
-## Failing
-
-By default, `report` will fail if any `ERROR`-level violations are found. This can be changed by setting the `--fail-on` level to a different logging level. For example, if you want your report to fail if there are any `WARN`-level violations:
-<!-- DO NOT TEST -->
-```
-robot report --input edit.owl \
-  --fail-on WARN \
-  --output report.tsv
-```
-
-If the report fails, the command will exit with a status of `1`, but a report will still be generated and written to the output file. To always pass (even with errors), change the level to `--fail-on none`.
-
-## Queries
-
-`report` runs a number of queries, each with a default logging level. [See the full list](report_queries/).
-
-Each query retrieves a triple in the form of `?entity ?property ?value`. The `?entity` is the violating entity, the `?property` is the property that is being violated, and `?value` is what is causing the violation (which could be empty).
-
-For example, the query to retrieve references to deprecatd classes:
-```
-SELECT DISTINCT ?entity ?property ?value WHERE
-  {?value owl:deprecated true .
-   ?entity a owl:Class .
-   ?entity ?property ?value }
-```
-Here, the `?value` is any deprecated class that is referenced in another entity's axioms.
-
-You can provide your own queries to use in the report (which can be included in the profile, described below). Please make sure to follow this `?entity ?property ?value` pattern when writing these queries.
-
-## Profiles
-
-Each QC query is given the corresponding logging level shown above in the [default profile](/). The profile is a simple text file with a logging level followed by the query name (separated by a tab). Each line represents one query configuration:
-```
-ERROR	definition_cardinality
-INFO	deprecated_class
-```
-
-`report` allows the user to define their own profile to configure different logging levels and include their own QC queries with the `--profile` option:
-<!-- DO NOT TEST -->
-```
-robot report --input edit.owl \
-  --profile my-profile.txt \
-  --output my-report.tsv
-```
-
-For all default queries, include the query name shown above. If you do not wish to include a default query in your report, simply omit it from your profile. Any queries not named in the profile will not be run. Furthermore, your own queries can be included by providing the desired logging level followed by the path.
-
-This example would create a report with references to deprecated classes as ERROR and the user query violations as INFO:
-```
-ERROR	deprecated_class
-INFO	file:///absolute/path/to/other_query.rq
-```
-
----
-
-## Error Messages
-
-### Report Level Error
-
-The logging level defined in a profile must be `ERROR`, `WARN`, or `INFO`.
diff --git a/docs/report_queries/annotation_whitespace.md b/docs/report_queries/annotation_whitespace.md
deleted file mode 100644
index bb9cdcc7..00000000
--- a/docs/report_queries/annotation_whitespace.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Annotation Whitespace
-
-Problem: An annotation has leading or trailing whitespace, usually a single space.
-
-Solution: Re-format the annotation to remove additional whitespace.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- {?property a owl:AnnotationProperty .
-  ?entity ?property ?value .
-  FILTER STRENDS(str(?value), " ")}
- UNION
- {?property a owl:AnnotationProperty .
-  ?entity ?property ?value .
-  FILTER STRSTARTS(str(?value), " ")}
-}
-```
diff --git a/docs/report_queries/deprecated_class_reference.md b/docs/report_queries/deprecated_class_reference.md
deleted file mode 100644
index 4aaf18f3..00000000
--- a/docs/report_queries/deprecated_class_reference.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Deprecated Class Reference
-
-Problem: A deprecated class is used in a logical axiom. A deprecated class can be the child of another class (e.g. ObsoleteClass), but it cannot have children or be used in blank nodes or equivalent class statements. Additionally, a deprecated class should not have any equivalent classes or anonymous parents.
-
-Solution: Replace deprecated class.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- {
-  VALUES ?property {
-    owl:equivalentClass
-    rdfs:subClassOf
-  }
-  ?entity owl:deprecated ?dep .
-  FILTER regex(str(?dep), "true") .
-  ?value ?property ?entity .
-  FILTER (!STRENDS(str(?property), "owl#deprecated"))
- }
- UNION
- {
-  ?entity owl:deprecated ?dep .
-  FILTER regex(str(?dep), "true") .
-  ?entity ?property ?value .
-  FILTER (!STRENDS(str(?property), "owl#deprecated")) .
-  FILTER NOT EXISTS { ?property a owl:AnnotationProperty }
-  FILTER NOT EXISTS {
-    ?entity rdfs:subClassOf ?value .
-    FILTER (!isBlank(?value))
-  }
-  FILTER NOT EXISTS {
-    ?entity rdfs:subPropertyOf ?value .
-    FILTER (!isBlank(?value))
-  }
- }
-}
-```
diff --git a/docs/report_queries/duplicate_definition.md b/docs/report_queries/duplicate_definition.md
deleted file mode 100644
index 97525a60..00000000
--- a/docs/report_queries/duplicate_definition.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# Duplicate Definition
-
-Problem: An entity shares an exact definition with another entity.
-
-Solution: Update the definition to reflect the entities, or determine if the entities are the same.
-
-```sparql
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {obo:IAO_0000115}
- ?entity obo:IAO_0000115 ?value .
- ?entity2 obo:IAO_0000115 ?value .
- FILTER (?entity != ?entity2) .
- FILTER (!isBlank(?entity))
-}
-ORDER BY ?value
-```
diff --git a/docs/report_queries/duplicate_exact_synonym.md b/docs/report_queries/duplicate_exact_synonym.md
deleted file mode 100644
index 9df9d010..00000000
--- a/docs/report_queries/duplicate_exact_synonym.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Duplicate Exact Synonym
-
-Problem: Two entities share an exact synonym. This causes ambiguity.
-
-Solution: Avoid ambiguity by assigning unique exact synonyms or changing the exact synonym to a different annotation (e.g. broad synonym).
-
-```sparql
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {
-   obo:IAO_0000118
-   oboInOwl:hasExactSynonym
- }
- ?entity ?property ?value .
- ?entity2 ?property ?value .
- FILTER (?entity != ?entity2)
-}
-```
diff --git a/docs/report_queries/duplicate_label.md b/docs/report_queries/duplicate_label.md
deleted file mode 100644
index 8b15eb56..00000000
--- a/docs/report_queries/duplicate_label.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Duplicate Label
-
-Problem: Two different subjects have been assigned the same label. This causes ambiguity.
-
-Solution: Avoid ambiguity by assigning distinct labels to each subject.
-
-```sparql
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {rdfs:label}
- ?entity ?property ?value .
- ?entity2 ?property ?value .
- FILTER (?entity != ?entity2)
- FILTER (!isBlank(?entity))
-}
-ORDER BY ?value
-```
diff --git a/docs/report_queries/duplicate_label_synonym.md b/docs/report_queries/duplicate_label_synonym.md
deleted file mode 100644
index a03e66f8..00000000
--- a/docs/report_queries/duplicate_label_synonym.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Duplicate Label-Synonym
-
-Problem: An entity shares a label with an exact synonym. This causes ambiguity.
-
-Solution: Avoid ambiguity by changing the exact synonym or label.
-
-```sparql
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {
-   obo:IAO_0000118
-   oboInOwl:hasExactSynonym
-   oboInOwl:hasRelatedSynonym
-   oboInOwl:hasNarrowSynonym
-   oboInOwl:hasBroadSynonym
- }
- ?entity rdfs:label ?value .
- ?entity ?property ?value
-}
-```
diff --git a/docs/report_queries/duplicate_scoped_synonym.md b/docs/report_queries/duplicate_scoped_synonym.md
deleted file mode 100644
index 0922e1db..00000000
--- a/docs/report_queries/duplicate_scoped_synonym.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Duplicate Scoped Synonyms
-
-Problem: An entity has duplicate synonyms with different properties (e.g. the same broad and related synonym). This causes ambiguity.
-
-Solution: Remove duplicate synonyms and determine the correct scope.
-
-```sparql
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {
-   obo:IAO_0000118
-   oboInOwl:hasExactSynonym
-   oboInOwl:hasBroadSynonym
-   oboInOwl:hasRelatedSynonym
-   oboInOwl:hasNarrowSynonym
- }
- VALUES ?property2 {
-   obo:IAO_0000118
-   oboInOwl:hasExactSynonym
-   oboInOwl:hasBroadSynonym
-   oboInOwl:hasRelatedSynonym
-   oboInOwl:hasNarrowSynonym
- }
- ?entity ?property ?value .
- ?entity ?property2 ?value .
- FILTER (?property != ?property2)
-}
-ORDER BY ?entity
-```
diff --git a/docs/report_queries/equivalent_pair.md b/docs/report_queries/equivalent_pair.md
deleted file mode 100644
index 65889929..00000000
--- a/docs/report_queries/equivalent_pair.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Equivalent Pair
-
-Problem: An entity has a one-to-one equivalency with another entity. This may be intentional (assuming it is not annotated with `is_inferred true`), or it may be due to incorrect logic and the reasoner asserting the equivalency.
-
-Solution: Ensure the reasoner is not incorrectly inferring equivalency. If so, update the logical axioms.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {owl:equivalentClass}
- ?entity ?property ?value .
- FILTER (!isBlank(?value))
-}
-```
diff --git a/docs/report_queries/index.md b/docs/report_queries/index.md
deleted file mode 100644
index 4222c8b0..00000000
--- a/docs/report_queries/index.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Report Queries
-
-The table below lists all the queries run by the `report` command,
-with their default severity levels.
-See [`report`](../report) for more details.
-
-| Name  | Default Severity  
-|-------|-------------------
-| [annotation whitespace](annotation_whitespace)  | WARN
-| [deprecated class reference](deprecated_class_reference)  | ERROR
-| [duplicate definition](duplicate_definition)  | ERROR
-| [duplicate exact synonym](duplicate_exact_synonym)  | WARN
-| [duplicate label synonym](duplicate_label_synonym)  | WARN
-| [duplicate label](duplicate_label)  | ERROR
-| [duplicate scoped synonym](duplicate_scoped_synonym)  | WARN
-| [equivalent pair](equivalent_pair)  | WARN
-| [invalid xref](invalid_xref)  | WARN
-| [label formatting](label_formatting)  | ERROR
-| [label whitespace](label_whitespace)  | ERROR
-| [lowercase definition](lowercase_definition)  | INFO
-| [missing definition](missing_definition)  | WARN
-| [missing label](missing_label)  | ERROR
-| [missing obsolete label](missing_obsolete_label)  | WARN
-| [missing superclass](missing_superclass)  | INFO
-| [misused obsolete label](misused_obsolete_label)  | ERROR
-| [multiple asserted superclasses](multiple_asserted_superclasses)  | WARN
-| [multiple definitions](multiple_definitions)  | ERROR
-| [multiple labels](multiple_labels)  | ERROR
-| [ontology metadata](ontology_metadata)  | ERROR
diff --git a/docs/report_queries/invalid_xref.md b/docs/report_queries/invalid_xref.md
deleted file mode 100644
index f9b2b691..00000000
--- a/docs/report_queries/invalid_xref.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Invalid Xref
-
-Problem: A database_cross_reference is not in CURIE format.
-
-Solution: Replace the reference with a [CURIE](https://www.w3.org/TR/2010/NOTE-curie-20101216/).
-
-```sparql
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {oboInOwl:hasDbXref}
- ?entity ?property ?value .
- FILTER (!regex(?value, "^[a-z|A-Z|_|0-9]*:(?!$)\\S*$"))
- FILTER (!isBlank(?entity))
-}
-```
diff --git a/docs/report_queries/label_formatting.md b/docs/report_queries/label_formatting.md
deleted file mode 100644
index 3aee0c4e..00000000
--- a/docs/report_queries/label_formatting.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Label Formatting
-
-Problem: Formatting characters are used in a label. This may cause issues when trying to reference the entity by label.
-
-Solution: Remove formatting characters from label.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- {
-  VALUES ?property {rdfs:label}
-  ?entity ?property ?value .
-  FILTER regex(?value, "\n")
- }
- UNION
- {
-  VALUES ?property {rdfs:label}
-  ?entity ?property ?value .
-  FILTER regex(?value, "\t")
- }
-}
-```
diff --git a/docs/report_queries/label_whitespace.md b/docs/report_queries/label_whitespace.md
deleted file mode 100644
index c0c84f5d..00000000
--- a/docs/report_queries/label_whitespace.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Label Whitespace
-
-Problem: A label has leading or trailing whitespace. This may cause issues when trying to reference the entity by label.
-
-Solution: Remove the additional whitespace.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- {
-  VALUES ?property {rdfs:label}
-  ?entity ?property ?value .
-  FILTER STRENDS(str(?value), " ")
- }
- UNION
- {
-  VALUES ?property {rdfs:label}
-  ?entity ?property ?value .
-  FILTER STRSTARTS(str(?value), " ")
- }
-}
-```
diff --git a/docs/report_queries/lowercase_definition.md b/docs/report_queries/lowercase_definition.md
deleted file mode 100644
index bacd1bd7..00000000
--- a/docs/report_queries/lowercase_definition.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Lowercase Definition
-
-Problem: A definition does not begin with an uppercase letter. This may be indicative of inconsistent formatting.
-
-Solution: Capitalize the first letter of the definition, or disregard this INFO.
-
-```sparql
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {obo:IAO_0000115}
- ?entity ?property ?value .
- FILTER (!regex(?value, "^[A-Z]"))
-}
-```
diff --git a/docs/report_queries/missing_definition.md b/docs/report_queries/missing_definition.md
deleted file mode 100644
index bd2f34cc..00000000
--- a/docs/report_queries/missing_definition.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Missing Definition
-
-Problem: An entity does not have a definition. This may cause confusion or misuse of the entity.
-
-Solution: Add a definition.
-
-```sparql
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- ?entity ?any ?o
- FILTER NOT EXISTS {?entity obo:IAO_0000115 ?value}
- FILTER NOT EXISTS {?entity a owl:Ontology}
- FILTER NOT EXISTS {
-   ?entity owl:deprecated ?dep .
-   FILTER regex(str(?dep), "true")
- }
- FILTER (!isBlank(?entity))
-}
-```
diff --git a/docs/report_queries/missing_label.md b/docs/report_queries/missing_label.md
deleted file mode 100644
index 100ad864..00000000
--- a/docs/report_queries/missing_label.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Missing Label
-
-Problem: An entity does not have a label. This may cause confusion or misuse.
-
-Solution: Add a label.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- ?entity ?any ?o .
- BIND ("rdfs:label" AS ?property) .
- FILTER NOT EXISTS {?entity rdfs:label ?value}
- FILTER NOT EXISTS {?entity a owl:Ontology}
- FILTER NOT EXISTS {
-   ?entity owl:deprecated ?dep .
-   FILTER regex(str(?dep), "true")
- }
- FILTER (!isBlank(?entity))
-}
-```
diff --git a/docs/report_queries/missing_obsolete_label.md b/docs/report_queries/missing_obsolete_label.md
deleted file mode 100644
index 2ac44d32..00000000
--- a/docs/report_queries/missing_obsolete_label.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Missing Obsolete Label
-
-Problem: An obsolete entity does not have a label beginning with "obsolete". Adding this prefix ensures that users are aware the entity has been deprecated.
-
-Solution: Add the "obsolete" (or "OBSOLETE") prefix.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {rdfs:label}
- ?entity owl:deprecated ?dep .
- FILTER regex(str(?dep), "true") .
- ?entity ?property ?value .
- FILTER (!regex(?value, "^obsolete", "i"))
-}
-```
diff --git a/docs/report_queries/missing_superclass.md b/docs/report_queries/missing_superclass.md
deleted file mode 100644
index ea2d1306..00000000
--- a/docs/report_queries/missing_superclass.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Missing Superclass
-
-Problem: A class does not have a superclass. This is not relevant for top-level classes, but may reveal orphaned children.
-
-Solution: Make sure there are no orphaned children - if so, assert a parent.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {rdfs:subClassOf}
- ?entity a owl:Class .
- FILTER (!isBlank(?entity)) .
- FILTER NOT EXISTS {?entity ?property ?value} .
- FILTER NOT EXISTS {
-   FILTER EXISTS {
-     ?entity owl:deprecated ?dep .
-     FILTER regex(str(?dep), "true")
-   }
- }
-}
-```
diff --git a/docs/report_queries/misused_obsolete_label.md b/docs/report_queries/misused_obsolete_label.md
deleted file mode 100644
index f2ea1741..00000000
--- a/docs/report_queries/misused_obsolete_label.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Misused Obsolete Label
-
-Problem: A non-deprecated class has the "obsolete" prefix. This may mean that a deprecated class is missing the `owl:deprecated` annotation, or that this prefix was added accidentally.
-
-Solution: Remove the "obsolete" prefix or add the `owl:deprecated` annotation.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {rdfs:label}
- ?entity ?property ?value .
- FILTER NOT EXISTS {
-   ?entity owl:deprecated ?dep .
-   FILTER regex(str(?dep), "true")
- }
- FILTER regex(?value, "^obsolete", "i")
-}
-```
diff --git a/docs/report_queries/multiple_asserted_superclasses.md b/docs/report_queries/multiple_asserted_superclasses.md
deleted file mode 100644
index fb8d84ac..00000000
--- a/docs/report_queries/multiple_asserted_superclasses.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# Multiple Asserted Superclasses
-
-Problem: A class has more than one asserted named parent. This filters any axioms with the `is_inferred true` annotation, but inferences may not always be annotated. Double check where the parent is coming from before making changes.
-
-Solution: Use logical axioms to infer dual parentage.
-
-```sparql
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {rdfs:subClassOf}
- ?entity a owl:Class .
- ?entity ?property ?value .
- ?entity ?property ?value2 .
- FILTER (?value != ?value2)
- FILTER (!isBlank(?value))
- FILTER (!isBlank(?value2))
- FILTER NOT EXISTS {
-   ?axiom owl:annotatedSource ?entity .
-   ?axiom owl:annotatedTarget ?value .
-   ?axiom owl:annotatedProperty rdfs:subClassOf .
-   ?axiom oboInOwl:is_inferred ?inf .
-   FILTER regex(str(?inf), "true")
- }
-}
-ORDER BY ?entity
-```
diff --git a/docs/report_queries/multiple_definitions.md b/docs/report_queries/multiple_definitions.md
deleted file mode 100644
index c20938be..00000000
--- a/docs/report_queries/multiple_definitions.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Multiple Defintions
-
-Problem: An entity has more than one definition. This may cause confusion or misuse, and will prevent translation to OBO format.
-
-Solution: Remove extra definitions.
-
-```sparql
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {obo:IAO_0000115}
- ?entity ?property ?value .
- ?entity ?property ?value2 .
- FILTER (?value != ?value2)
- FILTER NOT EXISTS {
-   ?entity owl:deprecated ?dep .
-   FILTER regex(str(?dep), "true")
- }
- FILTER (!isBlank(?entity))
-}
-ORDER BY ?entity
-```
diff --git a/docs/report_queries/multiple_labels.md b/docs/report_queries/multiple_labels.md
deleted file mode 100644
index e9667831..00000000
--- a/docs/report_queries/multiple_labels.md
+++ /dev/null
@@ -1,21 +0,0 @@
-# Multiple Labels
-
-Problem: An entity has more than one label. This may cause confusion or misuse, and will prevent translation to OBO format.
-
-Solution: Remove extra labels.
-
-```sparql
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {rdfs:label}
- ?entity ?property ?value .
- ?entity ?property ?value2 .
- FILTER (?value != ?value2) .
- FILTER NOT EXISTS {?entity owl:deprecated true}
- FILTER (!isBlank(?entity))
-}
-ORDER BY ?entity
-```
diff --git a/docs/report_queries/ontology_metadata.md b/docs/report_queries/ontology_metadata.md
deleted file mode 100644
index 0f27fa85..00000000
--- a/docs/report_queries/ontology_metadata.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Ontology Metadata
-
-Problem: The ontology header is missing required metadata. Currently, the OBO Foundry expects: a [license](http://dublincore.org/documents/dcmi-terms/#terms-license), a [description](http://dublincore.org/documents/dcmi-terms/#elements-description), and a [title](http://dublincore.org/documents/dcmi-terms/#elements-title).
-
-Solution: Add the missing metadata. See links for appropriate annotation properties.
-
-```sparql
-PREFIX dc: <http://purl.org/dc/elements/1.1/>
-PREFIX dcterms: <http://purl.org/dc/terms/>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
- VALUES ?property {
-   dcterms:license
- 	dc:description
- 	dc:title
- }
- ?entity a owl:Ontology .
- OPTIONAL { ?entity ?property ?value }
- FILTER (!bound(?value))
-}
-```
diff --git a/docs/template.md b/docs/template.md
index dcc945da..80689e92 100644
--- a/docs/template.md
+++ b/docs/template.md
@@ -35,7 +35,7 @@ The `template` command accepts an optional input ontology, either using the `--i
     - `>A` annotation on annotation: Annotates the annotation axiom created from the cell to the left with the cell value. The column to the left must be an `A*` template string.
     - `>C` annotation on class expression: Annotates the class expression axiom created from the cell to the left with the cell value. The column to the left must be a `C` template string.
 
-Sometimes you want to include zero or more values in a single spreadsheet cell, for example when you want to allow for multiple annotations or have seperate logical axioms. If a template string also contains `SPLIT=|`, then ROBOT will use the `|` character to split the contents of a cell in that column and add an annotation for each result (if there are any). Instead of `|` you can specify a string of characters of your choice - other than pure whitespace - to split on (e.g. `SPLIT=, `).
+Sometimes you want to include zero or more values in a single spreadsheet cell, for example when you want to allow for multiple annotations. If an annotation template string also contains `SPLIT=|`, then ROBOT will use the `|` character to split the contents of a cell in that column and add an annotation for each result (if there are any). Instead of `|` you can specify a string of non-whitespace characters of your choice to split on.
 
 
 ## Merging
diff --git a/docs/verify.md b/docs/verify.md
index dbdc8b97..8cf2b44f 100644
--- a/docs/verify.md
+++ b/docs/verify.md
@@ -22,4 +22,16 @@ Should output as a response:
 And the CSV file `results/equivalent.csv` should have:
 
     first,second,firstLabel,secondLabel
-    http://purl.obolibrary.org/obo/TEST_A,http://purl.obolibrary.org/obo/TEST_B,,
\ No newline at end of file
+    http://purl.obolibrary.org/obo/TEST_A,http://purl.obolibrary.org/obo/TEST_B,,
+
+---
+
+## Error Messages
+
+### Verification Failed
+
+At least one of the query you specifies returned results. The number of failures for each rule will be printed. A CSV file will be generated with the results that matched the rule.
+
+### Missing Query Error
+
+You must specify a query to execute with `--query` or `--queries`.
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 ca82da12..fbcb8ff7 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java
@@ -348,25 +348,15 @@ public class CommandLineHelper {
     // Check for multiple inputs
     List<String> inputOntologyPaths = getOptionalValues(line, "input");
     List<String> inputOntologyIRIs = getOptionalValues(line, "input-iri");
-    String catalogPath = getOptionalValue(line, "catalog");
-
     Integer check = inputOntologyPaths.size() + inputOntologyIRIs.size();
     if (check > 1) {
       throw new IllegalArgumentException(multipleInputsError);
     }
 
     if (!inputOntologyPaths.isEmpty()) {
-      if (catalogPath != null) {
-        inputOntology = ioHelper.loadOntology(inputOntologyPaths.get(0), catalogPath);
-      } else {
-        inputOntology = ioHelper.loadOntology(inputOntologyPaths.get(0));
-      }
+      inputOntology = ioHelper.loadOntology(inputOntologyPaths.get(0));
     } else if (!inputOntologyIRIs.isEmpty()) {
-      if (catalogPath != null) {
-        inputOntology = ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0)), catalogPath);
-      } else {
-        inputOntology = ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0)));
-      }
+      inputOntology = ioHelper.loadOntology(IRI.create(inputOntologyIRIs.get(0)));
     } else {
       // Both input options are empty
       throw new IllegalArgumentException(missingInputError);
@@ -391,12 +381,38 @@ public class CommandLineHelper {
       IOHelper ioHelper, CommandLine line, boolean allowEmpty)
       throws IllegalArgumentException, IOException {
     List<OWLOntology> inputOntologies = new ArrayList<OWLOntology>();
-    String catalogPath = getOptionalValue(line, "catalog");
 
-    if (catalogPath != null) {
-      inputOntologies.addAll(getInputOntologies(ioHelper, line, catalogPath));
-    } else {
-      inputOntologies.addAll(getInputOntologies(ioHelper, line));
+    // Check for input files
+    List<String> inputOntologyPaths = getOptionalValues(line, "input");
+    for (String inputOntologyPath : inputOntologyPaths) {
+      inputOntologies.add(ioHelper.loadOntology(inputOntologyPath));
+    }
+
+    // Check for input IRIs
+    List<String> inputOntologyIRIs = getOptionalValues(line, "input-iri");
+    for (String inputOntologyIRI : inputOntologyIRIs) {
+      inputOntologies.add(ioHelper.loadOntology(IRI.create(inputOntologyIRI)));
+    }
+
+    // Check for input patterns (wildcard)
+    List<String> inputOntologyPatterns = getOptionalValues(line, "inputs");
+    for (String inputOntologyPattern : inputOntologyPatterns) {
+      if (!inputOntologyPattern.contains("*") && !inputOntologyPattern.contains("?")) {
+        throw new IllegalArgumentException(wildcardError);
+      }
+      FileFilter fileFilter = new WildcardFileFilter(inputOntologyPattern);
+      File[] inputOntologyFiles = new File(".").listFiles(fileFilter);
+      if (inputOntologyFiles.length < 1) {
+        // Warn user, but continue (empty input checked later)
+        logger.error("No files match pattern: {}", inputOntologyPattern);
+      }
+      System.out.println("Loading matches to \"" + inputOntologyPattern + "\":");
+      int counter = 0;
+      for (File inputOntologyFile : inputOntologyFiles) {
+        counter++;
+        System.out.println(counter + ". " + inputOntologyFile.getName());
+        inputOntologies.add(ioHelper.loadOntology(inputOntologyFile));
+      }
     }
 
     if (inputOntologies.isEmpty() && !allowEmpty) {
@@ -630,7 +646,7 @@ public class CommandLineHelper {
     if (reasonerName.equals("structural")) {
       return new org.semanticweb.owlapi.reasoner.structural.StructuralReasonerFactory();
     } else if (reasonerName.equals("hermit")) {
-      return new org.semanticweb.HermiT.ReasonerFactory();
+      return new org.semanticweb.HermiT.Reasoner.ReasonerFactory();
     } else if (reasonerName.equals("jfact")) {
       return new JFactFactory();
       // Reason must change behavior with EMR, so not all commands can use it
@@ -673,7 +689,6 @@ public class CommandLineHelper {
     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, "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");
     o.addOption("noprefixes", false, "do not use default prefixes");
@@ -752,89 +767,4 @@ public class CommandLineHelper {
     ExceptionHelper.handleException(exception);
     System.exit(1);
   }
-
-  /**
-   * Given a wildcard pattern as string, return an array of files matching that pattern.
-   *
-   * @param pattern wildcard pattern to match
-   * @return array of files
-   */
-  private static File[] getFilesByPattern(String pattern) {
-    if (!pattern.contains("*") && !pattern.contains("?")) {
-      throw new IllegalArgumentException(wildcardError);
-    }
-    FileFilter fileFilter = new WildcardFileFilter(pattern);
-    File[] files = new File(".").listFiles(fileFilter);
-    if (files.length < 1) {
-      // Warn user, but continue (empty input checked later)
-      logger.error("No files match pattern: {}", pattern);
-    }
-    return files;
-  }
-
-  /**
-   * Given an IOHelper and a command line, check input options and return a list of loaded input
-   * ontologies.
-   *
-   * @param ioHelper the IOHelper to load the ontology with
-   * @param line the command line to use
-   * @return the list of input ontologies
-   * @throws IOException if the ontology cannot be loaded
-   */
-  private static List<OWLOntology> getInputOntologies(IOHelper ioHelper, CommandLine line)
-      throws IOException {
-    List<OWLOntology> inputOntologies = new ArrayList<>();
-    // Check for input files
-    List<String> inputOntologyPaths = getOptionalValues(line, "input");
-    for (String inputOntologyPath : inputOntologyPaths) {
-      inputOntologies.add(ioHelper.loadOntology(inputOntologyPath));
-    }
-    // Check for input IRIs
-    List<String> inputOntologyIRIs = getOptionalValues(line, "input-iri");
-    for (String inputOntologyIRI : inputOntologyIRIs) {
-      inputOntologies.add(ioHelper.loadOntology(IRI.create(inputOntologyIRI)));
-    }
-    // Check for input patterns (wildcard)
-    String pattern = getOptionalValue(line, "inputs");
-    if (pattern != null) {
-      for (File inputOntologyFile : getFilesByPattern(pattern)) {
-        inputOntologies.add(ioHelper.loadOntology(inputOntologyFile));
-      }
-    }
-    return inputOntologies;
-  }
-
-  /**
-   * Given an IOHelper, a command line, and the path to a catalog file, check input options and
-   * return a list of loaded input ontologies with the catalog file.
-   *
-   * @param ioHelper the IOHelper to load the ontology with
-   * @param line the command line to use
-   * @param catalogPath the catalog file to use
-   * @return the list of input ontologies
-   * @throws IOException if the ontology cannot be loaded
-   */
-  private static List<OWLOntology> getInputOntologies(
-      IOHelper ioHelper, CommandLine line, String catalogPath) throws IOException {
-    List<OWLOntology> inputOntologies = new ArrayList<>();
-    // Check for input files
-    List<String> inputOntologyPaths = getOptionalValues(line, "input");
-    for (String inputOntologyPath : inputOntologyPaths) {
-      inputOntologies.add(ioHelper.loadOntology(inputOntologyPath, catalogPath));
-    }
-    // Check for input IRIs
-    List<String> inputOntologyIRIs = getOptionalValues(line, "input-iri");
-    for (String inputOntologyIRI : inputOntologyIRIs) {
-      inputOntologies.add(ioHelper.loadOntology(IRI.create(inputOntologyIRI), catalogPath));
-    }
-    // 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));
-      }
-    }
-    return inputOntologies;
-  }
 }
diff --git a/robot-command/src/main/java/org/obolibrary/robot/ExportPrefixesCommand.java b/robot-command/src/main/java/org/obolibrary/robot/ExportPrefixesCommand.java
index 87141f91..366bde82 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/ExportPrefixesCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/ExportPrefixesCommand.java
@@ -17,7 +17,7 @@ public class ExportPrefixesCommand implements Command {
   private static final Logger logger = LoggerFactory.getLogger(ExportPrefixesCommand.class);
 
   /** Namespace for error messages. */
-  private static final String NS = "global#";
+  private static final String NS = "prefixes#";
 
   /** Error message when JSON-LD context cannot be generated. */
   private static final String jsonLDError = NS + "JSON-LD ERROR the JSON-LD could not be generated";
diff --git a/robot-command/src/main/java/org/obolibrary/robot/MergeCommand.java b/robot-command/src/main/java/org/obolibrary/robot/MergeCommand.java
index 4d95c2ee..a6962439 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/MergeCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/MergeCommand.java
@@ -104,7 +104,7 @@ public class MergeCommand implements Command {
       state = new CommandState();
     }
 
-    List<OWLOntology> inputOntologies = new ArrayList<>();
+    List<OWLOntology> inputOntologies = new ArrayList<OWLOntology>();
     // inputOntologies should not be empty
     boolean notEmpty = false;
     if (state != null && state.getOntology() != null) {
@@ -114,7 +114,7 @@ public class MergeCommand implements Command {
     inputOntologies.addAll(CommandLineHelper.getInputOntologies(ioHelper, line, notEmpty));
 
     boolean collapseImportClosure =
-        CommandLineHelper.getBooleanValue(line, "collapse-import-closure", true);
+        CommandLineHelper.getBooleanValue(line, "collapse-import-closure", false);
     boolean includeAnnotations =
         CommandLineHelper.getBooleanValue(line, "include-annotations", false);
     OWLOntology outputOntology =
diff --git a/robot-command/src/main/java/org/obolibrary/robot/ReasonCommand.java b/robot-command/src/main/java/org/obolibrary/robot/ReasonCommand.java
index 01a920f1..c2748343 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/ReasonCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/ReasonCommand.java
@@ -35,11 +35,6 @@ public class ReasonCommand implements Command {
     o.addOption("r", "reasoner", true, "reasoner to use: ELK, HermiT, JFact");
     o.addOption(
         "s", "remove-redundant-subclass-axioms", true, "if true, remove redundant subclass axioms");
-    o.addOption(
-        "p",
-        "preserve-annotated-axioms",
-        true,
-        "preserve annotated axioms when removing redundant subclass axioms");
     o.addOption(
         "n",
         "create-new-ontology",
@@ -60,12 +55,6 @@ public class ReasonCommand implements Command {
         "exclude-duplicate-axioms",
         true,
         "if true, do not add an axiom if it exists in import chain");
-    o.addOption(
-        "X",
-        "exclude-external-entities",
-        true,
-        "if true, do not add an axiom if it is about classes in external ontologies");
-    o.addOption("T", "exclude-owl-thing", true, "if true, exclude inferences to owl:Thing");
     o.addOption(
         "e",
         "equivalent-classes-allowed",
diff --git a/robot-command/src/main/java/org/obolibrary/robot/ReduceCommand.java b/robot-command/src/main/java/org/obolibrary/robot/ReduceCommand.java
index 67883a32..7b6d405a 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/ReduceCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/ReduceCommand.java
@@ -24,11 +24,7 @@ public class ReduceCommand implements Command {
   public ReduceCommand() {
     Options o = CommandLineHelper.getCommonOptions();
     o.addOption("r", "reasoner", true, "reasoner to use: (ELK, HermiT)");
-    o.addOption(
-        "p",
-        "preserve-annotated-axioms",
-        true,
-        "preserve annotated axioms when removing redundant subclass axioms");
+    o.addOption("s", "remove-redundant-subclass-axioms", true, "remove redundant subclass axioms");
     o.addOption("i", "input", true, "reduce ontology from a file");
     o.addOption("I", "input-iri", true, "reduce ontology from an IRI");
     o.addOption("o", "output", true, "save reduceed ontology to a file");
diff --git a/robot-command/src/main/java/org/obolibrary/robot/ReportCommand.java b/robot-command/src/main/java/org/obolibrary/robot/ReportCommand.java
index 061e832b..262286d7 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/ReportCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/ReportCommand.java
@@ -2,6 +2,7 @@ package org.obolibrary.robot;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Options;
+import org.semanticweb.owlapi.model.IRI;
 import org.semanticweb.owlapi.model.OWLOntology;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -23,10 +24,8 @@ public class ReportCommand implements Command {
     Options o = CommandLineHelper.getCommonOptions();
     o.addOption("i", "input", true, "load ontology from a file");
     o.addOption("I", "input-iri", true, "load ontology from an IRI");
-    o.addOption("o", "output", true, "save report to a file");
-    o.addOption("p", "profile", true, "reporting rules and levels to use");
-    o.addOption("f", "format", true, "save report in a given format (TSV or YAML)");
-    o.addOption("F", "fail-on", true, "logging level to fail on");
+    o.addOption("o", "output", true, "save ontology to a file");
+    o.addOption("O", "output-iri", true, "set OntologyIRI for output");
     options = o;
   }
 
@@ -54,7 +53,7 @@ public class ReportCommand implements Command {
    * @return usage
    */
   public String getUsage() {
-    return "robot report --input <file> " + "--output <file> ";
+    return "robot report --input <file> " + "--output <file> " + "--output-iri <iri>";
   }
 
   /**
@@ -89,6 +88,8 @@ public class ReportCommand implements Command {
    * @throws Exception on any problem
    */
   public CommandState execute(CommandState state, String[] args) throws Exception {
+    OWLOntology outputOntology = null;
+
     CommandLine line = CommandLineHelper.getCommandLine(getUsage(), getOptions(), args);
     if (line == null) {
       return null;
@@ -96,25 +97,15 @@ public class ReportCommand implements Command {
 
     IOHelper ioHelper = CommandLineHelper.getIOHelper(line);
     state = CommandLineHelper.updateInputOntology(ioHelper, state, line);
-    OWLOntology ontology = state.getOntology();
-
-    // output is optional - no output means the file will not be written anywhere
-    String outputPath = CommandLineHelper.getOptionalValue(line, "output");
-    // profile is optional - no profile means the default profile will be used
-    String profilePath = CommandLineHelper.getOptionalValue(line, "profile");
-    // format is optional - no format means the report will be in TSV
-    String format = CommandLineHelper.getOptionalValue(line, "format");
-    // fail-on is optional - if null, will always exit with 0
-    String failOn = CommandLineHelper.getDefaultValue(line, "fail-on", "error");
+    OWLOntology inputOntology = state.getOntology();
 
-    // Success is based on failOn
-    // If any violations are found of the fail-on level, this will be false
-    // If failOn is "none" or if no violations are found, this will be true
-    boolean success = ReportOperation.report(ontology, profilePath, outputPath, format, failOn);
-    if (!success) {
-      logger.error("Report failed!");
-      System.exit(1);
+    IRI outputIRI = CommandLineHelper.getOutputIRI(line);
+    if (outputIRI == null) {
+      outputIRI = inputOntology.getOntologyID().getOntologyIRI().orNull();
     }
+
+    // TODO save results
+    ReportOperation.report(inputOntology, ioHelper);
     return state;
   }
 }
diff --git a/robot-command/src/main/java/org/obolibrary/robot/VerifyCommand.java b/robot-command/src/main/java/org/obolibrary/robot/VerifyCommand.java
index bb549fac..089d3599 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/VerifyCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/VerifyCommand.java
@@ -1,22 +1,12 @@
 package org.obolibrary.robot;
 
-import com.google.common.io.Files;
-import com.hp.hpl.jena.query.ResultSet;
-import com.hp.hpl.jena.query.ResultSetFactory;
-import com.hp.hpl.jena.query.ResultSetRewindable;
 import com.hp.hpl.jena.sparql.core.DatasetGraph;
 import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.HashMap;
-import java.util.Map;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FilenameUtils;
-import org.obolibrary.robot.exceptions.CannotReadQuery;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -36,6 +26,10 @@ public class VerifyCommand implements Command {
   private static final String missingQueryError =
       NS + "MISSING QUERY ERROR at least one query is required";
 
+  /** Error message when no query is provided. */
+  private static final String verificationFailed =
+      NS + "VERIFICATION FAILED there were violations of at least one rule";
+
   /** Store the command-line options for the command. */
   private Options options;
 
@@ -122,44 +116,24 @@ public class VerifyCommand implements Command {
 
     File outputDir = new File(CommandLineHelper.getDefaultValue(line, "output-dir", "."));
 
-    Map<File, Tuple<ResultSetRewindable, OutputStream>> resultMap = new HashMap<>();
     String[] queryFilePaths = line.getOptionValues("queries");
-    if (queryFilePaths.length == 0) {
-      throw new IllegalArgumentException(missingQueryError);
-    }
+    boolean passing = true;
     for (String filePath : queryFilePaths) {
-      File query = new File(filePath);
-      ResultSet results = QueryOperation.execQuery(graph, fileContents(query));
-      ResultSetRewindable resultsCopy = ResultSetFactory.copyResults(results);
+      File queryFile = new File(filePath);
+      String queryString = FileUtils.readFileToString(queryFile);
       String csvPath = FilenameUtils.getBaseName(filePath).concat(".csv");
-      File resultCsv = outputDir.toPath().resolve(csvPath).toFile();
-      if (resultsCopy.size() > 0) {
-        resultMap.put(query, new Tuple<>(resultsCopy, new FileOutputStream(resultCsv)));
-      } else {
-        System.out.println("Rule " + resultCsv.getCanonicalPath() + ": 0 violations");
+      boolean result =
+          QueryOperation.runVerify(
+              graph, filePath, queryString, outputDir.toPath().resolve(csvPath), null);
+      if (result) {
+        passing = false;
       }
     }
 
-    boolean violationsExist = QueryOperation.execVerify(resultMap);
-    if (violationsExist) {
-      System.exit(1);
+    if (!passing) {
+      throw new Exception(verificationFailed);
     }
 
     return state;
   }
-
-  /**
-   * Utility function to get file contents.
-   *
-   * @param file the file to read
-   */
-  private static String fileContents(File file) {
-    try {
-      return Files.toString(file, Charset.defaultCharset());
-    } catch (IOException e) {
-      String message = "Cannot read from " + file + ": " + e.getMessage();
-      // TODO: Is this necessary?
-      throw new CannotReadQuery(message, e);
-    }
-  }
 }
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 d58d84b8..87c8cea5 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/IOHelper.java
@@ -6,7 +6,6 @@ import com.github.jsonldjava.core.JsonLdError;
 import com.github.jsonldjava.core.JsonLdOptions;
 import com.github.jsonldjava.core.JsonLdProcessor;
 import com.github.jsonldjava.utils.JsonUtils;
-import com.google.common.collect.Sets;
 import com.hp.hpl.jena.rdf.model.Model;
 import com.hp.hpl.jena.rdf.model.ModelFactory;
 import java.io.BufferedWriter;
@@ -314,10 +313,7 @@ public class IOHelper {
 
       OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
       if (catalogFile != null && catalogFile.isFile()) {
-        manager.setIRIMappers(Sets.newHashSet(new CatalogXmlIRIMapper(catalogFile)));
-      } else {
-        logger.warn(
-            "Catalog {} does not exist. Loading ontology without catalog.", catalogFile.getPath());
+        manager.addIRIMapper(new CatalogXmlIRIMapper(catalogFile));
       }
       return manager.loadOntologyFromOntologyDocument(ontologyFile);
     } catch (JsonLdError e) {
@@ -346,10 +342,10 @@ public class IOHelper {
   }
 
   /**
-   * Given an ontology IRI, load the ontology from the IRI.
+   * Load an ontology from the web using an IRI.
    *
    * @param ontologyIRI the ontology IRI to load
-   * @return a new ontology object, with a new OWLManager
+   * @return a new ontology objects, with a new OWLManager
    * @throws IOException on any problem
    */
   public OWLOntology loadOntology(IRI ontologyIRI) throws IOException {
@@ -363,31 +359,6 @@ public class IOHelper {
     return ontology;
   }
 
-  /**
-   * Given an IRI and a path to a catalog file, load the ontology from the IRI with the catalog.
-   *
-   * @param ontologyIRI the ontology IRI to load
-   * @param catalogPath the catalog file to use
-   * @return a new ontology object, with a new OWLManager
-   * @throws IOException on any problem
-   */
-  public OWLOntology loadOntology(IRI ontologyIRI, String catalogPath) throws IOException {
-    OWLOntology ontology = null;
-    File catalogFile = new File(catalogPath);
-    if (!catalogFile.isFile() || catalogFile == null) {
-      // TODO: should this be an exception?
-      logger.warn("Catalog {} does not exist. Loading ontology without catalog.", catalogPath);
-    }
-    try {
-      OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
-      manager.setIRIMappers(Sets.newHashSet(new CatalogXmlIRIMapper(catalogFile)));
-      ontology = manager.loadOntologyFromOntologyDocument(ontologyIRI);
-    } catch (OWLOntologyCreationException e) {
-      throw new IOException(e);
-    }
-    return ontology;
-  }
-
   /**
    * Given the name of a file format, return an instance of it.
    *
diff --git a/robot-core/src/main/java/org/obolibrary/robot/QueryOperation.java b/robot-core/src/main/java/org/obolibrary/robot/QueryOperation.java
index a2550af8..774e3ff5 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/QueryOperation.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/QueryOperation.java
@@ -5,6 +5,7 @@ import com.hp.hpl.jena.rdf.model.Model;
 import com.hp.hpl.jena.sparql.core.DatasetGraph;
 import com.hp.hpl.jena.sparql.core.DatasetGraphFactory;
 import java.io.*;
+import java.nio.file.Path;
 import java.util.Map;
 import org.apache.jena.riot.Lang;
 import org.apache.jena.riot.RDFDataMgr;
@@ -427,6 +428,57 @@ public class QueryOperation {
     return isViolation;
   }
 
+  /**
+   * Execute a SPARQL query and return true if there are any results, false otherwise. Prints
+   * violations to STDERR.
+   *
+   * @param dsg the graph to query over
+   * @param query the SPARQL query string
+   * @return true if the are results, false otherwise
+   */
+  public static boolean execVerify(DatasetGraph dsg, String ruleName, String query) {
+    ResultSetRewindable results = ResultSetFactory.copyResults(execQuery(dsg, query));
+    System.out.println("Rule " + ruleName + ": " + results.size() + " violation(s)");
+    if (results.size() == 0) {
+      System.out.println("PASS Rule " + ruleName + ": 0 violation(s)");
+      return false;
+    } else {
+      ResultSetMgr.write(System.err, results, Lang.CSV);
+      System.out.println("FAIL Rule " + ruleName + ": " + results.size() + " violation(s)");
+      return true;
+    }
+  }
+
+  /**
+   * Run a SELECT query and write the result to a file. Prints violations to STDERR.
+   *
+   * @param dsg The graph to query over.
+   * @param query The SPARQL query string.
+   * @param outputPath The file path to write to, if there are results
+   * @param outputFormat The file format.
+   * @throws FileNotFoundException if output file is not found
+   * @return true if the are results (so file is written), false otherwise
+   */
+  public static boolean runVerify(
+      DatasetGraph dsg, String ruleName, String query, Path outputPath, Lang outputFormat)
+      throws FileNotFoundException {
+    if (outputFormat == null) {
+      outputFormat = Lang.CSV;
+    }
+    ResultSetRewindable results = ResultSetFactory.copyResults(execQuery(dsg, query));
+    if (results.size() == 0) {
+      System.out.println("PASS Rule " + ruleName + ": 0 violation(s)");
+      return false;
+    } else {
+      System.out.println("FAIL Rule " + ruleName + ": " + results.size() + " violation(s)");
+      ResultSetMgr.write(System.err, results, Lang.CSV);
+      results.reset();
+      FileOutputStream csvFile = new FileOutputStream(outputPath.toFile());
+      writeResult(results, outputFormat, csvFile);
+      return true;
+    }
+  }
+
   /**
    * Count results.
    *
diff --git a/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java b/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java
index d195bd7c..231236fc 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java
@@ -18,16 +18,13 @@ import org.obolibrary.robot.exceptions.OntologyLogicException;
 import org.obolibrary.robot.reason.EquivalentClassReasoning;
 import org.obolibrary.robot.reason.EquivalentClassReasoningMode;
 import org.semanticweb.owlapi.apibinding.OWLManager;
-import org.semanticweb.owlapi.model.AxiomType;
 import org.semanticweb.owlapi.model.IRI;
 import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
 import org.semanticweb.owlapi.model.OWLAnnotationValue;
 import org.semanticweb.owlapi.model.OWLAxiom;
 import org.semanticweb.owlapi.model.OWLClass;
-import org.semanticweb.owlapi.model.OWLClassAxiom;
 import org.semanticweb.owlapi.model.OWLClassExpression;
 import org.semanticweb.owlapi.model.OWLDataFactory;
-import org.semanticweb.owlapi.model.OWLEntity;
 import org.semanticweb.owlapi.model.OWLImportsDeclaration;
 import org.semanticweb.owlapi.model.OWLNamedObject;
 import org.semanticweb.owlapi.model.OWLOntology;
@@ -67,11 +64,8 @@ public class ReasonOperation {
     options.put("create-new-ontology-with-annotations", "false");
     options.put("annotate-inferred-axioms", "false");
     options.put("exclude-duplicate-axioms", "false");
-    options.put("exclude-external-entities", "false");
-    options.put("exclude-owl-thing", "false");
     options.put("equivalent-classes-allowed", ALL.written());
     options.put("prevent-invalid-references", "false");
-    options.put("preserve-annotated-axioms", "false");
 
     return options;
   }
@@ -243,32 +237,7 @@ public class ReasonOperation {
       propertyIRI = IRI.create("http://www.geneontology.org/formats/oboInOwl#is_inferred");
       value = dataFactory.getOWLLiteral("true");
     }
-
-    // get all entities that 'belong' to the main ontology
-    // see: https://github.com/ontodev/robot/issues/296
-    Set<OWLEntity> ontologyEntities =
-        ontology
-            .getAxioms(AxiomType.DECLARATION)
-            .stream()
-            .map(a -> a.getEntity())
-            .collect(Collectors.toSet());
     for (OWLAxiom a : newAxiomOntology.getAxioms()) {
-      if (OptionsHelper.optionIsTrue(options, "exclude-external-entities")) {
-        if (a instanceof OWLClassAxiom) {
-          boolean overlapsSignature = false;
-          for (OWLClass c : a.getClassesInSignature()) {
-            if (ontologyEntities.contains(c)) {
-              overlapsSignature = true;
-              break;
-            }
-          }
-          if (!overlapsSignature) {
-            logger.debug("Excluding axiom as class signatures do not overlap: " + a);
-            continue;
-          }
-        }
-      }
-
       if (OptionsHelper.optionIsTrue(options, "exclude-duplicate-axioms")) {
         // if this option is passed, do not add any axioms that are
         // duplicates of existing axioms present at initial state.
@@ -297,7 +266,7 @@ public class ReasonOperation {
     }
 
     if (OptionsHelper.optionIsTrue(options, "remove-redundant-subclass-axioms")) {
-      removeRedundantSubClassAxioms(reasoner, options);
+      removeRedundantSubClassAxioms(reasoner);
     }
     logger.info("Ontology has {} axioms after all reasoning steps.", ontology.getAxioms().size());
 
@@ -316,10 +285,8 @@ public class ReasonOperation {
    *
    * @param reasoner an OWL reasoner, initialized with a root ontology; the ontology will be
    *     modified
-   * @param options
    */
-  public static void removeRedundantSubClassAxioms(
-      OWLReasoner reasoner, Map<String, String> options) {
+  public static void removeRedundantSubClassAxioms(OWLReasoner reasoner) {
     logger.info("Removing redundant subclass axioms...");
     OWLOntology ontology = reasoner.getRootOntology();
     OWLOntologyManager manager = ontology.getOWLOntologyManager();
@@ -345,12 +312,8 @@ public class ReasonOperation {
       // and the superclass is not in the set of inferred super classes,
       // then remove that axiom.
       for (OWLSubClassOfAxiom subClassAxiom : ontology.getSubClassAxiomsForSubClass(thisClass)) {
-        if (OptionsHelper.optionIsTrue(options, "preserve-annotated-axioms")) {
-
-          if (subClassAxiom.getAnnotations().size() > 0) {
-            // TODO make this configurable
-            continue;
-          }
+        if (subClassAxiom.getAnnotations().size() > 0) {
+          continue;
         }
         if (subClassAxiom.getSuperClass().isAnonymous()) {
           continue;
diff --git a/robot-core/src/main/java/org/obolibrary/robot/ReduceOperation.java b/robot-core/src/main/java/org/obolibrary/robot/ReduceOperation.java
index b391866b..f6be9ad0 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/ReduceOperation.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/ReduceOperation.java
@@ -67,7 +67,7 @@ public class ReduceOperation {
    */
   public static Map<String, String> getDefaultOptions() {
     Map<String, String> options = new HashMap<String, String>();
-    options.put("preserve-annotated-axioms", "false");
+    // options.put("remove-redundant-subclass-axioms", "true");
     return options;
   }
 
@@ -165,11 +165,10 @@ public class ReduceOperation {
 
     Set<OWLSubClassOfAxiom> rmAxioms = new HashSet<>();
     for (OWLSubClassOfAxiom ax : assertedSubClassAxioms) {
-      if (OptionsHelper.optionIsTrue(options, "preserve-annotated-axioms")) {
-        if (ax.getAnnotations().size() > 0) {
-          logger.debug("Protecting axiom with annotations: " + ax);
-          continue;
-        }
+      // TO DO: make configurable
+      if (ax.getAnnotations().size() > 0) {
+        logger.debug("Protecting axiom with annotations: " + ax);
+        continue;
       }
 
       logger.debug("Testing: " + ax);
diff --git a/robot-core/src/main/java/org/obolibrary/robot/ReportOperation.java b/robot-core/src/main/java/org/obolibrary/robot/ReportOperation.java
index c8e388ba..ebd148e5 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/ReportOperation.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/ReportOperation.java
@@ -1,369 +1,64 @@
 package org.obolibrary.robot;
 
-import com.hp.hpl.jena.query.QuerySolution;
-import com.hp.hpl.jena.query.ResultSet;
-import com.hp.hpl.jena.sparql.core.DatasetGraph;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import org.apache.commons.io.FileUtils;
-import org.obolibrary.robot.checks.Report;
-import org.obolibrary.robot.checks.Violation;
+import org.obolibrary.robot.checks.InvalidReferenceChecker;
+import org.obolibrary.robot.checks.InvalidReferenceViolation;
 import org.semanticweb.owlapi.model.OWLOntology;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Report issues with an ontology using a series of QC SPARQL queries.
+ * Report issues with an ontology.
  *
- * @author <a href="mailto:rctauber@gmail.com">Becky Tauber</a>
- * @author <a href="mailto:james@overton.ca">James A. Overton</a>
+ * <p>Currently this is minimal but we imagine later creating an extensive 'report card' for an
+ * ontology, describing ways to make the ontology conform to OBO conventions
+ *
+ * <p>TODO: decide on report structure. Perhaps JSON-LD? Create vocabulary for report violations?
  */
 public class ReportOperation {
-
-  /** Directory for queries. */
-  private static final String queryDir = "report_queries";
-
   /** Logger. */
   private static final Logger logger = LoggerFactory.getLogger(ReportOperation.class);
 
-  /** Namespace for general input error messages. */
-  private static final String NS = "report#";
-
-  /** Error message when user profiles an invalid fail-on level. */
-  private static final String failOnError = NS + "FAIL ON ERROR '%s' is not a valid fail-on level.";
-
-  /** Error message when user provides a rule level other than INFO, WARN, or ERROR. */
-  private static final String reportLevelError =
-      NS + "REPORT LEVEL ERROR '%s' is not a valid reporting level.";
-
-  /** Reporting level INFO. */
-  private static final String INFO = "INFO";
-
-  /** Reporting level WARN. */
-  private static final String WARN = "WARN";
-
-  /** Reporting level ERROR. */
-  private static final String ERROR = "ERROR";
-
-  /**
-   * Given an ontology, a profile path (or null), an output path (or null), and a report format (or
-   * null) report on the ontology using the rules within the profile and write results to the output
-   * path. If profile is null, use the default profile in resources. If the output path is null,
-   * write results to console. If the format is null, write results in TSV format.
-   *
-   * @param ontology OWLOntology to report on
-   * @param profilePath user profile file path to use, or null
-   * @param outputPath string path to write report file to, or null
-   * @param format string format for the output report (TSV or YAML), or null
-   * @throws Exception on any error
-   */
-  public static boolean report(
-      OWLOntology ontology, String profilePath, String outputPath, String format, String failOn)
-      throws Exception {
-    // The profile is a map of rule name and reporting level
-    Map<String, String> profile = getProfile(profilePath);
-    // The queries is a map of rule name and query string
-    Map<String, String> queries = getQueryStrings(profile.keySet());
-
-    Report report = new Report();
-    DatasetGraph dsg = QueryOperation.loadOntology(ontology);
-    for (String queryName : queries.keySet()) {
-      String fullQueryString = queries.get(queryName);
-      String queryString;
-      // Remove the headers
-      if (fullQueryString.startsWith("#")) {
-        queryString = fullQueryString.substring(fullQueryString.indexOf("PREFIX"));
-      } else {
-        queryString = fullQueryString;
-      }
-      report.addViolations(queryName, profile.get(queryName), getViolations(dsg, queryString));
-    }
-
-    Integer violationCount = report.getTotalViolations();
-    if (violationCount != 0) {
-      System.out.println("Violations: " + violationCount);
-      System.out.println("-----------------");
-      System.out.println("ERROR:      " + report.getTotalViolations(ERROR));
-      System.out.println("WARN:       " + report.getTotalViolations(WARN));
-      System.out.println("INFO:       " + report.getTotalViolations(INFO));
-    } else {
-      System.out.println("No violations found.");
-    }
-
-    // System.out.println(report.getIRIs());
-    String result;
-    if (format != null && format.equalsIgnoreCase("yaml")) {
-      result = report.toYAML();
-    } else {
-      // Default to TSV if nothing was provided, or if it is not YAML
-      result = report.toTSV();
-    }
-    if (outputPath != null) {
-      // If output is provided, write to that file
-      try (FileWriter fw = new FileWriter(outputPath);
-          BufferedWriter bw = new BufferedWriter(fw)) {
-        logger.debug("Writing report to: " + outputPath);
-        bw.write(result);
-      }
-    } else {
-      // Otherwise output to terminal
-      System.out.println(result);
-    }
-
-    // If a fail-on is provided, return false if there are violations of the given level
-    if (failOn.equalsIgnoreCase("none")) {
-      return true;
-    } else if (failOn.equalsIgnoreCase("error")) {
-      if (report.getTotalViolations(ERROR) > 0) {
-        return false;
-      }
-    } else if (failOn.equalsIgnoreCase("warn")) {
-      if ((report.getTotalViolations(ERROR) + report.getTotalViolations(WARN)) > 0) {
-        return false;
-      }
-    } else if (failOn.equalsIgnoreCase("info")) {
-      if (report.getTotalViolations() > 0) {
-        return false;
-      }
-    } else {
-      throw new IllegalArgumentException(String.format(failOnError, failOn));
-    }
-    return true;
-  }
-
   /**
-   * Given a set of rules (either as the default rule names or URL to a file), return a map of the
-   * rule names and the corresponding query strings.
+   * Return a map from option name to default option value, for all the available report options.
    *
-   * @param rules set of rules to get queries for
-   * @return map of rule name and query string
-   * @throws IOException on any issue reading the query file
-   * @throws URISyntaxException on issue converting URL to URI
+   * @return a map with default values for all available options
    */
-  private static Map<String, String> getQueryStrings(Set<String> rules)
-      throws IOException, URISyntaxException {
-    Set<String> defaultRules = new HashSet<>();
-    Set<String> userRules = new HashSet<>();
-    Map<String, String> queries = new HashMap<>();
-    for (String rule : rules) {
-      if (rule.startsWith("file://")) {
-        userRules.add(rule);
-      } else {
-        defaultRules.add(rule);
-      }
-    }
-    queries.putAll(getDefaultQueryStrings(defaultRules));
-    queries.putAll(getUserQueryStrings(userRules));
-    return queries;
-  }
+  public static Map<String, String> getDefaultOptions() {
+    Map<String, String> options = new HashMap<String, String>();
 
-  /**
-   * Given a set of user-provided query paths for a set of rules, return a map of the rule names and
-   * the file (query) contents.
-   *
-   * @param rules set of file paths to user query files
-   * @return map of rule name and query string
-   * @throws URISyntaxException on issue converting file path URL to URI
-   * @throws IOException on any issue reading the file
-   */
-  private static Map<String, String> getUserQueryStrings(Set<String> rules)
-      throws URISyntaxException, IOException {
-    Map<String, String> queries = new HashMap<>();
-    for (String rule : rules) {
-      File file = new File(new URL(rule).toURI());
-      queries.put(rule, FileUtils.readFileToString(file));
-    }
-    return queries;
+    return options;
   }
 
   /**
-   * Given a set of default rules, return a map of the rule names and query strings. This is a
-   * "brute-force" method to retrieve default query file contents from packaged jar.
+   * reports ontology
    *
-   * @param rules subset of the default rules to include
-   * @return map of rule name and query string
-   * @throws URISyntaxException on issue converting path to URI
-   * @throws IOException on any issue with accessing files or file contents
+   * @param ontology the OWLOntology to report
+   * @param iohelper IOHelper to work with ontology
    */
-  private static Map<String, String> getDefaultQueryStrings(Set<String> rules)
-      throws IOException, URISyntaxException {
-    URL dirURL = ReportOperation.class.getClassLoader().getResource(queryDir);
-    Map<String, String> queries = new HashMap<>();
-    // Handle simple file path, probably accessed during testing
-    if (dirURL != null && dirURL.getProtocol().equals("file")) {
-      String[] queryFilePaths = new File(dirURL.toURI()).list();
-      if (queryFilePaths == null || queryFilePaths.length == 0) {
-        throw new IOException(
-            "Cannot access report query files. There are no files in the directory.");
-      }
-      for (String qPath : queryFilePaths) {
-        String ruleName = qPath.substring(qPath.lastIndexOf("/")).split(".")[0];
-        // Only add it to the queries if the rule set contains that rule
-        // If rules == null, include all rules
-        if (rules == null || rules.contains(ruleName)) {
-          queries.put(ruleName, FileUtils.readFileToString(new File(qPath)));
-        }
-      }
-      return queries;
-    }
-    // Handle inside jar file
-    // This will be the case any time someone runs ROBOT via CLI
-    if (dirURL == null) {
-      String cls = ReportOperation.class.getName().replace(".", "/") + ".class";
-      dirURL = ReportOperation.class.getClassLoader().getResource(cls);
-    }
-    String protocol;
-    try {
-      protocol = dirURL.getProtocol();
-    } catch (NullPointerException e) {
-      throw new IOException(
-          "Cannot access report query files in JAR. The directory address has no protocol.");
-    }
-    if (protocol.equals("jar")) {
-      String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!"));
-      // Get all entries in jar
-      Enumeration<JarEntry> entries;
-      try (JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"))) {
-        entries = jar.entries();
-        if (!entries.hasMoreElements()) {
-          throw new IOException(
-              "Cannot access report query files in JAR. There are no entries in the JAR.");
-        }
-        // Track rules that have successfully been retrieved
-        while (entries.hasMoreElements()) {
-          JarEntry resource = entries.nextElement();
-          String resourceName = resource.getName();
-          if (resourceName.startsWith(queryDir) && !resourceName.endsWith("/")) {
-            // Get just the rule name
-            String ruleName =
-                resourceName.substring(
-                    resourceName.lastIndexOf("/") + 1, resourceName.indexOf(".rq"));
-            // Only add it to the queries if the rule set contains that rule
-            // If rules == null, include all rules
-            if (rules == null || rules.contains(ruleName)) {
-              InputStream is = jar.getInputStream(resource);
-              StringBuilder sb = new StringBuilder();
-              try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
-                String chr;
-                while ((chr = br.readLine()) != null) {
-                  sb.append(chr);
-                }
-              }
-              queries.put(ruleName, sb.toString());
-            }
-          }
-        }
-      }
-      return queries;
-    }
-    // If nothing has been returned, it's an exception
-    throw new IOException("Cannot access report query files.");
+  public static void report(OWLOntology ontology, IOHelper iohelper) {
+    report(ontology, iohelper, getDefaultOptions());
   }
 
   /**
-   * Given the path to a profile file (or null), return the rules and their levels (info, warn, or
-   * error). If profile == null, return the default profile in the resources.
+   * reports ontology
    *
-   * @param path path to profile, or null
-   * @return map of rule name and its reporting level
-   * @throws IOException on any issue reading the profile file
+   * @param ontology the OWLOntology to report
+   * @param iohelper IOHelper to work with ontology
+   * @param options map of report options
    */
-  private static Map<String, String> getProfile(String path) throws IOException {
-    Map<String, String> profile = new HashMap<>();
-    InputStream is;
-    // If the file was not provided, get the default
-    if (path == null) {
-      is = ReportOperation.class.getResourceAsStream("/report_profile.txt");
-    } else {
-      is = new FileInputStream(new File(path));
-    }
-    try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
-      String line;
-      while ((line = br.readLine()) != null) {
-        String[] split = line.trim().split("\t");
-        String level = split[0].toUpperCase();
-        // The level should be: INFO, WARN, or ERROR
-        if (!INFO.equals(level) && !WARN.equals(level) && !ERROR.equals(level)) {
-          throw new IllegalArgumentException(String.format(reportLevelError, split[0]));
-        }
-        String rule = split[1];
-        profile.put(rule, level);
-      }
-    }
-    return profile;
-  }
+  public static void report(OWLOntology ontology, IOHelper iohelper, Map<String, String> options) {
 
-  /**
-   * Given a QuerySolution and a String var to retrieve, return the value of the the var. If the var
-   * is not in the solution, return null.
-   *
-   * @param qs QuerySolution
-   * @param var String variable to retrieve from result
-   * @return string or null
-   */
-  private static String getQueryResultOrNull(QuerySolution qs, String var) {
-    try {
-      return qs.get(var).toString();
-    } catch (NullPointerException e) {
-      return null;
+    Set<InvalidReferenceViolation> refViolations =
+        InvalidReferenceChecker.getInvalidReferenceViolations(ontology, true);
+    for (InvalidReferenceViolation v : refViolations) {
+      System.err.println("REFERENCE VIOLATION: " + v);
     }
-  }
-
-  /**
-   * Given an ontology as a DatasetGraph and a query as a CheckerQuery, return the violations found
-   * by that query.
-   *
-   * @param dsg the ontology
-   * @param query the query
-   * @return List of Violations
-   */
-  private static List<Violation> getViolations(DatasetGraph dsg, String query) {
-    ResultSet violationSet = QueryOperation.execQuery(dsg, query);
-
-    Map<String, Violation> violations = new HashMap<>();
-    Violation violation;
-
-    while (violationSet.hasNext()) {
-      QuerySolution qs = violationSet.next();
-      // entity should never be null
-      String entity = getQueryResultOrNull(qs, "entity");
-      // skip RDFS and OWL terms
-      if (entity.contains("/rdf-schema#") || entity.contains("/owl#")) {
-        continue;
-      }
-      // find out if a this Violation already exists for this entity
-      violation = violations.get(entity);
-      // if the entity hasn't been added, create a new Violation
-      if (violation == null) {
-        violation = new Violation(entity);
-      }
-      // try and get a property and value from the query
-      String property = getQueryResultOrNull(qs, "property");
-      String value = getQueryResultOrNull(qs, "value");
-      // add details to Violation
-      if (property != null) {
-        violation.addStatement(property, value);
-      }
-      violations.put(entity, violation);
+    int totalViolations = refViolations.size();
+    if (totalViolations > 0) {
+      System.err.println("REPORT FAILED! Violations: " + totalViolations);
     }
-    return new ArrayList<>(violations.values());
   }
 }
diff --git a/robot-core/src/main/java/org/obolibrary/robot/TemplateHelper.java b/robot-core/src/main/java/org/obolibrary/robot/TemplateHelper.java
index e5d71508..fa8dda2c 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/TemplateHelper.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/TemplateHelper.java
@@ -15,8 +15,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 import org.apache.commons.io.FilenameUtils;
 import org.semanticweb.owlapi.model.IRI;
 import org.semanticweb.owlapi.model.OWLAnnotation;
@@ -80,30 +78,6 @@ public class TemplateHelper {
   /** OWL Namespace. */
   private static String owl = "http://www.w3.org/2002/07/owl#";
 
-  /**
-   * Given a set of rows, the row number, and the column number, get the content in the column for
-   * the row. If there are any issues, return an empty string. If the cell is empty, return null.
-   *
-   * @param rows list of rows (lists of strings)
-   * @param row row number to get ID of
-   * @param column column number
-   * @return content, null, or empty string.
-   */
-  public static String getCellContent(List<List<String>> rows, int row, Integer column) {
-    String id = null;
-    if (column != null && column != -1) {
-      try {
-        id = rows.get(row).get(column);
-      } catch (IndexOutOfBoundsException e) {
-        return "";
-      }
-      if (id == null || id.trim().isEmpty()) {
-        return "";
-      }
-    }
-    return id;
-  }
-
   /**
    * Create an OWLAnnotation based on the template string and cell value.
    *
@@ -574,30 +548,4 @@ public class TemplateHelper {
     csv.close();
     return rows;
   }
-
-  /**
-   * Given a template string, a cell value, and an empty list, fill the list with any number of
-   * values based on a SPLIT character, then return the template string without SPLIT. If there are
-   * no SPLITs, only add the original cell to the values.
-   *
-   * @param template template string
-   * @param cell cell contents
-   * @param values empty list to fill
-   * @return template string without SPLIT
-   */
-  public static String processSplit(String template, String cell, List<String> values) {
-    // If the template contains SPLIT=X,
-    // then split the cell value
-    // and remove that string from the template.
-    Pattern splitter = Pattern.compile("SPLIT=(\\S+)");
-    Matcher matcher = splitter.matcher(template);
-    if (matcher.find()) {
-      Pattern split = Pattern.compile(Pattern.quote(matcher.group(1)));
-      values.addAll(Arrays.asList(split.split(cell)));
-      template = matcher.replaceAll("").trim();
-    } else {
-      values.add(cell);
-    }
-    return template;
-  }
 }
diff --git a/robot-core/src/main/java/org/obolibrary/robot/TemplateOperation.java b/robot-core/src/main/java/org/obolibrary/robot/TemplateOperation.java
index a9856308..b938ef7a 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/TemplateOperation.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/TemplateOperation.java
@@ -1,7 +1,15 @@
 package org.obolibrary.robot;
 
 import com.google.common.collect.Sets;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import org.semanticweb.owlapi.apibinding.OWLManager;
 import org.semanticweb.owlapi.manchestersyntax.parser.ManchesterOWLSyntaxClassExpressionParser;
 import org.semanticweb.owlapi.manchestersyntax.renderer.ParserException;
@@ -382,8 +390,19 @@ public class TemplateOperation {
         continue;
       }
 
-      List<String> values = new ArrayList<>();
-      template = TemplateHelper.processSplit(template, cell, values);
+      // If the template contains SPLIT=X,
+      // then split the cell value
+      // and remove that string from the template.
+      List<String> values = new ArrayList<String>();
+      Pattern splitter = Pattern.compile("SPLIT=(\\S+)");
+      Matcher matcher = splitter.matcher(template);
+      if (matcher.find()) {
+        Pattern split = Pattern.compile(Pattern.quote(matcher.group(1)));
+        values = new ArrayList<String>(Arrays.asList(split.split(cell)));
+        template = matcher.replaceAll("").trim();
+      } else {
+        values.add(cell);
+      }
 
       // Create OWLAnnotation objects
       // Link any axiom annotations in a map
@@ -563,54 +582,50 @@ public class TemplateOperation {
       if (cell.trim().isEmpty()) {
         continue;
       }
-
-      List<String> values = new ArrayList<>();
-      template = TemplateHelper.processSplit(template, cell, values);
-
-      for (String value : values) {
-        String content = QuotedEntityChecker.wrap(value);
-        if (template.equals("CLASS_TYPE")) {
-          classType = cell.trim().toLowerCase();
-        } else if (template.startsWith("C ")) {
-          String sub = template.substring(2).trim().replaceAll("%", content);
-          try {
-            lastExpression = parser.parse(sub);
-          } catch (ParserException e) {
-            throw new Exception(
-                String.format(
-                    parseError, tableName, row + 1, id, column + 1, header, sub, e.getMessage()));
-          }
-          classExpressions.add(lastExpression);
-        } else if (template.startsWith("CI")) {
-          IRI iri = ioHelper.createIRI(cell);
-          lastExpression = dataFactory.getOWLClass(iri);
-          classExpressions.add(lastExpression);
-        } else if (template.startsWith(">C ")) {
-          if (lastExpression == null) {
-            throw new Exception(
-                String.format(
-                    axiomAnnotationError,
-                    tableName,
-                    row + 1,
-                    id,
-                    column + 1,
-                    template,
-                    cell,
-                    "a class expression"));
-          }
-          Set<OWLAnnotation> annotations;
-          if (annotatedExpressions.containsKey(lastExpression)) {
-            annotations = annotatedExpressions.get(lastExpression);
-          } else {
-            annotations = new HashSet<>();
-          }
-          annotations.add(
-              TemplateHelper.getStringAnnotation(checker, template.substring(1).trim(), cell));
-          annotatedExpressions.put(lastExpression, annotations);
-          // Remove to prevent duplication
-          if (classExpressions.contains(lastExpression)) {
-            classExpressions.remove(lastExpression);
-          }
+      String content = QuotedEntityChecker.wrap(cell);
+
+      if (template.equals("CLASS_TYPE")) {
+        classType = cell.trim().toLowerCase();
+      } else if (template.startsWith("C ")) {
+        String sub = template.substring(2).trim().replaceAll("%", content);
+        try {
+          lastExpression = parser.parse(sub);
+        } catch (ParserException e) {
+          throw new Exception(
+              String.format(
+                  parseError, tableName, row + 1, id, column + 1, header, sub, e.getMessage()),
+              e);
+        }
+        classExpressions.add(lastExpression);
+      } else if (template.startsWith("CI")) {
+        IRI iri = ioHelper.createIRI(cell);
+        lastExpression = dataFactory.getOWLClass(iri);
+        classExpressions.add(lastExpression);
+      } else if (template.startsWith(">C ")) {
+        if (lastExpression == null) {
+          throw new Exception(
+              String.format(
+                  axiomAnnotationError,
+                  tableName,
+                  row + 1,
+                  id,
+                  column + 1,
+                  template,
+                  cell,
+                  "a class expression"));
+        }
+        Set<OWLAnnotation> annotations;
+        if (annotatedExpressions.containsKey(lastExpression)) {
+          annotations = annotatedExpressions.get(lastExpression);
+        } else {
+          annotations = new HashSet<>();
+        }
+        annotations.add(
+            TemplateHelper.getStringAnnotation(checker, template.substring(1).trim(), cell));
+        annotatedExpressions.put(lastExpression, annotations);
+        // Remove to prevent duplication
+        if (classExpressions.contains(lastExpression)) {
+          classExpressions.remove(lastExpression);
         }
       }
     }
diff --git a/robot-core/src/main/java/org/obolibrary/robot/checks/Report.java b/robot-core/src/main/java/org/obolibrary/robot/checks/Report.java
deleted file mode 100644
index 2efb631f..00000000
--- a/robot-core/src/main/java/org/obolibrary/robot/checks/Report.java
+++ /dev/null
@@ -1,291 +0,0 @@
-package org.obolibrary.robot.checks;
-
-import java.net.URL;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import org.obolibrary.robot.IOHelper;
-import org.obolibrary.robot.UnmergeOperation;
-import org.semanticweb.owlapi.model.IRI;
-import org.semanticweb.owlapi.model.PrefixManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Report {
-
-  /** Logger. */
-  private static final Logger logger = LoggerFactory.getLogger(UnmergeOperation.class);
-
-  /** Reporting level INFO. */
-  private static final String INFO = "INFO";
-
-  /** Reporting level WARN. */
-  private static final String WARN = "WARN";
-
-  /** Reporting level ERROR. */
-  private static final String ERROR = "ERROR";
-
-  /** Map of rules and the violations for INFO level. */
-  public Map<String, List<Violation>> info;
-
-  /** Map of rules and the violations for WARN level. */
-  public Map<String, List<Violation>> warn;
-
-  /** Map of rules and the violations for ERROR level. */
-  public Map<String, List<Violation>> error;
-
-  /** Count of violations for INFO. */
-  private Integer infoCount;
-
-  /** Count of violations for WARN. */
-  private Integer warnCount;
-
-  /** Count of violations for ERROR. */
-  private Integer errorCount;
-
-  /** Create a new report object. */
-  public Report() {
-    info = new HashMap<>();
-    warn = new HashMap<>();
-    error = new HashMap<>();
-
-    infoCount = 0;
-    warnCount = 0;
-    errorCount = 0;
-  }
-
-  /**
-   * Given a rule name, it's reporting level, and a list of the violations from the ontology, add
-   * the violations to the correct map.
-   *
-   * @param ruleName name of rule
-   * @param level reporting level of rule
-   * @param violations list of violations from this rule
-   */
-  public void addViolations(String ruleName, String level, List<Violation> violations) {
-    logger.debug("violation found: " + ruleName);
-    if (INFO.equals(level)) {
-      info.put(ruleName, violations);
-      infoCount += violations.size();
-    } else if (WARN.equals(level)) {
-      warn.put(ruleName, violations);
-      warnCount += violations.size();
-    } else if (ERROR.equals(level)) {
-      error.put(ruleName, violations);
-      errorCount += violations.size();
-    }
-    // Otherwise do nothing
-  }
-
-  /**
-   * Return all the IRI strings in the current Violations.
-   *
-   * @return a set of IRI strings
-   */
-  public Set<String> getIRIs() {
-    Set<String> iris = new HashSet<String>();
-    iris.addAll(getIRIs(error));
-    iris.addAll(getIRIs(warn));
-    iris.addAll(getIRIs(info));
-    return iris;
-  }
-
-  /**
-   * Return all the IRI strings in the given list of Violations.
-   *
-   * @param violationSets map of rule name and violations
-   * @return a set of IRI strings
-   */
-  public Set<String> getIRIs(Map<String, List<Violation>> violationSets) {
-    Set<String> iris = new HashSet<String>();
-
-    for (Entry<String, List<Violation>> vs : violationSets.entrySet()) {
-      for (Violation v : vs.getValue()) {
-        iris.add(v.subject);
-        for (Entry<String, List<String>> statement : v.statements.entrySet()) {
-          iris.add(statement.getKey());
-          for (String value : statement.getValue()) {
-            if (!iris.contains(value)) {
-              try {
-                iris.add(IRI.create(new URL(value)).toString());
-              } catch (Exception e) {
-                // do nothing
-              }
-            }
-          }
-        }
-      }
-    }
-
-    return iris;
-  }
-
-  /**
-   * Return the total violations from reporting.
-   *
-   * @return number of violations
-   */
-  public Integer getTotalViolations() {
-    return infoCount + warnCount + errorCount;
-  }
-
-  /**
-   * Given a reporting level, return the number of violations.
-   *
-   * @param level reporting level
-   * @return number of violations
-   */
-  public Integer getTotalViolations(String level) {
-    if (INFO.equals(level)) {
-      return infoCount;
-    } else if (WARN.equals(level)) {
-      return warnCount;
-    } else if (ERROR.equals(level)) {
-      return errorCount;
-    } else {
-      logger.error("Not a valid report level: " + level);
-      return 0;
-    }
-  }
-
-  /**
-   * Return the report in TSV format.
-   *
-   * @return TSV string
-   */
-  public String toTSV() {
-    StringBuilder sb = new StringBuilder();
-    sb.append("Level\tRule Name\tSubject\tProperty\tValue\n");
-    sb.append(tsvHelper(ERROR, error));
-    sb.append(tsvHelper(WARN, warn));
-    sb.append(tsvHelper(INFO, info));
-    return sb.toString();
-  }
-
-  /**
-   * Return the report in YAML format.
-   *
-   * @return YAML string
-   */
-  public String toYAML() {
-    StringBuilder sb = new StringBuilder();
-    sb.append(yamlHelper(ERROR, error));
-    sb.append(yamlHelper(WARN, warn));
-    sb.append(yamlHelper(INFO, info));
-    return sb.toString();
-  }
-
-  /**
-   * Given a prefix manager and an IRI as a string, return the CURIE if the prefix is available.
-   * Otherwise, return the IRI as string.
-   *
-   * @param pm Prefix Manager to use
-   * @param iriString IRI to convert to CURIE
-   * @return CURIE or full IRI as string
-   */
-  private static String maybeGetCURIE(PrefixManager pm, String iriString) {
-    IRI iri = IRI.create(iriString);
-    if (iri != null) {
-      String curie = pm.getPrefixIRI(iri);
-      if (curie != null) {
-        return curie;
-      }
-    }
-    return iriString;
-  }
-
-  /**
-   * Given a reporting level and a map of rules and violations, build a TSV output.
-   *
-   * @param level reporting level
-   * @param violationSets map of rules and violations
-   * @return TSV string representation of the violations
-   */
-  private String tsvHelper(String level, Map<String, List<Violation>> violationSets) {
-    // Get a prefix manager for creating CURIEs
-    PrefixManager pm = new IOHelper().getPrefixManager();
-    if (violationSets.isEmpty()) {
-      return "";
-    }
-    StringBuilder sb = new StringBuilder();
-    for (Entry<String, List<Violation>> vs : violationSets.entrySet()) {
-      String ruleName = vs.getKey();
-      for (Violation v : vs.getValue()) {
-        String subject = maybeGetCURIE(pm, v.subject);
-        for (Entry<String, List<String>> statement : v.statements.entrySet()) {
-          String property = maybeGetCURIE(pm, statement.getKey());
-          for (String value : statement.getValue()) {
-            if (value == null) {
-              value = "";
-            } else {
-              value = maybeGetCURIE(pm, value);
-            }
-            sb.append(level + "\t");
-            sb.append(ruleName + "\t");
-            sb.append(subject + "\t");
-            sb.append(property + "\t");
-            sb.append(value.replace("\t", " ").replace("\n", " ") + "\t");
-            sb.append("\n");
-          }
-        }
-      }
-    }
-    return sb.toString();
-  }
-
-  /**
-   * Given a reporting level and a map of rules and violations, build a YAML output.
-   *
-   * @param level reporting level
-   * @param violationSets map of rules and violations
-   * @return YAML string representation of the violations
-   */
-  private String yamlHelper(String level, Map<String, List<Violation>> violationSets) {
-    // Get a prefix manager for creating CURIEs
-    PrefixManager pm = new IOHelper().getPrefixManager();
-    if (violationSets.isEmpty()) {
-      return "";
-    }
-    StringBuilder sb = new StringBuilder();
-    sb.append("- level : '" + level + "'");
-    sb.append("\n");
-    sb.append("  violations :");
-    sb.append("\n");
-    for (Entry<String, List<Violation>> vs : violationSets.entrySet()) {
-      String ruleName = vs.getKey();
-      if (vs.getValue().isEmpty()) {
-        continue;
-      }
-      sb.append("  - rule : '" + ruleName + "'");
-      sb.append("\n");
-      for (Violation v : vs.getValue()) {
-        String subject = maybeGetCURIE(pm, v.subject);
-        sb.append("    - subject : '" + subject + "'");
-        sb.append("\n");
-        for (Entry<String, List<String>> statement : v.statements.entrySet()) {
-          String property = maybeGetCURIE(pm, statement.getKey());
-          sb.append("      property : '" + property + "':");
-          sb.append("\n");
-          if (statement.getValue().isEmpty()) {
-            continue;
-          }
-          sb.append("      values :");
-          sb.append("\n");
-          for (String value : statement.getValue()) {
-            if (value == null) {
-              value = "null";
-            } else {
-              value = maybeGetCURIE(pm, value);
-            }
-            sb.append("        - '" + value + "'");
-            sb.append("\n");
-          }
-        }
-      }
-    }
-    return sb.toString();
-  }
-}
diff --git a/robot-core/src/main/java/org/obolibrary/robot/checks/Violation.java b/robot-core/src/main/java/org/obolibrary/robot/checks/Violation.java
deleted file mode 100644
index 9188606f..00000000
--- a/robot-core/src/main/java/org/obolibrary/robot/checks/Violation.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.obolibrary.robot.checks;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class Violation {
-
-  public String subject;
-  public Map<String, List<String>> statements;
-
-  public Violation(String subject) {
-    this.subject = subject;
-    this.statements = new HashMap<>();
-  }
-
-  public void addStatement(String property, String value) {
-    List<String> values = new ArrayList<>();
-    if (statements.get(property) != null) {
-      values.addAll(statements.get(property));
-      values.add(value);
-    } else {
-      values = Arrays.asList(value);
-    }
-    statements.put(property, values);
-  }
-}
diff --git a/robot-core/src/main/resources/blazegraph.properties b/robot-core/src/main/resources/blazegraph.properties
deleted file mode 100644
index b36dfbe3..00000000
--- a/robot-core/src/main/resources/blazegraph.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-# changing the axiom model to none essentially disables all inference
-com.bigdata.rdf.store.AbstractTripleStore.axiomsClass=com.bigdata.rdf.axioms.NoAxioms
-com.bigdata.rdf.store.AbstractTripleStore.quads=true
-com.bigdata.rdf.store.AbstractTripleStore.statementIdentifiers=false
-
-# turn off automatic inference in the SAIL
-com.bigdata.rdf.sail.truthMaintenance=false
-
-# turn off the free text index
-com.bigdata.rdf.store.AbstractTripleStore.textIndex=false
-
-com.bigdata.rdf.sail.bufferCapacity=100000
-com.bigdata.journal.AbstractJournal.bufferMode=DiskRW
\ No newline at end of file
diff --git a/robot-core/src/main/resources/report_profile.txt b/robot-core/src/main/resources/report_profile.txt
deleted file mode 100644
index e1f6c912..00000000
--- a/robot-core/src/main/resources/report_profile.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-WARN	annotation_whitespace
-ERROR	deprecated_class_reference
-ERROR	duplicate_definition
-WARN	duplicate_exact_synonym
-WARN	duplicate_label_synonym
-ERROR	duplicate_label
-WARN	duplicate_scoped_synonym
-WARN	equivalent_pair
-WARN	invalid_xref
-ERROR	label_formatting
-ERROR	label_whitespace
-INFO	lowercase_definition
-WARN	missing_definition
-ERROR	missing_label
-WARN	missing_obsolete_label
-INFO	missing_superclass
-ERROR	misused_obsolete_label
-WARN	multiple_asserted_superclasses
-ERROR	multiple_definitions
-ERROR	multiple_labels
-ERROR	ontology_metadata
diff --git a/robot-core/src/main/resources/report_queries/annotation_whitespace.rq b/robot-core/src/main/resources/report_queries/annotation_whitespace.rq
deleted file mode 100644
index 18201506..00000000
--- a/robot-core/src/main/resources/report_queries/annotation_whitespace.rq
+++ /dev/null
@@ -1,19 +0,0 @@
-# # Annotation Whitespace
-#
-# Problem: An annotation has leading or trailing whitespace, usually a single space.
-#
-# Solution: Re-format the annotation to remove additional whitespace.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  {?property a owl:AnnotationProperty .
-   ?entity ?property ?value .
-   FILTER STRENDS(str(?value), " ")}
-  UNION
-  {?property a owl:AnnotationProperty .
-   ?entity ?property ?value .
-   FILTER STRSTARTS(str(?value), " ")}
-}
diff --git a/robot-core/src/main/resources/report_queries/deprecated_class_reference.rq b/robot-core/src/main/resources/report_queries/deprecated_class_reference.rq
deleted file mode 100644
index 95a0a14b..00000000
--- a/robot-core/src/main/resources/report_queries/deprecated_class_reference.rq
+++ /dev/null
@@ -1,41 +0,0 @@
-# # Deprecated Class Reference
-#
-# Problem: A deprecated class is used in a logical axiom. A deprecated class can be the child of another class (e.g. ObsoleteClass), but it cannot have children or be used in blank nodes or equivalent class statements. Additionally, a deprecated class should not have any equivalent classes or anonymous parents.
-#
-# Solution: Replace deprecated class.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  {
-   VALUES ?property {
-     owl:equivalentClass
-     rdfs:subClassOf
-   }
-   ?entity owl:deprecated ?dep .
-   FILTER regex(str(?dep), "true") .
-   ?value ?property ?entity .
-   FILTER (!STRENDS(str(?property), "owl#deprecated"))
-  }
-  UNION
-  {
-   ?entity owl:deprecated ?dep .
-   FILTER regex(str(?dep), "true") .
-   ?entity ?property ?value .
-   FILTER (!STRENDS(str(?property), "owl#deprecated")) .
-   FILTER NOT EXISTS { ?property a owl:AnnotationProperty }
-   FILTER NOT EXISTS {
-     ?entity rdfs:subClassOf ?value .
-     FILTER (!isBlank(?value))
-   }
-   FILTER NOT EXISTS {
-     ?entity rdfs:subPropertyOf ?value .
-     FILTER (!isBlank(?value))
-   }
-  }
-}
diff --git a/robot-core/src/main/resources/report_queries/duplicate_definition.rq b/robot-core/src/main/resources/report_queries/duplicate_definition.rq
deleted file mode 100644
index 6a8a5e21..00000000
--- a/robot-core/src/main/resources/report_queries/duplicate_definition.rq
+++ /dev/null
@@ -1,18 +0,0 @@
-# # Duplicate Definition
-#
-# Problem: An entity shares an exact definition with another entity.
-#
-# Solution: Update the definition to reflect the entities, or determine if the entities are the same.
-
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {obo:IAO_0000115}
-  ?entity obo:IAO_0000115 ?value .
-  ?entity2 obo:IAO_0000115 ?value .
-  FILTER (?entity != ?entity2) .
-  FILTER (!isBlank(?entity))
-}
-ORDER BY ?value
diff --git a/robot-core/src/main/resources/report_queries/duplicate_exact_synonym.rq b/robot-core/src/main/resources/report_queries/duplicate_exact_synonym.rq
deleted file mode 100644
index 6aa4c2fc..00000000
--- a/robot-core/src/main/resources/report_queries/duplicate_exact_synonym.rq
+++ /dev/null
@@ -1,20 +0,0 @@
-# # Duplicate Exact Synonym
-#
-# Problem: Two entities share an exact synonym. This causes ambiguity.
-#
-# Solution: Avoid ambiguity by assigning unique exact synonyms or changing the exact synonym to a different annotation (e.g. broad synonym).
-
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {
-    obo:IAO_0000118
-    oboInOwl:hasExactSynonym
-  }
-  ?entity ?property ?value .
-  ?entity2 ?property ?value .
-  FILTER (?entity != ?entity2)
-}
diff --git a/robot-core/src/main/resources/report_queries/duplicate_label.rq b/robot-core/src/main/resources/report_queries/duplicate_label.rq
deleted file mode 100644
index a719a36e..00000000
--- a/robot-core/src/main/resources/report_queries/duplicate_label.rq
+++ /dev/null
@@ -1,17 +0,0 @@
-# # Duplicate Label
-#
-# Problem: Two different subjects have been assigned the same label. This causes ambiguity.
-#
-# Solution: Avoid ambiguity by assigning distinct labels to each subject.
-
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {rdfs:label}
-  ?entity ?property ?value .
-  ?entity2 ?property ?value .
-  FILTER (?entity != ?entity2)
-  FILTER (!isBlank(?entity))
-}
-ORDER BY ?value
diff --git a/robot-core/src/main/resources/report_queries/duplicate_label_synonym.rq b/robot-core/src/main/resources/report_queries/duplicate_label_synonym.rq
deleted file mode 100644
index e6edb3b9..00000000
--- a/robot-core/src/main/resources/report_queries/duplicate_label_synonym.rq
+++ /dev/null
@@ -1,22 +0,0 @@
-# # Duplicate Label-Synonym
-#
-# Problem: An entity shares a label with an exact synonym. This causes ambiguity.
-#
-# Solution: Avoid ambiguity by changing the exact synonym or label.
-
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {
-    obo:IAO_0000118
-    oboInOwl:hasExactSynonym
-    oboInOwl:hasRelatedSynonym
-    oboInOwl:hasNarrowSynonym
-    oboInOwl:hasBroadSynonym
-  }
-  ?entity rdfs:label ?value .
-  ?entity ?property ?value
-}
diff --git a/robot-core/src/main/resources/report_queries/duplicate_scoped_synonym.rq b/robot-core/src/main/resources/report_queries/duplicate_scoped_synonym.rq
deleted file mode 100644
index 7516c5e4..00000000
--- a/robot-core/src/main/resources/report_queries/duplicate_scoped_synonym.rq
+++ /dev/null
@@ -1,31 +0,0 @@
-# # Duplicate Scoped Synonyms
-#
-# Problem: An entity has duplicate synonyms with different properties (e.g. the same broad and related synonym). This causes ambiguity.
-#
-# Solution: Remove duplicate synonyms and determine the correct scope.
-
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {
-    obo:IAO_0000118
-    oboInOwl:hasExactSynonym
-    oboInOwl:hasBroadSynonym
-    oboInOwl:hasRelatedSynonym
-    oboInOwl:hasNarrowSynonym
-  }
-  VALUES ?property2 {
-    obo:IAO_0000118
-    oboInOwl:hasExactSynonym
-    oboInOwl:hasBroadSynonym
-    oboInOwl:hasRelatedSynonym
-    oboInOwl:hasNarrowSynonym
-  }
-  ?entity ?property ?value .
-  ?entity ?property2 ?value .
-  FILTER (?property != ?property2)
-}
-ORDER BY ?entity
diff --git a/robot-core/src/main/resources/report_queries/equivalent_pair.rq b/robot-core/src/main/resources/report_queries/equivalent_pair.rq
deleted file mode 100644
index 364af16e..00000000
--- a/robot-core/src/main/resources/report_queries/equivalent_pair.rq
+++ /dev/null
@@ -1,14 +0,0 @@
-# # Equivalent Pair
-#
-# Problem: An entity has a one-to-one equivalency with another entity. This may be intentional (assuming it is not annotated with `is_inferred true`), or it may be due to incorrect logic and the reasoner asserting the equivalency.
-#
-# Solution: Ensure the reasoner is not incorrectly inferring equivalency. If so, update the logical axioms.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {owl:equivalentClass}
-  ?entity ?property ?value .
-  FILTER (!isBlank(?value))
-}
diff --git a/robot-core/src/main/resources/report_queries/invalid_xref.rq b/robot-core/src/main/resources/report_queries/invalid_xref.rq
deleted file mode 100644
index 17a040a0..00000000
--- a/robot-core/src/main/resources/report_queries/invalid_xref.rq
+++ /dev/null
@@ -1,16 +0,0 @@
-# # Invalid Xref
-#
-# Problem: A database_cross_reference is not in CURIE format.
-#
-# Solution: Replace the reference with a [CURIE](https://www.w3.org/TR/2010/NOTE-curie-20101216/).
-
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {oboInOwl:hasDbXref}
-  ?entity ?property ?value .
-  FILTER (!regex(?value, "^[a-z|A-Z|_|0-9]*:(?!$)\\S*$"))
-  FILTER (!isBlank(?entity))
-}
diff --git a/robot-core/src/main/resources/report_queries/label_formatting.rq b/robot-core/src/main/resources/report_queries/label_formatting.rq
deleted file mode 100644
index 6195a67c..00000000
--- a/robot-core/src/main/resources/report_queries/label_formatting.rq
+++ /dev/null
@@ -1,23 +0,0 @@
-# # Label Formatting
-#
-# Problem: Formatting characters are used in a label. This may cause issues when trying to reference the entity by label.
-#
-# Solution: Remove formatting characters from label.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  {
-   VALUES ?property {rdfs:label}
-   ?entity ?property ?value .
-   FILTER regex(?value, "\n")
-  }
-  UNION
-  {
-   VALUES ?property {rdfs:label}
-   ?entity ?property ?value .
-   FILTER regex(?value, "\t")
-  }
-}
diff --git a/robot-core/src/main/resources/report_queries/label_whitespace.rq b/robot-core/src/main/resources/report_queries/label_whitespace.rq
deleted file mode 100644
index e7cfb3ed..00000000
--- a/robot-core/src/main/resources/report_queries/label_whitespace.rq
+++ /dev/null
@@ -1,23 +0,0 @@
-# # Label Whitespace
-#
-# Problem: A label has leading or trailing whitespace. This may cause issues when trying to reference the entity by label.
-#
-# Solution: Remove the additional whitespace.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  {
-   VALUES ?property {rdfs:label}
-   ?entity ?property ?value .
-   FILTER STRENDS(str(?value), " ")
-  }
-  UNION
-  {
-   VALUES ?property {rdfs:label}
-   ?entity ?property ?value .
-   FILTER STRSTARTS(str(?value), " ")
-  }
-}
diff --git a/robot-core/src/main/resources/report_queries/lowercase_definition.rq b/robot-core/src/main/resources/report_queries/lowercase_definition.rq
deleted file mode 100644
index a071572c..00000000
--- a/robot-core/src/main/resources/report_queries/lowercase_definition.rq
+++ /dev/null
@@ -1,14 +0,0 @@
-# # Lowercase Definition
-#
-# Problem: A definition does not begin with an uppercase letter. This may be indicative of inconsistent formatting.
-#
-# Solution: Capitalize the first letter of the definition, or disregard this INFO.
-
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {obo:IAO_0000115}
-  ?entity ?property ?value .
-  FILTER (!regex(?value, "^[A-Z]"))
-}
diff --git a/robot-core/src/main/resources/report_queries/missing_definition.rq b/robot-core/src/main/resources/report_queries/missing_definition.rq
deleted file mode 100644
index 23aefebb..00000000
--- a/robot-core/src/main/resources/report_queries/missing_definition.rq
+++ /dev/null
@@ -1,20 +0,0 @@
-# # Missing Definition
-#
-# Problem: An entity does not have a definition. This may cause confusion or misuse of the entity.
-#
-# Solution: Add a definition.
-
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  ?entity ?any ?o
-  FILTER NOT EXISTS {?entity obo:IAO_0000115 ?value}
-  FILTER NOT EXISTS {?entity a owl:Ontology}
-  FILTER NOT EXISTS {
-    ?entity owl:deprecated ?dep .
-    FILTER regex(str(?dep), "true")
-  }
-  FILTER (!isBlank(?entity))
-}
diff --git a/robot-core/src/main/resources/report_queries/missing_label.rq b/robot-core/src/main/resources/report_queries/missing_label.rq
deleted file mode 100644
index 2e3c21e5..00000000
--- a/robot-core/src/main/resources/report_queries/missing_label.rq
+++ /dev/null
@@ -1,21 +0,0 @@
-# # Missing Label
-#
-# Problem: An entity does not have a label. This may cause confusion or misuse.
-#
-# Solution: Add a label.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  ?entity ?any ?o .
-  BIND ("rdfs:label" AS ?property) .
-  FILTER NOT EXISTS {?entity rdfs:label ?value}
-  FILTER NOT EXISTS {?entity a owl:Ontology}
-  FILTER NOT EXISTS {
-    ?entity owl:deprecated ?dep .
-    FILTER regex(str(?dep), "true")
-  }
-  FILTER (!isBlank(?entity))
-}
diff --git a/robot-core/src/main/resources/report_queries/missing_obsolete_label.rq b/robot-core/src/main/resources/report_queries/missing_obsolete_label.rq
deleted file mode 100644
index fa43d219..00000000
--- a/robot-core/src/main/resources/report_queries/missing_obsolete_label.rq
+++ /dev/null
@@ -1,17 +0,0 @@
-# # Missing Obsolete Label
-#
-# Problem: An obsolete entity does not have a label beginning with "obsolete". Adding this prefix ensures that users are aware the entity has been deprecated.
-#
-# Solution: Add the "obsolete" (or "OBSOLETE") prefix.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {rdfs:label}
-  ?entity owl:deprecated ?dep .
-  FILTER regex(str(?dep), "true") .
-  ?entity ?property ?value .
-  FILTER (!regex(?value, "^obsolete", "i"))
-}
diff --git a/robot-core/src/main/resources/report_queries/missing_superclass.rq b/robot-core/src/main/resources/report_queries/missing_superclass.rq
deleted file mode 100644
index 1d99bc72..00000000
--- a/robot-core/src/main/resources/report_queries/missing_superclass.rq
+++ /dev/null
@@ -1,22 +0,0 @@
-# # Missing Superclass
-#
-# Problem: A class does not have a superclass. This is not relevant for top-level classes, but may reveal orphaned children.
-#
-# Solution: Make sure there are no orphaned children - if so, assert a parent.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {rdfs:subClassOf}
-  ?entity a owl:Class .
-  FILTER (!isBlank(?entity)) .
-  FILTER NOT EXISTS {?entity ?property ?value} .
-  FILTER NOT EXISTS {
-    FILTER EXISTS {
-      ?entity owl:deprecated ?dep .
-      FILTER regex(str(?dep), "true")
-    }
-  }
-}
diff --git a/robot-core/src/main/resources/report_queries/misused_obsolete_label.rq b/robot-core/src/main/resources/report_queries/misused_obsolete_label.rq
deleted file mode 100644
index 6e603c2f..00000000
--- a/robot-core/src/main/resources/report_queries/misused_obsolete_label.rq
+++ /dev/null
@@ -1,19 +0,0 @@
-# # Misused Obsolete Label
-#
-# Problem: A non-deprecated class has the "obsolete" prefix. This may mean that a deprecated class is missing the `owl:deprecated` annotation, or that this prefix was added accidentally.
-#
-# Solution: Remove the "obsolete" prefix or add the `owl:deprecated` annotation.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {rdfs:label}
-  ?entity ?property ?value .
-  FILTER NOT EXISTS {
-    ?entity owl:deprecated ?dep .
-    FILTER regex(str(?dep), "true")
-  }
-  FILTER regex(?value, "^obsolete", "i")
-}
diff --git a/robot-core/src/main/resources/report_queries/multiple_asserted_superclasses.rq b/robot-core/src/main/resources/report_queries/multiple_asserted_superclasses.rq
deleted file mode 100644
index 43b5efb5..00000000
--- a/robot-core/src/main/resources/report_queries/multiple_asserted_superclasses.rq
+++ /dev/null
@@ -1,28 +0,0 @@
-# # Multiple Asserted Superclasses
-#
-# Problem: A class has more than one asserted named parent. This filters any axioms with the `is_inferred true` annotation, but inferences may not always be annotated. Double check where the parent is coming from before making changes.
-#
-# Solution: Use logical axioms to infer dual parentage.
-
-PREFIX oboInOwl: <http://www.geneontology.org/formats/oboInOwl#>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {rdfs:subClassOf}
-  ?entity a owl:Class .
-  ?entity ?property ?value .
-  ?entity ?property ?value2 .
-  FILTER (?value != ?value2)
-  FILTER (!isBlank(?value))
-  FILTER (!isBlank(?value2))
-  FILTER NOT EXISTS {
-    ?axiom owl:annotatedSource ?entity .
-    ?axiom owl:annotatedTarget ?value .
-    ?axiom owl:annotatedProperty rdfs:subClassOf .
-    ?axiom oboInOwl:is_inferred ?inf .
-    FILTER regex(str(?inf), "true")
-  }
-}
-ORDER BY ?entity
diff --git a/robot-core/src/main/resources/report_queries/multiple_definitions.rq b/robot-core/src/main/resources/report_queries/multiple_definitions.rq
deleted file mode 100644
index 5d67c0e3..00000000
--- a/robot-core/src/main/resources/report_queries/multiple_definitions.rq
+++ /dev/null
@@ -1,22 +0,0 @@
-# # Multiple Defintions
-#
-# Problem: An entity has more than one definition. This may cause confusion or misuse, and will prevent translation to OBO format.
-#
-# Solution: Remove extra definitions.
-
-PREFIX obo: <http://purl.obolibrary.org/obo/>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {obo:IAO_0000115}
-  ?entity ?property ?value .
-  ?entity ?property ?value2 .
-  FILTER (?value != ?value2)
-  FILTER NOT EXISTS {
-    ?entity owl:deprecated ?dep .
-    FILTER regex(str(?dep), "true")
-  }
-  FILTER (!isBlank(?entity))
-}
-ORDER BY ?entity
diff --git a/robot-core/src/main/resources/report_queries/multiple_labels.rq b/robot-core/src/main/resources/report_queries/multiple_labels.rq
deleted file mode 100644
index ae8921b3..00000000
--- a/robot-core/src/main/resources/report_queries/multiple_labels.rq
+++ /dev/null
@@ -1,19 +0,0 @@
-# # Multiple Labels
-#
-# Problem: An entity has more than one label. This may cause confusion or misuse, and will prevent translation to OBO format.
-#
-# Solution: Remove extra labels.
-
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {rdfs:label}
-  ?entity ?property ?value .
-  ?entity ?property ?value2 .
-  FILTER (?value != ?value2) .
-  FILTER NOT EXISTS {?entity owl:deprecated true}
-  FILTER (!isBlank(?entity))
-}
-ORDER BY ?entity
diff --git a/robot-core/src/main/resources/report_queries/ontology_metadata.rq b/robot-core/src/main/resources/report_queries/ontology_metadata.rq
deleted file mode 100644
index f09d8c37..00000000
--- a/robot-core/src/main/resources/report_queries/ontology_metadata.rq
+++ /dev/null
@@ -1,21 +0,0 @@
-# # Ontology Metadata
-#
-# Problem: The ontology header is missing required metadata. Currently, the OBO Foundry expects: a [license](http://dublincore.org/documents/dcmi-terms/#terms-license), a [description](http://dublincore.org/documents/dcmi-terms/#elements-description), and a [title](http://dublincore.org/documents/dcmi-terms/#elements-title).
-#
-# Solution: Add the missing metadata. See links for appropriate annotation properties.
-
-PREFIX dc: <http://purl.org/dc/elements/1.1/>
-PREFIX dcterms: <http://purl.org/dc/terms/>
-PREFIX owl: <http://www.w3.org/2002/07/owl#>
-
-SELECT DISTINCT ?entity ?property ?value
-WHERE {
-  VALUES ?property {
-    dcterms:license
-  	dc:description
-  	dc:title
-  }
-  ?entity a owl:Ontology .
-  OPTIONAL { ?entity ?property ?value }
-  FILTER (!bound(?value))
-}


Test patch:
diff --git a/robot-core/src/test/java/org/obolibrary/robot/ReasonOperationTest.java b/robot-core/src/test/java/org/obolibrary/robot/ReasonOperationTest.java
index f70d0850..0ddfacf7 100644
--- a/robot-core/src/test/java/org/obolibrary/robot/ReasonOperationTest.java
+++ b/robot-core/src/test/java/org/obolibrary/robot/ReasonOperationTest.java
@@ -1,6 +1,6 @@
 package org.obolibrary.robot;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -11,13 +11,8 @@ import org.junit.Test;
 import org.obolibrary.robot.exceptions.InvalidReferenceException;
 import org.obolibrary.robot.exceptions.OntologyLogicException;
 import org.semanticweb.elk.owlapi.ElkReasonerFactory;
-import org.semanticweb.owlapi.model.AddImport;
-import org.semanticweb.owlapi.model.IRI;
-import org.semanticweb.owlapi.model.OWLAxiom;
-import org.semanticweb.owlapi.model.OWLImportsDeclaration;
 import org.semanticweb.owlapi.model.OWLOntology;
 import org.semanticweb.owlapi.model.OWLOntologyCreationException;
-import org.semanticweb.owlapi.model.OWLOntologyManager;
 import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
 import uk.ac.manchester.cs.jfact.JFactFactory;
 
@@ -243,65 +238,4 @@ public class ReasonOperationTest extends CoreTest {
     ReasonOperation.reason(reasoned, reasonerFactory, opts);
     assertIdentical("/relax_equivalence_axioms_expressions_materialized.obo", reasoned);
   }
-
-  /**
-   * Test reasoning with intersection axioms
-   *
-   * @throws IOException on file problem
-   * @throws OWLOntologyCreationException on ontology problem
-   * @throws OntologyLogicException on logic error
-   * @throws InvalidReferenceException
-   */
-  @Test
-  public void testIntersection()
-      throws IOException, OWLOntologyCreationException, OntologyLogicException,
-          InvalidReferenceException {
-    OWLOntology reasoned = loadOntology("/intersection.omn");
-    OWLReasonerFactory reasonerFactory = new ElkReasonerFactory();
-    ReasonOperation.reason(reasoned, reasonerFactory);
-    assertTrue(checkContains(reasoned, "SubClassOf(<http://x.org/XA> <http://x.org/XB>)"));
-  }
-
-  /**
-   * Test reasoning with external ontologies.
-   *
-   * <p>Depending on user option, inferred axioms that refer solely to external ontology classes
-   * (i.e. those in the import chain) should not be asserted
-   *
-   * @throws IOException on file problem
-   * @throws OWLOntologyCreationException on ontology problem
-   * @throws OntologyLogicException on logic error
-   * @throws InvalidReferenceException
-   */
-  @Test
-  public void testExternal()
-      throws IOException, OWLOntologyCreationException, OntologyLogicException,
-          InvalidReferenceException {
-    OWLOntology importOnt1 = loadOntology("/intersection.omn");
-    IRI oiri = importOnt1.getOntologyID().getOntologyIRI().get();
-    OWLOntology mainOnt = loadOntology("/simple.owl");
-    OWLOntologyManager mgr = mainOnt.getOWLOntologyManager();
-    OWLOntology importOnt = mgr.createOntology(oiri);
-    mgr.addAxioms(importOnt, importOnt1.getAxioms());
-
-    OWLImportsDeclaration importsDecl = mgr.getOWLDataFactory().getOWLImportsDeclaration(oiri);
-    AddImport ch = new AddImport(mainOnt, importsDecl);
-    mgr.applyChange(ch);
-    OWLReasonerFactory reasonerFactory = new ElkReasonerFactory();
-
-    Map<String, String> opts = new HashMap<>();
-    opts.put("exclude-external-entities", "true");
-    ReasonOperation.reason(mainOnt, reasonerFactory, opts);
-    assertFalse(checkContains(mainOnt, "SubClassOf(<http://x.org/XA> <http://x.org/XB>)"));
-    opts.put("exclude-external-entities", "false");
-    ReasonOperation.reason(mainOnt, reasonerFactory, opts);
-    assertTrue(checkContains(mainOnt, "SubClassOf(<http://x.org/XA> <http://x.org/XB>)"));
-  }
-
-  private boolean checkContains(OWLOntology reasoned, String axStr) {
-    for (OWLAxiom a : reasoned.getLogicalAxioms()) {
-      if (a.toString().equals(axStr)) return true;
-    }
-    return false;
-  }
 }
diff --git a/robot-core/src/test/java/org/obolibrary/robot/ReduceOperationTest.java b/robot-core/src/test/java/org/obolibrary/robot/ReduceOperationTest.java
index 5d06212f..8a0ebcfa 100644
--- a/robot-core/src/test/java/org/obolibrary/robot/ReduceOperationTest.java
+++ b/robot-core/src/test/java/org/obolibrary/robot/ReduceOperationTest.java
@@ -18,33 +18,17 @@ public class ReduceOperationTest extends CoreTest {
    * @throws OWLOntologyCreationException
    */
   @Test
-  public void testRemoveRedundantSubClassAxiomsPreserveAnnotated()
-      throws IOException, OWLOntologyCreationException {
+  public void testRemoveRedundantSubClassAxioms() throws IOException, OWLOntologyCreationException {
     OWLOntology reasoned = loadOntology("/redundant_subclasses.owl");
     OWLReasonerFactory reasonerFactory = new org.semanticweb.elk.owlapi.ElkReasonerFactory();
 
     Map<String, String> options = new HashMap<String, String>();
     options.put("remove-redundant-subclass-axioms", "true");
-    options.put("preserve-annotated-axioms", "true");
 
     ReduceOperation.reduce(reasoned, reasonerFactory, options);
     assertIdentical("/without_redundant_subclasses.owl", reasoned);
   }
 
-  @Test
-  public void testRemoveRedundantSubClassAxiomsComplete()
-      throws IOException, OWLOntologyCreationException {
-    OWLOntology reasoned = loadOntology("/redundant_subclasses.owl");
-    OWLReasonerFactory reasonerFactory = new org.semanticweb.elk.owlapi.ElkReasonerFactory();
-
-    Map<String, String> options = new HashMap<String, String>();
-    options.put("remove-redundant-subclass-axioms", "true");
-    options.put("preserve-annotated-axioms", "false");
-
-    ReduceOperation.reduce(reasoned, reasonerFactory, options);
-    assertIdentical("/without_redundant_subclasses2.owl", reasoned);
-  }
-
   /**
    * Test removing redundant subclass expression (existential restriction) axioms.
    *
diff --git a/robot-core/src/test/java/org/obolibrary/robot/TemplateOperationTest.java b/robot-core/src/test/java/org/obolibrary/robot/TemplateOperationTest.java
index b8dbbb13..a2be5ec6 100644
--- a/robot-core/src/test/java/org/obolibrary/robot/TemplateOperationTest.java
+++ b/robot-core/src/test/java/org/obolibrary/robot/TemplateOperationTest.java
@@ -116,7 +116,7 @@ public class TemplateOperationTest extends CoreTest {
     OWLOntology simpleParts = loadOntology("/simple_parts.owl");
     OWLOntology template = TemplateOperation.template(tables, simpleParts);
     assertEquals("Count classes", 4, template.getClassesInSignature().size());
-    assertEquals("Count logical axioms", 4, template.getLogicalAxiomCount());
-    assertEquals("Count all axioms", 10, template.getAxiomCount());
+    assertEquals("Count logical axioms", 3, template.getLogicalAxiomCount());
+    assertEquals("Count all axioms", 9, template.getAxiomCount());
   }
 }
diff --git a/robot-core/src/test/resources/intersection.omn b/robot-core/src/test/resources/intersection.omn
deleted file mode 100644
index b72a6990..00000000
--- a/robot-core/src/test/resources/intersection.omn
+++ /dev/null
@@ -1,18 +0,0 @@
-Prefix: : <http://x.org/>
-
-Ontology: <http://x.org>
-
-##
-
-Class: A
-  SubClassOf: B
-
-Class: B
-
-Class: X
-Class: XA
-  EquivalentTo: X and A
-Class: XB
-  EquivalentTo: X and B
-
-        
diff --git a/robot-core/src/test/resources/template-labels.csv b/robot-core/src/test/resources/template-labels.csv
index 898e4849..081f301d 100644
--- a/robot-core/src/test/resources/template-labels.csv
+++ b/robot-core/src/test/resources/template-labels.csv
@@ -1,4 +1,4 @@
 Label,Synonyms,Type,Parent,Parts
-LABEL,A IAO:0000118 SPLIT=|,CLASS_TYPE,C % SPLIT=|,C part_of some %
-test 3,synonym 1|synonym 2,subclass,test one|test2,test one
+LABEL,A IAO:0000118 SPLIT=|,CLASS_TYPE,C %,C part_of some %
+test 3,synonym 1|synonym 2,subclass,test2,test one
 test 4,,equivalent,test one,(test2 and 'test 3')
diff --git a/robot-core/src/test/resources/without_redundant_subclasses2.owl b/robot-core/src/test/resources/without_redundant_subclasses2.owl
deleted file mode 100644
index 9bdae9bb..00000000
--- a/robot-core/src/test/resources/without_redundant_subclasses2.owl
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0"?>
-<rdf:RDF xmlns="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl"
-     xml:base="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl"
-     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:owl="http://www.w3.org/2002/07/owl#"
-     xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
-     xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
-     xmlns:obo="http://purl.obolibrary.org/obo/"
-     xmlns:foaf="http://xmlns.com/foaf/0.1/">
-    <owl:Ontology rdf:about="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl"/>
-    
-
-
-    <!-- 
-    ///////////////////////////////////////////////////////////////////////////////////////
-    //
-    // Classes
-    //
-    ///////////////////////////////////////////////////////////////////////////////////////
-     -->
-
-    
-
-
-    <!-- https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test1 -->
-
-    <owl:Class rdf:about="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test1">
-        <rdfs:label>Test 1</rdfs:label>
-        <rdfs:label>test one</rdfs:label>
-        <rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
-    </owl:Class>
-    
-
-
-    <!-- https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test2 -->
-
-    <owl:Class rdf:about="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test2">
-        <rdfs:subClassOf rdf:resource="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test1"/>
-    </owl:Class>
-    
-
-
-    <!-- https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test3 -->
-
-    <owl:Class rdf:about="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test3">
-        <rdfs:subClassOf rdf:resource="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test2"/>
-    </owl:Class>
-    
-
-
-    <!-- https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test4 -->
-
-    <owl:Class rdf:about="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test4">
-        <rdfs:subClassOf rdf:resource="https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#test3"/>
-    </owl:Class>
-</rdf:RDF>
-
-
-
-<!-- Generated by the OWL API (version 3.5.1) http://owlapi.sourceforge.net -->
-