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,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie
3
+ # MetadataAdapter is the primary DataMapper object for metadata persistence.
4
+ # Used to register and locate adapters, persisters, and query services for individual
5
+ # metadata storage backends (such as fedora, postgres, etc)
3
6
  class MetadataAdapter
4
7
  class_attribute :adapters
5
8
  self.adapters = {}
@@ -14,8 +17,33 @@ module Valkyrie
14
17
  # Find an adapter by its short name.
15
18
  # @param short_name [Symbol]
16
19
  # @return [#persister,#query_service]
20
+ # @raise RuntimeError when the given short_name is not found amongst the registered adapters
17
21
  def find(short_name)
18
- adapters[short_name.to_sym]
22
+ symbolized_key = short_name.to_sym
23
+ return adapters[symbolized_key] if adapters.key?(symbolized_key)
24
+ raise "Unable to find unregistered adapter `#{short_name}'"
25
+ end
26
+
27
+ # @api public
28
+ # @since 0.1.0
29
+ # Find the persister registered under the given short-name
30
+ #
31
+ # @param short_name [Symbol]
32
+ # @return [Object] an object that behaves like "a Valkyrie::Persister"
33
+ # @see GEM_ROOT/lib/valkyrie/specs/shared_specs/persister.rb
34
+ def find_persister_for(short_name)
35
+ find(short_name).persister
36
+ end
37
+
38
+ # @api public
39
+ # @since 0.1.0
40
+ # Find the query service registered under the given short-name
41
+ #
42
+ # @param short_name [Symbol]
43
+ # @return [Object] an object that behaves like "a Valkyrie query provider"
44
+ # @see GEM_ROOT/lib/valkyrie/specs/shared_specs/queries.rb
45
+ def find_query_service_for(short_name)
46
+ find(short_name).query_service
19
47
  end
20
48
  end
21
49
  end
@@ -1,6 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie
3
+ # This is a namespacing module for metadata persisters as per the DataMapper pattern
4
+ # https://en.wikipedia.org/wiki/Data_mapper_pattern
5
+ #
6
+ # @note These persisters do not store binary content.
7
+ # See Valkyrie::Storage for persisting binary content (files).
8
+ #
9
+ # @example Register persisters in an initializer using Valkyrie::MetadataAdapter.register
10
+ # Valkyrie::MetadataAdapter.register(
11
+ # Valkyrie::Persistence::Memory::MetadataAdapter.new,
12
+ # :memory
13
+ # )
14
+ #
15
+ # @example Retrieve a registered persister using Valkyrie::MetadataAdapter.find
16
+ # Valkyrie::MetadataAdapter.find(:memory)
17
+ # => <Valkyrie::Persistence::Memory::MetadataAdapter:0x007fa6ec031bd8>
18
+ #
19
+ # @example Saving an object
20
+ #
21
+ # object1 = MyModel.new title: 'My Cool Object', authors: ['Jones, Alice', 'Smith, Bob']
22
+ # object1 = Valkyrie.config.metadata_adapter.persister.save(model: object1)
23
+ #
24
+ # @see https://github.com/samvera-labs/valkyrie/wiki/Persistence
25
+ # @see lib/valkyrie/specs/shared_specs/persister.rb
26
+ #
3
27
  module Persistence
28
+ require 'valkyrie/persistence/custom_query_container'
4
29
  require 'valkyrie/persistence/memory'
5
30
  require 'valkyrie/persistence/postgres'
6
31
  require 'valkyrie/persistence/solr'
@@ -10,5 +35,7 @@ module Valkyrie
10
35
  require 'valkyrie/persistence/buffered_persister'
11
36
  class ObjectNotFoundError < StandardError
12
37
  end
38
+ class UnsupportedDatatype < StandardError
39
+ end
13
40
  end
14
41
  end
@@ -1,8 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence
3
+ # Implements the DataMapper Pattern to proxy another Metadata Persister
4
+ #
5
+ # Provides with_buffer to send multiple updates at one time to the proxied persister
6
+ # In some cases this will realize performance gains
7
+ #
8
+ # @example
9
+ # buffered_persister.with_buffer do |persist, buffer|
10
+ # yield Valkyrie::AdapterContainer.new(persister: persist, query_service: metadata_adapter.query_service)
11
+ # buffer.persister.deletes.uniq(&:id).each do |delete|
12
+ # index_persister.delete(resource: delete)
13
+ # end
14
+ # index_persister.save_all(resources: buffer.query_service.find_all)
15
+ # end
16
+ #
17
+ # @see Valkyrie::Persistence::DeleteTrackingBuffer for more information on deletes used in the example above
18
+ #
3
19
  class BufferedPersister
