W3C Annotea

Annotea Protocols

This version:
http://www.w3.org/2002/12/AnnoteaProtocol-20021219
Latest version:
http://www.w3.org/2001/Annotea/User/Protocol
Previous version:
http://www.w3.org/2001/Annotea/User/Protocol-20010514
Authors:
Ralph Swick <swick>
Eric Prud'hommeaux <eric>
Marja-Riitta Koivunen <marja>
Jose Kahan <jose>

Abstract

Annotea is a system for creating and publishing shareable annotations of Web documents. Built on HTTP, RDF, and XML, Annotea provides an interoperable protocol suitable for implementation within Web browsers to permit users to attach data to Web pages such that other users may, at their choice, see the attached data when they later browse the same pages. The Annotea protocol works without modifying the original document; that is, there is no requirement that the user have write access to the Web page being annotated. The Annotea protocol is suitable both for annotation data that is expected to be primarily for human viewing as well as annotation data that is expected to be consumed by other application programs, such as automatic classification tools, search engines, and workflow applications.

Status of this document

This section describes the status of this document at the time of its publication. This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. The latest status of this document series is maintained at the W3C.

This document is a public DRAFT for discussion. It documents work that is part of the W3C Semantic Web Advanced Development project. This document is made available by W3C for discussion only. Publication of this document by W3C does not imply endorsement by W3C, including the Team and Membership.

The aim of this DRAFT document is to describe the general Annotea protocol as the authors currently see it. Separate documents will describe specific server and client implementations.

Our future plans include a revision of the protocol to add some extra information (attributions) about the origin of the data. The goal is to have better means to deal with metadata that is added to already existing annotations by other users and to be able separate that information when doing annotation or reply updates or deletes. This work is just beginning although the authors have done some experiments with their server implementation.

We expect to have more discussions in the www-annotation@w3.org mailing list about attributions and other protocol issues that may arise. Comments on this document may be sent to that mailing list, and are archived in a public archive.

Table of contents

  1. Overview
  2. Annotation protocols
    1. Posting a new annotation
      1. Posting a new annotation with an existing body
      2. Posting a new annotation with a new body
    2. Querying an annotation service
    3. Downloading an annotation or its body
    4. Updating an annotation
    5. Deleting an annotation
  3. Protocols for replies
    1. Posting a new reply
    2. Querying an annotation service for replies
    3. Downloading a reply or its body
    4. Updating a reply
    5. Deleting a reply
  4. Optimizing query requests
Acknowledgements
References
Appendix A Customized queries using Algae
Appendix B: Updating annotations with HTTP POST
Appendix C: Changes

1 Overview

This document describes a protocol for manipulating sharable annotations of Web documents. The protocol specifies how data is to be exchanged between a conforming client - an application that produces and consumes annotation data - and a service - an application that stores the data and supports query capabilities to return some or all of the stored data.

While clients are generally expected to present annotations visually in a graphical user interface, the Annotea protocol does not require nor does it assume that the data is generated or consumed by a visual tool. The Annotea protocol is equally suitable for use by applications to exchange data for non-visual uses by 'attaching' it to Web pages where no write access to the Web page is required.

An annotation service is an instance of an HTTP server that responds to the Annotea protocol at a specific URI. A single HTTP server might support multiple annotation services at the same host address; each such annotation service would have its own URI with the same 'host' portion. A site administrator may provide multiple annotation services on a single host as a convenience for simple clustering of annotations; e.g. multiple separate work groups, or for access control purposes, or for any other installation-dependent reason.

An Annotea capable client, such as Amaya, interacts with one or more annotation services using a set of protocols that are built on top of the HTTP protocol as described by this document.

Annotea currently specifies three kinds of protocols:

Annotation protocols (Section 2)
Describes the client-server interactions related to posting, downloading, updating, and deleting annotations.
Reply-to-annotation protocols (Section 3)
Describes the client-server interactions that support replies to annotations and thus promote threads of discussion.
Optimizing query requests (Section 4)
Describes special URI query parameters to combine queries in a single HTTP request.

In addition to defining the above protocols, Appendix A describes a generalized RDF query language called Algae that is used to implement the queries described in Section 4.

Notation:

The examples in this document attempt to use the following Web addresses consistently to denote instances of the following classes of server or service:

http://annotea.example.org
An instance of an annotation server.
http://annotea.example.org/Annotation
An instance of an annotation service, whose interface is the Annotation script. The specific name of this script, and thus the choice of the annotation service URI is chosen by the Web site administrator.
http://serv1.example.com/
http://serv2.example.com/
Instances of general Web (document) servers.

2 Annotation Protocols

We distinguish the following types of client-server interactions supporting annotations and replies to annotations:

Annotea uses a standard HTTP POST message to publish a new annotation to the annotation service and HTTP GET messages to fetch any annotations and return the result to the client. HTTP POST provides the necessary interface for the server to construct a URI for the new annotation and return that URI to the client. With a URI for a previously created annotation, the client can (with the proper permissions) use HTTP PUT to modify the annotation and HTTP DELETE to delete an annotation. HTTP GET is used for querying an annotation service.

