valkyrie 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +65 -56
  3. data/.lando.yml +58 -0
  4. data/.rubocop.yml +4 -1
  5. data/.tool-versions +1 -1
  6. data/Appraisals +4 -4
  7. data/CHANGELOG.md +134 -0
  8. data/README.md +21 -49
  9. data/Rakefile +26 -20
  10. data/db/config.yml +3 -10
  11. data/db/schema.rb +0 -40
  12. data/gemfiles/activerecord_5_2.gemfile +2 -0
  13. data/gemfiles/{activerecord_5_1.gemfile → activerecord_6_0.gemfile} +3 -1
  14. data/lib/generators/valkyrie/resource_generator.rb +3 -3
  15. data/lib/valkyrie.rb +33 -15
  16. data/lib/valkyrie/change_set.rb +3 -3
  17. data/lib/valkyrie/id.rb +26 -3
  18. data/lib/valkyrie/indexers/access_controls_indexer.rb +17 -17
  19. data/lib/valkyrie/logging.rb +72 -0
  20. data/lib/valkyrie/persistence/composite_persister.rb +1 -1
  21. data/lib/valkyrie/persistence/fedora.rb +2 -0
  22. data/lib/valkyrie/persistence/fedora/list_node.rb +46 -49
  23. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +7 -3
  24. data/lib/valkyrie/persistence/fedora/ordered_list.rb +90 -90
  25. data/lib/valkyrie/persistence/fedora/ordered_reader.rb +5 -5
  26. data/lib/valkyrie/persistence/fedora/permissive_schema.rb +3 -3
  27. data/lib/valkyrie/persistence/fedora/persister.rb +82 -83
  28. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +15 -15
  29. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +38 -18
  30. data/lib/valkyrie/persistence/fedora/query_service.rb +55 -54
  31. data/lib/valkyrie/persistence/memory/persister.rb +33 -33
  32. data/lib/valkyrie/persistence/memory/query_service.rb +52 -34
  33. data/lib/valkyrie/persistence/postgres/orm_converter.rb +52 -52
  34. data/lib/valkyrie/persistence/postgres/query_service.rb +86 -33
  35. data/lib/valkyrie/persistence/postgres/resource_converter.rb +1 -1
  36. data/lib/valkyrie/persistence/shared/json_value_mapper.rb +1 -1
  37. data/lib/valkyrie/persistence/solr/model_converter.rb +337 -337
  38. data/lib/valkyrie/persistence/solr/orm_converter.rb +3 -3
  39. data/lib/valkyrie/persistence/solr/persister.rb +4 -17
  40. data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +6 -0
  41. data/lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb +1 -1
  42. data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +1 -1
  43. data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +1 -1
  44. data/lib/valkyrie/persistence/solr/query_service.rb +42 -53
  45. data/lib/valkyrie/persistence/solr/repository.rb +2 -1
  46. data/lib/valkyrie/rdf_patches.rb +2 -2
  47. data/lib/valkyrie/resource.rb +36 -5
  48. data/lib/valkyrie/specs/shared_specs/change_set.rb +1 -1
  49. data/lib/valkyrie/specs/shared_specs/persister.rb +13 -5
  50. data/lib/valkyrie/specs/shared_specs/queries.rb +112 -9
  51. data/lib/valkyrie/specs/shared_specs/resource.rb +1 -1
  52. data/lib/valkyrie/storage/fedora.rb +18 -18
  53. data/lib/valkyrie/storage_adapter.rb +16 -13
  54. data/lib/valkyrie/types.rb +3 -1
  55. data/lib/valkyrie/version.rb +1 -1
  56. data/lib/valkyrie/vocab/pcdm_use.rb +12 -0
  57. data/solr/config/solrconfig.xml +0 -10
  58. data/tasks/dev.rake +14 -51
  59. data/valkyrie.gemspec +4 -4
  60. metadata +38 -35
  61. data/.docker-stack/valkyrie-development/docker-compose.yml +0 -53
  62. data/.docker-stack/valkyrie-test/docker-compose.yml +0 -53
  63. data/db/seeds.rb +0 -8
  64. data/tasks/docker.rake +0 -31
