--- a/ldp-primer/ldp-primer.html Thu May 01 16:22:06 2014 +0100
+++ b/ldp-primer/ldp-primer.html Thu May 01 16:29:59 2014 +0100
@@ -1,1 +1,1 @@
-<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" prefix="td: http://www.w3.org/2006/03/test-description# tn: http://ldp.example.org/NewTestDefinitions# ht: http://www.w3.org/2011/http#">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Linked Data Platform 1.0 Primer</title>
<style type="text/css">
div.syntaxmenu {
border: 1px dotted black;
padding: 0 0 0 0.5em;
margin: 0em;
}
div.code {
font-family: monospace;
font-size: 110%;
}
th {
text-align: left;
}
td {
vertical-align: top;
padding-right: 2em;
}
td.col1 {
width: 300px;
}
</style>
<script type="text/javascript">
var displayed = [];
displayed["turtle"] = 1;
displayed["jsonld"] = 0;
function primerOnLoad() {
setTimeout(function () {
display('turtle', '');
set_display_by_id('hide-ts', '');
set_display_by_id('show-ts', 'none');
display('jsonld', 'none');
set_display_by_id('hide-js', 'none');
set_display_by_id('show-js', '');
}, 500)
}
function display(syntax, status) {
var howmany = 0;
if (status == 'none') {
displayed[syntax] = 0;
} else {
displayed[syntax] = 1;
}
for (i in displayed) {
howmany = howmany + displayed[i];
}
set_display_by_class('div', syntax, status);
if (howmany == 1) {
set_display_by_class('b', 'syntax-head', 'none');
} else {
set_display_by_class('b', 'syntax-head', '');
}
}
function getElementsByClassName(oElm, strTagName, oClassNames) {
var arrElements = (!(!(strTagName == "*") || !(oElm.all))) ? oElm.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
var arrRegExpClassNames = new Array();
if (typeof oClassNames == "object") {
for (var i = 0; !(i >= oClassNames.length); i++) { /*>*/
arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)"));
}
} else {
arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)"));
}
var oElement;
var bMatchesAll;
for (var j = 0; !(j >= arrElements.length); j++) { /*>*/
oElement = arrElements[j];
bMatchesAll = true;
for (var k = 0; !(k >= arrRegExpClassNames.length); k++) { /*>*/
if (!arrRegExpClassNames[k].test(oElement.className)) {
bMatchesAll = false;
break;
}
}
if (bMatchesAll) {
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}
function set_display_by_class(el, cls, newValue) {
var e = getElementsByClassName(document, el, cls);
if (e != null) {
for (var i = 0; !(i >= e.length); i++) {
e[i].style.display = newValue;
}
}
}
function set_display_by_id(id, newValue) {
var e = document.getElementById(id);
if (e != null) {
e.style.display = newValue;
}
}
</script>
<script src='https://www.w3.org/Tools/respec/respec-w3c-common' class='remove' async></script>
<script class='remove'>
var respecConfig = {
// specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
specStatus: "ED",
// the specification's short name, as in http://www.w3.org/TR/short-name/
shortName: "ldp-primer",
// TODO: Confirm short name
// if your specification has a subtitle that goes below the main
// formal title, define it here
// subtitle : "an excellent document",
// if you wish the publication date to be other than today, set this
// publishDate: "2009-08-06",
// if the specification's copyright date is a range of years, specify
// the start date here:
// copyrightStart: "2005"
// if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
// and its maturity status
//previousPublishDate: "2013-03-07",
//previousMaturity: "FPWD",
//previousURI: "http://www.w3.org/TR/2013/WD-ldp-20130307/",
// if there a publicly available Editor's Draft, this is the link
edDraftURI: "http://www.w3.org/2012/ldp/hg/ldp-primer/ldp-primer.html",
// if this is a LCWD, uncomment and set the end of its review period
// lcEnd: "2009-08-05",
// if you want to have extra CSS, append them to this list
// it is recommended that the respec.css stylesheet be kept
//extraCSS: ["https://dvcs.w3.org/hg/ldpwg/css/respec.css"],
// editors, add as many as you like
// only "name" is required
editors: [{
name: "Nandana Mihindukulasooriya",
url: "http://mayor2.dia.fi.upm.es/oeg-upm/index.php/en/universitystaff/290-nandana",
company: "Ontology Engineering Group, Universidad Politécnica de Madrid",
companyURL: "http://www.oeg-upm.net/"
}, {
name: "Roger Menday",
url: "#",
company: "Fujitsu Laboratories of Europe Limited, London",
companyURL: "#"
}, ],
// authors, add as many as you like.
// This is optional, uncomment if you have authors as well as editors.
// only "name" is required. Same format as editors.
//authors: [
// { name: "Your Name", url: "http://example.org/",
// company: "Your Company", companyURL: "http://example.com/" },
//],
// name of the WG
wg: "Linked Data Platform Working Group",
// URI of the public WG page
wgURI: "http://www.w3.org/2012/ldp",
// name (without the @w3c.org) of the public mailing to which comments are due
wgPublicList: "public-ldp-wg",
// URI of the patent status for this WG, for Rec-track documents
// !!!! IMPORTANT !!!!
// This is important for Rec-track documents, do not copy a patent URI from a random
// document unless you know what you're doing. If in doubt ask your friendly neighbourhood
// Team Contact.
wgPatentURI: "http://www.w3.org/2004/01/pp-impl/55082/status",
doRDFa: "1.1",
localBiblio: {
"LDP-BP": {
title: "LDP Best Practices and Guidelines",
href: "https://dvcs.w3.org/hg/ldpwg/raw-file/tip/ldp-bp/ldp-bp.html",
authors: [
"Cody Burleson",
"Nandana Mihindukulasooriya"
],
status: "WD",
deliveredBy: [
"http://www.w3.org/2012/ldp/"
],
publisher: "W3C"
},
"LDP-TESTS": {
title: "Linked Data Platform 1.0 Test Cases",
href: "https://dvcs.w3.org/hg/ldpwg/raw-file/tip/Test%20Cases/LDP%20Test%20Cases.html",
authors: [
"Raúl García-Castro"
],
status: "WD",
deliveredBy: [
"http://www.w3.org/2012/ldp/"
],
publisher: "W3C"
}
}
};
// Replaces HTML characters (brackets and quotes) with legal HTML representations
// The following example would include a code example from another file and then
// call this function to make the included code renderable in a browser.
//
// <pre class='example' data-include='include-rdf-type.ttl' data-oninclude='fixCode'></pre>
function fixCode(r, content) {
var result = content;
result = result.replace(/</g, "<").replace(/>/g, ">");
result = result.replace(/'/g, "'").replace(/"/g, """);
var ss = result.split('---')
var s1 = "<div class='turtle' style='font-family: sans-serif;'>Turtle:</div><div class='turtle'><pre>" + ss[0] + "</pre></div>";
var s2 = "<div class='jsonld' style='font-family: sans-serif;'>JSON-LD:</div><div class='jsonld'><pre>" + ss[1] + "</pre></div>";
return s1 + s2;
}
function highlight(r, content) {
return '<span style="background-color:#ccffcc">' + content + '</span>';
}
</script>
</head>
<body onLoad="primerOnLoad()">
<section id='abstract'>
This primer provides an introduction to Linked Data Platform (LDP), including examples which explain the principal concepts, including the LDP resource, the contribution of the container and the associated affordances. Two sample scenarios show how an LDP client can interact with a LDP server in the context of read-write Linked Data application i.e. how to HTTP for accessing, updating, creating and deleting resources from servers that expose their resources as Linked Data.
</section>
<section id='sotd'>
<p>
This is the first draft of LDP Primer Note of W3C LDP WG.
</p>
</section>
<section id="intro-section">
<h1 id="intro">Introduction</h1>
<p>
Linked Data is a universal approach for handling data which fundamentally includes the notion of linking between data items. Much like the Web is giant network of interlinked documents for a human reader, the graph of Linked Data resources in the Web is a data layer on top of which applications are delivered, through the modification, processing, visualization and sharing of information. LDP specifies a protocol for the reading and writing of Linked Data.
</p>
<p>
The LDP specification discusses standard HTTP and RDF techniques and best practices that you should use, and anti-patterns you should avoid, when constructing clients and servers that read and write Linked Data resources. The Primer aims to provide introductory examples and guidance in the use of the LDP protocol. For a systematic account the reader should consult the normative LDP reference [[LDP]]. For an overview of the use cases for LDP and the elicited requirements that guided its design, the reader should consult the LDP Use Cases and Requirements [[LDP-UCR]] and for best practises and guidelines, the reader should consult the LDP LDP Best Practices and Guidelines document [[LDP-BP]].
</p>
<b id="conventions">Conventions Used in This Document</b>
<p>The examples in this guide are given as a serialization of RDF graphs using the Turtle [[TURTLE]] and JSON-LD [[JSON-LD]] syntaxes of RDF.</p>
<div class="syntaxmenu">
<p>The buttons below can be used to show or hide the available syntaxes.</p>
<form>
<p>
<input id="hide-ts" onclick="display('turtle', 'none'); set_display_by_id('hide-ts', 'none'); set_display_by_id('show-ts', ''); return false;" type="button" value="Hide Turtle Syntax" />
<input id="show-ts" onclick="display('turtle', ''); set_display_by_id('hide-ts', ''); set_display_by_id('show-ts', 'none'); return false;" style="display:none" type="button" value="Show Turtle Syntax" />
<input id="hide-js" onclick="display('jsonld','none'); set_display_by_id('hide-js', 'none'); set_display_by_id('show-js', ''); return false;" type="button" value="Hide JSON-LD Syntax" />
<input id="show-js" onclick="display('jsonld',''); set_display_by_id('hide-js', ''); set_display_by_id('show-js', 'none'); return false;" style="display:none" type="button" value="Show JSON-lD Syntax" />
</p>
</form>
</div>
<p>Commonly used namespace prefixes omitted from the Turtle serialisations:</p>
<pre style="word-wrap: break-word; white-space: pre-wrap;">
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix wdrs: <http://www.w3.org/2007/05/powder-s#> .
@prefix bt: <http://example.org/vocab/bugtracker#> . </pre>
<p>The JSON-LD examples refer to the following (external) context document:</p>
<pre style="word-wrap: break-word; white-space: pre-wrap;">
{
"@context":
{
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"owl": "http://www.w3.org/2002/07/owl#",
"ldp": "http://www.w3.org/ns/ldp#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"dcterms": "http://purl.org/dc/terms/",
"foaf": "http://xmlns.com/foaf/0.1/",
"wdrs": "http://www.w3.org/2007/05/powder-s#",
"bt": "http://example.org/vocab/bugtracker#"
}
}
</pre>
<p>
</p>
<h2>LDP concepts in a glance</h2>
<p>
A server hosting LDPRs may manage two kinds of LDPRs, those resources who whose state is represented using RDF called LDP RDF Sources (LDP-RS) and those using other formats called LDP Non-RDF Source (LDP-NR) such as html files, images, other binary files, etc. LDP-RS are sources of RDF triples. Resoures respond to retreival operations using HTTP GET. Often a description conveyed in the response document will describe a specific domain entity; Status, Friendship, Product, Order, Bug, etc. On the other hand, it might contain a description of a number of different concepts. The links contained in the descriptions lead to the subsequent discovery and processing of other resources. Affordances offered by the server make discoverable the forward paths in the application. Together the resources, links and associated affordances together specify what might be termed the API.
</p>
<p>
<img src="images/resources.png" />
</p>
<p>
The LDP protocols covers read and write interactions with Resources. Writable aspects include updates (using PATCH), deletion of resources and importantly creation. Resource creation is an essential feature providing structured creation of resources. Affordances published by the server show that some Resources can be used to create other Resources. This common pattern is often seen in cases where one resource is be made up of a number of others, e.g. a Document Store consists of Documents, a BugTracker consists of Bugs, a PhotoAlbum consists of Photos, a Networth of a person consists of Assets and Liabilities. This special kind of Resource is a Container (LDPC), and this is able to respond to requests to create new resources. During creation the created resource is appended to its Container and a containment link between the Container and the new entry is made.
</p>
<p>
A LDPC is a specialization of a LDP-RS representing a collection of links to LDPRs or information resources [[WEBARCH]] that responds to client requests for creation, modification, and/or enumeration of its linked members and documents. The simplest container is the Basic Container (LDP-BC). It defines the basic containment described using generic vocabularly. This can be used in a generic storage service to manage a containment hierarchy of arbitrary resources.
</p>
<figure id="fig-bc">
<img src="images/bc.png" alt=".." />
<figcaption>Generic document storage using a Basic Container.</figcaption>
</figure>
<p>
Such servers do not impose any restriction on LDPRs and generally act as storage systems without any domain specific application logic and vocabularies. An example is the document storage system based on Basic Containers.
</p>
<p>
A Direct Container allows to use some domain specific vocabulary to relate the resources of the hierarchy. The additional assertion is called the membership property.
</p>
<figure id="fig-dc1">
<img src="images/dc1.png" alt=".." />
<figcaption>Using domain vocabularly with a Direct container.</figcaption>
</figure>
<p>
Direct Containers can also use domain specific vocabulary and link from a resource other than the Container resource to the new resource.
</p>
<figure id="fig-dc_photos">
<img src="images/dc_photos.png" alt=".." />
<figcaption>Membership triples with a non-Container subject.</figcaption>
</figure>
<p>
Different facets of a Resource can be managed using multiple Containers.
</p>
<figure id="fig-dc_bugs">
<img src="images/dc_bugs.png" alt=".." />
<figcaption>Managing multiple facets of a Bug with two Direct Containers.</figcaption>
</figure>
<p>
Existing applications with their own data model and business logic can expose their data using the LDP specification. These systems impose restrictions on LDPRs since the LDP interaction should be compliant with the underlying business logic and data model. The bug tracker example presented in the latter part of the primer is an example of an application specific LDP server.
</p>
<p class="note">Formal definitions of two terms LDPR and LDPC and other concepts introduced by LDP can be found in the 'Terminology' section of the Linked Data Platform 1.0 specification [[LDP]]</p>
<!--
<p> A FOAF document file of a person that could be a good example of an LDP-RDF Source. When creating LDP-RSs, it is recommended that they reuse
existing vocabularies instead of inventing their own duplicate vocabulary terms. It is also recommended that LDP-RSs have at least one rdf:type set explicitly to
make the representations more useful to client applications that don’t support inferencing. For example, a FOAF file of a person as shown in Example 1 can be a LDP-RSs
if it conforms to lifecycle patterns and conventions in defined in LDP Specification. Following the LDP Best Practices and Guidelines [[LDP-BP]], it uses terms from Dublin Core
[[DC-TERMS]], Friend of a Friend [[FOAF]] vocabularies.
</p>
<table>
<tr>
<td class="col1"><img src="nandana_foaf.png" /></td>
<td>
<pre title="An example LDPR" class='example' data-include='ldpr_ex.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
</table>
<p> An avatar image of a person hosted in the same LDP server could be an example of an LDP-NR. These non-RDF resources also conform to the lifecycle patterns and
conventions defined in the LDP specification that are applicable to all LDPRs including non-RDF LDPRs such as they must have an Etags, and must support HEAD, OPTIONS
operations.
<p> Linked Data Platform Container (LDPC) is a specialization of an LDPR. An LDPC is a collection of same-subject, same-predicate triples which is uniquely identified by
a URI that responds to client requests for creation, modification, and enumeration of its members. For example, may be a person wants to keep information about her friends
organized as a collection of documents about those friends. This collection acts as an enumeration of links to existing documents that contain information about her friends
and also can be used to create documents about new friends when necessary. Example 2 shows an example of an LDP Container.
</p>
<table>
<tr>
<td class="col1"><img src="nandana_friends.png" /></td>
<td>
<pre title="An example LDPC" class='example' data-include='ldpc_ex.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
<tr>
<td class="col1"><img src="roger.png" /></td>
<td>
<pre title="A member resource of LDPC in Example 2" class='example' data-include='ldpc_ex_m.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
</table>
<p>
There are three different types of LDP Containers defined in the LDP specification: Basic Containers, Direct Containers, and Indirect Containers. Example 2 shows the
most simplest type that is LDP Basic Container. The other types of containers will be explained later in the primer.
</p>
<p>
Elements of the collection of which are denoted by ldp:contains predicate shows the information documents contained by the LDP Container. These elements does not have to
be LDPRs. Any HTTP resource can be contained in an LDPC. For example,
</p>
<table>
<tr>
<td class="col1"><img src="photos.png" /></td>
<td>
<pre title="An example LDPC with non-LDPRs" class='example' data-include='ldpc_ex_non_ldpr.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
</table>
<p>
Use cases [[LDP-UCR]] that motivated LDP specification varies from just publishing a dataset as Linked Data with advanced features as pagination,
providing read/write access to using Linked Data for application integration. The Linked Data Platform Use Cases and Requirements document provides
a more detailed information on the use cases that motivated the LDP specification.
</p>
<p>There are several categories of systems implementing the LDP specification. Two main categories of LDP servers include:</p>
<dl class="glossary">
<dt>Generic / vanilla LDP servers</dt>
<dd>RDF storage systems that allow interacting with their resources by means of the LDP specification. These servers do not impose any restriction on LDPRs and generally act as storage systems without any domain
specific application logic and vocabularies. The document storage system in the first example of the primer falls into this category. </dd>
<dt>Application specific LDP severs </dt>
<dd>Existing applications with their own data model and business logic exposing their data using the LDP specification. These systems impose restrictions on LDPRs since the LDP interaction should be compliant with the underlying
business logic and data model. The bug tracker example presented in the latter part of the primer is an example of an application specific LDP server.</dd>
</dl>
-->
<p>The following provide a set of examples to show the Linked Data Platform interactions. Note, this is a primer and should not be considered as a canonical example of ideal LDP modeling.</p>
</section>
<section id="photomanager">
<h1>Online document store example (LDP Basics)</h1>
<p>
This section provides a set of examples of using an online document store application. These examples will demonstrate the behaviour of LDPRs and LDP Basic Containers. Registration with the document store application by a user results in some data storage space (a root Basic Container) where web resources that are supported by Linked Data Platform can be stored. Using this root Basic Container a user can create new documents and also child containers to further organize these documents.
</p>
<p>
APIs of web applications are commonly documented by listing valid operations which can operate on URLs, where the URLs are described as templates. A description of a LDP based document store is contained in the following table. We note with emphasis that it is important for servers to use links as the main mechanism to reveal the location of resources. If it would be necessary to encode such templates into client applications, this would be a strong indicator that the design breaches a number of good design principles. </p>
</p>
<table class="simple">
<thead>
<th>Path</th>
<th>Method</th>
<th>Description</th>
</thead>
<tbody>
<tr>
<td rowspan="5">/{username}/</td>
<td>GET</td>
<td>Lists all the documents in the root container.</td>
</tr>
<tr>
<td>POST</td>
<td>Create a new document under the root container.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the description and/or list of files of the root container.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Update the description and/or list of files of the root container.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Not allowed.</td>
</tr>
<tr>
<td class="col1" rowspan="5">
<div class='code'>/{username}/{{document}/}*</div>
</td>
<td>GET</td>
<td>Retrive the document.</td>
</tr>
<tr>
<td>POST</td>
<td>Discovered from the resource affordances.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the document.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Partial update to the document if PATCH is supported.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Delete the project description and associated bug reports.</td>
</tr>
<tr>
<td rowspan="2">
<div class='code'>/*/*</div>
</td>
<td>OPTIONS</td>
<td>Discover the allowed operations over a resource</td>
</tr>
<tr>
<td>HEAD</td>
<td>Only retrieve metainformation about a resource</td>
</tr>
</tbody>
</table>
<p>
In this example, we will see how Alice, a user of this system, manages read / write management of documents using the LDP protocol. A typical interaction with the system would start with Alice registering as a user. It is likely that registration would be a LDP based interaction, but this that aspect is out of scope of this example. A consequence of the registration is allocation of space for the storage of documents, and communication of this URL to the user, e.g. a basic container at http://data.example.org/alice/. This section describes a typical flow of interactions where Alice firsts reads the root document and discovers its affordances. This is followed by subsequent examples of creation, update and delete, and finishes with how the client is able to create nested structure from the containers.
</p>
<section id="filelookup">
<h2>Looking up a basic container (GET on an LDP-BC) </h2>
<p>First Alice looks up her storage by retrieving the LDP Basic Container assigned to her to hold her documents. As it was just created, it is an empty container.</p>
<pre title="Request - basic container retreival" class='example' data-include='getbc.txt' data-oninclude='fixCode'></pre>
<pre title="Response - basic container retreival" class='example' data-include='getbc_res.txt' data-oninclude='fixCode'></pre>
</section>
<section>
<h2> Discovering the affordances (OPTIONS on an LDP-BC) </h2>
<p>
Now, Alice wants to know what she can do in her document space. She can use the OPTIONS operation to learn of the permitted LDP-BC operations.
</p>
<pre title="Request - retreiving OPTIONS of a basic container" class='example' data-include='optbc.txt' data-oninclude='fixCode'></pre>
<pre title="Response - retreiving OPTIONS of a basic container" class='example' data-include='optbc_res.txt' data-oninclude='fixCode'></pre>
<p>According to the response, HTTP operations {OPTIONS,HEAD, GET,POST,PUT,PATCH} are allowed on her root container. In addition to the allowed operations, Accept-Post and Accept-Patch provides which media types are supported by the respective operations. The rel="type" Link header advertises that this resource supports LDP protocol and it is an LDP Basic Container.</p>
<p>In this case, the response tells Alice's LDP client that this is an LDP-Basic Container and the container allows her to POST things of both RDF types (text/turtle, application/ld+json) and images (image/bmp and image/jpeg).</p>
</section>
<section>
<h2> Creating a RDF resource (POST an RDF resource to an LDP-BC) </h2>
<p>
Alice can uplaod a social profile document to her store, by POSTing her FOAF personal profile document to her LDP-BC at the root of her document store. Note, the Slug header offers the server a hint about URL of the created resource and the characters which found in the URL.
</p>
<pre title="Request - creating a RDF resource" class='example' data-include='bccreate.txt' data-oninclude='fixCode'></pre>
</pre>
<pre title="Response - creating a RDF resource" class="example" data-include='bccreate_res.txt' data-oninclude='fixCode'>
</pre>
<p>Once the resource is created, Alice can check the container again to confirm that it correctly contains the newly created resource.</p>
<pre title="Request - basic container retreival after resource created" class="example">
GET /alice/ HTTP/1.1
Host: example.org
Accept: text/turtle
</pre>
<pre title="Response - basic container retreival after resource created" class='example' data-include='bcget_res.txt' data-oninclude='fixCode'/>
<p>
The ldp:contains containment triple discloses the newly created resource in the response.
</p>
</section>
<section>
<h2> Creating a non-RDF (binary) resource (POST an image to an LDP-BC) </h2>
<p>Next, Alice wants to upload a photo of her to the document storage. She can create an image by POSTing it in the same way she created the RDF document.</p>
<pre title="Request - creating a non-RDF resource" class="example">
POST /alice/ HTTP/1.1
Host: data.example.org
Slug: avatar
Content-Type: image/png
Content- Length: nnn
### binary data ###
</pre>
<pre title="Response - creating a non-RDF resource" class="example">
HTTP/1.1 201 Created
Location: /alice/avatar
Link: <http://www.w3.org/ns/ldp/Resource>; rel="type"
Link: <http://data.example.org/alice/avatar/meta>; rel="describedby"
Content-Length: 0
</pre>
<p>The outcome of creating a non-RDF is similar to creating a RDF resource. If successful, the server will return a 201 success code with a Location header that points to the created resource. Furthermore, in the case of binary resources the server may create an additional file to maintain the metadata about the binary file like shown in the above example.</p>
</section>
<section>
<h2> Update a RDF LDP resource (PUT on an LDP-RS) </h2>
<!--
I MISSED THESE BITS OUT ... (??)
<pre title="A request for retrieving a RDF resource" class="example" data-include='getfoaf.txt' data-oninclude='fixCode'/>
<pre title="The response of retrieving a RDF resource" class='example' data-include='getfoaf_res.txt' data-oninclude='fixCode'/>
-->
<p>After creating the image, Alice now wants to update her FOAF profile with a link to the image. After retrieving her FOAF profile she uses HTTP PUT to update the document by amending the RDF with a link to her photo.</p>
<pre title="Request - updating a RDF resource" class="example" data-include='foafupdate.txt' data-oninclude='fixCode'></pre>
<pre title="Response - updating a RDF resource" class="example">
HTTP/1.1 204 No Content
Link: <http://www.w3.org/ns/ldp/Resource>; rel="type"
ETag: W/"123454322"
</pre>
<p>If the operation is successful, the document will be updated with new information.</p>
</section>
<section>
<h2> Deleting a resource (DELETE on an LDPR) </h2>
<p>If Alice decides to delete the document, she can do that with a delete operation.</p>
<pre title="A request for deleting a RDF resource" class="example">
DELETE /alice/foaf HTTP/1.1
Host: data.example.org
If-Match: W/"123454322"
</pre>
<pre title="The response for deleting a RDF resource" class="example">
HTTP/1.1 204 No Content
Link: <http://www.w3.org/ns/ldp/Resource>; rel="type"
ETag: W/"123454322"
</pre>
</section>
<section>
<h3 id="meta-structure">Structural Manipulation (Child Containers)</h3>
<p>To organize the documents in a better manner, the online document store allows creation of documents which are containers. That enables Alice can to create a container hierarchy to organise her documents. This can be done by POSTing (a child) container representation to a (parent) container.
</p>
<p>So if Alice wants to create a child container so that she can keep all her images organized in a separate container.</p>
<pre title="The state of Alice's document store before creating the photo (child) container" class='example' data-include='create_cr_s1.txt' data-oninclude='fixCode'></pre>
<p>So Alice POSTs a representation of a container (LDP-BC) for creating photos to the root container.</p>
<pre title="A request for creating a new container" class='example' data-include='create_cr_req.txt' data-oninclude='fixCode'></pre>
<p>If the create is successful, the server responds with location of the newly created container for the photos.</p>
<pre title="The response after creating the new container" class="example">
HTTP/1.1 201 Created
Location: /alice/photos/
Content-Length: 0
</pre>
<p>After creation of this new container, the parent container will look like</p>
<pre title="The state of Alice's document store after creating the photo (child) container" class='example' data-include='create_cr_s2.txt' data-oninclude='fixCode'></pre>
<p>and the photo container will look like the following.</p>
<pre title="The state of Alice's newly created photo container" class='example' data-include='create_cr_s3.txt' data-oninclude='fixCode'></pre>
</section>
</section>
<section id="bugtracker">
<h1>Bug Tracker Example (LDP Direct containers)</h1>
<p>The previous section provided practical examples of basic LDP interactions. One thing to note the example was using LDP Basic Containers. One of the limitations of LDP Basic Containers is that it only uses LDP vocabulary. However, there are scenarios where the applications want to use their own domain specific vocabulary for listing members of a container. For example, an application which already had its own vocabulary would like continue using the same vocabulary when using LDP protocol. LDP Direct containers allow the domain-specific vocabulary to be used when listing members in a container.</p>
<p>In addition to using the domain-specific vocabularies, in some applications would like to represent relationships other than the containment relationship of information resources within the containers. One example is that information resources contains relationship about non-information resources or real world things. LDP Indirect Containers allows the containers use these relations when new resources are created.
</p>
<p class="note">For more information on information resources (documents) vs real world entities (things) separation please refer to <a href="http://www.w3.org/TR/webarch/#id-resources">Web Arch (Section 2.2. URI/Resource Relationships) </a>, , <a href="http://www.w3.org/TR/cooluris/#semweb">Cool URIs (Section 3. URIs for Real-World Objects)</a>, <a href="http://www.w3.org/TR/urls-in-data/#landing-pages">URLs in Data (Section 3. Landing Pages and Records)</a>.</p>
<p>
The examples in this section will revolve around a very simple Bug Tracker application. Bug Tracker application records the bugs of several products allowing reporting, updating and deleting bugs and products. In contrast to the online document store example, the bug tracker wants to use a simple domain vocabulary , e.g. has_bug or related, to express membership relationships in the containers. LDP provides the additional interaction capability in the protocol to perform dynamic evolution of knowledge representation.
</p>
<p>RESTful APIs are often documented by through listing valid operations operating on URLs described as templates. A RESTful API for a simple Bug Tracker system might be described as follows:</p>
<table class="simple">
<thead>
<th>Path</th>
<th>Method</th>
<th>Description</th>
</thead>
<tbody>
<!--tr>
<td rowspan="5">/app/</td>
<td>GET</td>
<td>Lists all the product descriptions.</td>
</tr>
<tr>
<td>POST</td>
<td>Create a new product description.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the app description and/or list of product descriptions</td>
</tr>
<tr>
<td>PATCH</td>
<td>Update the app description and/or list of product descriptions</td>
</tr>
<tr>
<td>DELETE</td>
<td>Not allowed.</td>
</tr-->
<tr>
<td class="col1" rowspan="5">
<div class='code'>/app/{product-id}/</div>
</td>
<td>GET</td>
<td>Lists the bug reports associated with a product.</td>
</tr>
<tr>
<td>POST</td>
<td>Create a new bug report associated with a product.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the project description.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Not supported.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Delete the project description and associated bug reports.</td>
</tr>
<tr>
<td rowspan="5">
<div class='code'>/app/{product-id}/{bug-id}</div>
</td>
<td>GET</td>
<td>Gets the bug report.</td>
</tr>
<tr>
<td>POST</td>
<td>Not supported.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the bug report.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Not supported.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Delete the bug report.</td>
</tr>
<tr>
<td rowspan="2">
<div class='code'>/*/*</div>
</td>
<td>OPTIONS</td>
<td>Discover the allowed operations over a resource</td>
</tr>
<tr>
<td>HEAD</td>
<td>Only retrieve metainformation about a resource</td>
</tr>
</tbody>
</table>
<section id="navandret">
<h2>Navigation and Retreival</h2>
<p>One of the main use cases of the example bug tracker is to list of the bugs of a given product. Assuming that a user got a URL of a product by out of band means, one can look it up to get more information including the bugs associated with it.</p>
<p>To get the description of the product, a client can do a GET request on the URI of the known product resource. LDPR servers should provide text/turtle representations of the requested LDPRs and may provide RDF format representations using standard HTTP content negotiation.</p>
<pre class="example" title="Product lookup request" data-include='product_lookup_req.txt' data-oninclude='fixCode'></pre>
<p>If the product resource is available, the server responds with the representation of the resource using the requested media type,
<code>text/turtle</code> in this case.</p>
<pre title="HTTP response for product lookup" class='example' data-include='product_lookup_resp.txt' data-oninclude='fixCode'></pre>
<p>The project description resource contains both information about the project such as the title and the information about members of the product LDPC, i.e. the bugs associated with the product. This example uses an LDP Direct Container allowing the application to use domain specific vocabulary in the container. For example, it manages the (<?productURI>, bt:hasbug, <?bugURI>) relationship using the application-specific vocabulary. The next example illustrates the behaviour of LDP Direct containers when new resources are created.</p>
<!-- <p>Looking up a bug is similar to looking up a product. Based on links in the representation of the Product, the client uses GET to navigate to a known Bug resource.</p>
<pre class="example" title="Bug lookup request"
data-include='bug_look_up_req.txt' data-oninclude='fixCode'></pre>
<p>The server responds with the representation of the bug.</p>
<pre title="Bug lookup response"
class='example' data-include='bug_look_up_resp.txt'
data-oninclude='fixCode'></pre -->
</section>
<section>
<h3 id="BugCreate">Creation</h3>
<p>Continuing from the previous example, we can report a Bug against 'product1' by creating a Bug LDPR under the 'Product' LDPC. The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<p>The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<pre title="A request for creating a bug" class='example' data-include='bug_create_req.txt' data-oninclude='fixCode'></pre>
<p>If the create is successful, the server responds with location of the newly created resource.</p>
<pre title="A response of creating new a bug" class='example' data-oninclude='fixCode'>
HTTP/1.1 201 Created
Location: /app/product1/67
Content-Length: 0
</pre>
<p>If the creation fails, the server will respond with an appropriate status code depending on the error. After the resource is creation, the Product A LDPC will have the following representation.</p>
<pre title="The state of the product LDPC after the bug creation" class='example' data-include='bug_create_s1.txt' data-oninclude='fixCode'></pre>
<p> As you can see two new triples are added to the container. That is (</app/product1>, <ldp:contains>, </app/product1/bug67>) and
(</app/product1/#it>, <bt:hasbug>, </app/product1/bug67>). The former is added in any type of container and the latter is defined by the direct
container properties. The subject of the second triple is defined by the property ldp:membershipResource and the predicate is defined by the ldp:hasMemberRelation.
The object of the triple is the newly created resource. </p>
<p>And the created Bug resource will have the following representation. Note that server has added a server managed property, creation date (dcterms:created), and a default value for the state (bt:isInState) to the Bug in addition to what was being POSTed.</p>
<pre title="The state of the bug LDPR" class='example' data-include='bug_create_s2.txt' data-oninclude='fixCode'></pre>
</section>
<section>
<h3 id="BugDelete">Deletion</h3>
<pre class="example">
DELETE /app/product1/bug3 HTTP/1.1
Host: example.org
</pre>
<p>If the update is successful, the server will respond with a success status and a new etag.</p>
<pre class="example">
HTTP/1.1 204 No Content
ETag: W/"123456790"
</pre>
<p> After the deletion, the representation of the container will look like the following (Show that the two triples are gone) </p>
</section>
</section>
<section id="bugtrackerextd">
<h1>Extended Bug Tracker Example (LDP Indirect containers)</h1>
<p> In this example, we will use the same scenario as the previous example but using an LDP Indirect Container to show what is the use of Indirect containers and
how to use them. </p>
<section id="navandretext">
<h2>Navigation and Retreival</h2>
<pre class="example" title="Product lookup request" data-include='product_lookup_req.txt' data-oninclude='fixCode'></pre>
<p>If the product resource is available, the server responds with the representation of the resource using the requested media type,
<code>text/turtle</code> in this case.</p>
<pre title="HTTP response for product lookup" class='example' data-include='ic_product_lookup_resp.txt' data-oninclude='fixCode'></pre>
<p> Now the product container is an LDP Indirect container and we can notice several differences. </p>
</section>
<!-- end navandretext -->
<section id="creationext">
<h3 id="IndirectCreate">Creation</h3>
<p>Continuing from the previous example, we can report a Bug against 'product1' by creating a Bug LDPR under the 'Product' LDPC. The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<p>The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<pre title="A request for creating a bug" class='example' data-include='ic_bug_create_req.txt' data-oninclude='fixCode'></pre>
<p>If the create is successful, the server responds with location of the newly created resource.</p>
<pre title="A response of creating new a bug" class='example' data-oninclude='fixCode'>
HTTP/1.1 201 Created
Location: /app/product1/67
Content-Length: 0
</pre>
<p>If the creation fails, the server will respond with an appropriate status code depending on the error. After the resource is creation, the Product A LDPC will have the following representation.</p>
<pre title="The state of the product LDPC after the bug creation" class='example' data-include='ic_bug_create_s1.txt' data-oninclude='fixCode'></pre>
<p> As you can see two new triples are added to the container. That is (</app/product1>, <ldp:contains>, </app/product1/bug67>) and
(</app/product1/#it>, <bt:hasbug>, </app/product1/bug67#it>). </p>
<p>And the created Bug resource will have the following representation. Note that server has added a server managed property, creation date (dcterms:created), and a default value for the state (bt:isInState) to the Bug in addition to what was being POSTed.</p>
<pre title="The state of the bug LDPR" class='example' data-include='ic_bug_create_s2.txt' data-oninclude='fixCode'></pre>
</section>
<!-- end creationext -->
<section id="deleteext">
<h3 id="IndirectDelete">Deletion</h3>
<pre class="example">
DELETE /app/product1/bug3 HTTP/1.1
Host: example.org
</pre>
<p>If the update is successful, the server will respond with a success status and a new etag.</p>
<pre class="example">
HTTP/1.1 204 No Content
ETag: W/"123456790"
</pre>
<p> After the deletion, the representation of the container will look like the following (Show that the two triples are gone) </p>
</section>
<!-- end deleteext -->
</section>
<section>
<h1>Security</h1>
<p>It is not the focus of the Linked Data Platform WG to provide security mechanisms for read/write Linked Data applications. Though most of the security mechanisms that are applicable to general web applications are equally applicable to Linked Data applications, there is still some space to build security mechanisms specific to Linked Data applications by leverage the Linked Data technologies and providing concrete security requirements of Linked Data applications. In this context, LDP WG has started to create a WG note on Access Control which aims to produce use cases for security scenarios of LDP applications that can be used as the input to later initiative that will be focused on developing standard security mechanisms for LDP applications.</p>
</section>
<section>
<h1 id="ldpc">LDP Implementations</h1>
A list of implementations that plan to be LDP compliant is available in the LDP Implementations wiki page. LDP Implementation report provides the coverage of the specification by each LDP implementation.
</section>
<section>
<h1 id="next">What To Read Next</h1>
The primer only provide an overview of the Linked Data Platform specifications. LDP WG has produced following documents that contribute to the Linked Data Platform specification.
<ul>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/TR/ldp-ucr.html">Linked Data Platform Use Cases and Requirements</a> [[LDP-UCR]]</li>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp.html">Linked Data Platform 1.0 specifcation</a> [[LDP]]</li>
<li>Linked Data Platform 1.0 Primer (This document)</li>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp-bp/ldp-bp.html">LDP Best Practices and Guidelines</a> [[LDP-BP]]</li>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/Test%20Cases/LDP%20Test%20Cases.html">Linked Data Platform 1.0 Test Cases</a>[[LDP-TESTS]]</li>
</ul>
</section>
<section class='appendix informative' id="history">
<h1>Change History</h1>
<p>The change history is up to the editors to insert a brief summary of changes, ordered by most recent changes first and with heading from which public draft it has been changed from.
</p>
<ul>
<li>2013-08-05 - Providing JSON-LD representations of the examples.</li>
<li>2013-07-03 - Moving the content from the wiki to the note.</li>
</ul>
</section>
</body>
</html>
\ No newline at end of file
+<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" prefix="td: http://www.w3.org/2006/03/test-description# tn: http://ldp.example.org/NewTestDefinitions# ht: http://www.w3.org/2011/http#">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Linked Data Platform 1.0 Primer</title>
<style type="text/css">
div.syntaxmenu {
border: 1px dotted black;
padding: 0 0 0 0.5em;
margin: 0em;
}
div.code {
font-family: monospace;
font-size: 110%;
}
th {
text-align: left;
}
td {
vertical-align: top;
padding-right: 2em;
}
td.col1 {
width: 300px;
}
</style>
<script type="text/javascript">
var displayed = [];
displayed["turtle"] = 1;
displayed["jsonld"] = 0;
function primerOnLoad() {
setTimeout(function () {
display('turtle', '');
set_display_by_id('hide-ts', '');
set_display_by_id('show-ts', 'none');
display('jsonld', 'none');
set_display_by_id('hide-js', 'none');
set_display_by_id('show-js', '');
}, 500)
}
function display(syntax, status) {
var howmany = 0;
if (status == 'none') {
displayed[syntax] = 0;
} else {
displayed[syntax] = 1;
}
for (i in displayed) {
howmany = howmany + displayed[i];
}
set_display_by_class('div', syntax, status);
if (howmany == 1) {
set_display_by_class('b', 'syntax-head', 'none');
} else {
set_display_by_class('b', 'syntax-head', '');
}
}
function getElementsByClassName(oElm, strTagName, oClassNames) {
var arrElements = (!(!(strTagName == "*") || !(oElm.all))) ? oElm.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
var arrRegExpClassNames = new Array();
if (typeof oClassNames == "object") {
for (var i = 0; !(i >= oClassNames.length); i++) { /*>*/
arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames[i].replace(/\-/g, "\\-") + "(\\s|$)"));
}
} else {
arrRegExpClassNames.push(new RegExp("(^|\\s)" + oClassNames.replace(/\-/g, "\\-") + "(\\s|$)"));
}
var oElement;
var bMatchesAll;
for (var j = 0; !(j >= arrElements.length); j++) { /*>*/
oElement = arrElements[j];
bMatchesAll = true;
for (var k = 0; !(k >= arrRegExpClassNames.length); k++) { /*>*/
if (!arrRegExpClassNames[k].test(oElement.className)) {
bMatchesAll = false;
break;
}
}
if (bMatchesAll) {
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}
function set_display_by_class(el, cls, newValue) {
var e = getElementsByClassName(document, el, cls);
if (e != null) {
for (var i = 0; !(i >= e.length); i++) {
e[i].style.display = newValue;
}
}
}
function set_display_by_id(id, newValue) {
var e = document.getElementById(id);
if (e != null) {
e.style.display = newValue;
}
}
</script>
<script src='https://www.w3.org/Tools/respec/respec-w3c-common' class='remove' async></script>
<script class='remove'>
var respecConfig = {
// specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
specStatus: "ED",
// the specification's short name, as in http://www.w3.org/TR/short-name/
shortName: "ldp-primer",
// TODO: Confirm short name
// if your specification has a subtitle that goes below the main
// formal title, define it here
// subtitle : "an excellent document",
// if you wish the publication date to be other than today, set this
// publishDate: "2009-08-06",
// if the specification's copyright date is a range of years, specify
// the start date here:
// copyrightStart: "2005"
// if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
// and its maturity status
//previousPublishDate: "2013-03-07",
//previousMaturity: "FPWD",
//previousURI: "http://www.w3.org/TR/2013/WD-ldp-20130307/",
// if there a publicly available Editor's Draft, this is the link
edDraftURI: "http://www.w3.org/2012/ldp/hg/ldp-primer/ldp-primer.html",
// if this is a LCWD, uncomment and set the end of its review period
// lcEnd: "2009-08-05",
// if you want to have extra CSS, append them to this list
// it is recommended that the respec.css stylesheet be kept
//extraCSS: ["https://dvcs.w3.org/hg/ldpwg/css/respec.css"],
// editors, add as many as you like
// only "name" is required
editors: [{
name: "Nandana Mihindukulasooriya",
url: "http://mayor2.dia.fi.upm.es/oeg-upm/index.php/en/universitystaff/290-nandana",
company: "Ontology Engineering Group, Universidad Politécnica de Madrid",
companyURL: "http://www.oeg-upm.net/"
}, {
name: "Roger Menday",
url: "#",
company: "Fujitsu Laboratories of Europe Limited, London",
companyURL: "#"
}, ],
// authors, add as many as you like.
// This is optional, uncomment if you have authors as well as editors.
// only "name" is required. Same format as editors.
//authors: [
// { name: "Your Name", url: "http://example.org/",
// company: "Your Company", companyURL: "http://example.com/" },
//],
// name of the WG
wg: "Linked Data Platform Working Group",
// URI of the public WG page
wgURI: "http://www.w3.org/2012/ldp",
// name (without the @w3c.org) of the public mailing to which comments are due
wgPublicList: "public-ldp-wg",
// URI of the patent status for this WG, for Rec-track documents
// !!!! IMPORTANT !!!!
// This is important for Rec-track documents, do not copy a patent URI from a random
// document unless you know what you're doing. If in doubt ask your friendly neighbourhood
// Team Contact.
wgPatentURI: "http://www.w3.org/2004/01/pp-impl/55082/status",
doRDFa: "1.1",
localBiblio: {
"LDP-BP": {
title: "LDP Best Practices and Guidelines",
href: "https://dvcs.w3.org/hg/ldpwg/raw-file/tip/ldp-bp/ldp-bp.html",
authors: [
"Cody Burleson",
"Nandana Mihindukulasooriya"
],
status: "WD",
deliveredBy: [
"http://www.w3.org/2012/ldp/"
],
publisher: "W3C"
},
"LDP-TESTS": {
title: "Linked Data Platform 1.0 Test Cases",
href: "https://dvcs.w3.org/hg/ldpwg/raw-file/tip/Test%20Cases/LDP%20Test%20Cases.html",
authors: [
"Raúl García-Castro"
],
status: "WD",
deliveredBy: [
"http://www.w3.org/2012/ldp/"
],
publisher: "W3C"
}
}
};
// Replaces HTML characters (brackets and quotes) with legal HTML representations
// The following example would include a code example from another file and then
// call this function to make the included code renderable in a browser.
//
// <pre class='example' data-include='include-rdf-type.ttl' data-oninclude='fixCode'></pre>
function fixCode(r, content) {
var result = content;
result = result.replace(/</g, "<").replace(/>/g, ">");
result = result.replace(/'/g, "'").replace(/"/g, """);
var ss = result.split('---')
var s1 = "<div class='turtle' style='font-family: sans-serif;'>Turtle:</div><div class='turtle'><pre>" + ss[0] + "</pre></div>";
var s2 = "<div class='jsonld' style='font-family: sans-serif;'>JSON-LD:</div><div class='jsonld'><pre>" + ss[1] + "</pre></div>";
return s1 + s2;
}
function highlight(r, content) {
return '<span style="background-color:#ccffcc">' + content + '</span>';
}
</script>
</head>
<body onLoad="primerOnLoad()">
<section id='abstract'>
This primer provides an introduction to Linked Data Platform (LDP), including examples which explain the principal concepts, including the LDP resource, the contribution of the container and the associated affordances. Two sample scenarios show how an LDP client can interact with a LDP server in the context of read-write Linked Data application i.e. how to HTTP for accessing, updating, creating and deleting resources from servers that expose their resources as Linked Data.
</section>
<section id='sotd'>
<p>
This is the first draft of LDP Primer Note of W3C LDP WG.
</p>
</section>
<section id="intro-section">
<h1 id="intro">Introduction</h1>
<p>
Linked Data is a universal approach for handling data which fundamentally includes the notion of linking between data items. Much like the Web is giant network of interlinked documents for a human reader, the graph of Linked Data resources in the Web is a data layer on top of which applications are delivered, through the modification, processing, visualization and sharing of information. LDP specifies a protocol for the reading and writing of Linked Data.
</p>
<p>
The LDP specification discusses standard HTTP and RDF techniques and best practices that you should use, and anti-patterns you should avoid, when constructing clients and servers that read and write Linked Data resources. The Primer aims to provide introductory examples and guidance in the use of the LDP protocol. For a systematic account the reader should consult the normative LDP reference [[LDP]]. For an overview of the use cases for LDP and the elicited requirements that guided its design, the reader should consult the LDP Use Cases and Requirements [[LDP-UCR]] and for best practises and guidelines, the reader should consult the LDP LDP Best Practices and Guidelines document [[LDP-BP]].
</p>
<b id="conventions">Conventions Used in This Document</b>
<p>The examples in this guide are given as a serialization of RDF graphs using the Turtle [[TURTLE]] and JSON-LD [[JSON-LD]] syntaxes of RDF.</p>
<div class="syntaxmenu">
<p>The buttons below can be used to show or hide the available syntaxes.</p>
<form>
<p>
<input id="hide-ts" onclick="display('turtle', 'none'); set_display_by_id('hide-ts', 'none'); set_display_by_id('show-ts', ''); return false;" type="button" value="Hide Turtle Syntax" />
<input id="show-ts" onclick="display('turtle', ''); set_display_by_id('hide-ts', ''); set_display_by_id('show-ts', 'none'); return false;" style="display:none" type="button" value="Show Turtle Syntax" />
<input id="hide-js" onclick="display('jsonld','none'); set_display_by_id('hide-js', 'none'); set_display_by_id('show-js', ''); return false;" type="button" value="Hide JSON-LD Syntax" />
<input id="show-js" onclick="display('jsonld',''); set_display_by_id('hide-js', ''); set_display_by_id('show-js', 'none'); return false;" style="display:none" type="button" value="Show JSON-lD Syntax" />
</p>
</form>
</div>
<p>Commonly used namespace prefixes omitted from the Turtle serialisations:</p>
<pre style="word-wrap: break-word; white-space: pre-wrap;">
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix wdrs: <http://www.w3.org/2007/05/powder-s#> .
@prefix bt: <http://example.org/vocab/bugtracker#> . </pre>
<p>The JSON-LD examples refer to the following (external) context document:</p>
<pre style="word-wrap: break-word; white-space: pre-wrap;">
{
"@context":
{
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
"owl": "http://www.w3.org/2002/07/owl#",
"ldp": "http://www.w3.org/ns/ldp#",
"xsd": "http://www.w3.org/2001/XMLSchema#",
"dcterms": "http://purl.org/dc/terms/",
"foaf": "http://xmlns.com/foaf/0.1/",
"wdrs": "http://www.w3.org/2007/05/powder-s#",
"bt": "http://example.org/vocab/bugtracker#"
}
}
</pre>
<p>
</p>
<h2>LDP concepts in a glance</h2>
<p>
A server hosting LDPRs may manage two kinds of LDPRs, those resources who whose state is represented using RDF called LDP RDF Sources (LDP-RS) and those using other formats called LDP Non-RDF Source (LDP-NR) such as html files, images, other binary files, etc. LDP-RS are sources of RDF triples. Resoures respond to retreival operations using HTTP GET. Often a description conveyed in the response document will describe a specific domain entity; Status, Friendship, Product, Order, Bug, etc. On the other hand, it might contain a description of a number of different concepts. The links contained in the descriptions lead to the subsequent discovery and processing of other resources. Affordances offered by the server make discoverable the forward paths in the application. Together the resources, links and associated affordances together specify what might be termed the API.
</p>
<p>
<img src="images/resources.png" />
</p>
<p>
The LDP protocols covers read and write interactions with Resources. Writable aspects include updates (using PATCH), deletion of resources and importantly creation. Resource creation is an essential feature providing structured creation of resources. Affordances published by the server show that some Resources can be used to create other Resources. This common pattern is often seen in cases where one resource is be made up of a number of others, e.g. a Document Store consists of Documents, a BugTracker consists of Bugs, a PhotoAlbum consists of Photos, a Networth of a person consists of Assets and Liabilities. This special kind of Resource is a Container (LDPC), and this is able to respond to requests to create new resources. During creation the created resource is appended to its Container and a containment link between the Container and the new entry is made.
</p>
<p>
A LDPC is a specialization of a LDP-RS representing a collection of links to LDPRs or information resources [[WEBARCH]] that responds to client requests for creation, modification, and/or enumeration of its linked members and documents. The simplest container is the Basic Container (LDP-BC). It defines the basic containment described using generic vocabularly. This can be used in a generic storage service to manage a containment hierarchy of arbitrary resources.
</p>
<figure id="fig-bc">
<img src="images/bc.png" alt=".." />
<figcaption>Generic document storage using a Basic Container.</figcaption>
</figure>
<p>
Such servers do not impose any restriction on LDPRs and generally act as storage systems without any domain specific application logic and vocabularies. An example is the document storage system based on Basic Containers.
</p>
<p>
A Direct Container allows to use some domain specific vocabulary to relate the resources of the hierarchy. The additional assertion is called the membership property.
</p>
<figure id="fig-dc1">
<img src="images/dc1.png" alt=".." />
<figcaption>Using domain vocabularly with a Direct container.</figcaption>
</figure>
<p>
Direct Containers can also use domain specific vocabulary and link from a resource other than the Container resource to the new resource.
</p>
<figure id="fig-dc_photos">
<img src="images/dc_photos.png" alt=".." />
<figcaption>Membership triples with a non-Container subject.</figcaption>
</figure>
<p>
Different facets of a Resource can be managed using multiple Containers.
</p>
<figure id="fig-dc_bugs">
<img src="images/dc_bugs.png" alt=".." />
<figcaption>Managing multiple facets of a Bug with two Direct Containers.</figcaption>
</figure>
<p>
Existing applications with their own data model and business logic can expose their data using the LDP specification. These systems impose restrictions on LDPRs since the LDP interaction should be compliant with the underlying business logic and data model. The bug tracker example presented in the latter part of the primer is an example of an application specific LDP server.
</p>
<p class="note">Formal definitions of two terms LDPR and LDPC and other concepts introduced by LDP can be found in the 'Terminology' section of the Linked Data Platform 1.0 specification [[LDP]]</p>
<!--
<p> A FOAF document file of a person that could be a good example of an LDP-RDF Source. When creating LDP-RSs, it is recommended that they reuse
existing vocabularies instead of inventing their own duplicate vocabulary terms. It is also recommended that LDP-RSs have at least one rdf:type set explicitly to
make the representations more useful to client applications that don’t support inferencing. For example, a FOAF file of a person as shown in Example 1 can be a LDP-RSs
if it conforms to lifecycle patterns and conventions in defined in LDP Specification. Following the LDP Best Practices and Guidelines [[LDP-BP]], it uses terms from Dublin Core
[[DC-TERMS]], Friend of a Friend [[FOAF]] vocabularies.
</p>
<table>
<tr>
<td class="col1"><img src="nandana_foaf.png" /></td>
<td>
<pre title="An example LDPR" class='example' data-include='ldpr_ex.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
</table>
<p> An avatar image of a person hosted in the same LDP server could be an example of an LDP-NR. These non-RDF resources also conform to the lifecycle patterns and
conventions defined in the LDP specification that are applicable to all LDPRs including non-RDF LDPRs such as they must have an Etags, and must support HEAD, OPTIONS
operations.
<p> Linked Data Platform Container (LDPC) is a specialization of an LDPR. An LDPC is a collection of same-subject, same-predicate triples which is uniquely identified by
a URI that responds to client requests for creation, modification, and enumeration of its members. For example, may be a person wants to keep information about her friends
organized as a collection of documents about those friends. This collection acts as an enumeration of links to existing documents that contain information about her friends
and also can be used to create documents about new friends when necessary. Example 2 shows an example of an LDP Container.
</p>
<table>
<tr>
<td class="col1"><img src="nandana_friends.png" /></td>
<td>
<pre title="An example LDPC" class='example' data-include='ldpc_ex.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
<tr>
<td class="col1"><img src="roger.png" /></td>
<td>
<pre title="A member resource of LDPC in Example 2" class='example' data-include='ldpc_ex_m.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
</table>
<p>
There are three different types of LDP Containers defined in the LDP specification: Basic Containers, Direct Containers, and Indirect Containers. Example 2 shows the
most simplest type that is LDP Basic Container. The other types of containers will be explained later in the primer.
</p>
<p>
Elements of the collection of which are denoted by ldp:contains predicate shows the information documents contained by the LDP Container. These elements does not have to
be LDPRs. Any HTTP resource can be contained in an LDPC. For example,
</p>
<table>
<tr>
<td class="col1"><img src="photos.png" /></td>
<td>
<pre title="An example LDPC with non-LDPRs" class='example' data-include='ldpc_ex_non_ldpr.txt' data-oninclude='fixCode'></pre>
</td>
</tr>
</table>
<p>
Use cases [[LDP-UCR]] that motivated LDP specification varies from just publishing a dataset as Linked Data with advanced features as pagination,
providing read/write access to using Linked Data for application integration. The Linked Data Platform Use Cases and Requirements document provides
a more detailed information on the use cases that motivated the LDP specification.
</p>
<p>There are several categories of systems implementing the LDP specification. Two main categories of LDP servers include:</p>
<dl class="glossary">
<dt>Generic / vanilla LDP servers</dt>
<dd>RDF storage systems that allow interacting with their resources by means of the LDP specification. These servers do not impose any restriction on LDPRs and generally act as storage systems without any domain
specific application logic and vocabularies. The document storage system in the first example of the primer falls into this category. </dd>
<dt>Application specific LDP severs </dt>
<dd>Existing applications with their own data model and business logic exposing their data using the LDP specification. These systems impose restrictions on LDPRs since the LDP interaction should be compliant with the underlying
business logic and data model. The bug tracker example presented in the latter part of the primer is an example of an application specific LDP server.</dd>
</dl>
-->
<p>The following provide a set of examples to show the Linked Data Platform interactions. Note, this is a primer and should not be considered as a canonical example of ideal LDP modeling.</p>
</section>
<section id="photomanager">
<h1>Online document store example (LDP Basics)</h1>
<p>
This section provides a set of examples of using an online document store application. These examples will demonstrate the behaviour of LDPRs and LDP Basic Containers. Registration with the document store application by a user results in some data storage space (a root Basic Container) where web resources that are supported by Linked Data Platform can be stored. Using this root Basic Container a user can create new documents and also child containers to further organize these documents.
</p>
<p>
APIs of web applications are commonly documented by listing valid operations which can operate on URLs, where the URLs are described as templates. A description of a LDP based document store is contained in the following table. We note with emphasis that it is important for servers to use links as the main mechanism to reveal the location of resources. If it would be necessary to encode such templates into client applications, this would be a strong indicator that the design breaches a number of good design principles. </p>
</p>
<table class="simple">
<thead>
<th>Path</th>
<th>Method</th>
<th>Description</th>
</thead>
<tbody>
<tr>
<td rowspan="5">/{username}/</td>
<td>GET</td>
<td>Lists all the documents in the root container.</td>
</tr>
<tr>
<td>POST</td>
<td>Create a new document under the root container.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the description and/or list of files of the root container.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Update the description and/or list of files of the root container.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Not allowed.</td>
</tr>
<tr>
<td class="col1" rowspan="5">
<div class='code'>/{username}/{{document}/}*</div>
</td>
<td>GET</td>
<td>Retrive the document.</td>
</tr>
<tr>
<td>POST</td>
<td>Discovered from the resource affordances.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the document.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Partial update to the document if PATCH is supported.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Delete the project description and associated bug reports.</td>
</tr>
<tr>
<td rowspan="2">
<div class='code'>/*/*</div>
</td>
<td>OPTIONS</td>
<td>Discover the allowed operations over a resource</td>
</tr>
<tr>
<td>HEAD</td>
<td>Only retrieve metainformation about a resource</td>
</tr>
</tbody>
</table>
<p>
In this example, we will see how Alice, a user of this system, manages read / write management of documents using the LDP protocol. A typical interaction with the system would start with Alice registering as a user. It is likely that registration would be a LDP based interaction, but this that aspect is out of scope of this example. A consequence of the registration is allocation of space for the storage of documents, and communication of this URL to the user, e.g. a basic container at http://data.example.org/alice/. This section describes a typical flow of interactions where Alice firsts reads the root document and discovers its affordances. This is followed by subsequent examples of creation, update and delete, and finishes with how the client is able to create nested structure from the containers.
</p>
<section id="filelookup">
<h2>Looking up a basic container (GET on an LDP-BC) </h2>
<p>First Alice looks up her storage by retrieving the LDP Basic Container assigned to her to hold her documents. As it was just created, it is an empty container.</p>
<pre title="Request - basic container retreival" class='example' data-include='getbc.txt' data-oninclude='fixCode'></pre>
<pre title="Response - basic container retreival" class='example' data-include='getbc_res.txt' data-oninclude='fixCode'></pre>
</section>
<section>
<h2> Discovering the affordances (OPTIONS on an LDP-BC) </h2>
<p>
Now, Alice wants to know what she can do in her document space. She can use the OPTIONS operation to learn of the permitted LDP-BC operations.
</p>
<pre title="Request - retreiving OPTIONS of a basic container" class='example' data-include='optbc.txt' data-oninclude='fixCode'></pre>
<pre title="Response - retreiving OPTIONS of a basic container" class='example' data-include='optbc_res.txt' data-oninclude='fixCode'></pre>
<p>According to the response, HTTP operations {OPTIONS,HEAD, GET,POST,PUT,PATCH} are allowed on her root container. In addition to the allowed operations, Accept-Post and Accept-Patch provides which media types are supported by the respective operations. The rel="type" Link header advertises that this resource supports LDP protocol and it is an LDP Basic Container.</p>
<p>In this case, the response tells Alice's LDP client that this is an LDP-Basic Container and the container allows her to POST things of both RDF types (text/turtle, application/ld+json) and images (image/bmp and image/jpeg).</p>
</section>
<section>
<h2> Creating a RDF resource (POST an RDF resource to an LDP-BC) </h2>
<p>
Alice can uplaod a social profile document to her store, by POSTing her FOAF personal profile document to her LDP-BC at the root of her document store. Note, the Slug header offers the server a hint about URL of the created resource and the characters which found in the URL.
</p>
<pre title="Request - creating a RDF resource" class='example' data-include='bccreate.txt' data-oninclude='fixCode'></pre>
</pre>
<pre title="Response - creating a RDF resource" class="example" data-include='bccreate_res.txt' data-oninclude='fixCode'>
</pre>
<p>Once the resource is created, Alice can check the container again to confirm that it correctly contains the newly created resource.</p>
<pre title="Request - basic container retreival after resource created" class="example">
GET /alice/ HTTP/1.1
Host: example.org
Accept: text/turtle
</pre>
<pre title="Response - basic container retreival after resource created" class='example' data-include='bcget_res.txt' data-oninclude='fixCode'/>
<p>
The ldp:contains containment triple discloses the newly created resource in the response.
</p>
</section>
<section>
<h2> Creating a non-RDF (binary) resource (POST an image to an LDP-BC) </h2>
<p>Next, Alice wants to upload a photo of her to the document storage. She can create an image by POSTing it in the same way she created the RDF document.</p>
<pre title="Request - creating a non-RDF resource" class="example">
POST /alice/ HTTP/1.1
Host: data.example.org
Slug: avatar
Content-Type: image/png
Content- Length: nnn
### binary data ###
</pre>
<pre title="Response - creating a non-RDF resource" class="example">
HTTP/1.1 201 Created
Location: /alice/avatar
Link: <http://www.w3.org/ns/ldp/Resource>; rel="type"
Link: <http://data.example.org/alice/avatar/meta>; rel="describedby"
Content-Length: 0
</pre>
<p>The outcome of creating a non-RDF is similar to creating a RDF resource. If successful, the server will return a 201 success code with a Location header that points to the created resource. Furthermore, in the case of binary resources the server may create an additional file to maintain the metadata about the binary file like shown in the above example.</p>
</section>
<section>
<h2> Update a RDF LDP resource (PUT on an LDP-RS) </h2>
<!--
I MISSED THESE BITS OUT ... (??)
<pre title="A request for retrieving a RDF resource" class="example" data-include='getfoaf.txt' data-oninclude='fixCode'/>
<pre title="The response of retrieving a RDF resource" class='example' data-include='getfoaf_res.txt' data-oninclude='fixCode'/>
-->
<p>After creating the image, Alice now wants to update her FOAF profile with a link to the image. After retrieving her FOAF profile she uses HTTP PUT to update the document by amending the RDF with a link to her photo.</p>
<pre title="Request - updating a RDF resource" class="example" data-include='foafupdate.txt' data-oninclude='fixCode'></pre>
<pre title="Response - updating a RDF resource" class="example">
HTTP/1.1 204 No Content
Link: <http://www.w3.org/ns/ldp/Resource>; rel="type"
ETag: W/"123454322"
</pre>
<p>If the operation is successful, the document will be updated with new information.</p>
</section>
<section>
<h2> Deleting a resource (DELETE on an LDPR) </h2>
<p>If Alice decides to delete the document, she can do that with a delete operation.</p>
<pre title="Request - deleting a RDF resource" class="example">
DELETE /alice/foaf HTTP/1.1
Host: data.example.org
If-Match: W/"123454322"
</pre>
<pre title="Response - deleting a RDF resource" class="example">
HTTP/1.1 204 No Content
Link: <http://www.w3.org/ns/ldp/Resource>; rel="type"
ETag: W/"123454322"
</pre>
</section>
<section>
<h3 id="meta-structure">Structural Manipulation (Child Containers)</h3>
<p>In order for the client to introduce hierachy to the management of documents, the document store allows creation of documents which are containers. That enables Alice can to create a container hierarchy to organise her documents. This can be done by POSTing (a child) container representation to a (parent) container.
</p>
<p>This enables Alice to create a child container which she intends to use for image storage.</p>
<pre title="State of Alice's document store before creating the photo (child) container" class='example' data-include='create_cr_s1.txt' data-oninclude='fixCode'></pre>
<p>So Alice POSTs a representation of a container (LDP-BC) for creating photos to the root container.</p>
<pre title="Request - creating a new container" class='example' data-include='create_cr_req.txt' data-oninclude='fixCode'></pre>
<p>If the create is successful, the server responds with location of the newly created container for the photos.</p>
<pre title="Response - creating the new container" class="example">
HTTP/1.1 201 Created
Location: /alice/photos/
Content-Length: 0
</pre>
<p>After creation of this new container, the parent container will look like</p>
<pre title="State of Alice's document store after creating the photo (child) container" class='example' data-include='create_cr_s2.txt' data-oninclude='fixCode'></pre>
<p>and the photo container will look like the following.</p>
<pre title="State of Alice's newly created photo container" class='example' data-include='create_cr_s3.txt' data-oninclude='fixCode'></pre>
</section>
</section>
<section id="bugtracker">
<h1>Bug Tracker Example (LDP Direct containers)</h1>
<p>The previous section provided practical examples of basic LDP interactions. This example used LDP Basic Containers. One of the limitations of LDP Basic Containers is that fixed LDP vocabulary can be used to assert the relations between a container and its contained resource. However, some scenarios require domain specific vocabulary to be used to list the members of a container. For example, an application which already had its own vocabulary would like continue using the same vocabulary when using LDP protocol. LDP Direct containers allow the domain-specific vocabulary to be used when listing members in a container.</p>
<p>In addition to using the domain-specific vocabularies, in some applications would like to represent relationships other than the containment relationship of information resources within the containers. One example is that information resources contains relationship about non-information resources or real world things. LDP Indirect Containers allows the containers use these relations when new resources are created.
</p>
<p class="note">For more information on information resources (documents) vs real world entities (things) separation please refer to <a href="http://www.w3.org/TR/webarch/#id-resources">Web Arch (Section 2.2. URI/Resource Relationships) </a>, , <a href="http://www.w3.org/TR/cooluris/#semweb">Cool URIs (Section 3. URIs for Real-World Objects)</a>, <a href="http://www.w3.org/TR/urls-in-data/#landing-pages">URLs in Data (Section 3. Landing Pages and Records)</a>.</p>
<p>
The examples in this section will revolve around a very simple Bug Tracker application. Bug Tracker application records the bugs of several products allowing reporting, updating and deleting bugs and products. In contrast to the online document store example, the bug tracker wants to use a simple domain vocabulary , e.g. has_bug or related, to express membership relationships in the containers. LDP provides the additional interaction capability in the protocol to perform dynamic evolution of knowledge representation.
</p>
<p>A RESTful API for a simple Bug Tracker system might be described as follows.</p>
<table class="simple">
<thead>
<th>Path</th>
<th>Method</th>
<th>Description</th>
</thead>
<tbody>
<!--tr>
<td rowspan="5">/app/</td>
<td>GET</td>
<td>Lists all the product descriptions.</td>
</tr>
<tr>
<td>POST</td>
<td>Create a new product description.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the app description and/or list of product descriptions</td>
</tr>
<tr>
<td>PATCH</td>
<td>Update the app description and/or list of product descriptions</td>
</tr>
<tr>
<td>DELETE</td>
<td>Not allowed.</td>
</tr-->
<tr>
<td class="col1" rowspan="5">
<div class='code'>/app/{product-id}/</div>
</td>
<td>GET</td>
<td>Lists the bug reports associated with a product.</td>
</tr>
<tr>
<td>POST</td>
<td>Create a new bug report associated with a product.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the project description.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Not supported.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Delete the project description and associated bug reports.</td>
</tr>
<tr>
<td rowspan="5">
<div class='code'>/app/{product-id}/{bug-id}</div>
</td>
<td>GET</td>
<td>Gets the bug report.</td>
</tr>
<tr>
<td>POST</td>
<td>Not supported.</td>
</tr>
<tr>
<td>PUT</td>
<td>Update the bug report.</td>
</tr>
<tr>
<td>PATCH</td>
<td>Not supported.</td>
</tr>
<tr>
<td>DELETE</td>
<td>Delete the bug report.</td>
</tr>
<tr>
<td rowspan="2">
<div class='code'>/*/*</div>
</td>
<td>OPTIONS</td>
<td>Discover the allowed operations over a resource</td>
</tr>
<tr>
<td>HEAD</td>
<td>Only retrieve metainformation about a resource</td>
</tr>
</tbody>
</table>
<section id="navandret">
<h2>Navigation and Retreival</h2>
<p>One of the main use cases of the example bug tracker is to list of the bugs of a given product. Assuming that a user got a URL of a product by out of band means, one can look it up to get more information including the bugs associated with it.</p>
<p>To get the description of the product, a client can do a GET request on the URI of the known product resource. LDPR servers should provide text/turtle representations of the requested LDPRs and may provide RDF format representations using standard HTTP content negotiation.</p>
<pre class="example" title="Product lookup request" data-include='product_lookup_req.txt' data-oninclude='fixCode'></pre>
<p>If the product resource is available, the server responds with the representation of the resource using the requested media type,
<code>text/turtle</code> in this case.</p>
<pre title="HTTP response for product lookup" class='example' data-include='product_lookup_resp.txt' data-oninclude='fixCode'></pre>
<p>The project description resource contains both information about the project such as the title and the information about members of the product LDPC, i.e. the bugs associated with the product. This example uses an LDP Direct Container allowing the application to use domain specific vocabulary in the container. For example, it manages the (<?productURI>, bt:hasbug, <?bugURI>) relationship using the application-specific vocabulary. The next example illustrates the behaviour of LDP Direct containers when new resources are created.</p>
<!-- <p>Looking up a bug is similar to looking up a product. Based on links in the representation of the Product, the client uses GET to navigate to a known Bug resource.</p>
<pre class="example" title="Bug lookup request"
data-include='bug_look_up_req.txt' data-oninclude='fixCode'></pre>
<p>The server responds with the representation of the bug.</p>
<pre title="Bug lookup response"
class='example' data-include='bug_look_up_resp.txt'
data-oninclude='fixCode'></pre -->
</section>
<section>
<h3 id="BugCreate">Creation</h3>
<p>Continuing from the previous example, we can report a Bug against 'product1' by creating a Bug LDPR under the 'Product' LDPC. The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<p>The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<pre title="A request for creating a bug" class='example' data-include='bug_create_req.txt' data-oninclude='fixCode'></pre>
<p>If the create is successful, the server responds with location of the newly created resource.</p>
<pre title="A response of creating new a bug" class='example' data-oninclude='fixCode'>
HTTP/1.1 201 Created
Location: /app/product1/67
Content-Length: 0
</pre>
<p>If the creation fails, the server will respond with an appropriate status code depending on the error. After the resource is creation, the Product A LDPC will have the following representation.</p>
<pre title="The state of the product LDPC after the bug creation" class='example' data-include='bug_create_s1.txt' data-oninclude='fixCode'></pre>
<p> As you can see two new triples are added to the container. That is (</app/product1>, <ldp:contains>, </app/product1/bug67>) and
(</app/product1/#it>, <bt:hasbug>, </app/product1/bug67>). The former is added in any type of container and the latter is defined by the direct
container properties. The subject of the second triple is defined by the property ldp:membershipResource and the predicate is defined by the ldp:hasMemberRelation.
The object of the triple is the newly created resource. </p>
<p>And the created Bug resource will have the following representation. Note that server has added a server managed property, creation date (dcterms:created), and a default value for the state (bt:isInState) to the Bug in addition to what was being POSTed.</p>
<pre title="The state of the bug LDPR" class='example' data-include='bug_create_s2.txt' data-oninclude='fixCode'></pre>
</section>
<section>
<h3 id="BugDelete">Deletion</h3>
<pre class="example">
DELETE /app/product1/bug3 HTTP/1.1
Host: example.org
</pre>
<p>If the update is successful, the server will respond with a success status and a new etag.</p>
<pre class="example">
HTTP/1.1 204 No Content
ETag: W/"123456790"
</pre>
<p> After the deletion, the representation of the container will look like the following (Show that the two triples are gone) </p>
</section>
</section>
<section id="bugtrackerextd">
<h1>Extended Bug Tracker Example (LDP Indirect containers)</h1>
<p> In this example, we will use the same scenario as the previous example but using an LDP Indirect Container to show what is the use of Indirect containers and
how to use them. </p>
<section id="navandretext">
<h2>Navigation and Retreival</h2>
<pre class="example" title="Product lookup request" data-include='product_lookup_req.txt' data-oninclude='fixCode'></pre>
<p>If the product resource is available, the server responds with the representation of the resource using the requested media type,
<code>text/turtle</code> in this case.</p>
<pre title="HTTP response for product lookup" class='example' data-include='ic_product_lookup_resp.txt' data-oninclude='fixCode'></pre>
<p> Now the product container is an LDP Indirect container and we can notice several differences. </p>
</section>
<!-- end navandretext -->
<section id="creationext">
<h3 id="IndirectCreate">Creation</h3>
<p>Continuing from the previous example, we can report a Bug against 'product1' by creating a Bug LDPR under the 'Product' LDPC. The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<p>The client POSTs a representation of a Bug to the Bug Tracker LDPC.</p>
<pre title="A request for creating a bug" class='example' data-include='ic_bug_create_req.txt' data-oninclude='fixCode'></pre>
<p>If the create is successful, the server responds with location of the newly created resource.</p>
<pre title="A response of creating new a bug" class='example' data-oninclude='fixCode'>
HTTP/1.1 201 Created
Location: /app/product1/67
Content-Length: 0
</pre>
<p>If the creation fails, the server will respond with an appropriate status code depending on the error. After the resource is creation, the Product A LDPC will have the following representation.</p>
<pre title="The state of the product LDPC after the bug creation" class='example' data-include='ic_bug_create_s1.txt' data-oninclude='fixCode'></pre>
<p> As you can see two new triples are added to the container. That is (</app/product1>, <ldp:contains>, </app/product1/bug67>) and
(</app/product1/#it>, <bt:hasbug>, </app/product1/bug67#it>). </p>
<p>And the created Bug resource will have the following representation. Note that server has added a server managed property, creation date (dcterms:created), and a default value for the state (bt:isInState) to the Bug in addition to what was being POSTed.</p>
<pre title="The state of the bug LDPR" class='example' data-include='ic_bug_create_s2.txt' data-oninclude='fixCode'></pre>
</section>
<!-- end creationext -->
<section id="deleteext">
<h3 id="IndirectDelete">Deletion</h3>
<pre class="example">
DELETE /app/product1/bug3 HTTP/1.1
Host: example.org
</pre>
<p>If the update is successful, the server will respond with a success status and a new etag.</p>
<pre class="example">
HTTP/1.1 204 No Content
ETag: W/"123456790"
</pre>
<p> After the deletion, the representation of the container will look like the following (Show that the two triples are gone) </p>
</section>
<!-- end deleteext -->
</section>
<section>
<h1>Security</h1>
<p>It is not the focus of the Linked Data Platform WG to provide security mechanisms for read/write Linked Data applications. Though most of the security mechanisms that are applicable to general web applications are equally applicable to Linked Data applications, there is still some space to build security mechanisms specific to Linked Data applications by leverage the Linked Data technologies and providing concrete security requirements of Linked Data applications. In this context, LDP WG has started to create a WG note on Access Control which aims to produce use cases for security scenarios of LDP applications that can be used as the input to later initiative that will be focused on developing standard security mechanisms for LDP applications.</p>
</section>
<section>
<h1 id="ldpc">LDP Implementations</h1>
A list of implementations that plan to be LDP compliant is available in the LDP Implementations wiki page. LDP Implementation report provides the coverage of the specification by each LDP implementation.
</section>
<section>
<h1 id="next">What To Read Next</h1>
The primer only provide an overview of the Linked Data Platform specifications. LDP WG has produced following documents that contribute to the Linked Data Platform specification.
<ul>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/TR/ldp-ucr.html">Linked Data Platform Use Cases and Requirements</a> [[LDP-UCR]]</li>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp.html">Linked Data Platform 1.0 specifcation</a> [[LDP]]</li>
<li>Linked Data Platform 1.0 Primer (This document)</li>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp-bp/ldp-bp.html">LDP Best Practices and Guidelines</a> [[LDP-BP]]</li>
<li><a href="https://dvcs.w3.org/hg/ldpwg/raw-file/default/Test%20Cases/LDP%20Test%20Cases.html">Linked Data Platform 1.0 Test Cases</a>[[LDP-TESTS]]</li>
</ul>
</section>
<section class='appendix informative' id="history">
<h1>Change History</h1>
<p>The change history is up to the editors to insert a brief summary of changes, ordered by most recent changes first and with heading from which public draft it has been changed from.
</p>
<ul>
<li>2013-08-05 - Providing JSON-LD representations of the examples.</li>
<li>2013-07-03 - Moving the content from the wiki to the note.</li>
</ul>
</section>
</body>
</html>
\ No newline at end of file