valkyrie 0.1.0 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/.ctags +2 -0
  3. data/.rubocop.yml +5 -0
  4. data/.rubocop_todo.yml +3 -0
  5. data/CHANGELOG.md +43 -0
  6. data/Gemfile +0 -4
  7. data/LICENSE +15 -0
  8. data/README.md +13 -8
  9. data/Rakefile +15 -1
  10. data/bin/jetty_wait +14 -0
  11. data/bin/rspec +29 -0
  12. data/browserslist +3 -0
  13. data/circle.yml +17 -0
  14. data/config/fedora.yml +10 -0
  15. data/db/migrate/20161007101725_create_orm_resources.rb +9 -1
  16. data/db/migrate/20171011224121_create_path_gin_index.rb +6 -0
  17. data/db/migrate/20171204224121_create_internal_resource_index.rb +6 -0
  18. data/db/migrate/20180212092225_create_updated_at_index.rb +6 -0
  19. data/lib/generators/valkyrie/templates/resource_spec.rb.erb +1 -1
  20. data/lib/valkyrie.rb +1 -7
  21. data/lib/valkyrie/change_set.rb +21 -7
  22. data/lib/valkyrie/engine.rb +2 -0
  23. data/lib/valkyrie/id.rb +1 -0
  24. data/lib/valkyrie/indexers/access_controls_indexer.rb +50 -6
  25. data/lib/valkyrie/metadata_adapter.rb +29 -1
  26. data/lib/valkyrie/persistence.rb +27 -0
  27. data/lib/valkyrie/persistence/buffered_persister.rb +17 -1
  28. data/lib/valkyrie/persistence/composite_persister.rb +14 -2
  29. data/lib/valkyrie/persistence/custom_query_container.rb +63 -0
  30. data/lib/valkyrie/persistence/delete_tracking_buffer.rb +8 -0
  31. data/lib/valkyrie/persistence/fedora.rb +3 -0
  32. data/lib/valkyrie/persistence/fedora/list_node.rb +5 -2
  33. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +13 -11
  34. data/lib/valkyrie/persistence/fedora/ordered_list.rb +2 -2
  35. data/lib/valkyrie/persistence/fedora/ordered_reader.rb +3 -2
  36. data/lib/valkyrie/persistence/fedora/permissive_schema.rb +75 -0
  37. data/lib/valkyrie/persistence/fedora/persister.rb +22 -0
  38. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +110 -25
  39. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +49 -17
  40. data/lib/valkyrie/persistence/fedora/persister/resource_factory.rb +2 -0
  41. data/lib/valkyrie/persistence/fedora/query_service.rb +46 -3
  42. data/lib/valkyrie/persistence/memory.rb +5 -0
  43. data/lib/valkyrie/persistence/memory/metadata_adapter.rb +6 -1
  44. data/lib/valkyrie/persistence/memory/persister.rb +19 -1
  45. data/lib/valkyrie/persistence/memory/query_service.rb +49 -8
  46. data/lib/valkyrie/persistence/postgres.rb +2 -0
  47. data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +8 -1
  48. data/lib/valkyrie/persistence/postgres/orm.rb +1 -0
  49. data/lib/valkyrie/persistence/postgres/orm/resource.rb +12 -0
  50. data/lib/valkyrie/persistence/postgres/orm_converter.rb +99 -74
  51. data/lib/valkyrie/persistence/postgres/persister.rb +16 -0
  52. data/lib/valkyrie/persistence/postgres/query_service.rb +94 -6
  53. data/lib/valkyrie/persistence/postgres/resource_converter.rb +3 -1
  54. data/lib/valkyrie/persistence/postgres/resource_factory.rb +5 -5
  55. data/lib/valkyrie/persistence/solr.rb +2 -0
  56. data/lib/valkyrie/persistence/solr/composite_indexer.rb +29 -0
  57. data/lib/valkyrie/persistence/solr/metadata_adapter.rb +26 -1
  58. data/lib/valkyrie/persistence/solr/model_converter.rb +38 -8
  59. data/lib/valkyrie/persistence/solr/orm_converter.rb +43 -20
  60. data/lib/valkyrie/persistence/solr/persister.rb +16 -0
  61. data/lib/valkyrie/persistence/solr/queries.rb +3 -0
  62. data/lib/valkyrie/persistence/solr/queries/default_paginator.rb +2 -0
  63. data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +3 -1
  64. data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +4 -2
  65. data/lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb +2 -0
  66. data/lib/valkyrie/persistence/solr/queries/find_many_by_ids_query.rb +21 -0
  67. data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +13 -5
  68. data/lib/valkyrie/persistence/solr/queries/find_references_query.rb +7 -3
  69. data/lib/valkyrie/persistence/solr/query_service.rb +30 -2
  70. data/lib/valkyrie/persistence/solr/repository.rb +14 -2
  71. data/lib/valkyrie/persistence/solr/resource_factory.rb +3 -1
  72. data/lib/valkyrie/resource.rb +11 -4
  73. data/lib/valkyrie/resource/access_controls.rb +13 -0
  74. data/lib/valkyrie/specs/shared_specs.rb +1 -2
  75. data/lib/valkyrie/specs/shared_specs/change_set.rb +75 -0
  76. data/lib/valkyrie/specs/shared_specs/metadata_adapter.rb +3 -0
  77. data/lib/valkyrie/specs/shared_specs/persister.rb +145 -15
  78. data/lib/valkyrie/specs/shared_specs/queries.rb +153 -27
  79. data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +8 -3
  80. data/lib/valkyrie/storage.rb +29 -0
  81. data/lib/valkyrie/storage/disk.rb +17 -5
  82. data/lib/valkyrie/storage/fedora.rb +14 -1
  83. data/lib/valkyrie/storage/memory.rb +15 -2
  84. data/lib/valkyrie/storage_adapter.rb +26 -4
  85. data/lib/valkyrie/types.rb +65 -7
  86. data/lib/valkyrie/version.rb +1 -1
  87. data/solr/config/_rest_managed.json +3 -0
  88. data/solr/config/admin-extra.html +31 -0
  89. data/solr/config/elevate.xml +36 -0
  90. data/solr/config/mapping-ISOLatin1Accent.txt +246 -0
  91. data/solr/config/protwords.txt +21 -0
  92. data/solr/config/schema.xml +366 -0
  93. data/solr/config/scripts.conf +24 -0
  94. data/solr/config/solrconfig.xml +322 -0
  95. data/solr/config/spellings.txt +2 -0
  96. data/solr/config/stopwords.txt +58 -0
  97. data/solr/config/stopwords_en.txt +58 -0
  98. data/solr/config/synonyms.txt +31 -0
  99. data/solr/config/xslt/example.xsl +132 -0
  100. data/solr/config/xslt/example_atom.xsl +67 -0
  101. data/solr/config/xslt/example_rss.xsl +66 -0
  102. data/solr/config/xslt/luke.xsl +337 -0
  103. data/solr/solr.xml +35 -0
  104. data/tasks/dev.rake +66 -0
  105. data/valkyrie.gemspec +6 -6
  106. metadata +58 -63
  107. data/lib/valkyrie/decorators/decorator_list.rb +0 -15
  108. data/lib/valkyrie/decorators/decorator_with_arguments.rb +0 -14
  109. data/lib/valkyrie/derivative_service.rb +0 -42
  110. data/lib/valkyrie/file_characterization_service.rb +0 -42
  111. data/lib/valkyrie/local_file_service.rb +0 -11
  112. data/lib/valkyrie/persist_derivatives.rb +0 -29
  113. data/lib/valkyrie/persistence/postgres/queries.rb +0 -8
  114. data/lib/valkyrie/persistence/postgres/queries/find_inverse_references_query.rb +0 -31
  115. data/lib/valkyrie/persistence/postgres/queries/find_members_query.rb +0 -33
  116. data/lib/valkyrie/persistence/postgres/queries/find_references_query.rb +0 -33
  117. data/lib/valkyrie/specs/shared_specs/derivative_service.rb +0 -30
  118. data/lib/valkyrie/specs/shared_specs/file_characterization_service.rb +0 -33
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
3
  class Persister