2.1 Posting a new annotation

When a client creates a new annotation it posts RDF statements in an XML body that describe the new annotation resource to a selected annotation service. The client constructs an HTTP POST message containing the annotation as an anonymous RDF resource. The annotation service is responsible for allocating a URI for the annotation. The URI allocation mechanism is implementation dependent and not defined by this document.

The RDF/XML statements in the POST message define some information about the annotation; for example, a name for the user who created the annotation and the date on which it was created. The body of an annotation is a separate resource (Web document) that contains the material that the user wishes to convey through the annotation; that is, in a typical application the body would hold the text that a user entered to be the "content" of the annotation. The POST message must either refer to the URI of the body of the annotation (Section 2.1.1) or include the body in the message itself (Section 2.1.2). For both cases, the server sends back similar reply messages.

2.1.1 Posting a new annotation with an existing body

In the Annotea protocol, the body of the annotation can be a URI to an already existing document. As the body exists independently of the annotation, we refer to it as an external body. This section specifies the case in which an annotation is created using a known document as the annotation body.

In Figure 2.1 we show a request to the annotation service whose Web address is http://annotea.example.org/Annotation to create a simple annotation that annotates the Web page http://serv1.example.com/some/page.html while using an existing Web document http://serv2.example.com/mycomment.html as the body of the annotation. The creator of this annotation is identified as "Ralph Swick". Note that the body of the annotation could be stored anywhere, including serv1.example.com or on the annotation server itself. Figure 2.1 shows only a minimal set of HTTP headers.

POST /Annotation HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 786

<?xml version="1.0" ?>
<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 r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
  <r:type r:resource="http://www.w3.org/2000/10/annotationType#Comment"/>
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <a:context>
    http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])
  </a:context>
  <d:title>Annotation of Sample Page</d:title>
  <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://serv2.example.com/mycomment.html"/>
 </r:Description>
</r:RDF>

Figure 2.1: Creating an annotation with POST, using an existing document as the body.

The client must include an RDF type property specifying http://www.w3.org/2000/10/annotation-ns#Annotation as (one of) the annotation types and must include an http://www.w3.org/2000/10/annotation-ns#annotates property identifying the Web document to which the annotation refers. The queries specified in Section 2.2 rely on these two properties being present.

If the POST was not successful, the server should return a failure using any of the HTTP error statuses, such as those found in the 4xx family. If the POST was successful, the server responds with the status 201 Created.

If the POST was successful, the server creates a new annotation and assigns it a URI. The server must then reply with a set of RDF statements about the new annotation, giving the URI of the annotation that was posted (see the Location: header and r:about), and including the URI of the document that was annotated (see a:annotates) and the URI of the annotation body (see a:body). The reason for recalling the URI of the body is that by doing so the server can share the same reply regardless of which POST protocol was used.

Figure 2.2 shows a sample reply to the POST request sent in Figure 2.1. The HTTP Location header and the RDF about attribute must match. The server may include in the reply other RDF statements in addition to annotates and body. Clients may ignore any of the RDF statements in the server reply that they do not need.

Note: the authors solicit feedback on whether any implementations depend on having either the annotates or body properties included in this reply.

HTTP/1.1 201 Created
Location: http://annotea.example.org/Annotation/3ACF6D754
Content-Type: application/xml
Content-Length: 432

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/Annotation/3ACF6D754">
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <a:body r:resource="http://serv2.example.com/mycomment.html"/>
 </r:Description> 
</r:RDF>

Figure 2.2: Sample reply for the POST request sent in Figure 2.1

This protocol places no restrictions on the specific URI that the server may choose for the annotation; the server is free to assign any URI that it wishes, though in general the URI should be on the same host as the annotation service. There also need not be any textual similarity between the URIs for annotations and the name of the annotation service itself.

An Annotea server is only required to support UTF-8 encoding. Clients are responsible for making conversions between other encodings before sending requests to the server.

2.1.2 Posting a new annotation with a new body

In the case of a annotation with a new body, the client's POST message must include both the annotation metadata and the body of the annotation. The Annotea protocol is designed to permit the body to be a full XML document. The body is specified in the message as an anonymous resource. The server must allocate new URIs for both the annotation and for the body.

The Annotea protocol permits a new annotation body to have its own content type, just as an external body would have. Thus allows a client to use XML facilities such as XHTML, MATHML, and SVG in the body. At the same time, it was a design goal to minimize the number of server round-trips required to create an annotation. Therefore, Annotea specifies an RDF mechanism to publish a complete annotation in a single HTTP transaction and include the body as an separately identifiable XML document. From an architectural point of view, this mechanism to embed two XML documents in a single HTTP message is similar to the W3C XML fragment interchange work. Annotea pre-dates the XML fragment interchange working drafts. The authors have not decided whether to move to using that mechanism.

