This repository was archived by the owner on Sep 23, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Update ShEx shapes to be more self-documented #246
Merged
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
8a2558d
Update person.shex
pmcb55 318e01c
Adding comments to document shapes
megoth 29b802f
Update shapes/contacts/address-book.shex
megoth 31837cc
Trying to make documentation text in bookmarks clearer
megoth b1cc5f6
Update shapes/contacts/group-index.shex
megoth a11c58b
Update shapes/contacts/address-book.shex
megoth 0495328
Update shapes/contacts/group.shex
megoth 681cc69
Added examples for address book and bookmarks
megoth 9a2e2db
Merge remote-tracking branch 'origin/pmcb55-patch-1' into pmcb55-patch-1
megoth 6ab42a7
Added comment about caching the name of each member in a group
megoth 56fff0b
minor tweaks to Shapes README
pmcb55 6c4d577
more very minor English tweaks
pmcb55 065237c
create my example structure - example2
pmcb55 24f290c
cleaned up to just one Shape example directory
pmcb55 70ccd00
typos, feedback from Arne
pmcb55 7e1e820
added details on #this, and quads vs triples
pmcb55 e355752
adds question on modelling countries
pmcb55 9070d09
Update shapes/README.md
megoth bd0ab17
Update shapes/README.md
megoth 99b9acc
fixes a couple of typos
pmcb55 4105368
fix: typos (#248)
matthieubosquet File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,106 +1,235 @@ | ||
| # Solid User Profile | ||
|
|
||
| We don't currently have a specific Shape defined for user profiles. But the | ||
| original Solid specification provides good guidance on the basic requirements | ||
| for the Profile Document expected to be returned when de-referencing a WebID. | ||
|
|
||
| See here for details: https://github.com/solid/solid-spec#webid-profile-documents | ||
|
|
||
| We'd certainly be open to ideas on how to model these basic discovery | ||
| requirements differently, and also on how to model the actual human user profile | ||
| information (such as date-of-birth, gender, address, etc.). | ||
|
|
||
| ## The 'country' problem? | ||
| An interesting discussion point would be how to model something as seemingly | ||
| trivial as the 'country' field of a user's address. If we take the ISO as just | ||
| an example of a recognized 'authority' when referring to "countries of the | ||
| world" (of course they are by no means the only such authority), then a problem | ||
| arises in that the ISO do not provide IRIs for the countries they otherwise | ||
| standardize identifiers for (e.g., 'ie' for Ireland, 'de' for Germany). | ||
|
|
||
| (About 7 years ago I specifically asked the ISO if they might consider minting | ||
| official IRIs for countries. Their reply was, literally, "**_We do not product | ||
| (sic) any RDF formats, I am sorry"_**!) | ||
|
|
||
| By way of example of how long-running a fundamental modelling question this is, | ||
| see this mailing list thread I started 6 years ago (and specifically see the | ||
| guidance from Martin Hepp, re-iterated in the final email from Bernard Vatant), | ||
| which basically recommends just using the standardized string values for | ||
| countries, and not using IRIs at all(!): | ||
| - Martin Hepp: https://lists.w3.org/Archives/Public/public-vocabs/2015Mar/0165.html | ||
| - Bernard Vatant (last email): https://lists.w3.org/Archives/Public/public-vocabs/2015Mar/0181.html | ||
|
|
||
| # Shapes | ||
|
|
||
| The remainder of this document describes the overall contents of this | ||
| directory, and attempts to explain some of the rationale for the modelling. | ||
|
|
||
| This directory also includes a series of Turtle files demonstrating expected | ||
| usage. | ||
|
|
||
| ### Note: Use of triples versus quads for user data | ||
|
|
||
| Currently our modelling does not use quads for user data at all. | ||
|
|
||
| Instead we propose using Named Graphs to support various forms of meta-data | ||
| that might be associated with any resource, for example, server-managed | ||
| meta-data (e.g., the date/time the resource was created or last modified, or | ||
| the backend storage node used, etc.), or Access Control List (ACL) data | ||
| associated with the resource, or perhaps ShEx shapes the resource must conform | ||
| to, or client-side meta-data associated with Non-RDF resources (e.g., the 'name' | ||
| of a JPEG image resource, or the camera aperture settings of the image), etc. | ||
|
|
||
| ## Structure of the Shapes, and example Turtle contained here. | ||
|
|
||
| This directory contains a `bookmark` directory and a `contact` directory. Each | ||
| contains ShEx Shapes and an `/example` folder showing demonstration Turtle files | ||
| conforming to the relevant Shapes. | ||
|
|
||
| The Turtle files of the `contact` examples also demonstrate how instances of Pod | ||
| Resources are currently interlinked (e.g., it demonstrates groups of people | ||
| referenced from address books). | ||
|
|
||
| ## Use of the `#this` fragment identifier | ||
|
|
||
| This modelling follows a naming convention whereby the fragment identifier | ||
| `#this` can be used to denote the main RDF Subject in the dataset that makes up | ||
| all the triples of a single Pod resource. | ||
|
|
||
| For example, in `shapes/contact/example/group/group3-soccer-team.ttl` we use the | ||
| `#this` fragment identifier on the RDF Subject of the triples associated with | ||
| the Soccer Team Group itself. The resource is free to include triples using as | ||
| many other RDF Subjects as it likes, but `#this` is intended to identify the | ||
| main entity of the resource. | ||
|
|
||
| ## Indexes | ||
|
|
||
| We use the term 'index' throughout our modelling with two very different | ||
| interpretations: | ||
|
|
||
| - Index in the sense of a single Pod resource containing a collection of | ||
| entities. E.g., a single Person-Index resource might contain a list of 50 | ||
| Person instances, where each instance contains a reference (or link) to the | ||
| actual Person resource elsewhere in my Pod, but may also contain a copy of | ||
| the Person's name and profile image perhaps, directly in the index too. | ||
| - Index in the sense of a '_default resource to look for when navigating to a | ||
| Container_'. In much the same way as browsers will automatically look for a | ||
| resource named 'index.html' when browsing to a website, our modelling can | ||
| store resources named 'index.ttl' in the root of containers, which our | ||
| applications can then expect to contain app-specific information. | ||
|
|
||
| ### Indexes as 'efficient containers for a collection of entities' | ||
|
|
||
| We chose not to model these collections using either native RDF lists (e.g., | ||
| `rdf:Seq`), nor LDP containers, nor some existing list or set vocabulary (e.g., | ||
| such as Schema.org's [ItemList](https://schema.org/ItemList), or the Ordered | ||
| List Ontology ([OLO](http://smiy.sourceforge.net/olo/spec/orderedlistontology.html))). | ||
| The reasons for this were: | ||
| - This was originally modelled around limitations of the first Solid server | ||
| (NSS). | ||
| - Efficiency reasons, i.e., where we wish to retrieve a collection of entities | ||
| in a single HTTP resource request (e.g., a list of people, perhaps with just | ||
| their first name and date-of-birth values), as opposed to needing to make | ||
| multiple HTTP requests, one for each Person resource in our list. | ||
|
|
||
|
|
||
| #### Example of index use | ||
|
|
||
| For example, a single AddressBook resource may reference two indexes, one for | ||
| the collection of email addresses in that AddressBook (i.e., using the | ||
| predicate `vcard:nameEmailIndex`), and one for the collection of groups in that | ||
| AddressBook (i.e., using the predicate `vcard:groupIndex`). | ||
|
|
||
|
|
||
| ## Bookmarks | ||
|
|
||
| We've decided to keep the structure of bookmarks simple, only storing `terms:created`, `terms:title`, and | ||
| `bookmark:recalls`. Note that some Solid bookmarking apps also use `foaf:maker`, but we didn't think it necessary in the | ||
| We've decided to keep the structure of bookmarks simple, only storing | ||
| `dcterms:created`, `dcterms:title`, and `bookmark:recalls`. Note that some Solid | ||
| bookmarking apps also use `foaf:maker`, but we didn't think it necessary in the | ||
| context of the PodBrowser, so we've chosen to make it optional. | ||
|
|
||
| We've also decided to omit the use of an index using `dct:references`, as this would require us to keep the index | ||
| up-to-date manually, and we think it's better to find the bookmarks using the `bookmark:Bookmark` class. | ||
| We've also decided to omit the use of an index using `dcterms:references`, as | ||
| this would require us to keep the index up-to-date manually, and we think it's | ||
| better to find the bookmarks using the `bookmark:Bookmark` class. | ||
|
|
||
| At some point we might need to group bookmarks, but at this point we've chosen to keep it simple and simply | ||
| implement bookmarks as a set of bookmarks that are stored in one file. | ||
| At some point we might need to group bookmarks, but at this point we've chosen | ||
| to keep it simple and simply implement bookmarks as a set of bookmarks that are | ||
| stored in one file. | ||
|
|
||
| ## Contacts | ||
|
|
||
| Because there are some differences between the ShEx shapes we've described and previous work on SHACL shapes we wanted | ||
| to explain the differences those shapes. Once they have been resolved, we might remove this README altogether. | ||
| Because there are some differences between the ShEx shapes we've described and | ||
| previous work on SHACL shapes, we wanted to explain the differences between | ||
| those shapes. Once these differences have all been resolved, we might remove | ||
| this README altogether. | ||
|
|
||
| ### Address Book: Differences between ShEx and SHACL | ||
|
|
||
| The following is how the SHACL shape in `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` differs from the ShEx shape in `contacts/address-book.shex`. | ||
| The following is how the SHACL shape in | ||
| `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` | ||
| differs from the ShEx shape in `contacts/address-book.shex`. | ||
|
|
||
| - vcard:AddressBook | ||
| - vcard:fn (instead of dc:title) | ||
| - There can be one or more instances | ||
| - There can be one or more instances. | ||
| - vcard:nameEmailIndex | ||
| - There can be one or more instances | ||
| - There is not a specific datatype set | ||
| - vcard:vcard:groupIndex | ||
| - Using terms (sh:count, sh:FollowMe) that isn't formalized | ||
| - There can be one or more instances. | ||
| - There is no specific datatype set. | ||
| - vcard:groupIndex | ||
| - Uses terms (e.g., sh:count, sh:FollowMe) that aren't formalized. | ||
|
|
||
| ### Group Index: Differences between ShEx and SHACL | ||
|
|
||
| The following is how the SHACL shape in `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` differ from the ShEx shape in `contacts/group-index.shex`. | ||
| The following is how the SHACL shape in | ||
| `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` | ||
| differs from the ShEx shape in `contacts/group-index.shex`. | ||
|
|
||
| - vcard:AddressBook | ||
| - vcard:fn | ||
| - Different cardinality ({1,m} vs {1,1}) | ||
| - Different cardinality ({1,m} vs {1,1}). | ||
| - vcard:includesGroup | ||
| - We used an inverse triple constraint instead (putting this term under vcard:Group shape instead) | ||
| - We used an inverse triple constraint instead (putting this term under | ||
| vcard:Group shape instead). | ||
|
|
||
| ### Group: Differences between ShEx and SHACL | ||
|
|
||
| The following is how the SHACL shape in `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` differ from the ShEx shape in `contacts/group.shex`. | ||
| The following is how the SHACL shape in | ||
| `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` | ||
| differs from the ShEx shape in `contacts/group.shex`. | ||
|
|
||
| - vcard:AddressBook | ||
| - vcard:includesGroup | ||
| - Using informal terms (sh:count, sh:FollowMe) | ||
| - Using informal terms (sh:count, sh:FollowMe). | ||
| - vcard:Group | ||
| - vcard:fn cardinality difference (one or more instead of just one) | ||
| - vcard:member (informal term) instead of vcard:hasMember | ||
| - vcard:fn cardinality difference (one or more instead of just one). | ||
| - vcard:member (informal term) instead of vcard:hasMember. | ||
|
|
||
| ### People Index: Differences between ShEx and SHACL | ||
|
|
||
| The following is how the SHACL shape in `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` differ from the ShEx shape in `contacts/people-index.shex`. | ||
| The following is how the SHACL shape in | ||
| `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` | ||
| differs from the ShEx shape in `contacts/person-index.shex`. | ||
|
|
||
| - vcard:Individual | ||
| - vcard:inAddressBook | ||
| - uses informal term sh:BackwardLink | ||
| - minimum and maximum one instance of IRI (can be part of only one address book) | ||
| - uses informal term sh:BackwardLink. | ||
| - minimum and maximum one instance of IRI (i.e., can only be referenced from | ||
| one address book). | ||
|
|
||
| ### Person: Differences between ShEx and SHACL | ||
|
|
||
| The following is how the SHACL shape in `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` differ from the ShEx shape in `contacts/person.shex`. | ||
| The following is how the SHACL shape in | ||
| `https://raw.githubusercontent.com/solid/contacts-pane/master/shapes/contacts-shapes.ttl` | ||
| differs from the ShEx shape in `contacts/person.shex`. | ||
|
|
||
| - vcard:Individual | ||
| - is closed | ||
| - using informal term sh:count | ||
| - is closed. | ||
| - using informal term sh:count. | ||
| - vcard:fn | ||
| - uses sh:pattern ".* .*" | ||
| - uses sh:pattern ".* .*". | ||
| - vcard:hasUID | ||
| - different cardinality ({1, 1} vs {0, 1}) | ||
| - uses sh:pattern "^urn:uuid:" | ||
| - different cardinality ({1, 1} vs {0, 1}). | ||
| - uses sh:pattern "^urn:uuid:". | ||
| - vcard:hasName | ||
| - has a shape of its own (:NameShape) | ||
| - has a shape of its own (:NameShape): | ||
| - vcard:family-name | ||
| - vcard:given-name | ||
| - vcard:additional-name | ||
| - vcard:honorific-prefix | ||
| - vcard:honorific-suffix | ||
| - we used string, but added a comment | ||
| - we used string, but added a comment. | ||
| - vcard:hasImage | ||
| - don't specify type dc:Image | ||
| - don't specify type dc:Image. | ||
| - vcard:hasRelated | ||
| - don't specify node or sub-shape (we specified a shape for vcard:RelatedType in ShEx) | ||
| - don't specify node or sub-shape (we specified a shape for | ||
| vcard:RelatedType in ShEx). | ||
| - vcard:url | ||
| - has a shape of its own (:WebPageShape) | ||
| - uses vcard:value (vs rdf:value) | ||
| - uses sh:pattern "^https?:" | ||
| - uses informal term sh:count | ||
| - we specified type rdf:Resource in the ShEx shape | ||
| - has a shape of its own (:WebPageShape): | ||
| - uses vcard:value (vs rdf:value). | ||
| - uses sh:pattern "^https?:". | ||
| - uses informal term sh:count. | ||
| - we specified type rdf:Resource in the ShEx shape. | ||
| - vcard:hasAddress | ||
| - don't specify node or sub-shape (vcard:Address) | ||
| - don't specify node or sub-shape (vcard:Address). | ||
| - vcard:anniversary | ||
| - we used vcard:bday in the ShEx shape | ||
| - we used vcard:bday in the ShEx shape. | ||
| - vcard:hasEmail | ||
| - uses sh:pattern "^mailto:" (vs /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/ in ShEx) | ||
| - uses vcard:value (vs rdf:value) | ||
| - uses informal term sh:count | ||
| - different cardinality (ShEx is *) | ||
| - uses sh:pattern "^mailto:" (vs /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/ in ShEx). | ||
| - uses vcard:value (vs rdf:value). | ||
| - uses informal term sh:count. | ||
| - different cardinality (ShEx is *). | ||
| - vcard:hasTelephone | ||
| - uses sh:pattern "^tel:" (vs /^\+?[0-9]+[0-9-]*[0-9]$/ in ShEx) | ||
| - uses vcard:value (vs rdf:value) | ||
| - uses informal term sh:count | ||
| - different cardinality (ShEx is *) | ||
| - uses sh:pattern "^tel:" (vs /^\+?[0-9]+[0-9-]*[0-9]$/ in ShEx). | ||
| - uses vcard:value (vs rdf:value). | ||
| - uses informal term sh:count. | ||
| - different cardinality (ShEx is *). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Bookmark-related Turtle files | ||
|
|
||
| Bookmarks are modelled very simply. Due to this simplicity at the moment, we've | ||
| choosen to model a collection of bookmarks as simply being entities contained | ||
| within a single resource (as opposed to defining a resource-per-bookmark). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| @prefix : <#>. | ||
| @prefix bookm: <http://www.w3.org/2002/01/bookmark#>. | ||
| @prefix terms: <http://purl.org/dc/terms/>. | ||
| @prefix xsd: <http://www.w3.org/2001/XMLSchema#>. | ||
|
|
||
| :16115748945888512870652861511 | ||
| a bookm:Bookmark; | ||
| terms:created "2021-01-25T11:41:34.589Z"^^xsd:dateTime; | ||
| terms:title "Solid Project"; | ||
| bookm:recalls <https://solidproject.org/>. | ||
|
|
||
| :12391230834289702394820340982 | ||
| a bookm:Bookmark; | ||
| terms:created "2021-01-30T12:30:21.321Z"^^xsd:dateTime; | ||
| terms:title "Inrupt"; | ||
| bookm:recalls <https://inrupt.com/>. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| PREFIX acl: <http://www.w3.org/ns/auth/acl#> | ||
| PREFIX dc: <http://purl.org/dc/elements/1.1/> | ||
| PREFIX vcard: <http://www.w3.org/2006/vcard/ns#> | ||
| PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> | ||
|
|
||
| # This shape describes some of the information we store for an address book. | ||
| # It's intended to represent a single address book. We use the ID "#this" to | ||
| # refer to the subject of the address book. | ||
|
|
||
| # This model was originally developed as part of the | ||
| # SolidOS/Data Browser project, and we strive to keep it interoperable with | ||
| # their work. Some custom terms have been introduced to vocabularies we think | ||
| # they could belong to (e.g. vcard:nameEmailIndex). We'll make a note of the | ||
| # custom term when used. | ||
|
|
||
| # vcard:AddressBook is a custom class | ||
| vcard:AddressBook { | ||
| dc:title xsd:string {1} ; | ||
| # vcard:nameEmailIndex is a custom term | ||
| vcard:nameEmailIndex IRI {1} ; | ||
| # vcard:groupIndex is a custom term | ||
| vcard:groupIndex IRI {1} ; | ||
| acl:owner IRI + | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # Contacts-related Turtle files | ||
|
|
||
| The example Turtle files here describe the structure and modelling of the | ||
| following Contact-related concepts: | ||
|
|
||
| ### Two address books | ||
|
|
||
| Modelled as **_containers_**: | ||
|
|
||
| - Work colleagues (the `/addressBookWork` container). | ||
| - Friends (the `/addressBookFriend` container). | ||
|
|
||
| ### Four groups | ||
|
|
||
| Modelled as individual **_resources_** within the `/group` container, and with | ||
| that `/group` container having an `index.ttl` Group-Index. | ||
|
|
||
| - Work colleagues (`/group/group1-work-colleague.ttl`). | ||
| - Friends (`/group/group2-friend.ttl`). | ||
| - Local soccer team (`/group/group3-soccer-team.ttl`). | ||
| - Just an empty group (`/group/group4-empty.ttl`). | ||
|
|
||
| And the Group-Index - `/group/index.ttl`. | ||
|
|
||
| ### Three people | ||
|
|
||
| Each person modelled as a **_child container_** within the `/person` container, | ||
| with the parent `/person` container containing an `index.ttl` Person-Index. | ||
|
|
||
| - Arne H, who I work with, is a friend I play D&G, and is the striker on my | ||
| local soccer team! | ||
| - Vincent T, who I work with. | ||
| - Tommy Mc, who is a friend. | ||
|
|
||
| And the Person-Index - `/person/index.ttl`. | ||
|
|
||
|
|
||
| # Notes: | ||
|
|
||
| - The use of `index.ttl` is a convention, but it seems to be used for both | ||
| 'indexes' (i.e., a Group index (e.g., `/group/index.ttl`) listing a number of | ||
| contained groups), and the 'default resource' of a container (e.g., the | ||
| `index.ttl` resource within the individual person container (e.g., | ||
| `/person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl`). | ||
|
|
||
| - In Group-Indexes, is it necessary to duplicate the triple stating that each | ||
| contained group is of `rdf:type` `vcard:Group`? |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.