dor-services 5.2.0 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|