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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96681a7e685f8af473a2bfe9a2b25ffdb147a057
4
- data.tar.gz: 80a4b2e3efa3ec7aa7c41a0c6f252d67431babc0
3
+ metadata.gz: eb5f41c7209feb6a7669bf5a39284adb6ec15339
4
+ data.tar.gz: 2e5fd941cad72b6a32f2724a57210db788d56c92
5
5
  SHA512:
6
- metadata.gz: fd5442ef53e136c2dc83bc6fc5cb2d4c35b66d6e2be7669abd1c7d6eb5888d4fa5ecae8ccdfeb888d6e702675dbe1e2cab6f98ff01cd142c03f8baf826b86c30
7
- data.tar.gz: 1acbe59831cd7219ffb933957c96d67cbc16b21c4cd949d81b60f60201cba4c88490a4c2ab1897bae69a249858e2db77f4febe6c99a293da621de2e9b08a62d6
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
- bundle exec ruby app/lamprey.rb
22
+ ```sh
23
+ $ gem install rdf-ldp
24
+ $ lamprey
20
25
  ```
21
26
 
22
- An `ldp:BasicContainer` will be created at the address of your first
23
- `GET` request. Note that if that request is made to the server root,
24
- Sinatra will assume a trailing slash.
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.2.0
1
+ 0.3.0
data/bin/lamprey ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'app')))
3
+ require 'lamprey'
4
+
5
+ begin
6
+ require 'rdf/sparql'
7
+ rescue LoadError => e; end
8
+
9
+ RDF::Lamprey.run!
@@ -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.to_uri) do |membership, triple|
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.to_uri) do |membership, triple|
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
- # Aliases #subject_uri
32
- # @return [RDF::URI] #subject_uri
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
- case membership_resource_statements.count
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
- membership_resource_statements.first.object
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
- "#{membership_resource_statements.count}.")
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
- case member_relation_statements.count
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
- member_relation_statements.first.object
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
- "#{member_relation_statements.count}.")
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
- # @return [RDF::URI] the membership triple to be added to the
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