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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dor-services.rb +7 -6
  3. data/lib/dor/certificate_authenticated_rest_resource_factory.rb +2 -1
  4. data/lib/dor/config.rb +38 -37
  5. data/lib/dor/datastreams/administrative_metadata_ds.rb +98 -98
  6. data/lib/dor/datastreams/content_metadata_ds.rb +26 -17
  7. data/lib/dor/datastreams/datastream_spec_solrizer.rb +4 -2
  8. data/lib/dor/datastreams/default_object_rights_ds.rb +10 -7
  9. data/lib/dor/datastreams/desc_metadata_ds.rb +6 -6
  10. data/lib/dor/datastreams/embargo_metadata_ds.rb +94 -94
  11. data/lib/dor/datastreams/events_ds.rb +55 -54
  12. data/lib/dor/datastreams/geo_metadata_ds.rb +7 -6
  13. data/lib/dor/datastreams/identity_metadata_ds.rb +128 -125
  14. data/lib/dor/datastreams/provenance_metadata_ds.rb +3 -1
  15. data/lib/dor/datastreams/rights_metadata_ds.rb +4 -4
  16. data/lib/dor/datastreams/role_metadata_ds.rb +42 -42
  17. data/lib/dor/datastreams/simple_dublin_core_ds.rb +45 -43
  18. data/lib/dor/datastreams/technical_metadata_ds.rb +3 -1
  19. data/lib/dor/datastreams/version_metadata_ds.rb +12 -5
  20. data/lib/dor/datastreams/workflow_definition_ds.rb +74 -73
  21. data/lib/dor/datastreams/workflow_ds.rb +12 -7
  22. data/lib/dor/exceptions.rb +2 -0
  23. data/lib/dor/indexers/data_indexer.rb +16 -0
  24. data/lib/dor/indexers/describable_indexer.rb +2 -0
  25. data/lib/dor/indexers/editable_indexer.rb +2 -0
  26. data/lib/dor/indexers/identifiable_indexer.rb +23 -8
  27. data/lib/dor/indexers/processable_indexer.rb +2 -0
  28. data/lib/dor/indexers/releasable_indexer.rb +2 -0
  29. data/lib/dor/models/abstract.rb +2 -0
  30. data/lib/dor/models/admin_policy_object.rb +2 -0
  31. data/lib/dor/models/agreement.rb +2 -0
  32. data/lib/dor/models/collection.rb +3 -0
  33. data/lib/dor/models/concerns/assembleable.rb +2 -0
  34. data/lib/dor/models/concerns/contentable.rb +5 -2
  35. data/lib/dor/models/concerns/describable.rb +7 -2
  36. data/lib/dor/models/concerns/editable.rb +28 -21
  37. data/lib/dor/models/concerns/embargoable.rb +4 -0
  38. data/lib/dor/models/concerns/eventable.rb +2 -0
  39. data/lib/dor/models/concerns/geoable.rb +2 -0
  40. data/lib/dor/models/concerns/governable.rb +7 -2
  41. data/lib/dor/models/concerns/identifiable.rb +33 -34
  42. data/lib/dor/models/concerns/itemizable.rb +4 -1
  43. data/lib/dor/models/concerns/preservable.rb +2 -0
  44. data/lib/dor/models/concerns/processable.rb +15 -9
  45. data/lib/dor/models/concerns/publishable.rb +9 -4
  46. data/lib/dor/models/concerns/releaseable.rb +21 -11
  47. data/lib/dor/models/concerns/rightsable.rb +2 -0
  48. data/lib/dor/models/concerns/shelvable.rb +6 -2
  49. data/lib/dor/models/concerns/versionable.rb +8 -4
  50. data/lib/dor/models/item.rb +2 -0
  51. data/lib/dor/models/set.rb +2 -0
  52. data/lib/dor/models/workflow_object.rb +5 -1
  53. data/lib/dor/rest_resource_factory.rb +2 -0
  54. data/lib/dor/services/cleanup_reset_service.rb +2 -1
  55. data/lib/dor/services/cleanup_service.rb +2 -1
  56. data/lib/dor/services/digital_stacks_service.rb +3 -1
  57. data/lib/dor/services/indexing_service.rb +3 -1
  58. data/lib/dor/services/merge_service.rb +6 -4
  59. data/lib/dor/services/metadata_handlers/catalog_handler.rb +2 -0
  60. data/lib/dor/services/metadata_service.rb +4 -4
  61. data/lib/dor/services/public_desc_metadata_service.rb +16 -8
  62. data/lib/dor/services/public_xml_service.rb +7 -4
  63. data/lib/dor/services/registration_service.rb +25 -20
  64. data/lib/dor/services/reset_workspace_service.rb +4 -4
  65. data/lib/dor/services/sdr_ingest_service.rb +4 -2
  66. data/lib/dor/services/search_service.rb +8 -9
  67. data/lib/dor/services/suri_service.rb +3 -2
  68. data/lib/dor/services/technical_metadata_service.rb +15 -9
  69. data/lib/dor/services/thumbnail_service.rb +14 -10
  70. data/lib/dor/utils/hydrus_shims.rb +2 -0
  71. data/lib/dor/utils/ng_tidy.rb +3 -7
  72. data/lib/dor/utils/predicate_patch.rb +2 -0
  73. data/lib/dor/utils/sdr_client.rb +3 -0
  74. data/lib/dor/utils/solr_doc_helper.rb +4 -2
  75. data/lib/dor/version.rb +3 -1
  76. data/lib/dor/workflow/document.rb +113 -108
  77. data/lib/dor/workflow/process.rb +90 -87
  78. data/lib/tasks/rdoc.rake +4 -3
  79. 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'".freeze
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 # break out of the loop so we stop searching
53
+ break # break out of the loop so we stop searching
50
54
  end