4
+ # Responsible for converting {Valkyrie::Resource} to {LDP::Container::Basic}
4
5
  class ModelConverter
5
6
  attr_reader :resource, :adapter, :subject_uri
6
7
  delegate :connection, :connection_prefix, :base_path, to: :adapter
@@ -12,13 +13,21 @@ module Valkyrie::Persistence::Fedora
12
13
 
13
14
  def convert
14
15
  graph_resource.graph.delete([nil, nil, nil])
15
- resource.attributes.each do |key, values|
16
- output = property_converter.for(Property.new(subject_uri, key, values, adapter)).result
16
+ properties.each do |property|
17
+ values = resource_attributes[property]
18
+
19
+ output = property_converter.for(Property.new(subject_uri, property, values, adapter, resource)).result
17
20
  graph_resource.graph << output.to_graph
18
21
  end
19
22
  graph_resource
20
23
  end
21
24
 
25
+ def properties
26
+ resource_attributes.keys - [:new_record]
27
+ end
28
+
29
+ delegate :attributes, to: :resource, prefix: true
30
+
22
31
  def graph_resource
23
32
  @graph_resource ||= ::Ldp::Container::Basic.new(connection, subject, nil, base_path)
24
33
  end
@@ -32,25 +41,27 @@ module Valkyrie::Persistence::Fedora
32
41
  end