This Annotea protocol specifies a simple packaging protocol that permits a client to specify embedded HTTP message bodies. To do this, Annotea declares an RDF namespace for describing certain HTTP headers (http://www.w3.org/1999/xx/http#) and then a client specifies those HTTP headers as normal RDF properties.

In Figure 2.3 we show a request to the annotation service whose Web address is http://annotea.example.org/Annotation to create an annotation on the page http://serv1.example.com/some/page.html. The creator of this annotation is also "Ralph Swick". The body of this annotation contains "This is an important concept; see other page". The annotation metadata specifies an annotation body (a:body) using RDF properties for the HTTP headers (h:ContentType, h:ContentLength) and for the actual XHTML to be presented with the annotation (h:Body).

POST /Annotation HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 1258

<?xml version="1.0" ?>
<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 r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
  <r:type r:resource="http://www.w3.org/2000/10/annotationType#Comment"/>
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <a:context>
     http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])
  </a:context>
  <d:title>Annotation of Sample Page</d:title>
  <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>289</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://serv1.example.com/other/page.html">other page</a>.</p>
      </body>
     </html>
    </h:Body>
   </r:Description>
  </a:body>
 </r:Description>
</r:RDF>

Figure 2.3: Creating an annotation and a body with POST.

The client must include an RDF type property specifying http://www.w3.org/2000/10/annotation-ns#Annotation as (one of) the annotation types and must include an http://www.w3.org/2000/10/annotation-ns#annotates property identifying the Web document to which the annotation refers. The queries specified in Section 2.2 rely on these two properties being present.

If the POST was not successful, the server should return a failure using any of the HTTP error status codes, such as those found in the 4xx family. If the POST was successful, the server responds with the status 201 Created.

If the POST was successful, the server creates a new annotation, assigns it a URI, creates a separate body resource, and assigns the body resource a URI. The server must reply with a set of RDF/XML statements about the new annotation, giving the URI of the annotation (see the Location HTTP header and r:about), and including the URI of the document that was annotated (see a:annotates) and the URI of the newly created body in an a:body property as shown in Figure 2.4. The Location header and the RDF about attribute describing the new annotation must match. The server may return other implementation dependent RDF statements as well, that a client may choose to ignore. Both the annotation and the body URIs can be browsed as any other Web address (i.e. with HTTP GET).

Note: the authors solicit feedback on whether any implementations depend on having the annotates property included in this reply.

HTTP/1.1 201 Created
Location: http://annotea.example.org/Annotation/3ACF6D756
Content-Type: application/xml
Content-Length: 445

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/Annotation/3ACF6D756">
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <a:body r:resource="http://annotea.example.org/Annotation/body/3ACF6D756"/>
 </r:Description> 
</r:RDF>

Figure 2.4: Sample response when creating a new annotation with a new body.

This protocol places no restrictions on the specific URIs that the server may choose for the annotation and for the body; the server is free to assign any URIs that it wishes, although in general the URIs should be on the same host as the annotation service. There need not be any textual similarity between the URIs for annotations and the URIs for their associated bodies, nor between the URIs for annotations and the name of the annotation service itself.

With this ad hoc packaging Annotea defines a POST method that explicitly creates two resources with a single message. This packaging protocol has the additional advantage that it makes POST of multiple resources an atomic operation; there is no time window in which another client might modify the annotation body after the annotation properties have been stored but before the body is stored.

2.2 Querying an annotation service

A client queries an annotation service for the URIs of annotations it may hold by using the HTTP GET method. A service may support various kinds of queries, for example, to retrieve only the annotations made by a given user at a given time period.

This version of the Annotea protocol specification does not include a full query language for annotations. Rather, since clients will most commonly wish to query for annotations that have an annotates property naming a specific page that the user may currently be viewing, the protocol specifices a particular URL query parameter for passing the URI of the designated page to the server. This provides a simple implementation for annotation clients and servers without requiring the implementation of a custom query language. Appendix A describes the Algae custom query language that the authors are currently experimenting in the W3C sample annotation server.

Figure 2.5 shows the request that a client would issue if the user was viewing the page http://serv1.example.com/some/page.html and the client wished to know what annotations of that page might be available at a specific annotation service.

GET /Annotation?w3c_annotates=http://serv1.example.com/some/page.html HTTP/1.1
Host: annotea.example.org
Accept: application/xml

Figure 2.5: Querying an annotation service for annotations annotating http://serv1.example.com/some/page.html.

Figure 2.5 illustrates a sample annotation server query. As with the POST requests shows above, the specific choice of URI; i.e "/Annotation" in this example, identifies a script on the server that will handle the query. The name of this script and thus the full annotation service URI is selected by the Web site implementor. The query parameter w3c_annotates must be used as shown; that is, the script must recognize this specific parameter. The w3c_annotates parameter 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://serv1.example.com/some/page.html".

The server responds to this GET request by returning RDF/XML describing all the properties of each annotation that has an annotates relationship to the given URI. These properties include the URI of the body resource. Figure 2.6 illustrates a typical response; in this case there is only one annotation for the specified page. A client should expect the query response to include the properties that are described in the Annotea RDF schemas. Depending on the implementation, the server may return other RDF properties that are associated with the annotation. A client may choose to ignore any properties it wishes.

HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 860

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/Annotation/3ACF6D756">
  <r:type r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
  <r:type r:resource="http://www.w3.org/2000/10/annotationType#Comment"/>
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <d:title>Annotation of Sample Page</d:title>
  <a:context>
       http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])
  </a:context>
  <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://annotea.example.org/Annotation/body/3ACF6D754"/>
 </r:Description>
</r:RDF>

Figure 2.6: A typical response to the query of Figure 2.5.

2.3 Downloading an annotation or its body

As shown in Section 2.2, each annotation and the body of the annotation are associated with a distinct URI. Both the annotation and the body can be downloaded by browsing their respective URIs using the GET method. Figure 2.7 shows the request to retrieve the annotation that was created in Figure 2.3.

When downloading an annotation, the server should return all the properties associated with the annotation. These properties should include the ones that were in the original POST, and should also include other properties that may have been added by the server or by other users.

GET /Annotation/3ACF6D756 HTTP/1.1
Host: annotea.example.org
Accept: application/xml

Figure 2.7: Downloading a specific annotation.

For downloading the body that was created in Figure 2.3, we just follow the URI that was given as the value of the a:body property. This is illustrated in Figure 2.8.

GET /Annotation/body/3ACF6D756 HTTP/1.1
Host: annotea.example.org
Accept: application/xml

Figure 2.8: Downloading a specific annotation body.

2.4 Updating an annotation

An existing annotation can be updated by using the PUT method and by specifying the URI of the annotation the client wishes to update.

Note: The use of HTTP PUT to modify annotations is the intended protocol as designed. For historical reasons, the W3C public Annotea service also implements a modification using POST. See Appendix B.

In this version of the Annotea protocol, clients MUST include in the PUT all the properties that they want the server to remember, whether they have changed or not. This includes the body contents if the body was stored in the annotation server. The service may choose to discard some of the properties that are sent by the client; for example, if the service intends to override those property values with other values determined by the service.

Note: In the future, the authors intend to develop a more flexible update protocol that permits updating a subset of the annotation properties without requiring clients to PUT every property and to permit clients to update some properties without re-publishing the annotation body.

Figure 2.9 illustrates a sample annotation update message for the annotation whose URI is http://annotea.example.org/Annotations/3ACF6D754. The PUT specifies the URI of the annotation that must be updated. This URI should already exist in the annotation server. The body of this HTTP request is similar to the one sent when first publishing the annotation (see Figure 2.3).

PUT /Annotations/3ACF6D754 HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 1316

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/Annotation/3ACF6D754">
  <r:type r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
  <r:type r:resource="http://www.w3.org/2000/10/annotationType#Example"/>
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <d:title>Annotation of Sample Page</d:title>
  <a:context>http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])</a:context>
  <d:creator>Ralph Swick</d:creator>
  <a:created>1999-10-14T12:10Z</a:created>
  <d:date>1999-10-14T13:14Z</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://serv1.example.com/other/page.html">other page</a>.
       </p>
      </body>
     </html>
    </h:Body>
   </r:Description>
  </a:body>
 </r:Description>
</r:RDF>

Figure 2.9: Updating an annotation and its body using PUT.

If the PUT is successful, the server should respond with status 200 OK. The server may respond with other HTTP status codes as appropriate for other circumstances.

The server responds to a PUT request by returning RDF/XML that recalls the URIs of the annotation and its body (see Figure 2.10). A client should expect to receive back the properties that are described in the Annotea RDF schemas. Depending on the implementation, the server may return other RDF properties that are associated with the annotation. A client may choose to ignore those extra properties.

HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 860

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/Annotation/3ACF6D754">
  <r:type r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
  <r:type r:resource="http://www.w3.org/2000/10/annotationType#Comment"/>
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <d:title>Annotation of Sample Page</d:title>
  <a:context>
       http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])
  </a:context>
  <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://annotea.example.org/Annotation/body/3ACF6D754"/>
 </r:Description>
</r:RDF>

Figure 2.10: Reply to a an annotation update message.

2.5 Deleting an annotation

An annotation is deleted using the DELETE method, specifying the URI of the annotation the client wishes to remove. All properties created with the original POST or updated with PUT messages are deleted so the server needs to maintain an association between these statements. For example, to delete the annotation created in the message illustrated in Figure 2.1 above, a client uses the message shown in Figure 2.11. If the body content was included in the POST as in Figure 2.3 the server should also delete the body resource.

If the DELETE is successful, the server should respond with status 200 OK. The server may respond with other HTTP status codes as appropriate in other circumstances.

DELETE /Annotation/3ACF6D754 HTTP/1.1
Host: annotea.example.org

HTTP/1.1 200 OK

Figure 2.11: Deleting an annotation using DELETE.

3 Protocols for replies

Annotations are commonly thought of as comments that people can make about a Web document. To facilitate discussion about Web documents through the use of annotations, the Annotea protocol includes a separate class of resource called Reply. Replies are a mechanism that allows people to publish replies to annotations; for example, they allow someone to reply to a comment. Replies can also be made to other replies and thus promote threads of discussion. Moreover, as each reply is identified with a unique URI, the Annotea protocol also permits a client to annotate a reply.