@@ -19,5 +19,7 @@ module Valkyrie::Persistence
19
19
  require 'valkyrie/persistence/fedora/ordered_list'
20
20
  require 'valkyrie/persistence/fedora/ordered_reader'
21
21
  require 'valkyrie/persistence/fedora/list_node'
22
+
23
+ DEFAULT_FEDORA_VERSION = 5
22
24
  end
23
25
  end
@@ -18,7 +18,6 @@ module Valkyrie::Persistence::Fedora
18
18
  class ListNode
19
19
  attr_reader :rdf_subject, :graph
20
20
  attr_writer :next, :prev
21
- attr_accessor :target
22
21
  attr_writer :next_uri, :prev_uri
23
22
  attr_accessor :proxy_in, :proxy_for
24
23
  attr_reader :adapter
@@ -59,16 +58,15 @@ module Valkyrie::Persistence::Fedora
59
58
  def to_graph
60
59
  return RDF::Graph.new if target_id.blank?
61
60
  g = Resource.new(rdf_subject)
62
- g.proxy_for = target_uri
61
+ g.proxy_for = target
63
62
  g.proxy_in = proxy_in.try(:uri)
64
63
  g.next = self.next.try(:rdf_subject)
65
64
  g.prev = prev.try(:rdf_subject)
66
65
  g.graph
67
66
  end
68
67
 
69
- # Resolves the URI for the value of the list expression
70
- # @return [RDF::URI]
71
- def target_uri
68
+ # @return [RDF::URI] or [String]
69
+ def target
72
70
  if target_id.is_a?(Valkyrie::ID)
73
71
  adapter.id_to_uri(target_id.to_s)
74
72
  else
@@ -76,7 +74,6 @@ module Valkyrie::Persistence::Fedora
76
74
  end
77
75
  end
78
76
 
79
- # Generates the string ID value for the value in the list expression
80
77
  # @return [String]
81
78
  def target_id
82
79
  if proxy_for.to_s.include?("/") && proxy_for.to_s.start_with?(adapter.connection_prefix)
@@ -88,60 +85,60 @@ module Valkyrie::Persistence::Fedora
88
85
 
89
86
  private
90
87
 
91
- attr_reader :next_uri, :prev_uri, :node_cache
88
+ attr_reader :next_uri, :prev_uri, :node_cache
92
89
 
93
- # Class used to populate the RDF graph structure for the linked lists
94
- class Builder
95
- attr_reader :uri, :graph
90
+ # Class used to populate the RDF graph structure for the linked lists
91
+ class Builder
92
+ attr_reader :uri, :graph
96
93
 
97
- # @param uri [RDF::URI] the URI for the linked list in the graph store
98
- # @param graph [RDF::Repository] the RDF graph to be populated
99
- def initialize(uri, graph)
100
- @uri = uri
101
- @graph = graph
102
- end
94
+ # @param uri [RDF::URI] the URI for the linked list in the graph store
95
+ # @param graph [RDF::Repository] the RDF graph to be populated
96
+ def initialize(uri, graph)
97
+ @uri = uri
98
+ @graph = graph
99
+ end
103
100
 
104
- # Populates attributes for the LinkedNode
105
- # @param instance [ListNode]
106
- def populate(instance)
107
- instance.proxy_for = resource.proxy_for
108
- instance.proxy_in = resource.proxy_in
109
- instance.next_uri = resource.next
110
- instance.prev_uri = resource.prev
111
- end
101
+ # Populates attributes for the LinkedNode
102
+ # @param instance [ListNode]
103
+ def populate(instance)
104
+ instance.proxy_for = resource.proxy_for
105
+ instance.proxy_in = resource.proxy_in
106
+ instance.next_uri = resource.next
107
+ instance.prev_uri = resource.prev
108
+ end
112
109
 
113
- private
110
+ private
114
111
 
115
- # Constructs a set of triples using ActiveTriples as objects
116
- # @return [Valkyrie::Persistence::Fedora::ListNode::Resource]
117
- def resource
118
- @resource ||= Resource.new(uri, graph: graph)
119
- end
112
+ # Constructs a set of triples using ActiveTriples as objects
113
+ # @return [Valkyrie::Persistence::Fedora::ListNode::Resource]
114
+ def resource
115
+ @resource ||= Resource.new(uri, graph: graph)
120
116
  end