33
42
 
34
43
  class Property
35
- attr_reader :key, :value, :subject, :adapter
44
+ attr_reader :key, :value, :subject, :adapter, :resource
45
+ delegate :schema, to: :adapter
36
46
 
37
- def self.to_uri(key)
38
- RDF::URI.new("http://example.com/predicate/#{key}")
39
- end
40
-
41
- def initialize(subject, key, value, adapter)
47
+ def initialize(subject, key, value, adapter, resource)
42
48
  @subject = subject
43
49
  @key = key
44
50
  @value = value
45
51
  @adapter = adapter
52
+ @resource = resource
46
53
  end
47
54
 
48
55
  def to_graph(graph = RDF::Graph.new)
49
56
  Array(value).each do |val|
50
- graph << RDF::Statement.new(subject, self.class.to_uri(key), val)
57
+ graph << RDF::Statement.new(subject, predicate, val)
51
58
  end
52
59
  graph
53
60
  end
61
+
62
+ def predicate
63
+ schema.predicate_for(resource: resource, property: key)
64
+ end
54
65
  end
55
66
 
56
67
  class CompositeProperty
@@ -68,12 +79,13 @@ module Valkyrie::Persistence::Fedora
68
79
  end
69
80
 
70
81
  class GraphProperty
71
- attr_reader :key, :graph, :subject, :adapter
72
- def initialize(subject, key, graph, adapter)
82
+ attr_reader :key, :graph, :subject, :adapter, :resource
83
+ def initialize(subject, key, graph, adapter, resource)
73
84
  @subject = subject
74
85
  @key = key
75
86
  @graph = graph
76
87
  @adapter = adapter
88
+ @resource = resource
77
89
  end
78
90
 
79
91
  def to_graph(passed_graph = RDF::Graph.new)
@@ -93,7 +105,7 @@ module Valkyrie::Persistence::Fedora
93
105
  def result
94
106
  initialize_list
95
107
  apply_first_and_last
96
- GraphProperty.new(value.subject, value.key, graph, value.adapter)
108
+ GraphProperty.new(value.subject, value.key, graph, value.adapter, value.resource)
97
109
  end
98
110
 
99
111
  def graph
@@ -108,7 +120,7 @@ module Valkyrie::Persistence::Fedora
108
120
 
