An Annotea capable client, such as Amaya, interacts with annotation servers using HTTP. We distinguish five types of client-server interactions:
We use the standard HTTP POST protocol for storing a new annotation to the annotation server and HTTP GET protocol for fetching the annotations and returning the result to the client. POST provides the necessary interface for the server to construct a URI for the new annotation and return that URI to the client. When the client has the URI for a previously created annotation, it can (with the proper permissions) use HTTP PUT to modify the annotation and HTTP DELETE to delete an annotation.
In the examples shown here we use the URI
http://annotea.example.org/annot
to refer to an instance of an
annotation service.
To create a new annotation, the client posts some RDF describing the annotation to a selected annotation server. Both the annotation and its body are specified as anonymous RDF resources in the POST message. The server is responsible for allocating the URIs for them. If the body already exists, as will happen if the annotation body is another document that the user wants to use as an annotation, the URI of that existing document can be specified in the RDF when the annotation is posted.
In Figure 1 we illustrate a request to create a simple annotation using an existing document as the body of the annotation.
POST /annot HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 636
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:a="http://www.w3.org/2000/10/annotation-ns#"
xmlns:d="http://purl.org/dc/elements/1.1/">
<r:Description>
<r:type resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
<r:type resource="http://www.w3.org/2000/10/annotationType#Comment"/>
<a:annotates r:resource="http://example.com/some/page.html"/>
<a:context r:resource='http://example.com/some/page.html#xpointer(id("Main")/p[2])'/>
<d:creator>Ralph Swick</d:creator>
<a:created>1999-10-14T12:10Z</a:created>
<d:date>1999-10-14T12:10Z</d:date>
<a:body r:resource="http://www.example.com/mycomment.html"/>
</r:Description>
</r:RDF>
Note that the resource http://www.example.com/mycomment.html
is presumed to exist independently of this annotation.
A design issue we encountered is that we wanted to be able to use XML for describing the body of an annotation, and at the same time we wanted to be able to publish the complete annotation in a single HTTP transaction. In order to use XML in the body, the correct architectural approach is to store the body as a separate resource with its own content type. We therefore designed a simple packaging protocol that permits both the client and server to specify embedded HTTP message bodies. To do this, we declare an RDF namespace for describing certain HTTP headers and we specify those HTTP headers as normal RDF properties, as shown in Figure 2.
In Figure 2, we show the metadata that specifies an annotation of the page
whose URI is http://example.com/some/page.html
. The creator of
this annotation is identified as "Ralph Swick". The text of the annotation
body is "This is an important concept."
POST /annot HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 1082
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:a="http://www.w3.org/2000/10/annotation-ns#"
xmlns:d="http://purl.org/dc/elements/1.1/"
xmlns:h="http://www.w3.org/1999/xx/http#">
<r:Description>
<r:type resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
<r:type resource="http://www.w3.org/2000/10/annotationType#Comment"/>
<a:annotates r:resource="http://example.com/some/page.html"/>
<a:context r:resource='http://example.com/some/page.html#xpointer(id("Main")/p[2])'/>
<d:creator>Ralph Swick</d:creator>
<a:created>1999-10-14T12:10Z</a:created>
<d:date>1999-10-14T12:10Z</d:date>
<a:body>
<r:Description>
<h:ContentType>text/html</h:ContentType>
<h:ContentLength>250</h:ContentLength>
<h:Body r:parseType="Literal">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Ralph's Annotation</title>
</head>
<body>
<p>This is an <em>important</em> concept; see
<a href="http://example.com/other/page.html">other page</a>.</p>
</body>
</html>
</h:Body>
</r:Description>
</a:body>
</r:Description>
</r:RDF>
As specified by the RDF model, the data we pass to the server in the POST is a set of statements describing properties of the new (and unnamed) annotation resource that we would like the server to create. In response to the POST (Fig. 3), a new annotation is created and the server assigns URIs. Now the server has created the URIs for the anonymous resources and they can be used by the browser. The value of the a:body property is a URI of the content of the annotation; in this case the server implementation chose to store the text in a separate location and give it its own URI.
HTTP/1.1 201 Created
Location: http://www.example.org/Annotation/3ACF6D754
Content-Type: application/xml
Content-Length: 404
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:a="http://www.w3.org/2000/10/annotation-ns#"
xmlns:d="http://purl.org/dc/elements/1.1/">
<r:Description about="http://www.example.org/Annotation/3ACF6D754">
<a:annotates r:resource="http://example.com/some/page.html"/>
<a:body resource="http://www.example.org/Annotation/3ACF6D754text"/>
</r:Description>
</r:RDF>
With this little bit of ad hoc packaging we can have a POST method that explicitly creates two resources at the same message and a GET method that returns these same resources in one message. This packaging protocol has the additional advantage that it makes POST and GET of multiple resources an atomic operation; there is no window in which another client might modify the annotation body after the annotation properties have been returned but before the body is returned.
An annotation server is queried for the URIs of annotations it may hold
using the GET method. Since the client will most commonly wish to query for
annotations that have an annotates
property naming a specific
page that the user may currently be viewing, a particular query parameter is
designated to pass the URI of that page, as shown in Figure 4.
GET /annot?w3c_annotates=http://example.com/some/page.html HTTP/1.1
Host: annotea.example.org
Accept: application/xml
The query parameter w3c_annotates
may be best thought of as
an abbreviation for the longer property name
http://www.w3.org/2000/10/annotation-ns#annotates
; that is, this
GET is a short-hand for a query that says "return the names of resources that
are the subjects of RDF statements in which the predicate is
http://www.w3.org/2000/10/annotation-ns#annotates and the object is
http://example.com/some/page.html". The server responds to this GET request
by returning RDF/XML describing the properties of each annotation that has an
annotates
relationship to the given URI. In the first release of
our server implementation, we return all the properties of each annotation
including the URI of the body resource. Figure 5 illustrates a typical
response; in this case there is only one annotation for the specified
page.
HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 689
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:a="http://www.w3.org/2000/10/annotation-ns#"
xmlns:d="http://purl.org/dc/elements/1.1/">
<r:Description about="http://www.example.org/Annotation/3ACF6D754">
<r:type resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
<r:type resource="http://www.w3.org/2000/10/annotationType#Comment"/>
<a:annotates r:resource="http://example.com/some/page.html"/>
<a:context r:resource='http://example.com/some/page.html#xpointer(id("Main")/p[2])'/>
<d:creator>Ralph Swick</d:creator>
<a:created>1999-10-14T12:10Z</a:created>
<d:date>1999-10-14T12:10Z</d:date>
<a:body r:resource="http://www.example.com/mycomment.html"/>
</r:Description>
</r:RDF>
An annotation is downloaded from an annotation server using the GET method and specifying the annotation URI, as returned in a query response (Fig. 6).
GET /Annotation/3ACF6D754 HTTP/1.1
Host: www.example.org
Accept: application/xml
The response to this GET will be as in Figure 5.
An existing annotation is updated using the PUT1 method, specifying the URI of the annotation we wish to update. For example, to update the annotation created in the messages illustrated in Figures 2 and 3 above, we might specify the message in Figure 7.
PUT /Annotation/3ACF6D754 HTTP/1.1
Host: www.example.org
Content-Type: application/xml
Content-Length: 657
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:a="http://www.w3.org/2000/10/annotation-ns#"
xmlns:d="http://purl.org/dc/elements/1.1/">
<r:Description about="http://www.example.org/Annotation/3ACF6D754">
<r:type resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
<r:type resource="http://www.w3.org/2000/10/annotationType#Example"/>
<a:annotates r:resource="http://example.com/some/page.html"/>
<a:context r:resource='http://example.com/some/page.html#xpointer(id("Main")/p[2])'/>
<d:creator>Ralph Swick</d:creator>
<a:created>1999-10-14T12:10Z</a:created>
<d:date>1999-10-14T13:14Z</d:date>
<a:body>
...
</a:body>
</r:Description>
</r:RDF>
An annotation is deleted using the DELETE method, specifying the URI of the annotation we wish to remove. For example, to delete the annotation created in the messages illustrated in Figures 2 and 3 above, we might specify the message in Figure 8.
DELETE /Annotation/3ACF6D754 HTTP/1.1
Host: www.example.org
HTTP/1.1 200 OK
Users want to filter the annotations they see depending on what they are doing. For example, in order to unclutter a heavily annotated document, a user may want only to display annotations made by certain users, or attached to a part of the document, or that were modified in the past 24 hours, or that correspond to a combination of these filters. The filtering may be done locally on the annotations that were already downloaded from the server or remotely, by means of the query string that will be sent to the server. Some of the server queries are going to happen frequently and they can be offered through an easy graphical interface. Other, more complicated queries can be offered to expert users or applications related to semantic Web that want to utilize the annotation information as part of their queries.
We have adapted a form of query language syntax very similar to what is used in Algernon [Crawford90] because it was available to us from other prototyping work. This syntax uses triples in which place-holder variables are denoted by names beginning with a questionmark, such as ?a. The collect clause defines how to output the result of the query. For instance, the query in Figure 9 returns all the annotations attached to a certain document with their annotation URI (?a), the context (?context), the creator (?creator), the time created (?created), the date (?date) and their annotation content URI (?body).
(ask
'((http://www.w3.org/1999/02/22-rdf-syntax-ns#type ?a
http://www.w3.org/2000/10/annotation-ns#Annotation)
(http://www.w3.org/2000/10/annotation-ns#annotates ?a
http://example.com/some/page.html)
(http://www.w3.org/2000/10/annotation-ns#context ?a ?context)
(http://purl.org/dc/elements/1.1/creator ?a ?creator)
(http://www.w3.org/2000/10/annotation-ns#created ?a ?created)
(http://purl.org/dc/elements/1.1/date ?a ?date)
(http://www.w3.org/2000/10/annotation-ns#body ?a ?body)
) :collect '(?a ?context ?creator ?created ?date ?body))
The answer to the query is shown in Figure 10. It can consist of one or more annotation objects or return that no annotations were found. This RDF is processed by the browser and transferred to a format that is presented to the user.
<r:Description
about="http://example.org/CGI/annot?annotation=/2000/05/08-18:04:55">
<r:type
resource="http://www.w3.org/2000/10/annotation-ns#Annotation" />
<a:annotates
r:resource="http://example.com/some/page.html" />
<a:context r:resource='http://example.com/some/page.html#xpointer(id("Main")/p[2])'/>
<d:creator>Ralph Swick</d:creator>
<a:created>1999-10-14T12:10Z</a:created>
<d:date>1999-10-14T12:10Z</d:date>
<a:body
r:resource="http://example.org/CGI/annot?body=/2000/05/08-18:04:55" />
</r:Description>
Currently, Amaya can only send the annotation server couple of different types of queries, such as the one presented in Figure 11, asking for all the annotations related to a page at a given URI. In addition, as a first step to support a more general query mechanism users capable of doing so can write Algae queries in a text box in Amaya. In the future, we plan to extend the query language following closely the work on XML Query working group and try to develop better user interfaces for the queries.
GET /CGI/annot?w3c_annotates=http://example.com/some/page.html
Host: example.org
[1] The use of HTTP PUT to modify annotations is the protocol as designed. For historical reasons, the W3C public Annotea service also implements modification using POST <serviceUri>?replace_source=<annotURI>. The body of the POST is identical to the body of the PUT as shown. For example, the request to modify the annotation shown in this section could be sent to annotea.example.org as: POST /annot?replace_source=http://www.example.org/Annotation/3ACF6D754.
[Crawford90] J. Crawford. Access-Limited Logic: A Language for Knowledge Representation. UT Artificial Intelligence TR AI90-141, Department of Computer Sciences, University of Texas at Austin, Austin, Texas., Oct. 1990.
$Revision: 1.14 $ of $Date: 2001/05/14 10:36:33 $ by $Author: kahan $