valkyrie 1.2.0.rc1 → 1.2.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +12 -4
- data/lib/valkyrie/persistence/composite_persister.rb +1 -1
- data/lib/valkyrie/persistence/fedora/list_node.rb +42 -3
- data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +26 -0
- data/lib/valkyrie/persistence/fedora/ordered_list.rb +36 -5
- data/lib/valkyrie/persistence/fedora/ordered_reader.rb +6 -0
- data/lib/valkyrie/persistence/fedora/permissive_schema.rb +20 -1
- data/lib/valkyrie/persistence/fedora/persister.rb +33 -4
- data/lib/valkyrie/persistence/fedora/persister/alternate_identifier.rb +6 -0
- data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +254 -4
- data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +250 -3
- data/lib/valkyrie/persistence/fedora/persister/resource_factory.rb +6 -0
- data/lib/valkyrie/persistence/fedora/query_service.rb +22 -4
- data/lib/valkyrie/persistence/memory/metadata_adapter.rb +2 -0
- data/lib/valkyrie/persistence/memory/persister.rb +11 -3
- data/lib/valkyrie/persistence/memory/query_service.rb +11 -0
- data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +2 -0
- data/lib/valkyrie/persistence/postgres/orm.rb +4 -0
- data/lib/valkyrie/persistence/postgres/orm_converter.rb +62 -2
- data/lib/valkyrie/persistence/postgres/persister.rb +18 -7
- data/lib/valkyrie/persistence/postgres/query_service.rb +103 -11
- data/lib/valkyrie/persistence/postgres/resource_converter.rb +10 -0
- data/lib/valkyrie/persistence/postgres/resource_factory.rb +3 -0
- data/lib/valkyrie/persistence/solr/composite_indexer.rb +10 -0
- data/lib/valkyrie/persistence/solr/metadata_adapter.rb +7 -0
- data/lib/valkyrie/persistence/solr/model_converter.rb +137 -0
- data/lib/valkyrie/persistence/solr/orm_converter.rb +168 -0
- data/lib/valkyrie/persistence/solr/persister.rb +13 -5
- data/lib/valkyrie/persistence/solr/queries.rb +1 -0
- data/lib/valkyrie/persistence/solr/queries/default_paginator.rb +11 -1
- data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +12 -0
- data/lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb +12 -0
- data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +11 -0
- data/lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb +13 -0
- data/lib/valkyrie/persistence/solr/queries/find_many_by_ids_query.rb +9 -0
- data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +23 -0
- data/lib/valkyrie/persistence/solr/queries/find_ordered_references_query.rb +50 -0
- data/lib/valkyrie/persistence/solr/queries/find_references_query.rb +15 -0
- data/lib/valkyrie/persistence/solr/query_service.rb +47 -14
- data/lib/valkyrie/persistence/solr/repository.rb +21 -4
- data/lib/valkyrie/persistence/solr/resource_factory.rb +2 -0
- data/lib/valkyrie/resource.rb +1 -0
- data/lib/valkyrie/specs/shared_specs.rb +1 -0
- data/lib/valkyrie/specs/shared_specs/persister.rb +92 -2
- data/lib/valkyrie/specs/shared_specs/queries.rb +12 -0
- data/lib/valkyrie/specs/shared_specs/solr_indexer.rb +40 -0
- data/lib/valkyrie/storage/fedora.rb +0 -2
- data/lib/valkyrie/version.rb +1 -1
- metadata +4 -2
@@ -7,14 +7,20 @@ module Valkyrie::Persistence::Fedora
|
|
7
7
|
require 'valkyrie/persistence/fedora/persister/model_converter'
|
8
8
|
require 'valkyrie/persistence/fedora/persister/orm_converter'
|
9
9
|
attr_reader :adapter
|
10
|
+
|
11
|
+
# @param [Valkyrie::Persistence::Fedora::MetadataAdapter] adapter
|
10
12
|
def initialize(adapter:)
|
11
13
|
@adapter = adapter
|
12
14
|
end
|
13
15
|
|
16
|
+
# Construct a LDP::Container::Basic object for a Valkyrie Resource
|
17
|
+
# @return [Valkyrie::Resource] resource
|
14
18
|
def from_resource(resource:)
|
15
19
|
ModelConverter.new(resource: resource, adapter: adapter).convert
|
16
20
|
end
|
17
21
|
|
22
|
+
# Construct a Valkyrie::Resource object for a Valkyrie Resource
|
23
|
+
# @return [LDP::Container::Basic] object
|
18
24
|
def to_resource(object:)
|
19
25
|
OrmConverter.new(object: object, adapter: adapter).convert
|
20
26
|
end
|
@@ -47,6 +47,9 @@ module Valkyrie::Persistence::Fedora
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
# Specify the URIs used in triples directly related to the requested resource
|
51
|
+
# @see https://wiki.duraspace.org/display/FEDORA4x/RESTful+HTTP+API#RESTfulHTTPAPI-GETRetrievethecontentoftheresource
|
52
|
+
# @return [Array<RDF::URI>]
|
50
53
|
def include_uris
|
51
54
|
[
|
52
55
|
::RDF::Vocab::Fcrepo4.InboundReferences
|
@@ -64,8 +67,6 @@ module Valkyrie::Persistence::Fedora
|
|
64
67
|
end
|
65
68
|
|
66
69
|
# (see Valkyrie::Persistence::Memory::QueryService#find_all)
|
67
|
-
#
|
68
|
-
# @note This requires iterating over every resource in Fedora.
|
69
70
|
def find_all
|
70
71
|
resource = Ldp::Resource.for(connection, adapter.base_path, connection.get(adapter.base_path))
|
71
72
|
ids = resource.graph.query([nil, RDF::Vocab::LDP.contains, nil]).map(&:object).map { |x| adapter.uri_to_id(x) }
|
@@ -77,8 +78,6 @@ module Valkyrie::Persistence::Fedora
|
|
77
78
|
end
|
78
79
|
|
79
80
|
# (see Valkyrie::Persistence::Memory::QueryService#find_all_of_model)
|
80
|
-
#
|
81
|
-
# @note This requires iterating over every resource in Fedora.
|
82
81
|
def find_all_of_model(model:)
|
83
82
|
find_all.select do |m|
|
84
83
|
m.is_a?(model)
|
@@ -92,6 +91,11 @@ module Valkyrie::Persistence::Fedora
|
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
94
|
+
# Retrieves the RDF graph for the LDP container for a resource
|
95
|
+
# This includes inbound links
|
96
|
+
# @see https://wiki.duraspace.org/display/FEDORA4x/RESTful+HTTP+API#RESTfulHTTPAPI-GETRetrievethecontentoftheresource
|
97
|
+
# @param id [Valkyrie::ID]
|
98
|
+
# @return [Faraday::Response]
|
95
99
|
def content_with_inbound(id:)
|
96
100
|
uri = adapter.id_to_uri(id)
|
97
101
|
connection.get(uri) do |req|
|
@@ -102,6 +106,9 @@ module Valkyrie::Persistence::Fedora
|
|
102
106
|
end
|
103
107
|
|
104
108
|
# (see Valkyrie::Persistence::Memory::QueryService#find_inverse_references_by)
|
109
|
+
# Find all resources referencing a given resource (e. g. parents)
|
110
|
+
# *This is done by iterating through the ID of each resource referencing the resource in the query, and requesting each resource over the HTTP*
|
111
|
+
# *Also, an initial request is made to find the URIs of the resources referencing the resource in the query*
|
105
112
|
def find_inverse_references_by(resource:, property:)
|
106
113
|
ensure_persisted(resource)
|
107
114
|
content = content_with_inbound(id: resource.id)
|
@@ -112,17 +119,25 @@ module Valkyrie::Persistence::Fedora
|
|
112
119
|
end
|
113
120
|
end
|
114
121
|
|
122
|
+
# (see Valkyrie::Persistence::Memory::QueryService#custom_queries)
|
115
123
|
def custom_queries
|
116
124
|
@custom_queries ||= ::Valkyrie::Persistence::CustomQueryContainer.new(query_service: self)
|
117
125
|
end
|
118
126
|
|
119
127
|
private
|
120
128
|
|
129
|
+
# Ensures that an object is (or can be cast into a) Valkyrie::ID
|
130
|
+
# @return [Valkyrie::ID]
|
131
|
+
# @raise [ArgumentError]
|
121
132
|
def validate_id(id)
|
122
133
|
id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
|
123
134
|
raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
|
124
135
|
end
|
125
136
|
|
137
|
+
# Resolve a URI for an LDP resource in Fedora and construct a Valkyrie::Resource
|
138
|
+
# @param uri [RDF::URI]
|
139
|
+
# @return [Valkyrie::Resource]
|
140
|
+
# @raise [Valkyrie::Persistence::ObjectNotFoundError]
|
126
141
|
def resource_from_uri(uri)
|
127
142
|
resource = Ldp::Resource.for(connection, uri, connection.get(uri))
|
128
143
|
resource_factory.to_resource(object: resource)
|
@@ -130,6 +145,9 @@ module Valkyrie::Persistence::Fedora
|
|
130
145
|
raise ::Valkyrie::Persistence::ObjectNotFoundError
|
131
146
|
end
|
132
147
|
|
148
|
+
# Ensures that a Valkyrie::Resource has been persisted
|
149
|
+
# @param resource [Valkyrie::Resource]
|
150
|
+
# @raise [ArgumentError]
|
133
151
|
def ensure_persisted(resource)
|
134
152
|
raise ArgumentError, 'resource is not saved' unless resource.persisted?
|
135
153
|
end
|
@@ -20,10 +20,12 @@ module Valkyrie::Persistence::Memory
|
|
20
20
|
@query_service ||= Valkyrie::Persistence::Memory::QueryService.new(adapter: self)
|
21
21
|
end
|
22
22
|
|
23
|
+
# @return [Hash] The in-memory data cache.
|
23
24
|
def cache
|
24
25
|
@cache ||= {}
|
25
26
|
end
|
26
27
|
|
28
|
+
# @return [Valkyrie::ID] Identifier for this metadata adapter.
|
27
29
|
def id
|
28
30
|
@id ||= Valkyrie::ID.new(Digest::MD5.hexdigest(self.class.to_s))
|
29
31
|
end
|
@@ -14,11 +14,13 @@ module Valkyrie::Persistence::Memory
|
|
14
14
|
@adapter = adapter
|
15
15
|
end
|
16
16
|
|
17
|
+
# Save a single resource.
|
17
18
|
# @param resource [Valkyrie::Resource] The resource to save.
|
18
19
|
# @return [Valkyrie::Resource] The resource with an `#id` value generated by the
|
19
20
|
# persistence backend.
|
21
|
+
# @raise [Valkyrie::Persistence::StaleObjectError]
|
20
22
|
def save(resource:)
|
21
|
-
raise Valkyrie::Persistence::StaleObjectError, resource.id unless valid_lock?(resource)
|
23
|
+
raise Valkyrie::Persistence::StaleObjectError, "The object #{resource.id} has been updated by another process." unless valid_lock?(resource)
|
22
24
|
|
23
25
|
# duplicate the resource so we are not creating side effects on the caller's resource
|
24
26
|
internal_resource = resource.dup
|
@@ -32,25 +34,28 @@ module Valkyrie::Persistence::Memory
|
|
32
34
|
cache[internal_resource.id] = internal_resource
|
33
35
|
end
|
34
36
|
|
37
|
+
# Save a batch of resources.
|
35
38
|
# @param resources [Array<Valkyrie::Resource>] List of resources to save.
|
36
39
|
# @return [Array<Valkyrie::Resource>] List of resources with an `#id` value
|
37
40
|
# generated by the persistence backend.
|
41
|
+
# @raise [Valkyrie::Persistence::StaleObjectError]
|
38
42
|
def save_all(resources:)
|
39
43
|
resources.map do |resource|
|
40
44
|
save(resource: resource)
|
41
45
|
end
|
42
46
|
rescue Valkyrie::Persistence::StaleObjectError
|
43
47
|
# Re-raising with no error message to prevent confusion
|
44
|
-
raise Valkyrie::Persistence::StaleObjectError
|
48
|
+
raise Valkyrie::Persistence::StaleObjectError, "One or more resources have been updated by another process."
|
45
49
|
end
|
46
50
|
|
51
|
+
# Delete a resource.
|
47
52
|
# @param resource [Valkyrie::Resource] The resource to delete from the persistence
|
48
53
|
# backend.
|
49
54
|
def delete(resource:)
|
50
55
|
cache.delete(resource.id)
|
51
56
|
end
|
52
57
|
|
53
|
-
#
|
58
|
+
# Removes all data from the persistence backend.
|
54
59
|
def wipe!
|
55
60
|
cache.clear
|
56
61
|
end
|
@@ -61,6 +66,7 @@ module Valkyrie::Persistence::Memory
|
|
61
66
|
resource.new(id: SecureRandom.uuid)
|
62
67
|
end
|
63
68
|
|
69
|
+
# Convert all dates to DateTime in the UTC time zone for consistency.
|
64
70
|
def normalize_dates!(resource)
|
65
71
|
resource.attributes.each { |k, v| resource.send("#{k}=", normalize_date_values(v)) }
|
66
72
|
end
|
@@ -76,12 +82,14 @@ module Valkyrie::Persistence::Memory
|
|
76
82
|
value
|
77
83
|
end
|
78
84
|
|
85
|
+
# Create a new lock token based on the current timestamp.
|
79
86
|
def generate_lock_token(resource)
|
80
87
|
return unless resource.optimistic_locking_enabled?
|
81
88
|
token = Valkyrie::Persistence::OptimisticLockToken.new(adapter_id: adapter.id, token: Time.now.to_r)
|
82
89
|
resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", token)
|
83
90
|
end
|
84
91
|
|
92
|
+
# Check whether a resource is current.
|
85
93
|
def valid_lock?(resource)
|
86
94
|
return true unless resource.optimistic_locking_enabled?
|
87
95
|
|
@@ -15,6 +15,7 @@ module Valkyrie::Persistence::Memory
|
|
15
15
|
@query_handlers = []
|
16
16
|
end
|
17
17
|
|
18
|
+
# Get a single resource by ID.
|
18
19
|
# @param id [Valkyrie::ID] The ID to query for.
|
19
20
|
# @raise [Valkyrie::Persistence::ObjectNotFoundError] Raised when the ID
|
20
21
|
# isn't in the persistence backend.
|
@@ -26,6 +27,7 @@ module Valkyrie::Persistence::Memory
|
|
26
27
|
cache[id] || raise(::Valkyrie::Persistence::ObjectNotFoundError)
|
27
28
|
end
|
28
29
|
|
30
|
+
# Get a single resource by `alternate_identifier`.
|
29
31
|
# @param alternate_identifier [Valkyrie::ID] The alternate identifier to query for.
|
30
32
|
# @raise [Valkyrie::Persistence::ObjectNotFoundError] Raised when the alternate identifier
|
31
33
|
# isn't in the persistence backend.
|
@@ -37,6 +39,7 @@ module Valkyrie::Persistence::Memory
|
|
37
39
|
cache.select { |_key, resource| resource['alternate_ids'].include?(alternate_identifier) }.values.first || raise(::Valkyrie::Persistence::ObjectNotFoundError)
|
38
40
|
end
|
39
41
|
|
42
|
+
# Get a batch of resources by ID.
|
40
43
|
# @param ids [Array<Valkyrie::ID, String>] The IDs to query for.
|
41
44
|
# @raise [ArgumentError] Raised when any ID is not a String or a Valkyrie::ID
|
42
45
|
# @return [Array<Valkyrie::Resource>] All requested objects that were found
|
@@ -50,11 +53,13 @@ module Valkyrie::Persistence::Memory
|
|
50
53
|
end.reject(&:nil?)
|
51
54
|
end
|
52
55
|
|
56
|
+
# Get all objects.
|
53
57
|
# @return [Array<Valkyrie::Resource>] All objects in the persistence backend.
|
54
58
|
def find_all
|
55
59
|
cache.values
|
56
60
|
end
|
57
61
|
|
62
|
+
# Get all objects of a given model.
|
58
63
|
# @param model [Class] Class to query for.
|
59
64
|
# @return [Array<Valkyrie::Resource>] All objects in the persistence backend
|
60
65
|
# with the given class.
|
@@ -64,6 +69,7 @@ module Valkyrie::Persistence::Memory
|
|
64
69
|
end
|
65
70
|
end
|
66
71
|
|
72
|
+
# Get all members of a given resource.
|
67
73
|
# @param resource [Valkyrie::Resource] Model whose members are being searched for.
|
68
74
|
# @param model [Class] Class to query for. (optional)
|
69
75
|
# @return [Array<Valkyrie::Resource>] child objects of type `model` referenced by
|
@@ -76,6 +82,7 @@ module Valkyrie::Persistence::Memory
|
|
76
82
|
result.select { |obj| obj.is_a?(model) }
|
77
83
|
end
|
78
84
|
|
85
|
+
# Get all resources referenced from a resource with a given property.
|
79
86
|
# @param resource [Valkyrie::Resource] Model whose property is being searched.
|
80
87
|
# @param property [Symbol] Property which, on the `resource`, contains {Valkyrie::ID}s which are
|
81
88
|
# to be de-referenced.
|
@@ -87,6 +94,7 @@ module Valkyrie::Persistence::Memory
|
|
87
94
|
end
|
88
95
|
end
|
89
96
|
|
97
|
+
# Get all resources which link to a resource with a given property.
|
90
98
|
# @param resource [Valkyrie::Resource] The resource which is being referenced by
|
91
99
|
# other resources.
|
92
100
|
# @param property [Symbol] The property which, on other resources, is
|
@@ -106,6 +114,7 @@ module Valkyrie::Persistence::Memory
|
|
106
114
|
end
|
107
115
|
end
|
108
116
|
|
117
|
+
# Find all parents of a given resource.
|
109
118
|
# @param resource [Valkyrie::Resource] The resource whose parents are being searched
|
110
119
|
# for.
|
111
120
|
# @return [Array<Valkyrie::Resource>] All resources which are parents of the given
|
@@ -117,6 +126,8 @@ module Valkyrie::Persistence::Memory
|
|
117
126
|
end
|
118
127
|
end
|
119
128
|
|
129
|
+
# Get the set of custom queries configured for this query service.
|
130
|
+
# @return [Valkyrie::Persistence::CustomQueryContainer] Container of custom queries
|
120
131
|
def custom_queries
|
121
132
|
@custom_queries ||= ::Valkyrie::Persistence::CustomQueryContainer.new(query_service: self)
|
122
133
|
end
|
@@ -26,6 +26,8 @@ module Valkyrie::Persistence::Postgres
|
|
26
26
|
@resource_factory ||= Valkyrie::Persistence::Postgres::ResourceFactory.new(adapter: self)
|
27
27
|
end
|
28
28
|
|
29
|
+
# Construct a Valkyrie ID object using an MD5 hash generated from the database URL
|
30
|
+
# @return [Valkyrie::ID]
|
29
31
|
def id
|
30
32
|
@id ||= begin
|
31
33
|
to_hash = "#{resource_factory.orm_class.connection_config['host']}:#{resource_factory.orm_class.connection_config['database']}"
|
@@ -3,6 +3,10 @@ require 'valkyrie/persistence/postgres/orm/resource'
|
|
3
3
|
module Valkyrie::Persistence::Postgres
|
4
4
|
# Namespace for ActiveRecord access in Postgres adapter.
|
5
5
|
module ORM
|
6
|
+
# Provides the name prefix for the ActiveRecord database table name
|
7
|
+
# (Maps to the data model for persistence)
|
8
|
+
# @see https://api.rubyonrails.org/classes/ActiveRecord/ModelSchema.html#method-c-table_name_prefix
|
9
|
+
# @return [String]
|
6
10
|
def self.table_name_prefix
|
7
11
|
'orm_'
|
8
12
|
end
|
@@ -4,6 +4,9 @@ module Valkyrie::Persistence::Postgres
|
|
4
4
|
# {Valkyrie::Persistence::Postgres::ORM::Resource} to a {Valkyrie::Resource}
|
5
5
|
class ORMConverter
|
6
6
|
attr_reader :orm_object, :resource_factory
|
7
|
+
|
8
|
+
# @param [ORM::Resource] orm_object
|
9
|
+
# @param [ResourceFactory] resource_factory
|
7
10
|
def initialize(orm_object, resource_factory:)
|
8
11
|
@orm_object = orm_object
|
9
12
|
@resource_factory = resource_factory
|
@@ -11,12 +14,15 @@ module Valkyrie::Persistence::Postgres
|
|
11
14
|
|
12
15
|
# Create a new instance of the class described in attributes[:internal_resource]
|
13
16
|
# and send it all the attributes that @orm_object has
|
17
|
+
# @return [Valkyrie::Resource]
|
14
18
|
def convert!
|
15
19
|
@resource ||= resource
|
16
20
|
end
|
17
21
|
|
18
22
|
private
|
19
23
|
|
24
|
+
# Construct a new Valkyrie Resource using the attributes retrieved from the database
|
25
|
+
# @return [Valkyrie::Resource]
|
20
26
|
def resource
|
21
27
|
resource_klass.new(
|
22
28
|
attributes.merge(
|
@@ -26,6 +32,8 @@ module Valkyrie::Persistence::Postgres
|
|
26
32
|
)
|
27
33
|
end
|
28
34
|
|
35
|
+
# Construct the optimistic lock token using the adapter and lock version for the Resource
|
36
|
+
# @return [Valkyrie::Persistence::OptimisticLockToken]
|
29
37
|
def lock_token
|
30
38
|
return lock_token_warning unless orm_object.class.column_names.include?("lock_version")
|
31
39
|
@lock_token ||=
|
@@ -35,6 +43,7 @@ module Valkyrie::Persistence::Postgres
|
|
35
43
|
)
|
36
44
|
end
|
37
45
|
|
46
|
+
# Issue a migration warning for previous releases of Valkyrie which did not support optimistic locking
|
38
47
|
def lock_token_warning
|
39
48
|
return nil unless resource_klass.optimistic_locking_enabled?
|
40
49
|
warn "[MIGRATION REQUIRED] You have loaded a resource from the Postgres adapter with " \
|
@@ -44,10 +53,14 @@ module Valkyrie::Persistence::Postgres
|
|
44
53
|
nil
|
45
54
|
end
|
46
55
|
|
56
|
+
# Retrieve the Class used to construct the Valkyrie Resource
|
57
|
+
# @return [Class]
|
47
58
|
def resource_klass
|
48
59
|
internal_resource.constantize
|
49
60
|
end
|
50
61
|
|
62
|
+
# Access the String for the Valkyrie Resource type within the attributes
|
63
|
+
# @return [String]
|
51
64
|
def internal_resource
|
52
65
|
attributes[:internal_resource]
|
53
66
|
end
|
@@ -57,6 +70,8 @@ module Valkyrie::Persistence::Postgres
|
|
57
70
|
@attributes ||= orm_object.attributes.merge(rdf_metadata).symbolize_keys
|
58
71
|
end
|
59
72
|
|
73
|
+
# Generate a Hash derived from Valkyrie Resource metadata encoded in the RDF
|
74
|
+
# @return [Hash]
|
60
75
|
def rdf_metadata
|
61
76
|
@rdf_metadata ||= RDFMetadata.new(orm_object.metadata).result
|
62
77
|
end
|
@@ -66,12 +81,16 @@ module Valkyrie::Persistence::Postgres
|
|
66
81
|
# for {Valkyrie::Resource}
|
67
82
|
class RDFMetadata
|
68
83
|
attr_reader :metadata
|
84
|
+
|
85
|
+
# @param [Hash] metadata
|
69
86
|
def initialize(metadata)
|
70
87
|
# nil hash values are handled by the default state in dry-types
|
71
88
|
# anyways, so don't bother processing them here.
|
72
89
|
@metadata = metadata.compact
|
73
90
|
end
|
74
91
|
|
92
|
+
# Convert the database attribute values and map these to the existing keys in the Valkyrie Resource metadata
|
93
|
+
# @return [Hash]
|
75
94
|
def result
|
76
95
|
Hash[
|
77
96
|
metadata.map do |key, value|
|
@@ -80,16 +99,26 @@ module Valkyrie::Persistence::Postgres
|
|
80
99
|
]
|
81
100
|
end
|
82
101
|
|
102
|
+
# Abstract base class for mapping PostgreSQL database field values to Valkyrie Resource attributes
|
83
103
|
class PostgresValue < ::Valkyrie::ValueMapper
|
84
104
|
end
|
105
|
+
|
85
106
|
# Converts {RDF::Literal} typed-literals from JSON-LD stored into an
|
86
107
|
# {RDF::Literal}
|
87
108
|
class HashValue < ::Valkyrie::ValueMapper
|
88
109
|
PostgresValue.register(self)
|
110
|
+
|
111
|
+
# Determines whether or not a value is a Hash containing the key "@value"
|
112
|
+
# @param [Object] value
|
113
|
+
# @return [Boolean]
|
89
114
|
def self.handles?(value)
|
90
115
|
value.is_a?(Hash) && value["@value"]
|
91
116
|
end
|
92
117
|
|
118
|
+
# Constructs a RDF::Literal object using the Object keyed to "@value"
|
119
|
+
# in the value Hash, as well as the language keyed to "@language" and
|
120
|
+
# datatype keyed to "@type"
|
121
|
+
# @return [RDF::Literal]
|
93
122
|
def result
|
94
123
|
RDF::Literal.new(value["@value"],
|
95
124
|
language: value["@language"],
|
@@ -100,10 +129,16 @@ module Valkyrie::Persistence::Postgres
|
|
100
129
|
# Converts stored IDs into {Valkyrie::ID}s
|
101
130
|
class IDValue < ::Valkyrie::ValueMapper
|
102
131
|
PostgresValue.register(self)
|
132
|
+
|
133
|
+
# Determines whether or not a value is a Hash containing the key "id" (excluding those storing the Valkyrie Resource type)
|
134
|
+
# @param [Object] value
|
135
|
+
# @return [Boolean]
|
103
136
|
def self.handles?(value)
|
104
137
|
value.is_a?(Hash) && value["id"] && !value["internal_resource"]
|
105
138
|
end
|
106
139
|
|
140
|
+
# Constructs a Valkyrie::ID object using the String keyed to "id" in the value
|
141
|
+
# @return [Valkyrie::ID]
|
107
142
|
def result
|
108
143
|
Valkyrie::ID.new(value["id"])
|
109
144
|
end
|
@@ -112,10 +147,16 @@ module Valkyrie::Persistence::Postgres
|
|
112
147
|
# Converts stored URIs into {RDF::URI}s
|
113
148
|
class URIValue < ::Valkyrie::ValueMapper
|
114
149
|
PostgresValue.register(self)
|
150
|
+
|
151
|
+
# Determines whether or not a value is a Hash containing the key "@id"
|
152
|
+
# @param [Object] value
|
153
|
+
# @return [Boolean]
|
115
154
|
def self.handles?(value)
|
116
155
|
value.is_a?(Hash) && value["@id"]
|
117
156
|
end
|
118
157
|
|
158
|
+
# Constructs a RDF::URI object using the URI keyed to @id in the value
|
159
|
+
# @return [RDF::URI]
|
119
160
|
def result
|
120
161
|
::RDF::URI.new(value["@id"])
|
121
162
|
end
|
@@ -124,10 +165,16 @@ module Valkyrie::Persistence::Postgres
|
|
124
165
|
# Converts nested records into {Valkyrie::Resource}s
|
125
166
|
class NestedRecord < ::Valkyrie::ValueMapper
|
126
167
|
PostgresValue.register(self)
|
168
|
+
|
169
|
+
# Determines whether or not a value is a Hash containing multiple keys
|
170
|
+
# @param [Object] value
|
171
|
+
# @return [Boolean]
|
127
172
|
def self.handles?(value)
|
128
173
|
value.is_a?(Hash) && value.keys.length > 1
|
129
174
|
end
|
130
175
|
|
176
|
+
# Generates a Hash derived from the RDFMetadata for the value
|
177
|
+
# @return [Hash]
|
131
178
|
def result
|
132
179
|
RDFMetadata.new(value).result.symbolize_keys
|
133
180
|
end
|
@@ -136,13 +183,19 @@ module Valkyrie::Persistence::Postgres
|
|
136
183
|
# Handles iterating over arrays of values and converting each value.
|
137
184
|
class EnumeratorValue < ::Valkyrie::ValueMapper
|
138
185
|
PostgresValue.register(self)
|
186
|
+
|
187
|
+
# Determines whether or not a value has enumerable behavior
|
188
|
+
# @param [Object] value
|
189
|
+
# @return [Boolean]
|
139
190
|
def self.handles?(value)
|
140
191
|
value.respond_to?(:each)
|
141
192
|
end
|
142
193
|
|
194
|
+
# Convert the elements in the enumerable value in Valkyrie attribute values
|
195
|
+
# Casts single-valued arrays to the first value, letting Types::Set and
|
196
|
+
# Types::Array handle converting it back.
|
197
|
+
# @return [Array<Object>]
|
143
198
|
def result
|
144
|
-
# Cast single-valued arrays to the first value, let Types::Set and
|
145
|
-
# Types::Array handle converting it back.
|
146
199
|
if value.length == 1
|
147
200
|
calling_mapper.for(value.first).result
|
148
201
|
else
|
@@ -156,6 +209,11 @@ module Valkyrie::Persistence::Postgres
|
|
156
209
|
# Converts Date strings to `DateTime`
|
157
210
|
class DateValue < ::Valkyrie::ValueMapper
|
158
211
|
PostgresValue.register(self)
|
212
|
+
|
213
|
+
# Determines whether or not a value is an ISO 8601 datestamp String
|
214
|
+
# e. g. 1970-01-01
|
215
|
+
# @param [Object] value
|
216
|
+
# @return [Boolean]
|
159
217
|
def self.handles?(value)
|
160
218
|
return false unless value.is_a?(String)
|
161
219
|
return false unless value[4] == "-"
|
@@ -166,6 +224,8 @@ module Valkyrie::Persistence::Postgres
|
|
166
224
|
false
|
167
225
|
end
|
168
226
|
|
227
|
+
# Generates a Time object in the UTC from the datestamp string value
|
228
|
+
# @return [Time]
|
169
229
|
def result
|
170
230
|
DateTime.iso8601(value).utc
|
171
231
|
end
|