I think we are lacking a restful means of updating named graphs. SPARQL update (see w3c) provides a update semantics for named graphs but there is no RESTful resource model for this protcol.
There is some interest in the linked data community in coming up with a restful model for named graphs that includes update.
Being able to update a named graph requires the ability to address the graph. If the granularity of update is the graph itself, there are performance problems. Partial update of individual triples in a named graph deals with this.
Addressing triples in a named graph requires two things
- to be able to address the named graph, and,
- to be able to address the triple within that graph
for (1) we can identify the named graph with the RDF/XML representation of the OSLC Defined Resource. (The URI of the named graph is the URI of the RDF/XML (Turtle etc) document that serialises those triples.)
for (2) i suggest that we use the following query-like presentation (i think Martin used this first on the OSLC blog. need to search out the citation.)
for triple <s,p,o> in graph g we have
U ::= g?subject=s&predicate=p&object=o
Often, g and s are the same URI so this can be abbreviated, if desired.
A GET on U yields <s,p,o>
A PUT on U replaces <s,p,o> in g with <s,p,o> in the body
A POST on U with body <s,p,o> adds <s,p,o> to g
A DELETE on U removes <s,p,o> from g
Some examples.
consder the following resource:
<R rdf:about="http://example.com/req1">
<dc:title>A title for req1<dc:title/>
<dc:contributor>Ian</dc:contributor>
<implementedBy rdf:resource="urn:wi1"/>
<elaboratedBy rdf:resource="urn:model1"/>
</R>
Assume that implementedBy and elaboratedBy are multi-valued properties.
The URI of the graph is the URI of the document; in OSLC we typically identify the HTTP resource with the subject of the rdf:Description node in the RDF/XML. In this case, that's "http://example.com/req1".
So g ==
http://example.com/req1
Example: GET
http://example.com/req1
returns the representation shown above
Example: GET
http://example.com/req1?predicate=implementedBy
returns
<R rdf:about="http://example.com/req1">
<implementedBy rdf:resource="urn:wi1"/>
</R>
Example: PUT
http://example.com/req1?predicate=implementedBy
Body:
<R rdf:about="http://example.com/req1">
<implementedBy rdf:resource="urn:wi1"/>
<implementedBy rdf:resource="urn:wi3"/>
</R>
Adds an implemented by link to req1.
DELETE
http://example.com/req1?predicate=implementedBy&object=urn:wi3
removes the link to wi3.
POST
http://example.com/req1
<R rdf:about="http://example.com/req1">
<supportedBy rdf:resource="urn:model2"/>
</R>
Creates a new "supportedBy" link to model2
More than one rdf:Description in the graph
<R rdf:about="http://example.com/req1">
<dc:title>A title for req1<dc:title/>
<dc:contributor>
<foaf:Person rdf:about="urn:person1">
<foaf:nick>img</foaf:nick>
<foaf:email>img@email.com</foaf:email>
</foaf:Person>
</dc:contributor>
<dc:contributor>
<foaf:Person rdf:about="urn:person2">
<foaf:nick>margaret</foaf:nick>
<foaf:email>maggie@email.com</foaf:email>
</foaf:Person>
</dc:contributor>
<implementedBy rdf:resource="urn:wi1"/>
<elaboratedBy rdf:resource="urn:model1"/>
</R>
To DELETE the contributor "img" -
DELETE
http://example.com/req1?predicate=dc:contributor&object=urn:person1
And so on.
Single-valued, value-type properties
<s,p,"Ian">
is addressed with g?predicate=p. Since p is single-valued, there can only be at most one such triple and thus the object does not need to be part of the address.
Blank nodes
As above, but require that blank nodes have an rdf:nodeID in order that they can be addressed. This requires that the rdf:nodeID is stable in the representation of the named graph.
A triple having an object which is a blank node cannot be addressed and so is not accessible in this restful model.
Literals
Resources which are literals can be addressed by supplying the literal as the value of the object parameter in the URI that addresses that triple. So the URI of the triple
<req1, dc:contributor, "Ian">
would be
g?predicate=dc:contributor&object="Ian"
Problems
There is an assymetry between GET and PUT caused by the way in which elements in this model are addressed by their value.
Example: GET <s,p,o>
returns representation of that triple. The client updates that representation (changes the object), and then does a PUT
PUT <s,p,o>
<s,p,o'>
The intuition here is that the client wants to change the object of the triple - from o to o'. This update means that GET <s,p,o> might now be a 404.
So a PUT on a triple which changes an object from one value to another is more transparently a DELETE followed by a POST. There can be no notion of update on an element which does not have an explicit identity, since it is that notion of identity which is the way that update is defined.
We can either live with this or we could instead exclude PUT from this model. (I think that for links the idea of an update is flawed anyway - so DELETE/POST is correct. For literals DELETE/POST is not right.)
Living with it amounts to introducing a command object. The current OSLC proposal has a command object as well - but it has the addressing of the triple in the http headers.