117
+ end
121
118
 
122
- # Class for providing a set of triples modeling linked list nodes
123
- class Resource
124
- def self.property(property, predicate:)
125
- define_method property do
126
- graph.query([uri, predicate, nil]).objects.first
127
- end
119
+ # Class for providing a set of triples modeling linked list nodes
120
+ class Resource
121
+ def self.property(property, predicate:)
122
+ define_method property do
123
+ graph.query([uri, predicate, nil]).objects.first
124
+ end
128
125
 
129
- define_method "#{property}=" do |val|
130
- return if val.nil?
131
- graph << [uri, predicate, val]
132
- end
126
+ define_method "#{property}=" do |val|
127
+ return if val.nil?
128
+ graph << [uri, predicate, val]
133
129
  end
130
+ end
134
131
 
135
- property :proxy_for, predicate: ::RDF::Vocab::ORE.proxyFor
136
- property :proxy_in, predicate: ::RDF::Vocab::ORE.proxyIn
137
- property :next, predicate: ::RDF::Vocab::IANA.next
138
- property :prev, predicate: ::RDF::Vocab::IANA.prev
132
+ property :proxy_for, predicate: ::RDF::Vocab::ORE.proxyFor
133
+ property :proxy_in, predicate: ::RDF::Vocab::ORE.proxyIn
134
+ property :next, predicate: ::RDF::Vocab::IANA.next
135
+ property :prev, predicate: ::RDF::Vocab::IANA.prev
139
136
 
140
- attr_reader :graph, :uri
141
- def initialize(uri, graph: RDF::Graph.new)
142
- @uri = uri
143
- @graph = graph
144
- end
137
+ attr_reader :graph, :uri
138
+ def initialize(uri, graph: RDF::Graph.new)
139
+ @uri = uri
140
+ @graph = graph
145
141
  end
142
+ end
146
143
  end
147
144
  end
@@ -6,7 +6,7 @@ module Valkyrie::Persistence::Fedora
6
6
  # Valkyrie::Persistence::Fedora::MetadataAdapter.new(
7
7
  # connection: ::Ldp::Client.new("http://localhost:8988/rest"),
8
8
  # base_path: "test_fed",
9
- # schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new(title: RDF::URI("http://bad.com/title"))
9
+ # schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new(title: RDF::URI("http://example.com/title"))
10
10
  # )
11
11
  class MetadataAdapter
12
12
  attr_reader :connection, :base_path, :schema, :fedora_version
@@ -15,7 +15,7 @@ module Valkyrie::Persistence::Fedora
15
15
  # @param [String] base_path
16
16
  # @param [Valkyrie::Persistence::Fedora::PermissiveSchema] schema
17
17
  # @param [Integer] fedora_version
18
- def initialize(connection:, base_path: "/", schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new, fedora_version: 5)
18
+ def initialize(connection:, base_path: "/", schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new, fedora_version: Valkyrie::Persistence::Fedora::DEFAULT_FEDORA_VERSION)
19
19
  @connection = connection
20
20
  @base_path = base_path
21
21
  @schema = schema
@@ -58,7 +58,7 @@ module Valkyrie::Persistence::Fedora
58
58
  # @param [RDF::URI] id the Valkyrie ID
59
59
  # @return [RDF::URI]
60
60
  def id_to_uri(id)
61
- prefix = fedora_version == 5 ? "" : "#{pair_path(id)}/"
61
+ prefix = [5, 6].include?(fedora_version) ? "" : "#{pair_path(id)}/"
62
62
  RDF::URI("#{connection_prefix}/#{prefix}#{CGI.escape(id.to_s)}")
63
63
  end
64
64
 
@@ -71,6 +71,10 @@ module Valkyrie::Persistence::Fedora
71
71
  id.to_s.split(/[-\/]/).first.split("").each_slice(2).map(&:join).join("/")
72
72
  end
73
73
 
74
+ def url_prefix
75
+ connection.http.url_prefix
76
+ end
77
+
74
78
  # Generate the prefix used in HTTP requests to the Fedora RESTful endpoint
