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