dor-services 4.16.0 → 4.17.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bda19055e5488d98744f9b3f4c88030f5c2ed3fc
4
- data.tar.gz: fb252ec7e922e6ee181e6b1628b078dc6732c353
3
+ metadata.gz: f9827e7ec12f745a9cefc0fc8ef7495d59cd3e30
4
+ data.tar.gz: c36bbb94cb5472516891b3f1182b43df1e549dfc
5
5
  SHA512:
6
- metadata.gz: 7056ca6fd329bf73b0d617fe66a4b78caf22d22c903d1901471a20e2cfd66935a60c2b45eb522ea08bce8c9d1d7038bf3f18ada5fc759cb329566fa800ed4398
7
- data.tar.gz: 89251676387a262a78991de2112beeb87fcaf2aef1482c4452b114f9a60c4699e57668267ff87ab02e8aa148893d56c773cb00566b3f3eefdd80b49fb20de365
6
+ metadata.gz: 111845f2b86c6f361ac0f92782bdf7dbd4657dddf79d2982a255d410ad28f13c13f516b85b10d8e4b900b00468a8a852820383e13bc4de5001ea31a8f83451c9
7
+ data.tar.gz: ace98996317f041e2488bc690a6a2626150f7037210b35715f154a71d83a1af8134fd118081801848a392c0c50da19312ff978f35633628e2b28206d393292e9
@@ -2,7 +2,7 @@ cert_dir = File.join(File.dirname(__FILE__), "..", "certs")
2
2
 
3
3
  Dor::Config.configure do
4
4
  fedora do
5
- url 'https://sul-dor-dev.stanford.edu/fedora'
5
+ url 'https://sul-dor-test.stanford.edu/fedora'
6
6
  end
7
7
 
8
8
  ssl do
@@ -33,7 +33,7 @@ Dor::Config.configure do
33
33
  iiif_profile 'http://iiif.io/api/image/2/level1.json'
34
34
  end
35
35
 
36
- solrizer.url 'http://sul-solr.stanford.edu/solr/argo_dev'
36
+ solrizer.url 'http://127.0.0.1/solr/argo_test'
37
37
  workflow.url 'https://lyberservices-dev.stanford.edu/workflow/'
38
38
  dor_services.url 'https://dorAdmin:dorAdmin@sul-lyberservices-dev.stanford.edu/dor'
39
39
 
