Skip to content

Commit 2c0dc70

Browse files
feat: add SPARQL QC queries for CCO release pipeline (Tasks 1-9)
- Fix CCO_classes_have_BFO_superclass.sparql namespace (v1 -> v2) - Add validate-profile DL targets to Makefile (Step 6b) - Add build/artifacts/ and build/lib/ to .gitignore - New: no_cco_elucidation.sparql (Step 6j) - New: missing_definition_source.sparql (Step 6h) - New: exactly_1_label.sparql (Step 6c) - New: exactly_1_curated_in.sparql (Step 6c) - New: annotation_language_tag.sparql (Step 6i) - New: iri_format_check.sparql (Step 6e) - New: curated_in_matches_ontology.sparql (Step 6f) - New: no_duplicate_declarations.sparql (Step 6d) All queries tested against CommonCoreOntologiesMerged.ttl and verified with synthetic TTL files to confirm non-silent failure. Pre-release gaps surfaced: 815 missing definition sources, 1 missing curated-in (ont00001660), 9 missing @en language tags.
1 parent 4b48cca commit 2c0dc70

11 files changed

+403
-2
lines changed

.github/deployment/sparql/CCO_classes_have_BFO_superclass.sparql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
1313
SELECT DISTINCT ?class ?label
1414
WHERE {
1515
?class a owl:Class .
16-
FILTER (regex(str(?class),"http://www.ontologyrepository.com/CommonCoreOntologies/"))
16+
FILTER (regex(str(?class),"https://www.commoncoreontologies.org/"))
1717
FILTER NOT EXISTS {?class rdfs:subClassOf+ <http://purl.obolibrary.org/obo/BFO_0000001> }
1818
OPTIONAL {?class rdfs:label ?label}
1919
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Title:
2+
# Annotation Values Must Have English Language Tag
3+
# Constraint Description:
4+
# All natural-language annotation values on CCO ontology elements must carry
5+
# an English (@en) language tag. This applies to: rdfs:label, skos:definition,
6+
# rdfs:comment, skos:altLabel, skos:prefLabel, skos:editorNote,
7+
# cco:ont00001737 [doctrinal definition], and cco:ont00001748 [doctrinal label].
8+
# Values typed as xsd:anyURI are exempt (they are IRI references, not NL text).
9+
# English dialect tags such as @en-US and @en-GB are accepted.
10+
# Severity:
11+
# Error
12+
# Reference:
13+
# # Author:
14+
# github.com/shanmukhkalasamudram
15+
16+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
17+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
18+
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
19+
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
20+
PREFIX cco: <https://www.commoncoreontologies.org/>
21+
22+
SELECT DISTINCT ?resource ?prop ?val ?error
23+
WHERE {
24+
VALUES ?type {
25+
owl:Class
26+
owl:ObjectProperty
27+
owl:AnnotationProperty
28+
owl:DatatypeProperty
29+
owl:NamedIndividual
30+
}
31+
# Scope to natural-language annotation properties only.
32+
# xsd:anyURI-typed values (IRI references) are handled by the datatype filter below.
33+
VALUES ?prop {
34+
rdfs:label
35+
skos:definition
36+
rdfs:comment
37+
skos:altLabel
38+
skos:prefLabel
39+
skos:editorNote
40+
cco:ont00001737
41+
cco:ont00001748
42+
}
43+
?resource a ?type .
44+
FILTER (STRSTARTS(STR(?resource), "https://www.commoncoreontologies.org/"))
45+
FILTER (!isBlank(?resource))
46+
?resource ?prop ?val .
47+
FILTER (isLiteral(?val))
48+
# langMatches handles dialect tags: @en-US, @en-GB all pass.
49+
# lang("") of a plain literal returns "" — langMatches("", "en") = FALSE — flagged.
50+
FILTER (!langMatches(lang(?val), "en"))
51+
# Allow xsd:anyURI values (IRI references do not need a language tag).
52+
FILTER (datatype(?val) != xsd:anyURI)
53+
BIND (CONCAT(
54+
"ERROR: Term ", STR(?resource),
55+
" has annotation <", STR(?prop),
56+
"> with value \"", STR(?val),
57+
"\" that is missing an @en language tag (lang='", lang(?val), "')."
58+
) AS ?error)
59+
}
60+
ORDER BY ?resource ?prop
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Title:
2+
# cco:ont00001760 Value Must Point to a Declared CCO Ontology
3+
# Constraint Description:
4+
# The value of cco:ont00001760 [is curated in ontology] on every CCO ontology
5+
# element must be the IRI of a CCO ontology that is actually declared as
6+
# owl:Ontology within the CCO namespace
7+
# (https://www.commoncoreontologies.org/).
8+
# This catches values that:
9+
# - Point to a non-existent or deleted ontology module.
10+
# - Use the old v1 namespace (http://www.ontologyrepository.com/...).
11+
# - Contain a typo in the ontology name.
12+
# Severity:
13+
# Error
14+
# Reference:
15+
# CCO Release Process v2, Step 6c / Step 6f
16+
# Author:
17+
# github.com/shanmukhkalasamudram
18+
19+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
20+
PREFIX cco: <https://www.commoncoreontologies.org/>
21+
22+
SELECT DISTINCT ?resource ?curatedIn ?error
23+
WHERE {
24+
VALUES ?type {
25+
owl:Class
26+
owl:ObjectProperty
27+
owl:AnnotationProperty
28+
owl:DatatypeProperty
29+
owl:NamedIndividual
30+
}
31+
?resource a ?type .
32+
FILTER (STRSTARTS(STR(?resource), "https://www.commoncoreontologies.org/"))
33+
FILTER (!isBlank(?resource))
34+
?resource cco:ont00001760 ?curatedIn .
35+
# The merged file only carries one owl:Ontology IRI (CommonCoreOntologiesMerged),
36+
# so dynamic lookup against owl:Ontology triples is not feasible for merged runs.
37+
# Instead validate against the fixed allowlist of the 11 CCO module ontology IRIs.
38+
# Update this list whenever a module is added or removed.
39+
FILTER (STR(?curatedIn) NOT IN (
40+
"https://www.commoncoreontologies.org/AgentOntology",
41+
"https://www.commoncoreontologies.org/ArtifactOntology",
42+
"https://www.commoncoreontologies.org/CurrencyUnitOntology",
43+
"https://www.commoncoreontologies.org/EventOntology",
44+
"https://www.commoncoreontologies.org/ExtendedRelationOntology",
45+
"https://www.commoncoreontologies.org/FacilityOntology",
46+
"https://www.commoncoreontologies.org/GeospatialOntology",
47+
"https://www.commoncoreontologies.org/InformationEntityOntology",
48+
"https://www.commoncoreontologies.org/QualityOntology",
49+
"https://www.commoncoreontologies.org/TimeOntology",
50+
"https://www.commoncoreontologies.org/UnitsOfMeasureOntology"
51+
))
52+
BIND (CONCAT(
53+
"ERROR: Term <", STR(?resource),
54+
"> has cco:ont00001760 value <", STR(?curatedIn),
55+
"> which does not match any known CCO module ontology IRI."
56+
) AS ?error)
57+
}
58+
ORDER BY ?resource
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Title:
2+
# Exactly One cco:ont00001760 [is curated in ontology] Per Ontology Element
3+
# Constraint Description:
4+
# All CCO ontology elements (classes, properties, individuals) must have
5+
# exactly one cco:ont00001760 annotation. This query flags:
6+
# (a) Elements with NO cco:ont00001760 annotation at all.
7+
# (b) Elements with MORE THAN ONE cco:ont00001760 annotation.
8+
# Severity:
9+
# Error
10+
# Reference:
11+
# CCO Release Process v2, Step 6c
12+
# Author:
13+
# github.com/shanmukhkalasamudram
14+
15+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
16+
PREFIX cco: <https://www.commoncoreontologies.org/>
17+
18+
SELECT DISTINCT ?resource ?error
19+
WHERE {
20+
{
21+
# Branch (a): missing cco:ont00001760 entirely
22+
# All patterns are self-contained inside each UNION branch so that
23+
# ?resource is properly bound before FILTER NOT EXISTS is evaluated.
24+
VALUES ?type {
25+
owl:Class
26+
owl:ObjectProperty
27+
owl:AnnotationProperty
28+
owl:DatatypeProperty
29+
owl:NamedIndividual
30+
}
31+
?resource a ?type .
32+
FILTER (regex(str(?resource), "https://www.commoncoreontologies.org/"))
33+
FILTER (!isBlank(?resource))
34+
FILTER NOT EXISTS { ?resource cco:ont00001760 ?any }
35+
BIND (CONCAT("ERROR: Term ", str(?resource), " is missing cco:ont00001760 [is curated in ontology].") AS ?error)
36+
}
37+
UNION
38+
{
39+
# Branch (b): more than one cco:ont00001760 annotation
40+
VALUES ?type {
41+
owl:Class
42+
owl:ObjectProperty
43+
owl:AnnotationProperty
44+
owl:DatatypeProperty
45+
owl:NamedIndividual
46+
}
47+
?resource a ?type .
48+
FILTER (regex(str(?resource), "https://www.commoncoreontologies.org/"))
49+
FILTER (!isBlank(?resource))
50+
?resource cco:ont00001760 ?val1 .
51+
?resource cco:ont00001760 ?val2 .
52+
FILTER (STR(?val1) != STR(?val2))
53+
BIND (CONCAT("ERROR: Term ", str(?resource), " has duplicate cco:ont00001760 values: <", str(?val1), "> and <", str(?val2), ">.") AS ?error)
54+
}
55+
}
56+
ORDER BY ?resource
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Title:
2+
# Exactly One rdfs:label Per Language Per Ontology Element
3+
# Constraint Description:
4+
# All CCO ontology elements (classes, properties, individuals) must have
5+
# exactly one rdfs:label. This query flags:
6+
# (a) Elements with NO rdfs:label at all.
7+
# (b) Elements with MORE THAN ONE rdfs:label in the same language.
8+
# Severity:
9+
# Error
10+
# Reference:
11+
# CCO Release Process v2, Step 6c
12+
# Pattern based on: exactly_1_prefLabel_per_lang.sparql
13+
# Author:
14+
# github.com/shanmukhkalasamudram
15+
16+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
17+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
18+
19+
SELECT DISTINCT ?resource ?error
20+
WHERE {
21+
{
22+
# Branch (a): missing rdfs:label entirely
23+
# All patterns must be self-contained inside each UNION branch so that
24+
# ?resource is properly bound before FILTER NOT EXISTS is evaluated.
25+
VALUES ?type {
26+
owl:Class
27+
owl:ObjectProperty
28+
owl:AnnotationProperty
29+
owl:DatatypeProperty
30+
owl:NamedIndividual
31+
}
32+
?resource a ?type .
33+
FILTER (regex(str(?resource), "https://www.commoncoreontologies.org/"))
34+
FILTER (!isBlank(?resource))
35+
FILTER NOT EXISTS { ?resource rdfs:label ?anyLbl }
36+
BIND (CONCAT("ERROR: Term ", str(?resource), " has no rdfs:label.") AS ?error)
37+
}
38+
UNION
39+
{
40+
# Branch (b): more than one rdfs:label in the same language
41+
VALUES ?type {
42+
owl:Class
43+
owl:ObjectProperty
44+
owl:AnnotationProperty
45+
owl:DatatypeProperty
46+
owl:NamedIndividual
47+
}
48+
?resource a ?type .
49+
FILTER (regex(str(?resource), "https://www.commoncoreontologies.org/"))
50+
FILTER (!isBlank(?resource))
51+
?resource rdfs:label ?lbl1 .
52+
?resource rdfs:label ?lbl2 .
53+
FILTER (?lbl1 != ?lbl2)
54+
FILTER (lang(?lbl1) = lang(?lbl2))
55+
FILTER (lang(?lbl1) != "")
56+
BIND (CONCAT("ERROR: Term ", str(?resource), " has duplicate rdfs:label values in language '", lang(?lbl1), "': \"", str(?lbl1), "\" and \"", str(?lbl2), "\".") AS ?error)
57+
}
58+
}
59+
ORDER BY ?resource
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Title:
2+
# CCO Term IRI Format Check
3+
# Constraint Description:
4+
# All CCO ontology elements (classes, properties, individuals) must have an IRI
5+
# matching the canonical CCO format:
6+
# https://www.commoncoreontologies.org/ont<8 digits>
7+
# Example: https://www.commoncoreontologies.org/ont00001760
8+
# Ontology-level IRIs (owl:Ontology) are not term IRIs and are intentionally
9+
# excluded from this check.
10+
# Severity:
11+
# Error
12+
# Reference:
13+
# CCO Release Process v2, Step 6e
14+
# Author:
15+
# github.com/shanmukhkalasamudram
16+
17+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
18+
19+
SELECT DISTINCT ?resource ?error
20+
WHERE {
21+
VALUES ?type {
22+
owl:Class
23+
owl:ObjectProperty
24+
owl:AnnotationProperty
25+
owl:DatatypeProperty
26+
owl:NamedIndividual
27+
}
28+
?resource a ?type .
29+
FILTER (STRSTARTS(STR(?resource), "https://www.commoncoreontologies.org/"))
30+
FILTER (!isBlank(?resource))
31+
# Flag any term IRI that does NOT match ont + exactly 8 digits.
32+
FILTER (!REGEX(STR(?resource), "^https://www\\.commoncoreontologies\\.org/ont[0-9]{8}$"))
33+
BIND (CONCAT(
34+
"ERROR: Term IRI <", STR(?resource),
35+
"> does not match the required CCO format https://www.commoncoreontologies.org/ont<8 digits>."
36+
) AS ?error)
37+
}
38+
ORDER BY ?resource
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Title:
2+
# Definition Source Required
3+
# Constraint Description:
4+
# All CCO classes and object properties that have a skos:definition should also
5+
# have a cco:ont00001754 [definition source] annotation. Terms missing a
6+
# definition source are flagged as warnings. Some terms may legitimately lack a
7+
# source (e.g., primitive relations); those should be reviewed case by case.
8+
# Severity:
9+
# Warning
10+
# Reference:
11+
# CCO Release Process v2, Step 6h
12+
# Pattern based on: min_1_eng_def.sparql
13+
# Author:
14+
# github.com/shanmukhkalasamudram
15+
16+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
17+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
18+
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
19+
PREFIX cco: <https://www.commoncoreontologies.org/>
20+
21+
SELECT DISTINCT ?resource ?label ?error
22+
WHERE {
23+
VALUES ?type { owl:Class owl:ObjectProperty }
24+
?resource a ?type .
25+
26+
# Must have a definition (already caught by min_1_eng_def if missing)
27+
?resource skos:definition ?definition .
28+
29+
# Scope to current CCO terms only
30+
FILTER (regex(str(?resource), "https://www.commoncoreontologies.org/"))
31+
FILTER (!isBlank(?resource))
32+
33+
# Flag those missing a definition source
34+
OPTIONAL { ?resource cco:ont00001754 ?source }
35+
FILTER (!bound(?source))
36+
37+
OPTIONAL { ?resource rdfs:label ?label }
38+
39+
BIND (CONCAT("WARNING: Term ", str(?resource), " has a definition but is missing cco:ont00001754 [definition source].") AS ?error)
40+
}
41+
ORDER BY ?resource
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Title:
2+
# No Use of Deprecated cco:elucidation Property
3+
# Constraint Description:
4+
# The annotation property cco:elucidation (from the old CCO v1 namespace) is
5+
# deprecated. It was replaced by skos:editorNote in CCO v2. Any CCO term that
6+
# still uses cco:elucidation as a predicate must be updated.
7+
# Severity:
8+
# Error
9+
# Author:
10+
# github.com/shanmukhkalasamudram
11+
# Inspired by: Giacomo Decolle
12+
13+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
14+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
15+
16+
SELECT DISTINCT ?subject ?label ?error
17+
WHERE {
18+
?subject <http://www.ontologyrepository.com/CommonCoreOntologies/elucidation> ?value .
19+
20+
# Scope to current CCO terms only
21+
FILTER (regex(str(?subject), "https://www.commoncoreontologies.org/"))
22+
FILTER (!isBlank(?subject))
23+
24+
OPTIONAL { ?subject rdfs:label ?label }
25+
26+
BIND (CONCAT("ERROR: Term ", str(?subject), " uses deprecated cco:elucidation. Replace with skos:editorNote.") AS ?error)
27+
}
28+
ORDER BY ?subject

0 commit comments

Comments
 (0)