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.
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