@@ -0,0 +1,84 @@
1
+ cert_dir = File.join(File.dirname(__FILE__), "..", "certs")
2
+
3
+ Dor::Config.configure do
4
+ fedora do
5
+ url 'https://sul-dor-dev.stanford.edu/fedora'
6
+ end
7
+
8
+ ssl do
9
+ cert_file File.join(cert_dir,"robots-dor-dev.crt")
10
+ key_file File.join(cert_dir,"robots-dor-dev.key")
11
+ key_pass ''
12
+ end
13
+
14
+ suri do
15
+ mint_ids true
16
+ id_namespace 'druid'
17
+ url 'https://lyberservices-dev.stanford.edu'
18
+ user 'labware'
19
+ pass 'lyberteam'
20
+ end
21
+
22
+ metadata do
23
+ exist.url 'http://viewer:l3l%40nd@lyberapps-dev.stanford.edu/exist/rest/'
24
+ catalog.url 'http://lyberservices-prod.stanford.edu/catalog/mods'
25
+ end
26
+
27
+ stacks do
28
+ document_cache_host 'purl-dev.stanford.edu'
29
+ local_stacks_root '/stacks'
30
+ local_document_cache_root '/purl/document_cache'
31
+ local_workspace_root '/dor/workspace'
32
+ url 'http://stacks-dev.stanford.edu'
33
+ iiif_profile 'http://iiif.io/api/image/2/level1.json'
34
+ end
35
+
36
+ solrizer.url 'http://sul-solr.stanford.edu/solr/argo_dev'
37
+ workflow.url 'https://lyberservices-dev.stanford.edu/workflow/'
38
+ dor_services.url 'https://dorAdmin:dorAdmin@sul-lyberservices-dev.stanford.edu/dor'
39
+
40
+ cleanup do
41
+ local_workspace_root '/dor/workspace'
42
+ local_export_home '/dor/export'
43
+ end
44
+
45
+ sdr do
46
+ url 'https://sdrAdmin:sdrAdmin@sul-sdr-services-dev.stanford.edu/sdr/'
47
+ local_workspace_root '/dor/workspace'
48
+ local_export_home '/dor/export'
49
+ datastreams do
50
+ administrativeMetadata 'optional'
51
+ contentMetadata 'optional'
52
+ descMetadata 'required'
53
+ defaultObjectRights 'optional'
54
+ events 'optional'
55
+ embargoMetadata 'optional'
56
+ identityMetadata 'required'
57
+ provenanceMetadata 'required'
58
+ relationshipMetadata 'required'
59
+ rightsMetadata 'optional'
60
+ roleMetadata 'optional'
61
+ sourceMetadata 'optional'
62
+ technicalMetadata 'optional'
63
+ versionMetadata 'required'
64
+ workflows 'optional'
65
+ end
66
+ end
67
+
68
+ accessioning_robot_sleep_time 30
69
+
70
+ end
71
+
72
+
73
+ #WORKFLOW_URI = 'http://lyberservices-test.stanford.edu/workflow'
74
+
75
+ # Constants for Dor::WorkflowService
76
+ #module Dor
77
+ # CREATE_WORKFLOW = DOR_CREATE_WORKFLOW = true
78
+ # WF_URI = 'http://lyberservices-test.stanford.edu/workflow'
79
+ #end
80
+
81
+ # External application locations
82
+ JHOVE_HOME = File.join(ENV['HOME'], 'jhoveToolkit')
83
+
84
+ REDIS_URL = "sul-lyberservices-dev.stanford.edu:6379/resque:#{ENV['ROBOT_ENVIRONMENT']}"
@@ -2,7 +2,7 @@ cert_dir = File.join(File.dirname(__FILE__), "..", "certs")
2
2
 
3
3
  Dor::Config.configure do
4
4
  fedora do
5
- url 'https://sul-dor-dev.stanford.edu/fedora'
5
+ url 'https://sul-dor-test.stanford.edu/fedora'
6
6
  end
7
7
 
8
8
  ssl do
@@ -33,7 +33,7 @@ Dor::Config.configure do
33
33
  iiif_profile 'http://iiif.io/api/image/2/level1.json'
34
34
  end
35
35
 
36
- solrizer.url 'http://sul-solr.stanford.edu/solr/argo_dev'
36
+ solrizer.url 'http://127.0.0.1/solr/argo_test'
37
37
  workflow.url 'https://lyberservices-dev.stanford.edu/workflow/'
38
38
  dor_services.url 'https://dorAdmin:dorAdmin@sul-lyberservices-dev.stanford.edu/dor'
39
39
 
data/lib/dor-services.rb CHANGED
@@ -118,6 +118,7 @@ module Dor
118
118
  autoload :Discoverable, 'dor/models/discoverable'
119
119
  autoload :Geoable, 'dor/models/geoable'
120
120
  autoload :Presentable, 'dor/models/presentable'
121
+ autoload :Releaseable, 'dor/models/releaseable'
121
122
 
122
123
 
123
124
  # ActiveFedora Classes
@@ -31,6 +31,48 @@ module Dor
31
31
  def tags
32
32
  self.identityMetadata.tag
33
33
  end
