rdf-ldp 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
[](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
|