Annotea does not define a dedicated RDF reply schema independent of its annotation schema. A reply can be seen rather as a set of RDF statements that include most of the Annotation RDF schema properties. That is, an instance of a Reply will have most of the same properties that an instance of an Annotation has. Two features distinguish a Reply from an Annotation; the type and the http://www.w3.org/2000/10/annotation-ns#annotates property. Replies have RDF type http://www.w3.org/2001/03/thread#Reply and do not use the http://www.w3.org/2000/10/annotation-ns#annotates property. They use instead two new properties defined in a Discussion Thread RDF schema:

Replies have the same four protocol operations that are defined for annotations:

3.1 Posting a new reply

When creating a new reply, a client posts RDF/XML statements that describe the new reply resource. The reply can be posted to the same server in which the thread root annotation is stored or to another server. All replies belonging to the same discussion thread MUST be stored in the same server; that is, a reply to a reply must be posted to the service that hosts the initial reply. This is to permit the annotation service to exercise full control over an entire thread; for example, to prohibit the deletion of a reply from the middle of a thread. Note that when a discussion thread is not stored in the same server as the annotation to which it is attached, there is no protection against making an orphan discussion thread; that is, the root annotation may be deleted, thus breaking the link from discussion thread to that annotation.

An instance of a reply is created using an HTTP POST message very similar to the messages described in Section 2.1. The RDF statements in the POST message identify the resource that is being replied-to, as well as the discussion thread to which the reply belongs. Other properties are identical to those discussed above for creating an annotation.

In Figure 3.1, we show the metadata that specifies a reply to an annotation whose URI is http://annotea.example.org/Annotation/3ACF6D754. The creator of this reply is identified as "Marja". This message includes the reply body. The text of the reply body is "I agree with Ralph. What would be the next step?".

POST /Annotation HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 1254

<?xml version="1.0" ?>
<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:tr="http://www.w3.org/2001/03/thread#"
       xmlns:h="http://www.w3.org/1999/xx/http#"
       xmlns:rt:"http://www.w3.org/2001/12/replyType">
 <r:Description>
  <r:type r:resource="http://www.w3.org/2001/03/thread#Reply"/>
  <r:type r:resource="http://www.w3.org/2001/12/replyType#Agree"/>
  <tr:root r:resource="http://annotea.example.org/Annotation/3ACF6D754"/>
  <tr:inReplyTo r:resource="http://annotea.example.org/Annotation/3ACF6D754"/>
  <d:title>Annotation of Sample Page</d:title>
  <d:creator>Marja</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>221</h:ContentLength>
    <h:Body r:parseType="Literal">
     <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
       <title>Marja's Reply</title>
      </head>
      <body>
       <p>I agree with Ralph. What would be the next step?</a>.</p>
      </body>
     </html>
    </h:Body>
   </r:Description>
  </a:body>
 </r:Description>
</r:RDF>

Figure 3.1: Creating a reply with POST.

In this case, the new reply is the first one in the thread so the client specifies the same value for the root and inReplyTo properties. A further reply to the reply created by this message would use the same value for the root property but would specify the URI of the reply returned as shown in Figure 3.2 in its inReplyTo property.

Like annotations, the annotation service creates a new Reply resource in response to the POST and returns its URI (Figure 3.2) with HTTP status code 201 Created. The server must reply with a set of RDF/XML statements about the newly created Reply resource, giving the URI of the Reply resource (see the Location HTTP header and r:about), and the URI of the newly created body in an a:body property as shown in Figure 2.4. The Location header and the RDF about attribute must match. The service may return other RDF statements.

HTTP/1.1 201 Created
Location: http://annotea.example.org/Annotation/2DCC6DF41
Content-Type: application/xml
Content-Length: 579

<?xml version="1.0" ?>
<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:tr="http://www.w3.org/2001/03/thread#">
 <r:Description r:about="http://annotea.example.org/Annotation/2DCC6DF41">
  <tr:root r:resource="http://annotea.example.org/Annotation/3ACF6D754"/>
  <tr:inReplyTo r:resource="http://annotea.example.org/Annotation/3ACF6D754"/>
  <a:body r:resource="http://annotea.example.org/Annotation/2DCC6DF41text"/>
 </r:Description> 
</r:RDF>

Figure 3.2: Sample response when creating a new reply

Note that as for annotations it is also possible to specify an external body for a reply. The only change to the message shown in Figure 3.2 to specify an external reply body would be to use the URI of the external body as the value of the a:body property. The server response will be the same except for this URI.

3.2 Querying an annotation service for replies

A client queries an annotation service for the URIs of replies it may hold by using the HTTP GET method. Since clients will most commonly wish to query for replies that have a root property naming a specific annotation that the user is viewing, a particular query parameter is designated to pass the URI of that annotation, as shown in Figure 3.3.

GET /Annotation?w3c_reply_tree=http://annotea.example.org/Annotation/3ACF6D754 HTTP/1.1
Host: annotea.example.org
Accept: application/xml

