Warning:
This wiki has been archived and is now read-only.
Classes and Shapes
From RDF Data Shapes Working Group
Some design options on how to use "classes" and/or "shapes" in the new language. The running example has three classes:
- Person (with a property "email")
- Issue (with the properties "reportedBy"). Persons showing up under "reportedBy" must always have an email address.
- Bug is a subclass of Issue, which has the extra property "reproducedBy".
The rough RDF Schema would be:
ex:Issue a rdfs:Class ; rdfs:label "Issue" . ex:reportedBy a rdf:Property ; rdfs:label "reported by" ; rdfs:domain ex:Issue ; rdfs:range schema:Person . ex:Bug a rdfs:Class ; rdfs:subClassOf ex:Issue ; rdfs:label "Bug" . ex:reproducedBy a rdf:Property ; rdfs:label "reproduced by" ; rdfs:domain ex:Bug ; rdfs:range schema:Person . schema:Person a rdfs:Class ; rdfs:label "Person" . schema:email a rdf:Property ; rdfs:label "email" ; rdfs:domain schema:Person ; rdfs:range xsd:string .
Option A: ldom:Shape, rdfs:Class, rdf:type and rdfs:subClassOf
In this design, classes can play the role of shapes, in that they may describe a constraint pattern that is never instantiated directly.
ex:Issue a rdfs:Class ; rdfs:label "Issue" ; ldom:property [ ldom:predicate ex:reportedBy ; rdfs:label "reported by" ; ldom:valueType schema:Person ; ldom:all ex:PersonWithEmail ; ] . ex:Bug a rdfs:Class ; rdfs:subClassOf ex:Issue ; rdfs:label "Bug" ; ldom:property [ ldom:predicate ex:reproducedBy ; rdfs:label "reproduced by" ; ldom:valueType schema:Person ; ] . schema:Person a rdfs:Class ; rdfs:label "Person" ; ldom:property [ ldom:predicate schema:email ; ldom:valueType xsd:string ; rdfs:label "email" ; ] . ex:PersonWithEmail a ldom:Shape ; # or: rdfs:Class ldom:property [ ldom:predicate schema:email ; ldom:minCount 1 ; ] . ex:ValidBug a ex:Bug ; ex:reportedBy ex:John ; ex:reproducedBy ex:Anon . ex:John a schema:Person ; schema:email "john@doe.com" . ex:Anon a schema:Person .
The explicit ldom:Shape can also be replaced with a blank node:
ex:Issue a rdfs:Class ; rdfs:label "Issue" ; ldom:property [ ldom:predicate ex:reportedBy ; rdfs:label "reported by" ; ldom:valueType schema:Person ; ldom:all [ ldom:property [ ldom:predicate schema:email ; ldom:minCount 1 ; ] ] ] .
Some validation entry points with results:
ldom:hasShape(ex:ValidBug, ex:Bug) = true ldom:hasShape(ex:John, ex:PersonWithEmail) = true ldom:hasShape(ex:Anon, ex:PersonWithEmail) = false
Option B: ldom:Shape, ldom:shape, ldom:subShapeOf
In this design, classes and shapes are completely separated, and a dedicated property ldom:shape is used to instruct the engine what to validate. ldom:subShapeOf represents "inheritance"/inclusion between shapes.
ex:Issue a rdfs:Class ; rdfs:label "Issue" . ex:IssueShape a ldom:Shape ; ldom:property [ ldom:predicate ex:reportedBy ; rdfs:label "reported by" ; ldom:valueType schema:Person ; ldom:all ex:PersonWithEmailShape ; ] . ex:Bug a rdfs:Class ; rdfs:subClassOf ex:Issue ; rdfs:label "Bug" . ex:BugShape a ldom:Shape ; ldom:subShapeOf ex:IssueShape ; ldom:property [ ldom:predicate ex:reproducedBy ; rdfs:label "reproduced by" ; ldom:valueType schema:Person ; ] . schema:Person a rdfs:Class ; rdfs:label "Person" . schema:PersonShape a ldom:Shape ; ldom:property [ ldom:predicate schema:email ; ldom:valueType xsd:string ; rdfs:label "email" ; ] . ex:PersonWithEmailShape a ldom:Shape ; ldom:property [ ldom:predicate schema:email ; ldom:minCount 1 ; ] . ex:ValidBug a ex:Bug ; ldom:shape ldom:BugShape ; ex:reportedBy ex:John ; ex:reproducedBy ex:Anon . ex:John a schema:Person ; ldom:shape ex:PersonShape ; schema:email "john@doe.com" . ex:Anon a schema:Person ; ldom:shape ex:PersonShape .
Some validation entry points with results:
ldom:hasShape(ex:ValidBug, ex:BugShape) = true ldom:hasShape(ex:John, ex:PersonWithEmailShape) = true ldom:hasShape(ex:Anon, ex:PersonWithEmailShape) = false