51
55
 
52
56
  thumb_image
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hydrus
2
4
  # These shims allow DOR to interact seamlessly with Hydrus' custom models
3
5
  class Item < Dor::Item
@@ -1,5 +1,6 @@
1
- class Nokogiri::XML::Text
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
- EOC
29
+ EOC
33
30
 
34
31
  def prettify
35
32
  PRETTIFY_XSLT.transform(self).to_xml
36
33
  end
37
-
38
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Monkey patch ActiveFedora::RelsExtDatastream.short_predicate to
2
4
  # create missing mappings on the fly.
3
5
 
@@ -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
- when :symbol
5
- index_types << field_type
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dor
2
- VERSION = '6.0.0'.freeze
4
+ VERSION = '6.0.1'
3
5
  end
@@ -1,130 +1,135 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dor
2
- module Workflow
3
- class Document
4
- include SolrDocHelper
5
- include ::OM::XML::Document
6
-
7
- set_terminology do |t|
8
- t.root(:path => 'workflow')
9
- t.repository(:path => {:attribute => 'repository'})
10
- t.workflowId(:path => {:attribute => 'id'})
11
- t.process do
12
- t.name_(:path => {:attribute => 'name'})
13
- t.status(:path => {:attribute => 'status'})
14
- t.timestamp(:path => {:attribute => 'datetime'}) # , :data_type => :date)
15
- t.elapsed(:path => {:attribute => 'elapsed'})
16
- t.lifecycle(:path => {:attribute => 'lifecycle'})
17
- t.attempts(:path => {:attribute => 'attempts'}, :index_as => [:not_searchable])
18
- t.version(:path => {:attribute => 'version'})
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
- @@definitions = {}
24
+ @@definitions = {}
23
25
 
24
- def initialize(node)
25
- self.ng_xml = Nokogiri::XML(node)
26
- end
26
+ def initialize(node)
27
+ self.ng_xml = Nokogiri::XML(node)
28
+ end
27
29
 