Figure 3.3: Querying an annotation service for replies in the thread starting from the annotation http://annotea.example.org/Annotation/3ACF6D754.

The query parameter w3c_reply_tree may be best thought of as an abbreviation for the longer property name http://www.w3.org/2001/03/thread#root; 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/2001/03/thread#root and the object is http://annotea.example.org/Annotation/3ACF6D754".

The service responds to this GET request by returning a set of statements expressed in RDF/XML describing each reply that has an root relationship to the specified root URI. Figure 3.4 illustrates a typical response; in this case there is only one reply for the specified annotation.

HTTP/1.1 200 OK
Content-Type: application/xml
Content-Length: 689

<?xml version="1.0" ?>
<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:tr="http://www.w3.org/2001/03/thread#">
 <r:Description r:about="http://annotea.example.org/Annotation/2DCC6DF41">
  <r:type r:resource="http://www.w3.org/2001/03/thread#Reply"/>
  <r:type r:resource="http://www.w3.org/2001/03/thread#Agree"/>
  <tr:root r:resource="http://annotea.example.org/Annotation/3ACF6D754"/>
  <tr:inReplyTo r:resource="http://annotea.example.org/Annotation/3ACF6D754"/>    
  <d:title>Annotation of Sample Page</d:title>
  <d:creator>Marja</d:creator>
  <a:created>1999-10-14T12:10Z</a:created>
  <d:date>1999-10-14T12:10Z</d:date>
  <a:body r:resource="http://annotea.example.org/Annotation/2DCC6DF41text"/>
 </r:Description>
</r:RDF>

Figure 3.4: A typical response to the query in Figure 3.3.

The service must return all the properties for each Reply including the type, root, and inReplyTo properties that facilitate a generation of a hierarchical thread view. The service may return also additional RDF properties.

3.3 Downloading a reply or its body

Both a reply and its body have distinct URIs. Each can be downloaded by using a GET method with the corresponding URI. Figure 3.5 shows how to download the reply created by the message of Figure 3.3 and Figure 3.6 shows how to download the body of the same reply.

GET /Annotation/2DCC6DF41 HTTP/1.1
Host: annotea.example.org
Accept: application/xml

Figure 3.5: Downloading a specific reply.

If the request is successful, the server must reply with 200 OK and all the properties of the Reply it wishes the client to have in RDF/XML form. The server may reply with any of the HTTP status codes in other circumstances.

GET /Annotation/2DCC6DF41text HTTP/1.1
Host: annotea.example.org
Accept: application/xml

Figure 3.6: Downloading a body of a reply.

If the request is successful, the server must reply with 200 OK and the content of the Reply body. The server may reply with any of the HTTP status codes in other circumstances.

3.4 Updating a reply

An existing reply is updated using the PUT method using the URI of the reply the client wishes to update.

Note: The use of HTTP PUT to modify replies is the intended protocol as designed. For historical reasons, the W3C public Annotea service also implements a modification using POST. See Appendix B.

In this version of the Annotea protocol, clients MUST include in the PUT all the properties that they want the server to remember, whether these properties have changed or not. This includes the body contents if the body was stored in the annotation server. The service may choose to discard some of the properties that are sent by a client; for example, if the service intends to override those property values with other values determined by the service. For example, to update the reply created in the message illustrated in Figure 3.1 above, a client can use the message in Figure 3.7.

PUT /Annotation/2DCC6DF41 HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 864

<?xml version="1.0" ?>
<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:tr="http://www.w3.org/2001/03/thread#">
 <r:Description r:about="http://annotea.example.org/Annotation/2DCC6DF41">
  <r:type r:resource="http://www.w3.org/2001/03/thread#Reply"/>
  <r:type r:resource="http://www.w3.org/2001/03/thread#Agree"/>
  <tr:root r:resource="http://annotea.example.org/Annotation/3ACF6D754"/>
  <tr:inReplyTo r:resource="http://annotea.example.org/Annotation/3ACF6D754"/> 
  <d:title>Annotation of Sample Page</d:title>
 <d:creator>Marja</d:creator>
  <a:created>1999-10-14T12:10Z</a:created>
  <d:date>1999-10-14T12:10Z</d:date>
  <a:body r:resource="http://annotea.example.org/Annotation/2DCC6DF41text"/>
 </r:Description>
</r:RDF>

Figure 3.7: Updating a reply using PUT.

3.5 Deleting a reply

A reply is deleted using the DELETE method, specifying the URI of the reply a client wishes to remove. All properties created with the original POST message or updated with PUT messages are deleted. For example, to delete the reply created in the message illustrated in Figure 3.1 above, a client uses the message in Figure 3.8.

DELETE /Annotation/2DCC6DF41 HTTP/1.1
Host: annotea.example.org

HTTP/1.1 200 OK

Figure 3.8: Deleting a reply using DELETE.

The server must respond with HTTP status code 200 OK if the delete was successful and may respond with any of the other HTTP status codes otherwise.