4
20
  attr_reader :persister, :buffer_class
5
- delegate :adapter, to: :persister
21
+ delegate :adapter, :wipe!, to: :persister
6
22
  def initialize(persister, buffer_class: Valkyrie::Persistence::DeleteTrackingBuffer)
7
23
  @persister = persister
8
24
  @buffer_class = buffer_class
@@ -1,8 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence
3
- ##
4
- # Wrap up multiple persisters under a common interface, to transparently
3
+ # Wraps up multiple persisters under a common interface, to transparently
5
4
  # persist to multiple places at once.
5
+ #
6
+ # @example
7
+ # persister = Valkyrie.config.metadata_adapter
8
+ # index_persister = Valkyrie::MetadataAdapter.find(:index_solr)
9
+ # Valkyrie::MetadataAdapter.register(
10
+ # Valkyrie::Persistence::CompositePersister.new(persister, index_persister),
11
+ # :my_composite_persister
12
+ # )
13
+ #
6
14
  class CompositePersister
7
15
  attr_reader :persisters
8
16
  def initialize(*persisters)
@@ -25,5 +33,9 @@ module Valkyrie::Persistence
25
33
  def delete(resource:)
26
34
  persisters.inject(resource) { |m, persister| persister.delete(resource: m) }
27
35
  end
36
+
37
+ def wipe!
38
+ persisters.each_entry(&:wipe!)
39
+ end
28
40
  end
29
41
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Valkyrie::Persistence
4
+ # Allows for implementors to register and use custom queries on a
5
+ # per persister basis
6
+ #
7
+ # @example Custom Query Class
8
+ #
9
+ # # Snippet from custom query class see: https://github.com/pulibrary/figgy/blob/d0b1305a1564c2aa4e7d6c1e99f0c2a88ed673f4/app/queries/find_by_string_property.rb
10
+ # class FindByStringProperty
11
+ # def self.queries
12
+ # [:find_by_string_property]
13
+ # end
14
+ #
15
+ # ...
16
+ #
17
+ # def initialize(query_service:)
18
+ # @query_service = query_service
19
+ # end
20
+ # ...
21
+ #
22
+ # def find_by_string_property(property:, value:)
23
+ # internal_array = "{\"#{property}\": [\"#{value}\"]}"
24
+ # run_query(query, internal_array)
25
+ # end
26
+ # ...
27
+ # end
28
+ #
29
+ # @example Registration
30
+ #
31
+ # # in config/initializers/valkyrie.rb
32
+ # [FindByStringProperty].each do |query_handler|
33
+ # Valkyrie.config.metadata_adapter.query_service.custom_queries.register_query_handler(query_handler)
34
+ # end
35
+ #
36
+ # @see lib/valkyrie/persistence/solr/query_service.rb for use of this class
37
+ #
38
+ class CustomQueryContainer
39
+ attr_reader :query_service, :query_handlers
40
+ def initialize(query_service:)
41
+ @query_service = query_service
42
+ @query_handlers = []
43
+ end
44
+
45
+ def register_query_handler(query_handler)
46
+ @query_handlers << query_handler
47
+ end
48
+
49
+ def method_missing(meth_name, *args, &block)
50
+ query_handler = find_query_handler(meth_name).new(query_service: query_service)
51
+ return super unless query_handler
52
+ query_handler.__send__(meth_name, *args, &block)
53
+ end
54
+
55
+ def find_query_handler(method)
56
+ query_handlers.find { |x| x.queries.include?(method) }
57
+ end
58
+
59
+ def respond_to_missing?(meth_name, _args)
60
+ find_query_handler(meth_name).present?
61
+ end
62
+ end
63
+ end
@@ -1,5 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence
3
+ # Implements the DataMapper Pattern to store metadata in Memory
4
+ # In Addition this stores an array of all deleted resources
5
+ #
6
+ # This is used by the Valkyrie::Persistence::BufferedPersister to
7
+ # buffer deletes for efficiency
8
+ #
9
+ # @see Valkyrie::Persistence::BufferedPersister
10
+ #
3
11
  class DeleteTrackingBuffer < Valkyrie::Persistence::Memory::MetadataAdapter
4
12
  def persister
5
13
  @persister ||= DeleteTrackingBuffer::Persister.new(self)
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
+ #
2
3
  module Valkyrie::Persistence
4
+ # Implements the DataMapper Pattern to store metadata into Fedora
3
5
  module Fedora
6
+ require 'valkyrie/persistence/fedora/permissive_schema'
4
7
  require 'valkyrie/persistence/fedora/metadata_adapter'
5
8
  require 'valkyrie/persistence/fedora/persister'
