Re: Inheritance / composition of term definitions

On 29 Nov 2015, at 09:50, Dietrich Schulten <ds@escalon.de> wrote:

> Hi,
> Am 27.11.2015 17:06 schrieb Lukas Graf <lukas.graf.bern@gmail.com>:
> >
> > [...]
> >
> > GET /buildings/main/ - retrieves the collection members of the "main" building 
> > GET /buildings/main/lobby - retrieves the "lobby" room 
> > (POST /buildings/main/ - create a new "Room" resource in the "main" building) 
> >
> > we wouldn't have a way to access the collection's metadata (the building's "address" for example). So for that reason it seems we do need some intermediate level between the container and the contentish resource. 
> 
> What do you mean by metadata? An address is not metadata in the sense that it describes the actual data and hypermedia controls in the body like http headers do.

My use of the term "metadata" may have been misleading, sorry. I meant "metadata" to mean "any properties of a folderish object, other that its immediate children".

What makes folderish objects interesting are their children. They do have their own properties though as well, like an id and a title. Our CMS doesn't really distinguish between data and metadata. An object just has properties, and those can come from a number of sources. *Folderish* objects additionally can have children. In practice, folderish objects tend to have much fewer properties than non-folderish ones, but otherwise they work exactly the same.

An objects properties are definied via its base schema and so called "behaviors". A behavior really is just another (resuable) schema that can be mixed in. Typical behaviors are for example several sets of DublinCore metadata.
So the Building type would maybe have "address" defined in its base schema, and also have some DC metadata provided via a DC behavior. In the end, all those just end up as properties accessible on the object, there is no real distinction between actual data and data about the object. (Base schema vs. behavior is just a mechanism for reuse of commonly use schema definitions, not a distinction between data vs. metadata).

> If the address is data, you could say
> 
> { 
>   "@context": {"http://example.org/", ...} 
>    "@type":"Building", 
>   "@id":"http://example.org/buildings/main", 
>    "name":"Main Building", 
>    "address": { <-- or schema:address instead
>       "@type":"Address",
>       "@id": "/buildings/main/address",
>       "street": "...",
>       "postalcode": "...",
>       ...
>       "hydra:operation" : [{
>            "hydra:method": "PUT", <-- create or update address
>            ...
>       },
>       {
>            "hydra:method": "DELETE"
>       }],
>     }
> ...
> }
> 
> That simple idiom works as long as the value of "address" is a single item.

That does look quite appropriate for our case.

However, IRI's should be dereferencable, right? So "@id": "/buildings/main/address" would collide with a potential room named "address", no? 

> > > What would they gain by that? Do you want to allow users to filter the rooms for example? 
> >
> > That's definitely a use case as well, but we'll handle that via a separate search / query endpoint. 
> 
> Note that generic clients might not be able to work with that, if it is not expressed in terms of hydra.

We're currently considering hydra:freetextQuery in order to provide a link template for that endpoint for doing a simple full text search. Structured queries are trickier because of the data types involved, and I haven't seen anything in the Hydra spec that covers structured queries.

> > >> The new collection construct in the working group wiki, which is not in 
> > >> the spec yet, shows how this works: 
> > >> 
> > >>   "@context":"http://example.org/", 
> > >>   "@type":"Building", 
> > >>   "@id":"http://example.org/buildings/main", 
> > >>   "name":"Main Building", 
> > >>   "address": "...", 
> > >>    "hydra:collection" : [{ 
> > >>      "@id":"/rooms", 
> > >>      "hydra:operation" : ... 
> > >>       "hydra:manages" : { 
> > >>           "hydra:subject" : "/buildings/main", 
> > >>            "hydra:property" : "rooms" 
> > >>       } 
> > >>      "hydra:member":[ 
> > >>        { 
> > >>         "@type":"Room", 
> > >>         "@id":"http://example.org/buildings/main/lobby", 
> > >>         "name":"Lobby" 
> > >>        }, 
> > >>        { 
> > >>         "@type":"Room", 
> > >>         "@id":"http://example.org/buildings/main/blue-room", 
> > >>         "name":"Blue Room" 
> > >>        } 
> > >>     ] 
> > >>   }] 
> > >> } 
> > >> 
> > >> The new Collection has a "manages" attribute which allows to say that 
> > >> the items are rooms of the building. 
> > > 
> > > Yep, that could be used as well. But given that these will be custom vocabularies AFAICT, it would be much easier to simply point "rooms" to the collection of rooms instead of individual rooms. 
> >
> > That does in fact look interesting. But this does exhibit the deep nesting I wanted to avoid (an array "hydra:member" inside a "hydra:collection").
> 
> Using a "rooms" attribute with both an array value *and* a URI to POST to the set of rooms and say other things about them would require a possibility to let JSON arrays also have attributes. JSON doesn't  allow that (js does!).