Deleting a reply in a middle of a discussion thread makes the rest of the thread orphaned. To prevent this, Annotea servers may define different policies for deleting and updating replies. For instance, it is possible to allow no deletions at all, allow just deletions of the replies when the reply is a leaf reply and does not have replies of its own, or define some other policies.

Note: The W3C public Annotea service does not allow deletions unless the reply is a leaf reply. If the reply is not a leaf reply, then successive replies on the thread must be deleted first.

4. Optimizing query requests

In sections 2.2 and 3.2, we defined two URL query parameters for retrieving annotations and replies to annotations. If a client implements a user interface that presents all the annotations and replies in a hierarchical view, it might issue separate queries (GET requests) to the annotation service; one for retrieving the annotations and another to retrieve any threads rooted at each annotation.

When a client is viewing a specific annotation, however, it may prefer to issue a single query to the annotation service to return all the information about annotations and replies of that annotation.

If a client knows that it is making a query for statements regarding an annotation, it may combine both query parameters in a single request as shown in Figure 4.1. The query parameters that follow the Annotation fragment are indented below for better readability. They should be concatenated on a single line when sending the request.:

GET /Annotation
     ?w3c_annotates=http://annotea.example.org/Annotation/3ACF6D754/2DCC6DF41
     ?w3c_reply_tree=http://annotea.example.org/Annotation/3ACF6D754/2DCC6DF41 HTTP/1.1
Host: annotea.example.org
Accept: application/xml

Figure 4.1: Combining multiple query requests.

The result of the above request would be all the annotations and replies related to the given URI. As the above request could be misused (some clients may concatenate many queries in the same request), a server may refuse to honor the above request. An Annotea client must then make each request individually.

Acknowledgements

Development of Annotea and Algae is supported in part by funding from US Defense Advanced Research Projects Agency (DARPA) and Air Force Research Laboratory, Air Force Materiel Command, USAF, under agreement number F30602-00-2-0593, "Semantic Web Development" and also by Elisa Communications Oyj, Finland.

References

