moab-versioning 4.2.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,4 @@
1
1
  module Serializer
2
-
3
2
  # Subclass of {Serializable} that adds methods for marshalling/unmarshalling data
4
3
  # to a persistent XML file format.
5
4
  #
@@ -11,13 +10,12 @@ module Serializer
11
10
  # @note Copyright (c) 2012 by The Board of Trustees of the Leland Stanford Junior University.
12
11
  # All rights reserved. See {file:LICENSE.rdoc} for details.
13
12
  class Manifest < Serializer::Serializable
14
-
15
13
  include HappyMapper
16
14
 
17
15
  # @api internal
18
16
  # @param filename [String] Optional filename if one wishes to override the default filename
19
17
  # @return [String] Returns the standard filename (derived from the class name) to be used for serializing an object
20
- def self.xml_filename(filename=nil)
18
+ def self.xml_filename(filename = nil)
21
19
  if filename
22
20
  filename
23
21
  else
@@ -30,7 +28,7 @@ module Serializer
30
28
  # @param parent_dir [Pathname,String] The location of the directory in which the xml file is located
31
29
  # @param filename [String] Optional filename if one wishes to override the default filename
32
30
  # @return [Pathname] The location of the xml file
33
- def self.xml_pathname(parent_dir, filename=nil)
31
+ def self.xml_pathname(parent_dir, filename = nil)
34
32
  Pathname.new(parent_dir).join(self.xml_filename(filename))
35
33
  end
36
34
 
@@ -38,7 +36,7 @@ module Serializer
38
36
  # @param parent_dir [Pathname,String] The location of the directory in which the xml file is located
39
37
  # @param filename [String] Optional filename if one wishes to override the default filename
40
38
  # @return [Boolean] Returns true if the xml file exists
41
- def self.xml_pathname_exist?(parent_dir, filename=nil)
39
+ def self.xml_pathname_exist?(parent_dir, filename = nil)
42
40
  self.xml_pathname(parent_dir, filename).exist?
43
41
  end
44
42
 
@@ -47,7 +45,7 @@ module Serializer
47
45
  # @param filename [String] Optional filename if one wishes to override the default filename
48
46
  # @return [Serializable] Read the xml file and return the parsed XML
49
47
  # @example {include:file:spec/features/serializer/read_xml_spec.rb}
50
- def self.read_xml_file(parent_dir, filename=nil)
48
+ def self.read_xml_file(parent_dir, filename = nil)
51
49
  self.parse(self.xml_pathname(parent_dir, filename).read)
52
50
  end
53
51
 
@@ -56,7 +54,7 @@ module Serializer
56
54
  # @param parent_dir [Pathname,String] The location of the directory in which the xml file is located
57
55
  # @param filename [String] Optional filename if one wishes to override the default filename
58
56
  # @return [void] Serializize the in-memory object to a xml file instance
59
- def self.write_xml_file(xml_object, parent_dir, filename=nil)
57
+ def self.write_xml_file(xml_object, parent_dir, filename = nil)
60
58
  parent_dir.mkpath
61
59
  self.xml_pathname(parent_dir, filename).open('w') do |f|
62
60
  xmlBuilder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8')
@@ -71,10 +69,8 @@ module Serializer
71
69
  # @param filename [String] Optional filename if one wishes to override the default filename
72
70
  # @return [void] Serializize the in-memory object to a xml file instance
73
71
  # @example {include:file:spec/features/serializer/write_xml_spec.rb}
74
- def write_xml_file(parent_dir, filename=nil)
72
+ def write_xml_file(parent_dir, filename = nil)
75
73
  self.class.write_xml_file(self, parent_dir, filename)
76
74
  end
77
-
78
75
  end
79
-
80
76
  end
@@ -1,5 +1,4 @@
1
1
  module Serializer
2
-
3
2
  # Some utility methods to faciliate serialization of data fields to Hash, JSON, or YAML shared by all subclasses.
4
3
  # This class assumes that HappyMapper is used for declaration of fields to be serialized.
5
4
  #
@@ -11,7 +10,6 @@ module Serializer
11
10
  # @note Copyright (c) 2012 by The Board of Trustees of the Leland Stanford Junior University.
12
11
  # All rights reserved. See {file:LICENSE.rdoc} for details.
13
12
  class Serializable
14
-
15
13
  include HappyMapper
16
14
 
17
15
  # A flexible initializer based on the DataMapper "create factory" design pattern.
@@ -19,7 +17,7 @@ module Serializer
19
17
  # @see Serializable#initialize
20
18
  # @param opts [Hash<Symbol,Object>] a hash containing any number of symbol => value pairs.
