valkyrie 1.2.0.rc1 → 1.2.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +12 -4
- data/lib/valkyrie/persistence/composite_persister.rb +1 -1
- data/lib/valkyrie/persistence/fedora/list_node.rb +42 -3
- data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +26 -0
- data/lib/valkyrie/persistence/fedora/ordered_list.rb +36 -5
- data/lib/valkyrie/persistence/fedora/ordered_reader.rb +6 -0
- data/lib/valkyrie/persistence/fedora/permissive_schema.rb +20 -1
- data/lib/valkyrie/persistence/fedora/persister.rb +33 -4
- data/lib/valkyrie/persistence/fedora/persister/alternate_identifier.rb +6 -0
- data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +254 -4
- data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +250 -3
- data/lib/valkyrie/persistence/fedora/persister/resource_factory.rb +6 -0
- data/lib/valkyrie/persistence/fedora/query_service.rb +22 -4
- data/lib/valkyrie/persistence/memory/metadata_adapter.rb +2 -0
- data/lib/valkyrie/persistence/memory/persister.rb +11 -3
- data/lib/valkyrie/persistence/memory/query_service.rb +11 -0
- data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +2 -0
- data/lib/valkyrie/persistence/postgres/orm.rb +4 -0
- data/lib/valkyrie/persistence/postgres/orm_converter.rb +62 -2
- data/lib/valkyrie/persistence/postgres/persister.rb +18 -7
- data/lib/valkyrie/persistence/postgres/query_service.rb +103 -11
- data/lib/valkyrie/persistence/postgres/resource_converter.rb +10 -0
- data/lib/valkyrie/persistence/postgres/resource_factory.rb +3 -0
- data/lib/valkyrie/persistence/solr/composite_indexer.rb +10 -0
- data/lib/valkyrie/persistence/solr/metadata_adapter.rb +7 -0
- data/lib/valkyrie/persistence/solr/model_converter.rb +137 -0
- data/lib/valkyrie/persistence/solr/orm_converter.rb +168 -0
- data/lib/valkyrie/persistence/solr/persister.rb +13 -5
- data/lib/valkyrie/persistence/solr/queries.rb +1 -0
- data/lib/valkyrie/persistence/solr/queries/default_paginator.rb +11 -1
- data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +12 -0
- data/lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb +12 -0
- data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +11 -0
- data/lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb +13 -0
- data/lib/valkyrie/persistence/solr/queries/find_many_by_ids_query.rb +9 -0
- data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +23 -0
- data/lib/valkyrie/persistence/solr/queries/find_ordered_references_query.rb +50 -0
- data/lib/valkyrie/persistence/solr/queries/find_references_query.rb +15 -0
- data/lib/valkyrie/persistence/solr/query_service.rb +47 -14
- data/lib/valkyrie/persistence/solr/repository.rb +21 -4
- data/lib/valkyrie/persistence/solr/resource_factory.rb +2 -0
- data/lib/valkyrie/resource.rb +1 -0
- data/lib/valkyrie/specs/shared_specs.rb +1 -0
- data/lib/valkyrie/specs/shared_specs/persister.rb +92 -2
- data/lib/valkyrie/specs/shared_specs/queries.rb +12 -0
- data/lib/valkyrie/specs/shared_specs/solr_indexer.rb +40 -0
- data/lib/valkyrie/storage/fedora.rb +0 -2
- data/lib/valkyrie/version.rb +1 -1
- metadata +4 -2
@@ -1,19 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Valkyrie::Persistence::Fedora
|
3
3
|
class Persister
|
4
|
-
# Responsible for converting {LDP::Container::Basic} to {
|
4
|
+
# Responsible for converting {LDP::Container::Basic} to {Valkyrie::Resource}
|
5
5
|
class OrmConverter
|
6
6
|
attr_reader :object, :adapter
|
7
7
|
delegate :graph, to: :object
|
8
|
+
|
9
|
+
# @param [Ldp::Container::Basic] object
|
10
|
+
# @param [Valkyrie::Persistence::Fedora::MetadataAdapter] adapter
|
8
11
|
def initialize(object:, adapter:)
|
9
12
|
@object = object
|
10
13
|
@adapter = adapter
|
11
14
|
end
|
12
15
|
|
16
|
+
# Convert a Fedora LDP container to a Valkyrie Resource
|
17
|
+
# @return [Valkyrie::Resource]
|
13
18
|
def convert
|
14
19
|
populate_native_lock(Valkyrie::Types::Anything[attributes])
|
15
20
|
end
|
16
21
|
|
22
|
+
# Generate a Hash resulting from the mapping of Fedora LDP graphs to Valkyrie Resource attributes
|
23
|
+
# For example:
|
24
|
+
# {
|
25
|
+
# :internal_resource => "CustomResource",
|
26
|
+
# :created_at => 2018-08-08 15:45:03 UTC,
|
27
|
+
# [...]
|
28
|
+
# id => #<Valkyrie::ID:0x00007ff821e9cb38 @id="9e5aef75-f4cc-42f4-b050-0eadeeab908d",
|
29
|
+
# new_record => false
|
30
|
+
# }
|
31
|
+
# @return [Hash]
|
17
32
|
def attributes
|
18
33
|
GraphToAttributes.new(graph: graph, adapter: adapter)
|
19
34
|
.convert
|
@@ -31,22 +46,35 @@ module Valkyrie::Persistence::Fedora
|
|
31
46
|
resource
|
32
47
|
end
|
33
48
|
|
49
|
+
# Generate the Valkyrie ID from the existing Fedora LDP resource property
|
50
|
+
# Should no such property exist, the URI for the LDP resource is used to mint a new one
|
51
|
+
# @return [Valkyrie::ID]
|
34
52
|
def id
|
35
53
|
id_property.present? ? Valkyrie::ID.new(id_property) : adapter.uri_to_id(object.subject_uri)
|
36
54
|
end
|
37
55
|
|
56
|
+
# Retrieve the RDF property for the Valkyrie ID
|
57
|
+
# @see {Valkyrie::Persistence::Fedora::Persister::ModelConverter::NestedInternalValkyrieID}
|
58
|
+
# @return [String]
|
38
59
|
def id_property
|
39
60
|
return unless object.subject_uri.to_s.include?("#")
|
40
61
|
object.graph.query([RDF::URI(""), PermissiveSchema.id, nil]).to_a.first.try(:object).to_s
|
41
62
|
end
|
42
63
|
|
64
|
+
# Class for deriving an attribute Hash from a Fedora LDP resource graph
|
43
65
|
class GraphToAttributes
|
44
66
|
attr_reader :graph, :adapter
|
67
|
+
|
68
|
+
# @param [RDF::Graph] graph
|
69
|
+
# @param [Valkyrie::Persistence::Fedora::MetadataAdapter] adapter
|
45
70
|
def initialize(graph:, adapter:)
|
46
71
|
@graph = graph
|
47
72
|
@adapter = adapter
|
48
73
|
end
|
49
74
|
|
75
|
+
# Generates FedoraValue objects for each statement in the Fedora LDP resource graph
|
76
|
+
# Using these objects, it then generates a Hash of Valkyrie Resource attributes
|
77
|
+
# @return [Hash]
|
50
78
|
def convert
|
51
79
|
graph.each do |statement|
|
52
80
|
FedoraValue.for(Property.new(statement: statement, scope: graph, adapter: adapter)).result.apply_to(attributes)
|
@@ -54,44 +82,70 @@ module Valkyrie::Persistence::Fedora
|
|
54
82
|
attributes
|
55
83
|
end
|
56
84
|
|
85
|
+
# Access the attributes populated by RDF graph statements
|
86
|
+
# @return [Hash]
|
57
87
|
def attributes
|
58
88
|
@attributes ||= {}
|
59
89
|
end
|
60
90
|
|
91
|
+
# Class mapping values
|
61
92
|
class FedoraValue < ::Valkyrie::ValueMapper
|
93
|
+
# Constructs an Applicator object for the value being mapped
|
94
|
+
# @return [Applicator]
|
62
95
|
def result
|
63
96
|
Applicator.new(value)
|
64
97
|
end
|
65
98
|
end
|
66
99
|
|
100
|
+
# Class for handling cases where blacklisted values should not be mapped
|
67
101
|
class BlacklistedValue < ::Valkyrie::ValueMapper
|
68
102
|
FedoraValue.register(self)
|
103
|
+
|
104
|
+
# Determines whether or not the value has a blacklisted namespace for the RDF statement object
|
105
|
+
# (i. e. avoid attempting to map any RDF statements making assertions about LDP containers or resource internal to Fedora)
|
106
|
+
# @param [Property] value
|
107
|
+
# @return [Boolean]
|
69
108
|
def self.handles?(value)
|
70
109
|
value.statement.object.to_s.start_with?("http://www.w3.org/ns/ldp", "http://fedora.info")
|
71
110
|
end
|
72
111
|
|
112
|
+
# Provide the NullApplicator Class for any Property in a blacklisted namespace
|
73
113
|
def result
|
74
114
|
NullApplicator
|
75
115
|
end
|
76
116
|
end
|
77
117
|
|
118
|
+
# Class for handling cases where the RDF subject of a Property references a separate resource using a hash URI
|
78
119
|
class DifferentSubject < ::Valkyrie::ValueMapper
|
79
120
|
FedoraValue.register(self)
|
121
|
+
|
122
|
+
# Determines whether or not the value has an RDF subject using a hash URI
|
123
|
+
# (Hash URIs are treated as different resources)
|
124
|
+
# @param [Property] value
|
125
|
+
# @return [Boolean]
|
80
126
|
def self.handles?(value)
|
81
127
|
value.statement.subject.to_s.include?("#")
|
82
128
|
end
|
83
129
|
|
130
|
+
# Provide the NullApplicator Class for any Property with a hash URI in the RDF subject
|
84
131
|
def result
|
85
132
|
NullApplicator
|
86
133
|
end
|
87
134
|
end
|
88
135
|
|
136
|
+
# Class for handling Arrays of Properties
|
89
137
|
class CompositeApplicator
|
90
138
|
attr_reader :applicators
|
139
|
+
|
140
|
+
# @param [Array<Applicator>] applicators
|
91
141
|
def initialize(applicators)
|
92
142
|
@applicators = applicators
|
93
143
|
end
|
94
144
|
|
145
|
+
# Enumerate through the Applicator constructed for each Property
|
146
|
+
# updating the Valkyrie resource attribute Hash with each result
|
147
|
+
# @param [Hash] hsh a new or existing Hash of attribute for Valkyrie resource attributes
|
148
|
+
# @return [Hash]
|
95
149
|
def apply_to(hsh)
|
96
150
|
applicators.each do |applicator|
|
97
151
|
applicator.apply_to(hsh)
|
@@ -100,13 +154,20 @@ module Valkyrie::Persistence::Fedora
|
|
100
154
|
end
|
101
155
|
end
|
102
156
|
|
157
|
+
# Class for mapping resource member IDs in an RDF linked list
|
103
158
|
class MemberID < ::Valkyrie::ValueMapper
|
104
159
|
delegate :scope, :adapter, to: :value
|
105
160
|
FedoraValue.register(self)
|
161
|
+
|
162
|
+
# Determines whether or not the Property statement references an RDF linked list
|
163
|
+
# @param [Property] value
|
106
164
|
def self.handles?(value)
|
107
165
|
value.statement.predicate == ::RDF::Vocab::IANA.first
|
108
166
|
end
|
109
167
|
|
168
|
+
# Constructs a CompositeApplicator object for each element in the RDF linked list
|
169
|
+
# Involves mapping to Property objects using an OrderedList
|
170
|
+
# @return [CompositeApplicator]
|
110
171
|
def result
|
111
172
|
value.statement.predicate = PermissiveSchema.member_ids
|
112
173
|
values = OrderedList.new(scope, head, tail, adapter).to_a.map(&:proxy_for)
|
@@ -116,23 +177,61 @@ module Valkyrie::Persistence::Fedora
|
|
116
177
|
CompositeApplicator.new(values)
|
117
178
|
end
|
118
179
|
|
180
|
+
# Retrieve the URI for the first element in the linked list
|
181
|
+
# @return [RDF::URI]
|
119
182
|
def head
|
120
183
|
scope.query([value.statement.subject, RDF::Vocab::IANA.first]).to_a.first.object
|
121
184
|
end
|
122
185
|
|
186
|
+
# Retrieve the URI for the last element in the linked list
|
187
|
+
# @return [RDF::URI]
|
123
188
|
def tail
|
124
189
|
scope.query([value.statement.subject, RDF::Vocab::IANA.last]).to_a.first.object
|
125
190
|
end
|
126
191
|
end
|
127
192
|
|
193
|
+
class OrderedProperty < ::Valkyrie::ValueMapper
|
194
|
+
delegate :scope, :adapter, to: :value
|
195
|
+
FedoraValue.register(self)
|
196
|
+
def self.handles?(value)
|
197
|
+
value.statement.object.is_a?(RDF::URI) && value.statement.object.to_s.include?("#") &&
|
198
|
+
(value.statement.object.to_s.start_with?("#") ||
|
199
|
+
value.statement.object.to_s.start_with?(value.adapter.connection_prefix)) &&
|
200
|
+
value.scope.query([value.statement.object, nil, nil]).map(&:predicate).include?(::RDF::Vocab::IANA.first)
|
201
|
+
end
|
202
|
+
|
203
|
+
def result
|
204
|
+
values = OrderedList.new(scope, head, tail, adapter).to_a.map(&:proxy_for)
|
205
|
+
values = values.map do |val|
|
206
|
+
calling_mapper.for(Property.new(statement: RDF::Statement.new(value.statement.subject, value.statement.predicate, val), scope: value.scope, adapter: value.adapter)).result
|
207
|
+
end
|
208
|
+
CompositeApplicator.new(values)
|
209
|
+
end
|
210
|
+
|
211
|
+
def head
|
212
|
+
scope.query([value.statement.object, RDF::Vocab::IANA.first]).to_a.first.object
|
213
|
+
end
|
214
|
+
|
215
|
+
def tail
|
216
|
+
scope.query([value.statement.object, RDF::Vocab::IANA.last]).to_a.first.object
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Class for mapping RDF child graphs within parent graphs
|
128
221
|
class NestedValue < ::Valkyrie::ValueMapper
|
129
222
|
FedoraValue.register(self)
|
223
|
+
|
224
|
+
# Determines whether or not a Property lies within a parent graph
|
225
|
+
# @param [Property] value
|
226
|
+
# @return [Boolean]
|
130
227
|
def self.handles?(value)
|
131
228
|
value.statement.object.is_a?(RDF::URI) && value.statement.object.to_s.include?("#") &&
|
132
229
|
(value.statement.object.to_s.start_with?("#") ||
|
133
230
|
value.statement.object.to_s.start_with?(value.adapter.connection_prefix))
|
134
231
|
end
|
135
232
|
|
233
|
+
# Construct an Applicator object from the parent graph for the child graph in this Property
|
234
|
+
# @return [Applicator]
|
136
235
|
def result
|
137
236
|
value.scope.each do |statement|
|
138
237
|
next unless statement.subject.to_s.include?("#")
|
@@ -143,14 +242,22 @@ module Valkyrie::Persistence::Fedora
|
|
143
242
|
Applicator.new(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter))
|
144
243
|
end
|
145
244
|
|
245
|
+
# Construct a new GraphContainer object for the parent graph of the child graph in this Property
|
246
|
+
# @return [GraphContainer]
|
146
247
|
def container
|
147
248
|
GraphContainer.new(graph, value.statement.object)
|
148
249
|
end
|
149
250
|
|
251
|
+
# Recursively convert the parent graph into a Valkyrie Resource
|
252
|
+
# @return [Valkyrie::Resource]
|
150
253
|
def resource
|
151
254
|
OrmConverter.new(object: container, adapter: value.adapter).convert
|
152
255
|
end
|
153
256
|
|
257
|
+
# Retrieve a new RDF subject for a given statement
|
258
|
+
# If the subject of the statement and that of the Property statement are the same, generate an empty URI
|
259
|
+
# @param [RDF::Statement] statement
|
260
|
+
# @return [RDF::URI]
|
154
261
|
def new_subject(statement)
|
155
262
|
if statement.subject == value.statement.object
|
156
263
|
RDF::URI("")
|
@@ -159,12 +266,18 @@ module Valkyrie::Persistence::Fedora
|
|
159
266
|
end
|
160
267
|
end
|
161
268
|
|
269
|
+
# Construct the RDF graph used for the parent graph
|
270
|
+
# @return [RDF::Graph]
|
162
271
|
def graph
|
163
272
|
@graph ||= RDF::Graph.new
|
164
273
|
end
|
165
274
|
|
275
|
+
# Models a container for parent graphs
|
166
276
|
class GraphContainer
|
167
277
|
attr_reader :graph, :subject_uri
|
278
|
+
|
279
|
+
# @param [RDF::Graph] graph
|
280
|
+
# @param [RDF::URI] subject_uri
|
168
281
|
def initialize(graph, subject_uri)
|
169
282
|
@graph = graph
|
170
283
|
@subject_uri = subject_uri
|
@@ -172,148 +285,252 @@ module Valkyrie::Persistence::Fedora
|
|
172
285
|
end
|
173
286
|
end
|
174
287
|
|
288
|
+
# Class for mapping RDF boolean literals into Valkyrie Resource attribute values
|
175
289
|
class BooleanValue < ::Valkyrie::ValueMapper
|
176
290
|
FedoraValue.register(self)
|
291
|
+
|
292
|
+
# Determines whether or not a Property statement is an RDF literal typed for boolean values
|
293
|
+
# @param [Property] value
|
294
|
+
# @return [Boolean]
|
177
295
|
def self.handles?(value)
|
178
296
|
value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_bool
|
179
297
|
end
|
180
298
|
|
299
|
+
# Casts the value of the RDF literal into an Applicator for Boolean values
|
300
|
+
# @return [Applicator]
|
181
301
|
def result
|
182
302
|
value.statement.object = value.statement.object.value.casecmp("true").zero?
|
183
303
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
184
304
|
end
|
185
305
|
end
|
186
306
|
|
307
|
+
# Class for mapping RDF datetime literals into Valkyrie Resource attribute values
|
187
308
|
class DateTimeValue < ::Valkyrie::ValueMapper
|
188
309
|
FedoraValue.register(self)
|
310
|
+
|
311
|
+
# Determines whether or not a Property statement is an RDF literal typed for datetime values
|
312
|
+
# @param [Property] value
|
313
|
+
# @return [Boolean]
|
189
314
|
def self.handles?(value)
|
190
315
|
value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_datetime
|
191
316
|
end
|
192
317
|
|
318
|
+
# Casts the value of the RDF literal into an Applicator for DateTime values
|
319
|
+
# @return [Applicator]
|
193
320
|
def result
|
194
321
|
value.statement.object = ::DateTime.iso8601(value.statement.object.to_s).utc
|
195
322
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
196
323
|
end
|
197
324
|
end
|
198
325
|
|
326
|
+
# Class for mapping RDF integer literals into Valkyrie Resource attribute values
|
199
327
|
class IntegerValue < ::Valkyrie::ValueMapper
|
200
328
|
FedoraValue.register(self)
|
329
|
+
|
330
|
+
# Determines whether or not a Property statement is an RDF literal typed for Integer values
|
331
|
+
# @param [Property] value
|
332
|
+
# @return [Boolean]
|
201
333
|
def self.handles?(value)
|
202
334
|
value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_int
|
203
335
|
end
|
204
336
|
|
337
|
+
# Casts the value of the RDF literal into an Applicator for Integer values
|
338
|
+
# @return [Applicator]
|
205
339
|
def result
|
206
340
|
value.statement.object = value.statement.object.value.to_i
|
207
341
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
208
342
|
end
|
209
343
|
end
|
210
344
|
|
345
|
+
class FloatValue < ::Valkyrie::ValueMapper
|
346
|
+
FedoraValue.register(self)
|
347
|
+
def self.handles?(value)
|
348
|
+
value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_float
|
349
|
+
end
|
350
|
+
|
351
|
+
def result
|
352
|
+
value.statement.object = value.statement.object.value.to_f
|
353
|
+
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# Class for mapping RDF XML literals into Valkyrie Resource attribute values
|
211
358
|
class LiteralValue < ::Valkyrie::ValueMapper
|
212
359
|
FedoraValue.register(self)
|
360
|
+
|
361
|
+
# Determines whether or not a Property statement is an RDF literal typed using XML data types
|
362
|
+
# @see https://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal
|
363
|
+
# @see https://www.w3.org/TR/xmlschema-2/#built-in-datatypes
|
364
|
+
# @param [Property] value
|
365
|
+
# @return [Boolean]
|
213
366
|
def self.handles?(value)
|
214
367
|
value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#string")
|
215
368
|
end
|
216
369
|
|
370
|
+
# Casts the value of the RDF literal into an Applicator for XML datatype values
|
371
|
+
# @return [Applicator]
|
217
372
|
def result
|
218
373
|
value.statement.object = value.statement.object.to_s
|
219
374
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
220
375
|
end
|
221
376
|
end
|
222
377
|
|
223
|
-
#
|
224
|
-
#
|
378
|
+
# Class for mapping RDF datetime literals into Valkyrie Resource attribute values
|
379
|
+
# Class for mapping Property objects for Time values
|
380
|
+
# Technically Valkyrie does not support time, but when other persisters support time
|
381
|
+
# this code will make Fedora compliant with the established patterns.
|
225
382
|
#
|
226
383
|
# https://github.com/samvera-labs/valkyrie/wiki/Supported-Data-Types
|
227
384
|
class TimeValue < ::Valkyrie::ValueMapper
|
228
385
|
FedoraValue.register(self)
|
386
|
+
|
387
|
+
# Determines whether or not a Property statement is an RDF literal typed for Time values
|
388
|
+
# @param [Property] value
|
389
|
+
# @return [Boolean]
|
229
390
|
def self.handles?(value)
|
230
391
|
value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_time
|
231
392
|
end
|
232
393
|
|
394
|
+
# Casts the value of the RDF literal into an Applicator for DateTime values
|
395
|
+
# @return [Applicator]
|
233
396
|
def result
|
234
397
|
value.statement.object = Time.parse(value.statement.object.to_s).utc
|
235
398
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
236
399
|
end
|
237
400
|
end
|
238
401
|
|
402
|
+
# Casts the value of the RDF literal into an Applicator for Valkyrie ID objects
|
403
|
+
# @return [Applicator]
|
239
404
|
class ValkyrieIDValue < ::Valkyrie::ValueMapper
|
240
405
|
FedoraValue.register(self)
|
406
|
+
|
407
|
+
# Determines whether or not a Property statement is an RDF literal typed for Valkyrie ID literals
|
408
|
+
# @param [Property] value
|
409
|
+
# @return [Boolean]
|
241
410
|
def self.handles?(value)
|
242
411
|
value.statement.object.is_a?(RDF::Literal) && value.statement.object.datatype == PermissiveSchema.valkyrie_id
|
243
412
|
end
|
244
413
|
|
414
|
+
# Casts the value of the RDF literal into an Applicator for Valkyrie::ID objects
|
415
|
+
# @return [Applicator]
|
245
416
|
def result
|
246
417
|
value.statement.object = Valkyrie::ID.new(value.statement.object.to_s)
|
247
418
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
248
419
|
end
|
249
420
|
end
|
250
421
|
|
422
|
+
# Casts the value of the RDF literal into an Applicator for Valkyrie::Persistence::OptimisticLockToken objects
|
423
|
+
# @return [Applicator]
|
251
424
|
class ValkyrieOptimisticLockToken < ::Valkyrie::ValueMapper
|
252
425
|
FedoraValue.register(self)
|
426
|
+
|
427
|
+
# Determines whether or not a Property statement is an RDF literal typed for Valkyrie Optimistic Lock Token literals
|
428
|
+
# @param [Property] value
|
429
|
+
# @return [Boolean]
|
253
430
|
def self.handles?(value)
|
254
431
|
value.statement.object.is_a?(RDF::Literal) && value.statement.object.datatype == PermissiveSchema.optimistic_lock_token
|
255
432
|
end
|
256
433
|
|
434
|
+
# Casts the value of the RDF literal into an Applicator for Valkyrie::Persistence::OptimisticLockToken objects
|
435
|
+
# @return [Applicator]
|
257
436
|
def result
|
258
437
|
value.statement.object = Valkyrie::Persistence::OptimisticLockToken.new(adapter_id: value.adapter.id, token: value.statement.object.to_s)
|
259
438
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
260
439
|
end
|
261
440
|
end
|
262
441
|
|
442
|
+
# Casts the value of the RDF literal into an Applicator for URIs referencing Valkyrie Resources
|
443
|
+
# @return [Applicator]
|
263
444
|
class InternalURI < ::Valkyrie::ValueMapper
|
264
445
|
FedoraValue.register(self)
|
446
|
+
|
447
|
+
# Determines whether or not a Property statement is URI referring internally to a Valkyrie Resource
|
448
|
+
# @param [Property] value
|
449
|
+
# @return [Boolean]
|
265
450
|
def self.handles?(value)
|
266
451
|
value.statement.object.is_a?(RDF::URI) && value.statement.object.to_s.start_with?(value.adapter.connection_prefix)
|
267
452
|
end
|
268
453
|
|
454
|
+
# Casts the value of the URI into an Applicator for Valkyrie::Resource objects
|
455
|
+
# @return [Applicator]
|
269
456
|
def result
|
270
457
|
value.statement.object = value.adapter.uri_to_id(value.statement.object)
|
271
458
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
272
459
|
end
|
273
460
|
end
|
274
461
|
|
462
|
+
# Casts the value of the RDF statements encoding the type of Valkyrie Resource into the resource type
|
463
|
+
# @return [Applicator]
|
275
464
|
class InternalModelValue < ::Valkyrie::ValueMapper
|
276
465
|
FedoraValue.register(self)
|
277
466
|
|
467
|
+
# Determines whether or not the Property RDF statement refers to a resource type
|
468
|
+
# @param [Property] value
|
469
|
+
# @return [Boolean]
|
278
470
|
def self.handles?(value)
|
279
471
|
value.statement.predicate == value.adapter.schema.predicate_for(property: :internal_resource, resource: nil)
|
280
472
|
end
|
281
473
|
|
474
|
+
# Constructs a SingleApplicator object for mapping the resource type
|
475
|
+
# @return [SingleApplicator]
|
282
476
|
def result
|
283
477
|
SingleApplicator.new(value)
|
284
478
|
end
|
285
479
|
end
|
286
480
|
|
481
|
+
# Casts the value of the RDF statements encoding the time of creation for the Valkyrie Resource into a DateTime value
|
482
|
+
# @return [Applicator]
|
287
483
|
class CreatedAtValue < ::Valkyrie::ValueMapper
|
288
484
|
FedoraValue.register(self)
|
485
|
+
|
486
|
+
# Determines whether or not the Property RDF statement encodes a creation date
|
487
|
+
# @param [Property] value
|
488
|
+
# @return [Boolean]
|
289
489
|
def self.handles?(value)
|
290
490
|
value.statement.predicate == value.adapter.schema.predicate_for(property: :created_at, resource: nil)
|
291
491
|
end
|
292
492
|
|
493
|
+
# Constructs a NonStringSingleApplicator object for mapping the resource creation time
|
494
|
+
# @return [NonStringSingleApplicator]
|
293
495
|
def result
|
294
496
|
NonStringSingleApplicator.new(value)
|
295
497
|
end
|
296
498
|
end
|
297
499
|
|
500
|
+
# Casts the value of the RDF statements encoding the time of last update creation for the Valkyrie Resource into a DateTime value
|
501
|
+
# @return [Applicator]
|
298
502
|
class UpdatedAtValue < ::Valkyrie::ValueMapper
|
299
503
|
FedoraValue.register(self)
|
504
|
+
|
505
|
+
# Determines whether or not the Property RDF statement encodes an update date
|
506
|
+
# @param [Property] value
|
507
|
+
# @return [Boolean]
|
300
508
|
def self.handles?(value)
|
301
509
|
value.statement.predicate == value.adapter.schema.predicate_for(property: :updated_at, resource: nil)
|
302
510
|
end
|
303
511
|
|
512
|
+
# Constructs a NonStringSingleApplicator object for mapping the time at which the resource was last updated
|
513
|
+
# @return [NonStringSingleApplicator]
|
304
514
|
def result
|
305
515
|
NonStringSingleApplicator.new(value)
|
306
516
|
end
|
307
517
|
end
|
308
518
|
|
519
|
+
# Class for mapping nil values to the Valkyrie attribute Hash
|
309
520
|
class NullApplicator
|
521
|
+
# No nil object is actually added (this is a no-op)
|
522
|
+
# @param [Hash] hsh a new or existing Hash of attribute for Valkyrie resource attributes
|
523
|
+
# @param [Hash]
|
310
524
|
def self.apply_to(_hsh); end
|
311
525
|
end
|
312
526
|
|
527
|
+
# Class for mapping RDF statements in Property objects to Valkyrie Resource attributes
|
313
528
|
class Applicator
|
314
529
|
attr_reader :property
|
315
530
|
delegate :statement, :adapter, to: :property
|
316
531
|
delegate :schema, to: :adapter
|
532
|
+
|
533
|
+
# @param [Property] property
|
317
534
|
def initialize(property)
|
318
535
|
@property = property
|
319
536
|
end
|
@@ -322,6 +539,8 @@ module Valkyrie::Persistence::Fedora
|
|
322
539
|
# create an array. Done to support single values - if the resource is
|
323
540
|
# a Set or Array then it'll cast the single value back to an array
|
324
541
|
# appropriately.
|
542
|
+
# @param [Hash] hsh a new or existing Hash of attribute for Valkyrie resource attributes
|
543
|
+
# @return [Hash]
|
325
544
|
def apply_to(hsh)
|
326
545
|
return if blacklist?(key)
|
327
546
|
hsh[key.to_sym] = if hsh.key?(key.to_sym)
|
@@ -331,6 +550,8 @@ module Valkyrie::Persistence::Fedora
|
|
331
550
|
end
|
332
551
|
end
|
333
552
|
|
553
|
+
# Derive the key for the Valkyrie resource attribute from the RDF statement in the Property
|
554
|
+
# @return [Symbol]
|
334
555
|
def key
|
335
556
|
predicate = statement.predicate.to_s
|
336
557
|
key = schema.property_for(resource: nil, predicate: predicate)
|
@@ -340,6 +561,10 @@ module Valkyrie::Persistence::Fedora
|
|
340
561
|
key
|
341
562
|
end
|
342
563
|
|
564
|
+
# Determines whether or not a key is blacklisted for mapping
|
565
|
+
# (For example <http://fedora.info/definitions> assertions are not mapped to Valkyrie attributes)
|
566
|
+
# @param [Symbol] key
|
567
|
+
# @return [Boolean]
|
343
568
|
def blacklist?(key)
|
344
569
|
blacklist.each do |blacklist_item|
|
345
570
|
return true if key.start_with?(blacklist_item)
|
@@ -347,6 +572,9 @@ module Valkyrie::Persistence::Fedora
|
|
347
572
|
false
|
348
573
|
end
|
349
574
|
|
575
|
+
# Casts values into an Array
|
576
|
+
# @param [Object] values
|
577
|
+
# @return [Array<Object>]
|
350
578
|
def cast_array(values)
|
351
579
|
if values.is_a?(Time)
|
352
580
|
[values]
|
@@ -355,6 +583,8 @@ module Valkyrie::Persistence::Fedora
|
|
355
583
|
end
|
356
584
|
end
|
357
585
|
|
586
|
+
# Retrieve a list of blacklisted URIs for predicates
|
587
|
+
# @return [Array<String>]
|
358
588
|
def blacklist
|
359
589
|
[
|
360
590
|
"http://fedora.info/definitions",
|
@@ -362,6 +592,8 @@ module Valkyrie::Persistence::Fedora
|
|
362
592
|
]
|
363
593
|
end
|
364
594
|
|
595
|
+
# Retrieve a list of namespace URIs for predicates
|
596
|
+
# @return [Array<String>]
|
365
597
|
def namespaces
|
366
598
|
[
|
367
599
|
"http://www.fedora.info/definitions/v4/",
|
@@ -369,25 +601,40 @@ module Valkyrie::Persistence::Fedora
|
|
369
601
|
]
|
370
602
|
end
|
371
603
|
|
604
|
+
# Access the object for the RDF statement
|
605
|
+
# @return [RDF::URI]
|
372
606
|
def values
|
373
607
|
statement.object
|
374
608
|
end
|
375
609
|
end
|
376
610
|
|
611
|
+
# Class for mapping single values
|
377
612
|
class SingleApplicator < Applicator
|
613
|
+
# Ensure that the value string is inserted into the attribute Hash
|
614
|
+
# @param [Hash] hsh a new or existing Hash of attribute for Valkyrie resource attributes
|
615
|
+
# @return [Hash]
|
378
616
|
def apply_to(hsh)
|
379
617
|
hsh[key.to_sym] = values.to_s
|
380
618
|
end
|
381
619
|
end
|
382
620
|
|
621
|
+
# Class for mapping single values other than Strings
|
383
622
|
class NonStringSingleApplicator < Applicator
|
623
|
+
# For the trivial case, insert the value into the attribute Hash
|
624
|
+
# @param [Hash] hsh a new or existing Hash of attribute for Valkyrie resource attributes
|
625
|
+
# @return [Hash]
|
384
626
|
def apply_to(hsh)
|
385
627
|
hsh[key.to_sym] = values
|
386
628
|
end
|
387
629
|
end
|
388
630
|
|
631
|
+
# Class modeling RDF statements for Fedora LDP resources
|
389
632
|
class Property
|
390
633
|
attr_reader :statement, :scope, :adapter
|
634
|
+
|
635
|
+
# @param [RDF::Statement] statement
|
636
|
+
# @param [RDF::Graph] scope
|
637
|
+
# @param [Valkyrie::Persistence::Fedora::MetadataAdapter] adapter
|
391
638
|
def initialize(statement:, scope:, adapter:)
|
392
639
|
@statement = statement
|
393
640
|
@scope = scope
|