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