21
19
  # The symbols should correspond to attributes declared using HappyMapper syntax
22
- def initialize(opts={})
20
+ def initialize(opts = {})
23
21
  opts.each do |key, value|
24
22
  if variable_names.include?(key.to_s) || key == :test
25
23
  instance_variable_set("@#{key}", value)
@@ -47,7 +45,7 @@ module Serializer
47
45
  # @api internal
48
46
  # @return [Array] Extract the names of the variables
49
47
  def variable_names
50
- variables.collect { |variable| variable.name}
48
+ variables.collect { |variable| variable.name }
51
49
  end
52
50
 
53
51
  # @api internal
@@ -80,12 +78,12 @@ module Serializer
80
78
  # @return [Hash] Generate a hash from an array of objects.
81
79
  # If the array member has a field tagged as a key, that field will be used as the hash.key.
82
80
  # Otherwise the index position of the array member will be used as the key
83
- def array_to_hash(array,summary=false)
81
+ def array_to_hash(array, summary = false)
84
82
  item_hash = Hash.new
85
83
  array.each_index do |index|
86
84
  item = array[index]
87
- ikey = (item.respond_to?(:key) && item.key) ? item.key : index
88
- item_hash[ikey] = item.respond_to?(:to_hash) ? item.to_hash(summary) : item
85
+ ikey = (item.respond_to?(:key) && item.key) ? item.key : index
86
+ item_hash[ikey] = item.respond_to?(:to_hash) ? item.to_hash(summary) : item
89
87
  end
90
88
  item_hash
91
89
  end
@@ -93,19 +91,19 @@ module Serializer
93
91
  # @api internal
94
92
  # @return [Hash] Recursively generate an Hash containing the object's properties
95
93
  # @param summary [Boolean] Controls the depth and detail of recursion
96
- def to_hash(summary=false)
94
+ def to_hash(summary = false)
97
95
  oh = Hash.new
98
- vars = summary ? variables.select{|v| summary_fields.include?(v.name)} : variables
96
+ vars = summary ? variables.select { |v| summary_fields.include?(v.name) } : variables
99
97
  vars.each do |variable|
100
98
  key = variable.name.to_s
101
99
  value = self.send(variable.name)
102
100
  case value
103
- when Array
104
- oh[key] = array_to_hash(value,summary)
105
- when Serializable
106
- oh[key] = value.to_hash
107
- else
108
- oh[key] = value
101
+ when Array
102
+ oh[key] = array_to_hash(value, summary)
103
+ when Serializable
104
+ oh[key] = value.to_hash
105
+ else
106
+ oh[key] = value
109
107
  end
110
108
  end
111
109
  oh
@@ -113,7 +111,7 @@ module Serializer
113
111
 
114
112
  # @return [Hash] Calls to_hash(summary=true)
115
113
  def summary
116
- self.to_hash(summary=true)
114
+ self.to_hash(summary = true)
117
115
  end
118
116
 
119
117
  # @api internal
@@ -141,12 +139,12 @@ module Serializer
141
139
  def Serializable.deep_diff(*hashes)
142
140
  diff = Hash.new
143
141
  case hashes.length
144
- when 4
145
- ltag, left, rtag, right = hashes
146
- when 2
147
- ltag, left, rtag, right = :left, hashes[0], :right, hashes[1]
148
- else
149
- raise ArgumentError, "wrong number of arguments (#{hashes.length} for 2 or 4)"
142
+ when 4
143
+ ltag, left, rtag, right = hashes
144
+ when 2
145
+ ltag, left, rtag, right = :left, hashes[0], :right, hashes[1]
146
+ else
147
+ raise ArgumentError, "wrong number of arguments (#{hashes.length} for 2 or 4)"
150
148
  end
151
149
  (left.keys | right.keys).each do |k|
152
150
  if left[k] != right[k]
@@ -162,17 +160,15 @@ module Serializer
162
160
 
163
161
  # @api internal
164
162
  # @return [String] Generate JSON output from a hash of the object's variables
165
- def to_json(summary=false)
166
- hash=self.to_hash(summary)
163
+ def to_json(summary = false)
164
+ hash = self.to_hash(summary)
167
165
  JSON.pretty_generate(hash)
168
166
  end
169
167
 
170
168
  # @api internal
171
169
  # @return [String] Generate YAML output from a hash of the object's variables
172
- def to_yaml(summary=false)
170
+ def to_yaml(summary = false)
173
171
  self.to_hash(summary).to_yaml
174
172
  end
175
-
176
173
  end
177
-
178
174
  end
@@ -1,7 +1,6 @@
1
1
  require 'moab/stanford'
