rdf-ldp 0.9.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +10 -0
- data/CREDITS +1 -0
- data/README.md +66 -10
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/app/lamprey.rb +119 -40
- data/bin/lamprey +15 -1
- data/lib/rack/ldp.rb +23 -25
- data/lib/rdf/ldp/container.rb +32 -22
- data/lib/rdf/ldp/direct_container.rb +9 -7
- data/lib/rdf/ldp/indirect_container.rb +8 -6
- data/lib/rdf/ldp/interaction_model.rb +39 -29
- data/lib/rdf/ldp/non_rdf_source.rb +10 -6
- data/lib/rdf/ldp/rdf_source.rb +3 -3
- data/lib/rdf/ldp/resource.rb +33 -31
- data/lib/rdf/ldp/spec/container.rb +337 -0
- data/lib/rdf/ldp/spec/direct_container.rb +245 -0
- data/lib/rdf/ldp/spec/indirect_container.rb +152 -0
- data/lib/rdf/ldp/spec/non_rdf_source.rb +138 -0
- data/lib/rdf/ldp/spec/rdf_source.rb +370 -0
- data/lib/rdf/ldp/spec/resource.rb +242 -0
- data/lib/rdf/ldp/spec.rb +6 -0
- data/lib/rdf/ldp/storage_adapters/file_storage_adapter.rb +4 -4
- data/lib/rdf/ldp/version.rb +16 -3
- data/lib/rdf/ldp.rb +4 -3
- metadata +89 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a6eaa64d18272bf2f35f4d5852a5f8a116df0234d6b2decea3584255a987d9ad
|
4
|
+
data.tar.gz: 518ca26f3e55f464371be75c9bceefd49bb727b141d71f09a014cb4b2e350bff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3b9822d36e2714f7a31ce2e0b74e79f3f89e67ba33f40cd07d0d53c52cec043f9c7801caabad4ba7195b64f71527dda59047b14cdcf99fb98fd8d8670e740ae3
|
7
|
+
data.tar.gz: e1a9ad43326ba12973175108836abb33da8480a12a630582133a4afba7e6891bd782989f60a3902a1fe4f47dbc1e6730debcc18f59e45c2bee257e82eeb0252e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
0.9.3
|
2
|
+
-----
|
3
|
+
- Expose shared examples for LDP interaction models in
|
4
|
+
`lib/rdf/ldp/spec`.
|
5
|
+
|
1
6
|
0.9.2
|
2
7
|
-----
|
3
8
|
- Reduce memory allocation for URIs by using `RDF::URI#intern`.
|
@@ -77,3 +82,8 @@
|
|
77
82
|
- Ships with a limited server "Lamprey"
|
78
83
|
- Note: 0.1.0 was a gem containing only an `RDF::Vocabulary`, this
|
79
84
|
has been moved to `rdf-vocab`
|
85
|
+
|
86
|
+
0.2.1
|
87
|
+
------
|
88
|
+
- Deprecates Ruby < 2.6, supports Ruby 3.
|
89
|
+
- Updated dependencies.
|
data/CREDITS
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
* Gregg Kellogg <gregg@greggkellogg.net>
|
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
RDF::LDP
|
2
2
|
========
|
3
|
-
|
4
|
-
[![Build Status](https://
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/rdf-ldp.png)](https://badge.fury.io/rb/rdf-ldp)
|
4
|
+
[![Build Status](https://github.com/ruby-rdf/rdf-ldp/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/rdf-ldp/actions?query=workflow%3ACI)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/ruby-rdf/rdf-ldp/badge.svg)](https://coveralls.io/github/ruby-rdf/rdf-ldp)
|
6
|
+
[![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf)
|
5
7
|
|
6
8
|
Server-side support for Linked Data Platform (LDP) with RDF.rb. To get started
|
7
9
|
with LDP, see the [LDP Primer](https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp-primer/ldp-primer.html).
|
@@ -89,7 +91,7 @@ app = proc do |env|
|
|
89
91
|
# The `Rack::LDP` middleware marhsalls the request to the resource, builds the response,
|
90
92
|
# and handles conneg for RDF serializations (when the body is an `RDF::LDP::RDFSource`).
|
91
93
|
#
|
92
|
-
# @see
|
94
|
+
# @see https://www.rubydoc.info/github/rack/rack/master/file/SPEC#The_Response
|
93
95
|
|
94
96
|
[200, {}, RDF::LDP::Resource.find(RDF::URI(env['REQUEST_URI']), repository)]
|
95
97
|
end
|
@@ -103,6 +105,40 @@ And run your server with:
|
|
103
105
|
$ rackup
|
104
106
|
```
|
105
107
|
|
108
|
+
Testing
|
109
|
+
-------
|
110
|
+
|
111
|
+
RSpec shared examples for the required behaviors of LDP resource and container
|
112
|
+
types are included in `rdf/ldp/spec` for use in customized implementations.
|
113
|
+
Running these example sets will help ensure LDP compliance for specialized
|
114
|
+
resource behaviors.
|
115
|
+
|
116
|
+
This test suite is provided provisionally and may be incomplete or overly
|
117
|
+
strict. Please [report issues](https://github.com/ruby-rdf/rdf-ldp/issues)
|
118
|
+
encountered during its use.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
require 'rdf/ldp/spec'
|
122
|
+
|
123
|
+
describe MyResource do
|
124
|
+
it_behaves_like 'a Resource'
|
125
|
+
end
|
126
|
+
|
127
|
+
describe MyRDFSource do
|
128
|
+
it_behaves_like 'an RDFSource'
|
129
|
+
end
|
130
|
+
|
131
|
+
# ...
|
132
|
+
|
133
|
+
describe MyIndirectContainer do
|
134
|
+
it_behaves_like 'an IndirectContainer'
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
We recommend running the official
|
139
|
+
[LDP testsuite](https://github.com/cbeer/ldp_testsuite_wrapper), as integration
|
140
|
+
tests in addition to the above examples.
|
141
|
+
|
106
142
|
Compliance
|
107
143
|
----------
|
108
144
|
|
@@ -111,16 +147,36 @@ Reports are generated by the LDP test suite. We use the
|
|
111
147
|
[`ldp_testsuite_wrapper`](https://github.com/cbeer/ldp_testsuite_wrapper)
|
112
148
|
gem to run the suite and generate the tests.
|
113
149
|
|
114
|
-
RDF.rb
|
150
|
+
RDF.rb Compatibility
|
115
151
|
--------------------------
|
116
152
|
|
117
|
-
As of version
|
118
|
-
Ruby RDF version 1.99 will be maintained to the degree possible on the 0.5.x
|
119
|
-
release series. Users are encouraged to upgrade their projects to 2.0 to take
|
120
|
-
advantage of the latest development.
|
153
|
+
As of version 2.1, this software depends on RDF.rb 3.2 or greater.
|
121
154
|
|
155
|
+
## Contributing
|
122
156
|
|
123
|
-
|
124
|
-
|
157
|
+
This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
|
158
|
+
|
159
|
+
* Do your best to adhere to the existing coding conventions and idioms.
|
160
|
+
* Don't use hard tabs, and don't leave trailing whitespace on any line.
|
161
|
+
Before committing, run `git diff --check` to make sure of this.
|
162
|
+
* Do document every method you add using [YARD][] annotations. Read the
|
163
|
+
[tutorial][YARD-GS] or just look at the existing code for examples.
|
164
|
+
* Don't touch the `.gemspec` or `VERSION` files. If you need to change them,
|
165
|
+
do so on your private branch only.
|
166
|
+
* Do feel free to add yourself to the `CREDITS` file and the
|
167
|
+
corresponding list in the the `README`. Alphabetical order applies.
|
168
|
+
* Don't touch the `AUTHORS` file. If your contributions are significant
|
169
|
+
enough, be assured we will eventually add you in there.
|
170
|
+
* Do note that in order for us to merge any non-trivial changes (as a rule
|
171
|
+
of thumb, additions larger than about 15 lines of code), we need an
|
172
|
+
explicit [public domain dedication][PDD] on record from you,
|
173
|
+
which you will be asked to agree to on the first commit to a repo within the organization.
|
174
|
+
Note that the agreement applies to all repos in the [Ruby RDF](https://github.com/ruby-rdf/) organization.
|
175
|
+
|
176
|
+
## License
|
125
177
|
|
126
178
|
This software is released under a public domain waiver (Unlicense).
|
179
|
+
|
180
|
+
[YARD]: https://yardoc.org/
|
181
|
+
[YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
182
|
+
[PDD]: https://unlicense.org/#unlicensing-contributions
|
data/UNLICENSE
CHANGED
@@ -21,4 +21,4 @@ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
21
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
22
|
OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
|
-
For more information, please refer to <
|
24
|
+
For more information, please refer to <https://unlicense.org/>
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.1.0
|
data/app/lamprey.rb
CHANGED
@@ -1,54 +1,133 @@
|
|
1
1
|
require 'rack/ldp'
|
2
2
|
require 'sinatra/base'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
set :repository, RDF::Repository.new
|
15
|
-
end
|
4
|
+
module RDF
|
5
|
+
##
|
6
|
+
# A basic implementation of an LDP Server.
|
7
|
+
class Lamprey < Sinatra::Base
|
8
|
+
use Rack::Lint
|
9
|
+
use Rack::LDP::ContentNegotiation
|
10
|
+
use Rack::LDP::Errors
|
11
|
+
use Rack::LDP::Responses
|
12
|
+
use Rack::ConditionalGet
|
13
|
+
use Rack::LDP::Requests
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
get '/*' do
|
16
|
+
if settings.repository.empty?
|
17
|
+
RDF::LDP::Container
|
18
|
+
.new(RDF::URI(request.url), settings.repository)
|
19
|
+
.create(StringIO.new, 'text/turtle')
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
22
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
patch '/*' do
|
26
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
27
|
+
end
|
30
28
|
|
31
|
-
|
32
|
-
begin
|
29
|
+
post '/*' do
|
33
30
|
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
34
|
-
rescue RDF::LDP::NotFound
|
35
|
-
model = request.env.fetch('HTTP_LINK', '')
|
36
|
-
RDF::LDP::Resource.interaction_model(model)
|
37
|
-
.new(RDF::URI(request.url), settings.repository)
|
38
31
|
end
|
39
|
-
end
|
40
32
|
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
put '/*' do
|
34
|
+
begin
|
35
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
36
|
+
rescue RDF::LDP::NotFound
|
37
|
+
model = request.env.fetch('HTTP_LINK', '')
|
44
38
|
|
45
|
-
|
46
|
-
|
47
|
-
|
39
|
+
RDF::LDP::Resource
|
40
|
+
.interaction_model(model)
|
41
|
+
.new(RDF::URI(request.url), settings.repository)
|
42
|
+
end
|
43
|
+
end
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
|
45
|
+
options '/*' do
|
46
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
47
|
+
end
|
48
|
+
|
49
|
+
head '/*' do
|
50
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
51
|
+
end
|
52
|
+
|
53
|
+
delete '/*' do
|
54
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# @example Configuring Lamprey server
|
59
|
+
# Lamprey::Config
|
60
|
+
# .register_repository!(:my_repo, RDF::Repository)
|
61
|
+
#
|
62
|
+
# Lamprey::Config.configure!(repository: :my_repo)
|
63
|
+
class Config
|
64
|
+
##
|
65
|
+
# @see #new
|
66
|
+
# @see #configure!
|
67
|
+
def self.configure!(**options)
|
68
|
+
new(**options).configure!
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Registers a repository for use with the {#build_repository} method.
|
73
|
+
#
|
74
|
+
# @example Registering a custom repository
|
75
|
+
# MyRepository = Class.new(RDF::Repository)
|
76
|
+
#
|
77
|
+
# Lamprey::Config.register_repository!(:my_repo, MyRepository)
|
78
|
+
#
|
79
|
+
# @param name [Symbol]
|
80
|
+
# @param klass [Class]
|
81
|
+
# @return [void]
|
82
|
+
def self.register_repository!(name, klass)
|
83
|
+
@@repositories[name] = klass
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# @!attribute [rw] options
|
88
|
+
attr_accessor :options
|
52
89
|
|
53
|
-
|
90
|
+
@@repositories = { default: RDF::Repository }
|
91
|
+
|
92
|
+
##
|
93
|
+
# @param repository [RDF::Repository]
|
94
|
+
def initialize(repository: :default)
|
95
|
+
@options = {}
|
96
|
+
@options[:repository] = repository
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Builds the repository as given in the configuration.
|
101
|
+
#
|
102
|
+
# @return [RDF::Repository] a repository instance
|
103
|
+
def build_repository
|
104
|
+
@@repositories.fetch(options[:repository]) do
|
105
|
+
warn "#{options[:repository]} is not a configured repository. Use "\
|
106
|
+
'`Lamprey::Config.register_repository!` to register it before '\
|
107
|
+
'configuration. Falling back on the default: ' \
|
108
|
+
"#{@@repositories[:default]}."
|
109
|
+
@@repositories[:default]
|
110
|
+
end.new
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Configures {RDF::Lamprey} with {#options}.
|
115
|
+
#
|
116
|
+
# @return [void]
|
117
|
+
def configure!
|
118
|
+
repository = build_repository
|
119
|
+
unless repository.persistent?
|
120
|
+
warn "#{repository} is not a persistent repository. "\
|
121
|
+
'Data will be lost on server shutdown.'
|
122
|
+
end
|
123
|
+
|
124
|
+
RDF::Lamprey.configure { |config| config.set :repository, repository }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Set defaults in case user does not configure values
|
129
|
+
Config.configure!
|
130
|
+
|
131
|
+
run! if app_file == $PROGRAM_NAME
|
132
|
+
end
|
54
133
|
end
|
data/bin/lamprey
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
2
|
+
$LOAD_PATH
|
3
|
+
.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'app')))
|
3
4
|
require 'lamprey'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
|
9
|
+
OptionParser.new do |opts|
|
10
|
+
opts.banner = 'Usage: lamprey [options]'
|
11
|
+
|
12
|
+
opts.on('-rREPO', '--repository=REPO', 'Set the repository') do |repo|
|
13
|
+
options[:repository] = repo.to_sym
|
14
|
+
end
|
15
|
+
end.parse!
|
16
|
+
|
17
|
+
RDF::Lamprey::Config.configure!(**options)
|
4
18
|
|
5
19
|
RDF::Lamprey.run!
|
data/lib/rack/ldp.rb
CHANGED
@@ -14,15 +14,15 @@ module Rack
|
|
14
14
|
# Provides Rack middleware for handling Linked Data Platform requirements
|
15
15
|
# when passed {RDF::LDP::Resource} and its subclasses as response objects.
|
16
16
|
#
|
17
|
-
# Response objects that are not an {RDF::LDP::Resource} are passed over
|
17
|
+
# Response objects that are not an {RDF::LDP::Resource} are passed over
|
18
18
|
# without alteration, allowing server implementers to mix LDP interaction
|
19
19
|
# patterns with others on the same server.
|
20
20
|
#
|
21
|
-
# The suite can be mix-and-matched as needed. This allows easy swap in of
|
21
|
+
# The suite can be mix-and-matched as needed. This allows easy swap in of
|
22
22
|
# custom handlers for parts of the behavior. It is recommended that you use
|
23
23
|
# {Rack::LDP::ContentNegotiation}, {Rack::LDP::Errors}, {Rack::LDP::Responses}
|
24
|
-
# and {Rack::LDP::Reousets} as the outer middleware layers. With these in
|
25
|
-
# place, you can handle requests as needed in your application, giving
|
24
|
+
# and {Rack::LDP::Reousets} as the outer middleware layers. With these in
|
25
|
+
# place, you can handle requests as needed in your application, giving
|
26
26
|
# responses conforming to the core {RDF::LDP::Resource} interface.
|
27
27
|
#
|
28
28
|
# @example
|
@@ -33,8 +33,8 @@ module Rack
|
|
33
33
|
# use Rack::LDP::Requests
|
34
34
|
# # ...
|
35
35
|
# end
|
36
|
-
#
|
37
|
-
# @see
|
36
|
+
#
|
37
|
+
# @see https://www.w3.org/TR/ldp/ the LDP specification
|
38
38
|
module LDP
|
39
39
|
##
|
40
40
|
# Catches and handles RequestErrors thrown by RDF::LDP
|
@@ -46,17 +46,15 @@ module Rack
|
|
46
46
|
end
|
47
47
|
|
48
48
|
##
|
49
|
-
# Catches {RDF::LDP::RequestError} and its various subclasses, building an
|
50
|
-
# appropriate response
|
49
|
+
# Catches {RDF::LDP::RequestError} and its various subclasses, building an
|
50
|
+
# appropriate response
|
51
51
|
#
|
52
52
|
# @param [Array] env a rack env array
|
53
53
|
# @return [Array] a rack env array with added headers
|
54
54
|
def call(env)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
return [err.status, err.headers, [err.message]]
|
59
|
-
end
|
55
|
+
@app.call(env)
|
56
|
+
rescue ::RDF::LDP::RequestError => err
|
57
|
+
return [err.status, err.headers, [err.message]]
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
@@ -74,7 +72,7 @@ module Rack
|
|
74
72
|
def call(env)
|
75
73
|
status, headers, response = @app.call(env)
|
76
74
|
|
77
|
-
if response.is_a? RDF::LDP::Resource
|
75
|
+
if response.is_a? ::RDF::LDP::Resource
|
78
76
|
new_response = response.to_response
|
79
77
|
response.close if response.respond_to? :close
|
80
78
|
response = new_response
|
@@ -94,7 +92,7 @@ module Rack
|
|
94
92
|
end
|
95
93
|
|
96
94
|
##
|
97
|
-
# Handles a Rack protocol request. Sends appropriate request to the
|
95
|
+
# Handles a Rack protocol request. Sends appropriate request to the
|
98
96
|
# object, alters response accordingly.
|
99
97
|
#
|
100
98
|
# @param [Array] env a rack env array
|
@@ -102,21 +100,21 @@ module Rack
|
|
102
100
|
def call(env)
|
103
101
|
status, headers, response = @app.call(env)
|
104
102
|
return [status, headers, response] unless
|
105
|
-
response.is_a? RDF::LDP::Resource
|
106
|
-
|
103
|
+
response.is_a? ::RDF::LDP::Resource
|
104
|
+
|
107
105
|
response
|
108
106
|
.send(:request, env['REQUEST_METHOD'].to_sym, status, headers, env)
|
109
107
|
end
|
110
108
|
end
|
111
109
|
|
112
110
|
##
|
113
|
-
# Specializes
|
111
|
+
# Specializes `Rack::LinkedData::ContentNegotiation`, making the default
|
114
112
|
# return type 'text/turtle'.
|
115
113
|
#
|
116
|
-
# @see Rack::LinkedData::ContentNegotiation
|
114
|
+
# @see Rack::LinkedData::ContentNegotiation, making
|
117
115
|
class ContentNegotiation < Rack::LinkedData::ContentNegotiation
|
118
|
-
DEFAULT_PREFIXES =
|
119
|
-
Hash[
|
116
|
+
DEFAULT_PREFIXES =
|
117
|
+
Hash[*::RDF::Vocabulary.map { |v| [v.__prefix__, v.to_uri] }.flatten]
|
120
118
|
.freeze
|
121
119
|
|
122
120
|
def initialize(app, options = {})
|
@@ -126,13 +124,13 @@ module Rack
|
|
126
124
|
end
|
127
125
|
|
128
126
|
##
|
129
|
-
# The default LinkedData Conneg doesn't support wildcard operators. We
|
130
|
-
# patch in support for 'text/*' manually, giving Turtle. This should be
|
127
|
+
# The default LinkedData Conneg doesn't support wildcard operators. We
|
128
|
+
# patch in support for 'text/*' manually, giving Turtle. This should be
|
131
129
|
# considered helpful by LDP clients.
|
132
|
-
#
|
130
|
+
#
|
133
131
|
# @see Rack::LinkedData::ContentNegotiation#find_writer_for_content_type
|
134
132
|
def find_writer_for_content_type(content_type)
|
135
|
-
return [RDF::Writer.for(:ttl), 'text/turtle'] if
|
133
|
+
return [::RDF::Writer.for(:ttl), 'text/turtle'] if
|
136
134
|
content_type == 'text/*'
|
137
135
|
super
|
138
136
|
end
|
data/lib/rdf/ldp/container.rb
CHANGED
@@ -11,12 +11,12 @@ module RDF::LDP
|
|
11
11
|
# Containers will throw errors when attempting to edit them in conflict with
|
12
12
|
# LDP's restrictions on changing containment triples.
|
13
13
|
#
|
14
|
-
# @see
|
14
|
+
# @see https://www.w3.org/TR/ldp/#dfn-linked-data-platform-container definition
|
15
15
|
# of LDP Container
|
16
16
|
class Container < RDFSource
|
17
17
|
##
|
18
18
|
# @return [RDF::URI] uri with lexical representation
|
19
|
-
# '
|
19
|
+
# 'https://www.w3.org/ns/ldp#Container'
|
20
20
|
def self.to_uri
|
21
21
|
RDF::Vocab::LDP.Container
|
22
22
|
end
|
@@ -69,9 +69,10 @@ module RDF::LDP
|
|
69
69
|
# containment triple is completed when the transaction closes; otherwise it
|
70
70
|
# is handled atomically.
|
71
71
|
#
|
72
|
-
# @param [RDF::Term]
|
73
|
-
#
|
74
|
-
#
|
72
|
+
# @param [RDF::Term] resource
|
73
|
+
# a new member for this container
|
74
|
+
# @param transaction [RDF::Transaction] transaction
|
75
|
+
# an active transaction as context for the addition
|
75
76
|
# @return [Container] self
|
76
77
|
def add(resource, transaction = nil)
|
77
78
|
add_containment_triple(resource.to_uri, transaction)
|
@@ -82,12 +83,13 @@ module RDF::LDP
|
|
82
83
|
# membership triples as appropriate for the container type.
|
83
84
|
#
|
84
85
|
# If a transaction is passed as the second argument, the removal of the
|
85
|
-
# containment triple is completed when the transaction closes; otherwise it
|
86
|
-
# handled atomically.
|
86
|
+
# containment triple is completed when the transaction closes; otherwise it
|
87
|
+
# is handled atomically.
|
87
88
|
#
|
88
|
-
# @param [RDF::Term]
|
89
|
-
#
|
90
|
-
#
|
89
|
+
# @param [RDF::Term] resource
|
90
|
+
# a new member for this container
|
91
|
+
# @param transaction [RDF::Transaction] transaction
|
92
|
+
# an active transaction as context for the removal
|
91
93
|
# @return [Container] self
|
92
94
|
def remove(resource, transaction = nil)
|
93
95
|
remove_containment_triple(resource.to_uri, transaction)
|
@@ -140,9 +142,11 @@ module RDF::LDP
|
|
140
142
|
end
|
141
143
|
|
142
144
|
##
|
143
|
-
# @param [RDF::Term]
|
145
|
+
# @param [RDF::Term] resource
|
146
|
+
# a member to be represented in the containment triple
|
144
147
|
#
|
145
|
-
# @return [RDF::URI]
|
148
|
+
# @return [RDF::URI]
|
149
|
+
# the containment triple, with a graph_name pointing
|
146
150
|
# to `#graph`
|
147
151
|
def make_containment_triple(resource)
|
148
152
|
RDF::Statement(subject_uri, CONTAINS_URI, resource,
|
@@ -157,7 +161,7 @@ module RDF::LDP
|
|
157
161
|
|
158
162
|
raise UnsupportedMediaType unless method
|
159
163
|
|
160
|
-
temp_data
|
164
|
+
temp_data = RDF::Repository.new << graph.statements
|
161
165
|
temp_graph = RDF::Graph.new(graph_name: graph.name, data: temp_data)
|
162
166
|
send(method, env['rack.input'], temp_graph)
|
163
167
|
|
@@ -200,33 +204,39 @@ module RDF::LDP
|
|
200
204
|
def validate_triples!(transaction)
|
201
205
|
existing_triples = containment_triples.to_a
|
202
206
|
|
203
|
-
tx_containment = transaction.query(subject: subject_uri,
|
204
|
-
predicate: CONTAINS_URI)
|
207
|
+
tx_containment = transaction.query({subject: subject_uri,
|
208
|
+
predicate: CONTAINS_URI})
|
205
209
|
|
206
210
|
tx_containment.each do |statement|
|
207
|
-
|
208
|
-
|
209
|
-
|
211
|
+
unless existing_triples.include?(statement)
|
212
|
+
raise(Conflict, 'Attempted to write unacceptable LDP ' \
|
213
|
+
"containment-triple: #{statement}")
|
214
|
+
end
|
210
215
|
end
|
211
216
|
|
212
217
|
deletes = existing_triples.reject { |st| tx_containment.include?(st) }
|
218
|
+
|
219
|
+
return if deletes.empty?
|
220
|
+
|
213
221
|
raise(Conflict, 'Cannot remove containment triples in updates. ' \
|
214
|
-
"Attepted to remove #{deletes}")
|
222
|
+
"Attepted to remove #{deletes}")
|
215
223
|
end
|
216
224
|
|
217
225
|
##
|
218
226
|
# supports Patch.
|
219
227
|
def validate_statements!(statements)
|
220
228
|
existing_triples = containment_triples.to_a
|
221
|
-
statements.query(subject: subject_uri, predicate: CONTAINS_URI) do |st|
|
229
|
+
statements.query({subject: subject_uri, predicate: CONTAINS_URI}) do |st|
|
222
230
|
existing_triples.delete(st) do
|
223
231
|
raise(Conflict, 'Attempted to write unacceptable LDP ' \
|
224
232
|
"containment-triple: #{st}")
|
225
233
|
end
|
226
234
|
end
|
235
|
+
|
236
|
+
return if existing_triples.empty?
|
237
|
+
|
227
238
|
raise(Conflict, 'Cannot remove containment triples in updates. ' \
|
228
|
-
"Attepted to remove #{existing_triples}")
|
229
|
-
existing_triples.empty?
|
239
|
+
"Attepted to remove #{existing_triples}")
|
230
240
|
end
|
231
241
|
end
|
232
242
|
end
|
@@ -15,7 +15,7 @@ module RDF::LDP
|
|
15
15
|
# If more than one of either is given, all `#add/#remove` (POST/DELETE)
|
16
16
|
# requests will fail.
|
17
17
|
#
|
18
|
-
# @see
|
18
|
+
# @see https://www.w3.org/TR/ldp/#dfn-linked-data-platform-direct-container
|
19
19
|
# definition of LDP Direct Container
|
20
20
|
class DirectContainer < Container
|
21
21
|
MEMBER_URI = RDF::Vocab::LDP.member.freeze
|
@@ -65,7 +65,8 @@ module RDF::LDP
|
|
65
65
|
#
|
66
66
|
# @see RDF::LDP::Container#add
|
67
67
|
def add(resource, transaction = nil)
|
68
|
-
process_membership_resource(resource,
|
68
|
+
process_membership_resource(resource,
|
69
|
+
transaction) do |container, quad, subject|
|
69
70
|
super(subject, transaction) # super handles nil transaction case
|
70
71
|
target = transaction || container.graph
|
71
72
|
target.insert(quad)
|
@@ -79,7 +80,8 @@ module RDF::LDP
|
|
79
80
|
#
|
80
81
|
# @see RDF::LDP::Container#remove
|
81
82
|
def remove(resource, transaction = nil)
|
82
|
-
process_membership_resource(resource,
|
83
|
+
process_membership_resource(resource,
|
84
|
+
transaction) do |container, quad, subject|
|
83
85
|
super(subject, transaction) # super handles nil transaction case
|
84
86
|
target = transaction || container.graph
|
85
87
|
target.delete(quad)
|
@@ -96,7 +98,7 @@ module RDF::LDP
|
|
96
98
|
# @raise [RDF::LDP::NotAcceptable] if multiple membership constant uris
|
97
99
|
# exist
|
98
100
|
#
|
99
|
-
# @see
|
101
|
+
# @see https://www.w3.org/TR/ldp/#dfn-membership-triples
|
100
102
|
def membership_constant_uri
|
101
103
|
statements = membership_resource_statements
|
102
104
|
return statements.first.object if statements.count == 1
|
@@ -113,7 +115,7 @@ module RDF::LDP
|
|
113
115
|
#
|
114
116
|
# @raise [RDF::LDP::NotAcceptable] if multiple membership predicates exist
|
115
117
|
#
|
116
|
-
# @see
|
118
|
+
# @see https://www.w3.org/TR/ldp/#dfn-membership-predicate
|
117
119
|
def membership_predicate
|
118
120
|
statements = member_relation_statements
|
119
121
|
return statements.first.object if statements.count == 1
|
@@ -128,7 +130,7 @@ module RDF::LDP
|
|
128
130
|
# @return [RDF::URI] the membership triple representing membership of the
|
129
131
|
# `resource` parameter in this container
|
130
132
|
#
|
131
|
-
# @see
|
133
|
+
# @see https://www.w3.org/TR/ldp/#dfn-membership-triples
|
132
134
|
def make_membership_triple(resource)
|
133
135
|
predicate = membership_predicate
|
134
136
|
return RDF::Statement(membership_constant_uri, predicate, resource) if
|
@@ -156,7 +158,7 @@ module RDF::LDP
|
|
156
158
|
resource
|
157
159
|
end
|
158
160
|
|
159
|
-
def process_membership_resource(resource,
|
161
|
+
def process_membership_resource(resource, _transaction = nil, member = nil)
|
160
162
|
membership_triple = make_membership_triple((member || resource).to_uri)
|
161
163
|
|
162
164
|
membership_triple.graph_name = subject_uri
|