Warning:
This wiki has been archived and is now read-only.

Classes and Shapes

From RDF Data Shapes Working Group
Jump to: navigation, search

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