[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.

[Algae] http://www.w3.org/1999/02/26-modules/User/Algae-HOWTO.html

Appendix A: Customized queries using Algae

This is an informational appendix. Annotea clients and servers are not required to implement the Algae query language described here.

Algae is a query language that the authors have implemented in the W3C Annotea server. Algae provides general RDF queries to an annotation server in order to retrieve any set of RDF statements.

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 by clients on the annotations that were already downloaded from the server or remotely, by means of the query string that will be sent to the service. Some of the service queries are going to happen frequently and clients can offer them through an easy graphical interface. Other more complicated queries can be offered through a generic "expert user" interface or to Semantic Web applications that want to utilize the annotation information as part of their operation.

The authors have adapted a form of query language syntax very similar to the language used in Algernon [Crawford90] because it was available from other prototyping work. This syntax uses triples in which place-holder variables are denoted by names beginning with a questionmark, such as ?annot, a variable for an annotation URI. Contrary to conventional RDF triple notations, the order of the items within Algae triples is (predicate subject object). The triples, with their place-holder variables, form a template (or pattern) that the Algae engine uses to locate matching triples in its RDF data store. The template follows the 'ask' instruction. The collect clause (:collect) specifies the properties that are desired in the output result of the query. For instance, the query in Figure A.1 returns all the annotations attached to a document http://serv1.example.com/some/page.html with their annotation URI (?annot) and all the properties and values of that annotation.

(namespace (rdf http://www.w3.org/1999/02/22-rdf-syntax-ns#)
           (a http://www.w3.org/2000/10/annotation-ns#)
           (dc http://purl.org/dc/elements/1.1/)
ask
     '((a::annotates ?annot http://serv1.example.com/some/page.html)
       (?property ?annot ?value)
      ) :collect '(?annot ?property ?value))

Figure A.1: A sample query to the database from the annotation server.

It is also possible to explicitly enumerate each of the properties that should be returned. The query in Figure A.2 returns all the annotations attached to a certain document with their annotation URI (?annot), the context (?context), the creator (?creator), the time created (?created), the date (?date) and their annotation content URI (?body). The title is not returned here as it was not specified in this query. Note that this query specifies that the triple pattern must include each of the listed properties; if an annotation does not have a body property then it will not be returned in this query result.

(namespace (rdf http://www.w3.org/1999/02/22-rdf-syntax-ns#)
           (a http://www.w3.org/2000/10/annotation-ns#)
           (dc http://purl.org/dc/elements/1.1/)
ask
     '((rdf::type ?annot a::Annotation) 
       (a::annotates ?annot http://serv1.example.com/some/page.html)
       (a::context ?annot ?context)
       (dc::creator ?annot ?creator)
       (a::created ?annot ?created)
       (dc::date ?annot ?date)
       (a::body ?annot ?body)
      ) :collect '(?annot ?context ?creator ?created ?date ?body))

Figure A.2: A sample query to the database from the annotation server.

A typical answer to the query in Figure A.2 is shown in Figure A.3. It can consist of one or more annotation objects or return an empty result set indicating that no matching annotations were found. This RDF is processed by the browser and transferred to a format that is presented to the user.

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/CGI/annot?annotation=/2000/05/08-18:04:55">
   <r:type r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation" />
   <a:annotates r:resource="http://serv1.example.com/some/page.html" />
   <a:context>http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])</a:context>
   <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://annotea.example.org/CGI/annot?body=/2000/05/08-18:04:55" />
  </r:Description>
</r:RDF>

Figure A.3: A sample answer to the query in Figure A.2.

At the time of publication of this document, the authors' Amaya client can send the annotation server Algae queries by URL-encoded them, however it expects the query will be written in a manner such that the query result will contain all the information returned by the ?w3c_annotates response shown in Section 2.2. Figure A.4 illustrates a query that is equivalent to that shown in Figure A.1.

GET /Annotation?w3c_annotates=http://serv1.example.com/some/page.html
Host: annotea.example.org

Figure A.4: The client query to the server that resolves to the query in Figure A.1.

Appendix B: Updating annotations with HTTP POST

Although the first published version of the Annotea protocol proposed the use of the HTTP PUT method for updating annotations, for some obscure reason that the authors have already forgotten (probably rushing to prepare a demo), we implemented this feature using an HTTP POST with a specialized query parameter.

This Appendix is not part of the Annotea protocols. As some clients and servers have implemented the messages described below, the authors are documenting it for the benefit of all. If other developers think it is interesting to support the update with POST, the authors will add it to the Annotea protocols. At the date of publication of this document, both Amaya (release 7.1) and the W3C Annotea server support this method. Amaya does not yet support an update with PUT, but the authors intend to make it do so and to stop using the update POST. The W3C Annotea server supports both POST and PUT updates.

As is the case for PUT, in the current version of the protocol, clients MUST include in the POST all the properties that they want the server to remember, whether those properties have changed or not. This includes the body as well if the body content was stored in the Annotea server. The server may choose to discard some of the properties that are sent back.

The authors acknowledge that requiring clients to update all the properties is not the best design. It should be seen just as an intermediary way of updating an annotation. A future version of the protocol should permit posting only the properties or a subset of the properties that have changed. It should also be possible to publish the annotation separately from the body.

Figure B.1 illustrates a sample annotation update message for the annotation that was created in Figure 2.1. As with the PUT message described above, the specific choice of URI; i.e. the Annotation in this example, identifies a script on the server that will handle the update. The annotation service URI used to POST an update is the same service URI used to create new annotations and to query for existing annotations. The query parameters that follow the Annotation fragment are indented below for better readability. They should be concatenated on a single line when sending the request.

The query parameter replace_source is used to give the URI of the annotation that will be updated. The query parameter rdftype specifies the namespace for the RDF types of the resource we're updating. In this case, it specifies the annotation namespace.

The body of the request is similar to the one sent when first publishing the annotation. It should include all of the annotation metadata and the body that the client wants the server to store, whether or not that data has changed.

The server responds to this POST request by returning RDF/XML that repeats the URIs of the annotation and its body (see Figure B.2). A client should expect to receive back the properties that are described in the Annotea RDF schemas. Depending on the implementation, the server may return other RDF properties that are associated with the annotation. A client may chose to ignore those extra properties.

POST /Annotation
     ?replace_source=http://annotest.w3.org/Annotations/3ACF6D754
     &rdftype=http://www.w3.org/2000/10/annotation-ns HTTP/1.1
Host: annotea.example.org
Content-Type: application/xml
Content-Length: 1316

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/Annotation/3ACF6D754">
  <r:type r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
  <r:type r:resource="http://www.w3.org/2000/10/annotationType#Example"/>
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <d:title>Annotation of Sample Page</d:title>
  <a:context>http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])</a:context>
  <d:creator>Ralph Swick</d:creator>
  <a:created>1999-10-14T12:10Z</a:created>
  <d:date>1999-10-14T13:14Z</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://serv1.example.com/other/page.html">other page</a>.
       </p>
      </body>
     </html>
    </h:Body>
   </r:Description>
  </a:body>
 </r:Description>
</r:RDF>

Figure B.1: Updating an annotation and its body using POST.

HTTP/1.1 200 OK
Content-ype: application/xml
Content-Length: 860

<?xml version="1.0" ?>
<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:about="http://annotea.example.org/Annotation/3ACF6D754">
  <r:type r:resource="http://www.w3.org/2000/10/annotation-ns#Annotation"/>
  <r:type r:resource="http://www.w3.org/2000/10/annotationType#Comment"/>
  <a:annotates r:resource="http://serv1.example.com/some/page.html"/>
  <d:title>Annotation of Sample Page</d:title>
  <a:context>
       http://serv1.example.com/some/page.html#xpointer(id("Main")/p[2])
  </a:context>
  <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://annotea.example.org/Annotation/body/3ACF6D754"/>
 </r:Description>
</r:RDF>

Figure B.2: Reply to the request sent in Figure B.1.

Appendix C: Changes

Changes since the May 14 2001 working draft


$Revision: 1.314 $ of $Date: 2002/12/20 16:41:57 $ by $Author: swick $