# SHACL metamodel and syntax checker # doesn't check that shapes do not mention themselves # Core Language sh:Shape rdf:type rdfs:Class . # RDFS domains and ranges for the properties sh:scopeClass rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Class . sh:scopeNode rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Resource . sh:scopePropertyObject rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:Property . sh:scopePropertySubject rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:Property . sh:scopeAllObjects rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:boolean . sh:scopeAllSubjects rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:boolean . sh:filter rdf:type rdf:Property; rdfs:domain sh:Shape ; rdfs:range sh:Shape . sh:closed rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:boolean . sh:ignoredProperty rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:Property . sh:class rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Class . sh:classIn rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:List . sh:datatype rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Datatype . sh:datatypeIn rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:List . sh:directType rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Class . sh:minLength rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:Integer . sh:maxLength rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:Integer . sh:minExclusive rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Literal . sh:minInclusive rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Literal . sh:maxExclusive rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Literal . sh:maxInclusive rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Literal . sh:nodeKind rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:Resource . sh:pattern rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:equals rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:notEquals rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:lessThan rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:lessThanOrEquals rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:fillers rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:list rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range sh:Shape . sh:shape rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range sh:Shape . sh:and rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:or rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:not rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range sh:Shape . sh:minCount rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:Integer . sh:maxCount rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:Integer . sh:uniqueLang rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range xs:boolean . sh:partition rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdfs:List . sh:inverse rdf:type rdf:Property ; rdfs:range rdf:Property . # shapes that reiterate RDFS ranges (if this is felt desirable ) shmm:scopeClassRange rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:scopeClass [ sh:class rdfs:Class ] ) . # and so on for most of the SHACL constructs # shapes that go beyond the RDFS range shmm:scopeAllObjectsUnique rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:closed [ sh:maxCount 1 ] ) . sh:scopeAllSubjectsUnique rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:closed [ sh:maxCount 1 ] ) . shmm:closedUnique rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:closed [ sh:maxCount 1 ] ) . shmm:classInSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:classIn [ rdf:list rdfs:Class ] ) ; shmm:datatypeInSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:datatypeIn [ rdf:list rdfs:Datatype ] ) ; shmm:minLengthSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:minLength [ sh:minInclusive 0 ] ) . shmm:maxLengthSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:minLength [ sh:minInclusive 0 ] ) . shmm:nodeKindSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:severity [ sh:in ( sh:BlankNode sh:IRI sh:Literal ) ] ) . shmm:patternSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:pattern [ sh:or ( [ sh:datatype xs:string ] # no flags, just a pattern [ sh:list [ sh:datatype xs:string ] ; # pattern and flags are both strings sh:fillers ( ( sh:rest sh:rest ) [ sh:value rdf:nil ] ) ] ) ] ) . shmm:equalsSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:equals [ sh:list shmm:pathShape ] ) . shmm:notEqualsSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:notEquals [ sh:list shmm:pathShape ] ) . shmm:lessThanSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:lessThan [ sh:list shmm:pathShape ] ) . shmm:lessThanOrEqualsSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:lessThanOrEquals [ sh:list shmm:pathShape ] ) . shmm:fillersSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:fillers [ sh:list [ sh:and ( ) ] ; # no common shape for the list elements sh:fillers ( sh:first shmm:pathShape ) ; sh:fillers ( ( sh:rest sh:first ) sh:Shape ) ; sh:fillers ( ( sh:rest sh:rest ) [ sh:value rdf:nil ] ) ] ) . shmm:andSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:and [ sh:list sh:Shape ] ) ; shmm:orSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:or [ sh:list sh:Shape ] ) ; shmm:minCountSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:minCount [ sh:minInclusive 0 ] ) . shmm:maxCountSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:maxCount [ sh:minInclusive 0 ] ) . shmm:uniqueLangSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:uniqueLang [ sh:maxCount 1 ] ) . shmm:partitionSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:partition [ sh:list sh:Shape ] ) ; # utility shapes shmm:pathShape rdf:type sh:Shape ; sh:or ( pathPartShape [ sh:not pathPartShape ; sh:list pathPartShape ] ) . shmm:pathPartShape rdf:type sh:Shape ; sh:or ( [ sh:class rdf:Property ] [ sh:not [ sh:class rdf:Property ] ; sh:fillers ( sh:inverse [ sh:minCount 1 ; sh:maxCount 1 ; sh:class rdf:Property ] ) ] ) . # decorations sh:name rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:langString . sh:description rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:langString . sh:order rdf:type rdf:Property ; rdfs:domain sh:Shape ; rdfs:range rdf:langString . sh:defaultValue rdf:type rdf:Property ; rdfs:domain sh:Shape . sh:severity rdf:type rdf:Property ; rdfs:domain sh:Shape . sh:orderSyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:order [ sh:maxCount 1 ] ) . sh:severitySyntax rdf:type sh:Shape ; sh:scopeClass sh:Shape ; sh:fillers ( sh:severity [ sh:in ( sh:Info sh:Warning sh:Violation ) ] ) . # Extension language - not needed if sticking to core # # ex:example rdf:type sh:Template ; # sh:argument ( ex:predicate [ sh:class rdf:Property; # sh:minCount 1 ; sh:maxCount 1 ] ) ; # sh:argument ( ex:lang [ sh:datatype xs:string ] ) ; # sh:sparql """SELECT ... """ . # # ex:exampleShape rdf:type sh:Shape ; # ex:example [ ex:predicate ex:p ; ex:lang "de" ; ex:lang "en" ] . # sh:Component is the class of properties that make SHACL components sh:Component rdfs:subClassOf rdf:Property . sh:Component rdf:type rdfs:Class . # the code components actually belong to sh:Component, but this is not # needed if sticking to the core sh:class rdf:type sh:Component . sh:classIn rdf:type sh:Component . sh:datatype rdf:type sh:Component . sh:datatypeIn rdf:type sh:Component . sh:directType rdf:type sh:Component . sh:minLength rdf:type sh:Component . sh:maxLength rdf:type sh:Component . sh:minExclusive rdf:type sh:Component . sh:minInclusive rdf:type sh:Component . sh:maxExclusive rdf:type sh:Component . sh:maxInclusive rdf:type sh:Component . sh:nodeKind rdf:type sh:Component . sh:pattern rdf:type sh:Component . sh:equals rdf:type sh:Component . sh:notEquals rdf:type sh:Component . sh:lessThan rdf:type sh:Component . sh:lessThanOrEquals rdf:type sh:Component . sh:fillers rdf:type sh:Component . sh:list rdf:type sh:Component . sh:shape rdf:type sh:Component . sh:and rdf:type sh:Component . sh:or rdf:type sh:Component . sh:not rdf:type sh:Component . sh:minCount rdf:type sh:Component . sh:maxCount rdf:type sh:Component . sh:uniqueLang rdf:type sh:Component . sh:partition rdf:type sh:Component . # sh:Template is the class of templates, which each make SHACL components sh:Template rdf:type rdfs:Class . sh:Template rdfs:subClassOf sh:Component . sh:Function rdf:type rdfs:Class . sh:labelTemplate rdf:type rdf:Property ; rdfs:domain sh:Template ; rdfs:range xs:string . sh:message rdf:type rdf:Property ; rdfs:domain sh:Template ; rdfs:range xs:string . sh:argument rdf:type rdf:Property ; rdfs:domain rdfs:Resource ; rdfs:range rdf:List . sh:sparql rdf:type sh:Component ; rdfs:domain rdfs:Resource ; rdfs:range xs:string . # Decorations sh:labelTemplate rdf:type rdf:Property ; rdfs:domain sh:Template ; rdfs:range rdf:langString . sh:message rdf:type rdf:Property ; rdfs:domain sh:Template ; rdfs:range rdf:langString . shmm:argumentSubject rdf:type sh:Shape ; sh:scopePropertySubject sh:sparql ; sh:or ( [ sh:class sh:Template ] [ sh:class sh:Function ] ) . shmm:argumentSyntax rdf:type sh:Shape ; sh:scopeClass sh:Template ; sh:fillers ( sh:argument [ sh:list [ sh:and ( ) ] ; # no common shape for the list elements sh:fillers ( sh:first rdf:Property ) ; sh:fillers ( ( sh:rest sh:first ) sh:Shape ) ; sh:fillers ( ( sh:rest sh:rest ) [ sh:value rdf:nil ] ) ] ) . shmm:sparqlSubject rdf:type sh:Shape ; sh:scopePropertySubject sh:sparql ; sh:or ( [ sh:class sh:Shape ] [ sh:class sh:Template ] [ sh:class sh:Function ] ) . # Usage of templates in shapes (functions are hidden in SPARQL code) # may have bugs! requires notHasShape! # the subject of any template belongs to sh:Shape shmm:templateSubject rdf:type sh:Shape ; sh:scopeClass sh:Template ; sh:sparql """SELECT ?shape $this WHERE { ?shape $this ?arguments . NOT EXISTS { ?shape rdf:type sh:Shape } }""" . # the object of any template matches the template's arguments shmm:templateObject rdf:type sh:Shape ; sh:scopeClass sh:Template ; sh:sparql """SELECT ?shape $this ?argument ?values WHERE { ?this sh:argument ( ?argument ?shape ) . ?shape ?this ?arguments . ?arguments ?argument ?values . GROUP BY ?shape $this ?argument HAVING ( notHasShape(?values,?shape) ) }""" .