34
+
35
+ #helper method to get the release tags as a nodeset
36
+ #
37
+ #@return [Nokogiri::XML::NodeSet] of all release tags and their attributes
38
+ def release_tags
39
+ release_tags = self.identityMetadata.ng_xml.xpath('//release')
40
+ return_hash = {}
41
+ release_tags.each do |release_tag|
42
+ hashed_node = self.release_tag_node_to_hash(release_tag)
43
+ if return_hash[hashed_node[:to]] != nil
44
+ return_hash[hashed_node[:to]] << hashed_node[:attrs]
45
+ else
46
+ return_hash[hashed_node[:to]] = [hashed_node[:attrs]]
47
+ end
48
+ end
49
+ return return_hash
50
+ end
51
+
52
+ #method to convert one release element into an array
53
+ #
54
+ #@param rtag [Nokogiri::XML::Element] the release tag element
55
+ #
56
+ #return [Hash] in the form of {:to => String :attrs = Hash}
57
+ def release_tag_node_to_hash(rtag)
58
+ to = 'to'
59
+ release = 'release'
60
+ when_word = 'when' #TODO: Make to and when_word load from some config file instead of hardcoded here
61
+ attrs = rtag.attributes
62
+ return_hash = { :to => attrs[to].value }
63
+ attrs.tap { |a| a.delete(to)}
64
+ attrs[release] = rtag.text.downcase == "true" #save release as a boolean
65
+ return_hash[:attrs] = attrs
66
+
67
+ #convert all the attrs beside :to to strings, they are currently Nokogiri::XML::Attr
68
+ (return_hash[:attrs].keys-[to]).each do |a|
69
+ return_hash[:attrs][a] = return_hash[:attrs][a].to_s if a != release
70
+ end
71
+
72
+ return_hash[:attrs][when_word] = Time.parse(return_hash[:attrs][when_word]) #convert when to a datetime
73
+
74
+ return return_hash
75
+ end
34
76
 
35
77
  # helper method to get just the content type tag
36
78
  def content_type_tag
@@ -191,15 +233,7 @@ module Dor
191
233
  # the proposed tag is valid, return it in normalized form. if not, raise an exception with an
192
234
  # explanatory message.
193
235
  def validate_and_normalize_tag(tag_str, existing_tag_list)
194
- tag_arr = split_tag_to_arr(tag_str)
195
-
196
- if tag_arr.length < 2
197
- raise "Invalid tag structure: tag '#{tag_str}' must have at least 2 elements"
198
- end
199
-
200
- if tag_arr.detect {|str| str.empty?}
201
- raise "Invalid tag structure: tag '#{tag_str}' contains empty elements"
202
- end
236
+ tag_arr = validate_tag_format(tag_str)
203
237
 
204
238
  # note that the comparison for duplicate tags is case-insensitive, but we don't change case as part of the normalized version
205
239
  # we return, because we want to preserve the user's intended case.
@@ -211,13 +245,84 @@ module Dor
211
245
 
212
246
  return normalized_tag
213
247
  end
248
+
249
+ #Ensure that an administrative tag meets the proper mininum format
250
+ #
251
+ #@params tag_str [String] the tag
252
+ #
253
+ #@return [Array] the tag split into an array via ':'
254
+ def validate_tag_format(tag_str)
255
+ tag_arr = split_tag_to_arr(tag_str)
256
+
257
+ if tag_arr.length < 2
258
+ raise "Invalid tag structure: tag '#{tag_str}' must have at least 2 elements"
259
+ end
260
+
261
+ if tag_arr.detect {|str| str.empty?}
262
+ raise "Invalid tag structure: tag '#{tag_str}' contains empty elements"
263
+ end
264
+
265
+ return tag_arr
266
+
267
+ end
214
268
 
215
- def add_tag(tag)
269
+ #Add a tag for an item
270
+ #If you are adding just a :tag att
271
+ #
272
+ #@return [String] returned if this function is called with invalid parameters, eg a lack of :who for release_tag
273
+ #@return [Nokogiri::XML::Element] the tag added if successful
274
+ #
275
+ #@raise [RuntimeError] Raised if the tag already exists on the item or the tag is not of the form a:b
276
+ #
277
+ #@params tag [string] The content of the tag
278
+ #@params type [symbol] The type of tag, :tag is assumed as default
279
+ #@params attrs [hash] A hash of any attributes to be placed onto the tag
280
+ # release tag example:
281
+ # item.add_tag(true,:release,{:tag=>'Fitch : Batch2',:what=>'self',:to=>'Searchworks',:who=>'petucket'})
282
+ def add_tag(tag, type=:tag, attrs={})
283
+ needs_timestamp = [:release] #If you want a tag to get a timestamp attribute, add its symbol here
216
284
  identity_metadata_ds = self.identityMetadata
