Warning:
This wiki has been archived and is now read-only.

Issue-34 - Aggregation: simple proposal

From Linked Data Platform
Jump to: navigation, search

1 Overview

1.1 Vocabulary

The two main classes of object here are ldp:Containers and ldp:Aggregations, For detailed definitions see: Ontology sections It is argued there that ldp:Containers do not have any members in common with ldp:Aggregations.

1.2 Example Summary

We start with the following:

We show how we can use LDP as it is with no changes to create an aggregation container. By LDP as it is we mean the LDP with a strict notion of containership, ie a DELETE of a container deletes all the LDPRs it contains. We do this by:

  1. creating an resource that is a member of the container and that will be named http://localhost:9000/2013/aggReg
  2. <aggReg> LDPR defines an ldp:Aggregation http://localhost:9000/2013/aggReg#ion
  3. editing the aggregate collection using either PUT or PATCH
  4. deleting the aggregate collection using either PUT or PATCH

In both cases PATCH should just be thought of as an efficiency improvement over the equivalent method using PUT.

1.3 Known differences from an LDPC

  • An Aggregation container is not an LDPC. It is a resource defined inside or as an LDPR:  :Aggregation owl:disjointWith :Aggregation .
  • To create an Aggregation container one creates an LDPR, by POSTing the graph that describes the aggregation container to the LDPC
  • Deleting an Aggregation container does NOT delete the resources it contains, deleting an LDPC deletes the resources it contains.

Note that all of this ( except for the efficiency improvements using PATCH ) work with LDP as it is currently defined.

2 Example Interaction Scenario

Let us start with an empty collection http://localhost:9000/2013/.

2.1 Create resources

First we create a foaf:PersonalProfileDocument in the collection at /2013/. This can be done on the command line with curl like this:

$ curl -i -X POST -H "Expect:" -H "Content-Type: text/turtle" -H "Slug: card"  http://localhost:9000/2013/ --data-binary @card.ttl
HTTP/1.1 201 Created
Location: card
Content-Length: 0

The Location header shows that the resulting url is http://localhost:9000/2013/card

( note that, here I use a Slug: card Header to name the resource as proposed in Issue 43, to get a nice human readable name )

2.2 Create a new aggregation inside the container

Create an Aggregation container named aggReg inside the same collection. You can do this by using the telnet program. Connect to the remote server.

$ telnet localhost 9000

Then paste in the HTTP header & body. (Getting the Content-Length right is sometimes tricky)