109
121
  def initialize_list
110
122
  Array(value.value).each_with_index do |val, index|
111
- ordered_list.insert_proxy_for_at(index, calling_mapper.for(Property.new(value.subject, :member_id, val, value.adapter)).result.value)
123
+ ordered_list.insert_proxy_for_at(index, calling_mapper.for(Property.new(value.subject, :member_id, val, value.adapter, value.resource)).result.value)
112
124
  end
113
125
  end
114
126
 
@@ -124,8 +136,8 @@ module Valkyrie::Persistence::Fedora
124
136
  end
125
137
 
126
138
  def result
127
- nested_graph << RDF::Statement.new(value.subject, Property.to_uri(value.key), subject_uri)
128
- GraphProperty.new(value.subject, value.key, nested_graph, value.adapter)
139
+ nested_graph << RDF::Statement.new(value.subject, value.predicate, subject_uri)
140
+ GraphProperty.new(value.subject, value.key, nested_graph, value.adapter, value.resource)
129
141
  end
130
142
 
131
143
  def nested_graph
@@ -137,51 +149,124 @@ module Valkyrie::Persistence::Fedora
137
149
  end
138
150
  end
139
151
 
140
- class NestedInternalValkyrieID < ::Valkyrie::ValueMapper
152
+ class MappedFedoraValue < ::Valkyrie::ValueMapper
153
+ private
154
+
155
+ def map_value(converted_value:)
156
+ calling_mapper.for(
157
+ Property.new(
158
+ value.subject,
159
+ value.key,
160
+ converted_value,
161
+ value.adapter,
162
+ value.resource
163
+ )
164
+ ).result
165
+ end
166
+ end
167
+
168
+ class NestedInternalValkyrieID < MappedFedoraValue
141
169
  FedoraValue.register(self)
142
170
  def self.handles?(value)
143
171
  value.is_a?(Property) && value.value.is_a?(Valkyrie::ID) && value.subject.to_s.include?("#")
144
172
  end
145
173
 
146
174
  def result
147
- calling_mapper.for(Property.new(value.subject, value.key, RDF::Literal.new(value.value, datatype: RDF::URI("http://example.com/predicate/valkyrie_id")), value.adapter)).result
175
+ map_value(converted_value: RDF::Literal.new(
176
+ value.value,
177
+ datatype: PermissiveSchema.valkyrie_id
178
+ ))
148
179
  end
149
180
  end
150
181
 
151
- class InternalValkyrieID < ::Valkyrie::ValueMapper
182
+ class InternalValkyrieID < MappedFedoraValue
152
183
  FedoraValue.register(self)
153
184
  def self.handles?(value)
154
185
  value.is_a?(Property) && value.value.is_a?(Valkyrie::ID) && !value.value.to_s.include?("://")
155
186
  end
156
187
 
157
188
  def result
158
- calling_mapper.for(Property.new(value.subject, value.key, value.adapter.id_to_uri(value.value), value.adapter)).result
189
+ map_value(converted_value: value.adapter.id_to_uri(value.value))
190
+ end
191
+ end
192
+
193
+ class BooleanValue < MappedFedoraValue
194
+ FedoraValue.register(self)
195
+ def self.handles?(value)
196
+ value.is_a?(Property) && ([true, false].include? value.value)
197
+ end
198
+
199
+ def result
200
+ map_value(converted_value: RDF::Literal.new(
201
+ value.value,
202
+ datatype: PermissiveSchema.valkyrie_bool
203
+ ))
204
+ end
205
+ end
206
+
207
+ class IntegerValue < MappedFedoraValue
208
+ FedoraValue.register(self)
209
+ def self.handles?(value)
210
+ value.is_a?(Property) && value.value.is_a?(Integer)
211
+ end
212
+
213
+ def result
214
+ map_value(converted_value: RDF::Literal.new(
215
+ value.value,
216
+ datatype: PermissiveSchema.valkyrie_int
217
+ ))
218
+ end
219
+ end
220
+
221
+ class DateTimeValue < MappedFedoraValue
222
+ FedoraValue.register(self)
223
+ def self.handles?(value)
224
+ value.is_a?(Property) && value.value.is_a?(DateTime)
225
+ end
226
+
227
+ def result
228
+ map_value(converted_value: RDF::Literal.new(
229
+ value.value,
230
+ datatype: PermissiveSchema.valkyrie_datetime
231
+ ))
159
232
  end
