Files
app-organization-portal/config/report-profiles/report-spec-shapes.ttl
2026-09-26 23:24:13 +02:00

213 lines
6.0 KiB
Turtle

# Shapes for the report spec itself (rep:ReportSpec).
# Reference definition of the spec format: a machine-readable
# contract that doubles as documentation. validate_spec does more than this
# graph can express: it walks every path through the mounted profile and
# refuses what shapes alone cannot see (columns ending on a link without
# sh:nodeKind sh:IRI, unresolved
# hops, anyOf term limits, filters without a condition).
#
# Not yet: sh:count, sh:sum, sh:orderBy, sh:limit, sh:offset, rep:graph.
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix dct: <http://purl.org/dc/terms/> .
@prefix rep: <http://mu.semte.ch/vocabularies/reporting/> .
<http://data.lblod.info/id/report-profiles/report-spec>
a owl:Ontology ;
dct:title "Report spec shapes" ;
sh:prefixes [
sh:declare [ sh:prefix "rep" ; sh:namespace "http://mu.semte.ch/vocabularies/reporting/"^^xsd:anyURI ] ;
sh:declare [ sh:prefix "sh" ; sh:namespace "http://www.w3.org/ns/shacl#"^^xsd:anyURI ] ;
sh:declare [ sh:prefix "rdf" ; sh:namespace "http://www.w3.org/1999/02/22-rdf-syntax-ns#"^^xsd:anyURI ] ;
sh:declare [ sh:prefix "rdfs"; sh:namespace "http://www.w3.org/2000/01/rdf-schema#"^^xsd:anyURI ] ;
sh:declare [ sh:prefix "dct" ; sh:namespace "http://purl.org/dc/terms/"^^xsd:anyURI ] ;
] .
rep:ReportSpecShape
a sh:NodeShape ;
rdfs:label "rapportspec" ;
sh:targetClass rep:ReportSpec ;
sh:property [
sh:path dct:title ;
sh:name "titel" ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path rep:profile ;
sh:name "profiel" ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:targetClass ;
sh:name "klasse" ;
sh:nodeKind sh:IRI ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
# rep:entity picks the shape when two entities share one sh:targetClass
# (the profile lists the entity URI per entity).
sh:property [
sh:path rep:entity ;
sh:name "entiteit" ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:property ;
sh:name "filter" ;
sh:node rep:FilterShape ;
] ;
sh:property [
sh:path rep:columns ;
sh:name "kolommen" ;
sh:minCount 1 ;
sh:maxCount 1 ;
] .
# A filter: a path plus exactly one condition. A path without a condition
# selects everything and is refused by check.js (filterConstraint).
rep:FilterShape
a sh:NodeShape ;
sh:property [
sh:path sh:path ;
sh:name "pad" ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:hasValue ;
sh:name "gelijk aan" ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:in ;
sh:name "in lijst" ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:minInclusive ;
sh:name "vanaf" ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:maxInclusive ;
sh:name "tot en met" ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:minExclusive ;
sh:name "na" ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:maxExclusive ;
sh:name "voor" ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:pattern ;
sh:name "regex" ;
sh:datatype xsd:string ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:flags ;
sh:name "regex-vlaggen" ;
sh:datatype xsd:string ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:minCount ;
sh:name "minimaal aantal" ;
sh:datatype xsd:integer ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:maxCount ;
sh:name "maximaal aantal" ;
sh:datatype xsd:integer ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path rep:anyOf ;
sh:name "een van deze woorden" ;
sh:maxCount 1 ;
] ;
# rep:where: a condition on a node this filter walks through, written as a
# filter from the row. The steps it shares with this filter are the same
# nodes. check.js refuses one that shares no step, and one nested in
# another (whereConditions).
sh:property [
sh:path rep:where ;
sh:name "voorwaarde onderweg" ;
sh:node rep:FilterShape ;
] ;
sh:property [
sh:path rdfs:label ;
sh:name "label" ;
sh:maxCount 0 ;
] .
# A column: path, label, collect mode, separator. No constraints here;
# check.js refuses a constraint inside rep:columns (columnPure). The one
# exception is sh:nodeKind sh:IRI: the cell shows the URI of the node the
# path ends on, and only then may the path end on a link. A condition
# on a node the column walks through goes in rep:where; it drops values from
# the cell, never rows.
rep:ColumnShape
a sh:NodeShape ;
sh:property [
sh:path sh:path ;
sh:name "pad" ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path rdfs:label ;
sh:name "kolomnaam" ;
sh:datatype xsd:string ;
sh:minCount 1 ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path rep:collect ;
sh:name "verzamelwijze" ;
sh:nodeKind sh:IRI ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:separator ;
sh:name "scheidingsteken" ;
sh:datatype xsd:string ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path sh:nodeKind ;
sh:name "toon de URI" ;
sh:in ( sh:IRI ) ;
sh:maxCount 1 ;
] ;
sh:property [
sh:path rep:where ;
sh:name "voorwaarde onderweg" ;
sh:node rep:FilterShape ;
] .
# rep:collect takes exactly these values (SHACL Core groupConcat is the
# default when absent; min/max are SHACL-AF names). A shapes graph cannot
# enumerate an IRI value set without a class; check.js enforces it (columnPure).
rep:RowShape
a sh:NodeShape ; rdfs:comment "rep:collect value: one CSV line per value" .
# rep:self as sh:path marks the row's own subject URI: nothing to walk,
# the runner takes it from the seed.
rep:self
a rdf:Property ;
rdfs:comment "in a column's sh:path slot: the row's own subject URI" .