28
- # is this an incomplete workflow with steps that have a priority > 0
29
- def expedited?
30
- processes.any? { |proc| !proc.completed? && proc.priority.to_i > 0 }
31
- end
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
- # @return [Integer] value of the first > 0 priority. Defaults to 0
34
- def priority
35
- processes.map {|proc| proc.priority.to_i }.detect(0) {|p| p > 0}
36
- end
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
- # @return [Boolean] if any process node does not have version, returns true, false otherwise (all processes have version)
39
- def active?
40
- ng_xml.at_xpath('/workflow/process[not(@version)]') ? true : false
41
- end
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
- # @return [Dor::WorkflowDefinitionDs]
44
- def definition
45
- @definition ||= begin
46
- if @@definitions.key? workflowId.first
47
- @@definitions[workflowId.first]
48
- else
49
- wfo = Dor::WorkflowObject.find_by_name(workflowId.first)
50
- wf_def = wfo ? wfo.definition : nil
51
- @@definitions[workflowId.first] = wf_def
52
- wf_def
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
- def [](value)
58
- processes.find { |p| p.name == value }
59
- end
59
+ def [](value)
60
+ processes.find { |p| p.name == value }
61
+ end
60
62
 
61
- def processes
62
- # if the workflow service didnt return any processes, dont return any processes from the reified wf
63
- return [] if ng_xml.search('/workflow/process').length == 0
64
- @processes ||=
65
- if definition
66
- definition.processes.collect do |process|
67
- node = ng_xml.at("/workflow/process[@name = '#{process.name}']")
68
- process.update!(node, self)
69
- end
70
- else
71
- find_by_terms(:workflow, :process).collect do |x|
72
- pnode = Dor::Workflow::Process.new(repository, workflowId, {})
73
- pnode.update!(x, self)
74
- end.sort_by(&:datetime)
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
- def workflow_should_show_completed?(processes)
79
- processes.all? {|p| ['skipped', 'completed', '', nil].include?(p.status)}
80
- end
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
- def to_solr(solr_doc = {}, *args)
83
- wf_name = workflowId.first
84
- repo = repository.first
85
- wf_solr_type = :string
86
- wf_solr_attrs = [:symbol]
87
- add_solr_value(solr_doc, 'wf', wf_name, wf_solr_type, wf_solr_attrs)
88
- add_solr_value(solr_doc, 'wf_wps', wf_name, wf_solr_type, wf_solr_attrs)
89
- add_solr_value(solr_doc, 'wf_wsp', wf_name, wf_solr_type, wf_solr_attrs)
90
- status = processes.empty? ? 'empty' : (workflow_should_show_completed?(processes) ? 'completed' : 'active')
91
- errors = processes.count(&:error?)
92
- add_solr_value(solr_doc, 'workflow_status', [wf_name, status, errors, repo].join('|'), wf_solr_type, wf_solr_attrs)
93
-
94
- processes.each do |process|
95
- next unless process.status.present?
96
- # add a record of the robot having operated on this item, so we can track robot activity
97
- if !process.date_time.blank? && process.status && (process.status == 'completed' || process.status == 'error')
98
- solr_doc["wf_#{wf_name}_#{process.name}_dttsi"] = Time.parse(process.date_time).utc.iso8601
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
- solr_doc[Solrizer.solr_name('wf_wps', :symbol)].uniq! if solr_doc[Solrizer.solr_name('wf_wps', :symbol)]
118
- solr_doc[Solrizer.solr_name('wf_wsp', :symbol)].uniq! if solr_doc[Solrizer.solr_name('wf_wsp', :symbol)]
119
- solr_doc[Solrizer.solr_name('wf_swp', :symbol)].uniq! if solr_doc[Solrizer.solr_name('wf_swp', :symbol)]
120
- solr_doc['workflow_status'].uniq! if solr_doc['workflow_status']
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
- solr_doc
123
- end
127
+ solr_doc
128
+ end
124
129
 
125
- def inspect
126
- "#<#{self.class.name}:#{object_id}>"
130
+ def inspect
131
+ "#<#{self.class.name}:#{object_id}>"
132
+ end
127
133
  end
128
134
  end
129
135
  end
130
- end
@@ -1,108 +1,111 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dor
2
- module Workflow
3
- class Process
4
- attr_reader :owner, :repo, :workflow
4
+ module Workflow
5
+ class Process
6
+ attr_reader :owner, :repo, :workflow
5
7
 
