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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/config/config_defaults.yml +24 -41
  3. data/config/dev_console_env.rb.example +0 -9
  4. data/lib/dor-services.rb +6 -9
  5. data/lib/dor/config.rb +2 -126
  6. data/lib/dor/datastreams/content_metadata_ds.rb +7 -0
  7. data/lib/dor/datastreams/embargo_metadata_ds.rb +1 -1
  8. data/lib/dor/datastreams/role_metadata_ds.rb +1 -1
  9. data/lib/dor/datastreams/workflow_definition_ds.rb +0 -22
  10. data/lib/dor/datastreams/workflow_ds.rb +2 -64
  11. data/lib/dor/indexers/workflows_indexer.rb +7 -1
  12. data/lib/dor/models/abstract.rb +2 -4
  13. data/lib/dor/models/workflow_object.rb +0 -46
  14. data/lib/dor/release_tags.rb +13 -0
  15. data/lib/dor/release_tags/identity_metadata.rb +202 -0
  16. data/lib/dor/release_tags/purl.rb +50 -0
  17. data/lib/dor/release_tags/purl_client.rb +44 -0
  18. data/lib/dor/services/release_tag_service.rb +9 -179
  19. data/lib/dor/services/state_service.rb +23 -0
  20. data/lib/dor/static_config.rb +108 -0
  21. data/lib/dor/static_config/fedora_config.rb +36 -0
  22. data/lib/dor/static_config/solr_config.rb +21 -0
  23. data/lib/dor/static_config/ssl_config.rb +33 -0
  24. data/lib/dor/static_config/stacks_config.rb +39 -0
  25. data/lib/dor/static_config/suri_config.rb +45 -0
  26. data/lib/dor/static_config/workflow_config.rb +51 -0
  27. data/lib/dor/version.rb +1 -1
  28. data/lib/dor/workflow/document.rb +0 -10
  29. metadata +26 -66
  30. data/lib/dor/services/cleanup_service.rb +0 -63
  31. data/lib/dor/services/create_workflow_service.rb +0 -53
  32. data/lib/dor/services/delete_service.rb +0 -60
  33. data/lib/dor/services/metadata_handlers/catalog_handler.rb +0 -27
  34. data/lib/dor/services/metadata_service.rb +0 -64
  35. data/lib/dor/services/mods2dc.xslt +0 -474
  36. data/lib/dor/services/public_desc_metadata_service.rb +0 -184
  37. data/lib/dor/services/purl_client.rb +0 -42
  38. 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