160
233
  end
161
234
 
162
- class TimeValue < ::Valkyrie::ValueMapper
235
+ # technically valkyrie does not support time, but when other persister support time
236
+ # this code will make fedora compliant
237
+ #
238
+ # https://github.com/samvera-labs/valkyrie/wiki/Supported-Data-Types
239
+ class TimeValue < MappedFedoraValue
163
240
  FedoraValue.register(self)
164
241
  def self.handles?(value)
165
242
  value.is_a?(Property) && value.value.is_a?(Time)
166
243
  end
167
244
 
168
245
  def result
169
- calling_mapper.for(Property.new(value.subject, value.key, value.value.to_datetime, value.adapter)).result
246
+ # cast it to datetime for storage, to preserve miliseconds and date
247
+ map_value(converted_value:
248
+ RDF::Literal.new(
249
+ value.value.to_datetime,
250
+ datatype: PermissiveSchema.valkyrie_time
251
+ ))
170
252
  end
171
253
  end
172
254
 
173
- class IdentifiableValue < ::Valkyrie::ValueMapper
255
+ class IdentifiableValue < MappedFedoraValue
174
256
  FedoraValue.register(self)
175
257
  def self.handles?(value)
176
258
  value.is_a?(Property) && value.value.is_a?(Valkyrie::ID)
177
259
  end
178
260
 
179
261
  def result
180
- calling_mapper.for(Property.new(value.subject, value.key, RDF::Literal.new(value.value, datatype: RDF::URI("http://example.com/predicate/valkyrie_id")), value.adapter)).result
262
+ map_value(converted_value: RDF::Literal.new(
263
+ value.value,
264
+ datatype: PermissiveSchema.valkyrie_id
265
+ ))
181
266
  end
182
267
  end
183
268
 
184
- class EnumerableValue < ::Valkyrie::ValueMapper
269
+ class EnumerableValue < MappedFedoraValue
185
270
  FedoraValue.register(self)
186
271
  def self.handles?(value)
187
272
  value.is_a?(Property) && value.value.is_a?(Array)
@@ -189,7 +274,7 @@ module Valkyrie::Persistence::Fedora
189
274
 
190
275
  def result
191
276
  new_values = value.value.map do |val|
192
- calling_mapper.for(Property.new(value.subject, value.key, val, value.adapter)).result
277
+ map_value(converted_value: val)
193
278
  end
194
279
  CompositeProperty.new(new_values)
195
280
  end
@@ -1,6 +1,7 @@
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
5
  class OrmConverter
5
6
  attr_reader :object, :adapter
6
7
  delegate :graph, to: :object
@@ -14,8 +15,9 @@ module Valkyrie::Persistence::Fedora
14
15
  end
15
16
 
16
17
  def attributes
17
- GraphToAttributes.new(graph: graph, adapter: adapter).convert.merge(id:
18
- id)
18
+ GraphToAttributes.new(graph: graph, adapter: adapter)
19
+ .convert
20
+ .merge(id: id, new_record: false)
19
21
  end
20
22
 
21
23
  def id
@@ -24,7 +26,7 @@ module Valkyrie::Persistence::Fedora
24
26
 
25
27
  def id_property
26
28
  return unless object.subject_uri.to_s.include?("#")
27
- object.graph.query([RDF::URI(""), RDF::URI("http://example.com/predicate/id"), nil]).to_a.first.try(:object).to_s
29
+ object.graph.query([RDF::URI(""), PermissiveSchema.id, nil]).to_a.first.try(:object).to_s
28
30
  end
