dor-services 5.2.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/config/certs/robots-dor-dev.crt +29 -0
- data/config/certs/robots-dor-dev.key +27 -0
- data/config/config_defaults.yml +2 -0
- data/config/dev_console_env.rb +77 -0
- data/lib/dor-services.rb +31 -27
- data/lib/dor/config.rb +25 -19
- data/lib/dor/datastreams/administrative_metadata_ds.rb +19 -20
- data/lib/dor/datastreams/content_metadata_ds.rb +238 -177
- data/lib/dor/datastreams/datastream_spec_solrizer.rb +1 -1
- data/lib/dor/datastreams/default_object_rights_ds.rb +99 -16
- data/lib/dor/datastreams/desc_metadata_ds.rb +37 -34
- data/lib/dor/datastreams/embargo_metadata_ds.rb +16 -16
- data/lib/dor/datastreams/events_ds.rb +2 -2
- data/lib/dor/datastreams/geo_metadata_ds.rb +5 -10
- data/lib/dor/datastreams/identity_metadata_ds.rb +22 -22
- data/lib/dor/datastreams/rights_metadata_ds.rb +43 -32
- data/lib/dor/datastreams/role_metadata_ds.rb +5 -5
- data/lib/dor/datastreams/simple_dublin_core_ds.rb +13 -14
- data/lib/dor/datastreams/version_metadata_ds.rb +22 -23
- data/lib/dor/datastreams/workflow_definition_ds.rb +15 -15
- data/lib/dor/datastreams/workflow_ds.rb +64 -70
- data/lib/dor/exceptions.rb +0 -1
- data/lib/dor/migrations/identifiable/uriify_augmented_contentlocation_refs.rb +4 -4
- data/lib/dor/migrations/processable/unify_workflows.rb +1 -1
- data/lib/dor/models/admin_policy_object.rb +4 -4
- data/lib/dor/models/assembleable.rb +2 -3
- data/lib/dor/models/collection.rb +1 -1
- data/lib/dor/models/contentable.rb +113 -108
- data/lib/dor/models/describable.rb +136 -95
- data/lib/dor/models/editable.rb +205 -119
- data/lib/dor/models/embargoable.rb +16 -16
- data/lib/dor/models/eventable.rb +2 -2
- data/lib/dor/models/geoable.rb +3 -3
- data/lib/dor/models/governable.rb +25 -26
- data/lib/dor/models/identifiable.rb +66 -55
- data/lib/dor/models/item.rb +0 -1
- data/lib/dor/models/itemizable.rb +7 -8
- data/lib/dor/models/preservable.rb +7 -8
- data/lib/dor/models/processable.rb +76 -73
- data/lib/dor/models/publishable.rb +25 -30
- data/lib/dor/models/releaseable.rb +118 -155
- data/lib/dor/models/rightsable.rb +2 -3
- data/lib/dor/models/set.rb +1 -1
- data/lib/dor/models/shelvable.rb +8 -10
- data/lib/dor/models/upgradable.rb +5 -6
- data/lib/dor/models/versionable.rb +3 -4
- data/lib/dor/models/workflow_object.rb +15 -16
- data/lib/dor/services/cleanup_reset_service.rb +15 -16
- data/lib/dor/services/cleanup_service.rb +2 -4
- data/lib/dor/services/digital_stacks_service.rb +10 -13
- data/lib/dor/services/merge_service.rb +8 -9
- data/lib/dor/services/metadata_handlers/catalog_handler.rb +1 -1
- data/lib/dor/services/metadata_handlers/mdtoolkit_handler.rb +3 -3
- data/lib/dor/services/metadata_service.rb +19 -20
- data/lib/dor/services/registration_service.rb +80 -61
- data/lib/dor/services/reset_workspace_service.rb +6 -10
- data/lib/dor/services/sdr_ingest_service.rb +15 -16
- data/lib/dor/services/search_service.rb +18 -23
- data/lib/dor/services/suri_service.rb +6 -6
- data/lib/dor/services/technical_metadata_service.rb +27 -44
- data/lib/dor/utils/ng_tidy.rb +3 -3
- data/lib/dor/utils/sdr_client.rb +2 -3
- data/lib/dor/utils/solr_doc_helper.rb +1 -3
- data/lib/dor/version.rb +1 -1
- data/lib/dor/workflow/document.rb +43 -40
- data/lib/dor/workflow/graph.rb +26 -26
- data/lib/dor/workflow/process.rb +34 -35
- data/lib/tasks/rdoc.rake +5 -5
- metadata +129 -111
- data/lib/dor/models/presentable.rb +0 -146
@@ -1,7 +1,6 @@
|
|
1
1
|
module Dor
|
2
2
|
class ContentMetadataDS < ActiveFedora::OmDatastream
|
3
3
|
include Upgradable
|
4
|
-
include SolrDocHelper
|
5
4
|
|
6
5
|
set_terminology do |t|
|
7
6
|
t.root :path => 'contentMetadata', :index_as => [:not_searchable]
|
@@ -9,7 +8,7 @@ module Dor
|
|
9
8
|
t.stacks :path => '/contentMetadata/@stacks', :index_as => [:not_searchable]
|
10
9
|
t.resource(:index_as => [:not_searchable]) do
|
11
10
|
t.id_ :path => { :attribute => 'id' }
|
12
|
-
t.sequence :path => { :attribute => 'sequence' }
|
11
|
+
t.sequence :path => { :attribute => 'sequence' } # , :data_type => :integer
|
13
12
|
t.type_ :path => { :attribute => 'type' }, :index_as => [:displayable]
|
14
13
|
t.attribute(:path => 'attr', :index_as => [:not_searchable]) do
|
15
14
|
t.name :path => { :attribute => 'name' }, :index_as => [:not_searchable]
|
@@ -18,36 +17,121 @@ module Dor
|
|
18
17
|
t.id_ :path => { :attribute => 'id' }
|
19
18
|
t.mimeType :path => { :attribute => 'mimeType' }, :index_as => [:displayable]
|
20
19
|
t.dataType :path => { :attribute => 'dataType' }, :index_as => [:displayable]
|
21
|
-
t.size :path => { :attribute => 'size' }, :index_as => [:displayable]
|
22
|
-
t.shelve :path => { :attribute => 'shelve' }, :index_as => [:not_searchable]
|
23
|
-
t.publish :path => { :attribute => 'publish' }, :index_as => [:not_searchable]
|
24
|
-
t.preserve :path => { :attribute => 'preserve' }, :index_as => [:not_searchable]
|
20
|
+
t.size :path => { :attribute => 'size' }, :index_as => [:displayable] # , :data_type => :long
|
21
|
+
t.shelve :path => { :attribute => 'shelve' }, :index_as => [:not_searchable] # , :data_type => :boolean
|
22
|
+
t.publish :path => { :attribute => 'publish' }, :index_as => [:not_searchable] # , :data_type => :boolean
|
23
|
+
t.preserve :path => { :attribute => 'preserve' }, :index_as => [:not_searchable] # , :data_type => :boolean
|
25
24
|
t.checksum do
|
26
25
|
t.type_ :path => { :attribute => 'type' }
|
27
26
|
end
|
28
27
|
end
|
29
|
-
t.shelved_file(:path => 'file', :attributes => {:shelve=>'yes'}, :index_as => [:not_searchable]) do
|
28
|
+
t.shelved_file(:path => 'file', :attributes => {:shelve => 'yes'}, :index_as => [:not_searchable]) do
|
30
29
|
t.id_ :path => { :attribute => 'id' }, :index_as => [:displayable, :stored_searchable]
|
31
30
|
end
|
32
31
|
end
|
33
32
|
t.shelved_file_id :proxy => [:resource, :shelved_file, :id], :index_as => [:displayable, :stored_searchable]
|
34
33
|
end
|
35
34
|
|
35
|
+
### READ ONLY METHODS
|
36
|
+
|
37
|
+
# @return [Nokogiri::XML::Document] sanitized for public consumption
|
36
38
|
def public_xml
|
37
|
-
result =
|
38
|
-
result.xpath('/contentMetadata/resource[not(file[(@deliver="yes" or @publish="yes")])]' ).each
|
39
|
-
result.xpath('/contentMetadata/resource/file[not(@deliver="yes" or @publish="yes")]' ).each
|
40
|
-
result.xpath('/contentMetadata/resource/file').xpath('@preserve|@shelve|@publish|@deliver').each
|
41
|
-
result.xpath('/contentMetadata/resource/file/checksum' ).each
|
39
|
+
result = ng_xml.clone
|
40
|
+
result.xpath('/contentMetadata/resource[not(file[(@deliver="yes" or @publish="yes")])]' ).each(&:remove)
|
41
|
+
result.xpath('/contentMetadata/resource/file[not(@deliver="yes" or @publish="yes")]' ).each(&:remove)
|
42
|
+
result.xpath('/contentMetadata/resource/file').xpath('@preserve|@shelve|@publish|@deliver').each(&:remove)
|
43
|
+
result.xpath('/contentMetadata/resource/file/checksum' ).each(&:remove)
|
42
44
|
result
|
43
45
|
end
|
46
|
+
|
47
|
+
# Only use this when you want the behavior of raising an exception if anything besides exactly one matching node
|
48
|
+
# is found. Otherwise just use .xpath, .at_xpath or .search.
|
49
|
+
# @param xpath [String] accessor invocation for Nokogiri xpath
|
50
|
+
# @return [Nokogiri::XML::Element] the matched element
|
51
|
+
def singular_node(xpath)
|
52
|
+
node = ng_xml.search(xpath)
|
53
|
+
len = node.length
|
54
|
+
raise "#{xpath} not found" if len < 1
|
55
|
+
raise "#{xpath} duplicated: #{len} found" if len != 1
|
56
|
+
node.first
|
57
|
+
end
|
58
|
+
|
59
|
+
# Generates the XML tree for externalFile references. For example:
|
60
|
+
# <externalFile objectId="druid:mn123pq4567" resourceId="Image01" fileId="image_01.jp2000" mimetype="image/jp2" />
|
61
|
+
# @param [String] objectId the linked druid
|
62
|
+
# @param [String] resourceId the linked druid's resource identifier
|
63
|
+
# @param [String] fileId the linked druid's resource's file identifier
|
64
|
+
# @param [String] mimetype the file's MIME type
|
65
|
+
# @return [Nokogiri::XML::Element]
|
66
|
+
def generate_external_file_node(objectId, resourceId, fileId, mimetype)
|
67
|
+
externalFile = ng_xml.create_element 'externalFile'
|
68
|
+
externalFile[:objectId] = objectId
|
69
|
+
externalFile[:resourceId] = resourceId
|
70
|
+
externalFile[:fileId] = fileId
|
71
|
+
externalFile[:mimetype] = mimetype
|
72
|
+
externalFile
|
73
|
+
end
|
74
|
+
|
75
|
+
# Generates the XML tree for virtual resource relationship reference. For example:
|
76
|
+
# <relationship type="alsoAvailableAs" objectId="druid:mn123pq4567" />
|
77
|
+
# @param [String] objectId the linked druid
|
78
|
+
# @return [Nokogiri::XML::Element]
|
79
|
+
def generate_also_available_as_node(objectId)
|
80
|
+
relationship = ng_xml.create_element 'relationship'
|
81
|
+
relationship[:type] = 'alsoAvailableAs'
|
82
|
+
relationship[:objectId] = objectId
|
83
|
+
relationship
|
84
|
+
end
|
85
|
+
|
86
|
+
# Terminology-based solrization is going to be painfully slow for large
|
87
|
+
# contentMetadata streams. Just select the relevant elements instead.
|
88
|
+
# TODO: Call super()?
|
89
|
+
def to_solr(solr_doc = {}, *args)
|
90
|
+
doc = ng_xml
|
91
|
+
return solr_doc unless doc.root['type']
|
92
|
+
|
93
|
+
preserved_size = 0
|
94
|
+
counts = Hash.new(0) # default count is zero
|
95
|
+
resource_type_counts = Hash.new(0) # default count is zero
|
96
|
+
first_shelved_image = nil
|
97
|
+
|
98
|
+
doc.xpath('contentMetadata/resource').sort { |a, b| a['sequence'].to_i <=> b['sequence'].to_i }.each do |resource|
|
99
|
+
counts['resource'] += 1
|
100
|
+
resource_type_counts[resource['type']] += 1 if resource['type']
|
101
|
+
resource.xpath('file').each do |file|
|
102
|
+
counts['content_file'] += 1
|
103
|
+
preserved_size += file['size'].to_i if file['preserve'] == 'yes'
|
104
|
+
next unless file['shelve'] == 'yes'
|
105
|
+
counts['shelved_file'] += 1
|
106
|
+
first_shelved_image ||= file['id'] if file['id'].match(/jp2$/)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
solr_doc['content_type_ssim' ] = doc.root['type']
|
110
|
+
solr_doc['content_file_count_itsi' ] = counts['content_file']
|
111
|
+
solr_doc['shelved_content_file_count_itsi'] = counts['shelved_file']
|
112
|
+
solr_doc['resource_count_itsi' ] = counts['resource']
|
113
|
+
solr_doc['preserved_size_dbtsi' ] = preserved_size # double (trie) to support very large sizes
|
114
|
+
solr_doc['resource_types_ssim' ] = resource_type_counts.keys if resource_type_counts.size > 0
|
115
|
+
resource_type_counts.each do |key, count|
|
116
|
+
solr_doc["#{key}_resource_count_itsi"] = count
|
117
|
+
end
|
118
|
+
# first_shelved_image is neither indexed nor multiple
|
119
|
+
solr_doc['first_shelved_image_ss'] = first_shelved_image unless first_shelved_image.nil?
|
120
|
+
solr_doc
|
121
|
+
end
|
122
|
+
|
123
|
+
### END: READ ONLY METHODS
|
124
|
+
### DATSTREAM WRITING METHODS
|
125
|
+
|
126
|
+
# @param [Object] file
|
127
|
+
# @param [String] resource_name
|
128
|
+
# @return [Nokogiri::XML::Node] the added XML node
|
44
129
|
def add_file(file, resource_name)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
file_node=
|
50
|
-
file_node['id']=file[:name]
|
130
|
+
resource_nodes = ng_xml.search('//resource[@id=\'' + resource_name + '\']')
|
131
|
+
raise 'resource doesnt exist.' if resource_nodes.length == 0
|
132
|
+
node = resource_nodes.first
|
133
|
+
file_node = Nokogiri::XML::Node.new('file', ng_xml)
|
134
|
+
file_node['id'] = file[:name]
|
51
135
|
file_node['shelve' ] = file[:shelve ] ? file[:shelve ] : ''
|
52
136
|
file_node['publish' ] = file[:publish ] ? file[:publish ] : ''
|
53
137
|
file_node['preserve'] = file[:preserve] ? file[:preserve] : ''
|
@@ -55,227 +139,204 @@ module Dor
|
|
55
139
|
|
56
140
|
[:md5, :sha1].each do |algo|
|
57
141
|
next unless file[algo]
|
58
|
-
checksum_node = Nokogiri::XML::Node.new('checksum',
|
142
|
+
checksum_node = Nokogiri::XML::Node.new('checksum', ng_xml)
|
59
143
|
checksum_node['type'] = algo.to_s
|
60
144
|
checksum_node.content = file[algo]
|
61
145
|
file_node.add_child(checksum_node)
|
62
146
|
end
|
63
147
|
file_node['size' ] = file[:size ] if file[:size ]
|
64
148
|
file_node['mimetype'] = file[:mime_type] if file[:mime_type]
|
65
|
-
self.content=
|
66
|
-
|
149
|
+
self.content = ng_xml.to_s
|
150
|
+
file_node
|
67
151
|
end
|
68
152
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
153
|
+
# Copies the child's resource into the parent (self) as a virtual resource.
|
154
|
+
# Assumes the resource isn't a duplicate of an existing virtual or real resource.
|
155
|
+
# @param [String] child_druid druid
|
156
|
+
# @param [Nokogiri::XML::Element] child_resource
|
157
|
+
# @return [Nokogiri::XML::Element] the new resource that was added to the contentMetadata
|
158
|
+
def add_virtual_resource(child_druid, child_resource)
|
159
|
+
# create a virtual resource element with attributes linked to the child and omit label
|
160
|
+
sequence_max = ng_xml.search('//resource').map { |node| node[:sequence].to_i }.max
|
161
|
+
resource = Nokogiri::XML::Element.new('resource', ng_xml)
|
162
|
+
resource[:sequence] = sequence_max + 1
|
163
|
+
resource[:id] = "#{pid.gsub(/^druid:/, '')}_#{resource[:sequence]}"
|
164
|
+
resource[:type] = child_resource[:type]
|
165
|
+
|
166
|
+
# iterate over all the published files and link to them
|
167
|
+
child_resource.search('file[@publish=\'yes\']').each do |file|
|
168
|
+
resource << generate_external_file_node(child_druid, child_resource[:id], file[:id], file[:mimetype])
|
73
169
|
end
|
74
|
-
|
170
|
+
resource << generate_also_available_as_node(child_druid)
|
171
|
+
|
172
|
+
# attach the virtual resource as a sibling and return
|
173
|
+
ng_xml.root << resource
|
174
|
+
self.content = ng_xml.to_s
|
175
|
+
resource
|
176
|
+
end
|
75
177
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
178
|
+
# @param [Array] files
|
179
|
+
# @param [String] resource_name ID of the resource
|
180
|
+
# @param [Integer] position
|
181
|
+
# @param [String] type Resource type
|
182
|
+
# @return [Nokogiri::XML::Node] the new resource that was added to the contentMetadata
|
183
|
+
def add_resource(files, resource_name, position, type = 'file')
|
184
|
+
raise "resource #{resource_name} already exists" if ng_xml.search('//resource[@id=\'' + resource_name + '\']').length > 0
|
185
|
+
max = ng_xml.search('//resource').map { |node| node['sequence'].to_i }.max
|
186
|
+
# renumber all of the resources that will come after the newly added one
|
187
|
+
while max > position
|
188
|
+
node = ng_xml.search('//resource[@sequence=\'' + position + '\']')
|
189
|
+
node.first[sequence] = max + 1 if node.length > 0
|
190
|
+
max -= 1
|
82
191
|
end
|
83
|
-
node=Nokogiri::XML::Node.new('resource',
|
84
|
-
node['sequence']=position.to_s
|
85
|
-
node['id']=resource_name
|
86
|
-
node['type']=type
|
192
|
+
node = Nokogiri::XML::Node.new('resource', ng_xml)
|
193
|
+
node['sequence'] = position.to_s
|
194
|
+
node['id'] = resource_name
|
195
|
+
node['type'] = type
|
87
196
|
files.each do |file|
|
88
|
-
file_node=Nokogiri::XML::Node.new('file',
|
89
|
-
%w
|
197
|
+
file_node = Nokogiri::XML::Node.new('file', ng_xml)
|
198
|
+
%w(shelve publish preserve).each {|x| file_node[x] = file[x.to_sym] ? file[x.to_sym] : '' }
|
90
199
|
file_node['id'] = file[:name]
|
91
200
|
node.add_child(file_node)
|
92
201
|
|
93
202
|
[:md5, :sha1].each { |algo|
|
94
203
|
next if file[algo].nil?
|
95
|
-
checksum_node = Nokogiri::XML::Node.new('checksum',
|
204
|
+
checksum_node = Nokogiri::XML::Node.new('checksum', ng_xml)
|
96
205
|
checksum_node['type'] = algo.to_s
|
97
206
|
checksum_node.content = file[algo]
|
98
207
|
file_node.add_child(checksum_node)
|
99
208
|
}
|
100
209
|
file_node['size'] = file[:size] if file[:size]
|
101
210
|
end
|
102
|
-
|
103
|
-
self.content=
|
104
|
-
|
211
|
+
ng_xml.search('//contentMetadata').first.add_child(node)
|
212
|
+
self.content = ng_xml.to_s
|
213
|
+
node
|
105
214
|
end
|
106
215
|
|
107
|
-
|
108
|
-
|
109
|
-
node = singular_node('//resource[@id=\''+resource_name+'\']')
|
110
|
-
position = node['sequence'].to_i+1
|
216
|
+
# @param [String] resource_name ID of the resource
|
217
|
+
def remove_resource(resource_name)
|
218
|
+
node = singular_node('//resource[@id=\'' + resource_name + '\']')
|
219
|
+
position = node['sequence'].to_i + 1
|
111
220
|
node.remove
|
112
|
-
|
113
|
-
res=
|
114
|
-
break if res.length==0
|
115
|
-
res['sequence']=position.to_s
|
116
|
-
position+=1
|
221
|
+
loop do
|
222
|
+
res = ng_xml.search('//resource[@sequence=\'' + position.to_s + '\']')
|
223
|
+
break if res.length == 0
|
224
|
+
res['sequence'] = position.to_s
|
225
|
+
position += 1
|
117
226
|
end
|
118
|
-
self.content=
|
119
|
-
self.save
|
227
|
+
self.content = ng_xml.to_s
|
120
228
|
end
|
121
229
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
end
|
127
|
-
self.content=xml.to_s
|
128
|
-
self.save
|
230
|
+
# @param [String] file_name ID of the file element
|
231
|
+
def remove_file(file_name)
|
232
|
+
ng_xml.search('//file[@id=\'' + file_name + '\']').each(&:remove)
|
233
|
+
self.content = ng_xml.to_s
|
129
234
|
end
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
235
|
+
|
236
|
+
# @param [String] file_name ID of the file element
|
237
|
+
# @param [String] publish
|
238
|
+
# @param [String] shelve
|
239
|
+
# @param [String] preserve
|
240
|
+
def update_attributes(file_name, publish, shelve, preserve)
|
241
|
+
file_node = ng_xml.search('//file[@id=\'' + file_name + '\']').first
|
242
|
+
file_node['publish' ] = publish
|
243
|
+
file_node['shelve' ] = shelve
|
244
|
+
file_node['preserve'] = preserve
|
245
|
+
self.content = ng_xml.to_s
|
138
246
|
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
247
|
+
|
248
|
+
# @param file [Object] some hash-like file
|
249
|
+
# @param old_file_id [String] unique id attribute of the file element
|
250
|
+
def update_file(file, old_file_id)
|
251
|
+
file_node = ng_xml.search('//file[@id=\'' + old_file_id + '\']').first
|
252
|
+
file_node['id'] = file[:name]
|
143
253
|
[:md5, :sha1].each { |algo|
|
144
254
|
next if file[algo].nil?
|
145
|
-
checksum_node =
|
255
|
+
checksum_node = ng_xml.search('//file[@id=\'' + old_file_id + '\']/checksum[@type=\'' + algo.to_s + '\']').first
|
146
256
|
if checksum_node.nil?
|
147
|
-
checksum_node = Nokogiri::XML::Node.new('checksum',
|
257
|
+
checksum_node = Nokogiri::XML::Node.new('checksum', ng_xml)
|
148
258
|
file_node.add_child(checksum_node)
|
149
259
|
end
|
150
260
|
checksum_node['type'] = algo.to_s
|
151
261
|
checksum_node.content = file[algo]
|
152
262
|
}
|
153
263
|
|
154
|
-
[:size, :shelve, :preserve, :publish].each{ |x|
|
264
|
+
[:size, :shelve, :preserve, :publish].each { |x|
|
155
265
|
file_node[x.to_s] = file[x] if file[x]
|
156
266
|
}
|
157
|
-
self.content=
|
158
|
-
self.save
|
267
|
+
self.content = ng_xml.to_s
|
159
268
|
end
|
160
269
|
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
def
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
counts = Hash.new(0) # default count is zero
|
170
|
-
resource_type_counts = Hash.new(0) # default count is zero
|
171
|
-
first_shelved_image = nil
|
172
|
-
|
173
|
-
doc.xpath('contentMetadata/resource').sort { |a,b| a['sequence'].to_i <=> b['sequence'].to_i }.each do |resource|
|
174
|
-
counts['resource'] += 1
|
175
|
-
resource_type_counts[resource['type']] += 1 if resource['type']
|
176
|
-
resource.xpath('file').each do |file|
|
177
|
-
counts['content_file'] += 1
|
178
|
-
preserved_size += file['size'].to_i if file['preserve'] == 'yes'
|
179
|
-
next unless file['shelve'] == 'yes'
|
180
|
-
counts['shelved_file'] += 1
|
181
|
-
first_shelved_image ||= file['id'] if file['id'].match(/jp2$/)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
solr_doc["content_type_ssim" ] = doc.root['type']
|
185
|
-
solr_doc["content_file_count_itsi" ] = counts['content_file']
|
186
|
-
solr_doc["shelved_content_file_count_itsi"] = counts['shelved_file']
|
187
|
-
solr_doc["resource_count_itsi" ] = counts['resource']
|
188
|
-
solr_doc["preserved_size_dbtsi" ] = preserved_size # double (trie) to support very large sizes
|
189
|
-
solr_doc["resource_types_ssim" ] = resource_type_counts.keys if resource_type_counts.size > 0
|
190
|
-
resource_type_counts.each do |key, count|
|
191
|
-
solr_doc["#{key}_resource_count_itsi"] = count
|
192
|
-
end
|
193
|
-
# first_shelved_image is neither indexed nor multiple
|
194
|
-
solr_doc["first_shelved_image_ss"] = first_shelved_image unless first_shelved_image.nil?
|
195
|
-
solr_doc
|
196
|
-
end
|
197
|
-
|
198
|
-
#@param old_name [String] unique id attribute of the file element
|
199
|
-
#@param new_name [String] new unique id value being assigned
|
200
|
-
#@return [Nokogiri::XML::Element] the file node
|
201
|
-
def rename_file old_name, new_name
|
202
|
-
xml=self.ng_xml
|
203
|
-
file_node=xml.search('//file[@id=\''+old_name+'\']').first
|
204
|
-
file_node['id']=new_name
|
205
|
-
self.content=xml.to_s
|
206
|
-
self.save
|
270
|
+
# @param old_name [String] unique id attribute of the file element
|
271
|
+
# @param new_name [String] new unique id value being assigned
|
272
|
+
# @return [Nokogiri::XML::Element] the file node
|
273
|
+
def rename_file(old_name, new_name)
|
274
|
+
file_node = ng_xml.search('//file[@id=\'' + old_name + '\']').first
|
275
|
+
file_node['id'] = new_name
|
276
|
+
self.content = ng_xml.to_s
|
277
|
+
file_node
|
207
278
|
end
|
208
279
|
|
209
|
-
#Updates old label OR creates a new one if necessary
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
def update_resource_label
|
214
|
-
node = singular_node('//resource[@id=\''+resource_name+'\']')
|
280
|
+
# Updates old label OR creates a new one if necessary
|
281
|
+
# @param resource_name [String] unique id attribute of the resource
|
282
|
+
# @param new_label [String] label value being assigned
|
283
|
+
# @return [Nokogiri::XML::Element] the resource node
|
284
|
+
def update_resource_label(resource_name, new_label)
|
285
|
+
node = singular_node('//resource[@id=\'' + resource_name + '\']')
|
215
286
|
labels = node.xpath('./label')
|
216
|
-
if
|
217
|
-
#create a label
|
218
|
-
label_node =
|
219
|
-
label_node.content=new_label
|
287
|
+
if labels.length == 0
|
288
|
+
label_node = Nokogiri::XML::Node.new('label', ng_xml) # create a label
|
289
|
+
label_node.content = new_label
|
220
290
|
node.add_child(label_node)
|
221
291
|
else
|
222
|
-
labels.first.content=new_label
|
292
|
+
labels.first.content = new_label
|
223
293
|
end
|
224
|
-
|
294
|
+
self.content = ng_xml.to_s
|
295
|
+
node
|
225
296
|
end
|
226
297
|
|
227
|
-
|
228
|
-
|
229
|
-
def update_resource_type
|
230
|
-
singular_node('//resource[@id=\''+resource_name+'\']')['type']=new_type
|
298
|
+
# @param resource_name [String] unique id attribute of the resource
|
299
|
+
# @param new_type [String] type value being assigned
|
300
|
+
def update_resource_type(resource_name, new_type)
|
301
|
+
singular_node('//resource[@id=\'' + resource_name + '\']')['type'] = new_type
|
302
|
+
self.content = ng_xml.to_s
|
231
303
|
end
|
232
304
|
|
233
|
-
#You just *had* to have ordered lists in XML, didn't you?
|
234
|
-
#Re-enumerate the sequence numbers affected
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
def move_resource
|
239
|
-
node = singular_node('//resource[@id=\''+resource_name+'\']')
|
305
|
+
# You just *had* to have ordered lists in XML, didn't you?
|
306
|
+
# Re-enumerate the sequence numbers affected
|
307
|
+
# @param resource_name [String] unique id attribute of the resource
|
308
|
+
# @param new_position [Integer, String] new sequence number of the resource, or a string that looks like one
|
309
|
+
# @return [Nokogiri::XML::Element] the resource node
|
310
|
+
def move_resource(resource_name, new_position)
|
311
|
+
node = singular_node('//resource[@id=\'' + resource_name + '\']')
|
240
312
|
position = node['sequence'].to_i
|
241
|
-
new_position = new_position.to_i
|
313
|
+
new_position = new_position.to_i # tolerate strings as a Legacy behavior
|
242
314
|
return node if position == new_position
|
243
|
-
#otherwise, is the resource being moved earlier in the sequence or later?
|
244
|
-
up = new_position>position
|
245
|
-
others = new_position..(up ? position-1 : position+1)
|
315
|
+
# otherwise, is the resource being moved earlier in the sequence or later?
|
316
|
+
up = new_position > position
|
317
|
+
others = new_position..(up ? position - 1 : position + 1) # a range
|
246
318
|
others.each do |i|
|
247
|
-
item =
|
248
|
-
item['sequence'] = (up ? i-1 : i+1).to_s
|
319
|
+
item = ng_xml.at_xpath('/resource[@sequence=\'' + i.to_s + '\']')
|
320
|
+
item['sequence'] = (up ? i - 1 : i + 1).to_s # if you're going up, everything else comes down and vice versa
|
249
321
|
end
|
250
|
-
node['sequence'] = new_position.to_s
|
251
|
-
|
322
|
+
node['sequence'] = new_position.to_s # set the node we already had last, so we don't hit it twice!
|
323
|
+
self.content = ng_xml.to_s
|
324
|
+
node
|
252
325
|
end
|
253
326
|
|
254
|
-
#Set the content type and the resource
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
327
|
+
# Set the content type (e.g. "book") and the resource type (e.g. "book") for all resources
|
328
|
+
# @param [String] old_type the old content type
|
329
|
+
# @param [String] old_resource_type the old type for all resources
|
330
|
+
# @param [String] new_type the new content type
|
331
|
+
# @param [String] new_resource_type the new type for all resources
|
332
|
+
def set_content_type(old_type, old_resource_type, new_type, new_resource_type)
|
333
|
+
ng_xml.search('/contentMetadata[@type=\'' + old_type + '\']').each do |node|
|
334
|
+
node['type'] = new_type
|
335
|
+
ng_xml.search('//resource[@type=\'' + old_resource_type + '\']').each do |resource|
|
336
|
+
resource['type'] = new_resource_type
|
263
337
|
end
|
264
338
|
end
|
265
|
-
self.content=
|
266
|
-
end
|
267
|
-
|
268
|
-
# Only use this when you want the behavior of raising an exception if anything besides exactly one matching node
|
269
|
-
# is found. Otherwise just use .xpath, .at_xpath or .search.
|
270
|
-
#@param xpath [String] accessor invocation for Nokogiri xpath
|
271
|
-
#@return [Nokogiri::XML::Element] the matched element
|
272
|
-
def singular_node xpath
|
273
|
-
node = self.ng_xml.search(xpath)
|
274
|
-
len = node.length
|
275
|
-
raise "#{xpath} not found" if len < 1
|
276
|
-
raise "#{xpath} duplicated: #{len} found" if len != 1
|
277
|
-
node.first
|
339
|
+
self.content = ng_xml.to_s
|
278
340
|
end
|
279
341
|
end
|
280
|
-
|
281
342
|
end
|