diff --git a/CHANGELOG.md b/CHANGELOG.md index ea74137be..0646353be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add `--input-format` global option [#1038] +- Warn on missing `?property` and `?value` in `report` [#1273] ### Fixed - Inherit OWLDocumentFormat when performing SPARQL update [#1267] diff --git a/docs/report.md b/docs/report.md index 714238075..8c2d92dfc 100644 --- a/docs/report.md +++ b/docs/report.md @@ -80,14 +80,19 @@ If the report fails, the command will exit with a status of `1`, but a report wi 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 deprecated classes: +For example, in this query the `?value` is any deprecated class that is the object of a triple: + ``` -SELECT DISTINCT ?entity ?property ?value WHERE - {?value owl:deprecated true . - ?entity a owl:Class . - ?entity ?property ?value } +PREFIX owl: +PREFIX xsd: + +SELECT DISTINCT ?entity ?property ?value +WHERE { + ?value a owl:Class ; + owl:deprecated "true"^^xsd:boolean . + ?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. @@ -110,18 +115,10 @@ INFO deprecated_class 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 absolute or relative path. Note that in order for the queries to be included in the report, they _must_ return exactly three variables: `?entity ?property ?value`. -As an example, consider the query we have already mentioned: - -``` -SELECT DISTINCT ?entity ?property ?value WHERE - {?value owl:deprecated true . - ?entity a owl:Class . - ?entity ?property ?value } -``` - For other examples, you can refer to [the full list of default checks](report_queries/). -This example would create a report with references to deprecated classes as ERROR and the user query violations as INFO: +This example profile 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 diff --git a/docs/report_queries/duplicate_exact_synonym.md b/docs/report_queries/duplicate_exact_synonym.md index 86263e070..741b6cfee 100644 --- a/docs/report_queries/duplicate_exact_synonym.md +++ b/docs/report_queries/duplicate_exact_synonym.md @@ -37,4 +37,4 @@ WHERE { FILTER (UCASE(?value) = ?syn_std) } ORDER BY DESC(UCASE(str(?value))) -``` \ No newline at end of file +``` diff --git a/docs/report_queries/equivalent_class_axiom_no_genus.md b/docs/report_queries/equivalent_class_axiom_no_genus.md index 509d3b6b9..a68c52c0e 100644 --- a/docs/report_queries/equivalent_class_axiom_no_genus.md +++ b/docs/report_queries/equivalent_class_axiom_no_genus.md @@ -4,7 +4,7 @@ **Solution:** Add a genus to the class expression like: C = B and R some A. -``` +```sparql PREFIX owl: PREFIX rdf: @@ -17,5 +17,4 @@ SELECT DISTINCT ?entity ?property ?value WHERE { BIND (if(isIRI(?property1), ?property1, "blank node" ) as ?property) } ORDER BY ?entity - ``` diff --git a/docs/report_queries/illegal_use_of_built_in_vocabulary.md b/docs/report_queries/illegal_use_of_built_in_vocabulary.md index 9201bbad5..bbb95b59a 100644 --- a/docs/report_queries/illegal_use_of_built_in_vocabulary.md +++ b/docs/report_queries/illegal_use_of_built_in_vocabulary.md @@ -4,7 +4,7 @@ **Solution:** Remove any statements about build-in vocabulary -``` +```sparql PREFIX owl: PREFIX rdf: diff --git a/docs/report_queries/invalid_entity_uri.md b/docs/report_queries/invalid_entity_uri.md index 5f2c99099..054f8505d 100644 --- a/docs/report_queries/invalid_entity_uri.md +++ b/docs/report_queries/invalid_entity_uri.md @@ -1,10 +1,10 @@ # Invalid Entity URI -**Problem:** An entity's URI is not formatted correctly. OBO entities are formatted http://purl.obolibrary.org/obo/IDSPACE_0000000. This format is assumed by many OBO tools. Often, accidental typos cause an entity to be malformed, which can cause problems for tools that deal with OBO ontologies. +**Problem:** OBO entities are formatted http://purl.obolibrary.org/obo/IDSPACE_0000000. This format is assumed by many OBO tools. Often, accidentally typos cause entity to be ignored during processing. **Solution:** Fix the entity OBO URI. -``` +```sparql PREFIX rdf: SELECT DISTINCT ?entity ?property ?value WHERE { diff --git a/docs/report_queries/missing_synonymtype_declaration.md b/docs/report_queries/missing_synonymtype_declaration.md index f5d1ba87c..525a13d2c 100644 --- a/docs/report_queries/missing_synonymtype_declaration.md +++ b/docs/report_queries/missing_synonymtype_declaration.md @@ -14,4 +14,4 @@ SELECT DISTINCT ?entity ?property ?value WHERE { FILTER NOT EXISTS { ?entity ?property oboInOwl:SynonymTypeProperty } } ORDER BY ?entity -``` \ No newline at end of file +``` 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 f01eb0ffd..d613d96d2 100644 --- a/robot-core/src/main/java/org/obolibrary/robot/ReportOperation.java +++ b/robot-core/src/main/java/org/obolibrary/robot/ReportOperation.java @@ -919,6 +919,9 @@ private static List getViolationsFromResults( IOHelper ioHelper, String queryName, ResultSet violationSet, Integer limit) throws Exception { List violations = new ArrayList<>(); + boolean propertyWarning = false; + boolean valueWarning = false; + // Counter for stopping at limit int c = 0; while (violationSet.hasNext()) { @@ -977,9 +980,24 @@ private static List getViolationsFromResults( violation = new Violation("blank node"); } - // try and get a property and value from the query + // Try and get a property and value from the query. + // If none is found, print a warning, but only once. String property = getQueryResultOrNull(qs, "property"); + if (property == null) { + if (!propertyWarning) { + System.out.println(WARN + ": '" + queryName + "' query is missing ?property variable"); + } + propertyWarning = true; + } + String value = getQueryResultOrNull(qs, "value"); + if (value == null) { + if (!valueWarning) { + System.out.println(WARN + ": '" + queryName + "' query is missing ?value variable"); + } + valueWarning = true; + } + // add details to Violation if (property != null) { OWLEntity e = dataFactory.getOWLClass(ioHelper.createIRI(property));