Module: Dor::Releaseable
- Extended by:
- ActiveSupport::Concern
- Includes:
- Itemizable
- Included in:
- BasicItem, Collection
- Defined in:
- lib/dor/models/releaseable.rb
Constant Summary
Constants included from Itemizable
Instance Method Summary collapse
-
#add_release_node(release, attrs = {}) ⇒ Nokogiri::XML::Element
Add a release node for the item Will use the current time if timestamp not supplied.
-
#add_release_nodes_and_start_releaseWF(release_tags) ⇒ Object
Add release tags to an item and initialize the item release workflow Each tag should be of the form {:tag => ‘Fitch : Batch2’, :what => ‘self’, :to => ‘Searchworks’, :who => ‘petucket’, :release => true}.
-
#add_tags_from_purl(new_tags) ⇒ Hash
This function calls purl and gets a list of all release tags currently in purl.
-
#combine_two_release_tag_hashes(hash_one, hash_two) ⇒ Hash
Take two hashes of tags and combine them, will not overwrite but will enforce uniqueness of the tags.
-
#does_release_tag_apply(release_tag, admin_tags = false) ⇒ Boolean
Takes a tag and returns true or false if it applies to the specific item.
-
#form_purl_url ⇒ String
Take the and create the entire purl url that will usable for the open method in open-uri, returns http.
-
#generate_release_xml ⇒ String
Generate XML structure for inclusion to Purl.
-
#get_newest_release_tag(tags) ⇒ Hash
Take a hash of tags as obtained via Dor::Item.release_tags and returns the newest tag for each namespace.
-
#get_release_tags_for_item_and_all_governing_sets ⇒ Hash
Take an item and get all of its release tags and all tags on collections it is a member of it.
-
#get_release_tags_from_purl ⇒ Array
Pull all release nodes from the public xml obtained via the purl query.
-
#get_release_tags_from_purl_xml(doc) ⇒ Array
Pull all release nodes from the public xml obtained via the purl query.
-
#get_self_release_tags(tags) ⇒ Hash
Take a hash of tags as obtained via Dor::Item.release_tags and returns all self tags.
-
#get_tags_for_what_value(tags, what_target) ⇒ Hash
Take a hash of tags and return all tags with the matching what target.
-
#get_xml_from_purl ⇒ Nokogiri::HTML::Document
Get a list of all release nodes found in a purl document Fetches purl xml for a druid.
-
#latest_applicable_release_tag_in_array(release_tags, admin_tags) ⇒ Hash
Takes an array of release tags and returns the most recent one that applies to this item.
-
#newest_release_tag_in_an_array(array_of_tags) ⇒ Hash
Takes an array of release tags and returns the most recent one.
-
#release_nodes ⇒ Nokogiri::XML::NodeSet
Helper method to get the release nodes as a nodeset.
-
#release_tag_node_to_hash(rtag) ⇒ Hash{:to, :attrs => String, Hash}
Convert one release element into a Hash.
-
#release_tags ⇒ Nokogiri::XML::NodeSet
Helper method to get the release tags as a nodeset.
-
#released_for(skip_live_purl = false) ⇒ Hash{String => Boolean}
Determine projects in which an item is released.
- #to_solr(solr_doc = {}, *args) ⇒ Object
-
#valid_release_attributes(tag, attrs = {}) ⇒ Boolean
Determine if the supplied tag is a valid release node that meets all requirements.
-
#valid_release_attributes_and_tag(tag, attrs = {}) ⇒ Boolean
Determine if the supplied tag is a valid release tag that meets all requirements.
Methods included from Itemizable
#clear_diff_cache, #get_content_diff
Instance Method Details
#add_release_node(release, attrs = {}) ⇒ Nokogiri::XML::Element
Add a release node for the item Will use the current time if timestamp not supplied. You can supply a timestap for correcting history, etc if desired Timestamp will be calculated by the function
226 227 228 229 230 231 232 233 |
# File 'lib/dor/models/releaseable.rb', line 226 def add_release_node(release, attrs = {}) allowed_release_attributes=[:what,:to,:who,:when] # any other release attributes sent in will be rejected and not stored = identityMetadata attrs.delete_if { |key, value| !allowed_release_attributes.include?(key) } attrs[:when] = Time.now.utc.iso8601 if attrs[:when].nil? # add the timestamp valid_release_attributes(release, attrs) .add_value(:release, release.to_s, attrs) end |
#add_release_nodes_and_start_releaseWF(release_tags) ⇒ Object
Add release tags to an item and initialize the item release workflow Each tag should be of the form {:tag => ‘Fitch : Batch2’, :what => ‘self’, :to => ‘Searchworks’, :who => ‘petucket’, :release => true}
13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/dor/models/releaseable.rb', line 13 def add_release_nodes_and_start_releaseWF() = [] unless .is_a?(Array) # Add in each tag .each do |r_tag| add_release_node(r_tag[:release], r_tag) end # Save item to dor so the robots work with the latest data save create_workflow('releaseWF') end |
#add_tags_from_purl(new_tags) ⇒ Hash
This function calls purl and gets a list of all release tags currently in purl. It then compares to the list you have generated. Any tag that is on purl, but not in the newly generated list is added to the new list with a value of false.
312 313 314 315 316 317 318 319 |
# File 'lib/dor/models/releaseable.rb', line 312 def () = = .map(&:downcase) - .keys.map(&:downcase) .each do |missing_tag| [missing_tag.capitalize] = {'release' => false} end end |
#combine_two_release_tag_hashes(hash_one, hash_two) ⇒ Hash
Take two hashes of tags and combine them, will not overwrite but will enforce uniqueness of the tags
91 92 93 94 95 96 97 |
# File 'lib/dor/models/releaseable.rb', line 91 def combine_two_release_tag_hashes(hash_one, hash_two) hash_two.keys.each do |key| hash_one[key] = hash_two[key] if hash_one[key].nil? hash_one[key] = (hash_one[key] + hash_two[key]).uniq unless hash_one[key].nil? end hash_one end |
#does_release_tag_apply(release_tag, admin_tags = false) ⇒ Boolean
Takes a tag and returns true or false if it applies to the specific item
134 135 136 137 138 139 |
# File 'lib/dor/models/releaseable.rb', line 134 def does_release_tag_apply(release_tag, = false) # Is the tag global or restricted return true if release_tag['tag'].nil? # no specific tag specificied means this tag is global to all members of the collection = unless # 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 .include?(release_tag['tag']) end |
#form_purl_url ⇒ String
Take the and create the entire purl url that will usable for the open method in open-uri, returns http
289 290 291 |
# File 'lib/dor/models/releaseable.rb', line 289 def form_purl_url 'https://' + Dor::Config.stacks.document_cache_host + "/#{remove_druid_prefix}.xml" end |
#generate_release_xml ⇒ String
Generate XML structure for inclusion to Purl
28 29 30 31 32 33 34 35 36 37 |
# File 'lib/dor/models/releaseable.rb', line 28 def generate_release_xml builder = Nokogiri::XML::Builder.new do |xml| xml.releaseData { released_for.each do |project, released_value| xml.release(released_value['release'], :to => project) end } end builder.to_xml end |
#get_newest_release_tag(tags) ⇒ Hash
Take a hash of tags as obtained via Dor::Item.release_tags and returns the newest tag for each namespace
115 116 117 |
# File 'lib/dor/models/releaseable.rb', line 115 def get_newest_release_tag() Hash[.map {|key, val| [key, newest_release_tag_in_an_array(val)]}] end |
#get_release_tags_for_item_and_all_governing_sets ⇒ Hash
Take an item and get all of its release tags and all tags on collections it is a member of it
79 80 81 82 83 84 85 |
# File 'lib/dor/models/releaseable.rb', line 79 def = release_nodes || {} collections.each do |collection| = combine_two_release_tag_hashes(, Dor::Item.find(collection.id).) # recurvise so parents of parents are found end end |
#get_release_tags_from_purl ⇒ Array
Pull all release nodes from the public xml obtained via the purl query
304 305 306 |
# File 'lib/dor/models/releaseable.rb', line 304 def (get_xml_from_purl) end |
#get_release_tags_from_purl_xml(doc) ⇒ Array
Pull all release nodes from the public xml obtained via the purl query
296 297 298 299 300 |
# File 'lib/dor/models/releaseable.rb', line 296 def (doc) nodes = doc.xpath('//html/body/publicobject/releasedata').children # We only want the nodes with a name that isn't text nodes.reject {|n| n.name.nil? || n.name.casecmp('text') == 0 }.map {|n| n.attr('to')}.uniq end |
#get_self_release_tags(tags) ⇒ Hash
Take a hash of tags as obtained via Dor::Item.release_tags and returns all self tags
73 74 75 |
# File 'lib/dor/models/releaseable.rb', line 73 def () (, 'self') end |
#get_tags_for_what_value(tags, what_target) ⇒ Hash
Take a hash of tags and return all tags with the matching what target
103 104 105 106 107 108 109 110 |
# File 'lib/dor/models/releaseable.rb', line 103 def (, what_target) return_hash = {} .keys.each do |key| = [key].select {|tag| tag['what'].casecmp(what_target) == 0} return_hash[key] = if .size > 0 end return_hash end |
#get_xml_from_purl ⇒ Nokogiri::HTML::Document
Get a list of all release nodes found in a purl document Fetches purl xml for a druid
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/dor/models/releaseable.rb', line 271 def get_xml_from_purl url = form_purl_url handler = proc do |exception, attempt_number, total_delay| # We assume a 404 means the document has never been published before and thus has no purl Dor.logger.warn "[Attempt #{attempt_number}] GET #{url} -- #{exception.class}: #{exception.}; #{total_delay} seconds elapsed." raise exception unless exception.is_a? OpenURI::HTTPError return Nokogiri::HTML::Document.new if exception.io.status.first == '404' # ["404", "Not Found"] from OpenURI::Meta.status end with_retries(:max_retries => 3, :base_sleep_seconds => 3, :max_sleep_seconds => 5, :handler => handler) do |attempt| # If you change the method used for opening the webpage, you can change the :rescue param to handle the new method's errors Dor.logger.info "[Attempt #{attempt}] GET #{url}" return Nokogiri::HTML(OpenURI.open_uri(url)) end end |
#latest_applicable_release_tag_in_array(release_tags, admin_tags) ⇒ Hash
Takes an array of release tags and returns the most recent one that applies to this item
145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/dor/models/releaseable.rb', line 145 def latest_applicable_release_tag_in_array(, ) newest_tag = newest_release_tag_in_an_array() return newest_tag if does_release_tag_apply(newest_tag, ) # The latest tag wasn't applicable, slice it off and try again # 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 .slice!(.index(newest_tag)) return latest_applicable_release_tag_in_array(, ) if .size > 0 # Try again after dropping the inapplicable nil # We're out of tags, no applicable ones end |
#newest_release_tag_in_an_array(array_of_tags) ⇒ Hash
Takes an array of release tags and returns the most recent one
122 123 124 125 126 127 128 |
# File 'lib/dor/models/releaseable.rb', line 122 def newest_release_tag_in_an_array() latest_tag_in_array = [0] || {} .each do |tag| latest_tag_in_array = tag if tag['when'] > latest_tag_in_array['when'] end latest_tag_in_array end |
#release_nodes ⇒ Nokogiri::XML::NodeSet
Helper method to get the release nodes as a nodeset
253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/dor/models/releaseable.rb', line 253 def release_nodes = identityMetadata.ng_xml.xpath('//release') return_hash = {} .each do |release_tag| hashed_node = release_tag_node_to_hash(release_tag) if !return_hash[hashed_node[:to]].nil? return_hash[hashed_node[:to]] << hashed_node[:attrs] else return_hash[hashed_node[:to]] = [hashed_node[:attrs]] end end return_hash end |
#release_tag_node_to_hash(rtag) ⇒ Hash{:to, :attrs => String, Hash}
Convert one release element into a Hash
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/dor/models/releaseable.rb', line 176 def release_tag_node_to_hash(rtag) to = 'to' release = 'release' when_word = 'when' # TODO: Make to and when_word load from some config file instead of hardcoded here attrs = rtag.attributes return_hash = { :to => attrs[to].value } attrs.tap { |a| a.delete(to) } attrs[release] = rtag.text.casecmp('true') == 0 # save release as a boolean return_hash[:attrs] = attrs # convert all the attrs beside :to to strings, they are currently Nokogiri::XML::Attr (return_hash[:attrs].keys - [to]).each do |a| return_hash[:attrs][a] = return_hash[:attrs][a].to_s if a != release end return_hash[:attrs][when_word] = Time.parse(return_hash[:attrs][when_word]) # convert when to a datetime return_hash end |
#release_tags ⇒ Nokogiri::XML::NodeSet
Helper method to get the release tags as a nodeset
159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/dor/models/releaseable.rb', line 159 def = identityMetadata.ng_xml.xpath('//release') return_hash = {} .each do |release_tag| hashed_node = release_tag_node_to_hash(release_tag) if !return_hash[hashed_node[:to]].nil? return_hash[hashed_node[:to]] << hashed_node[:attrs] else return_hash[hashed_node[:to]] = [hashed_node[:attrs]] end end return_hash end |
#released_for(skip_live_purl = false) ⇒ Hash{String => Boolean}
Determine projects in which an item is released
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/dor/models/releaseable.rb', line 42 def released_for(skip_live_purl = false) released_hash = {} # Get the most recent self tag for all targets and retain their result since most recent self always trumps any other non self tags = get_newest_release_tag (release_nodes) .each do |key, payload| released_hash[key] = {'release' => payload['release']} end # With Self Tags resolved we now need to deal with tags on all sets this object is part of. # 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. # This will be where we store all tags that apply, regardless of their timestamp: = (, 'collection') = # Get admin tags once here and pass them down # 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. # In a nil case, the lack of an explicit false tag we do nothing. (.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 latest_tag = latest_applicable_release_tag_in_array([key], ) next if latest_tag.nil? # Otherwise, we have a valid tag, record it released_hash[key] = {'release' => latest_tag['release']} end # 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 (released_hash) unless skip_live_purl released_hash end |
#to_solr(solr_doc = {}, *args) ⇒ Object
321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/dor/models/releaseable.rb', line 321 def to_solr(solr_doc = {}, *args) super(solr_doc, *args) # TODO: sort of worried about the performance impact in bulk reindex # situations, since released_for recurses all parent collections. jmartin 2015-07-14 released_for(true).each { |release_target, release_info| add_solr_value(solr_doc, 'released_to', release_target, :symbol, []) if release_info['release'] } # TODO: need to solrize whether item is released to purl? does released_for return that? # logic is: "True when there is a published lifecycle and Access Rights is anything but Dark" solr_doc end |
#valid_release_attributes(tag, attrs = {}) ⇒ Boolean
Determine if the supplied tag is a valid release node that meets all requirements
241 242 243 244 245 246 247 248 249 |
# File 'lib/dor/models/releaseable.rb', line 241 def valid_release_attributes(tag, attrs = {}) 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? [:who, :to, :what].each do |check_attr| raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String end raise ArgumentError, ':what must be self or collection' unless %w(self collection).include? attrs[:what] raise ArgumentError, 'the value set for this tag is not a boolean' unless [true,false].include? tag true end |
#valid_release_attributes_and_tag(tag, attrs = {}) ⇒ Boolean
Determine if the supplied tag is a valid release tag that meets all requirements
200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/dor/models/releaseable.rb', line 200 def valid_release_attributes_and_tag(tag, attrs = {}) 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? [:who, :to, :what].each do |check_attr| raise ArgumentError, "#{check_attr} not supplied as a String" if attrs[check_attr].class != String end what_correct = false %w(self collection).each do |allowed_what_value| what_correct = true if attrs[:what] == allowed_what_value end raise ArgumentError, ':what must be self or collection' unless what_correct raise ArgumentError, 'the value set for this tag is not a boolean' if !!tag != tag # rubocop:disable Style/DoubleNegation true end |