rdf-ldp 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +0 -2
- data/VERSION +1 -1
- data/app/lamprey.rb +54 -0
- data/bin/lamprey +0 -4
- data/lib/rack/ldp.rb +27 -7
- data/lib/rdf/ldp/container.rb +96 -25
- data/lib/rdf/ldp/direct_container.rb +16 -12
- data/lib/rdf/ldp/non_rdf_source.rb +3 -6
- data/lib/rdf/ldp/rdf_source.rb +87 -79
- data/lib/rdf/ldp/resource.rb +186 -22
- metadata +68 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54ea7ba54f7ff921a5670547db56d81fcfc686ed
|
4
|
+
data.tar.gz: 3dfdbb9baa8e06b2e8ce34ef3c5f5c99f6af3a38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0df494fa4d14ffe6ccc5533bd042b567e9d5a166e35af5b4b759af9e738b486eac010f3eee40e5e2abdd3b0bcf6087f624b6b80756a575157498b5482a0e2d97
|
7
|
+
data.tar.gz: 8d69b716de23c7cf1a08d83e2b6620770d561c3aa4bfa43bf29a4024d74b60442c7fc19d58d4c8daf0b65e2d95502789d86fec192dad677b96c5576833c3ed51
|
data/README.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/app/lamprey.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rack/ldp'
|
2
|
+
require 'sinatra/base'
|
3
|
+
|
4
|
+
class RDF::Lamprey < Sinatra::Base
|
5
|
+
|
6
|
+
use Rack::LDP::ContentNegotiation
|
7
|
+
use Rack::LDP::Errors
|
8
|
+
use Rack::LDP::Responses
|
9
|
+
use Rack::ConditionalGet
|
10
|
+
use Rack::LDP::Requests
|
11
|
+
|
12
|
+
# Set defaults in case user has not configured values
|
13
|
+
configure do
|
14
|
+
set :repository, RDF::Repository.new
|
15
|
+
end
|
16
|
+
|
17
|
+
get '/*' do
|
18
|
+
RDF::LDP::Container.new(RDF::URI(request.url), settings.repository)
|
19
|
+
.create('', 'text/turtle') if settings.repository.empty?
|
20
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
21
|
+
end
|
22
|
+
|
23
|
+
patch '/*' do
|
24
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
25
|
+
end
|
26
|
+
|
27
|
+
post '/*' do
|
28
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
29
|
+
end
|
30
|
+
|
31
|
+
put '/*' do
|
32
|
+
begin
|
33
|
+
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
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
options '/*' do
|
42
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
43
|
+
end
|
44
|
+
|
45
|
+
head '/*' do
|
46
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
47
|
+
end
|
48
|
+
|
49
|
+
delete '/*' do
|
50
|
+
RDF::LDP::Resource.find(RDF::URI(request.url), settings.repository)
|
51
|
+
end
|
52
|
+
|
53
|
+
run! if app_file == $0
|
54
|
+
end
|
data/bin/lamprey
CHANGED
data/lib/rack/ldp.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rack'
|
2
2
|
begin
|
3
3
|
require 'linkeddata'
|
4
|
-
rescue LoadError
|
4
|
+
rescue LoadError
|
5
5
|
require 'rdf/turtle'
|
6
6
|
require 'json/ld'
|
7
7
|
end
|
@@ -11,7 +11,7 @@ require 'rdf/ldp'
|
|
11
11
|
|
12
12
|
module Rack
|
13
13
|
##
|
14
|
-
# Provides Rack middleware for handling Linked Data Platform
|
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
17
|
# Response objects that are not an {RDF::LDP::Resource} are passed over
|
@@ -20,16 +20,17 @@ module Rack
|
|
20
20
|
#
|
21
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
|
-
# {Rack::LDP::ContentNegotiation}, {Rack::LDP::Errors},
|
24
|
-
# {Rack::LDP::
|
25
|
-
# you can handle requests as needed in your application, giving
|
26
|
-
# conforming to the core {RDF::LDP::Resource} interface.
|
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
|
26
|
+
# responses conforming to the core {RDF::LDP::Resource} interface.
|
27
27
|
#
|
28
28
|
# @example
|
29
29
|
# run Rack:;Builder.new do
|
30
30
|
# use Rack::LDP::ContentNegotiation
|
31
31
|
# use Rack::LDP::Errors
|
32
32
|
# use Rack::LDP::Responses
|
33
|
+
# use Rack::LDP::Requests
|
33
34
|
# # ...
|
34
35
|
# end
|
35
36
|
#
|
@@ -110,10 +111,29 @@ module Rack
|
|
110
111
|
|
111
112
|
##
|
112
113
|
# Specializes {Rack::LinkedData::ContentNegotiation}, making the default
|
113
|
-
# return type 'text/turtle'
|
114
|
+
# return type 'text/turtle'.
|
115
|
+
#
|
116
|
+
# @see Rack::LinkedData::ContentNegotiation}, making
|
114
117
|
class ContentNegotiation < Rack::LinkedData::ContentNegotiation
|
118
|
+
DEFAULT_PREFIXES =
|
119
|
+
Hash[*RDF::Vocabulary.map { |v| [v.__prefix__, v.to_uri] }.flatten]
|
120
|
+
.freeze
|
121
|
+
|
115
122
|
def initialize(app, options = {})
|
116
123
|
options[:default] ||= 'text/turtle'
|
124
|
+
options[:prefixes] ||= DEFAULT_PREFIXES.dup
|
125
|
+
super
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# The default LinkedData Conneg doesn't support wildcard operators. We
|
130
|
+
# patch in support for 'text/*' manually, giving Turtle. This should be
|
131
|
+
# considered helpful by LDP clients.
|
132
|
+
#
|
133
|
+
# @see Rack::LinkedData::ContentNegotiation#find_writer_for_content_type
|
134
|
+
def find_writer_for_content_type(content_type)
|
135
|
+
return [RDF::Writer.for(:ttl), 'text/turtle'] if
|
136
|
+
content_type == 'text/*'
|
117
137
|
super
|
118
138
|
end
|
119
139
|
end
|
data/lib/rdf/ldp/container.rb
CHANGED
@@ -34,35 +34,63 @@ module RDF::LDP
|
|
34
34
|
end
|
35
35
|
|
36
36
|
##
|
37
|
+
# Create with validation as required for the LDP container.
|
38
|
+
#
|
39
|
+
# @raise [RDF::LDP::Conflict] if the create inserts triples that are not
|
40
|
+
# allowed by LDP for the container type
|
37
41
|
# @see RDFSource#create
|
38
|
-
def create(input, content_type)
|
39
|
-
super
|
42
|
+
def create(input, content_type, &block)
|
43
|
+
super do |transaction|
|
44
|
+
validate_triples!(transaction)
|
45
|
+
yield transaction if block_given?
|
46
|
+
end
|
47
|
+
self
|
40
48
|
end
|
41
49
|
|
42
50
|
##
|
51
|
+
# Updates with validation as required for the LDP container.
|
52
|
+
#
|
53
|
+
# @raise [RDF::LDP::Conflict] if the update edits triples that are not
|
54
|
+
# allowed by LDP for the container type
|
43
55
|
# @see RDFSource#update
|
44
|
-
def update(input, content_type)
|
45
|
-
super
|
56
|
+
def update(input, content_type, &block)
|
57
|
+
super do |transaction|
|
58
|
+
validate_triples!(transaction)
|
59
|
+
yield transaction if block_given?
|
60
|
+
end
|
61
|
+
self
|
46
62
|
end
|
47
63
|
|
48
64
|
##
|
49
65
|
# Adds a member `resource` to the container. Handles containment and
|
50
66
|
# membership triples as appropriate for the container type.
|
51
67
|
#
|
68
|
+
# If a transaction is passed as the second argument, the additon of the
|
69
|
+
# containment triple is completed when the transaction closes; otherwise it is
|
70
|
+
# handled atomically.
|
71
|
+
#
|
52
72
|
# @param [RDF::Term] a new member for this container
|
73
|
+
# @param transaction [RDF::Transaction] an active transaction as context for
|
74
|
+
# the addition
|
53
75
|
# @return [Container] self
|
54
|
-
def add(resource)
|
55
|
-
add_containment_triple(resource.to_uri)
|
76
|
+
def add(resource, transaction = nil)
|
77
|
+
add_containment_triple(resource.to_uri, transaction)
|
56
78
|
end
|
57
79
|
|
58
80
|
##
|
59
81
|
# Removes a member `resource` from the container. Handles containment and
|
60
82
|
# membership triples as appropriate for the container type.
|
61
83
|
#
|
84
|
+
# If a transaction is passed as the second argument, the removal of the
|
85
|
+
# containment triple is completed when the transaction closes; otherwise it is
|
86
|
+
# handled atomically.
|
87
|
+
#
|
62
88
|
# @param [RDF::Term] a new member for this container
|
89
|
+
# @param transaction [RDF::Transaction] an active transaction as context for
|
90
|
+
# the removal
|
63
91
|
# @return [Container] self
|
64
|
-
def remove(resource)
|
65
|
-
remove_containment_triple(resource.to_uri)
|
92
|
+
def remove(resource, transaction = nil)
|
93
|
+
remove_containment_triple(resource.to_uri, transaction)
|
66
94
|
end
|
67
95
|
|
68
96
|
##
|
@@ -77,39 +105,50 @@ module RDF::LDP
|
|
77
105
|
# @param [RDF::Statement] statement
|
78
106
|
#
|
79
107
|
# @return [Boolean] true if the containment triple exists
|
80
|
-
#
|
81
|
-
# @todo for some reason `#include?` doesn't work! figure out why, this is
|
82
|
-
# clumsy.
|
83
108
|
def has_containment_triple?(statement)
|
84
|
-
!(containment_triples.
|
109
|
+
!(containment_triples.find { |t| statement == t }.nil?)
|
85
110
|
end
|
86
111
|
|
87
112
|
##
|
88
113
|
# Adds a containment triple for `resource` to the container's `#graph`.
|
89
114
|
#
|
90
|
-
#
|
115
|
+
# If a transaction is passed as the second argument, the triple is added to
|
116
|
+
# the transaction's inserts; otherwise it is added directly to `#graph`.
|
117
|
+
#
|
118
|
+
# @param resource [RDF::Term] a new member for this container
|
119
|
+
# @param transaction [RDF::Transaction]
|
91
120
|
# @return [Container] self
|
92
|
-
def add_containment_triple(resource)
|
93
|
-
|
121
|
+
def add_containment_triple(resource, transaction = nil)
|
122
|
+
target = transaction || graph
|
123
|
+
target << make_containment_triple(resource)
|
124
|
+
set_last_modified(transaction)
|
94
125
|
self
|
95
126
|
end
|
96
127
|
|
97
128
|
##
|
98
129
|
# Remove a containment triple for `resource` to the container's `#graph`.
|
99
130
|
#
|
100
|
-
#
|
131
|
+
# If a transaction is passed as the second argument, the triple is added to
|
132
|
+
# the transaction's deletes; otherwise it is deleted directly from `#graph`.
|
133
|
+
#
|
134
|
+
# @param resource [RDF::Term] a member to remove from this container
|
135
|
+
# @param transaction [RDF::Transaction]
|
101
136
|
# @return [Container] self
|
102
|
-
def remove_containment_triple(resource)
|
103
|
-
graph
|
137
|
+
def remove_containment_triple(resource, transaction = nil)
|
138
|
+
target = transaction || graph
|
139
|
+
target.delete(make_containment_triple(resource))
|
140
|
+
set_last_modified(transaction)
|
104
141
|
self
|
105
142
|
end
|
106
143
|
|
107
144
|
##
|
108
|
-
# @param [RDF::Term] a member
|
145
|
+
# @param [RDF::Term] a member to be represented in the containment triple
|
109
146
|
#
|
110
|
-
# @return [RDF::URI] the containment triple
|
147
|
+
# @return [RDF::URI] the containment triple, with a graph_name pointing
|
148
|
+
# to `#graph`
|
111
149
|
def make_containment_triple(resource)
|
112
|
-
RDF::Statement(subject_uri, RDF::Vocab::LDP.contains, resource
|
150
|
+
RDF::Statement(subject_uri, RDF::Vocab::LDP.contains, resource,
|
151
|
+
graph_name: subject_uri)
|
113
152
|
end
|
114
153
|
|
115
154
|
private
|
@@ -123,10 +162,11 @@ module RDF::LDP
|
|
123
162
|
temp_graph = RDF::Graph.new << graph.statements
|
124
163
|
send(method, env['rack.input'], temp_graph)
|
125
164
|
|
126
|
-
|
165
|
+
validate_statements!(temp_graph)
|
127
166
|
graph.clear!
|
128
167
|
graph << temp_graph.statements
|
129
168
|
|
169
|
+
set_last_modified
|
130
170
|
[200, update_headers(headers), self]
|
131
171
|
end
|
132
172
|
|
@@ -149,14 +189,45 @@ module RDF::LDP
|
|
149
189
|
id = (subject_uri / slug).canonicalize
|
150
190
|
|
151
191
|
created = klass.new(id, @data)
|
152
|
-
|
192
|
+
|
193
|
+
created.create(env['rack.input'], env['CONTENT_TYPE']) do |transaction|
|
194
|
+
add(created, transaction)
|
195
|
+
end
|
153
196
|
|
154
|
-
add(created)
|
155
197
|
headers['Location'] = created.subject_uri.to_s
|
156
198
|
[201, created.send(:update_headers, headers), created]
|
157
199
|
end
|
158
200
|
|
159
|
-
def validate_triples!(
|
201
|
+
def validate_triples!(transaction)
|
202
|
+
existing_triples = containment_triples.to_a
|
203
|
+
|
204
|
+
inserts = transaction.inserts.select do |st|
|
205
|
+
st.subject == subject_uri && st.predicate == RDF::Vocab::LDP.contains
|
206
|
+
end
|
207
|
+
|
208
|
+
inserts.each do |statement|
|
209
|
+
existing_triples.delete(statement) do
|
210
|
+
raise Conflict.new('Attempted to write unacceptable LDP ' \
|
211
|
+
"containment-triple: #{statement}")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
deletes = transaction.deletes.select do |st|
|
216
|
+
st.subject == subject_uri &&
|
217
|
+
predicate == RDF::Vocab::LDP.contains &&
|
218
|
+
!inserts.include?(st)
|
219
|
+
end
|
220
|
+
|
221
|
+
deletes = deletes + existing_triples
|
222
|
+
|
223
|
+
raise Conflict.new('Cannot remove containment triples in updates. ' \
|
224
|
+
"Attepted to remove #{deletes}") unless
|
225
|
+
deletes.empty?
|
226
|
+
end
|
227
|
+
|
228
|
+
##
|
229
|
+
# supports Patch.
|
230
|
+
def validate_statements!(statements)
|
160
231
|
existing_triples = containment_triples.to_a
|
161
232
|
statements.query(subject: subject_uri,
|
162
233
|
predicate: RDF::Vocab::LDP.contains) do |statement|
|
@@ -36,11 +36,14 @@ module RDF::LDP
|
|
36
36
|
# membership triple to the memebership resource.
|
37
37
|
#
|
38
38
|
# @see RDF::LDP::Container#add
|
39
|
-
def add(resource)
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
def add(resource, transaction = nil)
|
40
|
+
target = transaction || graph
|
41
|
+
process_membership_resource(resource) do |membership, quad, resource|
|
42
|
+
super(resource, transaction)
|
43
|
+
target = transaction || membership.graph
|
44
|
+
target << quad
|
43
45
|
end
|
46
|
+
self
|
44
47
|
end
|
45
48
|
|
46
49
|
##
|
@@ -48,11 +51,13 @@ module RDF::LDP
|
|
48
51
|
# removes membership triple to the memebership resource.
|
49
52
|
#
|
50
53
|
# @see RDF::LDP::Container#remove
|
51
|
-
def remove(resource)
|
52
|
-
process_membership_resource(resource) do |membership,
|
53
|
-
super
|
54
|
-
membership.graph
|
54
|
+
def remove(resource, transaction = nil)
|
55
|
+
process_membership_resource(resource) do |membership, quad, resource|
|
56
|
+
super(resource, transaction)
|
57
|
+
target = transaction || membership.graph
|
58
|
+
target.delete(quad)
|
55
59
|
end
|
60
|
+
self
|
56
61
|
end
|
57
62
|
|
58
63
|
##
|
@@ -142,7 +147,7 @@ module RDF::LDP
|
|
142
147
|
end
|
143
148
|
|
144
149
|
def process_membership_resource(resource, &block)
|
145
|
-
|
150
|
+
statement = make_membership_triple(resource.to_uri)
|
146
151
|
|
147
152
|
begin
|
148
153
|
membership_rs = membership_resource
|
@@ -151,9 +156,8 @@ module RDF::LDP
|
|
151
156
|
"#{membership_constant_uri} does not exist")
|
152
157
|
end
|
153
158
|
|
154
|
-
|
155
|
-
|
156
|
-
self
|
159
|
+
statement.graph_name = membership_rs.subject_uri
|
160
|
+
yield(membership_rs, statement, resource) if block_given?
|
157
161
|
end
|
158
162
|
end
|
159
163
|
end
|
@@ -17,7 +17,7 @@ module RDF::LDP
|
|
17
17
|
# a definition of NonRDFSource in LDP
|
18
18
|
class NonRDFSource < Resource
|
19
19
|
# Use DC elements format
|
20
|
-
FORMAT_TERM = RDF::DC11.format
|
20
|
+
FORMAT_TERM = RDF::Vocab::DC11.format
|
21
21
|
DESCRIBED_BY_TERM = RDF::URI('http://www.w3.org/2007/05/powder-s#describedby')
|
22
22
|
|
23
23
|
##
|
@@ -50,7 +50,7 @@ module RDF::LDP
|
|
50
50
|
storage.io { |io| IO.copy_stream(input.binmode, io) }
|
51
51
|
super
|
52
52
|
self.content_type = c_type
|
53
|
-
RDFSource.new(description_uri, @data).create('', '
|
53
|
+
RDFSource.new(description_uri, @data).create('', 'application/n-triples')
|
54
54
|
self
|
55
55
|
end
|
56
56
|
|
@@ -58,6 +58,7 @@ module RDF::LDP
|
|
58
58
|
# @see RDF::LDP::Resource#update
|
59
59
|
def update(input, c_type)
|
60
60
|
storage.io { |io| IO.copy_stream(input.binmode, io) }
|
61
|
+
super
|
61
62
|
self.content_type = c_type
|
62
63
|
self
|
63
64
|
end
|
@@ -72,10 +73,6 @@ module RDF::LDP
|
|
72
73
|
super
|
73
74
|
end
|
74
75
|
|
75
|
-
def etag
|
76
|
-
"#{Digest::SHA1.base64digest(storage.io.read)}"
|
77
|
-
end
|
78
|
-
|
79
76
|
##
|
80
77
|
# @raise [RDF::LDP::NotFound] if the describedby resource doesn't exist
|
81
78
|
#
|
data/lib/rdf/ldp/rdf_source.rb
CHANGED
@@ -9,25 +9,26 @@ module RDF::LDP
|
|
9
9
|
# - a `#graph` representing the "entire persistent state"
|
10
10
|
# - a `#metagraph` containing internal properties of the RDFSource
|
11
11
|
#
|
12
|
-
#
|
13
|
-
# `#metagraph` accurately and separately (e.g
|
14
|
-
# named graphs).
|
15
|
-
#
|
16
|
-
#
|
12
|
+
# Repository implementations must be able to reconstruct both `#graph` and
|
13
|
+
# `#metagraph` accurately and separately (e.g., by saving them as distinct
|
14
|
+
# named graphs).
|
15
|
+
#
|
16
|
+
# The implementations of `#create` and `#update` in `RDF::LDP::Resource` are
|
17
|
+
# overloaded to handle the edits to `#graph` within the same transaction as
|
18
|
+
# the base `#metagraph` updates. `#to_response` is overloaded to return an
|
19
|
+
# unnamed `RDF::Graph`, to be transformed into an HTTP Body by
|
20
|
+
# `Rack::LDP::ContentNegotiation`.
|
17
21
|
#
|
18
|
-
#
|
19
|
-
# LDP-server-managed triples. `#metagraph` contains
|
20
|
-
#
|
21
|
-
#
|
22
|
+
# @note the contents of `#metagraph`'s are *not* the same as
|
23
|
+
# LDP-server-managed triples. `#metagraph` contains internal properties of the
|
24
|
+
# RDFSource which are necessary for the server's management purposes, but MAY
|
25
|
+
# be absent from (or in conflict with) the representation of its state in
|
26
|
+
# `#graph`.
|
22
27
|
#
|
23
28
|
# @see http://www.w3.org/TR/ldp/#dfn-linked-data-platform-rdf-source definition
|
24
29
|
# of ldp:RDFSource in the LDP specification
|
25
30
|
class RDFSource < Resource
|
26
31
|
|
27
|
-
# @!attribute [rw] graph
|
28
|
-
# a graph representing the current persistent state of the resource.
|
29
|
-
attr_accessor :graph
|
30
|
-
|
31
32
|
class << self
|
32
33
|
##
|
33
34
|
# @return [RDF::URI] uri with lexical representation
|
@@ -42,22 +43,50 @@ module RDF::LDP
|
|
42
43
|
##
|
43
44
|
# @see RDF::LDP::Resource#initialize
|
44
45
|
def initialize(subject_uri, data = RDF::Repository.new)
|
45
|
-
@
|
46
|
+
@subject_uri = subject_uri
|
47
|
+
@data = data
|
46
48
|
super
|
47
49
|
self
|
48
50
|
end
|
49
51
|
|
52
|
+
##
|
53
|
+
# @return [RDF::Graph] a graph representing the current persistent state of
|
54
|
+
# the resource.
|
55
|
+
def graph
|
56
|
+
@graph ||= RDF::Graph.new(@subject_uri, data: @data)
|
57
|
+
end
|
58
|
+
|
50
59
|
##
|
51
60
|
# Creates the RDFSource, populating its graph from the input given
|
52
61
|
#
|
62
|
+
# @example
|
63
|
+
# repository = RDF::Repository.new
|
64
|
+
# ldprs = RDF::LDP::RDFSource.new('http://example.org/moomin', repository)
|
65
|
+
# ldprs.create('<http://ex.org/1> <http://ex.org/prop> "moomin" .', 'text/turtle')
|
66
|
+
#
|
53
67
|
# @param [IO, File, #to_s] input input (usually from a Rack env's
|
54
68
|
# `rack.input` key) used to determine the Resource's initial state.
|
55
69
|
# @param [#to_s] content_type a MIME content_type used to read the graph.
|
56
70
|
#
|
57
|
-
# @yield gives
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
71
|
+
# @yield gives an in-progress transaction (changeset) to collect changes to
|
72
|
+
# graph, metagraph and other resources' (e.g. containers) graphs.
|
73
|
+
# @yieldparam tx [RDF::Transaction] a transaction targeting `#graph` as the
|
74
|
+
# default graph name
|
75
|
+
#
|
76
|
+
# @example altering changes before execution with block syntax
|
77
|
+
# content = '<http://ex.org/1> <http://ex.org/prop> "moomin" .'
|
78
|
+
#
|
79
|
+
# ldprs.create(content, 'text/turtle') do |tx|
|
80
|
+
# tx.insert([RDF::URI('s'), RDF::URI('p'), 'custom'])
|
81
|
+
# tx.insert([RDF::URI('s'), RDF::URI('p'), 'custom', RDF::URI('g')])
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# @example validating changes before execution with block syntax
|
85
|
+
# content = '<http://ex.org/1> <http://ex.org/prop> "moomin" .'
|
86
|
+
#
|
87
|
+
# ldprs.create(content, 'text/turtle') do |tx|
|
88
|
+
# raise "cannot delete triples on create!" unless tx.deletes.empty?
|
89
|
+
# end
|
61
90
|
#
|
62
91
|
# @raise [RDF::LDP::RequestError]
|
63
92
|
# @raise [RDF::LDP::UnsupportedMediaType] if no reader can be found for the
|
@@ -68,11 +97,12 @@ module RDF::LDP
|
|
68
97
|
#
|
69
98
|
# @return [RDF::LDP::Resource] self
|
70
99
|
def create(input, content_type, &block)
|
71
|
-
super
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
100
|
+
super do |transaction|
|
101
|
+
transaction.graph_name = subject_uri
|
102
|
+
statements = parse_graph(input, content_type)
|
103
|
+
transaction << statements
|
104
|
+
yield transaction if block_given?
|
105
|
+
end
|
76
106
|
end
|
77
107
|
|
78
108
|
##
|
@@ -84,10 +114,18 @@ module RDF::LDP
|
|
84
114
|
# @param [#to_s] content_type a MIME content_type used to interpret the
|
85
115
|
# input.
|
86
116
|
#
|
87
|
-
# @yield gives
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
117
|
+
# @yield gives an in-progress transaction (changeset) to collect changes to
|
118
|
+
# graph, metagraph and other resources' (e.g. containers) graphs.
|
119
|
+
# @yieldparam tx [RDF::Transaction] a transaction targeting `#graph` as the
|
120
|
+
# default graph name
|
121
|
+
#
|
122
|
+
# @example altering changes before execution with block syntax
|
123
|
+
# content = '<http://ex.org/1> <http://ex.org/prop> "moomin" .'
|
124
|
+
#
|
125
|
+
# ldprs.update(content, 'text/turtle') do |tx|
|
126
|
+
# tx.insert([RDF::URI('s'), RDF::URI('p'), 'custom'])
|
127
|
+
# tx.insert([RDF::URI('s'), RDF::URI('p'), 'custom', RDF::URI('g')])
|
128
|
+
# end
|
91
129
|
#
|
92
130
|
# @raise [RDF::LDP::RequestError]
|
93
131
|
# @raise [RDF::LDP::UnsupportedMediaType] if no reader can be found for the
|
@@ -95,11 +133,13 @@ module RDF::LDP
|
|
95
133
|
#
|
96
134
|
# @return [RDF::LDP::Resource] self
|
97
135
|
def update(input, content_type, &block)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
136
|
+
super do |transaction|
|
137
|
+
transaction.graph_name = subject_uri
|
138
|
+
transaction << parse_graph(input, content_type)
|
139
|
+
yield transaction if block_given?
|
140
|
+
graph.clear
|
141
|
+
end
|
142
|
+
|
103
143
|
self
|
104
144
|
end
|
105
145
|
|
@@ -107,42 +147,12 @@ module RDF::LDP
|
|
107
147
|
# Clears the graph and marks as destroyed.
|
108
148
|
#
|
109
149
|
# @see RDF::LDP::Resource#destroy
|
110
|
-
def destroy
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
##
|
116
|
-
# Returns an Etag. This may be a strong or a weak ETag.
|
117
|
-
#
|
118
|
-
# @return [String] an HTTP Etag
|
119
|
-
#
|
120
|
-
# @note the current implementation is a naive one that combines a couple of
|
121
|
-
# blunt heurisitics.
|
122
|
-
#
|
123
|
-
# @todo add an efficient hash function for RDF Graphs to RDF.rb and use that
|
124
|
-
# here?
|
125
|
-
#
|
126
|
-
# @see http://ceur-ws.org/Vol-1259/proceedings.pdf#page=65 for a recent
|
127
|
-
# treatment of digests for RDF graphs
|
128
|
-
#
|
129
|
-
# @see http://www.w3.org/TR/ldp#h-ldpr-gen-etags LDP ETag clause for GET
|
130
|
-
# @see http://www.w3.org/TR/ldp#h-ldpr-put-precond LDP ETag clause for PUT
|
131
|
-
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3
|
132
|
-
# description of strong vs. weak validators
|
133
|
-
def etag
|
134
|
-
subs = graph.subjects.map { |s| s.node? ? nil : s.to_s }
|
135
|
-
.compact.sort.join()
|
136
|
-
"\"#{Digest::SHA1.base64digest(subs)}#{graph.statements.count}\""
|
150
|
+
def destroy(&block)
|
151
|
+
super do |_|
|
152
|
+
graph.clear
|
153
|
+
end
|
137
154
|
end
|
138
155
|
|
139
|
-
##
|
140
|
-
# @param [String] tag a tag to compare to `#etag`
|
141
|
-
# @return [Boolean] whether the given tag matches `#etag`
|
142
|
-
# def match?(tag)
|
143
|
-
# return false unless tag.split('==').last == graph.statements.count.to_s
|
144
|
-
# end
|
145
|
-
|
146
156
|
##
|
147
157
|
# @return [Boolean] whether this is an ldp:RDFSource
|
148
158
|
def rdf_source?
|
@@ -161,6 +171,8 @@ module RDF::LDP
|
|
161
171
|
##
|
162
172
|
# Process & generate response for PUT requsets.
|
163
173
|
#
|
174
|
+
# @note patch is currently not transactional.
|
175
|
+
#
|
164
176
|
# @raise [RDF::LDP::UnsupportedMediaType] when a media type other than
|
165
177
|
# LDPatch is used
|
166
178
|
# @raise [RDF::LDP::BadRequest] when an invalid document is given
|
@@ -171,6 +183,7 @@ module RDF::LDP
|
|
171
183
|
raise UnsupportedMediaType unless method
|
172
184
|
|
173
185
|
send(method, env['rack.input'], graph)
|
186
|
+
set_last_modified
|
174
187
|
[200, update_headers(headers), self]
|
175
188
|
end
|
176
189
|
|
@@ -182,20 +195,16 @@ module RDF::LDP
|
|
182
195
|
'application/sparql-update' => :sparql_update }
|
183
196
|
end
|
184
197
|
|
185
|
-
def ld_patch(input, graph)
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
raise BadRequest, e.message
|
190
|
-
end
|
198
|
+
def ld_patch(input, graph, &block)
|
199
|
+
LD::Patch.parse(input).execute(graph)
|
200
|
+
rescue LD::Patch::Error => e
|
201
|
+
raise BadRequest, e.message
|
191
202
|
end
|
192
203
|
|
193
204
|
def sparql_update(input, graph)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
raise BadRequest, e.message
|
198
|
-
end
|
205
|
+
SPARQL.execute(input, graph, update: true)
|
206
|
+
rescue SPARQL::MalformedQuery => e
|
207
|
+
raise BadRequest, e.message
|
199
208
|
end
|
200
209
|
|
201
210
|
##
|
@@ -221,7 +230,6 @@ module RDF::LDP
|
|
221
230
|
env.has_key?('HTTP_IF_MATCH') && !match?(env['HTTP_IF_MATCH'])
|
222
231
|
end
|
223
232
|
|
224
|
-
|
225
233
|
##
|
226
234
|
# Finds an {RDF::Reader} appropriate for the given content_type and attempts
|
227
235
|
# to parse the graph string.
|
@@ -244,7 +252,7 @@ module RDF::LDP
|
|
244
252
|
raise(RDF::LDP::UnsupportedMediaType, content_type) if reader.nil?
|
245
253
|
input = input.read if input.respond_to? :read
|
246
254
|
begin
|
247
|
-
RDF::Graph.new << reader.new(input, base_uri: subject_uri)
|
255
|
+
RDF::Graph.new << reader.new(input, base_uri: subject_uri, validate: true)
|
248
256
|
rescue RDF::ReaderError => e
|
249
257
|
raise RDF::LDP::BadRequest, e.message
|
250
258
|
end
|
data/lib/rdf/ldp/resource.rb
CHANGED
@@ -19,14 +19,15 @@ module RDF::LDP
|
|
19
19
|
# from, and may conflict with, other RDF and non-RDF information about the
|
20
20
|
# resource (e.g. representations suitable for a response body). Metagraph
|
21
21
|
# contains a canonical `rdf:type` statement, which specifies the resource's
|
22
|
-
# interaction model
|
23
|
-
# indicates
|
22
|
+
# interaction model and a (dcterms:modified) last-modified date. If the
|
23
|
+
# resource is deleted, a (prov:invalidatedAt) flag in metagraph indicates
|
24
|
+
# this.
|
24
25
|
#
|
25
26
|
# The contents of `#metagraph` should not be confused with LDP
|
26
27
|
# server-managed-triples, Those triples are included in the state of the
|
27
28
|
# resource as represented by the response body. `#metagraph` is invisible to
|
28
29
|
# the client except where a subclass mirrors its contents in the body.
|
29
|
-
#
|
30
|
+
#
|
30
31
|
# @example creating a new Resource
|
31
32
|
# repository = RDF::Repository.new
|
32
33
|
# resource = RDF::LDP::Resource.new('http://example.org/moomin', repository)
|
@@ -36,14 +37,55 @@ module RDF::LDP
|
|
36
37
|
#
|
37
38
|
# resource.exists? # => true
|
38
39
|
# resource.metagraph.dump :ttl
|
39
|
-
# # => "<http://example.org/moomin> a <http://www.w3.org/ns/ldp#Resource
|
40
|
+
# # => "<http://example.org/moomin> a <http://www.w3.org/ns/ldp#Resource>;
|
41
|
+
# <http://purl.org/dc/terms/modified> "2015-10-25T14:24:56-07:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> ."
|
42
|
+
#
|
43
|
+
# @example updating a Resource updates the `#last_modified` date
|
44
|
+
# resource.last_modified
|
45
|
+
# # => #<DateTime: 2015-10-25T14:32:01-07:00 ((2457321j,77521s,571858283n),-25200s,2299161j)>
|
46
|
+
# resource.update('blah', 'text/plain')
|
47
|
+
# resource.last_modified
|
48
|
+
# # => #<DateTime: 2015-10-25T14:32:04-07:00 ((2457321j,77524s,330658065n),-25200s,2299161j)>
|
49
|
+
#
|
50
|
+
# @example destroying a Resource
|
51
|
+
# resource.exists? # => true
|
52
|
+
# resource.destroyed? # => false
|
53
|
+
#
|
54
|
+
# resource.destroy
|
55
|
+
#
|
56
|
+
# resource.exists? # => true
|
57
|
+
# resource.destroyed? # => true
|
58
|
+
#
|
59
|
+
# Rack (via `RDF::LDP::Rack`) uses the `#request` method to dispatch requests and
|
60
|
+
# interpret responses. Disallowed HTTP methods result in
|
61
|
+
# `RDF::LDP::MethodNotAllowed`. Individual Resources populate `Link`, `Allow`,
|
62
|
+
# `ETag`, `Last-Modified`, and `Accept-*` headers as required by LDP. All
|
63
|
+
# subclasses (MUST) return `self` as the Body, and respond to `#each`/
|
64
|
+
# `#respond_to` with the intended body.
|
65
|
+
#
|
66
|
+
# @example using HTTP request methods to get a Rack response
|
67
|
+
# resource.request(:get, 200, {}, {})
|
68
|
+
# # => [200,
|
69
|
+
# {"Link"=>"<http://www.w3.org/ns/ldp#Resource>;rel=\"type\"",
|
70
|
+
# "Allow"=>"GET, DELETE, OPTIONS, HEAD",
|
71
|
+
# "Accept-Post"=>"",
|
72
|
+
# "Accept-Patch"=>"",
|
73
|
+
# "ETag"=>"W/\"2015-10-25T21:39:13.111500405+00:00\"",
|
74
|
+
# "Last-Modified"=>"Sun, 25 Oct 2015 21:39:13 GMT"},
|
75
|
+
# #<RDF::LDP::Resource:0x00564f4a646028
|
76
|
+
# @data=#<RDF::Repository:0x2b27a5391708()>,
|
77
|
+
# @exists=true,
|
78
|
+
# @metagraph=#<RDF::Graph:0x2b27a5322538(http://example.org/moomin#meta)>,
|
79
|
+
# @subject_uri=#<RDF::URI:0x2b27a5322fec URI:http://example.org/moomin>>]
|
80
|
+
#
|
81
|
+
# resource.request(:put, 200, {}, {}) # RDF::LDP::MethodNotAllowed: put
|
40
82
|
#
|
41
83
|
# @see http://www.w3.org/TR/ldp/ for the Linked Data platform specification
|
42
84
|
# @see http://www.w3.org/TR/ldp/#dfn-linked-data-platform-resource for a
|
43
85
|
# definition of 'Resource' in LDP
|
44
86
|
class Resource
|
45
87
|
# @!attribute [r] subject_uri
|
46
|
-
# an rdf term
|
88
|
+
# an rdf term identifying the `Resource`
|
47
89
|
attr_reader :subject_uri
|
48
90
|
|
49
91
|
# @!attribute [rw] metagraph
|
@@ -159,14 +201,23 @@ module RDF::LDP
|
|
159
201
|
# input. This MAY be used as a content type for the created Resource
|
160
202
|
# (especially for `LDP::NonRDFSource`s).
|
161
203
|
#
|
204
|
+
# @yield gives a transaction (changeset) to collect changes to graph,
|
205
|
+
# metagraph and other resources' (e.g. containers) graphs
|
206
|
+
# @yieldparam tx [RDF::Transaction]
|
207
|
+
# @return [RDF::LDP::Resource] self
|
208
|
+
#
|
162
209
|
# @raise [RDF::LDP::RequestError] when creation fails. May raise various
|
163
210
|
# subclasses for the appropriate response codes.
|
164
211
|
# @raise [RDF::LDP::Conflict] when the resource exists
|
165
|
-
|
166
|
-
# @return [RDF::LDP::Resource] self
|
167
|
-
def create(input, content_type)
|
212
|
+
def create(input, content_type, &block)
|
168
213
|
raise Conflict if exists?
|
169
|
-
|
214
|
+
|
215
|
+
@data.transaction do |transaction|
|
216
|
+
set_interaction_model(transaction)
|
217
|
+
yield transaction if block_given?
|
218
|
+
set_last_modified(transaction)
|
219
|
+
end
|
220
|
+
|
170
221
|
self
|
171
222
|
end
|
172
223
|
|
@@ -178,12 +229,20 @@ module RDF::LDP
|
|
178
229
|
# @param [#to_s] content_type a MIME content_type used to interpret the
|
179
230
|
# input.
|
180
231
|
#
|
232
|
+
# @yield gives a transaction (changeset) to collect changes to graph,
|
233
|
+
# metagraph and other resources' (e.g. containers) graphs
|
234
|
+
# @yieldparam tx [RDF::Transaction]
|
235
|
+
# @return [RDF::LDP::Resource] self
|
236
|
+
#
|
181
237
|
# @raise [RDF::LDP::RequestError] when update fails. May raise various
|
182
238
|
# subclasses for the appropriate response codes.
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
239
|
+
def update(input, content_type, &block)
|
240
|
+
return create(input, content_type, &block) unless exists?
|
241
|
+
@data.transaction do |transaction|
|
242
|
+
yield transaction if block_given?
|
243
|
+
set_last_modified(transaction)
|
244
|
+
end
|
245
|
+
self
|
187
246
|
end
|
188
247
|
|
189
248
|
##
|
@@ -192,30 +251,69 @@ module RDF::LDP
|
|
192
251
|
# This adds a statment to the metagraph expressing that the resource has
|
193
252
|
# been deleted
|
194
253
|
#
|
254
|
+
# @yield gives a transaction (changeset) to collect changes to graph,
|
255
|
+
# metagraph and other resources' (e.g. containers) graphs
|
256
|
+
# @yieldparam tx [RDF::Transaction]
|
195
257
|
# @return [RDF::LDP::Resource] self
|
196
258
|
#
|
197
259
|
# @todo Use of owl:Nothing is probably problematic. Define an internal
|
198
260
|
# namespace and class represeting deletion status as a stateful property.
|
199
|
-
def destroy
|
200
|
-
|
201
|
-
|
261
|
+
def destroy(&block)
|
262
|
+
@data.transaction do |transaction|
|
263
|
+
containers.each { |c| c.remove(self, transaction) if c.container? }
|
264
|
+
transaction << RDF::Statement(subject_uri,
|
265
|
+
RDF::Vocab::PROV.invalidatedAtTime,
|
266
|
+
DateTime.now,
|
267
|
+
graph_name: metagraph_name)
|
268
|
+
yield if block_given?
|
269
|
+
end
|
202
270
|
self
|
203
271
|
end
|
204
272
|
|
205
273
|
##
|
274
|
+
# Gives the status of the resource's existance.
|
275
|
+
#
|
276
|
+
# @note destroyed resources continue to exist in the sense represeted by
|
277
|
+
# this method.
|
278
|
+
#
|
206
279
|
# @return [Boolean] true if the resource exists within the repository
|
207
280
|
def exists?
|
208
|
-
@data.
|
281
|
+
@data.has_graph? metagraph.graph_name
|
209
282
|
end
|
210
283
|
|
211
284
|
##
|
212
285
|
# @return [Boolean] true if resource has been destroyed
|
213
286
|
def destroyed?
|
214
|
-
|
287
|
+
times = @metagraph.query([subject_uri, RDF::Vocab::PROV.invalidatedAtTime, nil])
|
288
|
+
!(times.empty?)
|
215
289
|
end
|
216
290
|
|
291
|
+
##
|
292
|
+
# Returns an Etag. This may be a strong or a weak ETag.
|
293
|
+
#
|
294
|
+
# @return [String] an HTTP Etag
|
295
|
+
#
|
296
|
+
# @note these etags are strong if (and only if) all software that updates
|
297
|
+
# the resource also updates the ETag
|
298
|
+
#
|
299
|
+
# @see http://www.w3.org/TR/ldp#h-ldpr-gen-etags LDP ETag clause for GET
|
300
|
+
# @see http://www.w3.org/TR/ldp#h-ldpr-put-precond LDP ETag clause for PUT
|
301
|
+
# @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.3.3
|
302
|
+
# description of strong vs. weak validators
|
217
303
|
def etag
|
218
|
-
nil
|
304
|
+
return nil unless exists?
|
305
|
+
"W/\"#{last_modified.new_offset(0).iso8601(9)}\""
|
306
|
+
end
|
307
|
+
|
308
|
+
##
|
309
|
+
# @return [DateTime] the time this resource was last modified
|
310
|
+
#
|
311
|
+
# @todo handle cases where there is more than one RDF::DC.modified.
|
312
|
+
# check for the most recent date
|
313
|
+
def last_modified
|
314
|
+
results = @metagraph.query([subject_uri, RDF::Vocab::DC.modified, :time])
|
315
|
+
return nil if results.empty?
|
316
|
+
results.first.object.object
|
219
317
|
end
|
220
318
|
|
221
319
|
##
|
@@ -310,7 +408,7 @@ module RDF::LDP
|
|
310
408
|
raise Gone if destroyed?
|
311
409
|
begin
|
312
410
|
send(method.to_sym.downcase, status, headers, env)
|
313
|
-
rescue NotImplementedError
|
411
|
+
rescue NotImplementedError => e
|
314
412
|
raise MethodNotAllowed, method
|
315
413
|
end
|
316
414
|
end
|
@@ -344,6 +442,36 @@ module RDF::LDP
|
|
344
442
|
[204, headers, destroy]
|
345
443
|
end
|
346
444
|
|
445
|
+
##
|
446
|
+
# @abstract implement in subclasses as needed to support HTTP PATCH
|
447
|
+
def patch(*)
|
448
|
+
raise NotImplementedError
|
449
|
+
end
|
450
|
+
|
451
|
+
##
|
452
|
+
# @abstract implement in subclasses as needed to support HTTP POST
|
453
|
+
def post(*)
|
454
|
+
raise NotImplementedError
|
455
|
+
end
|
456
|
+
|
457
|
+
##
|
458
|
+
# @abstract implement in subclasses as needed to support HTTP PUT
|
459
|
+
def put(*)
|
460
|
+
raise NotImplementedError
|
461
|
+
end
|
462
|
+
|
463
|
+
##
|
464
|
+
# @abstract HTTP TRACE is not expected to be supported
|
465
|
+
def trace(*)
|
466
|
+
raise NotImplementedError
|
467
|
+
end
|
468
|
+
|
469
|
+
##
|
470
|
+
# @abstract HTTP CONNECT is not expected to be supported
|
471
|
+
def connect(*)
|
472
|
+
raise NotImplementedError
|
473
|
+
end
|
474
|
+
|
347
475
|
##
|
348
476
|
# @return [RDF::URI] the name for this resource's metagraph
|
349
477
|
def metagraph_name
|
@@ -361,14 +489,19 @@ module RDF::LDP
|
|
361
489
|
headers['Accept-Post'] = accept_post if respond_to?(:post, true)
|
362
490
|
headers['Accept-Patch'] = accept_patch if respond_to?(:patch, true)
|
363
491
|
|
364
|
-
|
492
|
+
tag = etag
|
493
|
+
headers['ETag'] ||= tag if tag
|
494
|
+
|
495
|
+
modified = last_modified
|
496
|
+
headers['Last-Modified'] ||= modified.httpdate if modified
|
497
|
+
|
365
498
|
headers
|
366
499
|
end
|
367
500
|
|
368
501
|
##
|
369
502
|
# @return [String] the Accept-Post headers
|
370
503
|
def accept_post
|
371
|
-
RDF::Reader.map
|
504
|
+
RDF::Reader.map(&:format).compact.map(&:content_type).flatten.join(', ')
|
372
505
|
end
|
373
506
|
|
374
507
|
##
|
@@ -400,5 +533,36 @@ module RDF::LDP
|
|
400
533
|
def link_type_header(uri)
|
401
534
|
"<#{uri}>;rel=\"type\""
|
402
535
|
end
|
536
|
+
|
537
|
+
##
|
538
|
+
# Sets the last modified date/time to now
|
539
|
+
def set_last_modified(transaction = nil)
|
540
|
+
if transaction
|
541
|
+
# transactions do not support updates or pattern deletes, so we must
|
542
|
+
# ask the Repository for the current last_modified to delete the statement
|
543
|
+
# transactionally
|
544
|
+
modified = last_modified
|
545
|
+
transaction.delete RDF::Statement(subject_uri,
|
546
|
+
RDF::Vocab::DC.modified,
|
547
|
+
modified,
|
548
|
+
graph_name: metagraph_name) if modified
|
549
|
+
|
550
|
+
transaction.insert RDF::Statement(subject_uri,
|
551
|
+
RDF::Vocab::DC.modified,
|
552
|
+
DateTime.now,
|
553
|
+
graph_name: metagraph_name)
|
554
|
+
else
|
555
|
+
metagraph.update([subject_uri, RDF::Vocab::DC.modified, DateTime.now])
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
##
|
560
|
+
# Sets the last modified date/time to the URI for this resource's class
|
561
|
+
def set_interaction_model(transaction)
|
562
|
+
transaction.insert(RDF::Statement(subject_uri,
|
563
|
+
RDF.type,
|
564
|
+
self.class.to_uri,
|
565
|
+
graph_name: metagraph.graph_name))
|
566
|
+
end
|
403
567
|
end
|
404
568
|
end
|
metadata
CHANGED
@@ -1,87 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rdf-ldp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Johnson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.6'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rdf
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1.
|
33
|
+
version: '1.99'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1.
|
40
|
+
version: '1.99'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rdf-turtle
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '1.1'
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 1.1.8
|
48
51
|
type: :runtime
|
49
52
|
prerelease: false
|
50
53
|
version_requirements: !ruby/object:Gem::Requirement
|
51
54
|
requirements:
|
52
55
|
- - "~>"
|
53
56
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
57
|
+
version: '1.1'
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.1.8
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
62
|
+
name: ld-patch
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
58
64
|
requirements:
|
59
|
-
- - "
|
65
|
+
- - "~>"
|
60
66
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
67
|
+
version: '0.1'
|
62
68
|
type: :runtime
|
63
69
|
prerelease: false
|
64
70
|
version_requirements: !ruby/object:Gem::Requirement
|
65
71
|
requirements:
|
66
|
-
- - "
|
72
|
+
- - "~>"
|
67
73
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
74
|
+
version: '0.1'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
76
|
+
name: rdf-vocab
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
72
78
|
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0.8'
|
73
82
|
- - ">="
|
74
83
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
84
|
+
version: 0.8.4
|
76
85
|
type: :runtime
|
77
86
|
prerelease: false
|
78
87
|
version_requirements: !ruby/object:Gem::Requirement
|
79
88
|
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0.8'
|
80
92
|
- - ">="
|
81
93
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
94
|
+
version: 0.8.4
|
83
95
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
96
|
+
name: rack-linkeddata
|
85
97
|
requirement: !ruby/object:Gem::Requirement
|
86
98
|
requirements:
|
87
99
|
- - "~>"
|
@@ -98,44 +110,50 @@ dependencies:
|
|
98
110
|
name: json-ld
|
99
111
|
requirement: !ruby/object:Gem::Requirement
|
100
112
|
requirements:
|
101
|
-
- - "
|
113
|
+
- - "~>"
|
102
114
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
115
|
+
version: '1.1'
|
104
116
|
type: :runtime
|
105
117
|
prerelease: false
|
106
118
|
version_requirements: !ruby/object:Gem::Requirement
|
107
119
|
requirements:
|
108
|
-
- - "
|
120
|
+
- - "~>"
|
109
121
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
122
|
+
version: '1.1'
|
111
123
|
- !ruby/object:Gem::Dependency
|
112
124
|
name: sinatra
|
113
125
|
requirement: !ruby/object:Gem::Requirement
|
114
126
|
requirements:
|
115
|
-
- - "
|
127
|
+
- - "~>"
|
116
128
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
129
|
+
version: '1.4'
|
118
130
|
type: :runtime
|
119
131
|
prerelease: false
|
120
132
|
version_requirements: !ruby/object:Gem::Requirement
|
121
133
|
requirements:
|
122
|
-
- - "
|
134
|
+
- - "~>"
|
123
135
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
136
|
+
version: '1.4'
|
125
137
|
- !ruby/object:Gem::Dependency
|
126
138
|
name: link_header
|
127
139
|
requirement: !ruby/object:Gem::Requirement
|
128
140
|
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0.0'
|
129
144
|
- - ">="
|
130
145
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
146
|
+
version: 0.0.8
|
132
147
|
type: :runtime
|
133
148
|
prerelease: false
|
134
149
|
version_requirements: !ruby/object:Gem::Requirement
|
135
150
|
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0.0'
|
136
154
|
- - ">="
|
137
155
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
156
|
+
version: 0.0.8
|
139
157
|
- !ruby/object:Gem::Dependency
|
140
158
|
name: rdf-spec
|
141
159
|
requirement: !ruby/object:Gem::Requirement
|
@@ -230,16 +248,16 @@ dependencies:
|
|
230
248
|
name: rack-test
|
231
249
|
requirement: !ruby/object:Gem::Requirement
|
232
250
|
requirements:
|
233
|
-
- - "
|
251
|
+
- - "~>"
|
234
252
|
- !ruby/object:Gem::Version
|
235
|
-
version: '0'
|
253
|
+
version: '0.6'
|
236
254
|
type: :development
|
237
255
|
prerelease: false
|
238
256
|
version_requirements: !ruby/object:Gem::Requirement
|
239
257
|
requirements:
|
240
|
-
- - "
|
258
|
+
- - "~>"
|
241
259
|
- !ruby/object:Gem::Version
|
242
|
-
version: '0'
|
260
|
+
version: '0.6'
|
243
261
|
- !ruby/object:Gem::Dependency
|
244
262
|
name: rspec-its
|
245
263
|
requirement: !ruby/object:Gem::Requirement
|
@@ -254,6 +272,20 @@ dependencies:
|
|
254
272
|
- - "~>"
|
255
273
|
- !ruby/object:Gem::Version
|
256
274
|
version: '1.0'
|
275
|
+
- !ruby/object:Gem::Dependency
|
276
|
+
name: timecop
|
277
|
+
requirement: !ruby/object:Gem::Requirement
|
278
|
+
requirements:
|
279
|
+
- - "~>"
|
280
|
+
- !ruby/object:Gem::Version
|
281
|
+
version: '0.8'
|
282
|
+
type: :development
|
283
|
+
prerelease: false
|
284
|
+
version_requirements: !ruby/object:Gem::Requirement
|
285
|
+
requirements:
|
286
|
+
- - "~>"
|
287
|
+
- !ruby/object:Gem::Version
|
288
|
+
version: '0.8'
|
257
289
|
- !ruby/object:Gem::Dependency
|
258
290
|
name: webmock
|
259
291
|
requirement: !ruby/object:Gem::Requirement
|
@@ -297,6 +329,7 @@ files:
|
|
297
329
|
- README.md
|
298
330
|
- UNLICENSE
|
299
331
|
- VERSION
|
332
|
+
- app/lamprey.rb
|
300
333
|
- bin/lamprey
|
301
334
|
- lib/rack/ldp.rb
|
302
335
|
- lib/rdf/ldp.rb
|
@@ -328,7 +361,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
328
361
|
version: '0'
|
329
362
|
requirements: []
|
330
363
|
rubyforge_project:
|
331
|
-
rubygems_version: 2.2.
|
364
|
+
rubygems_version: 2.2.0
|
332
365
|
signing_key:
|
333
366
|
specification_version: 4
|
334
367
|
summary: A suite of LDP software and middleware for RDF.rb.
|