POST /2013/ HTTP/1.1
Host: localhost:9000
Accept: */*
User-Agent: curl/7.27.0
Content-Length: 200
Slug: aggReg
Content-Type: text/turtle

@prefix : <http://www.w3.org/ns/ldp#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<> a :Document;
   :primaryTopic <#ion> .

<#ion> a :Aggregation;
    rdfs:member <card>,
         <http://www.w3.org/People/Berners-Lee/card> .

This will return a response from the server saying the http://localhost:9000/2013/aggReg resource was created.

HTTP/1.1 201 Created
Location: aggReg
Content-Length: 0

This resource defines the aggregate collection http://localhost:9000/2013/aggReg#ion, which contains the resource created by the collection, and a remote resource, namely Tim Berner's Lee's foaf profile. Tim Berner's Lee's Profile is of course not under the control of this localhost server.

Currently I distinguish between the LDPR <http://localhost:9000/2013/aggReg> and the LDP Aggregation http://localhost:9000/2013/aggReg#ion just to help with clarity. It may be that there is some overlap between the ldp:Aggregation and an LDPR but it would be I don't want to settle the issue immediately.

So at present we have 2 Collections:

First the initial LDP Container:

$ curl -i -X GET -H "Accept: text/turtle" http://localhost:9000/2013/
HTTP/1.1 200 OK
Content-Type: text/turtle
Content-Length: 97

@prefix : <http://www.w3.org/ns/ldp#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<> a :Container;
     rdfs:member <aggReg> , <card> .

This Container contains two LDPRs <aggReg> and <card> .

And secondly the Collection defined inside the LDPR </2013/aggReg> and named </2013/aggReg#ion>.

2.3 Edit the Aggregation Collection

This can be done in a number of ways.

2.3.1 Alternative 1: Using HTTP PUT to replace the content

This would work as the spec is written now. Imagine you wish to add a new person to that aggregation, then you can take the previous content with the previous change and PUT the new representation in place of the old one.

PUT /2013/aggReg HTTP/1.1
Host: localhost:9000
User-Agent: curl/7.27.0
Content-Length: 200
Content-Type: text/turtle

@prefix : <http://www.w3.org/ns/ldp#> .

<> a :Document;
   :primaryTopic <#ion> .

<#ion> a :Aggregation;
    rdfs:member <card>,
               <http://www.w3.org/People/Berners-Lee/card>,
                <http://b4mad.net/FOAF/goern.rdf> .

If the server responds with a 200 then the </2013/aggReg#cnt> collection contains the new member <http://b4mad.net/FOAF/goern.rdf> .

2.3.2 Alternative 2: Using PATCH

Of course the above is a clumsy and inefficient. With a patching mechanism - which the group is commited to come up with - the append could be expressed a lot more easily, like this:

PATCH /2013/aggReg HTTP/1.1
Host: localhost:9000
User-Agent: curl/7.27.0
Content-Length: 90
Content-Type: text/some-patch-language

@prefix : <http://www.w3.org/ns/ldp#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .


INSERT { <#ion> rdfs:member <http://b4mad.net/FOAF/goern.rdf> . }

Deletion could work the same way, and combining them one gets a full update:

PATCH /2013/aggReg HTTP/1.1
Host: localhost:9000
User-Agent: curl/7.27.0
Content-Length: 90
Content-Type: text/turtle

@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

DELETE { <#ion> rdfs:member <http://b4mad.net/FOAF/goern.rdf> . }
INSERT { <#ion> rdfs:member <http://novaspivack.typepad.com/foaf.rdf> . }

here we remove <http://b4mad.net/FOAF/goern.rdf> and then add <http://novaspivack.typepad.com/foaf.rdf>, in the same connection.

2.4 Delete your aggregation

There are two ways one can do that.


2.4.1 Alternative 1: Delete the resource containing the collection

The simplest way is just to delete the resource in which the aggregated collection

Request:

curl -i -X DELETE -H "Expect:"  http://localhost:9000/2013/aggReg
HTTP/1.1 200 OK
Content-Length: 0

This deletes the /2013/aggReg resource

$ curl -i -H "Expect:"  http://localhost:9000/2013/aggReg
HTTP/1.1 404 Not Found

but not the members of the collection

$ curl -i -H "Expect:"  http://localhost:9000/2013/
HTTP/1.1 200 Ok

@prefix : <http://www.w3.org/ns/ldp#> .

<> a :Container;
     rdfs:member <card> .


Ie an HTTP GET on card will still succeed.


2.4.2 Alternative 2: Remove with a PATCH

If for some reason there are other things inside the collection that should be kept, then one can just remove the collection definition itself

PATCH /2013/aggReg HTTP/1.1
Host: localhost:9000
User-Agent: curl/7.27.0
Content-Length: 90
Content-Type: text/turtle

@prefix : <http://www.w3.org/ns/ldp#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .


DELETE { <#ion> ldp:member ?q  . 
              ?s ?r <#ion> . }

Here the aggReg document still exists

$ curl http://localhost:9000/2013/aggReg

@prefix : <http://www.w3.org/ns/ldp#> .

<> a :Document .

But it no longer contains the primary topic. The collection still contains all the members.

$ curl -i -H "Accept: text/turtle" http://localhost:9000/2013/
HTTP/1.1 200 OK
Content-Type: text/turtle
Content-Length: 97

@prefix : <http://www.w3.org/ns/ldp#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .


<> a :Container;
     rdfs:member <aggReg> , <card> .

3 Further Open Questions

3.1 LDPAs and LDPRs

3.1.1 can LDPAs be LDPRs?

It seems very reasonable to have LDPRs be LDPAs.

{
  [] owl:intersectionOf ( ldpx:Resource ldpx:Aggregation ) 
      owl:differentFrom owl:Nothing .
 }  defendedBy [ = g5; foaf:member <http://bblfish.net/people/henry/card#me> ];
    = :lemma5 .

That is compatible with my example. It is just that in the example I tried not to take the special case. Essentally it would allow

<http://localhost:9000/2013/aggReg> to contain 

{ <> a ldpx:Aggregation . }

3.1.2 Must LDPAs be LDPRs ?

Others may want to claim that

{
   ldp:Aggregation rdfs:subClassOf ldp:Resource .
 }  defendedBy g6;
    owl:sameAs :c6 .

3.2 Inclusion of LDPC contents in an LDPA ?

It may be useful to be able to state in one line that all the members of an LDPC are members of an LDPA. (use case?) If so then a membership inclusion relation could do that by reference.

4 Notes

4.1 Representing containment and/or aggregation links

  • paraphrased email Steve Battle: I think we should avoid overloading existing aggregation properties because we may want the option to add existing (i.e. unmanaged) resources to a container via aggregation (e.g. using rdfs:member or its ilk). Indeed, I see this as the function of the ldp:membershipPredicate; as a convenience to create a structured aggregation/collection over and above the container structure.

4.2 Email threads that have been incorporated above