From 6ba3b0eb78417e505386d27be6a349b183e49b51 Mon Sep 17 00:00:00 2001 From: Rashif Ray Rahman Date: Sat, 8 Nov 2025 00:39:33 +0600 Subject: [PATCH] feat: initial support for fetching embedded SHACL info in OWL Support fetching domain, range and cardinality information from vocabularies containing a SHACL graph. The queries are different depending on whether it is an object property or a datatype property. Where the information isn't available, there will be empty cells in the report. There is also support for value node constraints for certain patterns of expressing ranges for IRIs with `sh:hasValue`, such as SKOS vocabularies, used for example in recent versions of the eProcurement ontology (ePO): ```ttl sh:nodeKind sh:IRI ; sh:node [ rdf:type sh:NodeShape ; sh:property [ sh:path skos:inScheme ; sh:hasValue atold:language ; ] ; ] . ``` Currently, this feature is NOT for capturing changes in the domain, range and cardinality, and is only for the case of ADDED instances of such resources, not their modifications. The information won't show up for individual property changes on the resources (added/updated/changed/moved labels and the whole shebang). The queries in those cases will differ between modification types, and there is the question of how to fit all of the information in an already-crowded table. Work will continue on how best to approach this. P.S: There are nested OPTIONALs as the graph may not exist, so performance may be affected, though hopefully not by too much. If that becomes a concern, we can turn these over onto a new template, where a SHACL graph would be made mandatory. --- .../query_templates/instance_additions.rq | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/dqgen/resources/query_templates/instance_additions.rq b/dqgen/resources/query_templates/instance_additions.rq index db8cf31..919283b 100644 --- a/dqgen/resources/query_templates/instance_additions.rq +++ b/dqgen/resources/query_templates/instance_additions.rq @@ -36,7 +36,11 @@ PREFIX sd: PREFIX sh: PREFIX xhv: # identify added instances +{% if cls == "owl:ObjectProperty" or cls == "owl:DatatypeProperty" %} +SELECT distinct ?class ?instance ?prefLabel ?prefLabelLang ?domain ?range ?minCardinality ?maxCardinality ("{{type_of_action}}" as ?actionType) +{% else %} SELECT distinct ?class ?instance ?prefLabel ?prefLabelLang ("{{type_of_action}}" as ?actionType) +{% endif %} WHERE { GRAPH ?versionHistoryGraph { # parameters @@ -143,5 +147,39 @@ WHERE { ?instance ?p [] . } } +{% if cls == "owl:ObjectProperty" %} + # and we get some domain, range and cardinality information from SHACL shapes if available + OPTIONAL { + GRAPH ?newVersionGraph { + { + ?nodeShape shacl:property ?propertyShape ; + shacl:targetClass ?domain . + ?propertyShape shacl:path ?instance ; + shacl:class ?range . + } + UNION + { + ?nodeShape shacl:property ?propertyShape ; + shacl:targetClass ?domain . + ?propertyShape shacl:path ?instance ; + shacl:node/shacl:property/shacl:hasValue ?range . + } + OPTIONAL { ?propertyShape shacl:minCount ?minCardinality } + OPTIONAL { ?propertyShape shacl:maxCount ?maxCardinality } + } + } +{% elif cls == "owl:DatatypeProperty" %} + # and we get some domain, range and cardinality information from SHACL shapes if available + OPTIONAL { + GRAPH ?newVersionGraph { + ?nodeShape shacl:property ?propertyShape ; + shacl:targetClass ?domain . + ?propertyShape shacl:path ?instance ; + shacl:datatype ?range . + OPTIONAL { ?propertyShape shacl:minCount ?minCardinality } + OPTIONAL { ?propertyShape shacl:maxCount ?maxCardinality } + } + } +{% endif %} } ORDER BY ?instance