29
31
 
30
32
  class GraphToAttributes
@@ -95,7 +97,7 @@ module Valkyrie::Persistence::Fedora
95
97
  end
96
98
 
97
99
  def result
98
- value.statement.predicate = ::RDF::URI("http://example.com/predicate/member_ids")
100
+ value.statement.predicate = PermissiveSchema.member_ids
99
101
  values = OrderedList.new(scope, head, tail, adapter).to_a.map(&:proxy_for)
100
102
  values = values.map do |val|
101
103
  calling_mapper.for(Property.new(statement: RDF::Statement.new(value.statement.subject, value.statement.predicate, val), scope: value.scope, adapter: value.adapter)).result
@@ -159,14 +161,14 @@ module Valkyrie::Persistence::Fedora
159
161
  end
160
162
  end
161
163
 
162
- class IntegerValue < ::Valkyrie::ValueMapper
164
+ class BooleanValue < ::Valkyrie::ValueMapper
163
165
  FedoraValue.register(self)
164
166
  def self.handles?(value)
165
- value.statement.object.is_a?(RDF::Literal) && value.statement.object.datatype == RDF::URI("http://www.w3.org/2001/XMLSchema#integer")
167
+ value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_bool
166
168
  end
167
169
 
168
170
  def result
169
- value.statement.object = value.statement.object.to_i
171
+ value.statement.object = value.statement.object.value.casecmp("true").zero?
170
172
  calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
171
173
  end
172
174
  end
@@ -174,7 +176,7 @@ module Valkyrie::Persistence::Fedora
174
176
  class DateTimeValue < ::Valkyrie::ValueMapper
175
177
  FedoraValue.register(self)
176
178
  def self.handles?(value)
177
- value.statement.object.is_a?(RDF::Literal::DateTime)
179
+ value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_datetime
178
180
  end
179
181
 
180
182
  def result
@@ -183,6 +185,18 @@ module Valkyrie::Persistence::Fedora
183
185
  end
184
186
  end
185
187
 
188
+ class IntegerValue < ::Valkyrie::ValueMapper
189
+ FedoraValue.register(self)
190
+ def self.handles?(value)
191
+ value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_int
192
+ end
193
+
194
+ def result
195
+ value.statement.object = value.statement.object.value.to_i
196
+ calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
197
+ end
198
+ end
199
+
186
200
  class LiteralValue < ::Valkyrie::ValueMapper
187
201
  FedoraValue.register(self)
188
202
  def self.handles?(value)
@@ -195,10 +209,26 @@ module Valkyrie::Persistence::Fedora
195
209
  end
196
210
  end
197
211
 
212
+ # technically valkyrie does not support time, but when other persister support time
213
+ # this code will make fedora compliant
214
+ #
215
+ # https://github.com/samvera-labs/valkyrie/wiki/Supported-Data-Types
216
+ class TimeValue < ::Valkyrie::ValueMapper
217
+ FedoraValue.register(self)
218
+ def self.handles?(value)
219
+ value.statement.object.is_a?(RDF::Literal) && value.statement.object.language.blank? && value.statement.object.datatype == PermissiveSchema.valkyrie_time
220
+ end
221
+
222
+ def result
223
+ value.statement.object = Time.parse(value.statement.object.to_s).utc
224
+ calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
225
+ end
226
+ end
227
+
198
228
  class ValkyrieIDValue < ::Valkyrie::ValueMapper
199
229
  FedoraValue.register(self)
200
230
  def self.handles?(value)
201
- value.statement.object.is_a?(RDF::Literal) && value.statement.object.datatype == RDF::URI("http://example.com/predicate/valkyrie_id")
231
+ value.statement.object.is_a?(RDF::Literal) && value.statement.object.datatype == PermissiveSchema.valkyrie_id
202
232
  end
203
233
 
204
234
  def result