217
- normalized_tag = validate_and_normalize_tag(tag, identity_metadata_ds.tags)
218
- identity_metadata_ds.add_value(:tag, normalized_tag)
285
+ normalized_tag = validate_and_normalize_tag(tag, identity_metadata_ds.tags) if type != :release #Release tags are always boolean, so skip this step
286
+ normalized_tag = tag.to_s if type == :release #just keep the boolean if we have just have a release
287
+
288
+ attrs[:when] = Time.now.utc.iso8601 if needs_timestamp.include? type
289
+
290
+
291
+ if type == :release
292
+ valid_release_attributes_and_tag(tag, attrs)
293
+ attrs[:tag] = normalize_tag_arr(validate_tag_format(attrs[:tag])) if attrs[:tag] != nil #:tag must be a valid administrative tag
294
+ end
295
+
296
+ return identity_metadata_ds.add_value(type, normalized_tag) if attrs == {}
297
+ return identity_metadata_ds.add_value(type, normalized_tag, attrs) if attrs != {}
219
298
  end
220
-
299
+
300
+
301
+ #Determine if the supplied tag is a valid release tag that meets all requirements
302
+ #
303
+ #@raises [RuntimeError] Raises an error of the first fault in the release tag
304
+ #
305
+ #@return [Boolean] Returns true if no errors found
306
+ #
307
+ #@params 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,
308
+ def valid_release_attributes_and_tag(tag, attrs={})
309
+ raise ":when is not iso8601" if attrs[:when].match('\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z') == nil
310
+ [:who, :to, :what].each do |check_attr|
311
+ raise "#{check_attr} not supplied as a String" if attrs[check_attr].class != String
312
+ end
313
+
314
+ what_correct = false
315
+ ['self', 'collection'].each do |allowed_what_value|
316
+ what_correct = true if attrs[:what] == allowed_what_value
317
+ end
318
+ raise ":what must be self or collection" if not what_correct
319
+
320
+ raise "the value set for this tag is not a boolean" if !!tag != tag
321
+ identity_metadata_ds = self.identityMetadata
322
+ validate_tag_format(attrs[:tag]) if attrs[:tag] != nil #Will Raise exception if invalid tag
323
+ return true
324
+ end
325
+
221
326
  def remove_tag(tag)
222
327
  identity_metadata_ds = self.identityMetadata
223
328
  ds_xml = identity_metadata_ds.ng_xml
@@ -15,6 +15,7 @@ module Dor
15
15
  include Contentable
16
16
  include Discoverable
17
17
  include Geoable
18
+ include Releaseable
18
19
 
19
20
  end
20
21
 
@@ -19,9 +19,9 @@ module Dor
19
19
  def build_iiif_manifest pub_obj_doc
20
20
  id = self.pid.split(':').last
21
21
 
22
- lbl_node = pub_obj_doc.at_xpath('/publicObject/identityMetadata/objectLabel')
22
+ lbl_node = pub_obj_doc.at_xpath '//oai_dc:dc/dc:title', DC_NS
23
23
  if lbl_node.nil?
24
- lbl_node = pub_obj_doc.at_xpath '//oai_dc:dc/dc:title', ns
24
+ lbl_node = pub_obj_doc.at_xpath('/publicObject/identityMetadata/objectLabel')
25
25
  end
26
26
  raise "Unable to build IIIF Presentation manifest: No identityMetadata/objectLabel or dc:title" if lbl_node.nil?
27
27
  lbl = lbl_node.text
@@ -37,8 +37,32 @@ module Dor
37
37
  'format' => 'application/mods+xml'
38
38
  }
39
39
  }
40
+ # Use the human copyright statement for attribution if present
41
+ if(cr = pub_obj_doc.at_xpath('/publicObject/rightsMetadata/copyright/human[@type="copyright"]'))
42
+ manifest_data['attribution'] = cr.text
43
+ end
44
+
40
45
  manifest = IIIF::Presentation::Manifest.new manifest_data
41
46
 
