valkyrie 2.1.0 → 3.0.0.pre.beta.1
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/.circleci/config.yml +71 -36
- data/.lando.yml +58 -0
- data/.rubocop.yml +11 -1
- data/.tool-versions +1 -1
- data/CHANGELOG.md +94 -13
- data/CONTRIBUTING.md +30 -8
- data/README.md +24 -48
- data/Rakefile +26 -20
- data/db/config.yml +3 -10
- data/lib/generators/valkyrie/resource_generator.rb +3 -3
- data/lib/valkyrie/change_set.rb +3 -3
- data/lib/valkyrie/id.rb +12 -19
- data/lib/valkyrie/indexers/access_controls_indexer.rb +17 -17
- data/lib/valkyrie/persistence/buffered_persister.rb +2 -2
- data/lib/valkyrie/persistence/composite_persister.rb +3 -3
- data/lib/valkyrie/persistence/custom_query_container.rb +8 -16
- data/lib/valkyrie/persistence/fedora/list_node.rb +43 -43
- data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +5 -1
- data/lib/valkyrie/persistence/fedora/ordered_list.rb +90 -90
- data/lib/valkyrie/persistence/fedora/ordered_reader.rb +5 -5
- data/lib/valkyrie/persistence/fedora/permissive_schema.rb +1 -1
- data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +15 -16
- data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +14 -19
- data/lib/valkyrie/persistence/fedora/persister.rb +83 -83
- data/lib/valkyrie/persistence/fedora/query_service.rb +39 -41
- data/lib/valkyrie/persistence/memory/persister.rb +51 -35
- data/lib/valkyrie/persistence/memory/query_service.rb +26 -30
- data/lib/valkyrie/persistence/postgres/orm_converter.rb +52 -52
- data/lib/valkyrie/persistence/postgres/persister.rb +4 -1
- data/lib/valkyrie/persistence/postgres/query_service.rb +34 -34
- data/lib/valkyrie/persistence/shared/json_value_mapper.rb +1 -1
- data/lib/valkyrie/persistence/solr/metadata_adapter.rb +15 -3
- data/lib/valkyrie/persistence/solr/model_converter.rb +323 -340
- data/lib/valkyrie/persistence/solr/orm_converter.rb +4 -4
- data/lib/valkyrie/persistence/solr/persister.rb +16 -4
- data/lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb +1 -1
- data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +1 -1
- data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +1 -1
- data/lib/valkyrie/persistence/solr/query_service.rb +12 -12
- data/lib/valkyrie/persistence/solr/repository.rb +17 -7
- data/lib/valkyrie/resource/access_controls.rb +1 -1
- data/lib/valkyrie/resource.rb +0 -1
- data/lib/valkyrie/specs/shared_specs/change_set.rb +1 -1
- data/lib/valkyrie/specs/shared_specs/file.rb +1 -0
- data/lib/valkyrie/specs/shared_specs/persister.rb +22 -4
- data/lib/valkyrie/specs/shared_specs/queries.rb +7 -0
- data/lib/valkyrie/specs/shared_specs/resource.rb +1 -1
- data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +19 -0
- data/lib/valkyrie/specs/shared_specs/write_only/metadata_adapter.rb +62 -0
- data/lib/valkyrie/specs/shared_specs.rb +2 -0
- data/lib/valkyrie/storage/disk.rb +24 -1
- data/lib/valkyrie/storage/fedora.rb +17 -17
- data/lib/valkyrie/storage_adapter.rb +12 -12
- data/lib/valkyrie/types.rb +1 -1
- data/lib/valkyrie/version.rb +1 -1
- data/lib/valkyrie/vocab/pcdm_use.rb +12 -0
- data/lib/valkyrie.rb +13 -27
- data/tasks/dev.rake +14 -51
- data/valkyrie.gemspec +3 -6
- metadata +25 -63
- data/.docker-stack/valkyrie-development/docker-compose.yml +0 -53
- data/.docker-stack/valkyrie-test/docker-compose.yml +0 -53
- data/tasks/docker.rake +0 -31
@@ -65,412 +65,395 @@ module Valkyrie::Persistence::Solr
|
|
65
65
|
|
66
66
|
private
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
68
|
+
# Maps Solr Document fields to attributes with single values
|
69
|
+
# Filters for fields which store the Valkyrie resource type
|
70
|
+
# @param [Hash] attribute_hash
|
71
|
+
# @return [Hash]
|
72
|
+
def add_single_values(attribute_hash)
|
73
|
+
attribute_hash.select do |k, v|
|
74
|
+
field = k.to_s.split("_").last
|
75
|
+
property = k.to_s.gsub("_#{field}", "")
|
76
|
+
next true if multivalued?(field)
|
77
|
+
next false if property == "internal_resource"
|
78
|
+
next false if v.length > 1
|
79
|
+
true
|
81
80
|
end
|
81
|
+
end
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
83
|
+
# Determines whether or not a field is multivalued
|
84
|
+
# @note this is tied to conventions in the Solr Schema
|
85
|
+
# @see https://github.com/samvera-labs/valkyrie/blob/main/solr/config/schema.xml
|
86
|
+
# @see https://lucene.apache.org/solr/guide/defining-fields.html#defining-fields
|
87
|
+
# @param [String] field
|
88
|
+
# @return [Boolean]
|
89
|
+
def multivalued?(field)
|
90
|
+
field.end_with?('m', 'mv')
|
91
|
+
end
|
92
92
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
93
|
+
# If optimistic locking is enabled for this Valkyrie Resource, generates a Hash containing the locking token
|
94
|
+
# @return [Hash]
|
95
|
+
def lock_hash
|
96
|
+
return {} unless resource.optimistic_locking_enabled? && lock_token.present?
|
97
|
+
{ _version_: lock_token }
|
98
|
+
end
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
end
|
100
|
+
# Retrieves the lock token from the resource attributes
|
101
|
+
# @return [String]
|
102
|
+
def lock_token
|
103
|
+
@lock_token ||= begin
|
104
|
+
found_token = resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
|
105
|
+
.find { |token| token.adapter_id == resource_factory.adapter_id }
|
106
|
+
return if found_token.nil?
|
107
|
+
found_token.token
|
109
108
|
end
|
109
|
+
end
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
111
|
+
# Generates the Valkyrie Resource attribute Hash
|
112
|
+
# @return [Hash]
|
113
|
+
def attribute_hash
|
114
|
+
properties.each_with_object({}) do |property, hsh|
|
115
|
+
next if property == Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK
|
116
|
+
attr = resource_attributes[property]
|
117
|
+
next if attr.nil?
|
118
|
+
mapper_val = SolrMapperValue.for(Property.new(property, attr)).result
|
119
|
+
unless mapper_val.respond_to?(:apply_to)
|
120
|
+
raise "Unable to cast #{resource_attributes[:internal_resource]}#" \
|
121
|
+
"#{property} which has been set to an instance of '#{attr.class}'"
|
122
|
+
end
|
123
|
+
mapper_val.apply_to(hsh)
|
124
124
|
end
|
125
|
+
end
|
125
126
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
# Access the attributes for the Valkyrie resources
|
133
|
-
# @return [Hash]
|
134
|
-
def resource_attributes
|
135
|
-
@resource_attributes ||= resource.attributes
|
136
|
-
end
|
137
|
-
|
138
|
-
##
|
139
|
-
# A container resource for holding a `key`, `value, and `scope` of a value
|
140
|
-
# in a resource together for casting.
|
141
|
-
class Property
|
142
|
-
attr_reader :key, :value, :scope
|
143
|
-
# @param key [Symbol] Property identifier.
|
144
|
-
# @param value [Object] Value or list of values which are underneath the
|
145
|
-
# key.
|
146
|
-
# @param scope [Object] The resource or point where the key and values
|
147
|
-
# came from.
|
148
|
-
def initialize(key, value, scope = [])
|
149
|
-
@key = key
|
150
|
-
@value = value
|
151
|
-
@scope = scope
|
152
|
-
end
|
153
|
-
end
|
127
|
+
# Accesses the keys for the attributes on the Valkyrie Resource
|
128
|
+
# @return [Array<Symbol>]
|
129
|
+
def properties
|
130
|
+
resource_attributes.keys - [:id, :created_at, :updated_at, :new_record]
|
131
|
+
end
|
154
132
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
# @param key [Symbol] Solr key.
|
161
|
-
# @param fields [Array<Symbol>] Field suffixes to index into.
|
162
|
-
# @param values [Array] Values to index into the given fields.
|
163
|
-
def initialize(key:, fields:, values:)
|
164
|
-
@key = key
|
165
|
-
@fields = Array.wrap(fields)
|
166
|
-
@values = Array.wrap(values)
|
167
|
-
end
|
133
|
+
# Access the attributes for the Valkyrie resources
|
134
|
+
# @return [Hash]
|
135
|
+
def resource_attributes
|
136
|
+
@resource_attributes ||= resource.attributes
|
137
|
+
end
|
168
138
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
139
|
+
##
|
140
|
+
# A container resource for holding a `key`, `value, and `scope` of a value
|
141
|
+
# in a resource together for casting.
|
142
|
+
class Property
|
143
|
+
attr_reader :key, :value, :scope
|
144
|
+
# @param key [Symbol] Property identifier.
|
145
|
+
# @param value [Object] Value or list of values which are underneath the
|
146
|
+
# key.
|
147
|
+
# @param scope [Object] The resource or point where the key and values
|
148
|
+
# came from.
|
149
|
+
def initialize(key, value, scope = [])
|
150
|
+
@key = key
|
151
|
+
@value = value
|
152
|
+
@scope = scope
|
179
153
|
end
|
154
|
+
end
|
180
155
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
# @param [Hash] hsh
|
194
|
-
# @see Valkyrie::Persistence::Solr::Mapper::SolrRow#apply_to
|
195
|
-
def apply_to(hsh)
|
196
|
-
solr_rows.each do |solr_row|
|
197
|
-
solr_row.apply_to(hsh)
|
198
|
-
end
|
199
|
-
hsh
|
200
|
-
end
|
156
|
+
##
|
157
|
+
# Represents a key/value combination in the solr document, used for isolating logic around
|
158
|
+
# how to apply a value to a hash.
|
159
|
+
class SolrRow
|
160
|
+
attr_reader :key, :fields, :values
|
161
|
+
# @param key [Symbol] Solr key.
|
162
|
+
# @param fields [Array<Symbol>] Field suffixes to index into.
|
163
|
+
# @param values [Array] Values to index into the given fields.
|
164
|
+
def initialize(key:, fields:, values:)
|
165
|
+
@key = key
|
166
|
+
@fields = fields
|
167
|
+
@values = values
|
201
168
|
end
|
202
169
|
|
203
|
-
#
|
204
|
-
|
170
|
+
# @param hsh [Hash] The solr hash to apply to.
|
171
|
+
# @return [Hash] The updated solr hash.
|
172
|
+
def apply_to(hsh)
|
173
|
+
return hsh if values.blank?
|
174
|
+
fields.each do |field|
|
175
|
+
hsh["#{key}_#{field}".to_sym] ||= []
|
176
|
+
hsh["#{key}_#{field}".to_sym] += values
|
177
|
+
end
|
178
|
+
hsh
|
205
179
|
end
|
180
|
+
end
|
206
181
|
|
207
|
-
|
208
|
-
|
209
|
-
|
182
|
+
##
|
183
|
+
# Wraps up multiple SolrRows to apply them all at once, while looking like
|
184
|
+
# just one.
|
185
|
+
class CompositeSolrRow
|
186
|
+
attr_reader :solr_rows
|
210
187
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
value.is_a?(Property) && ([true, false].include? value.value)
|
216
|
-
end
|
188
|
+
# @param [Array<Valkyrie::Persistence::Solr::Mapper::SolrRow>] solr_rows
|
189
|
+
def initialize(solr_rows)
|
190
|
+
@solr_rows = solr_rows
|
191
|
+
end
|
217
192
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
193
|
+
# Merge a Hash of attribute values into a logical row of Solr fields
|
194
|
+
# @param [Hash] hsh
|
195
|
+
# @see Valkyrie::Persistence::Solr::Mapper::SolrRow#apply_to
|
196
|
+
def apply_to(hsh)
|
197
|
+
solr_rows.each do |solr_row|
|
198
|
+
solr_row.apply_to(hsh)
|
223
199
|
end
|
200
|
+
hsh
|
224
201
|
end
|
202
|
+
end
|
225
203
|
|
226
|
-
|
227
|
-
|
228
|
-
|
204
|
+
# Container for casting mappers.
|
205
|
+
class SolrMapperValue < ::Valkyrie::ValueMapper
|
206
|
+
end
|
229
207
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
def self.handles?(value)
|
234
|
-
value.value.is_a?(Hash) || value.value.is_a?(Valkyrie::Resource)
|
235
|
-
end
|
208
|
+
# Casts {Boolean} values into a recognizable string in Solr.
|
209
|
+
class BooleanPropertyValue < ::Valkyrie::ValueMapper
|
210
|
+
SolrMapperValue.register(self)
|
236
211
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
# @return [SolrRow]
|
243
|
-
def result
|
244
|
-
SolrRow.new(key: value.key, fields: ["tsim"], values: "serialized-#{value.value.to_json}")
|
245
|
-
end
|
212
|
+
# Determines whether or not a Property value behaves like a boolean value
|
213
|
+
# @param [Object] value
|
214
|
+
# @return [Boolean]
|
215
|
+
def self.handles?(value)
|
216
|
+
value.is_a?(Property) && ([true, false].include? value.value)
|
246
217
|
end
|
247
218
|
|
248
|
-
#
|
249
|
-
|
250
|
-
|
219
|
+
# Constructs a SolrRow object for a Property with a Boolean value
|
220
|
+
# @note this prepends the string "boolean-" to the value indexed in Solr
|
221
|
+
# @return [SolrRow]
|
222
|
+
def result
|
223
|
+
calling_mapper.for(Property.new(value.key, "boolean-#{value.value}")).result
|
224
|
+
end
|
225
|
+
end
|
251
226
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
def self.handles?(value)
|
256
|
-
value.is_a?(Property) && value.value.is_a?(Array)
|
257
|
-
end
|
227
|
+
# Casts nested resources into a JSON string in solr.
|
228
|
+
class NestedObjectValue < ::Valkyrie::ValueMapper
|
229
|
+
SolrMapperValue.register(self)
|
258
230
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
calling_mapper.for(Property.new(value.key, val, value.value)).result
|
265
|
-
end
|
266
|
-
)
|
267
|
-
end
|
231
|
+
# Determines whether or not a Property value is a Hash
|
232
|
+
# @param [Object] value
|
233
|
+
# @return [Boolean]
|
234
|
+
def self.handles?(value)
|
235
|
+
value.value.is_a?(Hash) || value.value.is_a?(Valkyrie::Resource)
|
268
236
|
end
|
269
237
|
|
270
|
-
#
|
271
|
-
|
272
|
-
|
238
|
+
# Constructs a SolrRow object for a Property with a Hash value
|
239
|
+
# @note this prepends the string "serialized-" to the value indexed in Solr
|
240
|
+
# This is indexed as a stored multivalued text
|
241
|
+
# @see https://lucene.apache.org/solr/guide/defining-fields.html#defining-fields
|
242
|
+
# @see https://github.com/samvera-labs/valkyrie/blob/main/solr/config/schema.xml
|
243
|
+
# @return [SolrRow]
|
244
|
+
def result
|
245
|
+
SolrRow.new(key: value.key, fields: ["tsim"], values: ["serialized-#{value.value.to_json}"])
|
246
|
+
end
|
247
|
+
end
|
273
248
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
def self.handles?(value)
|
278
|
-
value.is_a?(Property) && value.value.nil?
|
279
|
-
end
|
249
|
+
# Casts enumerable values one by one.
|
250
|
+
class EnumerableValue < ::Valkyrie::ValueMapper
|
251
|
+
SolrMapperValue.register(self)
|
280
252
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
253
|
+
# Determines whether or not a Property value is an Array
|
254
|
+
# @param [Object] value
|
255
|
+
# @return [Boolean]
|
256
|
+
def self.handles?(value)
|
257
|
+
value.is_a?(Property) && value.value.is_a?(Array)
|
258
|
+
end
|
259
|
+
|
260
|
+
# Constructs a CompositeSolrRow object for a set of Property values
|
261
|
+
# @return [CompositeSolrRow]
|
262
|
+
def result
|
263
|
+
CompositeSolrRow.new(
|
264
|
+
value.value.map do |val|
|
265
|
+
calling_mapper.for(Property.new(value.key, val, value.value)).result
|
266
|
+
end
|
267
|
+
)
|
286
268
|
end
|
269
|
+
end
|
287
270
|
|
288
|
-
|
289
|
-
|
290
|
-
|
271
|
+
# Casts {Valkyrie::ID} values into a recognizable string in solr.
|
272
|
+
class IDPropertyValue < ::Valkyrie::ValueMapper
|
273
|
+
SolrMapperValue.register(self)
|
291
274
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
275
|
+
# Determines whether or not a Property value is a Valkyrie ID
|
276
|
+
# @param [Object] value
|
277
|
+
# @return [Boolean]
|
278
|
+
def self.handles?(value)
|
279
|
+
value.is_a?(Property) && value.value.is_a?(::Valkyrie::ID)
|
280
|
+
end
|
298
281
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
end
|
282
|
+
# Constructs a SolrRow object for the Property Valkyrie ID value
|
283
|
+
# @note this prepends the string "id-" to the value indexed in Solr
|
284
|
+
# @return [SolrRow]
|
285
|
+
def result
|
286
|
+
calling_mapper.for(Property.new(value.key, "id-#{value.value.id}")).result
|
305
287
|
end
|
288
|
+
end
|
306
289
|
|
307
|
-
|
308
|
-
|
309
|
-
|
290
|
+
# Casts {RDF::URI} values into a recognizable string in solr.
|
291
|
+
class URIPropertyValue < ::Valkyrie::ValueMapper
|
292
|
+
SolrMapperValue.register(self)
|
310
293
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
294
|
+
# Determines whether or not a Property value is a URI
|
295
|
+
# @param [Object] value
|
296
|
+
# @return [Boolean]
|
297
|
+
def self.handles?(value)
|
298
|
+
value.is_a?(Property) && value.value.is_a?(::RDF::URI)
|
299
|
+
end
|
317
300
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
end
|
301
|
+
# Constructs a SolrRow object for the Property URI value
|
302
|
+
# @note this prepends the string "uri-" to the value indexed in Solr
|
303
|
+
# @return [SolrRow]
|
304
|
+
def result
|
305
|
+
calling_mapper.for(Property.new(value.key, "uri-#{value.value}")).result
|
324
306
|
end
|
307
|
+
end
|
325
308
|
|
326
|
-
|
327
|
-
|
328
|
-
|
309
|
+
# Casts {Integer} values into a recognizable string in Solr.
|
310
|
+
class IntegerPropertyValue < ::Valkyrie::ValueMapper
|
311
|
+
SolrMapperValue.register(self)
|
329
312
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
313
|
+
# Determines whether or not a Property value is an Integer
|
314
|
+
# @param [Object] value
|
315
|
+
# @return [Boolean]
|
316
|
+
def self.handles?(value)
|
317
|
+
value.is_a?(Property) && value.value.is_a?(Integer)
|
318
|
+
end
|
336
319
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
end
|
320
|
+
# Constructs a SolrRow object for the Property Integer value
|
321
|
+
# @note this prepends the string "integer-" to the value indexed in Solr
|
322
|
+
# @return [SolrRow]
|
323
|
+
def result
|
324
|
+
calling_mapper.for(Property.new(value.key, "integer-#{value.value}")).result
|
343
325
|
end
|
326
|
+
end
|
344
327
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
328
|
+
# Casts {Float} values into a recognizable string in Solr.
|
329
|
+
class FloatPropertyValue < ::Valkyrie::ValueMapper
|
330
|
+
SolrMapperValue.register(self)
|
331
|
+
def self.handles?(value)
|
332
|
+
value.is_a?(Property) && value.value.is_a?(Float)
|
333
|
+
end
|
351
334
|
|
352
|
-
|
353
|
-
|
354
|
-
end
|
335
|
+
def result
|
336
|
+
calling_mapper.for(Property.new(value.key, "float-#{value.value}")).result
|
355
337
|
end
|
338
|
+
end
|
356
339
|
|
357
|
-
|
358
|
-
|
359
|
-
|
340
|
+
# Casts {DateTime} values into a recognizable string in Solr.
|
341
|
+
class DateTimePropertyValue < ::Valkyrie::ValueMapper
|
342
|
+
SolrMapperValue.register(self)
|
360
343
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
344
|
+
# Determines whether or not a Property value is a DateTime or Time
|
345
|
+
# @param [Object] value
|
346
|
+
# @return [Boolean]
|
347
|
+
def self.handles?(value)
|
348
|
+
value.is_a?(Property) && (value.value.is_a?(Time) || value.value.is_a?(DateTime))
|
349
|
+
end
|
367
350
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
351
|
+
# Constructs a SolrRow object for a datestamp derived from the value
|
352
|
+
# @note this prepends the string "datetime-" to the value indexed in Solr
|
353
|
+
# @return [SolrRow]
|
354
|
+
def result
|
355
|
+
calling_mapper.for(Property.new(value.key, "datetime-#{JSON.parse(to_datetime(value.value).to_json)}")).result
|
356
|
+
end
|
374
357
|
|
375
|
-
|
358
|
+
private
|
376
359
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
end
|
360
|
+
# Converts a value to a UTC timestamp if it is a DateTime or behaves like a Time value
|
361
|
+
# @param [Object] value
|
362
|
+
# @return [Time]
|
363
|
+
def to_datetime(value)
|
364
|
+
return value.new_offset(0) if value.is_a?(DateTime)
|
365
|
+
return value.to_datetime.new_offset(0) if value.respond_to?(:to_datetime)
|
384
366
|
end
|
367
|
+
end
|
385
368
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
369
|
+
# Handles casting language-tagged strings when there are both
|
370
|
+
# language-tagged and non-language-tagged strings in Solr. Assumes English
|
371
|
+
# for non-language-tagged strings.
|
372
|
+
class SharedStringPropertyValue < ::Valkyrie::ValueMapper
|
373
|
+
SolrMapperValue.register(self)
|
391
374
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
375
|
+
# Determines whether or not a Property value is a String whether or not the Property has an RDF literal specifying the language tag
|
376
|
+
# @param [Object] value
|
377
|
+
# @return [Boolean]
|
378
|
+
def self.handles?(value)
|
379
|
+
value.is_a?(Property) && value.value.is_a?(String) && value.scope.find { |x| x.is_a?(::RDF::Literal) }.present?
|
380
|
+
end
|
398
381
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
end
|
382
|
+
# Constructs a CompositeSolrRow object with the language-tagged literal value
|
383
|
+
# @return [CompositeSolrRow]
|
384
|
+
def result
|
385
|
+
CompositeSolrRow.new(
|
386
|
+
[
|
387
|
+
calling_mapper.for(Property.new(value.key, value.value)).result,
|
388
|
+
calling_mapper.for(Property.new("#{value.key}_lang", "eng")).result,
|
389
|
+
calling_mapper.for(Property.new("#{value.key}_type", "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString")).result
|
390
|
+
]
|
391
|
+
)
|
410
392
|
end
|
393
|
+
end
|
411
394
|
|
412
|
-
|
413
|
-
|
414
|
-
|
395
|
+
# Handles casting strings.
|
396
|
+
class StringPropertyValue < ::Valkyrie::ValueMapper
|
397
|
+
SolrMapperValue.register(self)
|
415
398
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
399
|
+
# Determines whether or not a Property value is a String
|
400
|
+
# @param [Object] value
|
401
|
+
# @return [Boolean]
|
402
|
+
def self.handles?(value)
|
403
|
+
value.is_a?(Property) && value.value.is_a?(String)
|
404
|
+
end
|
422
405
|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
406
|
+
# Constructs a SolrRow object with the String values and Solr field settings
|
407
|
+
# @return [SolrRow]
|
408
|
+
def result
|
409
|
+
SolrRow.new(key: value.key, fields: fields, values: [value.value])
|
410
|
+
end
|
428
411
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
end
|
412
|
+
# Generates the Solr fields used during the indexing
|
413
|
+
# String are normally indexed using the following:
|
414
|
+
# - stored text
|
415
|
+
# - stored english text
|
416
|
+
# - stored single string
|
417
|
+
# - multivalued string
|
418
|
+
# - stored multivalued text
|
419
|
+
# - stored multivalued english text
|
420
|
+
# If the string is greater than 1000 characters in length, it is only indexed as a stored multivalued text
|
421
|
+
# @see https://lucene.apache.org/solr/guide/defining-fields.html#defining-fields
|
422
|
+
# @see https://github.com/samvera-labs/valkyrie/blob/main/solr/config/schema.xml
|
423
|
+
# @return [Array<Symbol>]
|
424
|
+
def fields
|
425
|
+
if value.value.length > 1000
|
426
|
+
[:tsim]
|
427
|
+
else
|
428
|
+
[:tsim, :ssim, :tesim, :tsi, :ssi, :tesi]
|
447
429
|
end
|
448
430
|
end
|
431
|
+
end
|
449
432
|
|
450
|
-
|
451
|
-
|
452
|
-
|
433
|
+
# Handles casting language-typed {RDF::Literal}s
|
434
|
+
class LiteralPropertyValue < ::Valkyrie::ValueMapper
|
435
|
+
SolrMapperValue.register(self)
|
453
436
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
437
|
+
# Determines whether or not a Property value is an RDF literal
|
438
|
+
# @param [Object] value
|
439
|
+
# @return [Boolean]
|
440
|
+
def self.handles?(value)
|
441
|
+
value.is_a?(Property) && value.value.is_a?(::RDF::Literal)
|
442
|
+
end
|
460
443
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
end
|
444
|
+
# Constructs a CompositeSolrRow object with the language-tagged literal value
|
445
|
+
# @return [CompositeSolrRow]
|
446
|
+
def result
|
447
|
+
key = value.key
|
448
|
+
val = value.value
|
449
|
+
CompositeSolrRow.new(
|
450
|
+
[
|
451
|
+
calling_mapper.for(Property.new(key, val.to_s)).result,
|
452
|
+
calling_mapper.for(Property.new("#{key}_lang", val.language.to_s)).result,
|
453
|
+
calling_mapper.for(Property.new("#{key}_type", val.datatype.to_s)).result
|
454
|
+
]
|
455
|
+
)
|
474
456
|
end
|
457
|
+
end
|
475
458
|
end
|
476
459
|
end
|