dor-services 6.0.5 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dor-services.rb +27 -12
- data/lib/dor/config.rb +45 -42
- data/lib/dor/datastreams/administrative_metadata_ds.rb +137 -44
- data/lib/dor/datastreams/content_metadata_ds.rb +42 -42
- data/lib/dor/datastreams/datastream_spec_solrizer.rb +1 -1
- data/lib/dor/datastreams/default_object_rights_ds.rb +185 -44
- data/lib/dor/datastreams/desc_metadata_ds.rb +36 -28
- data/lib/dor/datastreams/embargo_metadata_ds.rb +12 -14
- data/lib/dor/datastreams/events_ds.rb +10 -10
- data/lib/dor/datastreams/geo_metadata_ds.rb +4 -5
- data/lib/dor/datastreams/identity_metadata_ds.rb +14 -14
- data/lib/dor/datastreams/rights_metadata_ds.rb +23 -23
- data/lib/dor/datastreams/role_metadata_ds.rb +61 -15
- data/lib/dor/datastreams/simple_dublin_core_ds.rb +8 -8
- data/lib/dor/datastreams/version_metadata_ds.rb +10 -12
- data/lib/dor/datastreams/workflow_definition_ds.rb +6 -6
- data/lib/dor/datastreams/workflow_ds.rb +13 -13
- data/lib/dor/exceptions.rb +2 -2
- data/lib/dor/indexers/data_indexer.rb +1 -7
- data/lib/dor/indexers/describable_indexer.rb +1 -1
- data/lib/dor/indexers/identifiable_indexer.rb +0 -2
- data/lib/dor/indexers/processable_indexer.rb +55 -28
- data/lib/dor/indexers/releasable_indexer.rb +2 -2
- data/lib/dor/models/admin_policy_object.rb +4 -4
- data/lib/dor/models/concerns/assembleable.rb +4 -0
- data/lib/dor/models/concerns/contentable.rb +27 -69
- data/lib/dor/models/concerns/describable.rb +14 -29
- data/lib/dor/models/concerns/editable.rb +20 -334
- data/lib/dor/models/concerns/embargoable.rb +7 -11
- data/lib/dor/models/concerns/eventable.rb +5 -1
- data/lib/dor/models/concerns/geoable.rb +4 -4
- data/lib/dor/models/concerns/governable.rb +18 -87
- data/lib/dor/models/concerns/identifiable.rb +15 -75
- data/lib/dor/models/concerns/itemizable.rb +9 -11
- data/lib/dor/models/concerns/preservable.rb +4 -0
- data/lib/dor/models/concerns/processable.rb +30 -129
- data/lib/dor/models/concerns/publishable.rb +6 -55
- data/lib/dor/models/concerns/releaseable.rb +14 -227
- data/lib/dor/models/concerns/rightsable.rb +3 -3
- data/lib/dor/models/concerns/shelvable.rb +4 -49
- data/lib/dor/models/concerns/versionable.rb +21 -44
- data/lib/dor/models/set.rb +1 -1
- data/lib/dor/models/workflow_object.rb +2 -2
- data/lib/dor/services/ability.rb +77 -0
- data/lib/dor/services/cleanup_reset_service.rb +1 -3
- data/lib/dor/services/create_workflow_service.rb +51 -0
- data/lib/dor/services/creative_commons_license_service.rb +31 -0
- data/lib/dor/services/datastream_builder.rb +90 -0
- data/lib/dor/services/digital_stacks_service.rb +3 -21
- data/lib/dor/services/dublin_core_service.rb +40 -0
- data/lib/dor/services/file_metadata_merge_service.rb +67 -0
- data/lib/dor/services/indexing_service.rb +8 -4
- data/lib/dor/services/merge_service.rb +5 -5
- data/lib/dor/services/metadata_handlers/catalog_handler.rb +1 -1
- data/lib/dor/services/metadata_service.rb +6 -8
- data/lib/dor/{models/concerns → services}/mods2dc.xslt +0 -0
- data/lib/dor/services/ontology.rb +35 -0
- data/lib/dor/services/open_data_license_service.rb +20 -0
- data/lib/dor/services/public_desc_metadata_service.rb +21 -14
- data/lib/dor/services/public_xml_service.rb +6 -6
- data/lib/dor/services/publish_metadata_service.rb +100 -0
- data/lib/dor/services/registration_service.rb +43 -46
- data/lib/dor/services/release_tag_service.rb +251 -0
- data/lib/dor/services/reset_workspace_service.rb +1 -3
- data/lib/dor/services/sdr_ingest_service.rb +5 -7
- data/lib/dor/services/search_service.rb +10 -10
- data/lib/dor/services/secondary_file_name_service.rb +10 -0
- data/lib/dor/services/shelving_service.rb +67 -0
- data/lib/dor/services/status_service.rb +121 -0
- data/lib/dor/services/suri_service.rb +3 -5
- data/lib/dor/services/tag_service.rb +100 -0
- data/lib/dor/services/technical_metadata_service.rb +5 -4
- data/lib/dor/services/version_service.rb +84 -0
- data/lib/dor/utils/ng_tidy.rb +1 -1
- data/lib/dor/utils/sdr_client.rb +25 -9
- data/lib/dor/version.rb +1 -1
- data/lib/dor/workflow/document.rb +13 -13
- data/lib/dor/workflow/process.rb +71 -26
- data/lib/tasks/rdoc.rake +1 -1
- metadata +77 -51
- data/config/certs/robots-dor-dev.crt +0 -29
- data/config/certs/robots-dor-dev.key +0 -27
- data/config/dev_console_env.rb +0 -80
@@ -44,7 +44,7 @@ module Dor
|
|
44
44
|
def public_relationships
|
45
45
|
include_elements = ['fedora:isMemberOf', 'fedora:isMemberOfCollection', 'fedora:isConstituentOf']
|
46
46
|
rels_doc = Nokogiri::XML(datastreams['RELS-EXT'].content)
|
47
|
-
rels_doc.xpath('/rdf:RDF/rdf:Description/*',
|
47
|
+
rels_doc.xpath('/rdf:RDF/rdf:Description/*', 'rdf' => 'http://www.w3.org/1999/02/22-rdf-syntax-ns#').each do |rel|
|
48
48
|
unless include_elements.include?([rel.namespace.prefix, rel.name].join(':'))
|
49
49
|
rel.next_sibling.remove if rel.next_sibling.content.strip.empty?
|
50
50
|
rel.remove
|
@@ -58,68 +58,19 @@ module Dor
|
|
58
58
|
def public_xml
|
59
59
|
PublicXmlService.new(self).to_xml
|
60
60
|
end
|
61
|
+
deprecation_deprecate public_xml: 'Use PublicXmlService#to_xml instead'
|
61
62
|
|
62
63
|
# Copies this object's public_xml to the Purl document cache if it is world discoverable
|
63
64
|
# otherwise, it prunes the object's metadata from the document cache
|
64
65
|
def publish_metadata
|
65
|
-
|
66
|
-
if rights.at_xpath("//rightsMetadata/access[@type='discover']/machine/world")
|
67
|
-
dc_xml = generate_dublin_core.to_xml { |config| config.no_declaration }
|
68
|
-
DigitalStacksService.transfer_to_document_store(pid, dc_xml, 'dc')
|
69
|
-
%w(identityMetadata contentMetadata rightsMetadata).each do |stream|
|
70
|
-
DigitalStacksService.transfer_to_document_store(pid, datastreams[stream].content.to_s, stream) if datastreams[stream]
|
71
|
-
end
|
72
|
-
DigitalStacksService.transfer_to_document_store(pid, public_xml, 'public')
|
73
|
-
DigitalStacksService.transfer_to_document_store(pid, generate_public_desc_md, 'mods')
|
74
|
-
publish_notify_on_success
|
75
|
-
else
|
76
|
-
# Clear out the document cache for this item
|
77
|
-
DigitalStacksService.prune_purl_dir pid
|
78
|
-
publish_delete_on_success
|
79
|
-
end
|
66
|
+
PublishMetadataService.publish(self)
|
80
67
|
end
|
68
|
+
deprecation_deprecate publish_metadata: 'use Dor::PublishMetadataService.publish(obj) instead or use publish_metadata_remotely'
|
81
69
|
|
82
70
|
# Call dor services app to have it publish the metadata
|
83
71
|
def publish_metadata_remotely
|
84
|
-
|
85
|
-
endpoint = dor_services["v1/objects/#{pid}/publish"]
|
86
|
-
endpoint.post ''
|
87
|
-
endpoint.url
|
88
|
-
end
|
89
|
-
|
90
|
-
##
|
91
|
-
# When publishing a PURL, we notify purl-fetcher of changes.
|
92
|
-
# If the purl service isn't configured, instead we drop a `aa11bb2222` file into the `local_recent_changes` folder
|
93
|
-
# to notify other applications watching the filesystem (i.e., purl-fetcher).
|
94
|
-
# We also remove any .deletes entry that may have left over from a previous removal
|
95
|
-
def publish_notify_on_success
|
96
|
-
id = pid.gsub(/^druid:/, '')
|
97
|
-
|
98
|
-
if Dor::Config.purl_services.url
|
99
|
-
purl_services = Dor::Config.purl_services.rest_client
|
100
|
-
purl_services["purls/#{id}"].post ''
|
101
|
-
else
|
102
|
-
local_recent_changes = Config.stacks.local_recent_changes
|
103
|
-
raise ArgumentError, "Missing local_recent_changes directory: #{local_recent_changes}" unless File.directory?(local_recent_changes)
|
104
|
-
|
105
|
-
FileUtils.touch(File.join(local_recent_changes, id))
|
106
|
-
begin
|
107
|
-
DruidTools::Druid.new(id, Dor::Config.stacks.local_document_cache_root).deletes_delete_record
|
108
|
-
rescue Errno::EACCES
|
109
|
-
Dor.logger.warn "Access denied while trying to remove .deletes file for druid:#{id}"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
##
|
115
|
-
# When publishing a PURL, we notify purl-fetcher of changes.
|
116
|
-
def publish_delete_on_success
|
117
|
-
return unless Dor::Config.purl_services.url
|
118
|
-
|
119
|
-
id = pid.gsub(/^druid:/, '')
|
120
|
-
|
121
|
-
purl_services = Dor::Config.purl_services.rest_client
|
122
|
-
purl_services["purls/#{id}"].delete
|
72
|
+
Dor::Services::Client.publish(object: pid)
|
123
73
|
end
|
74
|
+
deprecation_deprecate publish_metadata_remotely: 'use Dor::Services::Client.publish instead'
|
124
75
|
end
|
125
76
|
end
|
@@ -6,6 +6,8 @@ require 'retries'
|
|
6
6
|
module Dor
|
7
7
|
module Releaseable
|
8
8
|
extend ActiveSupport::Concern
|
9
|
+
extend Deprecation
|
10
|
+
self.deprecation_horizon = 'dor-services version 7.0.0'
|
9
11
|
|
10
12
|
# Add release tags to an item and initialize the item release workflow
|
11
13
|
# Each tag should be of the form !{:tag => 'Fitch : Batch2', :what => 'self', :to => 'Searchworks', :who => 'petucket', :release => true}
|
@@ -23,166 +25,18 @@ module Dor
|
|
23
25
|
save
|
24
26
|
create_workflow('releaseWF')
|
25
27
|
end
|
28
|
+
deprecation_deprecate add_release_nodes_and_start_releaseWF: 'No longer used by any DLSS code'
|
26
29
|
|
30
|
+
# Called in Dor::UpdateMarcRecordService (in dor-services-app too)
|
27
31
|
# Determine projects in which an item is released
|
28
32
|
# @param [Boolean] skip_live_purl set true to skip requesting from purl backend
|
29
33
|
# @return [Hash{String => Boolean}] all namespaces, keys are Project name Strings, values are Boolean
|
30
34
|
def released_for(skip_live_purl = false)
|
31
|
-
|
32
|
-
|
33
|
-
# Get the most recent self tag for all targets and retain their result since most recent self always trumps any other non self tags
|
34
|
-
latest_self_tags = get_newest_release_tag get_self_release_tags(release_nodes)
|
35
|
-
latest_self_tags.each do |key, payload|
|
36
|
-
released_hash[key] = { 'release' => payload['release'] }
|
37
|
-
end
|
38
|
-
|
39
|
-
# With Self Tags resolved we now need to deal with tags on all sets this object is part of.
|
40
|
-
# Get all release tags on the item and strip out the what = self ones, we've already processed all the self tags on this item.
|
41
|
-
# This will be where we store all tags that apply, regardless of their timestamp:
|
42
|
-
potential_applicable_release_tags = get_tags_for_what_value(get_release_tags_for_item_and_all_governing_sets, 'collection')
|
43
|
-
administrative_tags = tags # Get admin tags once here and pass them down
|
44
|
-
|
45
|
-
# We now have the keys for all potential releases, we need to check the tags: the most recent timestamp with an explicit true or false wins.
|
46
|
-
# In a nil case, the lack of an explicit false tag we do nothing.
|
47
|
-
(potential_applicable_release_tags.keys - released_hash.keys).each do |key| # don't bother checking if already added to the release hash, they were added due to a self tag so that has won
|
48
|
-
latest_tag = latest_applicable_release_tag_in_array(potential_applicable_release_tags[key], administrative_tags)
|
49
|
-
next if latest_tag.nil? # Otherwise, we have a valid tag, record it
|
50
|
-
|
51
|
-
released_hash[key] = { 'release' => latest_tag['release'] }
|
52
|
-
end
|
53
|
-
|
54
|
-
# See what the application is currently released for on Purl. If released in purl but not listed here, it needs to be added as a false
|
55
|
-
add_tags_from_purl(released_hash) unless skip_live_purl
|
56
|
-
released_hash
|
57
|
-
end
|
58
|
-
|
59
|
-
# Take a hash of tags as obtained via Dor::Item.release_tags and returns all self tags
|
60
|
-
# @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
61
|
-
# @return [Hash] a hash of self tags for each to value
|
62
|
-
def get_self_release_tags(tags)
|
63
|
-
get_tags_for_what_value(tags, 'self')
|
64
|
-
end
|
65
|
-
|
66
|
-
# Take an item and get all of its release tags and all tags on collections it is a member of it
|
67
|
-
# @return [Hash] a hash of all tags
|
68
|
-
def get_release_tags_for_item_and_all_governing_sets
|
69
|
-
return_tags = release_nodes || {}
|
70
|
-
collections.each do |collection|
|
71
|
-
next if collection.id == id # recursive, so parents of parents are found, but we need to avoid an infinite loop if the collection references itself (i.e. bad data)
|
72
|
-
|
73
|
-
return_tags = combine_two_release_tag_hashes(return_tags, collection.get_release_tags_for_item_and_all_governing_sets)
|
74
|
-
end
|
75
|
-
return_tags
|
76
|
-
end
|
77
|
-
|
78
|
-
# Take two hashes of tags and combine them, will not overwrite but will enforce uniqueness of the tags
|
79
|
-
# @param hash_one [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
80
|
-
# @param hash_two [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
81
|
-
# @return [Hash] the combined hash with uniquiness enforced
|
82
|
-
def combine_two_release_tag_hashes(hash_one, hash_two)
|
83
|
-
hash_two.keys.each do |key|
|
84
|
-
hash_one[key] = hash_two[key] if hash_one[key].nil?
|
85
|
-
hash_one[key] = (hash_one[key] + hash_two[key]).uniq unless hash_one[key].nil?
|
86
|
-
end
|
87
|
-
hash_one
|
88
|
-
end
|
89
|
-
|
90
|
-
# Take a hash of tags and return all tags with the matching what target
|
91
|
-
# @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
92
|
-
# @param what_target [String] the target for the 'what' key, self or collection
|
93
|
-
# @return [Hash] a hash of self tags for each to value
|
94
|
-
def get_tags_for_what_value(tags, what_target)
|
95
|
-
return_hash = {}
|
96
|
-
tags.keys.each do |key|
|
97
|
-
self_tags = tags[key].select { |tag| tag['what'].casecmp(what_target) == 0 }
|
98
|
-
return_hash[key] = self_tags if self_tags.size > 0
|
99
|
-
end
|
100
|
-
return_hash
|
101
|
-
end
|
102
|
-
|
103
|
-
# Take a hash of tags as obtained via Dor::Item.release_tags and returns the newest tag for each namespace
|
104
|
-
# @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
105
|
-
# @return [Hash] a hash of latest tags for each to value
|
106
|
-
def get_newest_release_tag(tags)
|
107
|
-
Hash[tags.map { |key, val| [key, newest_release_tag_in_an_array(val)] }]
|
35
|
+
releases.released_for(skip_live_purl: skip_live_purl)
|
108
36
|
end
|
109
37
|
|
110
|
-
|
111
|
-
|
112
|
-
# @return [Hash] the most recent tag
|
113
|
-
def newest_release_tag_in_an_array(array_of_tags)
|
114
|
-
latest_tag_in_array = array_of_tags[0] || {}
|
115
|
-
array_of_tags.each do |tag|
|
116
|
-
latest_tag_in_array = tag if tag['when'] > latest_tag_in_array['when']
|
117
|
-
end
|
118
|
-
latest_tag_in_array
|
119
|
-
end
|
120
|
-
|
121
|
-
# Takes a tag and returns true or false if it applies to the specific item
|
122
|
-
# @param release_tag [Hash] the tag in a hashed form
|
123
|
-
# @param admin_tags [Array] the administrative tags on an item, if not supplied it will attempt to retrieve them
|
124
|
-
# @return [Boolean] true or false if it applies (not true or false if it is released, that is the release_tag data)
|
125
|
-
def does_release_tag_apply(release_tag, admin_tags = false)
|
126
|
-
# Is the tag global or restricted
|
127
|
-
return true if release_tag['tag'].nil? # no specific tag specificied means this tag is global to all members of the collection
|
128
|
-
|
129
|
-
admin_tags = tags unless admin_tags # We use false instead of [], since an item can have no admin_tags at which point we'd be passing this var as [] and would not attempt to retrieve it
|
130
|
-
admin_tags.include?(release_tag['tag'])
|
131
|
-
end
|
132
|
-
|
133
|
-
# Takes an array of release tags and returns the most recent one that applies to this item
|
134
|
-
# @param release_tags [Array] an array of release tags in hashed form
|
135
|
-
# @param admin_tags [Array] the administrative tags on an on item
|
136
|
-
# @return [Hash] the tag, or nil if none applicable
|
137
|
-
def latest_applicable_release_tag_in_array(release_tags, admin_tags)
|
138
|
-
newest_tag = newest_release_tag_in_an_array(release_tags)
|
139
|
-
return newest_tag if does_release_tag_apply(newest_tag, admin_tags)
|
140
|
-
|
141
|
-
# The latest tag wasn't applicable, slice it off and try again
|
142
|
-
# This could be optimized by reordering on the timestamp and just running down it instead of constantly resorting, at least if we end up getting numerous release tags on an item
|
143
|
-
release_tags.slice!(release_tags.index(newest_tag))
|
144
|
-
|
145
|
-
return latest_applicable_release_tag_in_array(release_tags, admin_tags) if release_tags.size > 0 # Try again after dropping the inapplicable
|
146
|
-
|
147
|
-
nil # We're out of tags, no applicable ones
|
148
|
-
end
|
149
|
-
|
150
|
-
# Helper method to get the release tags as a nodeset
|
151
|
-
# @return [Nokogiri::XML::NodeSet] all release tags and their attributes
|
152
|
-
def release_tags
|
153
|
-
release_tags = identityMetadata.ng_xml.xpath('//release')
|
154
|
-
return_hash = {}
|
155
|
-
release_tags.each do |release_tag|
|
156
|
-
hashed_node = release_tag_node_to_hash(release_tag)
|
157
|
-
if !return_hash[hashed_node[:to]].nil?
|
158
|
-
return_hash[hashed_node[:to]] << hashed_node[:attrs]
|
159
|
-
else
|
160
|
-
return_hash[hashed_node[:to]] = [hashed_node[:attrs]]
|
161
|
-
end
|
162
|
-
end
|
163
|
-
return_hash
|
164
|
-
end
|
165
|
-
|
166
|
-
# Convert one release element into a Hash
|
167
|
-
# @param rtag [Nokogiri::XML::Element] the release tag element
|
168
|
-
# @return [Hash{:to, :attrs => String, Hash}] in the form of !{:to => String :attrs = Hash}
|
169
|
-
def release_tag_node_to_hash(rtag)
|
170
|
-
to = 'to'
|
171
|
-
release = 'release'
|
172
|
-
when_word = 'when' # TODO: Make to and when_word load from some config file instead of hardcoded here
|
173
|
-
attrs = rtag.attributes
|
174
|
-
return_hash = { :to => attrs[to].value }
|
175
|
-
attrs.tap { |a| a.delete(to) }
|
176
|
-
attrs[release] = rtag.text.casecmp('true') == 0 # save release as a boolean
|
177
|
-
return_hash[:attrs] = attrs
|
178
|
-
|
179
|
-
# convert all the attrs beside :to to strings, they are currently Nokogiri::XML::Attr
|
180
|
-
(return_hash[:attrs].keys - [to]).each do |a|
|
181
|
-
return_hash[:attrs][a] = return_hash[:attrs][a].to_s if a != release
|
182
|
-
end
|
183
|
-
|
184
|
-
return_hash[:attrs][when_word] = Time.parse(return_hash[:attrs][when_word]) # convert when to a datetime
|
185
|
-
return_hash
|
38
|
+
def releases
|
39
|
+
@releases ||= ReleaseTagService.for(self)
|
186
40
|
end
|
187
41
|
|
188
42
|
# Determine if the supplied tag is a valid release tag that meets all requirements
|
@@ -193,7 +47,7 @@ module Dor
|
|
193
47
|
def valid_release_attributes_and_tag(tag, attrs = {})
|
194
48
|
raise ArgumentError, ':when is not iso8601' if attrs[:when].match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z').nil?
|
195
49
|
|
196
|
-
[
|
50
|
+
%i[who to what].each do |check_attr|
|
197
51
|
raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String
|
198
52
|
end
|
199
53
|
|
@@ -206,6 +60,7 @@ module Dor
|
|
206
60
|
|
207
61
|
true
|
208
62
|
end
|
63
|
+
deprecation_deprecate valid_release_attributes_and_tag: 'No longer used by any DLSS code'
|
209
64
|
|
210
65
|
# Add a release node for the item
|
211
66
|
# Will use the current time if timestamp not supplied. You can supply a timestap for correcting history, etc if desired
|
@@ -219,13 +74,14 @@ module Dor
|
|
219
74
|
# @example
|
220
75
|
# item.add_release_node(true,{:what=>'self',:to=>'Searchworks',:who=>'petucket'})
|
221
76
|
def add_release_node(release, attrs = {})
|
222
|
-
allowed_release_attributes = [
|
77
|
+
allowed_release_attributes = %i[what to who when] # any other release attributes sent in will be rejected and not stored
|
223
78
|
identity_metadata_ds = identityMetadata
|
224
|
-
attrs.delete_if { |key,
|
79
|
+
attrs.delete_if { |key, _value| !allowed_release_attributes.include?(key) }
|
225
80
|
attrs[:when] = Time.now.utc.iso8601 if attrs[:when].nil? # add the timestamp
|
226
81
|
valid_release_attributes(release, attrs)
|
227
82
|
identity_metadata_ds.add_value(:release, release.to_s, attrs)
|
228
83
|
end
|
84
|
+
deprecation_deprecate add_release_node: 'No longer used by any DLSS code'
|
229
85
|
|
230
86
|
# Determine if the supplied tag is a valid release node that meets all requirements
|
231
87
|
#
|
@@ -236,7 +92,7 @@ module Dor
|
|
236
92
|
def valid_release_attributes(tag, attrs = {})
|
237
93
|
raise ArgumentError, ':when is not iso8601' if attrs[:when].match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z').nil?
|
238
94
|
|
239
|
-
[
|
95
|
+
%i[who to what].each do |check_attr|
|
240
96
|
raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String
|
241
97
|
end
|
242
98
|
raise ArgumentError, ':what must be self or collection' unless %w(self collection).include? attrs[:what]
|
@@ -244,75 +100,6 @@ module Dor
|
|
244
100
|
|
245
101
|
true
|
246
102
|
end
|
247
|
-
|
248
|
-
# Helper method to get the release nodes as a nodeset
|
249
|
-
# @return [Nokogiri::XML::NodeSet] of all release tags and their attributes
|
250
|
-
def release_nodes
|
251
|
-
release_tags = identityMetadata.ng_xml.xpath('//release')
|
252
|
-
return_hash = {}
|
253
|
-
release_tags.each do |release_tag|
|
254
|
-
hashed_node = release_tag_node_to_hash(release_tag)
|
255
|
-
if !return_hash[hashed_node[:to]].nil?
|
256
|
-
return_hash[hashed_node[:to]] << hashed_node[:attrs]
|
257
|
-
else
|
258
|
-
return_hash[hashed_node[:to]] = [hashed_node[:attrs]]
|
259
|
-
end
|
260
|
-
end
|
261
|
-
return_hash
|
262
|
-
end
|
263
|
-
|
264
|
-
# Get a list of all release nodes found in a purl document
|
265
|
-
# Fetches purl xml for a druid
|
266
|
-
# @raise [OpenURI::HTTPError]
|
267
|
-
# @return [Nokogiri::HTML::Document] parsed XML for the druid or an empty document if no purl is found
|
268
|
-
def get_xml_from_purl
|
269
|
-
url = form_purl_url
|
270
|
-
handler = proc do |exception, attempt_number, total_delay|
|
271
|
-
# We assume a 404 means the document has never been published before and thus has no purl
|
272
|
-
Dor.logger.warn "[Attempt #{attempt_number}] GET #{url} -- #{exception.class}: #{exception.message}; #{total_delay} seconds elapsed."
|
273
|
-
raise exception unless exception.is_a? OpenURI::HTTPError
|
274
|
-
return Nokogiri::HTML::Document.new if exception.io.status.first == '404' # ["404", "Not Found"] from OpenURI::Meta.status
|
275
|
-
end
|
276
|
-
|
277
|
-
with_retries(:max_retries => 3, :base_sleep_seconds => 3, :max_sleep_seconds => 5, :handler => handler) do |attempt|
|
278
|
-
# If you change the method used for opening the webpage, you can change the :rescue param to handle the new method's errors
|
279
|
-
Dor.logger.info "[Attempt #{attempt}] GET #{url}"
|
280
|
-
return Nokogiri::HTML(OpenURI.open_uri(url))
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
|
-
# Take the and create the entire purl url that will usable for the open method in open-uri, returns http
|
285
|
-
# @return [String] the full url
|
286
|
-
def form_purl_url
|
287
|
-
'https://' + Dor::Config.stacks.document_cache_host + "/#{remove_druid_prefix}.xml"
|
288
|
-
end
|
289
|
-
|
290
|
-
# Pull all release nodes from the public xml obtained via the purl query
|
291
|
-
# @param doc [Nokogiri::HTML::Document] The druid of the object you want
|
292
|
-
# @return [Array] An array containing all the release tags
|
293
|
-
def get_release_tags_from_purl_xml(doc)
|
294
|
-
nodes = doc.xpath('//html/body/publicobject/releasedata').children
|
295
|
-
# We only want the nodes with a name that isn't text
|
296
|
-
nodes.reject { |n| n.name.nil? || n.name.casecmp('text') == 0 }.map { |n| n.attr('to') }.uniq
|
297
|
-
end
|
298
|
-
|
299
|
-
# Pull all release nodes from the public xml obtained via the purl query
|
300
|
-
# @return [Array] An array containing all the release tags
|
301
|
-
def get_release_tags_from_purl
|
302
|
-
get_release_tags_from_purl_xml(get_xml_from_purl)
|
303
|
-
end
|
304
|
-
|
305
|
-
# This function calls purl and gets a list of all release tags currently in purl. It then compares to the list you have generated.
|
306
|
-
# Any tag that is on purl, but not in the newly generated list is added to the new list with a value of false.
|
307
|
-
# @param new_tags [Hash{String => Boolean}] all new tags in the form of !{"Project" => Boolean}
|
308
|
-
# @return [Hash] same form as new_tags, with all missing tags not in new_tags, but in current_tag_names, added in with a Boolean value of false
|
309
|
-
def add_tags_from_purl(new_tags)
|
310
|
-
tags_currently_in_purl = get_release_tags_from_purl
|
311
|
-
missing_tags = tags_currently_in_purl.map(&:downcase) - new_tags.keys.map(&:downcase)
|
312
|
-
missing_tags.each do |missing_tag|
|
313
|
-
new_tags[missing_tag.capitalize] = { 'release' => false }
|
314
|
-
end
|
315
|
-
new_tags
|
316
|
-
end
|
103
|
+
deprecation_deprecate valid_release_attributes: 'No longer used by any DLSS code'
|
317
104
|
end
|
318
105
|
end
|
@@ -5,7 +5,7 @@ module Dor
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
has_metadata :
|
8
|
+
has_metadata name: 'rightsMetadata', type: Dor::RightsMetadataDS, label: 'Rights metadata'
|
9
9
|
end
|
10
10
|
|
11
11
|
def build_rightsMetadata_datastream(ds)
|
@@ -16,9 +16,9 @@ module Dor
|
|
16
16
|
|
17
17
|
def world_doc
|
18
18
|
Nokogiri::XML::Builder.new do |xml|
|
19
|
-
xml.access(:
|
19
|
+
xml.access(type: 'read') do
|
20
20
|
xml.machine { xml.world }
|
21
|
-
|
21
|
+
end
|
22
22
|
end.doc
|
23
23
|
end
|
24
24
|
end
|
@@ -1,60 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'moab/stanford'
|
4
|
-
|
5
3
|
module Dor
|
6
4
|
module Shelvable
|
5
|
+
extend Deprecation
|
7
6
|
extend ActiveSupport::Concern
|
7
|
+
self.deprecation_horizon = 'dor-services version 7.0.0'
|
8
8
|
|
9
9
|
# Push file changes for shelve-able files into the stacks
|
10
10
|
def shelve
|
11
|
-
|
12
|
-
shelve_diff = get_shelve_diff
|
13
|
-
stacks_object_pathname = get_stacks_location
|
14
|
-
# determine the location of the object's files in the stacks area
|
15
|
-
stacks_druid = DruidTools::StacksDruid.new id, stacks_object_pathname
|
16
|
-
stacks_object_pathname = Pathname(stacks_druid.path)
|
17
|
-
# determine the location of the object's content files in the workspace area
|
18
|
-
workspace_druid = DruidTools::Druid.new(id, Config.stacks.local_workspace_root)
|
19
|
-
workspace_content_pathname = workspace_content_dir(shelve_diff, workspace_druid)
|
20
|
-
# delete, rename, or copy files to the stacks area
|
21
|
-
DigitalStacksService.remove_from_stacks(stacks_object_pathname, shelve_diff)
|
22
|
-
DigitalStacksService.rename_in_stacks(stacks_object_pathname, shelve_diff)
|
23
|
-
DigitalStacksService.shelve_to_stacks(workspace_content_pathname, stacks_object_pathname, shelve_diff)
|
24
|
-
end
|
25
|
-
|
26
|
-
# retrieve the differences between the current contentMetadata and the previously ingested version
|
27
|
-
# (filtering to select only the files that should be shelved to stacks)
|
28
|
-
def get_shelve_diff
|
29
|
-
inventory_diff = get_content_diff(:shelve)
|
30
|
-
shelve_diff = inventory_diff.group_difference('content')
|
31
|
-
shelve_diff
|
32
|
-
end
|
33
|
-
|
34
|
-
# Find the location of the object's content files in the workspace area
|
35
|
-
# @param [Moab::FileGroupDifference] content_diff The differences between the current contentMetadata and the previously ingested version
|
36
|
-
# @param [DruidTools::Druid] workspace_druid the location of the object's files in the workspace area
|
37
|
-
# @return [Pathname] The location of the object's content files in the workspace area
|
38
|
-
def workspace_content_dir(content_diff, workspace_druid)
|
39
|
-
deltas = content_diff.file_deltas
|
40
|
-
filelist = deltas[:modified] + deltas[:added] + deltas[:copyadded].collect { |old, new| new }
|
41
|
-
return nil if filelist.empty?
|
42
|
-
|
43
|
-
content_pathname = Pathname(workspace_druid.find_filelist_parent('content', filelist))
|
44
|
-
content_pathname
|
45
|
-
end
|
46
|
-
|
47
|
-
# get the stack location based on the contentMetadata stacks attribute
|
48
|
-
# or using the default value from the config file if it doesn't exist
|
49
|
-
def get_stacks_location
|
50
|
-
contentMetadataDS = datastreams['contentMetadata']
|
51
|
-
unless contentMetadataDS.nil? || contentMetadataDS.stacks.length == 0
|
52
|
-
stacks_location = contentMetadataDS.stacks[0]
|
53
|
-
return stacks_location if stacks_location.start_with? '/' # Absolute stacks path
|
54
|
-
|
55
|
-
raise 'stacks attribute for item: ' + id + ' contentMetadata should start with /. The current value is ' + stacks_location
|
56
|
-
end
|
57
|
-
Config.stacks.local_stacks_root # Default stacks
|
11
|
+
ShelvingService.shelve(self)
|
58
12
|
end
|
13
|
+
deprecation_deprecate shelve: 'Use ShelvingService.shelve(work) instead'
|
59
14
|
end
|
60
15
|
end
|