@@ -221,8 +251,9 @@ module Valkyrie::Persistence::Fedora
221
251
 
222
252
  class InternalModelValue < ::Valkyrie::ValueMapper
223
253
  FedoraValue.register(self)
254
+
224
255
  def self.handles?(value)
225
- value.statement.predicate.to_s == "http://example.com/predicate/internal_resource"
256
+ value.statement.predicate == value.adapter.schema.predicate_for(property: :internal_resource, resource: nil)
226
257
  end
227
258
 
228
259
  def result
@@ -233,7 +264,7 @@ module Valkyrie::Persistence::Fedora
233
264
  class CreatedAtValue < ::Valkyrie::ValueMapper
234
265
  FedoraValue.register(self)
235
266
  def self.handles?(value)
236
- value.statement.predicate.to_s == "http://example.com/predicate/created_at"
267
+ value.statement.predicate == value.adapter.schema.predicate_for(property: :created_at, resource: nil)
237
268
  end
238
269
 
239
270
  def result
@@ -244,7 +275,7 @@ module Valkyrie::Persistence::Fedora
244
275
  class UpdatedAtValue < ::Valkyrie::ValueMapper
245
276
  FedoraValue.register(self)
246
277
  def self.handles?(value)
247
- value.statement.predicate.to_s == "http://example.com/predicate/updated_at"
278
+ value.statement.predicate == value.adapter.schema.predicate_for(property: :updated_at, resource: nil)
248
279
  end
249
280
 
250
281
  def result
@@ -258,7 +289,8 @@ module Valkyrie::Persistence::Fedora
258
289
 
259
290
  class Applicator
260
291
  attr_reader :property
261
- delegate :statement, to: :property
292
+ delegate :statement, :adapter, to: :property
293
+ delegate :schema, to: :adapter
262
294
  def initialize(property)
263
295
  @property = property
264
296
  end
@@ -270,9 +302,10 @@ module Valkyrie::Persistence::Fedora
270
302
  end
271
303
 
272
304
  def key
273
- key = statement.predicate.to_s
305
+ predicate = statement.predicate.to_s
306
+ key = schema.property_for(resource: nil, predicate: predicate)
274
307
  namespaces.each do |namespace|