75
79
  # @return [String]
76
80
  def connection_prefix
@@ -67,111 +67,111 @@ module Valkyrie::Persistence::Fedora
67
67
 
68
68
  private
69
69
 
70
- attr_reader :node_cache
71
-
72
- # Append a node to a linked list
73
- # @param source [ListNode] the node being appended
74
- # @param append_node [ListNode] the node already in the existing list
75
- def append_to(source, append_node)
76
- source.prev = append_node
77
- append_node.next.prev = source
78
- source.next = append_node.next
79
- append_node.next = source
80
- @changed = true
81
- end
70
+ attr_reader :node_cache
71
+
72
+ # Append a node to a linked list
73
+ # @param source [ListNode] the node being appended
74
+ # @param append_node [ListNode] the node already in the existing list
75
+ def append_to(source, append_node)
76
+ source.prev = append_node
77
+ append_node.next.prev = source
78
+ source.next = append_node.next
79
+ append_node.next = source
80
+ @changed = true
81
+ end
82
82
 
83
- # Constructs a new OrderedReader for this OrderedList
84
- # @return [OrderedReader]
85
- def ordered_reader
86
- OrderedReader.new(self)
87
- end
83
+ # Constructs a new OrderedReader for this OrderedList
84
+ # @return [OrderedReader]
85
+ def ordered_reader
86
+ OrderedReader.new(self)
87
+ end
88
88
 
89
- # Populates the list with constructed ListNode Objects
90
- # @param subject [RDF::URI]
91
- def build_node(subject = nil)
92
- return nil unless subject
93
- node_cache.fetch(subject) do
94
- ListNode.new(node_cache, subject, adapter, graph)
95
- end
89
+ # Populates the list with constructed ListNode Objects
90
+ # @param subject [RDF::URI]
91
+ def build_node(subject = nil)
92
+ return nil unless subject
93
+ node_cache.fetch(subject) do
94
+ ListNode.new(node_cache, subject, adapter, graph)
96
95
  end
96
+ end
97
97
 
98
- # Generates hash URIs for the subject of the LinkedList
99
- # Should one of these URIs already be in use, a new URI will be generated
100
- # @return [RDF::URI]
101
- def new_node_subject
102
- node = ::RDF::URI("##{::RDF::Node.new.id}")
103
- node = ::RDF::URI("##{::RDF::Node.new.id}") while node_cache.key?(node)
104
- node
105
- end
98
+ # Generates hash URIs for the subject of the LinkedList
99
+ # Should one of these URIs already be in use, a new URI will be generated
100
+ # @return [RDF::URI]
101
+ def new_node_subject
102
+ node = ::RDF::URI("##{::RDF::Node.new.id}")
103
+ node = ::RDF::URI("##{::RDF::Node.new.id}") while node_cache.key?(node)
104
+ node
105
+ end
106
106
 
107
- # Class used for caching LinkedNode objects mapped to URIs
108
- class NodeCache
109
- def initialize
110
- @cache ||= {}
111
- end
107
+ # Class used for caching LinkedNode objects mapped to URIs
108
+ class NodeCache
109
+ def initialize
110
+ @cache ||= {}
111
+ end
112
112
 
113
- # Retrieve the ListNode for a given URI
114
- # If a block is passed, set its output to the cache
115
- # @param uri [RDF::URI]
116
- # @return [ListNode]
117
- def fetch(uri)
118
- @cache[uri] ||= yield if block_given?
119
- end
113
+ # Retrieve the ListNode for a given URI
114
+ # If a block is passed, set its output to the cache
115
+ # @param uri [RDF::URI]
116
+ # @return [ListNode]
117
+ def fetch(uri)
118
+ @cache[uri] ||= yield if block_given?
119
+ end
120
120
 
121
- # Determines whether or not the cache contains a key
122
- # @param key [Object]
123
- # @return [Boolean]
124
- def key?(key)
125
- @cache.key?(key)
126
- end
121
+ # Determines whether or not the cache contains a key
122
+ # @param key [Object]
123
+ # @return [Boolean]
124
+ def key?(key)
125
+ @cache.key?(key)
127
126
  end
127
+ end
128
128
 
