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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +12 -4
  4. data/lib/valkyrie/persistence/composite_persister.rb +1 -1
  5. data/lib/valkyrie/persistence/fedora/list_node.rb +42 -3
  6. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +26 -0
  7. data/lib/valkyrie/persistence/fedora/ordered_list.rb +36 -5
  8. data/lib/valkyrie/persistence/fedora/ordered_reader.rb +6 -0
  9. data/lib/valkyrie/persistence/fedora/permissive_schema.rb +20 -1
  10. data/lib/valkyrie/persistence/fedora/persister.rb +33 -4
  11. data/lib/valkyrie/persistence/fedora/persister/alternate_identifier.rb +6 -0
  12. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +254 -4
  13. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +250 -3
  14. data/lib/valkyrie/persistence/fedora/persister/resource_factory.rb +6 -0
  15. data/lib/valkyrie/persistence/fedora/query_service.rb +22 -4
  16. data/lib/valkyrie/persistence/memory/metadata_adapter.rb +2 -0
  17. data/lib/valkyrie/persistence/memory/persister.rb +11 -3
  18. data/lib/valkyrie/persistence/memory/query_service.rb +11 -0
  19. data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +2 -0
  20. data/lib/valkyrie/persistence/postgres/orm.rb +4 -0
  21. data/lib/valkyrie/persistence/postgres/orm_converter.rb +62 -2
  22. data/lib/valkyrie/persistence/postgres/persister.rb +18 -7
  23. data/lib/valkyrie/persistence/postgres/query_service.rb +103 -11
  24. data/lib/valkyrie/persistence/postgres/resource_converter.rb +10 -0
  25. data/lib/valkyrie/persistence/postgres/resource_factory.rb +3 -0
  26. data/lib/valkyrie/persistence/solr/composite_indexer.rb +10 -0
  27. data/lib/valkyrie/persistence/solr/metadata_adapter.rb +7 -0
  28. data/lib/valkyrie/persistence/solr/model_converter.rb +137 -0
  29. data/lib/valkyrie/persistence/solr/orm_converter.rb +168 -0
  30. data/lib/valkyrie/persistence/solr/persister.rb +13 -5
  31. data/lib/valkyrie/persistence/solr/queries.rb +1 -0
  32. data/lib/valkyrie/persistence/solr/queries/default_paginator.rb +11 -1
  33. data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +12 -0
  34. data/lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb +12 -0
  35. data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +11 -0
  36. data/lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb +13 -0
  37. data/lib/valkyrie/persistence/solr/queries/find_many_by_ids_query.rb +9 -0
  38. data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +23 -0
  39. data/lib/valkyrie/persistence/solr/queries/find_ordered_references_query.rb +50 -0
  40. data/lib/valkyrie/persistence/solr/queries/find_references_query.rb +15 -0
  41. data/lib/valkyrie/persistence/solr/query_service.rb +47 -14
  42. data/lib/valkyrie/persistence/solr/repository.rb +21 -4
  43. data/lib/valkyrie/persistence/solr/resource_factory.rb +2 -0
  44. data/lib/valkyrie/resource.rb +1 -0
  45. data/lib/valkyrie/specs/shared_specs.rb +1 -0
  46. data/lib/valkyrie/specs/shared_specs/persister.rb +92 -2
  47. data/lib/valkyrie/specs/shared_specs/queries.rb +12 -0
  48. data/lib/valkyrie/specs/shared_specs/solr_indexer.rb +40 -0
  49. data/lib/valkyrie/storage/fedora.rb +0 -2
  50. data/lib/valkyrie/version.rb +1 -1
  51. 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 {RDF::Resource}
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
- # technically valkyrie does not support time, but when other persister support time
224
- # this code will make fedora compliant
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