rdf-ldp 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/IMPLEMENTATION.md +280 -0
- data/README.md +72 -11
- data/VERSION +1 -1
- data/bin/lamprey +9 -0
- data/lib/rdf/ldp/container.rb +30 -0
- data/lib/rdf/ldp/direct_container.rb +61 -14
- data/lib/rdf/ldp/indirect_container.rb +81 -0
- data/lib/rdf/ldp/non_rdf_source.rb +237 -0
- data/lib/rdf/ldp/rdf_source.rb +84 -21
- data/lib/rdf/ldp/resource.rb +91 -5
- data/lib/rdf/ldp.rb +44 -1
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb5f41c7209feb6a7669bf5a39284adb6ec15339
|
4
|
+
data.tar.gz: 2e5fd941cad72b6a32f2724a57210db788d56c92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 147ea229c52f3c64eb2ba925b80b71fb3adb4bdbee938ad8df991b88e7356ed38e014866fd2e416ba209d26710a75b9ed6d55992f3c2a177111650bfa94e97a4
|
7
|
+
data.tar.gz: e1104014e6961b8a10ff2d6fcc7c76b7785fa0514975d372ba74a4d44dc5d1c547336ac4bc8b8633e710b5309136e6626e17d0aa6755700e621ecf28d97824c8
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
|
2
|
+
0.3.0
|
3
|
+
------
|
4
|
+
- Adds LDP-NR support with basic file storage
|
5
|
+
- Moves `Lamprey` to `RDF::Lamprey`
|
6
|
+
- Adds server executable (`./bin/lamprey`)
|
7
|
+
- Adds support for IndirectContainer
|
8
|
+
- Develops HTTP PATCH support with LDPatch and SPARQL Update formats
|
9
|
+
- Allows new resource creation with PUT in Lamprey
|
10
|
+
- Improves handling of Rack input (avoids calling off-SPEC `#eof?`)
|
11
|
+
|
12
|
+
0.2.0
|
13
|
+
------
|
14
|
+
- Initial release
|
15
|
+
- Supports LDP-RS, BasicContainer, and DirectContainer
|
16
|
+
- Ships with a limited server "Lamprey"
|
17
|
+
- Note: 0.1.0 was a gem containing only an `RDF::Vocabulary`, this
|
18
|
+
has been moved to `rdf-vocab`
|
data/IMPLEMENTATION.md
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
LDP Implementation Overview
|
2
|
+
============================
|
3
|
+
|
4
|
+
4.2 Resource
|
5
|
+
------------
|
6
|
+
|
7
|
+
### 4.2.1 General
|
8
|
+
|
9
|
+
- __4.2.1.1__: HTTP 1.1 is supported through Rack. Implementers can use
|
10
|
+
Rackup, Sinatra, Rails, and other Rack-driven frameworks to fully support
|
11
|
+
HTTP 1.1 in their servers.
|
12
|
+
- __4.2.1.2__: Both LDP-RSs and LDP-NRs are supported. LDP-RS is the default
|
13
|
+
interaction model; clients must request an LDP-NR specificially at time of
|
14
|
+
creation.
|
15
|
+
- __4.2.1.3__: Etags are generated for all LDPRs and returned for all requests
|
16
|
+
to the resource.
|
17
|
+
- __4.2.1.4__: Link headers for the resquested resource are added by
|
18
|
+
`Rack::LDP::Headers` middleware.
|
19
|
+
- __4.2.1.5__: Relative URI resolution in RDF graphs is handled with
|
20
|
+
`RDF::Reader#base_uri`. This is tested for Turtle input.
|
21
|
+
- __4.2.1.6__: Constraints are published in the {CONSTRAINED_BY.md} file in
|
22
|
+
this repository. Additional, implementation specific constraints should be
|
23
|
+
published by the server implementer and added to the headers for the server.
|
24
|
+
|
25
|
+
### 4.2.2 HTTP GET
|
26
|
+
|
27
|
+
- __4.2.2.1__: LDPRs support GET.
|
28
|
+
- __4.2.2.2__: The "Allow" headers specified for OPTIONS are returned with
|
29
|
+
all requests for a given resource; this is handeled by the `Rack::LDP::Headers`
|
30
|
+
middleware.
|
31
|
+
|
32
|
+
### 4.2.3 HTTP POST
|
33
|
+
|
34
|
+
- POST is supported for LDP Containers, constranits are published in
|
35
|
+
{CONSTRAINED_BY.md}. See: __4.2.1.6__ for details.
|
36
|
+
|
37
|
+
### 4.2.4 HTTP PUT
|
38
|
+
|
39
|
+
- __4.2.4.1__: RDFSources completely replace the content of existing graphs with
|
40
|
+
the graph in the PUT request body. Any properties to be handled by the server
|
41
|
+
with update restrictions are left to implementers to enforce.
|
42
|
+
- __4.2.4.2__: See: __4.2.4.1__
|
43
|
+
- __4.2.4.3__: Server allows client to modify all content except that
|
44
|
+
explicitly excluded by LDP (i.e. server-managed-triples), which are handled
|
45
|
+
as described under relevant sections.
|
46
|
+
- __4.2.4.4__: Server persists all content PUT to LDP-RS's, per __4.2.4.1__.
|
47
|
+
- __4.2.4.5__: [IGNORED SHOULD] Etags are checked as specified IF an
|
48
|
+
`If-Match` header is present. `If-Match` headers are NOT required, and requests
|
49
|
+
without them will operate as though the correct Etag has been given. We
|
50
|
+
consider "_clients SHOULD use the HTTP If-Match header_".
|
51
|
+
- __4.2.4.6__: Sending a PUT request to a non-existant Resource creates a
|
52
|
+
Resource at that URI with the selected interaction model (defaulting to
|
53
|
+
ldp:RDFSource). The created Resource will not be in any container.
|
54
|
+
|
55
|
+
### 4.2.5 HTTP DELETE
|
56
|
+
|
57
|
+
- DELETE is supported
|
58
|
+
|
59
|
+
### 4.2.6 HTTP HEAD
|
60
|
+
|
61
|
+
- __4.2.6.1__: HEAD is supported. See: __4.2.2.2__ for details on HTTP headers.
|
62
|
+
|
63
|
+
### 4.2.7 HTTP PATCH
|
64
|
+
|
65
|
+
- PATCH support is implemented with the LDPatch format and with SPARQL Update.
|
66
|
+
|
67
|
+
### 4.2.8 HTTP OPTIONS
|
68
|
+
|
69
|
+
- __4.2.8.1__: OPTIONS is supported for all resources.
|
70
|
+
- __4.2.8.2__: See: __4.2.2.2__ for details on HTTP headers.
|
71
|
+
|
72
|
+
4.3 LDP RDFSource
|
73
|
+
------------------
|
74
|
+
|
75
|
+
### 4.3.1 General
|
76
|
+
|
77
|
+
- __4.3.1.1__: Each LDP-RS is an LDPR as described in this reports description
|
78
|
+
of __4.2__.
|
79
|
+
- __4.3.1.2__: [IGNORING SHOULD] Enforcement of the presence rdf:type is left
|
80
|
+
to the client and/or server implementer. This software does not add or manage
|
81
|
+
rdf:type in its representations.
|
82
|
+
- __4.3.1.3__: See: __4.3.1.2__.
|
83
|
+
- __4.3.1.4__: See: __4.2.2.1__. Content negotiation for returned RDF
|
84
|
+
representations is handled by `Rack::LDP::ContentNegotiation`, which inherits
|
85
|
+
`Rack::LinkedData::ContentNegotiation`.
|
86
|
+
- __4.3.1.5-6__: Vocabulary use is left to the client.
|
87
|
+
- __4.3.1.7-9__: These are constraints on the client, not addressed by this
|
88
|
+
software.
|
89
|
+
- __4.3.1.10__: No specialized rules about update or graph contents are
|
90
|
+
enforced by this software. It requires no inferencing.
|
91
|
+
- __4.3.1.11-13__: These are constraints on the client, not addressed by this
|
92
|
+
software.
|
93
|
+
|
94
|
+
### 4.3.2 HTTP GET
|
95
|
+
|
96
|
+
- __4.3.2.1__: [UNKNOWN] The default return type is `text/turtle`. No testing
|
97
|
+
has been performed for the tie breaks prescribed in this section. Content
|
98
|
+
negotiation is handled by `Rack::LDP::ContentNegotiation`.
|
99
|
+
- __4.3.2.2__: The default return type is `text/turtle`.
|
100
|
+
- __4.3.2.3__: [UNKNOWN] Content negotiation for explicit `application/ld+json`
|
101
|
+
requests is functional. No testing has been performed for the tie breaks prescribed
|
102
|
+
in this section.
|
103
|
+
|
104
|
+
4.4 Non-RDFSource
|
105
|
+
------------------
|
106
|
+
|
107
|
+
### 4.4.1 General
|
108
|
+
|
109
|
+
- __4.4.1.1__: Each LDP-NR is an LDPR as described in this reports description
|
110
|
+
of __4.2__. LDP-NRs are persisted through a `StorageAdapter` allowing easily
|
111
|
+
swappable approaches to persistence.
|
112
|
+
- __4.4.1.2__: LDP-NRs include the specified Link header on all requests.
|
113
|
+
|
114
|
+
5.2 Container
|
115
|
+
--------------
|
116
|
+
|
117
|
+
### 5.2.1 General
|
118
|
+
|
119
|
+
- __5.2.1.1__: Each LDPC is an LDP-RS as described in this report's description
|
120
|
+
of __4.2__.
|
121
|
+
- __5.2.1.2-3__: rdf:type is left to the client and/or implementer.
|
122
|
+
- __5.2.1.4__: Link headers for type are added for all Resources; See:
|
123
|
+
__4.2.1.4__.
|
124
|
+
- __5.2.1.5__: [IGNORING SHOULD] Client hints are unimplemented. We are
|
125
|
+
considering including them in future development. [TODO]
|
126
|
+
|
127
|
+
### 5.2.2 HTTP GET
|
128
|
+
|
129
|
+
- __5.2.2.1__: See: __4.3.2.1__.
|
130
|
+
|
131
|
+
### 5.2.3 HTTP POST
|
132
|
+
- __5.2.3.1__: Server responds 201 unless an error is thrown while completing
|
133
|
+
the POST.
|
134
|
+
- __5.2.3.2__: Server adds a containment triple with predicate `ldp:contains`
|
135
|
+
when POST is successful.
|
136
|
+
- __5.2.3.3__: POSTs of LDP-NRs are accepted if the client specifies the LDP-NR
|
137
|
+
interaction model. Content types for LDP-NRs must be sent in a request header.
|
138
|
+
- __5.2.3.4__: Honors LDP interaction models in HTTP Link headers. Requests
|
139
|
+
without an interaction model specified are treated as requests to create an
|
140
|
+
LDP-RS.
|
141
|
+
- Interaction models are honored for all of LDP-RS, LDP-NR, LDPC, as well as
|
142
|
+
Basic, Direct, and Indirect container types.
|
143
|
+
- Requests for LDPRs are treated as LDP-RS. We read the specification as
|
144
|
+
vague with respect to the clause about requested LDPR interaction model.
|
145
|
+
This behavior represents our interpretation.
|
146
|
+
- __5.2.3.5__: POST requests to create an LDP-RS accept all content types
|
147
|
+
supported with an `RDF::Reader` in the `linkeddata` gem (including
|
148
|
+
'text/turtle').
|
149
|
+
- __5.2.3.6__: The server relies solely on the `Content-Type` headers to
|
150
|
+
understand the format of posted graphs. Requests without a `Content-Type` (or
|
151
|
+
body) will fail.
|
152
|
+
- __5.2.3.7__: Relative URI resolution in RDF graphs is handled with
|
153
|
+
`RDF::Reader#base_uri`. This is tested for Turtle input.
|
154
|
+
- __5.2.3.8__: Created resources are assigned UUID's with the container as
|
155
|
+
the base URI when no Slug header is present.
|
156
|
+
- __5.2.3.9__: No constraints on graph contents are imposed.
|
157
|
+
- __5.2.3.10__: Slug headers are treated as non-negotiable requests to create
|
158
|
+
a resource at [container-uri]/[Slug]. If a resource exists at that address the
|
159
|
+
request will fail.
|
160
|
+
- __5.2.3.11__: Deleted resources are tombstoned and their URI's are protected
|
161
|
+
from future use.
|
162
|
+
- __5.2.3.12__: When an LDP-NR is created, an LDP-RS is created at
|
163
|
+
`[ldp-nr-uri]/.well-known/desc`. The `describedBy` Link header is added.
|
164
|
+
- __5.2.3.13__: Accept-Post headers are added to all responses from resources
|
165
|
+
that accept post requests. Content types are added dynamically when new
|
166
|
+
RDF::Readers are loaded.
|
167
|
+
- __5.2.3.14__: See: __5.2.3.5__.
|
168
|
+
|
169
|
+
### 5.2.4 HTTP PUT
|
170
|
+
|
171
|
+
- __5.2.4.1__: Responds with 409 when attempting to write containment triples
|
172
|
+
that do not already exist.
|
173
|
+
- __5.2.4.2__: See: __5.2.3.11__.
|
174
|
+
|
175
|
+
|
176
|
+
### 5.2.5 HTTP DELETE
|
177
|
+
|
178
|
+
- __5.2.5.1__: Containment triples are removed as required when a resource is destroyed.
|
179
|
+
- __5.2.5.2__: See: __5.2.8.1__.
|
180
|
+
|
181
|
+
### 5.2.6 HTTP HEAD
|
182
|
+
|
183
|
+
- See: __4.2.6__
|
184
|
+
|
185
|
+
### 5.2.7 HTTP PATCH
|
186
|
+
|
187
|
+
- See: __4.2.7__
|
188
|
+
|
189
|
+
### 5.2.8 HTTP OPTIONS
|
190
|
+
|
191
|
+
- __5.2.8.1__: The related LDP-RSs are created and the required Link headers
|
192
|
+
are included on all requests to LDP-NRs.
|
193
|
+
|
194
|
+
5.3 Basic Container
|
195
|
+
--------------------
|
196
|
+
|
197
|
+
### 5.3.1 General
|
198
|
+
|
199
|
+
- __5.3.1.1__: Basic Containers are treated as an alias for Container.
|
200
|
+
|
201
|
+
5.4 Direct Container
|
202
|
+
--------------------
|
203
|
+
|
204
|
+
### 5.4.1 General
|
205
|
+
|
206
|
+
- __5.4.1.1__: DirectContainers inherit all BasicContainer behavior
|
207
|
+
- __5.4.1.2__: `ldp:member` is used as the default predicate in cases where the
|
208
|
+
client provides none.
|
209
|
+
- __5.4.1.3__: We enforce the inclusion of _exactly one_
|
210
|
+
`ldp:membershipResource` by:
|
211
|
+
- adding the LDPDC as the `ldp:membershipResource` if the client does not
|
212
|
+
provide one.
|
213
|
+
- rejecting POST requests with `NotAcceptable` if more than one is present
|
214
|
+
We allow clients to change triples including `ldp:membershipResource` at their
|
215
|
+
own risk.
|
216
|
+
- __5.4.1.4__: The behaivor described in __5.4.1.3__ applies to statements
|
217
|
+
with either of `ldp:hasMemberRelation` and `ldp:isMemberOfRelation`.
|
218
|
+
- __5.4.1.5__: We implement the `ldp:MemberSubject` behavior as described and
|
219
|
+
ignore `ldp:insertedContentRelation` on DirectContainers.
|
220
|
+
|
221
|
+
### 5.4.2 POST
|
222
|
+
|
223
|
+
- __5.4.2.1__: Triples are created as described when POSTing to a container. We
|
224
|
+
allow clients to delete and replace triples at their own risk, per the MAY in
|
225
|
+
this section.
|
226
|
+
- Membership triples are added to the Membership Resource's graph.
|
227
|
+
- If the Membership Resource is an LDP-NR, membership triples are added to
|
228
|
+
the server-created LDP-RS (`describedby`, resource).
|
229
|
+
- POST requests are rejected if the Membership Resource does not exist.
|
230
|
+
|
231
|
+
|
232
|
+
### 5.4.2 DELETE
|
233
|
+
|
234
|
+
- __5.4.3.1__: Triples are deleted as described in this section.
|
235
|
+
|
236
|
+
|
237
|
+
5.5 Indirect Container
|
238
|
+
-----------------------
|
239
|
+
|
240
|
+
### 5.5.1 General
|
241
|
+
|
242
|
+
- __5.5.1.1__: Indirect Containers are implemented as a subclass of Direct
|
243
|
+
Containers, inheriting all of their behavior.
|
244
|
+
- __5.5.1.2__: We enforce the inclusion of _exactly one_
|
245
|
+
`ldp:insertedContentRelation` by:
|
246
|
+
- adding `ldp:MemberSubject` if the client does not provide one.
|
247
|
+
- rejecting POST requests with `NotAcceptable` if more than one is present.
|
248
|
+
We allow clients to change triples including `ldp:insertedContentRelation` at
|
249
|
+
their own risk.
|
250
|
+
|
251
|
+
POST requests for LDP-NRs and LDP-RSs missing an expected inserted content
|
252
|
+
relation, or with multiple inserted content relations, are also rejected with
|
253
|
+
`NotAcceptable`.
|
254
|
+
|
255
|
+
### 5.5.2 HTTP POST
|
256
|
+
|
257
|
+
- __5.5.2.1__: `ldp:contains` triples are added in the same way as with Basic
|
258
|
+
and Direct Containers.
|
259
|
+
|
260
|
+
Handling of Non-Normative Notes
|
261
|
+
================================
|
262
|
+
|
263
|
+
- __6.2.2__ We supply swappable backends via the `RDF::Repository` abstraction.
|
264
|
+
Clients may edit the resources available to LDP freely through the interfaces
|
265
|
+
provided by `RDF::Repository` or by other means. Resources are marked as LDPRs
|
266
|
+
by the presence of a specific named graph structure, which should be maintained
|
267
|
+
for resources indended to be created or accessed over this server.
|
268
|
+
- __6.2.3__ After delete, we supply `410 GONE` responses. Resourced deleted are
|
269
|
+
treated as permanently deleted. Clients may recover them manually.
|
270
|
+
- __6.2.5__ PATCH support is implemented with the LDPatch format and with SPARQL
|
271
|
+
Update.
|
272
|
+
- __6.2.6__ We do not infer content types (or LDP interaction models) from
|
273
|
+
resource contents, instead relying exclusively on the headers defined and used
|
274
|
+
by LDP.
|
275
|
+
- __6.3.1__ We allow clients complete control over graph contents, except
|
276
|
+
where LDP _requires_ otherwise.
|
277
|
+
|
278
|
+
|
279
|
+
Test Suite
|
280
|
+
==========
|
data/README.md
CHANGED
@@ -3,9 +3,13 @@ RDF::LDP
|
|
3
3
|
|
4
4
|
[![Build Status](https://travis-ci.org/ruby-rdf/rdf-ldp.svg?branch=develop)](https://travis-ci.org/ruby-rdf/rdf-ldp)
|
5
5
|
|
6
|
+
Server-side support for Linked Data Platform (LDP) with RDF.rb. To get started
|
7
|
+
with LDP, see the [LDP Primer](https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp-primer/ldp-primer.html).
|
8
|
+
|
6
9
|
This software ships with the following libraries:
|
7
10
|
|
8
|
-
- `RDF::LDP` --- contains the domain model for LDP Resources
|
11
|
+
- `RDF::LDP` --- contains the domain model and behavior for LDP Resources and
|
12
|
+
interaction models.
|
9
13
|
- `Rack::LDP` --- a suite of Rack middleware for creating LDP servers based on
|
10
14
|
`RDF::LDP`.
|
11
15
|
- Lamprey --- a basic LDP server implemented with `Rack::LDP`.
|
@@ -15,13 +19,22 @@ Lamprey
|
|
15
19
|
|
16
20
|
Lamprey is a basic LDP server. To start it, use:
|
17
21
|
|
18
|
-
```
|
19
|
-
|
22
|
+
```sh
|
23
|
+
$ gem install rdf-ldp
|
24
|
+
$ lamprey
|
20
25
|
```
|
21
26
|
|
22
|
-
|
23
|
-
|
24
|
-
|
27
|
+
Lamprey currently uses an in-memory repository, and is therefore not a
|
28
|
+
persistent datastore out of the box. Backends are swappable, using any
|
29
|
+
`RDF::Repository` implementation with named graph (`#context`) support. We are
|
30
|
+
working to complete a recommended, default backend and introduce startup
|
31
|
+
configuration. See [/CONSTRAINED_BY.md](/CONSTRAINED_BY.md) and
|
32
|
+
[/IMPLEMENTATION.md](/IMPLEMENTATION.md) for details.
|
33
|
+
|
34
|
+
An `ldp:BasicContainer` will be created at the address of your first `GET`
|
35
|
+
request if the backend store is empty. _Note that if that request is made to the
|
36
|
+
server root, Sinatra will assume a trailing slash_. You can also create an
|
37
|
+
initial container (or other resource) with HTTP `PUT`.
|
25
38
|
|
26
39
|
```bash
|
27
40
|
$ curl -i http://localhost:4567
|
@@ -40,6 +53,58 @@ Content-Length: 0
|
|
40
53
|
Connection: Keep-Alive
|
41
54
|
```
|
42
55
|
|
56
|
+
See
|
57
|
+
|
58
|
+
Rack::LDP
|
59
|
+
==========
|
60
|
+
|
61
|
+
Setting up a Custom Server
|
62
|
+
--------------------------
|
63
|
+
|
64
|
+
You can quickly create your own server with any framework supporting
|
65
|
+
[Rack](https://github.com/rack/). The simplest way to do this is with
|
66
|
+
[Rackup](https://github.com/rack/rack/wiki/(tutorial)-rackup-howto).
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
# ./config.ru
|
70
|
+
|
71
|
+
require 'rack/ldp'
|
72
|
+
|
73
|
+
use Rack::LDP::ContentNegotiation
|
74
|
+
use Rack::LDP::Errors
|
75
|
+
use Rack::LDP::Responses
|
76
|
+
use Rack::LDP::Requests
|
77
|
+
|
78
|
+
# Setup a repository and an initial container:
|
79
|
+
#
|
80
|
+
# - You probably want some persistent repository implementation. The example
|
81
|
+
# uses an in-memory repository.
|
82
|
+
# - You may not need an initial "base" container, if you handle create on PUT
|
83
|
+
# requests.
|
84
|
+
#
|
85
|
+
repository = RDF::Repository.new
|
86
|
+
RDF::LDP::Container.new(RDF::URI('http://localhost:9292/'), repository)
|
87
|
+
.create('', 'text/plain') if repository.empty?
|
88
|
+
|
89
|
+
app = proc do |env|
|
90
|
+
# Return a Rack response, giving an `RDF::LDP::Resource`-like object as the body.
|
91
|
+
# The `Rack::LDP` middleware marhsalls the request to the resource, builds the response,
|
92
|
+
# and handles conneg for RDF serializations (when the body is an `RDF::LDP::RDFSource`).
|
93
|
+
#
|
94
|
+
# @see http://www.rubydoc.info/github/rack/rack/master/file/SPEC#The_Response
|
95
|
+
|
96
|
+
[200, {}, RDF::LDP::Resource.find(RDF::URI(env['REQUEST_URI']), repository)]
|
97
|
+
end
|
98
|
+
|
99
|
+
run app
|
100
|
+
```
|
101
|
+
|
102
|
+
And run your server with:
|
103
|
+
|
104
|
+
```sh
|
105
|
+
$ rackup
|
106
|
+
```
|
107
|
+
|
43
108
|
Compliance
|
44
109
|
----------
|
45
110
|
|
@@ -48,12 +113,8 @@ Reports are generated by the LDP test suite. To duplicate the results,
|
|
48
113
|
use the `testsuite` branch, which contains a work-around for
|
49
114
|
[w3c/ldp-testsuite#224](https://github.com/w3c/ldp-testsuite/issues/224).
|
50
115
|
|
116
|
+
|
51
117
|
License
|
52
118
|
========
|
53
119
|
|
54
120
|
This software is released under a public domain waiver (Unlicense).
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/bin/lamprey
ADDED
data/lib/rdf/ldp/container.rb
CHANGED
@@ -1,4 +1,18 @@
|
|
1
1
|
module RDF::LDP
|
2
|
+
##
|
3
|
+
# An LDP Basic Container. This also serves as a base class for other
|
4
|
+
# container types. Containers are implemented as `RDF::LDP::RDFSources` with
|
5
|
+
# the ability to contain other resources.
|
6
|
+
#
|
7
|
+
# Containers respond to `#post`, allowing new resources to be added to them.
|
8
|
+
# On the public interface (not running through HTTP/`#request`), this is
|
9
|
+
# supported by `#add` and `#remove`.
|
10
|
+
#
|
11
|
+
# Containers will throw errors when attempting to edit them in conflict with
|
12
|
+
# LDP's restrictions on changing containment triples.
|
13
|
+
#
|
14
|
+
# @see http://www.w3.org/TR/ldp/#dfn-linked-data-platform-container definition
|
15
|
+
# of LDP Container
|
2
16
|
class Container < RDFSource
|
3
17
|
##
|
4
18
|
# @return [RDF::URI] uri with lexical representation
|
@@ -100,6 +114,22 @@ module RDF::LDP
|
|
100
114
|
|
101
115
|
private
|
102
116
|
|
117
|
+
def patch(status, headers, env)
|
118
|
+
check_precondition!(env)
|
119
|
+
method = patch_types[env['CONTENT_TYPE']]
|
120
|
+
|
121
|
+
raise UnsupportedMediaType unless method
|
122
|
+
|
123
|
+
temp_graph = RDF::Graph.new << graph.statements
|
124
|
+
send(method, env['rack.input'], temp_graph)
|
125
|
+
|
126
|
+
validate_triples!(temp_graph)
|
127
|
+
graph.clear!
|
128
|
+
graph << temp_graph.statements
|
129
|
+
|
130
|
+
[200, update_headers(headers), self]
|
131
|
+
end
|
132
|
+
|
103
133
|
##
|
104
134
|
# Handles a POST request. Parses a graph in the body of `env` and treats all
|
105
135
|
# statements in that graph (irrespective of any graph names) as constituting
|
@@ -1,4 +1,22 @@
|
|
1
1
|
module RDF::LDP
|
2
|
+
##
|
3
|
+
# An extension of `RDF::LDP::Container` implementing direct containment.
|
4
|
+
# This adds the concepts of a membership resource, predicate, and triples to
|
5
|
+
# the Basic Container's containment triples.
|
6
|
+
#
|
7
|
+
# When the membership resource is an `RDFSource`, the membership triple is
|
8
|
+
# added/removed from its graph when the resource created/deleted within the
|
9
|
+
# container. When the membership resource is a `NonRDFSource`, the triple is
|
10
|
+
# added/removed on its description's graph instead.
|
11
|
+
#
|
12
|
+
# A membership constant URI and membership predicate MUST be specified as
|
13
|
+
# described in LDP--exactly one of each. If none is given, we default to
|
14
|
+
# the container itself as a membership resource and `ldp:member` as predicate.
|
15
|
+
# If more than one of either is given, all `#add/#remove` (POST/DELETE)
|
16
|
+
# requests will fail.
|
17
|
+
#
|
18
|
+
# @see http://www.w3.org/TR/ldp/#dfn-linked-data-platform-direct-container
|
19
|
+
# definition of LDP Direct Container
|
2
20
|
class DirectContainer < Container
|
3
21
|
def self.to_uri
|
4
22
|
RDF::Vocab::LDP.DirectContainer
|
@@ -13,62 +31,89 @@ module RDF::LDP
|
|
13
31
|
CONTAINER_CLASSES[:direct]
|
14
32
|
end
|
15
33
|
|
34
|
+
##
|
35
|
+
# Adds a member `resource` to the container. Handles containment and adds
|
36
|
+
# membership triple to the memebership resource.
|
37
|
+
#
|
38
|
+
# @see RDF::LDP::Container#add
|
16
39
|
def add(resource)
|
17
|
-
process_membership_resource(resource
|
40
|
+
process_membership_resource(resource) do |membership, triple|
|
18
41
|
super
|
19
42
|
membership.graph << triple
|
20
43
|
end
|
21
44
|
end
|
22
45
|
|
46
|
+
##
|
47
|
+
# Removes a member `resource` to the container. Handles containment and
|
48
|
+
# removes membership triple to the memebership resource.
|
49
|
+
#
|
50
|
+
# @see RDF::LDP::Container#remove
|
23
51
|
def remove(resource)
|
24
|
-
process_membership_resource(resource
|
52
|
+
process_membership_resource(resource) do |membership, triple|
|
25
53
|
super
|
26
54
|
membership.graph.delete(triple)
|
27
55
|
end
|
28
56
|
end
|
29
57
|
|
30
58
|
##
|
31
|
-
#
|
32
|
-
#
|
59
|
+
# Gives the membership constant URI. If none is present in the container
|
60
|
+
# state, we add the current resource as a membership constant.
|
61
|
+
#
|
62
|
+
# @return [RDF::URI] the membership constant uri for the container
|
63
|
+
#
|
64
|
+
# @raise [RDF::LDP::NotAcceptable] if multiple membership constant uris exist
|
65
|
+
#
|
66
|
+
# @see http://www.w3.org/TR/ldp/#dfn-membership-triples
|
33
67
|
def membership_constant_uri
|
34
|
-
|
68
|
+
statements = membership_resource_statements
|
69
|
+
case statements.count
|
35
70
|
when 0
|
36
71
|
graph << RDF::Statement(subject_uri,
|
37
72
|
RDF::Vocab::LDP.membershipResource,
|
38
73
|
subject_uri)
|
39
74
|
subject_uri
|
40
75
|
when 1
|
41
|
-
|
76
|
+
statements.first.object
|
42
77
|
else
|
43
78
|
raise NotAcceptable.new('An LDP-DC MUST have exactly ' \
|
44
79
|
'one membership resource; found ' \
|
45
|
-
"#{
|
80
|
+
"#{statements}.")
|
46
81
|
end
|
47
82
|
end
|
48
83
|
|
49
84
|
##
|
85
|
+
# Gives the membership predicate. If none is present in the container
|
86
|
+
# state, we add the current resource as a membership constant.
|
87
|
+
#
|
50
88
|
# @return [RDF::URI] the membership predicate
|
89
|
+
#
|
90
|
+
# @raise [RDF::LDP::NotAcceptable] if multiple membership predicates exist
|
91
|
+
#
|
51
92
|
# @see http://www.w3.org/TR/ldp/#dfn-membership-predicate
|
52
93
|
def membership_predicate
|
53
|
-
|
94
|
+
statements = member_relation_statements
|
95
|
+
case statements.count
|
54
96
|
when 0
|
55
97
|
graph << RDF::Statement(subject_uri,
|
56
98
|
RELATION_TERMS.first,
|
57
99
|
RDF::Vocab::LDP.member)
|
58
100
|
RDF::Vocab::LDP.member
|
59
101
|
when 1
|
60
|
-
|
102
|
+
statements.first.object
|
61
103
|
else
|
62
104
|
raise NotAcceptable.new('An LDP-DC MUST have exactly ' \
|
63
105
|
'one member relation triple; found ' \
|
64
|
-
"#{
|
106
|
+
"#{statements.count}.")
|
65
107
|
end
|
66
108
|
end
|
67
109
|
|
68
110
|
##
|
69
|
-
# @param [RDF::Term] a member for this container
|
111
|
+
# @param [RDF::Term] resource a member for this container
|
112
|
+
#
|
113
|
+
# @return [RDF::URI] the membership triple representing membership of the
|
114
|
+
# `resource` parameter in this container
|
70
115
|
#
|
71
|
-
# @
|
116
|
+
# @see http://www.w3.org/TR/ldp/#dfn-membership-triples
|
72
117
|
def make_membership_triple(resource)
|
73
118
|
predicate = membership_predicate
|
74
119
|
return RDF::Statement(membership_constant_uri, predicate, resource) if
|
@@ -91,11 +136,13 @@ module RDF::LDP
|
|
91
136
|
def membership_resource
|
92
137
|
uri = membership_constant_uri
|
93
138
|
uri = uri.fragment ? (uri.root / uri.request_uri) : uri
|
94
|
-
RDF::LDP::Resource.find(uri, @data)
|
139
|
+
resource = RDF::LDP::Resource.find(uri, @data)
|
140
|
+
return resource.description if resource.non_rdf_source?
|
141
|
+
resource
|
95
142
|
end
|
96
143
|
|
97
144
|
def process_membership_resource(resource, &block)
|
98
|
-
triple = make_membership_triple(resource)
|
145
|
+
triple = make_membership_triple(resource.to_uri)
|
99
146
|
|
100
147
|
begin
|
101
148
|
membership_rs = membership_resource
|