6
- # @param repo [String] the name of the repository, typically 'dor'
7
- # @param workflow [String] the name of the workflow, e.g. 'assemblyWF'
8
- # @param attrs [Nokogiri::XML::Node, Hash]
9
- def initialize(repo, workflow, attrs)
10
- @workflow = workflow
11
- @repo = repo
12
- if attrs.is_a? Nokogiri::XML::Node
13
- init_from_node(attrs)
14
- else
15
- @attrs = attrs
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
- def init_from_node(node)
20
- @attrs = {
21
- 'name' => node['name'],
22
- 'sequence' => node['sequence'] ? node['sequence'].to_i : nil,
23
- 'status' => node['status'], # TODO: see how this affects argo
24
- 'lifecycle' => node['lifecycle'],
25
- 'label' => node.at_xpath('label/text()').to_s,
26
- 'batch_limit' => node['batch-limit'] ? node['batch-limit'].to_i : nil,
27
- 'error_limit' => node['error-limit'] ? node['error-limit'].to_i : nil,
28
- 'priority' => node['priority'] ? node['priority'].to_i : 0,
29
- 'prerequisite' => node.xpath('prereq').collect { |p|
30
- repo = (p['repository'].nil? || p['repository'] == @repo ) ? nil : p['repository']
31
- wf = (p['workflow'].nil? || p['workflow'] == @workflow) ? nil : p['workflow']
32
- [repo, wf, p.text.to_s].compact.join(':')
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
- def name ; @attrs['name'] ; end
38
- def sequence ; @attrs['sequence'] ; end
39
- def lifecycle ; @attrs['lifecycle'] ; end
40
- def label ; @attrs['label'] ; end
41
- def batch_limit ; @attrs['batch_limit'] ; end
42
- def error_limit ; @attrs['error_limit'] ; end
43
- def error_message ; @attrs['errorMessage'] ; end
44
- def prerequisite ; @attrs['prerequisite'] ; end
45
- def status ; @attrs['status'] ; end
46
- def note ; @attrs['note'] ; end
47
- def version ; @attrs['version'] ; end
48
- def priority ; @attrs['priority'] ; end
49
- def completed? ; status == 'completed' ; end
50
- def error? ; status == 'error' ; end
51
- def waiting? ; status == 'waiting' ; end
52
- def date_time ; @attrs['datetime'] ; end
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
- def archived?
55
- @attrs['archived'] =~ /true$/i
56
- end
56
+ def archived?
57
+ @attrs['archived'] =~ /true$/i
58
+ end
57
59
 
58
- def ready?
59
- self.waiting? && !prerequisite.nil? && prerequisite.all? { |pr| (prq = owner[pr]) && prq.completed? }
60
- end
60
+ def ready?
61
+ self.waiting? && !prerequisite.nil? && prerequisite.all? { |pr| (prq = owner[pr]) && prq.completed? }
62
+ end
61
63
 
62
- def blocked?
63
- self.waiting? && !prerequisite.nil? && prerequisite.any? { |pr| (prq = owner[pr]) && (prq.error? || prq.blocked?) }
64
- end
64
+ def blocked?
65
+ self.waiting? && !prerequisite.nil? && prerequisite.any? { |pr| (prq = owner[pr]) && (prq.error? || prq.blocked?) }
66
+ end
65
67
 
66
- def state
67
- if blocked?
68
- 'blocked'
69
- elsif ready?
70
- 'ready'
71
- else
72
- status
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
- def attempts
77
- @attrs['attempts'].to_i
78
- end
78
+ def attempts
79
+ @attrs['attempts'].to_i
80
+ end
79
81
 
80
- def datetime
81
- @attrs['datetime'] ? Time.parse(@attrs['datetime']) : nil
82
- end
82
+ def datetime
83
+ @attrs['datetime'] ? Time.parse(@attrs['datetime']) : nil
84
+ end
83
85
 
84
- def elapsed
85
- @attrs['elapsed'].nil? ? nil : @attrs['elapsed'].to_f
86
- end
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
- # Updates this object with the attributes passed in.
89
- # @param info [Hash,Nokogiri::XML::Element,NilClass]
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
- if info.is_a? Nokogiri::XML::Node
97
- info = Hash[info.attributes.collect { |k, v| [k, v.value] }]
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
- def to_hash
104
- @attrs.reject { |k, v| v.nil? || v == 0 || (v.respond_to?(:empty?) && v.empty?) }
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