dor-services 5.1.1 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/dor-services.rb +1 -2
- data/lib/dor/config.rb +5 -6
- data/lib/dor/datastreams/content_metadata_ds.rb +17 -20
- data/lib/dor/datastreams/datastream_spec_solrizer.rb +1 -1
- data/lib/dor/datastreams/desc_metadata_ds.rb +7 -7
- data/lib/dor/datastreams/embargo_metadata_ds.rb +2 -7
- data/lib/dor/datastreams/events_ds.rb +9 -9
- data/lib/dor/datastreams/identity_metadata_ds.rb +29 -34
- data/lib/dor/datastreams/rights_metadata_ds.rb +1 -1
- data/lib/dor/datastreams/role_metadata_ds.rb +0 -1
- data/lib/dor/datastreams/simple_dublin_core_ds.rb +12 -13
- data/lib/dor/datastreams/version_metadata_ds.rb +11 -15
- data/lib/dor/datastreams/workflow_definition_ds.rb +18 -22
- data/lib/dor/datastreams/workflow_ds.rb +24 -36
- data/lib/dor/migrations/identifiable/assert_adminPolicy.rb +1 -1
- data/lib/dor/migrations/identifiable/fix_model_assertions.rb +1 -1
- data/lib/dor/migrations/identifiable/record_remediation.rb +2 -2
- data/lib/dor/migrations/identifiable/uriify_augmented_contentlocation_refs.rb +1 -1
- data/lib/dor/migrations/identifiable/uriify_contentlocation_refs.rb +1 -1
- data/lib/dor/migrations/processable/unify_workflows.rb +4 -4
- data/lib/dor/migrations/versionable/add_missing_version_md.rb +2 -2
- data/lib/dor/models/assembleable.rb +2 -2
- data/lib/dor/models/collection.rb +1 -0
- data/lib/dor/models/contentable.rb +3 -3
- data/lib/dor/models/describable.rb +16 -13
- data/lib/dor/models/editable.rb +3 -3
- data/lib/dor/models/embargoable.rb +2 -2
- data/lib/dor/models/eventable.rb +2 -2
- data/lib/dor/models/geoable.rb +14 -18
- data/lib/dor/models/governable.rb +1 -1
- data/lib/dor/models/identifiable.rb +36 -57
- data/lib/dor/models/itemizable.rb +6 -6
- data/lib/dor/models/presentable.rb +12 -12
- data/lib/dor/models/preservable.rb +2 -5
- data/lib/dor/models/processable.rb +19 -25
- data/lib/dor/models/publishable.rb +2 -2
- data/lib/dor/models/releaseable.rb +165 -212
- data/lib/dor/models/shelvable.rb +10 -14
- data/lib/dor/models/upgradable.rb +11 -11
- data/lib/dor/models/versionable.rb +16 -21
- data/lib/dor/models/workflow_object.rb +3 -3
- data/lib/dor/services/cleanup_reset_service.rb +32 -27
- data/lib/dor/services/digital_stacks_service.rb +3 -3
- data/lib/dor/services/merge_service.rb +4 -8
- data/lib/dor/services/metadata_handlers/catalog_handler.rb +1 -1
- data/lib/dor/services/metadata_handlers/mdtoolkit_handler.rb +4 -6
- data/lib/dor/services/metadata_service.rb +20 -22
- data/lib/dor/services/registration_service.rb +6 -8
- data/lib/dor/services/reset_workspace_service.rb +14 -16
- data/lib/dor/services/sdr_ingest_service.rb +2 -6
- data/lib/dor/services/search_service.rb +3 -3
- data/lib/dor/services/suri_service.rb +2 -3
- data/lib/dor/services/technical_metadata_service.rb +2 -3
- data/lib/dor/utils/ng_tidy.rb +6 -6
- data/lib/dor/utils/predicate_patch.rb +1 -1
- data/lib/dor/utils/solr_doc_helper.rb +2 -2
- data/lib/dor/version.rb +1 -1
- data/lib/dor/workflow/document.rb +27 -33
- data/lib/dor/workflow/graph.rb +34 -37
- data/lib/dor/workflow/process.rb +8 -8
- data/lib/tasks/rdoc.rake +5 -5
- metadata +4 -11
- data/bin/dor-indexer +0 -108
- data/bin/dor-indexerd +0 -73
- 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 -78
@@ -33,7 +33,7 @@ module Dor
|
|
33
33
|
|
34
34
|
im=self.datastreams['identityMetadata'].ng_xml.clone
|
35
35
|
im.search('//release').each {|node| node.remove} # remove any <release> tags from public xml which have full history
|
36
|
-
im.root.add_child(release_xml)
|
36
|
+
im.root.add_child(release_xml)
|
37
37
|
|
38
38
|
pub.add_child(im.root) # add in modified identityMetadata datastream
|
39
39
|
pub.add_child(self.datastreams['contentMetadata'].public_xml.root.clone)
|
@@ -54,7 +54,7 @@ module Dor
|
|
54
54
|
# otherwise, it prunes the object's metadata from the document cache
|
55
55
|
def publish_metadata
|
56
56
|
rights = datastreams['rightsMetadata'].ng_xml.clone.remove_namespaces!
|
57
|
-
if
|
57
|
+
if rights.at_xpath("//rightsMetadata/access[@type='discover']/machine/world")
|
58
58
|
dc_xml = self.generate_dublin_core.to_xml {|config| config.no_declaration}
|
59
59
|
DigitalStacksService.transfer_to_document_store(pid, dc_xml, 'dc')
|
60
60
|
DigitalStacksService.transfer_to_document_store(pid, self.datastreams['identityMetadata'].to_xml, 'identityMetadata')
|
@@ -5,126 +5,113 @@ module Dor
|
|
5
5
|
module Releaseable
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
include Itemizable
|
8
|
-
|
9
|
-
#Add release tags to an item and initialize the item release workflow
|
10
|
-
#
|
11
|
-
|
12
|
-
#
|
13
|
-
#@raise [ArgumentError] Raised if the tags are improperly supplied
|
14
|
-
#
|
15
|
-
#
|
8
|
+
|
9
|
+
# Add release tags to an item and initialize the item release workflow
|
10
|
+
# Each tag should be of the form !{:tag => 'Fitch : Batch2', :what => 'self', :to => 'Searchworks', :who => 'petucket', :release => true}
|
11
|
+
# @param release_tags [Hash, Array<Hash>] hash of a single release tag or an array of many such hashes
|
12
|
+
# @raise [ArgumentError] Raised if the tags are improperly supplied
|
16
13
|
def add_release_nodes_and_start_releaseWF(release_tags)
|
17
14
|
release_tags = [release_tags] unless release_tags.class == Array
|
18
|
-
|
15
|
+
|
19
16
|
#Add in each tag
|
20
17
|
release_tags.each do |r_tag|
|
21
18
|
self.add_release_node(r_tag[:release],r_tag)
|
22
19
|
end
|
23
|
-
|
20
|
+
|
24
21
|
#Save the item to dor so the robots work with the latest data
|
25
|
-
self.save
|
26
|
-
|
22
|
+
self.save
|
23
|
+
|
27
24
|
#Intialize the release workflow
|
28
|
-
self.initialize_workflow('releaseWF')
|
25
|
+
self.initialize_workflow('releaseWF')
|
29
26
|
end
|
30
27
|
|
31
|
-
#Generate XML structure for inclusion to Purl
|
32
|
-
#
|
33
|
-
#@return [String] The XML release node as a string, with ReleaseDigest as the root document
|
28
|
+
# Generate XML structure for inclusion to Purl
|
29
|
+
# @return [String] The XML release node as a string, with ReleaseDigest as the root document
|
34
30
|
def generate_release_xml
|
35
31
|
builder = Nokogiri::XML::Builder.new do |xml|
|
36
32
|
xml.releaseData {
|
37
|
-
self.released_for.each do |project,released_value|
|
33
|
+
self.released_for.each do |project, released_value|
|
38
34
|
xml.release(released_value["release"],:to=>project)
|
39
|
-
end
|
35
|
+
end
|
40
36
|
}
|
41
37
|
end
|
42
38
|
return builder.to_xml
|
43
39
|
end
|
44
|
-
|
45
|
-
#Determine which projects an item is released for
|
46
|
-
#
|
47
|
-
#@return [Hash] all namespaces in the form of {"Project" => Boolean}
|
40
|
+
|
41
|
+
# Determine which projects an item is released for
|
42
|
+
# @return [Hash{String => Boolean}] all namespaces, keys are Project name Strings, values are Boolean
|
48
43
|
def released_for
|
49
44
|
released_hash = {}
|
50
|
-
|
51
|
-
#Get release tags on the item itself
|
45
|
+
|
46
|
+
#Get release tags on the item itself
|
52
47
|
release_tags_on_this_item = self.release_nodes
|
53
|
-
|
48
|
+
|
54
49
|
#Get any self tags on this item
|
55
50
|
self_release_tags = self.get_self_release_tags(release_tags_on_this_item)
|
56
|
-
|
51
|
+
|
57
52
|
#Get the most recent self tag for all targets and save their result since most recent self always trumps any other non self tags
|
58
53
|
latest_self_tags = self.get_newest_release_tag(self_release_tags)
|
59
54
|
latest_self_tags.keys.each do |target|
|
60
55
|
released_hash[target] = self.clean_release_tag_for_purl(latest_self_tags[target])
|
61
56
|
end
|
62
|
-
|
63
|
-
#With Self Tags Resolved We Now need to deal with tags on all sets this object is part of
|
64
|
-
|
57
|
+
|
58
|
+
#With Self Tags Resolved We Now need to deal with tags on all sets this object is part of
|
59
|
+
|
65
60
|
potential_applicable_release_tags = {} #This will be where we store all tags that apply, regardless of their timestamp
|
66
|
-
|
67
|
-
#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
|
61
|
+
|
62
|
+
#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
|
68
63
|
potential_applicable_release_tags = get_tags_for_what_value(self.get_release_tags_for_item_and_all_governing_sets, 'collection')
|
69
|
-
|
64
|
+
|
70
65
|
administrative_tags = self.tags #Get them once here and pass them down
|
71
|
-
|
66
|
+
|
72
67
|
#We now have the keys for all potential releases, we need to check the tags and the most recent time stamp with an explicit true or false wins, in a nil case, the lack of an explicit false tag we do nothing
|
73
68
|
(potential_applicable_release_tags.keys-released_hash.keys).each do |key| #don't bother checking the ones already added to the release hash, they were added due to a self tag and that has won
|
74
69
|
latest_applicable_tag_for_key = latest_applicable_release_tag_in_array(potential_applicable_release_tags[key], administrative_tags)
|
75
|
-
|
76
|
-
released_hash[key] = self.clean_release_tag_for_purl(latest_applicable_tag_for_key)
|
70
|
+
unless latest_applicable_tag_for_key.nil? #We have a valid tag, record it
|
71
|
+
released_hash[key] = self.clean_release_tag_for_purl(latest_applicable_tag_for_key)
|
77
72
|
end
|
78
|
-
|
73
|
+
|
79
74
|
end
|
80
|
-
|
75
|
+
|
81
76
|
#See what the application is currently released for on Purl. If something is released in purl but not listed here, it needs to be added as a false
|
82
77
|
released_hash = self.add_tags_from_purl(released_hash)
|
83
|
-
|
78
|
+
|
84
79
|
return released_hash
|
85
80
|
end
|
86
|
-
|
87
|
-
#Take a hash of tags as obtained via Dor::Item.release_tags and returns all self tags
|
88
|
-
#
|
89
|
-
|
90
|
-
#
|
91
|
-
#@return [Hash] a hash of self tags for each to value
|
81
|
+
|
82
|
+
# Take a hash of tags as obtained via Dor::Item.release_tags and returns all self tags
|
83
|
+
# @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
84
|
+
# @return [Hash] a hash of self tags for each to value
|
92
85
|
def get_self_release_tags(tags)
|
93
86
|
return get_tags_for_what_value(tags, 'self')
|
94
87
|
end
|
95
|
-
|
96
|
-
#Take an item and get all of its release tags and all tags on collections it is a member of it
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#@return [Hash] a hash of all tags
|
88
|
+
|
89
|
+
# Take an item and get all of its release tags and all tags on collections it is a member of it
|
90
|
+
# @return [Hash] a hash of all tags
|
100
91
|
def get_release_tags_for_item_and_all_governing_sets
|
101
92
|
return_tags = self.release_nodes || {}
|
102
93
|
self.collections.each do |collection|
|
103
94
|
return_tags = combine_two_release_tag_hashes(return_tags, Dor::Item.find(collection.id).get_release_tags_for_item_and_all_governing_sets) #this will function recurvisely so parents of parents are found
|
104
95
|
end
|
105
|
-
return return_tags
|
96
|
+
return return_tags
|
106
97
|
end
|
107
|
-
|
108
|
-
#Take two hashes of tags and combine them, will not overwrite but will enforce uniqueness of the tags
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
#
|
113
|
-
#@return [Hash] the combined hash with uniquiness enforced
|
98
|
+
|
99
|
+
# Take two hashes of tags and combine them, will not overwrite but will enforce uniqueness of the tags
|
100
|
+
# @param hash_one [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
101
|
+
# @param hash_two [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
102
|
+
# @return [Hash] the combined hash with uniquiness enforced
|
114
103
|
def combine_two_release_tag_hashes(hash_one, hash_two)
|
115
104
|
hash_two.keys.each do |key|
|
116
|
-
hash_one[key] = hash_two[key] if hash_one[key]
|
117
|
-
hash_one[key] = (hash_one[key] + hash_two[key]).uniq
|
105
|
+
hash_one[key] = hash_two[key] if hash_one[key].nil?
|
106
|
+
hash_one[key] = (hash_one[key] + hash_two[key]).uniq unless hash_one[key].nil?
|
118
107
|
end
|
119
108
|
return hash_one
|
120
109
|
end
|
121
|
-
|
122
|
-
#Take a hash of tags and return all tags with the matching what target
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
#
|
127
|
-
#@return [Hash] a hash of self tags for each to value
|
110
|
+
|
111
|
+
# Take a hash of tags and return all tags with the matching what target
|
112
|
+
# @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
113
|
+
# @param what_target [String] the target for the 'what' key, self or collection
|
114
|
+
# @return [Hash] a hash of self tags for each to value
|
128
115
|
def get_tags_for_what_value(tags, what_target)
|
129
116
|
return_hash = {}
|
130
117
|
tags.keys.each do |key|
|
@@ -133,26 +120,22 @@ module Dor
|
|
133
120
|
end
|
134
121
|
return return_hash
|
135
122
|
end
|
136
|
-
|
137
|
-
#Take a hash of tags as obtained via Dor::Item.release_tags and returns the newest tag for each namespace
|
138
|
-
#
|
139
|
-
|
140
|
-
#
|
141
|
-
#@return [Hash] a hash of latest tags for each to value
|
123
|
+
|
124
|
+
# Take a hash of tags as obtained via Dor::Item.release_tags and returns the newest tag for each namespace
|
125
|
+
# @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
|
126
|
+
# @return [Hash] a hash of latest tags for each to value
|
142
127
|
def get_newest_release_tag(tags)
|
143
128
|
return_hash = {}
|
144
129
|
tags.keys.each do |key|
|
145
130
|
latest_for_key = newest_release_tag_in_an_array(tags[key])
|
146
|
-
return_hash[key] = latest_for_key
|
131
|
+
return_hash[key] = latest_for_key
|
147
132
|
end
|
148
133
|
return return_hash
|
149
134
|
end
|
150
|
-
|
151
|
-
#Take a tag and return only the attributes we want to put into purl
|
152
|
-
#
|
153
|
-
|
154
|
-
#
|
155
|
-
#@return [Hash] a hash of the attributes we want for purl
|
135
|
+
|
136
|
+
# Take a tag and return only the attributes we want to put into purl
|
137
|
+
# @param tag [Hash] a tag
|
138
|
+
# @return [Hash] a hash of the attributes we want for purl
|
156
139
|
def clean_release_tag_for_purl(tag)
|
157
140
|
for_purl = ['release']
|
158
141
|
return_hash = {}
|
@@ -161,12 +144,10 @@ module Dor
|
|
161
144
|
end
|
162
145
|
return return_hash
|
163
146
|
end
|
164
|
-
|
165
|
-
#Takes an array of release tags and returns the most recent one
|
166
|
-
#
|
167
|
-
|
168
|
-
#
|
169
|
-
#@return [Hash] the most recent tag
|
147
|
+
|
148
|
+
# Takes an array of release tags and returns the most recent one
|
149
|
+
# @param array_of_tags [Array] an array of hashes, each hash a release tag
|
150
|
+
# @return [Hash] the most recent tag
|
170
151
|
def newest_release_tag_in_an_array(array_of_tags)
|
171
152
|
latest_tag_in_array = array_of_tags[0] || {}
|
172
153
|
array_of_tags.each do |tag|
|
@@ -174,62 +155,54 @@ module Dor
|
|
174
155
|
end
|
175
156
|
return latest_tag_in_array
|
176
157
|
end
|
177
|
-
|
178
|
-
#Takes a tag and returns true or false if it applies to the specific item
|
179
|
-
#
|
180
|
-
|
181
|
-
|
182
|
-
#
|
183
|
-
#@return [Boolean] true or false if it applies (not true or false if it is released, that is the release_tag data)
|
158
|
+
|
159
|
+
# Takes a tag and returns true or false if it applies to the specific item
|
160
|
+
# @param release_tag [Hash] the tag in a hashed form
|
161
|
+
# @param admin_tags [Array] the administrative tags on an item, if not supplied it will attempt to retrieve them
|
162
|
+
# @return [Boolean] true or false if it applies (not true or false if it is released, that is the release_tag data)
|
184
163
|
def does_release_tag_apply(release_tag, admin_tags=false)
|
185
|
-
#Is the tag global or restricted
|
186
|
-
return true if release_tag['tag']
|
187
|
-
|
188
|
-
admin_tags = self.tags
|
164
|
+
#Is the tag global or restricted
|
165
|
+
return true if release_tag['tag'].nil? #there is no specific tag specificied, so that means this tag is global to all members of the collection, it applies, return true
|
166
|
+
|
167
|
+
admin_tags = self.tags unless admin_tags #We use false instead of [], since an item can have no admin_tags that which point we'd be passing down this variable as [] and would not an attempt to retrieve it
|
189
168
|
return admin_tags.include?(release_tag['tag'])
|
190
169
|
end
|
191
|
-
|
192
|
-
#Takes an array of release tags and returns the most recent one that applies to this item
|
193
|
-
#
|
194
|
-
|
195
|
-
#
|
196
|
-
#
|
197
|
-
#@return [Hash] the tag
|
170
|
+
|
171
|
+
# Takes an array of release tags and returns the most recent one that applies to this item
|
172
|
+
# @param release_tags [Array] an array of release tags in hashed form
|
173
|
+
# @param admin_tags [Array] the administrative tags on an on item
|
174
|
+
# @return [Hash] the tag
|
198
175
|
def latest_applicable_release_tag_in_array(release_tags, admin_tags)
|
199
176
|
newest_tag = newest_release_tag_in_an_array(release_tags)
|
200
177
|
return newest_tag if does_release_tag_apply(newest_tag, admin_tags) #Return true if we have it
|
201
|
-
|
178
|
+
|
202
179
|
#The latest tag wasn't applicable, slice it off and try again
|
203
180
|
#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
|
204
181
|
release_tags.slice!(release_tags.index(newest_tag))
|
205
|
-
|
206
|
-
return latest_applicable_release_tag_in_array(release_tags, admin_tags) if release_tags.size > 0 #Try again after dropping the one that wasn't applicable
|
207
|
-
|
182
|
+
|
183
|
+
return latest_applicable_release_tag_in_array(release_tags, admin_tags) if release_tags.size > 0 #Try again after dropping the one that wasn't applicable
|
208
184
|
return nil #We're out of tags, no applicable ones
|
209
185
|
end
|
210
|
-
|
211
|
-
#
|
212
|
-
#
|
213
|
-
#@return [Nokogiri::XML::NodeSet] of all release tags and their attributes
|
186
|
+
|
187
|
+
# Helper method to get the release tags as a nodeset
|
188
|
+
# @return [Nokogiri::XML::NodeSet] all release tags and their attributes
|
214
189
|
def release_tags
|
215
190
|
release_tags = self.identityMetadata.ng_xml.xpath('//release')
|
216
191
|
return_hash = {}
|
217
192
|
release_tags.each do |release_tag|
|
218
193
|
hashed_node = self.release_tag_node_to_hash(release_tag)
|
219
|
-
if return_hash[hashed_node[:to]]
|
194
|
+
if !return_hash[hashed_node[:to]].nil?
|
220
195
|
return_hash[hashed_node[:to]] << hashed_node[:attrs]
|
221
196
|
else
|
222
|
-
|
197
|
+
return_hash[hashed_node[:to]] = [hashed_node[:attrs]]
|
223
198
|
end
|
224
199
|
end
|
225
200
|
return return_hash
|
226
201
|
end
|
227
202
|
|
228
|
-
#
|
229
|
-
#
|
230
|
-
|
231
|
-
#
|
232
|
-
#return [Hash] in the form of {:to => String :attrs = Hash}
|
203
|
+
# Convert one release element into a Hash
|
204
|
+
# @param rtag [Nokogiri::XML::Element] the release tag element
|
205
|
+
# @return [Hash{:to, :attrs => String, Hash}] in the form of !{:to => String :attrs = Hash}
|
233
206
|
def release_tag_node_to_hash(rtag)
|
234
207
|
to = 'to'
|
235
208
|
release = 'release'
|
@@ -249,90 +222,84 @@ module Dor
|
|
249
222
|
|
250
223
|
return return_hash
|
251
224
|
end
|
252
|
-
|
253
|
-
#Determine if the supplied tag is a valid release tag that meets all requirements
|
254
|
-
#
|
255
|
-
#@raises [RuntimeError] Raises an error of the first fault in the release tag
|
256
|
-
#
|
257
|
-
#@return [Boolean] Returns true if no errors found
|
225
|
+
|
226
|
+
# Determine if the supplied tag is a valid release tag that meets all requirements
|
258
227
|
#
|
259
|
-
|
228
|
+
# @param attrs [hash] A hash of attributes for the tag, must contain: :when, a ISO 8601 timestamp; :who, to identify who or what added the tag; and :to, a string identifying the release target
|
229
|
+
# @raise [RuntimeError] Raises an error of the first fault in the release tag
|
230
|
+
# @return [Boolean] Returns true if no errors found
|
260
231
|
def valid_release_attributes_and_tag(tag, attrs={})
|
261
|
-
raise ArgumentError, ":when is not iso8601" if attrs[:when].match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z')
|
232
|
+
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?
|
262
233
|
[:who, :to, :what].each do |check_attr|
|
263
234
|
raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String
|
264
235
|
end
|
265
236
|
|
266
237
|
what_correct = false
|
267
|
-
|
238
|
+
%w(self collection).each do |allowed_what_value|
|
268
239
|
what_correct = true if attrs[:what] == allowed_what_value
|
269
240
|
end
|
270
|
-
raise ArgumentError, ":what must be self or collection"
|
241
|
+
raise ArgumentError, ":what must be self or collection" unless what_correct
|
271
242
|
raise ArgumentError, "the value set for this tag is not a boolean" if !!tag != tag
|
272
|
-
validate_tag_format(attrs[:tag])
|
243
|
+
validate_tag_format(attrs[:tag]) unless attrs[:tag].nil? #Will Raise exception if invalid tag
|
273
244
|
return true
|
274
245
|
end
|
275
|
-
|
276
|
-
#Add a release node for the item
|
277
|
-
#Will use the current time
|
278
|
-
#
|
279
|
-
#@return [Nokogiri::XML::Element] the tag added if successful
|
280
|
-
#
|
281
|
-
#@raise [ArgumentError] Raised if attributes are improperly supplied
|
246
|
+
|
247
|
+
# Add a release node for the item
|
248
|
+
# Will use the current time if timestamp not supplied. You can supply a timestap for correcting history, etc if desired
|
249
|
+
# Timestamp will be calculated by the function, if no displayType is passed in, it will default to file
|
282
250
|
#
|
283
|
-
|
284
|
-
|
285
|
-
#
|
251
|
+
# @param release [Boolean] True or false for the release node
|
252
|
+
# @param attrs [hash] A hash of any attributes to be placed onto the tag
|
253
|
+
# @return [Nokogiri::XML::Element] the tag added if successful
|
254
|
+
# @raise [ArgumentError] Raised if attributes are improperly supplied
|
286
255
|
#
|
287
|
-
|
256
|
+
# @example
|
288
257
|
# item.add_tag(true,:release,{:tag=>'Fitch : Batch2',:what=>'self',:to=>'Searchworks',:who=>'petucket', :displayType='filmstrip'})
|
289
258
|
def add_release_node(release, attrs={})
|
290
259
|
identity_metadata_ds = self.identityMetadata
|
291
260
|
attrs[:when] = Time.now.utc.iso8601 if attrs[:when].nil? #add the timestamp
|
292
261
|
attrs[:displayType] = 'file' if attrs[:displayType].nil? #default to file is no display type is passed
|
293
262
|
valid_release_attributes(release, attrs)
|
294
|
-
|
263
|
+
|
295
264
|
#Remove the old displayType and then add the one for this tag
|
296
265
|
remove_displayTypes
|
297
266
|
identity_metadata_ds.add_value(:displayType, attrs[:displayType], {})
|
298
|
-
|
267
|
+
|
299
268
|
return identity_metadata_ds.add_value(:release, release.to_s, attrs)
|
300
269
|
end
|
301
270
|
|
302
|
-
#Determine if the supplied tag is a valid release node that meets all requirements
|
303
|
-
#
|
304
|
-
#@raises [ArgumentError] Raises an error of the first fault in the release tag
|
271
|
+
# Determine if the supplied tag is a valid release node that meets all requirements
|
305
272
|
#
|
306
|
-
|
307
|
-
#
|
308
|
-
|
273
|
+
# @param tag [Boolean] True or false for the release node
|
274
|
+
# @param attrs [hash] A hash of attributes for the tag, must contain :when, a ISO 8601 timestamp and :who to identify who or what added the tag, :to,
|
275
|
+
# @raise [ArgumentError] Raises an error of the first fault in the release tag
|
276
|
+
# @return [Boolean] Returns true if no errors found
|
309
277
|
def valid_release_attributes(tag, attrs={})
|
310
|
-
raise ArgumentError, ":when is not iso8601" if attrs[:when].match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z')
|
278
|
+
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?
|
311
279
|
[:who, :to, :what].each do |check_attr|
|
312
280
|
raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String
|
313
281
|
end
|
314
282
|
|
315
283
|
what_correct = false
|
316
|
-
|
284
|
+
%w(self collection).each do |allowed_what_value|
|
317
285
|
what_correct = true if attrs[:what] == allowed_what_value
|
318
286
|
end
|
319
|
-
raise ArgumentError, ":what must be self or collection"
|
287
|
+
raise ArgumentError, ":what must be self or collection" unless what_correct
|
320
288
|
raise ArgumentError, "the value set for this tag is not a boolean" if !!tag != tag
|
321
289
|
raise ArgumentError, ":displayType must be passed in as a String" unless attrs[:displayType].class == String
|
322
|
-
|
323
|
-
validate_tag_format(attrs[:tag])
|
290
|
+
|
291
|
+
validate_tag_format(attrs[:tag]) unless attrs[:tag].nil? #Will Raise exception if invalid tag
|
324
292
|
return true
|
325
293
|
end
|
326
294
|
|
327
|
-
#
|
328
|
-
#
|
329
|
-
#@return [Nokogiri::XML::NodeSet] of all release tags and their attributes
|
295
|
+
# Helper method to get the release nodes as a nodeset
|
296
|
+
# @return [Nokogiri::XML::NodeSet] of all release tags and their attributes
|
330
297
|
def release_nodes
|
331
298
|
release_tags = self.identityMetadata.ng_xml.xpath('//release')
|
332
299
|
return_hash = {}
|
333
300
|
release_tags.each do |release_tag|
|
334
301
|
hashed_node = self.release_tag_node_to_hash(release_tag)
|
335
|
-
if return_hash[hashed_node[:to]]
|
302
|
+
if !return_hash[hashed_node[:to]].nil?
|
336
303
|
return_hash[hashed_node[:to]] << hashed_node[:attrs]
|
337
304
|
else
|
338
305
|
return_hash[hashed_node[:to]] = [hashed_node[:attrs]]
|
@@ -340,81 +307,67 @@ module Dor
|
|
340
307
|
end
|
341
308
|
return return_hash
|
342
309
|
end
|
343
|
-
|
344
|
-
#Get a list of all release nodes found in a purl document
|
345
|
-
#
|
346
|
-
|
347
|
-
#
|
348
|
-
#@raises [OpenURI::HTTPError]
|
349
|
-
#
|
350
|
-
#Fetches purl xml for a druid
|
351
|
-
#
|
352
|
-
#@return [Nokogiri::HTML::Document] the parsed xml for the druid or an empty document if no purl is found
|
310
|
+
|
311
|
+
# Get a list of all release nodes found in a purl document
|
312
|
+
# Fetches purl xml for a druid
|
313
|
+
# @raise [OpenURI::HTTPError]
|
314
|
+
# @return [Nokogiri::HTML::Document] parsed XML for the druid or an empty document if no purl is found
|
353
315
|
def get_xml_from_purl
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
316
|
+
handler = Proc.new do |exception, attempt_number, total_delay|
|
317
|
+
#We assume a 404 means the document has never been published before and thus has no purl
|
318
|
+
#The strip is needed before the actual message is "404 "
|
319
|
+
return Nokogiri::HTML::Document.new if exception.message.strip == "404"
|
320
|
+
end
|
359
321
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
322
|
+
with_retries(:max_retries => 5, :base_sleep_seconds => 3, :max_sleep_seconds=> 5, :rescue => OpenURI::HTTPError, :handler => handler) {
|
323
|
+
#If you change the method used for opening the webpage, you can change the :rescue param to handle the new method's errors
|
324
|
+
return Nokogiri::HTML(open(self.form_purl_url))
|
325
|
+
}
|
365
326
|
end
|
366
|
-
|
367
|
-
#Since purl does not use the druid: prefix but much of dor does, use this function to strip the druid: if needed
|
368
|
-
#
|
369
|
-
#@return [String] the druid sans the druid: or if there was no druid: prefix, the entire string you passed
|
327
|
+
|
328
|
+
# Since purl does not use the druid: prefix but much of dor does, use this function to strip the druid: if needed
|
329
|
+
# @return [String] the druid sans the druid: or if there was no druid: prefix, the entire string you passed
|
370
330
|
def remove_druid_prefix
|
371
331
|
druid_prefix = "druid:"
|
372
332
|
return self.id.split(druid_prefix)[1] if self.id.split(druid_prefix).size > 1
|
373
333
|
return druid
|
374
334
|
end
|
375
|
-
|
376
|
-
#Take the and create the entire purl url that will usable for the open method in open-uri, returns http
|
377
|
-
#
|
378
|
-
#params druid [String], the druid without or without the driud prefix
|
379
|
-
#
|
380
|
-
#return [String], the full url
|
335
|
+
|
336
|
+
# Take the and create the entire purl url that will usable for the open method in open-uri, returns http
|
337
|
+
# @return [String], the full url
|
381
338
|
def form_purl_url
|
382
|
-
prefix = "http://"
|
339
|
+
prefix = "http://"
|
383
340
|
return prefix + Dor::Config.stacks.document_cache_host + "/#{self.remove_druid_prefix}.xml"
|
384
341
|
end
|
385
|
-
|
386
|
-
#Pull all release nodes from the public xml obtained via the purl query
|
387
|
-
#
|
388
|
-
|
389
|
-
#
|
390
|
-
#@return [Array] An array containing all the release tags
|
342
|
+
|
343
|
+
# Pull all release nodes from the public xml obtained via the purl query
|
344
|
+
# @param doc [Nokogiri::HTML::Document] The druid of the object you want
|
345
|
+
# @return [Array] An array containing all the release tags
|
391
346
|
def get_release_tags_from_purl_xml(doc)
|
392
|
-
nodes = doc.xpath("//html/body/publicobject/releasedata").children
|
347
|
+
nodes = doc.xpath("//html/body/publicobject/releasedata").children
|
393
348
|
#We only want the nodes with a name that isn't text
|
394
349
|
return_array = []
|
395
350
|
nodes.each do |n|
|
396
|
-
return_array << n.attr('to') if n.name
|
351
|
+
return_array << n.attr('to') if !n.name.nil? && n.name.downcase != "text"
|
397
352
|
end
|
398
|
-
return return_array.uniq
|
353
|
+
return return_array.uniq
|
399
354
|
end
|
400
|
-
|
401
|
-
#Pull all release nodes from the public xml obtained via the purl query
|
402
|
-
#
|
403
|
-
#@return [Array] An array containing all the release tags
|
355
|
+
|
356
|
+
# Pull all release nodes from the public xml obtained via the purl query
|
357
|
+
# @return [Array] An array containing all the release tags
|
404
358
|
def get_release_tags_from_purl
|
405
359
|
xml = self.get_xml_from_purl
|
406
360
|
return self.get_release_tags_from_purl_xml(xml)
|
407
361
|
end
|
408
|
-
|
409
|
-
#This function calls purl and gets a list of all release tags currently in purl. It then compares to the list you have generated.
|
410
|
-
#Any tag that is on purl, but not in the newly generated list is added to the new list with a value of false.
|
411
|
-
#
|
412
|
-
#params new_tags [Hash] a hash of all new tags in the form of {Project => Boolean}, where Project is a string
|
362
|
+
|
363
|
+
# This function calls purl and gets a list of all release tags currently in purl. It then compares to the list you have generated.
|
364
|
+
# Any tag that is on purl, but not in the newly generated list is added to the new list with a value of false.
|
413
365
|
#
|
414
|
-
#
|
415
|
-
|
366
|
+
# @param new_tags [Hash{String => Boolean}] all new tags in the form of !{"Project" => Boolean}
|
367
|
+
# @return [Hash], a hash in the 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
|
368
|
+
def add_tags_from_purl(new_tags)
|
416
369
|
tags_currently_in_purl = self.get_release_tags_from_purl
|
417
|
-
missing_tags = tags_currently_in_purl.map(&:downcase) - new_tags.keys.map(&:downcase)
|
370
|
+
missing_tags = tags_currently_in_purl.map(&:downcase) - new_tags.keys.map(&:downcase)
|
418
371
|
missing_tags.each do |missing_tag|
|
419
372
|
new_tags[missing_tag.capitalize] = {"release"=>false}
|
420
373
|
end
|
@@ -424,14 +377,14 @@ module Dor
|
|
424
377
|
def to_solr(solr_doc=Hash.new, *args)
|
425
378
|
super(solr_doc, *args)
|
426
379
|
|
427
|
-
#TODO: sort of worried about the performance impact in bulk reindex
|
380
|
+
#TODO: sort of worried about the performance impact in bulk reindex
|
428
381
|
# situations, since released_for recurses all parent collections. jmartin 2015-07-14
|
429
382
|
released_for().each { |key, val|
|
430
383
|
add_solr_value(solr_doc, "released_to", key, :symbol, []) if val
|
431
384
|
}
|
432
385
|
|
433
|
-
#TODO: need to solrize whether item is released to purl? does released_for
|
434
|
-
# return that? logic is: "True when there is a published lifecycle and Access
|
386
|
+
#TODO: need to solrize whether item is released to purl? does released_for
|
387
|
+
# return that? logic is: "True when there is a published lifecycle and Access
|
435
388
|
# Rights is anything but Dark"
|
436
389
|
|
437
390
|
return solr_doc
|