diff --git a/shapes/README.md b/shapes/README.md index 5698f940..4f491b42 100644 --- a/shapes/README.md +++ b/shapes/README.md @@ -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 *). diff --git a/shapes/bookmark/README.md b/shapes/bookmark/README.md new file mode 100644 index 00000000..deb47192 --- /dev/null +++ b/shapes/bookmark/README.md @@ -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). diff --git a/shapes/bookmarks/bookmark.shex b/shapes/bookmark/bookmark.shex similarity index 59% rename from shapes/bookmarks/bookmark.shex rename to shapes/bookmark/bookmark.shex index 338540f5..59712860 100644 --- a/shapes/bookmarks/bookmark.shex +++ b/shapes/bookmark/bookmark.shex @@ -3,6 +3,12 @@ PREFIX foaf: PREFIX terms: PREFIX xsd: +# +# This shape describes the information we store for a bookmark. +# In Pod Browser we store all bookmarks within the one resource (as opposed to +# storing one bookmark per resource and containing them all within an +# `ldp:Container`). +# bookmark:Bookmark { terms:created xsd:dateTime {1} ; terms:title xsd:string {1} ; diff --git a/shapes/bookmark/example/bookmark/index.ttl b/shapes/bookmark/example/bookmark/index.ttl new file mode 100644 index 00000000..8d6965ac --- /dev/null +++ b/shapes/bookmark/example/bookmark/index.ttl @@ -0,0 +1,16 @@ +@prefix : <#>. +@prefix bookm: . +@prefix terms: . +@prefix xsd: . + +:16115748945888512870652861511 + a bookm:Bookmark; + terms:created "2021-01-25T11:41:34.589Z"^^xsd:dateTime; + terms:title "Solid Project"; + bookm:recalls . + +:12391230834289702394820340982 + a bookm:Bookmark; + terms:created "2021-01-30T12:30:21.321Z"^^xsd:dateTime; + terms:title "Inrupt"; + bookm:recalls . diff --git a/shapes/contact/address-book.shex b/shapes/contact/address-book.shex new file mode 100644 index 00000000..a69d695b --- /dev/null +++ b/shapes/contact/address-book.shex @@ -0,0 +1,24 @@ +PREFIX acl: +PREFIX dc: +PREFIX vcard: +PREFIX xsd: + +# 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 + +} diff --git a/shapes/contact/example/README.md b/shapes/contact/example/README.md new file mode 100644 index 00000000..43d2795a --- /dev/null +++ b/shapes/contact/example/README.md @@ -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`? diff --git a/shapes/contact/example/addressBookFriend/index.ttl b/shapes/contact/example/addressBookFriend/index.ttl new file mode 100644 index 00000000..ce90cdc9 --- /dev/null +++ b/shapes/contact/example/addressBookFriend/index.ttl @@ -0,0 +1,16 @@ +prefix : <#> +prefix acl: +prefix dcterms: +prefix vcard: + +# +# This is my address book that I use to list just my friends... +# It contains references to two indexes: +# - one listing my friends +# - one listing my groups of friends +# +:this a vcard:AddressBook ; + acl:owner ; + dcterms:title "Contacts of all my friends" ; + vcard:nameEmailIndex <../person/index.ttl> ; + vcard:groupIndex <../group/index.ttl> . diff --git a/shapes/contact/example/addressBookWork/index.ttl b/shapes/contact/example/addressBookWork/index.ttl new file mode 100644 index 00000000..5c998200 --- /dev/null +++ b/shapes/contact/example/addressBookWork/index.ttl @@ -0,0 +1,16 @@ +prefix : <#> +prefix acl: +prefix dcterms: +prefix vcard: + +# +# This is my address book that I use to list just my work colleagues... +# It contains references to two indexes: +# - one listing my work colleagues +# - one listing my groups of work colleagues +# +:this a vcard:AddressBook ; + acl:owner ; + dcterms:title "Contacts of all my work colleagues" ; + vcard:nameEmailIndex ; + vcard:groupIndex . diff --git a/shapes/contact/example/group/group1-work-colleague.ttl b/shapes/contact/example/group/group1-work-colleague.ttl new file mode 100644 index 00000000..f22c0426 --- /dev/null +++ b/shapes/contact/example/group/group1-work-colleague.ttl @@ -0,0 +1,22 @@ +prefix : <#> +prefix vcard: + +:this + a vcard:Group ; + vcard:fn "Group 1 - my work colleagues" ; + vcard:hasMember <../person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl#this> ; + vcard:hasMember <../person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl#this> . + +<../addressBookFriend/index.ttl#this> vcard:includesGroup :this . + +# +# This is caching some data from an external resource by copying it here (just +# so that we don't need to fetch each `vcard:hasMember` instance to get their +# `vcard:fn` values. +# +<../person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl#this> + vcard:fn "Arne - who I work with" . + +<../person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl#this> + vcard:fn "Vincent - but name could be different here (since it's a copy)" . + diff --git a/shapes/contact/example/group/group2-friend.ttl b/shapes/contact/example/group/group2-friend.ttl new file mode 100644 index 00000000..25c46d37 --- /dev/null +++ b/shapes/contact/example/group/group2-friend.ttl @@ -0,0 +1,22 @@ +prefix : <#> +prefix vcard: + +:this + a vcard:Group ; + vcard:fn "Group 2 - my friends" ; + vcard:hasMember <../person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl#this> ; + vcard:hasMember <../person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl#this> . + +<../addressBookFriend/index.ttl#this> vcard:includesGroup :this . + +# +# This is caching some data from an external resource by copying it here (just +# so that we don't need to fetch each `vcard:hasMember` instance to get their +# `vcard:fn` values. +# +<../person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl#this> + vcard:fn "Arne - from work, but my mate from D&G" . + +<../person/76344edd-b1c7-67c2-ec3e-89ab5494e233/index.ttl#this> + vcard:fn "Tommy - friend from the soccer team" . + diff --git a/shapes/contact/example/group/group3-soccer-team.ttl b/shapes/contact/example/group/group3-soccer-team.ttl new file mode 100644 index 00000000..d480011c --- /dev/null +++ b/shapes/contact/example/group/group3-soccer-team.ttl @@ -0,0 +1,23 @@ +prefix : <#> +prefix vcard: + +:this + a vcard:Group ; + vcard:fn "Group 3 - local soccer team" ; + vcard:hasMember + <../person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl#this> , + <../person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl#this> . + +<../addressBookFriend/index.ttl#this> vcard:includesGroup :this . + +# +# This is caching some data from an external resource by copying it here (just +# so that we don't need to fetch each `vcard:hasMember` instance to get their +# `vcard:fn` values. +# +<../person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl#this> + vcard:fn "Arne - soccer team striker!" . + +<../person/76344edd-b1c7-67c2-ec3e-89ab5494e233/index.ttl#this> + vcard:fn "Tommy - soccer team goalkeeper" . + diff --git a/shapes/contact/example/group/group4-empty.ttl b/shapes/contact/example/group/group4-empty.ttl new file mode 100644 index 00000000..20f58dda --- /dev/null +++ b/shapes/contact/example/group/group4-empty.ttl @@ -0,0 +1,11 @@ +prefix : <#> +prefix vcard: + +# This is simply an empty group (i.e., no members, yet). +:this + a vcard:Group ; + vcard:fn "Group 4 - empty, for now..." . + +<../addressBookFriend/index.ttl#this> + vcard:includesGroup :this . + diff --git a/shapes/contact/example/group/index.ttl b/shapes/contact/example/group/index.ttl new file mode 100644 index 00000000..0cc0d361 --- /dev/null +++ b/shapes/contact/example/group/index.ttl @@ -0,0 +1,36 @@ +prefix : <#> +prefix vcard: + +# +# This is a Group-specific index. +# +# Here we cache (copy) some data from our 'contained' groups, in this case just +# the formatted name of each group (and since they are 'copies', they can have +# different values), and the fact that each is of `rdf:type` `vcard:Group`. +# +<./group1-work-colleague.ttl#this> + a vcard:Group ; + vcard:fn "Group 1 - all my work colleagues" . + +<./group2-friend.ttl#this> + a vcard:Group ; + vcard:fn "Group 2 - all my friends" . + +<./group3-soccer-team.ttl#this> + a vcard:Group ; + vcard:fn "Group 3 - my local soccer team" . + +<./group4-empty.ttl#this> + a vcard:Group ; + vcard:fn "Group 4 - which I expect to be empty" . + + +<../addressBookWork/index.ttl#this> + vcard:includesGroup + <./group1-work-colleague.ttl#this> . + +<../addressBookFriend/index.ttl#this> + vcard:includesGroup + <./group2-friend.ttl#this> , + <./group3-soccer-team.ttl#this> , + <./group4-empty.ttl#this> . diff --git a/shapes/contact/example/person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl b/shapes/contact/example/person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl new file mode 100644 index 00000000..52ef805e --- /dev/null +++ b/shapes/contact/example/person/2d73ccc1-9d76-4398-8840-3c23a8ddf04c/index.ttl @@ -0,0 +1,25 @@ +prefix : <#> +prefix dcterms: +prefix XML: +prefix vcard: + +# This data was generated when this 'Person' container was created initially +# via Data Browser and rdflib.js. +<> + dcterms:created "2021-02-04T06:19:42Z"^^XML:dateTime . + +# +# Here we describe the actual entity - in this case a Person. +# +:this + a vcard:Individual ; + vcard:fn "Arne H - work colleague, friend and soccer striker" ; + vcard:url [ + a vcard:WebID; + vcard:value "https://megoth-demo1.inrupt.net/profile/card#me" + ] , + # Perhaps other forms of dereferencable URL's (but not email!)... + [ + a vcard:DID; + vcard:value "did:sovrin:34537453453-2432424-23424324" + ] . diff --git a/shapes/contact/example/person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl b/shapes/contact/example/person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl new file mode 100644 index 00000000..30462aa0 --- /dev/null +++ b/shapes/contact/example/person/347429c1-e6b5-40c0-bd6f-61ba1265d357/index.ttl @@ -0,0 +1,17 @@ +prefix : <#> +prefix vcard: + +# +# Person instance saved via Pod Browser... +# +:this + a vcard:Individual ; + vcard:fn "Vincent T - work colleague" ; + vcard:url :16112499761464744406237652592 . + +# +# Using a named node (as opposed to a Blank Node). +# +:16112499761464744406237652592 + a vcard:WebId ; + vcard:value . diff --git a/shapes/contact/example/person/76344edd-b1c7-67c2-ec3e-89ab5494e233/index.ttl b/shapes/contact/example/person/76344edd-b1c7-67c2-ec3e-89ab5494e233/index.ttl new file mode 100644 index 00000000..f3d0919a --- /dev/null +++ b/shapes/contact/example/person/76344edd-b1c7-67c2-ec3e-89ab5494e233/index.ttl @@ -0,0 +1,17 @@ +prefix : <#> +prefix vcard: + +# +# Person instance saved via Pod Browser... +# +:this + a vcard:Individual ; + vcard:fn "Tommy - friend and goalkeeper extraordinaire" ; + vcard:url :56456268332379795455777077312 . + +# +# Using a named node (as opposed to a Blank Node). +# +:56456268332379795455777077312 + a vcard:WebId ; + vcard:value . diff --git a/shapes/contact/example/person/index.ttl b/shapes/contact/example/person/index.ttl new file mode 100644 index 00000000..878f0094 --- /dev/null +++ b/shapes/contact/example/person/index.ttl @@ -0,0 +1,23 @@ +prefix : <#> +prefix vcard: + +# +# This is a Person-specific index. +# +# We define a container for each Person (but for Groups we don't), and we +# can cache (or copy) specific data from each person to here in this index too +# (so that we can access that data without having to read all the individual +# people resources when just listing all the people with their names). + + vcard:fn "Arne H" ; + vcard:inAddressBook + <../addressBookFriend/index.ttl#this> , + <../addressBookWork/index.ttl#this> . + + + vcard:fn "Vincent" ; + vcard:inAddressBook <../addressBookWork/index.ttl#this> . + + + vcard:fn "Tommy Mc" ; + vcard:inAddressBook <../addressBookFriend/index.ttl#this> . diff --git a/shapes/contact/group-index.shex b/shapes/contact/group-index.shex new file mode 100644 index 00000000..7c23524a --- /dev/null +++ b/shapes/contact/group-index.shex @@ -0,0 +1,20 @@ +PREFIX vcard: +PREFIX xsd: + +# This shape describes part of the information we store when adding a group to +# an address book. The resource it is used for is an index of groups. There will +# be multiple groups added in this resource, and each referring to the group +# resource where there are more information on the group (e.g. members). + +# 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:includesGroup). We'll make a note of the +# custom term when used. + +vcard:Group { + vcard:fn xsd:string {1} ; + # vcard:includesGroup is a custom term + # vcard:AddressBook is a custom class + ^ vcard:includesGroup vcard:AddressBook ; +} diff --git a/shapes/contact/group.shex b/shapes/contact/group.shex new file mode 100644 index 00000000..0c673918 --- /dev/null +++ b/shapes/contact/group.shex @@ -0,0 +1,26 @@ +PREFIX vcard: +PREFIX xsd: + +# This shape describes some of the information we store when adding a group to +# an address book. The resource it is used for is to describe the group itself +# (meaning the resource should only contain one group). We use the id "#this" +# to refer to the subject of the group. + +# 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:includesGroup). We'll make a note of the +# custom term when used. + +vcard:Group { + vcard:fn xsd:string {1} ; + vcard:note xsd:string ? ; + vcard:hasMember vcard:Individual * OR vcard:Organization * ; + # vcard:includesGroup is a custom term + # vcard:AddressBook is a custom class + ^vcard:includesGroup vcard:AddressBook +} + +# Note that we also cache the name of each member, so that we don't have to +# fetch the profile of each member to get their name. An example of this can +# be seen in example/Group/Group_1.ttl. diff --git a/shapes/contact/person-index.shex b/shapes/contact/person-index.shex new file mode 100644 index 00000000..01ef18c1 --- /dev/null +++ b/shapes/contact/person-index.shex @@ -0,0 +1,22 @@ +PREFIX vcard: +PREFIX xsd: + +# This shape describes part of the information we store when adding a person to +# an address book. The resource it is used for is an index of people. There will +# be multiple people added in this resource, and each referring to the person +# resource where there are more information on the person (e.g. photo, email, +# etc). + +# This model is 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:inAddressBook). We'll make a note of the +# custom term when used. + +vcard:Individual { + vcard:fn xsd:string {1} ; + + # vcard:inAddressBook is a custom term + # vcard:AddressBook is a custom class + vcard:inAddressBook vcard:AddressBook ? +} diff --git a/shapes/contacts/person.shex b/shapes/contact/person.shex similarity index 51% rename from shapes/contacts/person.shex rename to shapes/contact/person.shex index df04fb05..cad4605d 100644 --- a/shapes/contacts/person.shex +++ b/shapes/contact/person.shex @@ -1,18 +1,30 @@ -PREFIX vcard: -PREFIX xsd: -PREFIX owl: -PREFIX dc: -PREFIX rdf: +PREFIX vcard: +PREFIX xsd: +PREFIX owl: +PREFIX dcterms: +PREFIX rdf: -# We should store the preferred WebId for each person, since sameAs can be multiple WebIds +# This shape describes the information we store when adding a person to an +# address book. The resource it is used for represents a local copy of a +# person's profile. We use the id "#this" to refer to the subject of the person. + +# This model is 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:inAddressBook). We'll make a note of the custom term +# when used. vcard:Individual { vcard:fn xsd:string {1} ; - vcard:inAddressBook vcard:AddressBook + ; - vcard:url vcard:WebId {1}; + + # vcard:WebId is a custom term + vcard:url vcard:WebId {1}; + + # Not sure if we use this anymore vcard:hasUID xsd:string ? ; + vcard:hasName xsd:string ? ; # structured name - vcard:hasPhoto dc:Image * ; + vcard:hasPhoto dcterms:Image * ; vcard:hasRelated vcard:RelatedType * ; vcard:hasAddress vcard:Address * ; vcard:bday xsd:date ? ; @@ -22,8 +34,16 @@ vcard:Individual { vcard:role xsd:string ? ; vcard:title xsd:string ? ; vcard:note xsd:string ? ; + vcard:inAddressBook vcard:AddressBook + ; + # vcard:inAddressBook is a custom term + # vcard:AddressBook is a custom class } +# We store the preferred WebID for each person. The use of vcard:WebId +# refer to the Individual's WebIDs, but the idea is that we could expand it +# to refer to other type of unique identifiers later +# vcard:WebId is a custom term +# Big question - SHOULD something as fundamental as WebID be defined in vCard? vcard:WebId { vcard:value xsd:string {1}; } diff --git a/shapes/contacts/address-book.shex b/shapes/contacts/address-book.shex deleted file mode 100644 index abd19a36..00000000 --- a/shapes/contacts/address-book.shex +++ /dev/null @@ -1,11 +0,0 @@ -PREFIX acl: -PREFIX dc: -PREFIX vcard: -PREFIX xsd: - -vcard:AddressBook { - dc:title xsd:string {1} ; - vcard:nameEmailIndex IRI {1} ; - vcard:groupIndex IRI {1} ; - acl:owner IRI + -} diff --git a/shapes/contacts/group-index.shex b/shapes/contacts/group-index.shex deleted file mode 100644 index 29c3c96f..00000000 --- a/shapes/contacts/group-index.shex +++ /dev/null @@ -1,7 +0,0 @@ -PREFIX vcard: -PREFIX xsd: - -vcard:Group { - vcard:fn xsd:string {1} ; - ^ vcard:includesGroup vcard:AddressBook ; -} diff --git a/shapes/contacts/group.shex b/shapes/contacts/group.shex deleted file mode 100644 index 8fda45bd..00000000 --- a/shapes/contacts/group.shex +++ /dev/null @@ -1,9 +0,0 @@ -PREFIX vcard: -PREFIX xsd: - -vcard:Group { - vcard:fn xsd:string {1} ; - vcard:note xsd:string ? ; - vcard:hasMember vcard:Individual * OR vcard:Organization * ; - ^vcard:includesGroup vcard:AddressBook -} diff --git a/shapes/contacts/people-index.shex b/shapes/contacts/people-index.shex deleted file mode 100644 index 1821de42..00000000 --- a/shapes/contacts/people-index.shex +++ /dev/null @@ -1,7 +0,0 @@ -PREFIX vcard: -PREFIX xsd: - -vcard:Individual { - vcard:fn xsd:string {1} ; - vcard:inAddressBook vcard:AddressBook ? -}