129
- # Class modeling sentinels within the linked list
130
- # @see https://en.wikipedia.org/wiki/Sentinel_value
131
- class Sentinel
132
- attr_reader :parent, :next, :prev
133
- attr_writer :next, :prev
134
-
135
- # @param parent [Valkyrie::Persistence::Fedora::OrderedList]
136
- # @param next_node [ListNode]
137
- # @param prev_node [ListNode]
138
- def initialize(parent, next_node: nil, prev_node: nil)
139
- @parent = parent
140
- @next = next_node
141
- @prev = prev_node
142
- end
129
+ # Class modeling sentinels within the linked list
130
+ # @see https://en.wikipedia.org/wiki/Sentinel_value
131
+ class Sentinel
132
+ attr_reader :parent, :next, :prev
133
+ attr_writer :next, :prev
134
+
135
+ # @param parent [Valkyrie::Persistence::Fedora::OrderedList]
136
+ # @param next_node [ListNode]
137
+ # @param prev_node [ListNode]
138
+ def initialize(parent, next_node: nil, prev_node: nil)
139
+ @parent = parent
140
+ @next = next_node
141
+ @prev = prev_node
142
+ end
143
143
 
144
- # Ensure that this always behaves like a NilClass
145
- # @return [TrueClass]
146
- def nil?
147
- true
148
- end
144
+ # Ensure that this always behaves like a NilClass
145
+ # @return [TrueClass]
146
+ def nil?
147
+ true
148
+ end
149
149
 
150
- # Ensure that this does not have a URI
151
- # @return [NilClass]
152
- def rdf_subject
153
- nil
154
- end
150
+ # Ensure that this does not have a URI
151
+ # @return [NilClass]
152
+ def rdf_subject
153
+ nil
155
154
  end
155
+ end
156
156
 
157
- class HeadSentinel < Sentinel
158
- # @param parent [Valkyrie::Persistence::Fedora::OrderedList]
159
- # @param next_node [ListNode]
160
- # @param prev_node [ListNode]
161
- def initialize(*args)
162
- super
163
- @next ||= TailSentinel.new(parent, prev_node: self)
164
- end
157
+ class HeadSentinel < Sentinel
158
+ # @param parent [Valkyrie::Persistence::Fedora::OrderedList]
159
+ # @param next_node [ListNode]
160
+ # @param prev_node [ListNode]
161
+ def initialize(*args)
162
+ super
163
+ @next ||= TailSentinel.new(parent, prev_node: self)
165
164
  end
165
+ end
166
166
 
167
- class TailSentinel < Sentinel
168
- # @param parent [Valkyrie::Persistence::Fedora::OrderedList]
169
- # @param next_node [ListNode]
170
- # @param prev_node [ListNode]
171
- def initialize(*args)
172
- super
173
- prev.next = self if prev&.next != self
174
- end
167
+ class TailSentinel < Sentinel
168
+ # @param parent [Valkyrie::Persistence::Fedora::OrderedList]
169
+ # @param next_node [ListNode]
170
+ # @param prev_node [ListNode]
171
+ def initialize(*args)
172
+ super
173
+ prev.next = self if prev&.next != self
175
174
  end
175
+ end
176
176
  end
177
177
  end
@@ -26,10 +26,10 @@ module Valkyrie::Persistence::Fedora
26
26
 
27
27
  private
28
28
 
29
- # Access the "first" (head) node for the linked list
30
- # @return [Valkyrie::Persistence::Fedora::OrderedList::HeadSentinel]
31
- def first_head
32
- root.head
33
- end
29
+ # Access the "first" (head) node for the linked list
30
+ # @return [Valkyrie::Persistence::Fedora::OrderedList::HeadSentinel]
31
+ def first_head
32
+ root.head
33
+ end
34
34
  end
35
35
  end
@@ -6,8 +6,8 @@ module Valkyrie::Persistence::Fedora
6
6
  #
7
7
  # @example Passing in a mapping
8
8
  # schema = Valkyrie::Persistence::Fedora::PermissiveSchema.new(member_ids:
