dor-services 7.2.4 → 8.0.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 +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
|