Re: PATCH Use Case and Implemented Proposal

On 09/07/2013 10:39 PM, Sandro Hawke wrote:
> Thanks for something so concrete, Dave.   For myself, much of the 
> challenge here is that I've not had time to implement, so it remains 
> too abstract.    Some questions and thoughts, inline....
>
> On 09/07/2013 09:09 PM, David Wood wrote:
>> Hi all,
>>
>> The need for a PATCH format for LDP was brought up again in last 
>> week's meeting with TimBL [1].  To summarize briefly, Tim made the 
>> point that LDP has no generic way to update data without a PATCH 
>> format and Arnaud said that the WG wanted one but hadn't yet been 
>> able to define it.  Arnaud called for a halt on PATCH formats in May [2]
>>
>> The two main approaches would seem to be Andy's proposal [3] which 
>> uses basic triple patterns to define what to add or remove from a 
>> store and Sandro's TurtlePatch [4].
>>
>
> I also did a Trig-based patch format, DataPatch: 
> http://www.w3.org/People/Sandro/datapatch but like TurtlePatch I 
> haven't actually been pushing it.    But it was going the direction 
> the WG said it wanted to go, using TriG.
>

Oh, also datapatch has a bunch of stuff that's been obsoleted by RDF 1.1 
being more clear about who literals match, right after I wrote it.

         -- Sandro