9
- # RDF::URI("http://mypredicates.com/member_ids"))
10
- # schema.predicate_for(resource: Resource.new, property: :member_ids) # => RDF::URI<"http://mypredicates.com/member_ids">
9
+ # RDF::URI("http://example.com/member_ids"))
10
+ # schema.predicate_for(resource: Resource.new, property: :member_ids) # => RDF::URI<"http://example.com/member_ids">
11
11
  # schema.predicate_for(resource: Resource.new, property: :unknown) # => RDF::URI<"http://example.com/predicate/unknown">
12
12
  class PermissiveSchema
13
13
  URI_PREFIX = 'http://example.com/predicate/'
@@ -92,7 +92,7 @@ module Valkyrie::Persistence::Fedora
92
92
  existing_predicates = schema.find { |_k, v| v == RDF::URI(predicate.to_s) }
93
93
  predicate_name = predicate.to_s.gsub(URI_PREFIX, '')
94
94
 
95
- return predicate_name if existing_predicates.nil? || existing_predicates.empty?
95
+ return predicate_name if existing_predicates.blank?
96
96
  existing_predicates.first
97
97
  end
98
98
  end
@@ -64,11 +64,12 @@ module Valkyrie::Persistence::Fedora
64
64
  # (see Valkyrie::Persistence::Memory::Persister#wipe!)
65
65
  # Deletes Fedora repository resource *and* the tombstone resources which remain
66
66
  # @see https://wiki.duraspace.org/display/FEDORA4x/RESTful+HTTP+API#RESTfulHTTPAPI-RedDELETEDeletearesource
67
+ # @see Valkyrie::Logging for details concerning log suppression.
67
68
  def wipe!
68
69
  connection.delete(base_path)
69
70
  connection.delete("#{base_path}/fcr:tombstone")
70
71
  rescue => error
71
- Valkyrie.logger.debug("Failed to wipe Fedora for some reason: #{error}") unless error.is_a?(::Ldp::NotFound)
72
+ Valkyrie.logger.debug("Failed to wipe Fedora for some reason: #{error}", logging_context: "Valkyrie::Persistence::Fedora::Persister#wipe") unless error.is_a?(::Ldp::NotFound)
72
73
  end
73
74
 
74
75
  # Creates the root LDP Container for the connection with Fedora
@@ -85,97 +86,95 @@ module Valkyrie::Persistence::Fedora
85
86
 
86
87
  private
87
88
 
88
- # Ensure that all alternate IDs for a given resource are persisted
89
- # @param [Valkyrie::Resource] resource
90
- # @return [Array<Valkyrie::Persistence::Fedora::AlternateIdentifier>]
91
- def find_or_create_alternate_ids(resource)
92
- return nil unless resource.try(:alternate_ids)
93
-
94
- resource.alternate_ids.map do |alternate_identifier|
95
- begin
96
- adapter.query_service.find_by(id: alternate_identifier)
97
- rescue ::Valkyrie::Persistence::ObjectNotFoundError
98
- alternate_resource = ::Valkyrie::Persistence::Fedora::AlternateIdentifier.new(id: alternate_identifier)
99
- adapter.persister.save(resource: alternate_resource)
100
- end
101
- end
89
+ # Ensure that all alternate IDs for a given resource are persisted
90
+ # @param [Valkyrie::Resource] resource
91
+ # @return [Array<Valkyrie::Persistence::Fedora::AlternateIdentifier>]
92
+ def find_or_create_alternate_ids(resource)
93
+ return nil unless resource.try(:alternate_ids)
94
+
95
+ resource.alternate_ids.map do |alternate_identifier|
96
+ adapter.query_service.find_by(id: alternate_identifier)
97
+ rescue ::Valkyrie::Persistence::ObjectNotFoundError
98
+ alternate_resource = ::Valkyrie::Persistence::Fedora::AlternateIdentifier.new(id: alternate_identifier)
99
+ adapter.persister.save(resource: alternate_resource)
102
100
  end
101
+ end
103
102
 