6
9
  require 'valkyrie/persistence/fedora/query_service'
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
+ # Represents a node in an ORE List. Used for persisting ordered members into
4
+ # an RDF Graph for Fedora, to keep order maintained.
3
5
  class ListNode
4
6
  attr_reader :rdf_subject, :graph
5
- attr_accessor :prev, :next, :target
7
+ attr_writer :next, :prev
8
+ attr_accessor :target
6
9
  attr_writer :next_uri, :prev_uri
7
10
  attr_accessor :proxy_in, :proxy_for
8
11
  attr_reader :adapter
@@ -55,7 +58,7 @@ module Valkyrie::Persistence::Fedora
55
58
 
56
59
  private
57
60
 
58
- attr_reader :next_uri, :prev_uri, :graph, :node_cache
61
+ attr_reader :next_uri, :prev_uri, :node_cache
59
62
 
60
63
  class Builder
61
64
  attr_reader :uri, :graph
@@ -1,14 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
+ # Metadata Adapter for Fedora adapter.
4
+ #
5
+ # @example Instantiate with connection to Fedora.
6
+ # Valkyrie::Persistence::Fedora::MetadataAdapter.new(
7
+ # connection: ::Ldp::Client.new("http://localhost:8988/rest"),
8
+ # base_path: "test_fed",
9
+ # schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new(title: RDF::URI("http://bad.com/title"))
10
+ # )
3
11
  class MetadataAdapter
4
- attr_reader :connection, :base_path
5
- def initialize(connection:, base_path: "/")
12
+ attr_reader :connection, :base_path, :schema
13
+ def initialize(connection:, base_path: "/", schema: Valkyrie::Persistence::Fedora::PermissiveSchema.new)
6
14
  @connection = connection
7
15
  @base_path = base_path
16
+ @schema = schema
8
17
  end
9
18
 
10
19
  def query_service
11
- Valkyrie::Persistence::Fedora::QueryService.new(adapter: self)
20
+ @query_service ||= Valkyrie::Persistence::Fedora::QueryService.new(adapter: self)
12
21
  end
13
22
 
14
23
  def persister
@@ -32,14 +41,7 @@ module Valkyrie::Persistence::Fedora
32
41
  end
33
42
 
34
43
  def connection_prefix
35
- "#{connection.options}/#{base_path}"
36
- end
37
-
38
- def wipe!
39
- connection.delete(base_path)
40
- connection.delete("#{base_path}/fcr:tombstone")
41
- rescue => error
42
- Valkyrie.logger.debug("Failed to wipe Fedora for some reason.") unless error.is_a?(::Ldp::NotFound)
44
+ "#{connection.http.url_prefix}/#{base_path}"
43
45
  end
44
46
  end
45
47
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
- ##
4
3
  # Ruby object representation of an ORE doubly linked list.
4
+ # Used in the Fedora adapter for persisting ordered members.
5
5
  class OrderedList
6
6
  include Enumerable
7
7
  attr_reader :graph, :head_subject, :tail_subject, :adapter
@@ -139,7 +139,7 @@ module Valkyrie::Persistence::Fedora
139
139
  class TailSentinel < Sentinel
140
140
  def initialize(*args)
141
141
  super
142
- prev.next = self if prev && prev.next != self
142
+ prev.next = self if prev&.next != self
143
143
  end
144
144
  end
145
145
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
- ##
4
3
  # Lazily iterates over a doubly linked list, fixing up nodes if necessary.
4
+ # Used for reading ordered members out of Fedora, and then converting them to
5
+ # member_ids.
5
6
  class OrderedReader
6
7
  include Enumerable
7
8
  attr_reader :root
@@ -14,7 +15,7 @@ module Valkyrie::Persistence::Fedora
14
15
  while proxy
15
16
  yield proxy unless proxy.nil?
16
17
  next_proxy = proxy.next
17
- next_proxy.try(:prev=, proxy) if next_proxy && next_proxy.prev != proxy
18
+ next_proxy.try(:prev=, proxy) if next_proxy&.prev != proxy
18
19
  proxy = next_proxy
19
20
  end