>> This message suggests a third approach based on a strictly defined 
>> subset of SPARQL Update
>
> Isn't that exactly what TurtlePatch was?     True, your subset is 
> somewhat..
>
>> .  Our approach is already implemented in the (Apache 2 licensed) 
>> Callimachus Project [5] and documented later in this message.  Henry 
>> has already mentioned that a subset of SPARQL Update could work [6] 
>> for the WG's purposes.
>>
>> A strict subset of SPARQL Update is used in the Callimachus 
>> implementation to support the following constructs in a 
>> PATCH request. However, each clause can only contain zero or more 
>> basic graph patterns and only the default graph can be used.
>>      * DELETE DATA
>>      * INSERT DATA
>>      * DELETE WHERE
>>      * INSERT WHERE
>>      * DELETE INSERT WHERE
>>
>> Callimachus further restricts the SPARQL Update spec such that all 
>> nodes are connected and all URIs, in the subject position, before a 
>> '#' (if present), are the same.
>>
>
> What's the reasoning behind this?   I've always assumed that a basic 
> requirement of Patch was that it be able to patch any RDF graph to any 
> other RDF graph (given enough computing resources).    Is there some 
> other requirement that necessitates this restriction?
>
>     -- Sandro
>
>> Callimachus enforces this by walking the syntax tree of the 
>> parsed SPARQL Update request and flags any construct that does fit 
>> with the above. Callimachus uses the Sesame query model, which is a 
>> bit different than the SPARQRL grammer. The code that walks 
>> the SPARQL Update tree and flags constructs that are not explicitly 
>> listed is available online at [7].
>>
>> Then it verifies the request body [8] by checking that all URIs 
>> in the subject position (before '#') are the same [9], all nodes are
>> connected [10], all present constructs are permitted[7], and finally 
>> it makes sure no blank nodes are left disconnected[11].
>>
>> To try this out, fire up a Callimachus instance and run the follow 
>> curl commands:
>>
>> ################################
>> # Discover the LDPR of the root resource by looknig for rel="describedby"
>> ################################
>> $ curl -iX OPTIONS http://localhost:8080/
>>
>> HTTP/1.1 204 No Content
>> Allow: OPTIONS, TRACE, GET, HEAD, POST, PATCH, DELETE, PUT
>> Access-Control-Allow-Methods: OPTIONS, TRACE, GET, HEAD, POST, PATCH, 
>> DELETE, PUT
>> Access-Control-Allow-Headers: 
>> Accept,Accept-Charset,Accept-Encoding,Accept-Language,Authorization,Cache-Control,Content-Encoding,Content-Language,Content-Length,Content-Location,Content-MD5,Content-Type,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Range,Cookie,Referer,Slug
>> Link: <http://localhost:8080/?discussion>; rel="comments"; 
>> type="text/html"
>> Link: <http://localhost:8080/?search>; rel="search"; 
>> type="application/opensearchdescription+xml"
>> Link: <http://localhost:8080/?describe>; rel="describedby"; 
>> type="text/html application/rdf+xml;q=0.4 text/turtle;q=0.5"; 
>> title="RDF Describe"
>> Link: <http://localhost:8080/?realms>; 
>> rel="http://callimachusproject.org/rdf/2009/framework#realms"; 
>> type="application/atom+xml;q=0.9"
>> Link: <http://localhost:8080/?contents>; rel="contents"; 
>> type="application/atom+xml;q=0.9"
>> Link: <http://localhost:8080/?edit>; rel="edit-form"; type="text/html"
>> Link: <http://localhost:8080/?history>; rel="version-history"; 
>> type="text/html application/atom+xml;q=0.9"
>> Link: <http://localhost:8080/?view>; rel="alternate"; type="text/html"
>> Link: <http://localhost:8080/?archive>; 
>> rel="http://callimachusproject.org/rdf/2009/framework#archive"
>> Link: <http://localhost:8080/?changes>; rel="alternate"; type="text/html"
>> Cache-Control: public
>> Vary: Accept
>> Vary: Origin
>> Vary: Access-Control-Request-Method
>> Content-Version: "/callimachus/changes/2013/09/05/t140ee789cecx1971"
>> ETag: W/"216e0b6d-a038f4fe"
>> Last-Modified: Thu, 05 Sep 2013 15:59:13 GMT
>> Access-Control-Allow-Origin: http://localhost:8080
>> Access-Control-Expose-Headers: Content-Length, Allow, 
>> Access-Control-Allow-Methods, Access-Control-Allow-Headers, Link, 
>> Cache-Control, Vary, Content-Version, ETag, Last-Modified, 
>> Access-Control-Allow-Origin, Content-Type, Content-Encoding, Date, Server
>> Date: Thu, 05 Sep 2013 16:55:48 GMT
>> Server: Callimachus/1.2-beta-10
>>
>>
>> ################################
>> # Create a new resource, by POSTing the RDF as sparql-update
>> ################################
>> $ curl -i --digest --user james --data-binary @- -H 
>> content-type:application/sparql-update http://localhost:8080/?describe
>> BASE <http://localhost:8080/>
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> INSERT DATA {
>>    <sun> a skos:Concept, </callimachus/1.0/types/Concept> ;
>>        skos:prefLabel "Sun" ;
>>        skos:definition "The great luminary" .
>> }
>>
>> HTTP/1.1 201 Created
>> Location: http://localhost:8080/sun
>> Content-Version: "/callimachus/changes/2013/09/05/t140ee789cecx2216"
>> Derived-From: "/callimachus/changes/2013/09/05/t140ee789cecx2190"
>> ETag: W/"216e64d0-62cbb087"
>> Content-Type: text/uri-list;charset=UTF-8
>> Access-Control-Allow-Origin: http://localhost:8080
>> Access-Control-Expose-Headers: Location, Content-Version, 
>> Derived-From, ETag, Content-Type, Access-Control-Allow-Origin, 
>> Content-Length, Content-Encoding, Date, Server
>> Date: Thu, 05 Sep 2013 17:02:45 GMT
>> Content-Length: 25
>> Content-Encoding: identity
>> Server: Callimachus/1.2-beta-10
>>
>> http://localhost:8080/sun
>>
>>
>> ################################
>> # Discover the LDPR of the newly created resource
>> ################################
>> $ curl -iX OPTIONS http://localhost:8080/sun
>>
>> HTTP/1.1 204 No Content
>> Allow: OPTIONS, TRACE, POST, PATCH, GET, HEAD, DELETE
>> Access-Control-Allow-Methods: OPTIONS, TRACE, POST, PATCH, GET, HEAD, 
>> DELETE
>> Access-Control-Allow-Headers: 
>> Accept,Accept-Charset,Accept-Encoding,Accept-Language,Authorization,Cache-Control,Content-Encoding,Content-Language,Content-Length,Content-Location,Content-MD5,Content-Type,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Range
>> Link: <http://localhost:8080/sun?history>; rel="version-history"; 
>> type="text/html application/atom+xml;q=0.9"
>> Link: <http://localhost:8080/sun?discussion>; rel="comments"; 
>> type="text/html"
>> Link: <http://localhost:8080/sun?describe>; rel="describedby"; 
>> type="text/html application/rdf+xml;q=0.4 text/turtle;q=0.5"; 
>> title="RDF Describe"
>> Link: <http://localhost:8080/sun?edit>; rel="edit-form"; type="text/html"
>> Link: <http://localhost:8080/sun?view>; rel="alternate"; type="text/html"
>> Cache-Control: public
>> Vary: Accept
>> Vary: Origin
>> Vary: Access-Control-Request-Method
>> Content-Version: "/callimachus/changes/2013/09/05/t140ee789cecx2216"
>> ETag: W/"216e64d0"
>> Last-Modified: Thu, 05 Sep 2013 17:02:45 GMT
>> Access-Control-Allow-Origin: http://localhost:8080
>> Access-Control-Expose-Headers: Content-Length, Allow, 
>> Access-Control-Allow-Methods, Access-Control-Allow-Headers, Link, 
>> Cache-Control, Vary, Content-Version, ETag, Last-Modified, 
>> Access-Control-Allow-Origin, Content-Type, Content-Encoding, Date, Server
>> Date: Thu, 05 Sep 2013 17:03:44 GMT
>> Server: Callimachus/1.2-beta-10
>>
>>
>> ################################
>> # Now update the resource using a subset of sparql-update
>> ################################
>> $ curl --digest --user james -X PATCH --data-binary @- -H 
>> content-type:application/sparql-update http://localhost:8080/sun?describe
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> DELETE DATA {
>>    </sun> skos:definition "The great luminary" .
>> };
>> INSERT DATA {
>>    </sun> skos:definition "The lamp of day" .
>> };
>>
>> HTTP/1.1 204 No Content
>> Content-Version: "/callimachus/changes/2013/09/05/t140ee789cecx2245"
>> Derived-From: "/callimachus/changes/2013/09/05/t140ee789cecx2241"
>> ETag: W/"216e652c-469953d3"
>> Access-Control-Allow-Origin: http://localhost:8080
>> Access-Control-Expose-Headers: Content-Length, Content-Version, 
>> Derived-From, ETag, Access-Control-Allow-Origin, Content-Type, 
>> Content-Encoding, Date, Server
>> Date: Thu, 05 Sep 2013 17:05:48 GMT
>> Server: Callimachus/1.2-beta-10
>>
>>
>> With the above, you can try out these other requests below.
>>
>> The following are some examples of valid PATCH requests:
>>
>>
>> PATCH /sun?describe HTTP/1.1
>> Host: localhost:8080
>> Content-Type:application/sparql-update
>> Transfer-Encoding: identity
>>
>> BASE <http://localhost:8080/>
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> DELETE DATA {
>>    </sun> skos:definition "The great luminary" .
>> };
>> INSERT DATA {
>>    </sun> skos:definition "The lamp of day" .
>> };
>>
>>
>> PATCH /sun?describe HTTP/1.1
>> Host: localhost:8080
>> Content-Type:application/sparql-update
>> Transfer-Encoding: identity
>>
>> BASE <http://localhost:8080/>
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> INSERT DATA {
>>    </sun> skos:scopeNode "sun is part of our solar system" .
>> }
>>
>>
>> PATCH /sun?describe HTTP/1.1
>> Host: localhost:8080
>> Content-Type:application/sparql-update
>> Transfer-Encoding: identity
>>
>> BASE <http://localhost:8080/>
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> DELETE DATA {
>>    </sun> skos:scopeNode "sun is part of our solar system" .
>> };
>> INSERT {
>>    </sun> skos:scopeNode ("sun is part of our " <solarSystem>) .
>> } WHERE {};
>>
>>
>> PATCH /sun?describe HTTP/1.1
>> Host: localhost:8080
>> Content-Type:application/sparql-update
>> Transfer-Encoding: identity
>>
>> BASE <http://localhost:8080/>
>> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> DELETE WHERE {
>>    </sun> skos:scopeNode ?list0 .
>>    ?list0 rdf:first "sun is part of our "; rdf:rest ?list1 .
>>    ?list1 rdf:first <solarSystem>; rdf:rest rdf:nil .
>> };
>> INSERT {
>>    </sun> skos:scopeNode ("sun is in our " <solarSystem>) .
>> } WHERE {};
>>
>>
>> The following requests are INVALID as outlined below.
>>
>> PATCH /sun?describe HTTP/1.1
>> Host: localhost:8080
>> Content-Type:application/sparql-update
>> Transfer-Encoding: identity
>>
>> BASE <http://localhost:8080/>
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> DELETE {
>>    </sun> skos:definition ?definition .
>> } INSERT {
>>    </sun> skos:definition ?newvalue .
>> } WHERE {
>>    </sun> skos:definition ?definition .
>>    BIND (concat(?definition,"!") AS ?newvalue)
>> };
>>
>> HTTP/1.1 400 Only basic graph patterns are permitted
>>
>>
>> PATCH /sun?describe HTTP/1.1
>> Host: localhost:8080
>> Content-Type:application/sparql-update
>> Transfer-Encoding: identity
>>
>> BASE <http://localhost:8080/>
>> CREATE GRAPH </sun>
>>
>> HTTP/1.1 500 Unsupported type of update statement: Create
>>
>>
>> PATCH /sun?describe HTTP/1.1
>> Host: localhost:8080
>> Content-Type:application/sparql-update
>> Transfer-Encoding: identity
>>
>> BASE <http://localhost:8080/>
>> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
>> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
>> DELETE WHERE {
>>    </sun> skos:scopeNode ("sun is part of our " <solarSystem>) .
>> };
>> INSERT {
>>    </sun> skos:scopeNode ("sun is in our " <solarSystem>) .
>> } WHERE {};
>>
>> HTTP/1.1 500 DELETE WHERE may not contain blank nodes
>>
>>
>> Using a sparql-update grammer parser it was fairly easy to limited the
>> tokens to a subset that can be validated easily, yet useful to the
>> client.
>>
>>
>> Regards,
>> Dave, with massive work by James Leigh
>> --
>> http://about.me/david_wood
>>
>>
>> [1] http://www.w3.org/2013/meeting/ldp/2013-09-03
>> [2] http://lists.w3.org/Archives/Public/public-ldp-wg/2013May/0233.html
>> [3] http://afs.github.io/rdf-patch/
>> [4] http://www.w3.org/2001/sw/wiki/TurtlePatch
>> [5] http://callimachusproject.org
>> [6] http://lists.w3.org/Archives/Public/public-ldp-wg/2013May/0239.html
>> [7] 
>> https://code.google.com/p/callimachus/source/browse/tags/1.1.2/src/org/callimachusproject/form/helpers/TripleAnalyzer.java#220
>> [8] 
>> https://code.google.com/p/callimachus/source/browse/tags/1.1.2/src/org/callimachusproject/form/helpers/EntityUpdater.java#105 
>>
>> [9] 
>> https://code.google.com/p/callimachus/source/browse/tags/1.1.2/src/org/callimachusproject/form/helpers/TripleVerifier.java#176
>> [10] 
>> https://code.google.com/p/callimachus/source/browse/tags/1.1.2/src/org/callimachusproject/form/helpers/TripleVerifier.java#289
>> [11] 
>> https://code.google.com/p/callimachus/source/browse/tags/1.1.2/src/org/callimachusproject/form/helpers/EntityUpdater.java#98
>>
>

Received on Sunday, 8 September 2013 02:58:06 UTC