104
- # Ensure that any Resources referenced by alternate IDs are deleted when a Resource has these IDs deleted
105
- # @param [Valkyrie::Resource] updated_resource
106
- def cleanup_alternate_resources(updated_resource)
107
- persisted_resource = adapter.query_service.find_by(id: updated_resource.id)
108
- removed_identifiers = persisted_resource.alternate_ids - updated_resource.alternate_ids
103
+ # Ensure that any Resources referenced by alternate IDs are deleted when a Resource has these IDs deleted
104
+ # @param [Valkyrie::Resource] updated_resource
105
+ def cleanup_alternate_resources(updated_resource)
106
+ persisted_resource = adapter.query_service.find_by(id: updated_resource.id)
107
+ removed_identifiers = persisted_resource.alternate_ids - updated_resource.alternate_ids
109
108
 
110
- removed_identifiers.each do |removed_id|
111
- adapter.persister.delete(resource: adapter.query_service.find_by(id: removed_id))
112
- end
109
+ removed_identifiers.each do |removed_id|
110
+ adapter.persister.delete(resource: adapter.query_service.find_by(id: removed_id))
113
111
  end
112
+ end
114
113
 
115
- # Ensure that any Resources referenced by alternate IDs are persisted when a Resource has these IDs added
116
- # @param [Valkyrie::Resource] resource
117
- # @param [Array<Valkyrie::Persistence::Fedora::AlternateIdentifier>] alternate_resources
118
- # @return [Valkyrie::Resource]
119
- def save_reference_to_resource(resource, alternate_resources)
120
- alternate_resources.each do |alternate_resource|
121
- alternate_resource.references = resource.id
122
- adapter.persister.save(resource: alternate_resource)
123
- end
124
-
125
- resource
114
+ # Ensure that any Resources referenced by alternate IDs are persisted when a Resource has these IDs added
115
+ # @param [Valkyrie::Resource] resource
116
+ # @param [Array<Valkyrie::Persistence::Fedora::AlternateIdentifier>] alternate_resources
117
+ # @return [Valkyrie::Resource]
118
+ def save_reference_to_resource(resource, alternate_resources)
119
+ alternate_resources.each do |alternate_resource|
120
+ alternate_resource.references = resource.id
121
+ adapter.persister.save(resource: alternate_resource)
126
122
  end
127
123
 
128
- # Generate the lock token for a Resource, and set it for attribute
129
- # @param [Valkyrie::Resource] resource
130
- # @return [Valkyrie::Persistence::OptimisticLockToken]
131
- # @see https://github.com/samvera-labs/valkyrie/wiki/Optimistic-Locking
132
- # @note Fedora's last modified response is not granular enough to produce an effective lock token
133
- # therefore, we use the same implementation as the memory adapter. This could fail to lock a
134
- # resource if Fedora updated this resource between the time it was saved and Valkyrie created
135
- # the token.
136
- def generate_lock_token(resource)
137
- return unless resource.optimistic_locking_enabled?
138
- token = Valkyrie::Persistence::OptimisticLockToken.new(adapter_id: adapter.id, token: Time.now.to_r)
139
- resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", token)
140
- end
124
+ resource
125
+ end
141
126
 
