From 087348fcdbc17c8598fad7f81778dc1ecdf8bd6c Mon Sep 17 00:00:00 2001 From: hoodcm Date: Tue, 22 Sep 2026 13:37:04 -0400 Subject: [PATCH 1/2] Add seven SPARQL integrity checks and fix what they found Widen the whitespace check to rdfs:label and rid:UMLS_Term. Add checks for empty annotation values, rid:RadLexID matching the IRI, class IRIs in RID form (WARN), and rid:Replaced_by being an IRI, aimed at a live class, and carried only by retired classes. Fix the violations on main: 7 labels, 2 rid:RadLexID typos, 4 rid:Replaced_by literals, 2 chained retirements. Remove a stray conflict marker from .gitignore. Part of #5. Related to #8. --- .gitignore | 1 - RadLex.owl | 30 +++++++++---------- tests/robot-report-profile.txt | 9 +++++- .../robot/annotation_value_not_empty.rq | 22 ++++++++++++++ tests/sparql/robot/class_iri_is_rid.rq | 24 +++++++++++++++ .../leading_trailing_multi_whitespace.rq | 6 +++- .../robot/obsolete_class_not_a_parent.rq | 26 ++++++++++++++++ tests/sparql/robot/radlexid_matches_iri.rq | 29 ++++++++++++++++++ tests/sparql/robot/replaced_by_is_iri.rq | 19 ++++++++++++ .../replaced_by_only_on_obsolete_class.rq | 22 ++++++++++++++ .../robot/replaced_by_target_is_live_class.rq | 30 +++++++++++++++++++ 11 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 tests/sparql/robot/annotation_value_not_empty.rq create mode 100644 tests/sparql/robot/class_iri_is_rid.rq create mode 100644 tests/sparql/robot/obsolete_class_not_a_parent.rq create mode 100644 tests/sparql/robot/radlexid_matches_iri.rq create mode 100644 tests/sparql/robot/replaced_by_is_iri.rq create mode 100644 tests/sparql/robot/replaced_by_only_on_obsolete_class.rq create mode 100644 tests/sparql/robot/replaced_by_target_is_live_class.rq diff --git a/.gitignore b/.gitignore index 46d8767..3329f18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -<<<<<<< HEAD # OS .DS_Store diff --git a/RadLex.owl b/RadLex.owl index 17fd4c2..151c959 100644 --- a/RadLex.owl +++ b/RadLex.owl @@ -10389,7 +10389,7 @@ duplicate term balloon dilation of structure RID10400 4.1 obs - RID11030 + Ballondilatation einer Struktur @@ -23277,7 +23277,7 @@ AND An artifact resulting in ghost images of a vessel extending across the image in the phase encoding direction. RID11488 - Betonung des pulsatilen Flussartefaktes + Betonung des pulsatilen Flussartefaktes accentuation of pulsatile flow artifact @@ -23889,7 +23889,7 @@ AND RID11529 - Komplikation eines Abszesses + Komplikation eines Abszesses abscess complication @@ -68441,7 +68441,7 @@ The LI-RADS definition of “size” correspons to the definition of the longest Brodmann area 5 of left post central gyrus RID13601 4.3 obs - RID25948 + Brodmann-Areal 5 des linken Gyrus postcentralis @@ -540446,7 +540446,7 @@ US: A mass that is spherical, ball-shaped, circular or globular. A round mass h anterior thoracic region front of chest pectus - Vorderseite des Brustkorbs + Vorderseite des Brustkorbs anterior chest @@ -544783,7 +544783,7 @@ US: A mass that is spherical, ball-shaped, circular or globular. A round mass h lumbar region regio lumbalis regio lumbalis - Rückwand des Abdomens + Rückwand des Abdomens back of abdomen @@ -586331,7 +586331,7 @@ US: A mass that is spherical, ball-shaped, circular or globular. A round mass h duplicate inferior diaphragmatic lymph node group RID31917 - + @@ -655665,7 +655665,7 @@ Duplicate of RID3506 Tubular opacities within bronchi, seen in mucoid impaction (mucous plugging). finger-in-glove sign RID35211 - + RadsWiki @@ -741605,7 +741605,7 @@ not yet enhanced early hepatic arterial phase RID39534 4.1 obs - RID11082 + LI-RADS early arterial phase (liver) früharterielle Phase der Leber @@ -741625,7 +741625,7 @@ enhanced late hepatic arterial phase RID39535 4.1 obs - RID39127 + LI-RADS spätarterielle Phase der Leber @@ -871055,7 +871055,7 @@ Enhancement from hypo on precontrast to iso on arterial phase does not qualify a RID45693 Playbook - Bildgebung in Bloodpool- phase + Bildgebung in Bloodpool-Phase blood pool imaging @@ -993046,7 +993046,7 @@ strong association with benignity RID50296 3.15 new PI-RADS v2.1 - PI-RADS 1 - Very low (Lesion) + PI-RADS 1 - Very low (Lesion) @@ -993060,7 +993060,7 @@ strong association with benignity RID50297 3.15 new PI-RADS v2.1 - PI-RADS 2 - Low (Lesion) + PI-RADS 2 - Low (Lesion) @@ -998169,7 +998169,7 @@ Does not apply to blood pool agents. Beverly Collins 2022-01-21T21:16:57.865324Z - RID60643 + RID50643 4.2 new LOINC view Canale @@ -998801,7 +998801,7 @@ Does not apply to blood pool agents. Beverly Collins 2022-08-19T16:24:49.983716Z - RID50580 + RID50680 4.2 new ‘CT Kidney and Abdominal Renal Mass’ report template invades collecting system diff --git a/tests/robot-report-profile.txt b/tests/robot-report-profile.txt index 00c1f4c..4c88031 100644 --- a/tests/robot-report-profile.txt +++ b/tests/robot-report-profile.txt @@ -1 +1,8 @@ -ERROR file:./tests/sparql/robot/leading_trailing_multi_whitespace.rq \ No newline at end of file +ERROR file:./tests/sparql/robot/leading_trailing_multi_whitespace.rq +ERROR file:./tests/sparql/robot/annotation_value_not_empty.rq +ERROR file:./tests/sparql/robot/radlexid_matches_iri.rq +WARN file:./tests/sparql/robot/class_iri_is_rid.rq +ERROR file:./tests/sparql/robot/replaced_by_is_iri.rq +ERROR file:./tests/sparql/robot/replaced_by_target_is_live_class.rq +ERROR file:./tests/sparql/robot/replaced_by_only_on_obsolete_class.rq +ERROR file:./tests/sparql/robot/obsolete_class_not_a_parent.rq diff --git a/tests/sparql/robot/annotation_value_not_empty.rq b/tests/sparql/robot/annotation_value_not_empty.rq new file mode 100644 index 0000000..34398d0 --- /dev/null +++ b/tests/sparql/robot/annotation_value_not_empty.rq @@ -0,0 +1,22 @@ +PREFIX rdfs: +PREFIX owl: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that no annotation assertion has an empty or whitespace-only value. An empty assertion falsely signals +# that the field is populated. Every declared owl:AnnotationProperty is covered, plus rdfs:label, which is a +# built-in and therefore not declared. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The entity carrying the empty assertion. +# - The annotation property. +# - The empty value. +# +SELECT ?entity ?property ?value +WHERE { + { ?property a owl:AnnotationProperty } UNION { BIND(rdfs:label AS ?property) } + ?entity ?property ?value . + FILTER(isLiteral(?value)) + FILTER(REGEX(STR(?value), "^\\s*$")) +} diff --git a/tests/sparql/robot/class_iri_is_rid.rq b/tests/sparql/robot/class_iri_is_rid.rq new file mode 100644 index 0000000..143614f --- /dev/null +++ b/tests/sparql/robot/class_iri_is_rid.rq @@ -0,0 +1,24 @@ +PREFIX rdf: +PREFIX owl: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that every class in the RadLex namespace has an IRI local name of the form RID. Two classes +# violate this today (RadLex_term and Non-RadLex_term, both direct children of RID0), so the check is +# registered at WARN until the committee decides whether they are renumbered or retired. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The class whose IRI does not follow the RID pattern. +# - rdf:type. +# - The offending local name. +# +SELECT ?entity ?property ?value +WHERE { + ?entity a owl:Class . + FILTER(isIRI(?entity)) + FILTER(STRSTARTS(STR(?entity), "http://www.radlex.org/RID/")) + FILTER(!REGEX(STR(?entity), "^http://www\\.radlex\\.org/RID/RID[0-9]+$")) + BIND(rdf:type AS ?property) + BIND(REPLACE(STR(?entity), "^http://www\\.radlex\\.org/RID/", "") AS ?value) +} diff --git a/tests/sparql/robot/leading_trailing_multi_whitespace.rq b/tests/sparql/robot/leading_trailing_multi_whitespace.rq index 6b255df..67a1128 100644 --- a/tests/sparql/robot/leading_trailing_multi_whitespace.rq +++ b/tests/sparql/robot/leading_trailing_multi_whitespace.rq @@ -9,6 +9,10 @@ PREFIX rid: # Test for stray whitespace on values (strings) of the annotation properties used for names. Specifically, this test # prohibits: leading or trailing whitespace, or consecutive whitespace characters within a string. # +# The constrained properties are checked directly and through any declared sub-property. Matching only through +# rdfs:subPropertyOf would skip rdfs:label and rid:UMLS_Term, which have no sub-properties (rid:Synonym is caught +# that way only because it is declared as a sub-property of itself). +# # VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: # - The entity on which the violation occurs (e.g., the class). # - The property on which the violation occurs (i.e., the annotation property, e.g. rdfs:label). @@ -17,7 +21,7 @@ PREFIX rid: SELECT ?entity ?property ?value WHERE { VALUES ?constrained_property {rdfs:label rid:Synonym rid:UMLS_Term} . - ?property rdfs:subPropertyOf ?constrained_property . + ?property rdfs:subPropertyOf* ?constrained_property . ?entity ?property ?value . FILTER(REGEX(STR(?value), "^\\s|\\s+$|\\s\\s")) } diff --git a/tests/sparql/robot/obsolete_class_not_a_parent.rq b/tests/sparql/robot/obsolete_class_not_a_parent.rq new file mode 100644 index 0000000..db37810 --- /dev/null +++ b/tests/sparql/robot/obsolete_class_not_a_parent.rq @@ -0,0 +1,26 @@ +PREFIX rdfs: +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that no live class is asserted as a subclass of a retired class. A retired class is one that carries +# rid:Preferred_Name_for_Obsolete or is filed under RID15849 ("Obsolete RadLex Term"). RID15849 itself is +# exempt as a parent, since retired classes are meant to hang under it, and a retired child under a retired +# parent is not reported. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The live class. +# - rdfs:subClassOf. +# - The retired parent. +# +SELECT DISTINCT ?entity ?property ?value +WHERE { + BIND(rdfs:subClassOf AS ?property) + ?entity ?property ?value . + FILTER(isIRI(?value)) + FILTER(?value != rid:RID15849) + { ?value rid:Preferred_Name_for_Obsolete ?_pname } UNION { ?value rdfs:subClassOf rid:RID15849 } + FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_cname } + FILTER NOT EXISTS { ?entity rdfs:subClassOf rid:RID15849 } +} diff --git a/tests/sparql/robot/radlexid_matches_iri.rq b/tests/sparql/robot/radlexid_matches_iri.rq new file mode 100644 index 0000000..eeac479 --- /dev/null +++ b/tests/sparql/robot/radlexid_matches_iri.rq @@ -0,0 +1,29 @@ +PREFIX rdfs: +PREFIX owl: +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that a class's rid:RadLexID restates the local name of its own IRI. The ID is redundant with the IRI by +# design, so any disagreement is a copy or typing error that desynchronises ID-keyed consumers from IRI-keyed +# ones. A class in the RID namespace with no rid:RadLexID at all is also a violation. +# +# Scope: classes whose IRI local name has the form RID. Classes with other local names are reported +# by class_iri_is_rid.rq instead. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The class whose ID disagrees with (or is missing from) its IRI. +# - rid:RadLexID. +# - The ID value found, or the empty string when the class carries none. +# +SELECT ?entity ?property ?value +WHERE { + ?entity a owl:Class . + FILTER(REGEX(STR(?entity), "^http://www\\.radlex\\.org/RID/RID[0-9]+$")) + BIND(rid:RadLexID AS ?property) + BIND(REPLACE(STR(?entity), "^http://www\\.radlex\\.org/RID/", "") AS ?expected) + OPTIONAL { ?entity rid:RadLexID ?id } + BIND(COALESCE(STR(?id), "") AS ?value) + FILTER(?value != ?expected) +} diff --git a/tests/sparql/robot/replaced_by_is_iri.rq b/tests/sparql/robot/replaced_by_is_iri.rq new file mode 100644 index 0000000..ba6bce8 --- /dev/null +++ b/tests/sparql/robot/replaced_by_is_iri.rq @@ -0,0 +1,19 @@ +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that every rid:Replaced_by value is an IRI reference to another class, not a string literal such as +# "RID11030". A literal cannot be followed by tooling that walks retired terms to their replacements. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The retired class carrying the pointer. +# - rid:Replaced_by. +# - The literal value that should have been an IRI. +# +SELECT ?entity ?property ?value +WHERE { + BIND(rid:Replaced_by AS ?property) + ?entity ?property ?value . + FILTER(isLiteral(?value)) +} diff --git a/tests/sparql/robot/replaced_by_only_on_obsolete_class.rq b/tests/sparql/robot/replaced_by_only_on_obsolete_class.rq new file mode 100644 index 0000000..2471a32 --- /dev/null +++ b/tests/sparql/robot/replaced_by_only_on_obsolete_class.rq @@ -0,0 +1,22 @@ +PREFIX rdfs: +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that only retired classes carry rid:Replaced_by. A retired class is one that carries +# rid:Preferred_Name_for_Obsolete or is filed under RID15849 ("Obsolete RadLex Term"). A live class with a +# replacement pointer is contradictory: either the retirement was never recorded or the pointer is stray. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The live class carrying the pointer. +# - rid:Replaced_by. +# - The pointer's target. +# +SELECT ?entity ?property ?value +WHERE { + BIND(rid:Replaced_by AS ?property) + ?entity ?property ?value . + FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_name } + FILTER NOT EXISTS { ?entity rdfs:subClassOf rid:RID15849 } +} diff --git a/tests/sparql/robot/replaced_by_target_is_live_class.rq b/tests/sparql/robot/replaced_by_target_is_live_class.rq new file mode 100644 index 0000000..8d6d826 --- /dev/null +++ b/tests/sparql/robot/replaced_by_target_is_live_class.rq @@ -0,0 +1,30 @@ +PREFIX rdfs: +PREFIX owl: +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that a rid:Replaced_by pointer aims at a class that exists and is not itself retired. A retired class is +# one that carries rid:Preferred_Name_for_Obsolete or is filed under RID15849 ("Obsolete RadLex Term"). A pointer +# to a retired class is a chained retirement that was never re-pointed at the live replacement; a pointer to an +# undeclared IRI dangles. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The retired class carrying the pointer. +# - rid:Replaced_by. +# - The target IRI that is retired or undeclared. +# +SELECT DISTINCT ?entity ?property ?value +WHERE { + BIND(rid:Replaced_by AS ?property) + ?entity ?property ?value . + FILTER(isIRI(?value)) + { + FILTER NOT EXISTS { ?value a owl:Class } + } + UNION + { + { ?value rid:Preferred_Name_for_Obsolete ?_name } UNION { ?value rdfs:subClassOf rid:RID15849 } + } +} From 7d7f44e9551af821346dc88deffbd4a1b6f598b9 Mon Sep 17 00:00:00 2001 From: hoodcm Date: Thu, 1 Oct 2026 11:58:50 -0400 Subject: [PATCH 2/2] Address review: name checks for what they find, define obsolete by RID15849 alone Rename the queries for the violations they return. Drop the RID IRI check pending its own issue. Use rdfs:subClassOf+ to find obsolete classes at any depth. Add a check that Preferred_Name_for_Obsolete sits only on obsolete classes, and file its two hits (RID27787, RID49508) under RID15849. Narrow the Replaced_by target check to undeclared targets and restore the two chained pointers. --- RadLex.owl | 8 ++--- tests/robot-report-profile.txt | 14 ++++----- tests/sparql/robot/class_iri_is_rid.rq | 24 --------------- .../robot/dangling_replaced_by_target.rq | 22 ++++++++++++++ ...not_empty.rq => empty_annotation_value.rq} | 2 +- ...is_iri.rq => literal_replaced_by_value.rq} | 4 +-- .../robot/live_class_under_obsolete_parent.rq | 24 +++++++++++++++ ..._class_with_preferred_name_for_obsolete.rq | 22 ++++++++++++++ ...lass.rq => live_class_with_replaced_by.rq} | 9 +++--- ..._matches_iri.rq => mismatched_radlexid.rq} | 3 +- .../robot/obsolete_class_not_a_parent.rq | 26 ---------------- .../robot/replaced_by_target_is_live_class.rq | 30 ------------------- 12 files changed, 87 insertions(+), 101 deletions(-) delete mode 100644 tests/sparql/robot/class_iri_is_rid.rq create mode 100644 tests/sparql/robot/dangling_replaced_by_target.rq rename tests/sparql/robot/{annotation_value_not_empty.rq => empty_annotation_value.rq} (96%) rename tests/sparql/robot/{replaced_by_is_iri.rq => literal_replaced_by_value.rq} (88%) create mode 100644 tests/sparql/robot/live_class_under_obsolete_parent.rq create mode 100644 tests/sparql/robot/live_class_with_preferred_name_for_obsolete.rq rename tests/sparql/robot/{replaced_by_only_on_obsolete_class.rq => live_class_with_replaced_by.rq} (53%) rename tests/sparql/robot/{radlexid_matches_iri.rq => mismatched_radlexid.rq} (89%) delete mode 100644 tests/sparql/robot/obsolete_class_not_a_parent.rq delete mode 100644 tests/sparql/robot/replaced_by_target_is_live_class.rq diff --git a/RadLex.owl b/RadLex.owl index 151c959..0b18f42 100644 --- a/RadLex.owl +++ b/RadLex.owl @@ -498439,7 +498439,7 @@ FMA has same as pelvis RID2507 - + tenia choroidea of lateral ventricle RID27787 3.14 obs @@ -586331,7 +586331,7 @@ US: A mass that is spherical, ball-shaped, circular or globular. A round mass h duplicate inferior diaphragmatic lymph node group RID31917 - + @@ -655665,7 +655665,7 @@ Duplicate of RID3506 Tubular opacities within bronchi, seen in mucoid impaction (mucous plugging). finger-in-glove sign RID35211 - + RadsWiki @@ -979816,7 +979816,7 @@ the apex - + "capsule of prostate" and "pseudocapsule of prostate" were determined to be the same entity. This term was deprecated in favor of the existing term with the preferred "pseudocapsule". 2014-07-07T00:00:00 PI-RADS: Tumor involvement of the “capsule” or extension across the “capsule” diff --git a/tests/robot-report-profile.txt b/tests/robot-report-profile.txt index 4c88031..d04314d 100644 --- a/tests/robot-report-profile.txt +++ b/tests/robot-report-profile.txt @@ -1,8 +1,8 @@ ERROR file:./tests/sparql/robot/leading_trailing_multi_whitespace.rq -ERROR file:./tests/sparql/robot/annotation_value_not_empty.rq -ERROR file:./tests/sparql/robot/radlexid_matches_iri.rq -WARN file:./tests/sparql/robot/class_iri_is_rid.rq -ERROR file:./tests/sparql/robot/replaced_by_is_iri.rq -ERROR file:./tests/sparql/robot/replaced_by_target_is_live_class.rq -ERROR file:./tests/sparql/robot/replaced_by_only_on_obsolete_class.rq -ERROR file:./tests/sparql/robot/obsolete_class_not_a_parent.rq +ERROR file:./tests/sparql/robot/empty_annotation_value.rq +ERROR file:./tests/sparql/robot/mismatched_radlexid.rq +ERROR file:./tests/sparql/robot/literal_replaced_by_value.rq +ERROR file:./tests/sparql/robot/dangling_replaced_by_target.rq +ERROR file:./tests/sparql/robot/live_class_with_replaced_by.rq +ERROR file:./tests/sparql/robot/live_class_with_preferred_name_for_obsolete.rq +ERROR file:./tests/sparql/robot/live_class_under_obsolete_parent.rq diff --git a/tests/sparql/robot/class_iri_is_rid.rq b/tests/sparql/robot/class_iri_is_rid.rq deleted file mode 100644 index 143614f..0000000 --- a/tests/sparql/robot/class_iri_is_rid.rq +++ /dev/null @@ -1,24 +0,0 @@ -PREFIX rdf: -PREFIX owl: - -# -# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. -# -# Test that every class in the RadLex namespace has an IRI local name of the form RID. Two classes -# violate this today (RadLex_term and Non-RadLex_term, both direct children of RID0), so the check is -# registered at WARN until the committee decides whether they are renumbered or retired. -# -# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: -# - The class whose IRI does not follow the RID pattern. -# - rdf:type. -# - The offending local name. -# -SELECT ?entity ?property ?value -WHERE { - ?entity a owl:Class . - FILTER(isIRI(?entity)) - FILTER(STRSTARTS(STR(?entity), "http://www.radlex.org/RID/")) - FILTER(!REGEX(STR(?entity), "^http://www\\.radlex\\.org/RID/RID[0-9]+$")) - BIND(rdf:type AS ?property) - BIND(REPLACE(STR(?entity), "^http://www\\.radlex\\.org/RID/", "") AS ?value) -} diff --git a/tests/sparql/robot/dangling_replaced_by_target.rq b/tests/sparql/robot/dangling_replaced_by_target.rq new file mode 100644 index 0000000..e7206b2 --- /dev/null +++ b/tests/sparql/robot/dangling_replaced_by_target.rq @@ -0,0 +1,22 @@ +PREFIX owl: +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that every rid:Replaced_by pointer aims at a class declared in RadLex. A pointer to an undeclared IRI, +# such as a mistyped RID, cannot be followed. A pointer to a class that is itself obsolete is allowed: the +# chain records the retirement history, and a consumer can follow it to the end. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The obsolete class carrying the pointer. +# - rid:Replaced_by. +# - The undeclared target IRI. +# +SELECT ?entity ?property ?value +WHERE { + BIND(rid:Replaced_by AS ?property) + ?entity ?property ?value . + FILTER(isIRI(?value)) + FILTER NOT EXISTS { ?value a owl:Class } +} diff --git a/tests/sparql/robot/annotation_value_not_empty.rq b/tests/sparql/robot/empty_annotation_value.rq similarity index 96% rename from tests/sparql/robot/annotation_value_not_empty.rq rename to tests/sparql/robot/empty_annotation_value.rq index 34398d0..508fba3 100644 --- a/tests/sparql/robot/annotation_value_not_empty.rq +++ b/tests/sparql/robot/empty_annotation_value.rq @@ -11,7 +11,7 @@ PREFIX owl: # VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: # - The entity carrying the empty assertion. # - The annotation property. -# - The empty value. +# - The empty or whitespace value. # SELECT ?entity ?property ?value WHERE { diff --git a/tests/sparql/robot/replaced_by_is_iri.rq b/tests/sparql/robot/literal_replaced_by_value.rq similarity index 88% rename from tests/sparql/robot/replaced_by_is_iri.rq rename to tests/sparql/robot/literal_replaced_by_value.rq index ba6bce8..b5944a2 100644 --- a/tests/sparql/robot/replaced_by_is_iri.rq +++ b/tests/sparql/robot/literal_replaced_by_value.rq @@ -4,10 +4,10 @@ PREFIX rid: # Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. # # Test that every rid:Replaced_by value is an IRI reference to another class, not a string literal such as -# "RID11030". A literal cannot be followed by tooling that walks retired terms to their replacements. +# "RID11030". A literal cannot be followed by tooling that walks obsolete terms to their replacements. # # VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: -# - The retired class carrying the pointer. +# - The obsolete class carrying the pointer. # - rid:Replaced_by. # - The literal value that should have been an IRI. # diff --git a/tests/sparql/robot/live_class_under_obsolete_parent.rq b/tests/sparql/robot/live_class_under_obsolete_parent.rq new file mode 100644 index 0000000..8d02bf1 --- /dev/null +++ b/tests/sparql/robot/live_class_under_obsolete_parent.rq @@ -0,0 +1,24 @@ +PREFIX rdfs: +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that no class is filed under an obsolete class without itself being marked obsolete. An obsolete class +# is one filed, directly or through another obsolete class, under RID15849 ("Obsolete RadLex Term"). Filing +# makes every descendant obsolete, so a live class left under a class being retired is retired silently. +# rid:Preferred_Name_for_Obsolete is the per-class mark that the retirement was intended. RID15849 itself is +# not an obsolete parent, since obsolete classes are meant to hang under it. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The class that was never marked obsolete. +# - rdfs:subClassOf. +# - The obsolete parent. +# +SELECT ?entity ?property ?value +WHERE { + BIND(rdfs:subClassOf AS ?property) + ?entity ?property ?value . + ?value rdfs:subClassOf+ rid:RID15849 . + FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_name } +} diff --git a/tests/sparql/robot/live_class_with_preferred_name_for_obsolete.rq b/tests/sparql/robot/live_class_with_preferred_name_for_obsolete.rq new file mode 100644 index 0000000..b99fd21 --- /dev/null +++ b/tests/sparql/robot/live_class_with_preferred_name_for_obsolete.rq @@ -0,0 +1,22 @@ +PREFIX rdfs: +PREFIX rid: + +# +# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. +# +# Test that only obsolete classes carry rid:Preferred_Name_for_Obsolete. An obsolete class is one filed, +# directly or through another obsolete class, under RID15849 ("Obsolete RadLex Term"). A live class carrying +# the property was made obsolete in name but never filed under RID15849, so tools that exclude RID15849's subclasses +# still offer it as a live term. +# +# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: +# - The live class carrying the property. +# - rid:Preferred_Name_for_Obsolete. +# - The obsolete name. +# +SELECT ?entity ?property ?value +WHERE { + BIND(rid:Preferred_Name_for_Obsolete AS ?property) + ?entity ?property ?value . + FILTER NOT EXISTS { ?entity rdfs:subClassOf+ rid:RID15849 } +} diff --git a/tests/sparql/robot/replaced_by_only_on_obsolete_class.rq b/tests/sparql/robot/live_class_with_replaced_by.rq similarity index 53% rename from tests/sparql/robot/replaced_by_only_on_obsolete_class.rq rename to tests/sparql/robot/live_class_with_replaced_by.rq index 2471a32..718df01 100644 --- a/tests/sparql/robot/replaced_by_only_on_obsolete_class.rq +++ b/tests/sparql/robot/live_class_with_replaced_by.rq @@ -4,9 +4,9 @@ PREFIX rid: # # Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. # -# Test that only retired classes carry rid:Replaced_by. A retired class is one that carries -# rid:Preferred_Name_for_Obsolete or is filed under RID15849 ("Obsolete RadLex Term"). A live class with a -# replacement pointer is contradictory: either the retirement was never recorded or the pointer is stray. +# Test that only obsolete classes carry rid:Replaced_by. An obsolete class is one filed, directly or through +# another obsolete class, under RID15849 ("Obsolete RadLex Term"). A live class with a replacement pointer is +# contradictory: either the class was never filed as obsolete or the pointer is stray. # # VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: # - The live class carrying the pointer. @@ -17,6 +17,5 @@ SELECT ?entity ?property ?value WHERE { BIND(rid:Replaced_by AS ?property) ?entity ?property ?value . - FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_name } - FILTER NOT EXISTS { ?entity rdfs:subClassOf rid:RID15849 } + FILTER NOT EXISTS { ?entity rdfs:subClassOf+ rid:RID15849 } } diff --git a/tests/sparql/robot/radlexid_matches_iri.rq b/tests/sparql/robot/mismatched_radlexid.rq similarity index 89% rename from tests/sparql/robot/radlexid_matches_iri.rq rename to tests/sparql/robot/mismatched_radlexid.rq index eeac479..1efd594 100644 --- a/tests/sparql/robot/radlexid_matches_iri.rq +++ b/tests/sparql/robot/mismatched_radlexid.rq @@ -9,8 +9,7 @@ PREFIX rid: # design, so any disagreement is a copy or typing error that desynchronises ID-keyed consumers from IRI-keyed # ones. A class in the RID namespace with no rid:RadLexID at all is also a violation. # -# Scope: classes whose IRI local name has the form RID. Classes with other local names are reported -# by class_iri_is_rid.rq instead. +# Scope: classes whose IRI local name has the form RID. # # VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: # - The class whose ID disagrees with (or is missing from) its IRI. diff --git a/tests/sparql/robot/obsolete_class_not_a_parent.rq b/tests/sparql/robot/obsolete_class_not_a_parent.rq deleted file mode 100644 index db37810..0000000 --- a/tests/sparql/robot/obsolete_class_not_a_parent.rq +++ /dev/null @@ -1,26 +0,0 @@ -PREFIX rdfs: -PREFIX rid: - -# -# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. -# -# Test that no live class is asserted as a subclass of a retired class. A retired class is one that carries -# rid:Preferred_Name_for_Obsolete or is filed under RID15849 ("Obsolete RadLex Term"). RID15849 itself is -# exempt as a parent, since retired classes are meant to hang under it, and a retired child under a retired -# parent is not reported. -# -# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: -# - The live class. -# - rdfs:subClassOf. -# - The retired parent. -# -SELECT DISTINCT ?entity ?property ?value -WHERE { - BIND(rdfs:subClassOf AS ?property) - ?entity ?property ?value . - FILTER(isIRI(?value)) - FILTER(?value != rid:RID15849) - { ?value rid:Preferred_Name_for_Obsolete ?_pname } UNION { ?value rdfs:subClassOf rid:RID15849 } - FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_cname } - FILTER NOT EXISTS { ?entity rdfs:subClassOf rid:RID15849 } -} diff --git a/tests/sparql/robot/replaced_by_target_is_live_class.rq b/tests/sparql/robot/replaced_by_target_is_live_class.rq deleted file mode 100644 index 8d6d826..0000000 --- a/tests/sparql/robot/replaced_by_target_is_live_class.rq +++ /dev/null @@ -1,30 +0,0 @@ -PREFIX rdfs: -PREFIX owl: -PREFIX rid: - -# -# Part of the RadLex ontology SPARQL test suite. Bindings to this query represent violations of the test. -# -# Test that a rid:Replaced_by pointer aims at a class that exists and is not itself retired. A retired class is -# one that carries rid:Preferred_Name_for_Obsolete or is filed under RID15849 ("Obsolete RadLex Term"). A pointer -# to a retired class is a chained retirement that was never re-pointed at the live replacement; a pointer to an -# undeclared IRI dangles. -# -# VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: -# - The retired class carrying the pointer. -# - rid:Replaced_by. -# - The target IRI that is retired or undeclared. -# -SELECT DISTINCT ?entity ?property ?value -WHERE { - BIND(rid:Replaced_by AS ?property) - ?entity ?property ?value . - FILTER(isIRI(?value)) - { - FILTER NOT EXISTS { ?value a owl:Class } - } - UNION - { - { ?value rid:Preferred_Name_for_Obsolete ?_name } UNION { ?value rdfs:subClassOf rid:RID15849 } - } -}