2
2
 
3
3
  module Stanford
4
-
5
4
  # Utility Class for extracting content or other information from a Fedora Instance
6
5
  #
7
6
  # ====Data Model
@@ -12,7 +11,6 @@ module Stanford
12
11
  # @note Copyright (c) 2012 by The Board of Trustees of the Leland Stanford Junior University.
13
12
  # All rights reserved. See {file:LICENSE.rdoc} for details.
14
13
  class ActiveFedoraObject
15
-
16
14
  # @param fedora_object [Object] The Active Fedora representation of the Fedora Object
17
15
  # @return [Stanford::ActiveFedoraObject] Create a u
18
16
  def initialize(fedora_object)
@@ -28,7 +26,5 @@ module Stanford
28
26
  def get_datastream_content(ds_id)
29
27
  @fedora_object.datastreams[ds_id].content
30
28
  end
31
-
32
29
  end
33
-
34
30
  end
@@ -1,7 +1,6 @@
1
1
  require 'moab/stanford'
2
2
 
3
3
  module Stanford
4
-
5
4
  # Stanford-specific utility methods for transforming contentMetadata to versionInventory and doing comparisons
6
5
  #
7
6
  # ====Data Model
@@ -12,20 +11,19 @@ module Stanford
12
11
  # @note Copyright (c) 2012 by The Board of Trustees of the Leland Stanford Junior University.
13
12
  # All rights reserved. See {file:LICENSE.rdoc} for details.
14
13
  class ContentInventory
15
-
16
14
  # @param content_metadata [String] The content metadata to be transformed into a versionInventory
17
15
  # @param object_id [String] The identifier of the digital object
18
16
  # @param subset [String] Speciifes which subset of files to list (all|preserve|publish|shelve)
19
17
  # @param version_id [Integer] The ID of the version whosen content metadata is to be transformed
20
18
  # @return [FileInventory] The versionInventory equivalent of the contentMetadata
21
19
  # if the supplied content_metadata is blank or empty, then a skeletal FileInventory will be returned
22
- def inventory_from_cm(content_metadata, object_id, subset, version_id=nil)
20
+ def inventory_from_cm(content_metadata, object_id, subset, version_id = nil)
23
21
  # The contentMetadata datastream is not required for ingest, since some object types, such as collection
24
22
  # or APO do not require one.
25
23
  # Many of these objects have contentMetadata with no child elements, such as this:
26
24
  # <contentMetadata objectId="bd608mj3166" type="file"/>
27
25
  # but there are also objects that have no datasteam of this name at all
28
- cm_inventory = Moab::FileInventory.new(:type=>"version",:digital_object_id=>object_id, :version_id=>version_id)
26
+ cm_inventory = Moab::FileInventory.new(:type => "version", :digital_object_id => object_id, :version_id => version_id)
29
27
  content_group = group_from_cm(content_metadata, subset)
30
28
  cm_inventory.groups << content_group
31
29
  cm_inventory
@@ -40,18 +38,18 @@ module Stanford
40
38
  ng_doc = Nokogiri::XML(content_metadata)
41
39
  validate_content_metadata(ng_doc)
42
40
  nodeset = case subset.to_s.downcase
43
- when 'preserve'
44
- ng_doc.xpath("//file[@preserve='yes']")
45
- when 'publish'
46
- ng_doc.xpath("//file[@publish='yes']")
47
- when 'shelve'
48
- ng_doc.xpath("//file[@shelve='yes']")
49
- when 'all'
50
- ng_doc.xpath("//file")
51
- else
52
- raise "Unknown disposition subset (#{subset})"
53
- end
54
- content_group = Moab::FileGroup.new(:group_id=>'content', :data_source => "contentMetadata-#{subset}")
41
+ when 'preserve'
42
+ ng_doc.xpath("//file[@preserve='yes']")
43
+ when 'publish'
44
+ ng_doc.xpath("//file[@publish='yes']")
45
+ when 'shelve'
46
+ ng_doc.xpath("//file[@shelve='yes']")
47
+ when 'all'
48
+ ng_doc.xpath("//file")
49
+ else
50
+ raise "Unknown disposition subset (#{subset})"
51
+ end
52
+ content_group = Moab::FileGroup.new(:group_id => 'content', :data_source => "contentMetadata-#{subset}")
55
53
  nodeset.each do |file_node|
56
54
  signature = generate_signature(file_node)
57
55
  instance = generate_instance(file_node)
@@ -69,12 +67,12 @@ module Stanford
69
67
  checksum_nodes = node.xpath('checksum')
70
68
  checksum_nodes.each do |checksum_node|