142
- # Determine whether or not a lock token is still valid for a persisted Resource
143
- # If the persisted Resource has been updated since it was last read into memory,
144
- # then the resouce in memory has been invalidated and Valkyrie::Persistence::StaleObjectError
145
- # is raised.
146
- # @param [Valkyrie::Resource] resource
147
- # @see https://github.com/samvera-labs/valkyrie/wiki/Optimistic-Locking
148
- # @raise [Valkyrie::Persistence::StaleObjectError]
149
- def validate_lock_token(resource)
150
- return unless resource.optimistic_locking_enabled?
151
- return if resource.id.blank?
152
-
153
- current_lock_token = resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].find { |lock_token| lock_token.adapter_id == adapter.id }
154
- return if current_lock_token.blank?
155
-
156
- retrieved_lock_tokens = adapter.query_service.find_by(id: resource.id)[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
157
- retrieved_lock_token = retrieved_lock_tokens.find { |lock_token| lock_token.adapter_id == adapter.id }
158
- return if retrieved_lock_token.blank?
159
-
160
- raise Valkyrie::Persistence::StaleObjectError, "The object #{resource.id} has been updated by another process." unless current_lock_token == retrieved_lock_token
161
- end
127
+ # Generate the lock token for a Resource, and set it for attribute
128
+ # @param [Valkyrie::Resource] resource
129
+ # @return [Valkyrie::Persistence::OptimisticLockToken]
130
+ # @see https://github.com/samvera-labs/valkyrie/wiki/Optimistic-Locking
131
+ # @note Fedora's last modified response is not granular enough to produce an effective lock token
132
+ # therefore, we use the same implementation as the memory adapter. This could fail to lock a
133
+ # resource if Fedora updated this resource between the time it was saved and Valkyrie created
134
+ # the token.
135
+ def generate_lock_token(resource)
136
+ return unless resource.optimistic_locking_enabled?
137
+ token = Valkyrie::Persistence::OptimisticLockToken.new(adapter_id: adapter.id, token: Time.now.to_r)
138
+ resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", token)
139
+ end
162
140
 
163
- # Retrieve the lock token that holds Fedora's system-managed last-modified date
164
- # @param [Valkyrie::Resource] resource
165
- # @return [Valkyrie::Persistence::OptimisticLockToken]
166
- def native_lock_token(resource)
167
- return unless resource.optimistic_locking_enabled?
168
- resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].find { |lock_token| lock_token.adapter_id.to_s == "native-#{adapter.id}" }
169
- end
141
+ # Determine whether or not a lock token is still valid for a persisted Resource
142
+ # If the persisted Resource has been updated since it was last read into memory,
143
+ # then the resouce in memory has been invalidated and Valkyrie::Persistence::StaleObjectError
144
+ # is raised.
145
+ # @param [Valkyrie::Resource] resource
146
+ # @see https://github.com/samvera-labs/valkyrie/wiki/Optimistic-Locking
147
+ # @raise [Valkyrie::Persistence::StaleObjectError]
148
+ def validate_lock_token(resource)
149
+ return unless resource.optimistic_locking_enabled?
150
+ return if resource.id.blank?
151
+
152
+ current_lock_token = resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].find { |lock_token| lock_token.adapter_id == adapter.id }
153
+ return if current_lock_token.blank?
154
+
155
+ retrieved_lock_tokens = adapter.query_service.find_by(id: resource.id)[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
156
+ retrieved_lock_token = retrieved_lock_tokens.find { |lock_token| lock_token.adapter_id == adapter.id }
157
+ return if retrieved_lock_token.blank?
158
+
159
+ raise Valkyrie::Persistence::StaleObjectError, "The object #{resource.id} has been updated by another process." unless current_lock_token == retrieved_lock_token
160
+ end
170
161
 
171
- # Set Fedora request headers:
172
- # * `Prefer: handling=lenient; received="minimal"` allows us to avoid sending all server-managed triples
173
- # * `If-Unmodified-Since` triggers Fedora's server-side optimistic locking
174
- # @param request [Faraday::Request]
175
- # @param lock_token [Valkyrie::Persistence::OptimisticLockToken]
176
- def update_request_headers(request, lock_token)
177
- request.headers["Prefer"] = "handling=lenient; received=\"minimal\""
178
- request.headers["If-Unmodified-Since"] = lock_token.token if lock_token
179
- end
162
+ # Retrieve the lock token that holds Fedora's system-managed last-modified date
163
+ # @param [Valkyrie::Resource] resource
164
+ # @return [Valkyrie::Persistence::OptimisticLockToken]
165
+ def native_lock_token(resource)
166
+ return unless resource.optimistic_locking_enabled?
167
+ resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].find { |lock_token| lock_token.adapter_id.to_s == "native-#{adapter.id}" }
168
+ end
169
+
170
+ # Set Fedora request headers:
171
+ # * `Prefer: handling=lenient; received="minimal"` allows us to avoid sending all server-managed triples
172
+ # * `If-Unmodified-Since` triggers Fedora's server-side optimistic locking
173
+ # @param request [Faraday::Request]
174
+ # @param lock_token [Valkyrie::Persistence::OptimisticLockToken]
175
+ def update_request_headers(request, lock_token)
176
+ request.headers["Prefer"] = "handling=lenient; received=\"minimal\""
177
+ request.headers["If-Unmodified-Since"] = lock_token.token if lock_token
178
+ end
180
179
  end
181
180
  end