dor-services 7.2.4 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/config_defaults.yml +24 -41
- data/config/dev_console_env.rb.example +0 -9
- data/lib/dor-services.rb +6 -9
- data/lib/dor/config.rb +2 -126
- data/lib/dor/datastreams/content_metadata_ds.rb +7 -0
- data/lib/dor/datastreams/embargo_metadata_ds.rb +1 -1
- data/lib/dor/datastreams/role_metadata_ds.rb +1 -1
- data/lib/dor/datastreams/workflow_definition_ds.rb +0 -22
- data/lib/dor/datastreams/workflow_ds.rb +2 -64
- data/lib/dor/indexers/workflows_indexer.rb +7 -1
- data/lib/dor/models/abstract.rb +2 -4
- data/lib/dor/models/workflow_object.rb +0 -46
- data/lib/dor/release_tags.rb +13 -0
- data/lib/dor/release_tags/identity_metadata.rb +202 -0
- data/lib/dor/release_tags/purl.rb +50 -0
- data/lib/dor/release_tags/purl_client.rb +44 -0
- data/lib/dor/services/release_tag_service.rb +9 -179
- data/lib/dor/services/state_service.rb +23 -0
- data/lib/dor/static_config.rb +108 -0
- data/lib/dor/static_config/fedora_config.rb +36 -0
- data/lib/dor/static_config/solr_config.rb +21 -0
- data/lib/dor/static_config/ssl_config.rb +33 -0
- data/lib/dor/static_config/stacks_config.rb +39 -0
- data/lib/dor/static_config/suri_config.rb +45 -0
- data/lib/dor/static_config/workflow_config.rb +51 -0
- data/lib/dor/version.rb +1 -1
- data/lib/dor/workflow/document.rb +0 -10
- metadata +26 -66
- data/lib/dor/services/cleanup_service.rb +0 -63
- data/lib/dor/services/create_workflow_service.rb +0 -53
- data/lib/dor/services/delete_service.rb +0 -60
- data/lib/dor/services/metadata_handlers/catalog_handler.rb +0 -27
- data/lib/dor/services/metadata_service.rb +0 -64
- data/lib/dor/services/mods2dc.xslt +0 -474
- data/lib/dor/services/public_desc_metadata_service.rb +0 -184
- data/lib/dor/services/purl_client.rb +0 -42
- data/lib/dor/services/thumbnail_service.rb +0 -59
@@ -1,184 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dor
|
4
|
-
class PublicDescMetadataService
|
5
|
-
extend Deprecation
|
6
|
-
|
7
|
-
attr_reader :object
|
8
|
-
|
9
|
-
NOKOGIRI_DEEP_COPY = 1
|
10
|
-
|
11
|
-
def initialize(object)
|
12
|
-
Deprecation.warn(self, 'Dor::PublicDescMetadataService has moved to dor-services-app')
|
13
|
-
@object = object
|
14
|
-
end
|
15
|
-
|
16
|
-
# @return [Nokogiri::XML::Document] A copy of the descriptiveMetadata of the object, to be modified
|
17
|
-
def doc
|
18
|
-
@doc ||= object.descMetadata.ng_xml.dup(NOKOGIRI_DEEP_COPY)
|
19
|
-
end
|
20
|
-
|
21
|
-
# @return [String] Public descriptive medatada XML
|
22
|
-
def to_xml(include_access_conditions: true)
|
23
|
-
ng_xml(include_access_conditions: include_access_conditions).to_xml
|
24
|
-
end
|
25
|
-
|
26
|
-
# @return [Nokogiri::XML::Document]
|
27
|
-
def ng_xml(include_access_conditions: true)
|
28
|
-
@ng_xml ||= begin
|
29
|
-
add_collection_reference!
|
30
|
-
add_access_conditions! if include_access_conditions
|
31
|
-
add_constituent_relations!
|
32
|
-
strip_comments!
|
33
|
-
|
34
|
-
new_doc = Nokogiri::XML(doc.to_xml, &:noblanks)
|
35
|
-
new_doc.encoding = 'UTF-8'
|
36
|
-
new_doc
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def strip_comments!
|
43
|
-
doc.xpath('//comment()').remove
|
44
|
-
end
|
45
|
-
|
46
|
-
# Create MODS accessCondition statements from rightsMetadata
|
47
|
-
def add_access_conditions!
|
48
|
-
# clear out any existing accessConditions
|
49
|
-
doc.xpath('//mods:accessCondition', 'mods' => 'http://www.loc.gov/mods/v3').each(&:remove)
|
50
|
-
rights = object.datastreams['rightsMetadata'].ng_xml
|
51
|
-
|
52
|
-
rights.xpath('//use/human[@type="useAndReproduction"]').each do |use|
|
53
|
-
txt = use.text.strip
|
54
|
-
next if txt.empty?
|
55
|
-
|
56
|
-
doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', txt, type: 'useAndReproduction')
|
57
|
-
end
|
58
|
-
rights.xpath('//copyright/human[@type="copyright"]').each do |cr|
|
59
|
-
txt = cr.text.strip
|
60
|
-
next if txt.empty?
|
61
|
-
|
62
|
-
doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', txt, type: 'copyright')
|
63
|
-
end
|
64
|
-
rights.xpath("//use/machine[#{ci_compare('type', 'creativecommons')}]").each do |lic_type|
|
65
|
-
next if lic_type.text =~ /none/i
|
66
|
-
|
67
|
-
lic_text = rights.at_xpath("//use/human[#{ci_compare('type', 'creativecommons')}]").text.strip
|
68
|
-
next if lic_text.empty?
|
69
|
-
|
70
|
-
new_text = "CC #{lic_type.text}: #{lic_text}"
|
71
|
-
doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', new_text, type: 'license')
|
72
|
-
end
|
73
|
-
rights.xpath("//use/machine[#{ci_compare('type', 'opendatacommons')}]").each do |lic_type|
|
74
|
-
next if lic_type.text =~ /none/i
|
75
|
-
|
76
|
-
lic_text = rights.at_xpath("//use/human[#{ci_compare('type', 'opendatacommons')}]").text.strip
|
77
|
-
next if lic_text.empty?
|
78
|
-
|
79
|
-
new_text = "ODC #{lic_type.text}: #{lic_text}"
|
80
|
-
doc.root.element_children.last.add_next_sibling doc.create_element('accessCondition', new_text, type: 'license')
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
# expand constituent relations into relatedItem references -- see JUMBO-18
|
85
|
-
# @return [Void]
|
86
|
-
def add_constituent_relations!
|
87
|
-
object.relationships(:is_constituent_of).each do |parent|
|
88
|
-
# fetch the parent object to get title
|
89
|
-
druid = parent.gsub(/^info:fedora\//, '')
|
90
|
-
parent_item = Dor.find(druid)
|
91
|
-
|
92
|
-
# create the MODS relation
|
93
|
-
relatedItem = doc.create_element 'relatedItem'
|
94
|
-
relatedItem['type'] = 'host'
|
95
|
-
relatedItem['displayLabel'] = 'Appears in'
|
96
|
-
|
97
|
-
# load the title from the parent's DC.title
|
98
|
-
titleInfo = doc.create_element 'titleInfo'
|
99
|
-
title = doc.create_element 'title'
|
100
|
-
title.content = parent_item.full_title
|
101
|
-
titleInfo << title
|
102
|
-
relatedItem << titleInfo
|
103
|
-
|
104
|
-
# point to the PURL for the parent
|
105
|
-
location = doc.create_element 'location'
|
106
|
-
url = doc.create_element 'url'
|
107
|
-
url.content = "http://#{Dor::Config.stacks.document_cache_host}/#{druid.split(':').last}"
|
108
|
-
location << url
|
109
|
-
relatedItem << location
|
110
|
-
|
111
|
-
# finish up by adding relation to public MODS
|
112
|
-
doc.root << relatedItem
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# Adds to desc metadata a relatedItem with information about the collection this object belongs to.
|
117
|
-
# For use in published mods and mods-to-DC conversion.
|
118
|
-
# @return [Void]
|
119
|
-
def add_collection_reference!
|
120
|
-
collections = object.relationships(:is_member_of_collection)
|
121
|
-
return if collections.empty?
|
122
|
-
|
123
|
-
remove_related_item_nodes_for_collections!
|
124
|
-
|
125
|
-
collections.each do |collection_uri|
|
126
|
-
collection_druid = collection_uri.gsub('info:fedora/', '')
|
127
|
-
add_related_item_node_for_collection! collection_druid
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# Remove existing relatedItem entries for collections from descMetadata
|
132
|
-
def remove_related_item_nodes_for_collections!
|
133
|
-
doc.search('/mods:mods/mods:relatedItem[@type="host"]/mods:typeOfResource[@collection=\'yes\']', 'mods' => 'http://www.loc.gov/mods/v3').each do |node|
|
134
|
-
node.parent.remove
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def add_related_item_node_for_collection!(collection_druid)
|
139
|
-
begin
|
140
|
-
collection_obj = Dor.find(collection_druid)
|
141
|
-
rescue ActiveFedora::ObjectNotFoundError
|
142
|
-
return nil
|
143
|
-
end
|
144
|
-
|
145
|
-
title_node = Nokogiri::XML::Node.new('title', doc)
|
146
|
-
title_node.content = collection_obj.full_title
|
147
|
-
|
148
|
-
title_info_node = Nokogiri::XML::Node.new('titleInfo', doc)
|
149
|
-
title_info_node.add_child(title_node)
|
150
|
-
|
151
|
-
# e.g.:
|
152
|
-
# <location>
|
153
|
-
# <url>http://purl.stanford.edu/rh056sr3313</url>
|
154
|
-
# </location>
|
155
|
-
loc_node = doc.create_element('location')
|
156
|
-
url_node = doc.create_element('url')
|
157
|
-
url_node.content = "https://#{Dor::Config.stacks.document_cache_host}/#{collection_druid.split(':').last}"
|
158
|
-
loc_node << url_node
|
159
|
-
|
160
|
-
type_node = Nokogiri::XML::Node.new('typeOfResource', doc)
|
161
|
-
type_node['collection'] = 'yes'
|
162
|
-
|
163
|
-
related_item_node = Nokogiri::XML::Node.new('relatedItem', doc)
|
164
|
-
related_item_node['type'] = 'host'
|
165
|
-
|
166
|
-
related_item_node.add_child(title_info_node)
|
167
|
-
related_item_node.add_child(loc_node)
|
168
|
-
related_item_node.add_child(type_node)
|
169
|
-
|
170
|
-
doc.root.add_child(related_item_node)
|
171
|
-
end
|
172
|
-
|
173
|
-
private
|
174
|
-
|
175
|
-
# Builds case-insensitive xpath translate function call that will match the attribute to a value
|
176
|
-
def ci_compare(attribute, value)
|
177
|
-
"translate(
|
178
|
-
@#{attribute},
|
179
|
-
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
180
|
-
'abcdefghijklmnopqrstuvwxyz'
|
181
|
-
) = '#{value}' "
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dor
|
4
|
-
# Calls the purl service and returns the XML document
|
5
|
-
class PurlClient
|
6
|
-
def initialize(host:, pid:)
|
7
|
-
@host = host
|
8
|
-
@pid = pid
|
9
|
-
end
|
10
|
-
|
11
|
-
# Get XML from the purl service
|
12
|
-
# Fetches purl xml for a druid
|
13
|
-
# @raise [OpenURI::HTTPError]
|
14
|
-
# @return [Nokogiri::HTML::Document] parsed XML for the druid or an empty document if no purl is found
|
15
|
-
def fetch
|
16
|
-
handler = proc do |exception, attempt_number, total_delay|
|
17
|
-
# We assume a 404 means the document has never been published before and thus has no purl
|
18
|
-
Dor.logger.warn "[Attempt #{attempt_number}] GET #{url} -- #{exception.class}: #{exception.message}; #{total_delay} seconds elapsed."
|
19
|
-
raise exception unless exception.is_a? OpenURI::HTTPError
|
20
|
-
return Nokogiri::HTML::Document.new if exception.io.status.first == '404' # ["404", "Not Found"] from OpenURI::Meta.status
|
21
|
-
end
|
22
|
-
|
23
|
-
with_retries(max_retries: 3, base_sleep_seconds: 3, max_sleep_seconds: 5, handler: handler) do |attempt|
|
24
|
-
# If you change the method used for opening the webpage, you can change the :rescue param to handle the new method's errors
|
25
|
-
Dor.logger.debug "[Attempt #{attempt}] GET #{url}"
|
26
|
-
return Nokogiri::XML(OpenURI.open_uri(url))
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
# Take the and create the entire purl url that will usable for the open method in open-uri, returns http
|
33
|
-
# @return [String] the full url
|
34
|
-
def url
|
35
|
-
@url ||= "https://#{@host}/#{druid_without_prefix}.xml"
|
36
|
-
end
|
37
|
-
|
38
|
-
def druid_without_prefix
|
39
|
-
PidUtils.remove_druid_prefix(@pid)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dor
|
4
|
-
# Responsible for finding a path to a thumbnail based on the contentMetadata of an object
|
5
|
-
class ThumbnailService
|
6
|
-
# allow the mimetype attribute to be lower or camelcase when searching to make it more robust
|
7
|
-
MIME_TYPE_FINDER = "@mimetype='image/jp2' or @mimeType='image/jp2'"
|
8
|
-
|
9
|
-
# these are the finders we will use to search for a thumb resource in contentMetadata, they will be searched in the order provided, stopping when one is reached
|
10
|
-
THUMB_XPATH_FINDERS = [
|
11
|
-
# first find a file of mimetype jp2 explicitly marked as a thumb in the resource type and with a thumb=yes attribute
|
12
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/file[#{MIME_TYPE_FINDER}]" },
|
13
|
-
# same thing for external files
|
14
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]" },
|
15
|
-
# next find any image or page resource types with the thumb=yes attribute of mimetype jp2
|
16
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/file[#{MIME_TYPE_FINDER}]" },
|
17
|
-
# same thing for external file
|
18
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]" },
|
19
|
-
# next find a file of mimetype jp2 and resource type=thumb but not marked with the thumb directive
|
20
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[@type='thumb']/file[#{MIME_TYPE_FINDER}]" },
|
21
|
-
# same thing for external file
|
22
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[@type='thumb']/externalFile[#{MIME_TYPE_FINDER}]" },
|
23
|
-
# finally find the first page or image resource of mimetype jp2
|
24
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[@type='page' or @type='image']/file[#{MIME_TYPE_FINDER}]" },
|
25
|
-
# same thing for external file
|
26
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[@type='page' or @type='image']/externalFile[#{MIME_TYPE_FINDER}]" }
|
27
|
-
].freeze
|
28
|
-
|
29
|
-
# @param [Dor::Item] object
|
30
|
-
def initialize(object)
|
31
|
-
@object = object
|
32
|
-
end
|
33
|
-
|
34
|
-
attr_reader :object
|
35
|
-
|
36
|
-
# @return [String] the computed thumb filename, with the druid prefix and a slash in front of it, e.g. oo000oo0001/filenamewith space.jp2
|
37
|
-
def thumb
|
38
|
-
return unless object.respond_to?(:contentMetadata) && object.contentMetadata.present?
|
39
|
-
|
40
|
-
cm = object.contentMetadata.ng_xml
|
41
|
-
thumb_image = nil
|
42
|
-
|
43
|
-
THUMB_XPATH_FINDERS.each do |search_path|
|
44
|
-
thumb_files = cm.xpath(search_path[:finder]) # look for a thumb
|
45
|
-
next if thumb_files.empty?
|
46
|
-
|
47
|
-
# if we find one, return the filename based on whether it is a local file or external file
|
48
|
-
thumb_image = if search_path[:image_type] == 'local'
|
49
|
-
"#{PidUtils.remove_druid_prefix(object.pid)}/#{thumb_files[0]['id']}"
|
50
|
-
else
|
51
|
-
"#{PidUtils.remove_druid_prefix(thumb_files[0]['objectId'])}/#{thumb_files[0]['fileId']}"
|
52
|
-
end
|
53
|
-
break # break out of the loop so we stop searching
|
54
|
-
end
|
55
|
-
|
56
|
-
thumb_image
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|