47
+ # Set viewingHint to paged if this is a book
48
+ if(pub_obj_doc.at_xpath('/publicObject/contentMetadata[@type="book"]'))
49
+ manifest.viewingHint = "paged"
50
+ end
51
+
52
+ metadata = []
53
+ # make into method, pass in xpath and label
54
+ add_metadata 'Creator', '//oai_dc:dc/dc:creator', metadata, pub_obj_doc
55
+ add_metadata 'Contributor', '//oai_dc:dc/dc:contributor', metadata, pub_obj_doc
56
+ add_metadata 'Publisher', '//oai_dc:dc/dc:publisher', metadata, pub_obj_doc
57
+ add_metadata 'Date', '//oai_dc:dc/dc:date', metadata, pub_obj_doc
58
+
59
+ # Save off the first dc:description without displayLabel
60
+ if(desc = pub_obj_doc.at_xpath('//oai_dc:dc/dc:description[not(@displayLabel)]', DC_NS))
61
+ manifest.description = desc.text
62
+ end
63
+
64
+ manifest.metadata = metadata unless metadata.empty?
65
+
42
66
  seq_data = {
43
67
  '@id' => "#{purl_base_uri}/sequence-1",
44
68
  'label' => 'Current order'
@@ -76,6 +100,14 @@ module Dor
76
100
  'profile' => Dor::Config.stacks.iiif_profile
77
101
  })
78
102
 
103
+ # Use the first image to create a thumbnail on the manifest
104
+ if count == 1
105
+ thumb = IIIF::Presentation::Resource.new
106
+ thumb['@id'] = "#{stacks_uri}/full/400,/0/default.jpg"
107
+ thumb.service = svc
108
+ manifest.thumbnail = thumb
109
+ end
110
+
79
111
  img_res.service = svc
80
112
  anno.resource = img_res
81
113
  canv.images << anno
@@ -85,5 +117,17 @@ module Dor
85
117
  manifest.sequences << sequence
86
118
  manifest.to_json(:pretty => true)
87
119
  end
120
+
121
+ def add_metadata label, xpath, metadata, pub_obj_doc
122
+ nodes = pub_obj_doc.xpath xpath, DC_NS
123
+ nodes.each do |node|
124
+ h = {
125
+ 'label' => label,
126
+ 'value' => node.text
127
+ }
128
+ metadata << h
129
+ end
130
+ end
131
+
88
132
  end
89
133
  end
@@ -32,17 +32,28 @@ module Dor
32
32
  rels_doc
33
33
  end
34
34
 
35
+ #Generate the public .xml for a PURL page.
36
+ #@return [xml] The public xml for the item
37
+ #
35
38
  def public_xml
36
39
  pub = Nokogiri::XML("<publicObject/>").root
37
40
  pub['id'] = pid
38
41
  pub['published'] = Time.now.xmlschema
39
- pub.add_child(self.datastreams['identityMetadata'].ng_xml.root.clone)
42
+ release_xml=Nokogiri(self.generate_release_xml).xpath('//release')
43
+
44
+ im=self.datastreams['identityMetadata'].ng_xml.clone
45
+ im.search('//release').each {|node| node.remove} # remove any <release> tags from public xml which have full history
46
+ im.root.add_child(release_xml) # now add in final <release> tag #TODO: Adding this breaks tests, rework these
47
+
48
+ pub.add_child(im.root) # add in modified identityMetadata datastream
40
49
  pub.add_child(self.datastreams['contentMetadata'].public_xml.root.clone)
41
50
  pub.add_child(self.datastreams['rightsMetadata'].ng_xml.root.clone)
51
+
42
52
  rels = public_relationships.root
43
53
  pub.add_child(rels.clone) unless rels.nil? # TODO: Should never be nil in practice; working around an ActiveFedora quirk for testing
44
54
  pub.add_child(self.generate_dublin_core.root.clone)
45
55
  @public_xml_doc = pub # save this for possible IIIF Presentation manifest
56
+ pub.add_child(Nokogiri(self.generate_release_xml).root.clone) #TODO: Adding this breaks tests, rework these
46
57
  new_pub = Nokogiri::XML(pub.to_xml) { |x| x.noblanks }
47
58
  new_pub.encoding = 'UTF-8'
48
59
  new_pub.to_xml
