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