valkyrie 2.1.0 → 3.0.0.pre.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.circleci/config.yml +71 -36
- data/.lando.yml +58 -0
- data/.rubocop.yml +11 -1
- data/.tool-versions +1 -1
- data/CHANGELOG.md +94 -13
- data/CONTRIBUTING.md +30 -8
- data/README.md +24 -48
- data/Rakefile +26 -20
- data/db/config.yml +3 -10
- data/lib/generators/valkyrie/resource_generator.rb +3 -3
- data/lib/valkyrie/change_set.rb +3 -3
- data/lib/valkyrie/id.rb +12 -19
- data/lib/valkyrie/indexers/access_controls_indexer.rb +17 -17
- data/lib/valkyrie/persistence/buffered_persister.rb +2 -2
- data/lib/valkyrie/persistence/composite_persister.rb +3 -3
- data/lib/valkyrie/persistence/custom_query_container.rb +8 -16
- data/lib/valkyrie/persistence/fedora/list_node.rb +43 -43
- data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +5 -1
- data/lib/valkyrie/persistence/fedora/ordered_list.rb +90 -90
- data/lib/valkyrie/persistence/fedora/ordered_reader.rb +5 -5
- data/lib/valkyrie/persistence/fedora/permissive_schema.rb +1 -1
- data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +15 -16
- data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +14 -19
- data/lib/valkyrie/persistence/fedora/persister.rb +83 -83
- data/lib/valkyrie/persistence/fedora/query_service.rb +39 -41
- data/lib/valkyrie/persistence/memory/persister.rb +51 -35
- data/lib/valkyrie/persistence/memory/query_service.rb +26 -30
- data/lib/valkyrie/persistence/postgres/orm_converter.rb +52 -52
- data/lib/valkyrie/persistence/postgres/persister.rb +4 -1
- data/lib/valkyrie/persistence/postgres/query_service.rb +34 -34
- data/lib/valkyrie/persistence/shared/json_value_mapper.rb +1 -1
- data/lib/valkyrie/persistence/solr/metadata_adapter.rb +15 -3
- data/lib/valkyrie/persistence/solr/model_converter.rb +323 -340
- data/lib/valkyrie/persistence/solr/orm_converter.rb +4 -4
- data/lib/valkyrie/persistence/solr/persister.rb +16 -4
- data/lib/valkyrie/persistence/solr/queries/find_by_alternate_identifier_query.rb +1 -1
- data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +1 -1
- data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +1 -1
- data/lib/valkyrie/persistence/solr/query_service.rb +12 -12
- data/lib/valkyrie/persistence/solr/repository.rb +17 -7
- data/lib/valkyrie/resource/access_controls.rb +1 -1
- data/lib/valkyrie/resource.rb +0 -1
- data/lib/valkyrie/specs/shared_specs/change_set.rb +1 -1
- data/lib/valkyrie/specs/shared_specs/file.rb +1 -0
- data/lib/valkyrie/specs/shared_specs/persister.rb +22 -4
- data/lib/valkyrie/specs/shared_specs/queries.rb +7 -0
- data/lib/valkyrie/specs/shared_specs/resource.rb +1 -1
- data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +19 -0
- data/lib/valkyrie/specs/shared_specs/write_only/metadata_adapter.rb +62 -0
- data/lib/valkyrie/specs/shared_specs.rb +2 -0
- data/lib/valkyrie/storage/disk.rb +24 -1
- data/lib/valkyrie/storage/fedora.rb +17 -17
- data/lib/valkyrie/storage_adapter.rb +12 -12
- data/lib/valkyrie/types.rb +1 -1
- data/lib/valkyrie/version.rb +1 -1
- data/lib/valkyrie/vocab/pcdm_use.rb +12 -0
- data/lib/valkyrie.rb +13 -27
- data/tasks/dev.rake +14 -51
- data/valkyrie.gemspec +3 -6
- metadata +25 -63
- data/.docker-stack/valkyrie-development/docker-compose.yml +0 -53
- data/.docker-stack/valkyrie-test/docker-compose.yml +0 -53
- data/tasks/docker.rake +0 -31
data/Rakefile
CHANGED
@@ -6,7 +6,6 @@ require 'config/database_connection'
|
|
6
6
|
require 'active_record'
|
7
7
|
require 'rubocop/rake_task'
|
8
8
|
load 'tasks/dev.rake'
|
9
|
-
load 'tasks/docker.rake'
|
10
9
|
|
11
10
|
RSpec::Core::RakeTask.new(:spec)
|
12
11
|
|
@@ -33,12 +32,21 @@ namespace :db do
|
|
33
32
|
task configure_connection: :configuration do
|
34
33
|
DatabaseConnection.connect!(DATABASE_ENV)
|
35
34
|
ActiveRecord::Base.logger = Logger.new STDOUT if @config['logger']
|
35
|
+
@config = if ::ActiveRecord::Base.configurations.respond_to?(:configs_for)
|
36
|
+
::ActiveRecord::Base.configurations.configs_for(env_name: DATABASE_ENV.to_s)[0]
|
37
|
+
else
|
38
|
+
::ActiveRecord::Base.configurations[DATABASE_ENV.to_s]
|
39
|
+
end
|
36
40
|
end
|
37
41
|
|
38
42
|
desc 'Create the database from db/config.yml for the current DATABASE_ENV'
|
39
43
|
task create: :configure_connection do
|
40
|
-
|
41
|
-
|
44
|
+
begin
|
45
|
+
database = ActiveRecord::Tasks::PostgreSQLDatabaseTasks.new(@config)
|
46
|
+
database.create
|
47
|
+
rescue
|
48
|
+
puts "Database already exists."
|
49
|
+
end
|
42
50
|
puts "Database created"
|
43
51
|
end
|
44
52
|
|
@@ -51,25 +59,23 @@ namespace :db do
|
|
51
59
|
|
52
60
|
desc 'Migrate the database (options: VERSION=x, VERBOSE=false).'
|
53
61
|
task migrate: :configure_connection do
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
scope.blank? || scope == migration.scope
|
67
|
-
end
|
62
|
+
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
63
|
+
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
64
|
+
scope = ENV['SCOPE']
|
65
|
+
verbose_was = ActiveRecord::Migration.verbose
|
66
|
+
ActiveRecord::Migration.verbose = verbose
|
67
|
+
if ActiveRecord::Migrator.respond_to?(:migrate)
|
68
|
+
ActiveRecord::Migrator.migrate(MIGRATIONS_DIR, version) do |migration|
|
69
|
+
scope.blank? || scope == migration.scope
|
70
|
+
end
|
71
|
+
else
|
72
|
+
ActiveRecord::Base.connection.migration_context.migrate(version) do |migration|
|
73
|
+
scope.blank? || scope == migration.scope
|
68
74
|
end
|
69
|
-
ActiveRecord::Base.clear_cache!
|
70
|
-
ensure
|
71
|
-
ActiveRecord::Migration.verbose = verbose_was
|
72
75
|
end
|
76
|
+
ActiveRecord::Base.clear_cache!
|
77
|
+
ensure
|
78
|
+
ActiveRecord::Migration.verbose = verbose_was
|
73
79
|
end
|
74
80
|
|
75
81
|
namespace :schema do
|
data/db/config.yml
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
<% local = File.exist?('/tmp/.s.PGSQL.5432') && File.stat('/tmp/.s.PGSQL.5432').socket? %>
|
2
1
|
default: &default
|
3
2
|
adapter: postgresql
|
4
3
|
encoding: utf8
|
@@ -6,22 +5,16 @@ default: &default
|
|
6
5
|
pool: <%= Integer(ENV.fetch("DB_POOL", 5)) %>
|
7
6
|
reaping_frequency: <%= Integer(ENV.fetch("DB_REAPING_FREQUENCY", 10)) %>
|
8
7
|
timeout: 5000
|
9
|
-
<% unless local %>
|
10
8
|
host: localhost
|
11
|
-
username:
|
12
|
-
password:
|
13
|
-
<% end %>
|
9
|
+
username: postgres
|
10
|
+
password:
|
14
11
|
|
15
12
|
development:
|
16
13
|
<<: *default
|
17
14
|
database: Valkyrie_gem_development
|
18
|
-
<% unless local %>
|
19
15
|
port: 5433
|
20
|
-
<% end %>
|
21
16
|
|
22
17
|
test:
|
23
18
|
<<: *default
|
24
19
|
database: Valkyrie_gem_test
|
25
|
-
|
26
|
-
port: 5434
|
27
|
-
<% end %>
|
20
|
+
port: <%= ENV["POSTGRES_PORT"] || 5433 %>
|
data/lib/valkyrie/change_set.rb
CHANGED
data/lib/valkyrie/id.rb
CHANGED
@@ -10,36 +10,29 @@ module Valkyrie
|
|
10
10
|
@id = id.to_s
|
11
11
|
end
|
12
12
|
|
13
|
+
##
|
14
|
+
# @return [String]
|
13
15
|
def to_s
|
16
|
+
to_str
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# @return [String]
|
21
|
+
def to_str
|
14
22
|
id
|
15
23
|
end
|
16
24
|
|
17
25
|
delegate :hash, to: :state
|
18
26
|
|
19
27
|
def eql?(other)
|
20
|
-
|
21
|
-
default_equality(other)
|
28
|
+
other == to_str
|
22
29
|
end
|
23
30
|
alias == eql?
|
24
31
|
|
25
32
|
protected
|
26
33
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
if output == false && string_equality(other) && Valkyrie.config.id_string_equality.nil?
|
31
|
-
warn "[DEPRECATION] Valkyrie::IDs will always be equal to their string counterparts in 3.0.0. " \
|
32
|
-
"To silence this message, please either compare IDs or set Valkyrie.config.id_string_equality = true."
|
33
|
-
end
|
34
|
-
false
|
35
|
-
end
|
36
|
-
|
37
|
-
def string_equality(other)
|
38
|
-
other.to_s == to_s
|
39
|
-
end
|
40
|
-
|
41
|
-
def state
|
42
|
-
[@id]
|
43
|
-
end
|
34
|
+
def state
|
35
|
+
[@id]
|
36
|
+
end
|
44
37
|
end
|
45
38
|
end
|
@@ -40,24 +40,24 @@ module Valkyrie::Indexers
|
|
40
40
|
|
41
41
|
private
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
43
|
+
# rubocop:disable Metrics/MethodLength
|
44
|
+
def default_config
|
45
|
+
if defined?(Hydra) && Hydra.respond_to?(:config)
|
46
|
+
{
|
47
|
+
read_groups: Hydra.config[:permissions][:read].group,
|
48
|
+
read_users: Hydra.config[:permissions][:read].individual,
|
49
|
+
edit_groups: Hydra.config[:permissions][:edit].group,
|
50
|
+
edit_users: Hydra.config[:permissions][:edit].individual
|
51
|
+
}
|
52
|
+
else
|
53
|
+
{
|
54
|
+
read_groups: 'read_access_group_ssim',
|
55
|
+
read_users: 'read_access_person_ssim',
|
56
|
+
edit_groups: 'edit_access_group_ssim',
|
57
|
+
edit_users: 'edit_access_person_ssim'
|
58
|
+
}
|
60
59
|
end
|
60
|
+
end
|
61
61
|
# rubocop:enable Metrics/MethodLength
|
62
62
|
end
|
63
63
|
end
|
@@ -24,8 +24,8 @@ module Valkyrie::Persistence
|
|
24
24
|
@buffer_class = buffer_class
|
25
25
|
end
|
26
26
|
|
27
|
-
def save(resource:)
|
28
|
-
persister.save(resource: resource)
|
27
|
+
def save(resource:, external_resource: false)
|
28
|
+
persister.save(resource: resource, external_resource: external_resource)
|
29
29
|
end
|
30
30
|
|
31
31
|
def save_all(resources:)
|
@@ -24,14 +24,14 @@ module Valkyrie::Persistence
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# (see Valkyrie::Persistence::Memory::Persister#save)
|
27
|
-
def save(resource:)
|
27
|
+
def save(resource:, external_resource: false)
|
28
28
|
# Assume the first persister is the canonical data store; that's the optlock we want
|
29
29
|
first, *rest = *persisters
|
30
|
-
cached_resource = first.save(resource: resource)
|
30
|
+
cached_resource = first.save(resource: resource, external_resource: external_resource)
|
31
31
|
# Don't pass opt lock tokens to other persisters
|
32
32
|
internal_resource = cached_resource.dup
|
33
33
|
internal_resource.clear_optimistic_lock_token!
|
34
|
-
rest.inject(internal_resource) { |m, persister| persister.save(resource: m) }
|
34
|
+
rest.inject(internal_resource) { |m, persister| persister.save(resource: m, external_resource: true) }
|
35
35
|
# return the one with the desired opt lock token
|
36
36
|
cached_resource
|
37
37
|
end
|
@@ -39,25 +39,17 @@ module Valkyrie::Persistence
|
|
39
39
|
attr_reader :query_service, :query_handlers
|
40
40
|
def initialize(query_service:)
|
41
41
|
@query_service = query_service
|
42
|
-
@query_handlers =
|
42
|
+
@query_handlers = {}
|
43
43
|
end
|
44
44
|
|
45
45
|
def register_query_handler(query_handler)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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?
|
46
|
+
query_handler.queries.each do |query|
|
47
|
+
handler = query_handler.new(query_service: query_service)
|
48
|
+
query_handlers[query.to_sym] = handler
|
49
|
+
define_singleton_method query do |*args, &block|
|
50
|
+
query_handlers[query.to_sym].__send__(query, *args, &block)
|
51
|
+
end
|
52
|
+
end
|
61
53
|
end
|
62
54
|
end
|
63
55
|
end
|
@@ -85,60 +85,60 @@ module Valkyrie::Persistence::Fedora
|
|
85
85
|
|
86
86
|
private
|
87
87
|
|
88
|
-
|
88
|
+
attr_reader :next_uri, :prev_uri, :node_cache
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
# Class used to populate the RDF graph structure for the linked lists
|
91
|
+
class Builder
|
92
|
+
attr_reader :uri, :graph
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
109
109
|
|
110
|
-
|
110
|
+
private
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
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)
|
117
116
|
end
|
117
|
+
end
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
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
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
end
|
126
|
+
define_method "#{property}=" do |val|
|
127
|
+
return if val.nil?
|
128
|
+
graph << [uri, predicate, val]
|
130
129
|
end
|
130
|
+
end
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
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
|
136
136
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
137
|
+
attr_reader :graph, :uri
|
138
|
+
def initialize(uri, graph: RDF::Graph.new)
|
139
|
+
@uri = uri
|
140
|
+
@graph = graph
|
142
141
|
end
|
142
|
+
end
|
143
143
|
end
|
144
144
|
end
|
@@ -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 =
|
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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
83
|
+
# Constructs a new OrderedReader for this OrderedList
|
84
|
+
# @return [OrderedReader]
|
85
|
+
def ordered_reader
|
86
|
+
OrderedReader.new(self)
|
87
|
+
end
|
88
88
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
107
|
+
# Class used for caching LinkedNode objects mapped to URIs
|
108
|
+
class NodeCache
|
109
|
+
def initialize
|
110
|
+
@cache ||= {}
|
111
|
+
end
|
112
112
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
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
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
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
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
144
|
+
# Ensure that this always behaves like a NilClass
|
145
|
+
# @return [TrueClass]
|
146
|
+
def nil?
|
147
|
+
true
|
148
|
+
end
|
149
149
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
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
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
@@ -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.
|
95
|
+
return predicate_name if existing_predicates.blank?
|
96
96
|
existing_predicates.first
|
97
97
|
end
|
98
98
|
end
|