- From: Karol Szczepański <karol.szczepanski@gmail.com>
- Date: Sun, 28 Feb 2016 22:24:32 +0100
- To: Asbjørn Ulsberg <asbjorn@ulsberg.no>, "Ruben Verborgh" <ruben.verborgh@ugent.be>
- Cc: "Markus Lanthaler" <markus.lanthaler@gmx.net>, "Hydra" <public-hydra@w3.org>
Hi Asbjørn Finally I had time to craft few examples of what I've implemented. >> Client side have several components which are checked against each >> mapping >> and if it responds positively it is allowed to process passed information >> (current filter settings, paging, etc.) and generates an expression. This >> way I can have several components which may "understand" various >> mappings. >> If no components is applicable, it is just left untouched. Iri template >> allows the value to be optional, thus it will miss that very variable >> value. >Could you please post examples of how this looks on the wiki so it can >be discussed further and so people understand just exactly how OData >can be used in Hydra? I think that's unclear for a lot of people, >perhaps me included. :-) Consider an API entry point that generates an API documentation containing the snipped below (in Turtle, it's sooo much shorter than JSON-LD): @PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @PREFIX hydra: <http://www.w3.org/ns/hydra/core#> . @BASE <http://temp.uri/api/person/> . <LIST#withTemplate> a hydra:TemplatedLink; hydra:supportedOperation <#LIST> . <#LIST> a hydra:Operation; rdfs:label "List"; hydra:method "GET"; hydra:returns [ a hydra:Collection ] . <LIST#template> a hydra:IriTemplate; hydra:template "/api/person{?$skip,$top,$filter}"; hydra:mapping [ hydra:property <http://docs.oasis-open.org/odata/odata/v4.0/$skip>; hydra:variable "$skip" ], [ hydra:property <http://docs.oasis-open.org/odata/odata/v4.0/$top>; hydra:variable "$top" ], [ hydra:property <http://docs.oasis-open.org/odata/odata/v4.0/$filter>; hydra:variable "$filter" ] . <http://docs.oasis-open.org/odata/odata/v4.0/$skip> rdfs:range <http://www.w3.org/2001/XMLSchema#int> . <http://docs.oasis-open.org/odata/odata/v4.0/$top> rdfs:range <http://www.w3.org/2001/XMLSchema#int> . <http://docs.oasis-open.org/odata/odata/v4.0/$filter> rdfs:range <http://www.w3.org/2001/XMLSchema#string> . Now when client figures it out that there is a GET operation that returns a hydra:Collection it will find out the IRI template with three mappings. The client is designed so it is possible to plug custom component implementations that will be asked for each of the mapping in the template whether it is capable of processing it. If so, it is passed an object that has current UI filter states, including current page and page size, i.e. (in JSON): { "http://schema.org/givenName": "karol", "http://schema.org/familyName": "s", "currentPage": 1, "pageSize: 10 } The OData component would respond positively for all of the three mappings as it understands mapped properties. While processing passed instance, the instance would be transformed into an actual object passed to the IRI template processor. Based on the API description it would know that "currentPage" (a generic property, unmapped to anything specific) would be translated to skip = 0, "pageSize" to top = 10 and other properties would be translated into a filter: { "$skip": 0, "$top": 10, "$filter": "(indexOf(<http://schema.org/givenName>, 'karol') gt -1) and (indexOf(<http://schema.org/familyName>, 's') gt -1)" } The logic of how to transform properties into a filter sits in that component - it is hardcoded how and when to use indexOf or eq(Equal) or gt (Greater Than). If no component is available that would transform the filters into a variable, it would be omitted as the template allows it leaving space for uncertainty. >> I could use >> http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part2-url-conventions/odata-v4.0-errata02-os-part2-url-conventions-complete.html#_Toc406398094 >> as the reference, which is actual one leading to $filter description, but >> it >> looks ugly. >Indeed. How about defining an alias in purl.org and using the purl alias >instead? I have poor experiences with purl.org - it failed me several times :(. But still, having an alias would an option. >I agree, which is why I'd really appreciate if Karol could contribute his >OData implementation on the wiki. I hesitated to put this example on the Collections Interaction Flow as it seems quite complex and somehow doesn't fit there - if you have any idea on where to put it give me a shout! >> EQUALS is not enough for everything; but it is a good default. >> The mechanism should be extensible (for instance, freeTextQuery). Equals is not good as default as well. It would work for integer numbers, but starts to fail for floats and dates. I was implementing this logic in my URSA client for OData and it contains quite a logic! I.e., for dates different filter is generated when a full date/time is provided, different when only date and time rounded to hours. >I think it's unwise for Hydra to have any querying capability at all >built in. Instead, it should be really easy to plug in OData, SPARQL >and other extrenal query langauges. Anything we try to specify in >Hydra is not going to be sufficient for anything but the simplest and >most banal cases and I'd argue won't be anywhere near the 80/20 rule >that often governs decisions on whether to include something like this >in a specification or not. I think I'm keen to agree with that. Querying is a huge topic and having some prothesis would do more harm than good. Tomasz's idea of pluggable vocabs seems more reasonable. I'm almost done with fooling aroung with my code, thus I should be able to push the updated demo with filters to the live site. Code is already available on the github. BTW. Recently I revisited HTTP RFC and it reminded me of a HTTP 206 Partial Content and Content-Range header. Isn't it a preferred solution of HTTP understanding ReST API client implementation for paging? Best Karol
Received on Sunday, 28 February 2016 21:25:04 UTC