@@ -0,0 +1,186 @@
1
+ module Dor
2
+ module Releaseable
3
+ extend ActiveSupport::Concern
4
+ include Itemizable
5
+
6
+
7
+ #Generate XML structure for inclusion to Purl
8
+ #
9
+ #@return [String] The XML release node as a string, with ReleaseDigest as the root document
10
+ def generate_release_xml
11
+ builder = Nokogiri::XML::Builder.new do |xml|
12
+ xml.ReleaseDigest {
13
+ self.released_for.each do |project,released_value|
14
+ xml.release(released_value["release"],:to=>project)
15
+ end
16
+ }
17
+ end
18
+ return builder.to_xml
19
+ end
20
+
21
+ #Determine which projects an item is released for
22
+ #
23
+ #@return [Hash] all namespaces in the form of {"Project" => Boolean}
24
+ def released_for
25
+ released_hash = {}
26
+
27
+ #Get release tags on the item itself
28
+ release_tags_on_this_item = self.release_tags
29
+
30
+ #Get any self tags on this item
31
+ self_release_tags = self.get_self_release_tags(release_tags_on_this_item)
32
+
33
+ #Get the most recent self tag for all targets and save their result since most recent self always trumps any other non self tags
34
+ latest_self_tags = self.get_newest_release_tag(self_release_tags)
35
+ latest_self_tags.keys.each do |target|
36
+ released_hash[target] = self.clean_release_tag_for_purl(latest_self_tags[target])
37
+ end
38
+
39
+ #With Self Tags Resolved We Now need to deal with tags on all sets this object is part of
40
+
41
+ potential_applicable_release_tags = {} #This will be where we store all tags that apply, regardless of their timestamp
42
+
43
+ #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
44
+ potential_applicable_release_tags = get_tags_for_what_value(self.get_release_tags_for_item_and_all_governing_sets, 'collection')
45
+
46
+ administrative_tags = self.tags #Get them once here and pass them down
47
+
48
+ #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
49
+ (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
50
+ latest_applicable_tag_for_key = latest_applicable_release_tag_in_array(potential_applicable_release_tags[key], administrative_tags)
51
+ if latest_applicable_tag_for_key != nil #We have a valid tag, record it
52
+ released_hash[key] = self.clean_release_tag_for_purl(latest_applicable_tag_for_key)
53
+ end
54
+
55
+ end
56
+
57
+ return released_hash
58
+ end
59
+
60
+ #Take a hash of tags as obtained via Dor::Item.release_tags and returns all self tags
61
+ #
62
+ #@param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
63
+ #
64
+ #@return [Hash] a hash of self tags for each to value
65
+ def get_self_release_tags(tags)
66
+ return get_tags_for_what_value(tags, 'self')
67
+ end
68
+
69
+ #Take an item and get all of its release tags and all tags on collections it is a member of it
70
+ #
71
+ #
72
+ #@return [Hash] a hash of all tags
73
+ def get_release_tags_for_item_and_all_governing_sets
74
+ return_tags = self.release_tags || {}
75
+ self.collections.each do |collection|
76
+ 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
77
+ end
78
+ return return_tags
79
+ end
80
+
81
+ #Take two hashes of tags and combine them, will not overwrite but will enforce uniqueness of the tags
82
+ #
83
+ #@param hash_one [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
84
+ #@param hash_two [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
85
+ #
86
+ #@return [Hash] the combined hash with uniquiness enforced
87
+ def combine_two_release_tag_hashes(hash_one, hash_two)
88
+ hash_two.keys.each do |key|
89
+ hash_one[key] = hash_two[key] if hash_one[key] == nil
90
+ hash_one[key] = (hash_one[key] + hash_two[key]).uniq if hash_one[key] != nil
91
+ end
92
+ return hash_one
93
+ end
94
+
95
+ #Take a hash of tags and return all tags with the matching what target
96
+ #
97
+ #@param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
98
+ #@param what_target [String] the target for the 'what' key, self or collection
99
+ #
100
+ #@return [Hash] a hash of self tags for each to value
101
+ def get_tags_for_what_value(tags, what_target)
102
+ return_hash = {}
103
+ tags.keys.each do |key|
104
+ self_tags = tags[key].select{|tag| tag['what'] == what_target.downcase}
105
+ return_hash[key] = self_tags if self_tags.size > 0
106
+ end
107
+ return return_hash
108
+ end
109
+
110
+ #Take a hash of tags as obtained via Dor::Item.release_tags and returns the newest tag for each namespace
111
+ #
112
+ #@params tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
113
+ #
114
+ #@return [Hash] a hash of latest tags for each to value
115
+ def get_newest_release_tag(tags)
116
+ return_hash = {}
117
+ tags.keys.each do |key|
118
+ latest_for_key = newest_release_tag_in_an_array(tags[key])
119
+ return_hash[key] = latest_for_key
120
+ end
121
+ return return_hash
122
+ end
123
+
124
+ #Take a tag and return only the attributes we want to put into purl
125
+ #
126
+ #@param tag [Hash] a tag
127
+ #
128
+ #@return [Hash] a hash of the attributes we want for purl
129
+ def clean_release_tag_for_purl(tag)
130
+ for_purl = ['release']
131
+ return_hash = {}
132
+ for_purl.each do |attr|
133
+ return_hash[attr] = tag[attr]
134
+ end
135
+ return return_hash
136
+ end
137
+
138
+ #Takes an array of release tags and returns the most recent one
139
+ #
140
+ #@params tags [Array] an array of hashes, with the hashes being release tags
141
+ #
142
+ #@return [Hash] the most recent tag
143
+ def newest_release_tag_in_an_array(array_of_tags)
144
+ latest_tag_in_array = array_of_tags[0] || {}
145
+ array_of_tags.each do |tag|
146
+ latest_tag_in_array = tag if tag['when'] > latest_tag_in_array['when']
147
+ end
148
+ return latest_tag_in_array
149
+ end
150
+
151
+
152
+ #Takes a tag and returns true or false if it applies to the specific item
153
+ #
154
+ #@param release_tag [Hash] the tag in a hashed form
155
+ #@param Optional admin_tags [Array] the administrative tags on an item, if not supplied it will attempt to retrieve them
156
+ #
157
+ #@return [Boolean] true or false if it applies (not true or false if it is released, that is the release_tag data)
158
+ def does_release_tag_apply(release_tag, admin_tags=false)
159
+ #Is the tag global or restricted
160
+ 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
161
+
162
+ admin_tags = self.tags if not 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
163
+ return admin_tags.include?(release_tag['tag'])
164
+ end
165
+
166
+ #Takes an array of release tags and returns the most recent one that applies to this item
167
+ #
168
+ #@param release_tags [Array] an array of release tags in hashed form
169
+ #param admin_tags [Array] the administrative tags on an on item
170
+ #
171
+ #@return [Hash] the tag
172
+ def latest_applicable_release_tag_in_array(release_tags, admin_tags)
173
+ newest_tag = newest_release_tag_in_an_array(release_tags)
174
+ return newest_tag if does_release_tag_apply(newest_tag, admin_tags) #Return true if we have it
175
+
176
+ #The latest tag wasn't applicable, slice it off and try again
177
+ #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
178
+ release_tags.slice!(release_tags.index(newest_tag))
179
+
180
+ 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
181
+
182
+ return nil #We're out of tags, no applicable ones
183
+ end
184
+
185
+ end
186
+ end
data/lib/dor/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dor
2
- VERSION = '4.16.0'
2
+ VERSION = '4.17.0'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dor-services
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.16.0
4
+ version: 4.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Klein
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2015-01-16 00:00:00.000000000 Z
15
+ date: 2015-01-23 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: active-fedora
@@ -506,6 +506,7 @@ files:
506
506
  - config/dev_console_env.rb
507
507
  - config/dev_console_env.rb.example
508
508
  - config/environments/development.rb
509
+ - config/environments/development.rb.old
509
510
  - config/environments/test.rb
510
511
  - config/predicate_mappings.yml
511
512
  - lib/dor-services.rb
@@ -554,6 +555,7 @@ files:
554
555
  - lib/dor/models/preservable.rb
555
556
  - lib/dor/models/processable.rb
556
557
  - lib/dor/models/publishable.rb
558
+ - lib/dor/models/releaseable.rb
557
559
  - lib/dor/models/set.rb
558
560
  - lib/dor/models/shelvable.rb
559
561
  - lib/dor/models/upgradable.rb