71
69
  case checksum_node.attributes['type'].content.upcase
72
- when 'MD5'
73
- signature.md5 = checksum_node.text
74
- when 'SHA1', 'SHA-1'
75
- signature.sha1 = checksum_node.text
76
- when 'SHA256', 'SHA-256'
77
- signature.sha256 = checksum_node.text
70
+ when 'MD5'
71
+ signature.md5 = checksum_node.text
72
+ when 'SHA1', 'SHA-1'
73
+ signature.sha1 = checksum_node.text
74
+ when 'SHA256', 'SHA-256'
75
+ signature.sha256 = checksum_node.text
78
76
  end
79
77
  end
80
78
  signature
@@ -96,22 +94,23 @@ module Stanford
96
94
  # @example {include:file:spec/features/stanford/content_metadata_write_spec.rb}
97
95
  def generate_content_metadata(file_group, object_id, version_id)
98
96
  cm = Nokogiri::XML::Builder.new do |xml|
99
- xml.contentMetadata(:type=>"sample", :objectId=>object_id) {
100
- xml.resource(:type=>"version", :sequence=>"1", :id=>"version-#{version_id}") {
97
+ xml.contentMetadata(:type => "sample", :objectId => object_id) {
98
+ xml.resource(:type => "version", :sequence => "1", :id => "version-#{version_id}") {
101
99
  file_group.files.each do |file_manifestation|
102
100
  signature = file_manifestation.signature
103
101
  file_manifestation.instances.each do |instance|
104
102
  xml.file(
105
- :id=>instance.path,
106
- :size=>signature.size,
107
- :datetime=>instance.datetime,
108
- :shelve=>'yes',
109
- :publish=>'yes',
110
- :preserve=>'yes') {
103
+ :id => instance.path,
104
+ :size => signature.size,
105
+ :datetime => instance.datetime,
106
+ :shelve => 'yes',
107
+ :publish => 'yes',
108
+ :preserve => 'yes'
109
+ ) {
111
110
  fixity = signature.fixity
112
- xml.checksum(:type=>"MD5") {xml.text signature.md5 } if fixity[:md5]
113
- xml.checksum(:type=>"SHA-1") {xml.text signature.sha1} if fixity[:sha1]
114
- xml.checksum(:type=>"SHA-256") {xml.text signature.sha256} if fixity[:sha256]
111
+ xml.checksum(:type => "MD5") { xml.text signature.md5 } if fixity[:md5]
112
+ xml.checksum(:type => "SHA-1") { xml.text signature.sha1 } if fixity[:sha1]
113
+ xml.checksum(:type => "SHA-256") { xml.text signature.sha256 } if fixity[:sha256]
115
114
  }
116
115
  end
117
116
  end
@@ -125,7 +124,7 @@ module Stanford
125
124
  # @return [Boolean] True if contentMetadata has essential file attributes, else raise exception
126
125
  def validate_content_metadata(content_metadata)
127
126
  result = validate_content_metadata_details(content_metadata)
128
- raise Moab::InvalidMetadataException, result[0]+" ..." if result.size > 0
127
+ raise Moab::InvalidMetadataException, result[0] + " ..." if result.size > 0
129
128
  true
130
129
  end
131
130
 
@@ -135,27 +134,27 @@ module Stanford
135
134
  result = []
136
135
  content_metadata_doc =
137
136
  case content_metadata.class.name
138
- when "String"
139
- Nokogiri::XML(content_metadata)
140
- when "Pathname"
141
- Nokogiri::XML(content_metadata.read)
142
- when "Nokogiri::XML::Document"
143
- content_metadata
144
- else
145
- raise Moab::InvalidMetadataException, "Content Metadata is in unrecognized format"
146
- end
137
+ when "String"
138
+ Nokogiri::XML(content_metadata)
139
+ when "Pathname"
140
+ Nokogiri::XML(content_metadata.read)
141
+ when "Nokogiri::XML::Document"
142
+ content_metadata
143
+ else
144
+ raise Moab::InvalidMetadataException, "Content Metadata is in unrecognized format"
145
+ end
147
146
  nodeset = content_metadata_doc.xpath("//file")
148
147
  nodeset.each do |file_node|
149
- missing = ['id', 'size','md5','sha1']
148
+ missing = ['id', 'size', 'md5', 'sha1']
150
149
  missing.delete('id') if file_node.has_attribute?('id')
151
150
  missing.delete('size') if file_node.has_attribute?('size')
152
151
  checksum_nodes = file_node.xpath('checksum')
153
152
  checksum_nodes.each do |checksum_node|
154
153
  case checksum_node.attributes['type'].content.upcase
155
- when 'MD5'
156
- missing.delete('md5')
157
- when 'SHA1', 'SHA-1'
158
- missing.delete('sha1')
154
+ when 'MD5'
155
+ missing.delete('md5')
156
+ when 'SHA1', 'SHA-1'
157
+ missing.delete('sha1')
159
158
  end
160
159
  end
161
160
  if missing.include?('id')
@@ -214,14 +213,14 @@ module Stanford
214
213
  # add new <checksum> elements for the other checksum types that were missing
215
214
  @names_for_type.each do |type, names|
216
215
  unless checksum_nodes.has_key?(type)
217
- checksum_node = Nokogiri::XML::Element.new('checksum',file_node.document)
216
+ checksum_node = Nokogiri::XML::Element.new('checksum', file_node.document)
218
217
  checksum_node['type'] = names[0]
219
218
  file_node << checksum_node
220
219
  checksum_nodes[type] = checksum_node
221
220
  end
222
221
  end
223
222
  # make sure the <checksum> element has a content value
224
- checksum_nodes.each do |type,checksum_node|
223
+ checksum_nodes.each do |type, checksum_node|
225
224
  cm_checksum = checksum_node.content
226
225
  sig_checksum = signature.checksums[type]
227
226
  if cm_checksum.nil? or cm_checksum.empty?
@@ -231,7 +230,5 @@ module Stanford
231
230
  end
232
231
  end
233
232
  end
234
-
235
233
  end
236
-
237
234
  end
@@ -1,7 +1,6 @@
1
1
  require 'moab/stanford'
2
2
 
3
3
  module Stanford
4
-
5
4
  # Stanford-specific utility methods for interfacing with DOR metadata files
6
5
  #
7
6
  # ====Data Model
@@ -12,7 +11,6 @@ module Stanford
12
11
  # @note Copyright (c) 2012 by The Board of Trustees of the Leland Stanford Junior University.
13
12
  # All rights reserved. See {file:LICENSE.rdoc} for details.
14
13
  class DorMetadata
15
-
16
14
  # @return [String] The digital object identifier (druid)
17
15
  attr_accessor :digital_object_id
18
16
 
@@ -22,7 +20,7 @@ module Stanford
22
20
  # @param digital_object_id [String] The digital object identifier
23
21
  # @param version_id [Integer] The ordinal version number
24
22
  # @return [Stanford::DorMetadata]
25
- def initialize(digital_object_id, version_id=nil)
23
+ def initialize(digital_object_id, version_id = nil)
26
24
  @digital_object_id = digital_object_id
27
25
  @version_id = version_id
28
26
  end
@@ -31,16 +29,15 @@ module Stanford
31
29
  # @param directory [String] The location of the directory to be inventoried
32
30
  # @param version_id (see #initialize)
33
31
  # @return [FileInventory] Inventory of the files under the specified directory
34
- def inventory_from_directory(directory, version_id=nil)
32
+ def inventory_from_directory(directory, version_id = nil)
35
33
  version_id ||= @version_id
36
34
  version_inventory = Moab::FileInventory.new(type: 'version', digital_object_id: @digital_object_id, version_id: version_id)
37
- content_metadata = IO.read(File.join(directory,'contentMetadata.xml'))
38
- content_group = Stanford::ContentInventory.new.group_from_cm(content_metadata, 'preserve' )
35
+ content_metadata = IO.read(File.join(directory, 'contentMetadata.xml'))
36
+ content_group = Stanford::ContentInventory.new.group_from_cm(content_metadata, 'preserve')
39
37
  version_inventory.groups << content_group
40
- metadata_group = Moab::FileGroup.new(:group_id=>'metadata').group_from_directory(directory)
38
+ metadata_group = Moab::FileGroup.new(:group_id => 'metadata').group_from_directory(directory)
41
39
  version_inventory.groups << metadata_group
42
40
  version_inventory
43
41
  end
44
42
  end
45
-
46
43
  end
@@ -3,12 +3,11 @@ require 'moab'
3
3
  module Stanford
4
4
  # druids are Stanford specific entities
5
5
  class StorageObjectValidator < Moab::StorageObjectValidator
6
-
7
6
  # TODO: test to make sure constants don't collide on underlying int vals?
8
7
  # keep from stepping on previously defined error code constants.
9
8
  DRUID_MISMATCH = superclass.error_code_to_messages.keys.max + 1
10
9
 
11
- def validation_errors(allow_content_subdirs=true)
10
+ def validation_errors(allow_content_subdirs = true)
12
11
  errors = []
13
12
  errors.concat super(allow_content_subdirs)
14
13
  errors.concat(identify_druid) if errors.empty?