20
21
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+ module Valkyrie::Persistence::Fedora
3
+ # Default schema for Fedora MetadataAdapter. It's used to generate a mapping
4
+ # of {Valkyrie::Resource} attributes to predicates. This implementation will
5
+ # make up a URI if one doesn't exist in a passed in schema.
6
+ #
7
+ # @example Passing in a mapping
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">
11
+ # schema.predicate_for(resource: Resource.new, property: :unknown) # => RDF::URI<"http://example.com/predicate/unknown">
12
+ class PermissiveSchema
13
+ URI_PREFIX = 'http://example.com/predicate/'
14
+
15
+ # @return [RDF::URI]
16
+ def self.valkyrie_id
17
+ uri_for('valkyrie_id')
18
+ end
19
+
20
+ # @return [RDF::URI]
21
+ def self.id
22
+ uri_for(:id)
23
+ end
24
+
25
+ # @return [RDF::URI]
26
+ def self.member_ids
27
+ uri_for(:member_ids)
28
+ end
29
+
30
+ # @return [RDF::URI]
31
+ def self.valkyrie_bool
32
+ uri_for(:valkyrie_bool)
33
+ end
34
+
35
+ # @return [RDF::URI]
36
+ def self.valkyrie_datetime
37
+ uri_for(:valkyrie_datetime)
38
+ end
39
+
40
+ # @return [RDF::URI]
41
+ def self.valkyrie_int
42
+ uri_for(:valkyrie_int)
43
+ end
44
+
45
+ # @return [RDF::URI]
46
+ def self.valkyrie_time
47
+ uri_for(:valkyrie_time)
48
+ end
49
+
50
+ # Cast the property to a URI in the namespace
51
+ # @param property [Symbol]
52
+ # @return [RDF::URI]
53
+ def self.uri_for(property)
54
+ RDF::URI("#{URI_PREFIX}#{property}")
55
+ end
56
+
57
+ attr_reader :schema
58
+ def initialize(schema = {})
59
+ @schema = schema
60
+ end
61
+
62
+ def predicate_for(resource:, property:)
63
+ schema.fetch(property) { self.class.uri_for(property) }
64
+ end
65
+
66
+ # Find the property in the schema. If it's not there check to see
67
+ # if this prediate is in the URI_PREFIX namespace, return the suffix as the property
68
+ # @example:
69
+ # property_for(resource: nil, predicate: "http://example.com/predicate/internal_resource")
70
+ # #=> 'internal_resource'
71
+ def property_for(resource:, predicate:)
72
+ (schema.find { |_k, v| v == RDF::URI(predicate.to_s) } || []).first || predicate.to_s.gsub(URI_PREFIX, '')
73
+ end
74
+ end
75
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Fedora
3
+ # Persister for Fedora MetadataAdapter.
3
4
  class Persister
4
5
  require 'valkyrie/persistence/fedora/persister/resource_factory'
5
6
  attr_reader :adapter
@@ -8,10 +9,12 @@ module Valkyrie::Persistence::Fedora
8
9
  @adapter = adapter
9
10
  end
10
11
 
12
+ # (see Valkyrie::Persistence::Memory::Persister#save)
11
13
  def save(resource:)
12
14
  initialize_repository
13
15
  resource.created_at ||= Time.current
14
16
  resource.updated_at ||= Time.current
17
+ ensure_multiple_values!(resource)
15
18
  orm = resource_factory.from_resource(resource: resource)
16
19
  if !orm.new? || resource.id
17
20
  orm.update do |req|
@@ -23,18 +26,28 @@ module Valkyrie::Persistence::Fedora
23
26
  resource_factory.to_resource(object: orm)
24
27
  end
25
28
 
29
+ # (see Valkyrie::Persistence::Memory::Persister#save_all)
26
30
  def save_all(resources:)
27
31
  resources.map do |resource|
28
32
  save(resource: resource)
29
33
  end
30
34
  end
31
35
 
36
+ # (see Valkyrie::Persistence::Memory::Persister#delete)
32
37
  def delete(resource:)
33
38
  orm = resource_factory.from_resource(resource: resource)
34
39
  orm.delete
35
40
  resource
36
41
  end
37
42
 
43
+ # (see Valkyrie::Persistence::Memory::Persister#wipe!)
44
+ def wipe!
45
+ connection.delete(base_path)
46
+ connection.delete("#{base_path}/fcr:tombstone")
47
+ rescue => error
48
+ Valkyrie.logger.debug("Failed to wipe Fedora for some reason.") unless error.is_a?(::Ldp::NotFound)
49
+ end
50
+
38
51
  def initialize_repository
39
52
  @initialized ||=
40
53
  begin
@@ -43,5 +56,14 @@ module Valkyrie::Persistence::Fedora
43
56
  true
44
57
  end
45
58
  end
59
+
60
+ private
61
+
62
+ def ensure_multiple_values!(resource)
63
+ bad_keys = resource.attributes.except(:internal_resource, :created_at, :updated_at, :new_record, :id).select do |_k, v|
64
+ !v.nil? && !v.is_a?(Array)
65
+ end
66
+ raise ::Valkyrie::Persistence::UnsupportedDatatype, "#{resource}: #{bad_keys.keys} have non-array values, which can not be persisted by Valkyrie. Cast to arrays." unless bad_keys.keys.empty?
67
+ end
46
68
  end
47
69
  end