275
- key = key.gsub(/^#{namespace}/, '')
308
+ key = key.to_s.gsub(/^#{namespace}/, '')
276
309
  end
277
310
  key
278
311
  end
@@ -302,8 +335,7 @@ module Valkyrie::Persistence::Fedora
302
335
  def namespaces
303
336
  [
304
337
  "http://www.fedora.info/definitions/v4/",
305
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
306
- "http://example.com/predicate/"
338
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
307
339
  ]
308
340
  end
309
341
 
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
3
  class Persister
4
+ # Provides access to generic methods for converting to/from
5
+ # {Valkyrie::Resource} and {LDP::Container::Basic}.
4
6
  class ResourceFactory
5
7
  require 'valkyrie/persistence/fedora/persister/model_converter'
6
8
  require 'valkyrie/persistence/fedora/persister/orm_converter'
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
+ # Query Service for Fedora MetadataAdapter
3
4
  class QueryService
4
5
  attr_reader :adapter
5
6
  delegate :connection, :resource_factory, to: :adapter
@@ -7,7 +8,10 @@ module Valkyrie::Persistence::Fedora
7
8
  @adapter = adapter
8
9
  end
9
10
 
11
+ # (see Valkyrie::Persistence::Memory::QueryService#find_by)
10
12
  def find_by(id:)
13
+ id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
14
+ validate_id(id)
11
15
  uri = adapter.id_to_uri(id)
12
16
  begin
13
17
  resource = Ldp::Resource.for(connection, uri, connection.get(uri))
@@ -17,6 +21,18 @@ module Valkyrie::Persistence::Fedora
17
21
  end
18
22
  end
19
23
 
24
+ # (see Valkyrie::Persistence::Memory::QueryService#find_many_by_ids)
25
+ def find_many_by_ids(ids:)
26
+ ids.map do |id|
27
+ begin
28
+ find_by(id: id)
29
+ rescue ::Valkyrie::Persistence::ObjectNotFoundError
30
+ nil
31
+ end
32
+ end.reject(&:nil?)
33
+ end
34
+
35
+ # (see Valkyrie::Persistence::Memory::QueryService#find_parents)
20
36
  def find_parents(resource:)
21
37
  content = content_with_inbound(id: resource.id)
22
38
  parent_ids = content.graph.query([nil, RDF::Vocab::ORE.proxyFor, nil]).map(&:subject).map { |x| x.to_s.gsub(/#.*/, '') }.map { |x| adapter.uri_to_id(x) }
@@ -31,12 +47,19 @@ module Valkyrie::Persistence::Fedora
31
47
  ]
32
48
  end
33
49
 
34
- def find_members(resource:)
35
- Array(resource.member_ids).lazy.map do |id|
50
+ # (see Valkyrie::Persistence::Memory::QueryService#find_members)
51
+ def find_members(resource:, model: nil)
52
+ return [] unless resource.respond_to? :member_ids
53
+ result = Array(resource.member_ids).lazy.map do |id|
36
54
  find_by(id: id)
37
55
  end.select(&:present?)
56
+ return result unless model
57
+ result.select { |obj| obj.is_a?(model) }
38
58
  end
39
59
 
60
+ # (see Valkyrie::Persistence::Memory::QueryService#find_all)
61
+ #
62
+ # @note This requires iterating over every resource in Fedora.
40
63
  def find_all
41
64
  resource = Ldp::Resource.for(connection, adapter.base_path, connection.get(adapter.base_path))
42
65
  ids = resource.graph.query([nil, RDF::Vocab::LDP.contains, nil]).map(&:object).map { |x| adapter.uri_to_id(x) }
@@ -47,12 +70,16 @@ module Valkyrie::Persistence::Fedora
47
70
  []
48
71
  end
49
72
 
73
+ # (see Valkyrie::Persistence::Memory::QueryService#find_all_of_model)
74
+ #
75
+ # @note This requires iterating over every resource in Fedora.
50
76
  def find_all_of_model(model:)
51
77
  find_all.select do |m|
52
78
  m.is_a?(model)
53
79
  end
54
80
  end
55
81
 
82
+ # (see Valkyrie::Persistence::Memory::QueryService#find_references_by)
56
83
  def find_references_by(resource:, property:)
57
84
  (resource[property] || []).select { |x| x.is_a?(Valkyrie::ID) }.lazy.map do |id|
58
85
  find_by(id: id)
@@ -68,13 +95,29 @@ module Valkyrie::Persistence::Fedora
68
95
  end
69
96
  end
70
97
 
98
+ # (see Valkyrie::Persistence::Memory::QueryService#find_inverse_references_by)
71
99
  def find_inverse_references_by(resource:, property:)
100
+ ensure_persisted(resource)
72
101
  content = content_with_inbound(id: resource.id)
73
- property_uri = RDF::URI("http://example.com/predicate/#{property}")
102
+ property_uri = adapter.schema.predicate_for(property: property, resource: nil)
74
103
  ids = content.graph.query([nil, property_uri, nil]).map(&:subject).map { |x| x.to_s.gsub(/#.*/, '') }.map { |x| adapter.uri_to_id(x) }
75
104
  ids.lazy.map do |id|
76
105
  find_by(id: id)
77
106
  end
78
107
  end
108
+
109
+ def custom_queries
110
+ @custom_queries ||= ::Valkyrie::Persistence::CustomQueryContainer.new(query_service: self)
111
+ end
112
+
113
+ private
114
+
115
+ def validate_id(id)
116
+ raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
117
+ end
118
+
119
+ def ensure_persisted(resource)
120
+ raise ArgumentError, 'resource is not saved' unless resource.persisted?
121
+ end
79
122
  end
80
123
  end