By "say other things about them" do you mean say other things about the *relationship* that the set of rooms has to the containing building? Or saying things about the individual rooms in the set that aren't part of those rooms' properties?

> Therefore I'm afraid you need an object like a :Collection with an array attribute  like :member. But that has nothing to do with hydra or jsonld.

I think that's the way to go for us.

> You could avoid the hydra:collection (lowercase) attribute on the building if you define your rooms property in your custom vocabulary so that its value (its range) can be considered a hydra:Collection. That is what Markus proposed. It only works if you do not use properties with a defined range from well-established vocabularies (like foaf:knows), because a hydra.Collection as value of those properties leads to the questionable  inference that if
> 
> /alice foaf:knows /friends
> 
> then the /friends resource must a foaf:Person, which it is not - it is a hydra:Collection. In schema.org properties have no range, but a rangeIncludes, so this inference won't happen - still my feeling is that using a hydra:Collection as value of schema:colleague comes as a surprise for a machine which expects that the colleague is a Person.

I think I get the gist of what you're saying, but I need to digest that a liitle bit more, and look up the concepts behind ranges / rangeIncludes.

> BTW did you look at schema.org/Place?

Do you mean specifically for the "Building" type resp. its "address"? That's just a made up example. In practice, we really can't now what types the users of our CMS will come up with. It really could be anything, we'll have to provide them with a way to annotate their custom-built schemata with some semantic hints that allows them to map their types or properties to well-known ones. The CMS itself provides very little in terms of "concrete" content types - there's a couple very generic stock ones (like Folder, Page, Image, Event) that we will pre-associate, but that's about it.     

> A hydra compliant client must be prepared to consider the manages block anyway to identify a collection it is looking for, therefore you do not gain much by avoiding the deep nesting. It isn't easy on the eye - I know.

I'd like to avoid the deep nesting mainly to keep things simple for dumb, non-Hydra capable clients. Which at first probably will be the majority. Linked data and Hydra is pretty much uncharted territory for us, so while we no doubt will have some excited early adoperts, many people will likely not know exactly what to do with it I presume.

> > hydra:member is what we see being used in the example section "5.1 Collections" of the Hydra spec ;-) But honestly, it's not quite clear to me what exactly we would gain with using hydra:Collection, resp. what we'd lose if we wouldn't be using it. 
> 
> You lose the capability to make your collection a first-class ReST resource with a URL that identifies it. That URL
> - allows you to externalize the set of rooms behind a single URL on the /building/main resource
> - gives the collection a linked data name, so you can say things about the collection, e.g that it can be filtered, you can POST to it, it has other related collections, it can be distributed over several consecutive responses, it tells you how many items there are etc.

Wait, that is if I were to use the new collection construct you gave an example of above? Or just by mapping my "rooms" property to hydra:member?

If the set of rooms were exposed at /buildings/main/rooms we'd again have a potential name conflict with a room called "rooms" if the individual rooms were also exposed as /buildings/main/lobby, no?

Thanks,

Lukas

Received on Tuesday, 1 December 2015 00:15:14 UTC