dor-services 6.0.0 → 6.0.1
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/lib/dor-services.rb +7 -6
- data/lib/dor/certificate_authenticated_rest_resource_factory.rb +2 -1
- data/lib/dor/config.rb +38 -37
- data/lib/dor/datastreams/administrative_metadata_ds.rb +98 -98
- data/lib/dor/datastreams/content_metadata_ds.rb +26 -17
- data/lib/dor/datastreams/datastream_spec_solrizer.rb +4 -2
- data/lib/dor/datastreams/default_object_rights_ds.rb +10 -7
- data/lib/dor/datastreams/desc_metadata_ds.rb +6 -6
- data/lib/dor/datastreams/embargo_metadata_ds.rb +94 -94
- data/lib/dor/datastreams/events_ds.rb +55 -54
- data/lib/dor/datastreams/geo_metadata_ds.rb +7 -6
- data/lib/dor/datastreams/identity_metadata_ds.rb +128 -125
- data/lib/dor/datastreams/provenance_metadata_ds.rb +3 -1
- data/lib/dor/datastreams/rights_metadata_ds.rb +4 -4
- data/lib/dor/datastreams/role_metadata_ds.rb +42 -42
- data/lib/dor/datastreams/simple_dublin_core_ds.rb +45 -43
- data/lib/dor/datastreams/technical_metadata_ds.rb +3 -1
- data/lib/dor/datastreams/version_metadata_ds.rb +12 -5
- data/lib/dor/datastreams/workflow_definition_ds.rb +74 -73
- data/lib/dor/datastreams/workflow_ds.rb +12 -7
- data/lib/dor/exceptions.rb +2 -0
- data/lib/dor/indexers/data_indexer.rb +16 -0
- data/lib/dor/indexers/describable_indexer.rb +2 -0
- data/lib/dor/indexers/editable_indexer.rb +2 -0
- data/lib/dor/indexers/identifiable_indexer.rb +23 -8
- data/lib/dor/indexers/processable_indexer.rb +2 -0
- data/lib/dor/indexers/releasable_indexer.rb +2 -0
- data/lib/dor/models/abstract.rb +2 -0
- data/lib/dor/models/admin_policy_object.rb +2 -0
- data/lib/dor/models/agreement.rb +2 -0
- data/lib/dor/models/collection.rb +3 -0
- data/lib/dor/models/concerns/assembleable.rb +2 -0
- data/lib/dor/models/concerns/contentable.rb +5 -2
- data/lib/dor/models/concerns/describable.rb +7 -2
- data/lib/dor/models/concerns/editable.rb +28 -21
- data/lib/dor/models/concerns/embargoable.rb +4 -0
- data/lib/dor/models/concerns/eventable.rb +2 -0
- data/lib/dor/models/concerns/geoable.rb +2 -0
- data/lib/dor/models/concerns/governable.rb +7 -2
- data/lib/dor/models/concerns/identifiable.rb +33 -34
- data/lib/dor/models/concerns/itemizable.rb +4 -1
- data/lib/dor/models/concerns/preservable.rb +2 -0
- data/lib/dor/models/concerns/processable.rb +15 -9
- data/lib/dor/models/concerns/publishable.rb +9 -4
- data/lib/dor/models/concerns/releaseable.rb +21 -11
- data/lib/dor/models/concerns/rightsable.rb +2 -0
- data/lib/dor/models/concerns/shelvable.rb +6 -2
- data/lib/dor/models/concerns/versionable.rb +8 -4
- data/lib/dor/models/item.rb +2 -0
- data/lib/dor/models/set.rb +2 -0
- data/lib/dor/models/workflow_object.rb +5 -1
- data/lib/dor/rest_resource_factory.rb +2 -0
- data/lib/dor/services/cleanup_reset_service.rb +2 -1
- data/lib/dor/services/cleanup_service.rb +2 -1
- data/lib/dor/services/digital_stacks_service.rb +3 -1
- data/lib/dor/services/indexing_service.rb +3 -1
- data/lib/dor/services/merge_service.rb +6 -4
- data/lib/dor/services/metadata_handlers/catalog_handler.rb +2 -0
- data/lib/dor/services/metadata_service.rb +4 -4
- data/lib/dor/services/public_desc_metadata_service.rb +16 -8
- data/lib/dor/services/public_xml_service.rb +7 -4
- data/lib/dor/services/registration_service.rb +25 -20
- data/lib/dor/services/reset_workspace_service.rb +4 -4
- data/lib/dor/services/sdr_ingest_service.rb +4 -2
- data/lib/dor/services/search_service.rb +8 -9
- data/lib/dor/services/suri_service.rb +3 -2
- data/lib/dor/services/technical_metadata_service.rb +15 -9
- data/lib/dor/services/thumbnail_service.rb +14 -10
- data/lib/dor/utils/hydrus_shims.rb +2 -0
- data/lib/dor/utils/ng_tidy.rb +3 -7
- data/lib/dor/utils/predicate_patch.rb +2 -0
- data/lib/dor/utils/sdr_client.rb +3 -0
- data/lib/dor/utils/solr_doc_helper.rb +4 -2
- data/lib/dor/version.rb +3 -1
- data/lib/dor/workflow/document.rb +113 -108
- data/lib/dor/workflow/process.rb +90 -87
- data/lib/tasks/rdoc.rake +4 -3
- metadata +4 -4
@@ -1,27 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dor
|
2
4
|
# Responsible for finding a path to a thumbnail based on the contentMetadata of an object
|
3
5
|
class ThumbnailService
|
4
6
|
# allow the mimetype attribute to be lower or camelcase when searching to make it more robust
|
5
|
-
MIME_TYPE_FINDER = "@mimetype='image/jp2' or @mimeType='image/jp2'"
|
7
|
+
MIME_TYPE_FINDER = "@mimetype='image/jp2' or @mimeType='image/jp2'"
|
6
8
|
|
7
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
|
8
10
|
THUMB_XPATH_FINDERS = [
|
9
11
|
# first find a file of mimetype jp2 explicitly marked as a thumb in the resource type and with a thumb=yes attribute
|
10
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/file[#{MIME_TYPE_FINDER}]"},
|
12
|
+
{ image_type: 'local', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/file[#{MIME_TYPE_FINDER}]" },
|
11
13
|
# same thing for external files
|
12
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]"},
|
14
|
+
{ image_type: 'external', finder: "/contentMetadata/resource[@type='thumb' and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]" },
|
13
15
|
# next find any image or page resource types with the thumb=yes attribute of mimetype jp2
|
14
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/file[#{MIME_TYPE_FINDER}]"},
|
16
|
+
{ image_type: 'local', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/file[#{MIME_TYPE_FINDER}]" },
|
15
17
|
# same thing for external file
|
16
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]"},
|
18
|
+
{ image_type: 'external', finder: "/contentMetadata/resource[(@type='page' or @type='image') and @thumb='yes']/externalFile[#{MIME_TYPE_FINDER}]" },
|
17
19
|
# next find a file of mimetype jp2 and resource type=thumb but not marked with the thumb directive
|
18
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[@type='thumb']/file[#{MIME_TYPE_FINDER}]"},
|
20
|
+
{ image_type: 'local', finder: "/contentMetadata/resource[@type='thumb']/file[#{MIME_TYPE_FINDER}]" },
|
19
21
|
# same thing for external file
|
20
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[@type='thumb']/externalFile[#{MIME_TYPE_FINDER}]"},
|
22
|
+
{ image_type: 'external', finder: "/contentMetadata/resource[@type='thumb']/externalFile[#{MIME_TYPE_FINDER}]" },
|
21
23
|
# finally find the first page or image resource of mimetype jp2
|
22
|
-
{ image_type: 'local', finder: "/contentMetadata/resource[@type='page' or @type='image']/file[#{MIME_TYPE_FINDER}]"},
|
24
|
+
{ image_type: 'local', finder: "/contentMetadata/resource[@type='page' or @type='image']/file[#{MIME_TYPE_FINDER}]" },
|
23
25
|
# same thing for external file
|
24
|
-
{ image_type: 'external', finder: "/contentMetadata/resource[@type='page' or @type='image']/externalFile[#{MIME_TYPE_FINDER}]"}
|
26
|
+
{ image_type: 'external', finder: "/contentMetadata/resource[@type='page' or @type='image']/externalFile[#{MIME_TYPE_FINDER}]" }
|
25
27
|
].freeze
|
26
28
|
|
27
29
|
# @params [Dor::Item] object
|
@@ -34,19 +36,21 @@ module Dor
|
|
34
36
|
# @return [String] the computed thumb filename, with the druid prefix and a slash in front of it, e.g. oo000oo0001/filenamewith space.jp2
|
35
37
|
def thumb
|
36
38
|
return unless object.respond_to?(:contentMetadata) && object.contentMetadata.present?
|
39
|
+
|
37
40
|
cm = object.contentMetadata.ng_xml
|
38
41
|
thumb_image = nil
|
39
42
|
|
40
43
|
THUMB_XPATH_FINDERS.each do |search_path|
|
41
44
|
thumb_files = cm.xpath(search_path[:finder]) # look for a thumb
|
42
45
|
next if thumb_files.empty?
|
46
|
+
|
43
47
|
# if we find one, return the filename based on whether it is a local file or external file
|
44
48
|
thumb_image = if search_path[:image_type] == 'local'
|
45
49
|
"#{object.remove_druid_prefix}/#{thumb_files[0]['id']}"
|
46
50
|
else
|
47
51
|
"#{object.remove_druid_prefix(thumb_files[0]['objectId'])}/#{thumb_files[0]['fileId']}"
|
48
52
|
end
|
49
|
-
break
|
53
|
+
break # break out of the loop so we stop searching
|
50
54
|
end
|
51
55
|
|
52
56
|
thumb_image
|
data/lib/dor/utils/ng_tidy.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
class Nokogiri::XML::Text
|
3
4
|
def normalize
|
4
5
|
content =~ /\S/ ? content.gsub(/\s+/, ' ').strip : content
|
5
6
|
end
|
@@ -7,19 +8,15 @@ class Nokogiri::XML::Text
|
|
7
8
|
def normalize!
|
8
9
|
self.content = normalize
|
9
10
|
end
|
10
|
-
|
11
11
|
end
|
12
12
|
|
13
13
|
class Nokogiri::XML::Node
|
14
|
-
|
15
14
|
def normalize_text!
|
16
15
|
xpath('//text()').each { |t| t.normalize! }
|
17
16
|
end
|
18
|
-
|
19
17
|
end
|
20
18
|
|
21
19
|
class Nokogiri::XML::Document
|
22
|
-
|
23
20
|
PRETTIFY_XSLT = Nokogiri::XSLT <<-EOC
|
24
21
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
25
22
|
<xsl:output omit-xml-declaration="yes" indent="yes"/>
|
@@ -29,10 +26,9 @@ class Nokogiri::XML::Document
|
|
29
26
|
</xsl:copy>
|
30
27
|
</xsl:template>
|
31
28
|
</xsl:stylesheet>
|
32
|
-
|
29
|
+
EOC
|
33
30
|
|
34
31
|
def prettify
|
35
32
|
PRETTIFY_XSLT.transform(self).to_xml
|
36
33
|
end
|
37
|
-
|
38
34
|
end
|
data/lib/dor/utils/sdr_client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'moab'
|
2
4
|
module Sdr
|
3
5
|
class Client
|
@@ -10,6 +12,7 @@ module Sdr
|
|
10
12
|
begin
|
11
13
|
doc = Nokogiri::XML xml
|
12
14
|
raise if doc.root.name != 'currentVersion'
|
15
|
+
|
13
16
|
return Integer(doc.text)
|
14
17
|
rescue
|
15
18
|
raise "Unable to parse XML from SDR current_version API call: #{xml}"
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SolrDocHelper
|
2
4
|
def add_solr_value(solr_doc, field_name, value, field_type = :default, index_types = [:searchable])
|
3
5
|
case field_type
|
4
|
-
|
5
|
-
|
6
|
+
when :symbol
|
7
|
+
index_types << field_type
|
6
8
|
end
|
7
9
|
::Solrizer.insert_field(solr_doc, field_name, value, *index_types)
|
8
10
|
end
|
data/lib/dor/version.rb
CHANGED
@@ -1,130 +1,135 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dor
|
2
|
-
module Workflow
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
4
|
+
module Workflow
|
5
|
+
class Document
|
6
|
+
include SolrDocHelper
|
7
|
+
include ::OM::XML::Document
|
8
|
+
|
9
|
+
set_terminology do |t|
|
10
|
+
t.root(:path => 'workflow')
|
11
|
+
t.repository(:path => { :attribute => 'repository' })
|
12
|
+
t.workflowId(:path => { :attribute => 'id' })
|
13
|
+
t.process do
|
14
|
+
t.name_(:path => { :attribute => 'name' })
|
15
|
+
t.status(:path => { :attribute => 'status' })
|
16
|
+
t.timestamp(:path => { :attribute => 'datetime' }) # , :data_type => :date)
|
17
|
+
t.elapsed(:path => { :attribute => 'elapsed' })
|
18
|
+
t.lifecycle(:path => { :attribute => 'lifecycle' })
|
19
|
+
t.attempts(:path => { :attribute => 'attempts' }, :index_as => [:not_searchable])
|
20
|
+
t.version(:path => { :attribute => 'version' })
|
21
|
+
end
|
19
22
|
end
|
20
|
-
end
|
21
23
|
|
22
|
-
|
24
|
+
@@definitions = {}
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
def initialize(node)
|
27
|
+
self.ng_xml = Nokogiri::XML(node)
|
28
|
+
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
# is this an incomplete workflow with steps that have a priority > 0
|
31
|
+
def expedited?
|
32
|
+
processes.any? { |proc| !proc.completed? && proc.priority.to_i > 0 }
|
33
|
+
end
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
# @return [Integer] value of the first > 0 priority. Defaults to 0
|
36
|
+
def priority
|
37
|
+
processes.map { |proc| proc.priority.to_i }.detect(0) { |p| p > 0 }
|
38
|
+
end
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
# @return [Boolean] if any process node does not have version, returns true, false otherwise (all processes have version)
|
41
|
+
def active?
|
42
|
+
ng_xml.at_xpath('/workflow/process[not(@version)]') ? true : false
|
43
|
+
end
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
45
|
+
# @return [Dor::WorkflowDefinitionDs]
|
46
|
+
def definition
|
47
|
+
@definition ||= begin
|
48
|
+
if @@definitions.key? workflowId.first
|
49
|
+
@@definitions[workflowId.first]
|
50
|
+
else
|
51
|
+
wfo = Dor::WorkflowObject.find_by_name(workflowId.first)
|
52
|
+
wf_def = wfo ? wfo.definition : nil
|
53
|
+
@@definitions[workflowId.first] = wf_def
|
54
|
+
wf_def
|
55
|
+
end
|
53
56
|
end
|
54
57
|
end
|
55
|
-
end
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
-
|
59
|
+
def [](value)
|
60
|
+
processes.find { |p| p.name == value }
|
61
|
+
end
|
60
62
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
63
|
+
def processes
|
64
|
+
# if the workflow service didnt return any processes, dont return any processes from the reified wf
|
65
|
+
return [] if ng_xml.search('/workflow/process').length == 0
|
66
|
+
|
67
|
+
@processes ||=
|
68
|
+
if definition
|
69
|
+
definition.processes.collect do |process|
|
70
|
+
node = ng_xml.at("/workflow/process[@name = '#{process.name}']")
|
71
|
+
process.update!(node, self)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
find_by_terms(:workflow, :process).collect do |x|
|
75
|
+
pnode = Dor::Workflow::Process.new(repository, workflowId, {})
|
76
|
+
pnode.update!(x, self)
|
77
|
+
end.sort_by(&:datetime)
|
78
|
+
end
|
75
79
|
end
|
76
|
-
end
|
77
80
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
+
def workflow_should_show_completed?(processes)
|
82
|
+
processes.all? { |p| ['skipped', 'completed', '', nil].include?(p.status) }
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_solr(solr_doc = {}, *args)
|
86
|
+
wf_name = workflowId.first
|
87
|
+
repo = repository.first
|
88
|
+
wf_solr_type = :string
|
89
|
+
wf_solr_attrs = [:symbol]
|
90
|
+
add_solr_value(solr_doc, 'wf', wf_name, wf_solr_type, wf_solr_attrs)
|
91
|
+
add_solr_value(solr_doc, 'wf_wps', wf_name, wf_solr_type, wf_solr_attrs)
|
92
|
+
add_solr_value(solr_doc, 'wf_wsp', wf_name, wf_solr_type, wf_solr_attrs)
|
93
|
+
status = processes.empty? ? 'empty' : (workflow_should_show_completed?(processes) ? 'completed' : 'active')
|
94
|
+
errors = processes.count(&:error?)
|
95
|
+
add_solr_value(solr_doc, 'workflow_status', [wf_name, status, errors, repo].join('|'), wf_solr_type, wf_solr_attrs)
|
81
96
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
processes.each do |process|
|
98
|
+
next unless process.status.present?
|
99
|
+
|
100
|
+
# add a record of the robot having operated on this item, so we can track robot activity
|
101
|
+
if !process.date_time.blank? && process.status && (process.status == 'completed' || process.status == 'error')
|
102
|
+
solr_doc["wf_#{wf_name}_#{process.name}_dttsi"] = Time.parse(process.date_time).utc.iso8601
|
103
|
+
end
|
104
|
+
# index the error message without the druid so we hopefully get some overlap
|
105
|
+
add_solr_value(solr_doc, 'wf_error', "#{wf_name}:#{process.name}:#{process.error_message}", wf_solr_type, wf_solr_attrs) if process.error_message
|
106
|
+
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.status}", wf_solr_type, wf_solr_attrs)
|
107
|
+
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.status}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
108
|
+
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
109
|
+
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}:#{process.status}", wf_solr_type, wf_solr_attrs)
|
110
|
+
add_solr_value(solr_doc, 'wf_swp', "#{process.status}", wf_solr_type, wf_solr_attrs)
|
111
|
+
add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}", wf_solr_type, wf_solr_attrs)
|
112
|
+
add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
113
|
+
next unless process.state != process.status
|
114
|
+
|
115
|
+
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.state}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
116
|
+
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}:#{process.state}", wf_solr_type, wf_solr_attrs)
|
117
|
+
add_solr_value(solr_doc, 'wf_swp', "#{process.state}", wf_solr_type, wf_solr_attrs)
|
118
|
+
add_solr_value(solr_doc, 'wf_swp', "#{process.state}:#{wf_name}", wf_solr_type, wf_solr_attrs)
|
119
|
+
add_solr_value(solr_doc, 'wf_swp', "#{process.state}:#{wf_name}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
99
120
|
end
|
100
|
-
# index the error message without the druid so we hopefully get some overlap
|
101
|
-
add_solr_value(solr_doc, 'wf_error', "#{wf_name}:#{process.name}:#{process.error_message}", wf_solr_type, wf_solr_attrs) if process.error_message
|
102
|
-
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.status}", wf_solr_type, wf_solr_attrs)
|
103
|
-
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.status}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
104
|
-
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
105
|
-
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}:#{process.status}", wf_solr_type, wf_solr_attrs)
|
106
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.status}", wf_solr_type, wf_solr_attrs)
|
107
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}", wf_solr_type, wf_solr_attrs)
|
108
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
109
|
-
next unless process.state != process.status
|
110
|
-
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.state}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
111
|
-
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}:#{process.state}", wf_solr_type, wf_solr_attrs)
|
112
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.state}", wf_solr_type, wf_solr_attrs)
|
113
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.state}:#{wf_name}", wf_solr_type, wf_solr_attrs)
|
114
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.state}:#{wf_name}:#{process.name}", wf_solr_type, wf_solr_attrs)
|
115
|
-
end
|
116
121
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
122
|
+
solr_doc[Solrizer.solr_name('wf_wps', :symbol)]&.uniq!
|
123
|
+
solr_doc[Solrizer.solr_name('wf_wsp', :symbol)]&.uniq!
|
124
|
+
solr_doc[Solrizer.solr_name('wf_swp', :symbol)]&.uniq!
|
125
|
+
solr_doc['workflow_status']&.uniq!
|
121
126
|
|
122
|
-
|
123
|
-
|
127
|
+
solr_doc
|
128
|
+
end
|
124
129
|
|
125
|
-
|
126
|
-
|
130
|
+
def inspect
|
131
|
+
"#<#{self.class.name}:#{object_id}>"
|
132
|
+
end
|
127
133
|
end
|
128
134
|
end
|
129
135
|
end
|
130
|
-
end
|
data/lib/dor/workflow/process.rb
CHANGED
@@ -1,108 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dor
|
2
|
-
module Workflow
|
3
|
-
|
4
|
-
|
4
|
+
module Workflow
|
5
|
+
class Process
|
6
|
+
attr_reader :owner, :repo, :workflow
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
8
|
+
# @param repo [String] the name of the repository, typically 'dor'
|
9
|
+
# @param workflow [String] the name of the workflow, e.g. 'assemblyWF'
|
10
|
+
# @param attrs [Nokogiri::XML::Node, Hash]
|
11
|
+
def initialize(repo, workflow, attrs)
|
12
|
+
@workflow = workflow
|
13
|
+
@repo = repo
|
14
|
+
if attrs.is_a? Nokogiri::XML::Node
|
15
|
+
init_from_node(attrs)
|
16
|
+
else
|
17
|
+
@attrs = attrs
|
18
|
+
end
|
16
19
|
end
|
17
|
-
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
21
|
+
def init_from_node(node)
|
22
|
+
@attrs = {
|
23
|
+
'name' => node['name'],
|
24
|
+
'sequence' => node['sequence'] ? node['sequence'].to_i : nil,
|
25
|
+
'status' => node['status'], # TODO: see how this affects argo
|
26
|
+
'lifecycle' => node['lifecycle'],
|
27
|
+
'label' => node.at_xpath('label/text()').to_s,
|
28
|
+
'batch_limit' => node['batch-limit'] ? node['batch-limit'].to_i : nil,
|
29
|
+
'error_limit' => node['error-limit'] ? node['error-limit'].to_i : nil,
|
30
|
+
'priority' => node['priority'] ? node['priority'].to_i : 0,
|
31
|
+
'prerequisite' => node.xpath('prereq').collect { |p|
|
32
|
+
repo = (p['repository'].nil? || p['repository'] == @repo) ? nil : p['repository']
|
33
|
+
wf = (p['workflow'].nil? || p['workflow'] == @workflow) ? nil : p['workflow']
|
34
|
+
[repo, wf, p.text.to_s].compact.join(':')
|
35
|
+
}
|
33
36
|
}
|
34
|
-
|
35
|
-
end
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
def name; @attrs['name']; end
|
40
|
+
def sequence; @attrs['sequence']; end
|
41
|
+
def lifecycle; @attrs['lifecycle']; end
|
42
|
+
def label; @attrs['label']; end
|
43
|
+
def batch_limit; @attrs['batch_limit']; end
|
44
|
+
def error_limit; @attrs['error_limit']; end
|
45
|
+
def error_message; @attrs['errorMessage']; end
|
46
|
+
def prerequisite; @attrs['prerequisite']; end
|
47
|
+
def status; @attrs['status']; end
|
48
|
+
def note; @attrs['note']; end
|
49
|
+
def version; @attrs['version']; end
|
50
|
+
def priority; @attrs['priority']; end
|
51
|
+
def completed?; status == 'completed'; end
|
52
|
+
def error?; status == 'error'; end
|
53
|
+
def waiting?; status == 'waiting'; end
|
54
|
+
def date_time; @attrs['datetime']; end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
def archived?
|
57
|
+
@attrs['archived'] =~ /true$/i
|
58
|
+
end
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
|
60
|
+
def ready?
|
61
|
+
self.waiting? && !prerequisite.nil? && prerequisite.all? { |pr| (prq = owner[pr]) && prq.completed? }
|
62
|
+
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
|
64
|
+
def blocked?
|
65
|
+
self.waiting? && !prerequisite.nil? && prerequisite.any? { |pr| (prq = owner[pr]) && (prq.error? || prq.blocked?) }
|
66
|
+
end
|
65
67
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
def state
|
69
|
+
if blocked?
|
70
|
+
'blocked'
|
71
|
+
elsif ready?
|
72
|
+
'ready'
|
73
|
+
else
|
74
|
+
status
|
75
|
+
end
|
73
76
|
end
|
74
|
-
end
|
75
77
|
|
76
|
-
|
77
|
-
|
78
|
-
|
78
|
+
def attempts
|
79
|
+
@attrs['attempts'].to_i
|
80
|
+
end
|
79
81
|
|
80
|
-
|
81
|
-
|
82
|
-
|
82
|
+
def datetime
|
83
|
+
@attrs['datetime'] ? Time.parse(@attrs['datetime']) : nil
|
84
|
+
end
|
83
85
|
|
84
|
-
|
85
|
-
|
86
|
-
|
86
|
+
def elapsed
|
87
|
+
@attrs['elapsed'].nil? ? nil : @attrs['elapsed'].to_f
|
88
|
+
end
|
89
|
+
|
90
|
+
# Updates this object with the attributes passed in.
|
91
|
+
# @param info [Hash,Nokogiri::XML::Element,NilClass]
|
92
|
+
# @param new_owner [Dor::Workflow::Document]
|
93
|
+
def update!(info, new_owner)
|
94
|
+
raise ArgumentError, 'Owner can not be nil. It must be an instance of Dor::Workflow::Document' unless new_owner
|
87
95
|
|
88
|
-
|
89
|
-
|
90
|
-
# @param new_owner [Dor::Workflow::Document]
|
91
|
-
def update!(info, new_owner)
|
92
|
-
raise ArgumentError, 'Owner can not be nil. It must be an instance of Dor::Workflow::Document' unless new_owner
|
93
|
-
@owner = new_owner
|
94
|
-
return self if info.nil?
|
96
|
+
@owner = new_owner
|
97
|
+
return self if info.nil?
|
95
98
|
|
96
|
-
|
97
|
-
|
99
|
+
if info.is_a? Nokogiri::XML::Node
|
100
|
+
info = Hash[info.attributes.collect { |k, v| [k, v.value] }]
|
101
|
+
end
|
102
|
+
@attrs.merge! info
|
103
|
+
self
|
98
104
|
end
|
99
|
-
@attrs.merge! info
|
100
|
-
self
|
101
|
-
end
|
102
105
|
|
103
|
-
|
104
|
-
|
106
|
+
def to_hash
|
107
|
+
@attrs.reject { |k, v| v.nil? || v == 0 || (v.respond_to?(:empty?) && v.empty?) }
|
108
|
+
end
|
105
109
|
end
|
106
110
|
end
|
107
111
|
end
|
108
|
-
end
|