dor-services 8.6.0 → 9.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/config/config_defaults.yml +0 -1
  3. data/config/dev_console_env.rb.example +0 -1
  4. data/lib/dor-services.rb +0 -34
  5. data/lib/dor/models/abstract.rb +1 -47
  6. data/lib/dor/models/admin_policy_object.rb +0 -9
  7. data/lib/dor/models/collection.rb +0 -9
  8. data/lib/dor/models/etd.rb +0 -6
  9. data/lib/dor/models/item.rb +0 -9
  10. data/lib/dor/models/part.rb +0 -2
  11. data/lib/dor/models/set.rb +0 -8
  12. data/lib/dor/services/search_service.rb +1 -0
  13. data/lib/dor/static_config.rb +0 -8
  14. data/lib/dor/static_config/stacks_config.rb +0 -15
  15. data/lib/dor/version.rb +1 -1
  16. metadata +2 -55
  17. data/lib/dor/datastreams/simple_dublin_core_ds.rb +0 -59
  18. data/lib/dor/datastreams/workflow_definition_ds.rb +0 -71
  19. data/lib/dor/datastreams/workflow_ds.rb +0 -20
  20. data/lib/dor/indexers/composite_indexer.rb +0 -27
  21. data/lib/dor/indexers/data_indexer.rb +0 -24
  22. data/lib/dor/indexers/describable_indexer.rb +0 -60
  23. data/lib/dor/indexers/editable_indexer.rb +0 -25
  24. data/lib/dor/indexers/identifiable_indexer.rb +0 -102
  25. data/lib/dor/indexers/process_indexer.rb +0 -58
  26. data/lib/dor/indexers/processable_indexer.rb +0 -99
  27. data/lib/dor/indexers/releasable_indexer.rb +0 -33
  28. data/lib/dor/indexers/workflow_indexer.rb +0 -47
  29. data/lib/dor/indexers/workflows_indexer.rb +0 -34
  30. data/lib/dor/models/workflow_object.rb +0 -28
  31. data/lib/dor/models/workflow_solr_document.rb +0 -93
  32. data/lib/dor/release_tags.rb +0 -13
  33. data/lib/dor/release_tags/identity_metadata.rb +0 -145
  34. data/lib/dor/release_tags/purl.rb +0 -51
  35. data/lib/dor/release_tags/purl_client.rb +0 -44
  36. data/lib/dor/services/release_tag_service.rb +0 -40
  37. data/lib/dor/services/state_service.rb +0 -34
  38. data/lib/dor/services/status_service.rb +0 -125
  39. data/lib/dor/static_config/workflow_config.rb +0 -51
  40. data/lib/dor/workflow/document.rb +0 -72
  41. data/lib/dor/workflow/process.rb +0 -157
@@ -1,99 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dor
4
- class ProcessableIndexer
5
- include SolrDocHelper
6
-
7
- attr_reader :resource
8
- def initialize(resource:)
9
- @resource = resource
10
- @status_service = StatusService.new(resource)
11
- end
12
-
13
- # @return [Hash] the partial solr document for processable concerns
14
- def to_solr
15
- {}.tap do |solr_doc|
16
- add_versions(solr_doc)
17
- add_milestones(solr_doc)
18
- solr_doc['modified_latest_dttsi'] = resource.modified_date.to_datetime.utc.strftime('%FT%TZ')
19
- add_solr_value(solr_doc, 'rights', resource.rights, :string, [:symbol]) if resource.respond_to? :rights
20
- add_status(solr_doc)
21
- end
22
- end
23
-
24
- private
25
-
26
- attr_reader :status_service
27
-
28
- def current_version
29
- @current_version ||= begin
30
- resource.current_version
31
- rescue StandardError
32
- '1'
33
- end
34
- end
35
-
36
- def add_status(solr_doc)
37
- solr_doc['status_ssi'] = status_service.status # status is singular (i.e. the current one)
38
- status_info_hash = status_service.status_info
39
- status_code = status_info_hash[:status_code]
40
- add_solr_value(solr_doc, 'processing_status_text', simplified_status_code_disp_txt(status_code), :string, [:stored_sortable])
41
- solr_doc['processing_status_code_isi'] = status_code
42
- end
43
-
44
- def add_milestones(solr_doc)
45
- status_service.milestones.each do |milestone|
46
- timestamp = milestone[:at].utc.xmlschema
47
- milestone[:version] ||= current_version
48
- solr_doc['lifecycle_ssim'] ||= []
49
- solr_doc['lifecycle_ssim'] << milestone[:milestone]
50
- add_solr_value(solr_doc, 'lifecycle', "#{milestone[:milestone]}:#{timestamp};#{milestone[:version]}", :symbol)
51
- end
52
-
53
- add_sortable_milestones(solr_doc)
54
- end
55
-
56
- def sortable_milestones
57
- sortable = {}
58
- status_service.milestones.each do |milestone|
59
- sortable[milestone[:milestone]] ||= []
60
- sortable[milestone[:milestone]] << milestone[:at].utc.xmlschema
61
- end
62
- sortable
63
- end
64
-
65
- def add_sortable_milestones(solr_doc)
66
- sortable_milestones.each do |milestone, unordered_dates|
67
- dates = unordered_dates.sort
68
- # create the published_dttsi and published_day fields and the like
69
- dates.each do |date|
70
- solr_doc["#{milestone}_dttsim"] ||= []
71
- solr_doc["#{milestone}_dttsim"] << date unless solr_doc["#{milestone}_dttsim"].include?(date)
72
- end
73
- # fields for OAI havester to sort on: _dttsi is trie date +stored +indexed (single valued, i.e. sortable)
74
- solr_doc["#{milestone}_earliest_dttsi"] = dates.first
75
- solr_doc["#{milestone}_latest_dttsi"] = dates.last
76
- end
77
- end
78
-
79
- def add_versions(solr_doc)
80
- current_version_num = current_version.to_i
81
- solr_doc['current_version_isi'] = current_version_num
82
-
83
- return unless resource.respond_to?('versionMetadata')
84
-
85
- # add an entry with version id, tag and description for each version
86
- while current_version_num > 0
87
- new_val = "#{current_version_num};#{resource.versionMetadata.tag_for_version(current_version_num.to_s)};#{resource.versionMetadata.description_for_version(current_version_num.to_s)}"
88
- add_solr_value(solr_doc, 'versions', new_val, :string, [:displayable])
89
- current_version_num -= 1
90
- end
91
- end
92
-
93
- # @return [String] text translation of the status code, minus any trailing parenthetical explanation
94
- # e.g. 'In accessioning (described)' and 'In accessioning (described, published)' both return 'In accessioning'
95
- def simplified_status_code_disp_txt(status_code)
96
- StatusService::STATUS_CODE_DISP_TXT[status_code].gsub(/\(.*\)$/, '').strip
97
- end
98
- end
99
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dor
4
- class ReleasableIndexer
5
- include SolrDocHelper
6
-
7
- attr_reader :resource
8
- def initialize(resource:)
9
- @resource = resource
10
- end
11
-
12
- # @return [Hash] the partial solr document for releasable concerns
13
- def to_solr
14
- solr_doc = {}
15
- # TODO: sort of worried about the performance impact in bulk reindex
16
- # situations, since released_for recurses all parent collections. jmartin 2015-07-14
17
- released_for.each do |release_target, release_info|
18
- add_solr_value(solr_doc, 'released_to', release_target, :symbol, []) if release_info['release']
19
- end
20
-
21
- # TODO: need to solrize whether item is released to purl? does released_for return that?
22
- # logic is: "True when there is a published lifecycle and Access Rights is anything but Dark"
23
-
24
- solr_doc
25
- end
26
-
27
- private
28
-
29
- def released_for
30
- ReleaseTagService.for(resource).released_for(skip_live_purl: true)
31
- end
32
- end
33
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dor
4
- # Indexes the objects position in workflows
5
- class WorkflowIndexer
6
- # @param [Workflow::Response::Workflow] workflow the workflow document to index
7
- def initialize(workflow:)
8
- @workflow = workflow
9
- end
10
-
11
- # @return [Hash] the partial solr document for the workflow document
12
- def to_solr
13
- WorkflowSolrDocument.new do |solr_doc|
14
- solr_doc.name = workflow_name
15
-
16
- errors = 0 # The error count is used by the Report class in Argo
17
- processes.each do |process|
18
- ProcessIndexer.new(solr_doc: solr_doc, workflow_name: workflow_name, process: process).to_solr
19
- errors += 1 if process.status == 'error'
20
- end
21
- solr_doc.status = [workflow_name, workflow_status, errors, repository].join('|')
22
- end
23
- end
24
-
25
- private
26
-
27
- attr_reader :workflow
28
- delegate :workflow_name, :repository, to: :workflow
29
-
30
- def definition_process_names
31
- @definition_process_names ||= begin
32
- definition = Dor::Config.workflow.client.workflow_template(workflow_name)
33
- definition['processes'].map { |p| p['name'] }
34
- end
35
- end
36
-
37
- def processes
38
- @processes ||= definition_process_names.map do |process_name|
39
- workflow.process_for_recent_version(name: process_name)
40
- end
41
- end
42
-
43
- def workflow_status
44
- workflow.complete? ? 'completed' : 'active'
45
- end
46
- end
47
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dor
4
- # Indexes the objects position in workflows
5
- class WorkflowsIndexer
6
- attr_reader :resource
7
- def initialize(resource:)
8
- @resource = resource
9
- end
10
-
11
- # @return [Hash] the partial solr document for workflow concerns
12
- def to_solr
13
- WorkflowSolrDocument.new do |combined_doc|
14
- workflows.each do |wf|
15
- doc = WorkflowIndexer.new(workflow: wf).to_solr
16
- combined_doc.merge!(doc)
17
- end
18
- end.to_h
19
- end
20
-
21
- private
22
-
23
- # @return [Array<Workflow::Response::Workflow>]
24
- def workflows
25
- all_workflows.workflows
26
- end
27
-
28
- # TODO: remove Dor::Workflow::Document
29
- # @return [Workflow::Response::Workflows]
30
- def all_workflows
31
- @all_workflows ||= Dor::Config.workflow.client.workflow_routes.all_workflows pid: resource.pid
32
- end
33
- end
34
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'dor/datastreams/workflow_definition_ds'
4
-
5
- module Dor
6
- # @deprecated
7
- class WorkflowObject < Dor::Abstract
8
- has_object_type 'workflow'
9
- has_metadata name: 'workflowDefinition', type: Dor::WorkflowDefinitionDs, label: 'Workflow Definition'
10
-
11
- self.resource_indexer = CompositeIndexer.new(
12
- DataIndexer,
13
- DescribableIndexer,
14
- IdentifiableIndexer,
15
- ProcessableIndexer,
16
- WorkflowsIndexer
17
- )
18
-
19
- def self.find_by_name(name)
20
- Dor::WorkflowObject.where(Solrizer.solr_name('workflow_name', :symbol) => name).first
21
- end
22
-
23
- # @return [Dor::WorkflowDefinitionDs]
24
- def definition
25
- datastreams['workflowDefinition']
26
- end
27
- end
28
- end
@@ -1,93 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dor
4
- # Represents that part of the solr document that holds workflow data
5
- class WorkflowSolrDocument
6
- WORKFLOW_SOLR = 'wf_ssim'
7
- # field that indexes workflow name, process status then process name
8
- WORKFLOW_WPS_SOLR = 'wf_wps_ssim'
9
- # field that indexes workflow name, process name then process status
10
- WORKFLOW_WSP_SOLR = 'wf_wsp_ssim'
11
- # field that indexes process status, workflowname then process name
12
- WORKFLOW_SWP_SOLR = 'wf_swp_ssim'
13
- WORKFLOW_ERROR_SOLR = 'wf_error_ssim'
14
- WORKFLOW_STATUS_SOLR = 'workflow_status_ssim'
15
-
16
- KEYS_TO_MERGE = [
17
- WORKFLOW_SOLR,
18
- WORKFLOW_WPS_SOLR,
19
- WORKFLOW_WSP_SOLR,
20
- WORKFLOW_SWP_SOLR,
21
- WORKFLOW_STATUS_SOLR,
22
- WORKFLOW_ERROR_SOLR
23
- ].freeze
24
-
25
- def initialize
26
- @data = empty_document
27
- yield self if block_given?
28
- end
29
-
30
- def name=(wf_name)
31
- data[WORKFLOW_SOLR] += [wf_name]
32
- data[WORKFLOW_WPS_SOLR] += [wf_name]
33
- data[WORKFLOW_WSP_SOLR] += [wf_name]
34
- end
35
-
36
- def status=(status)
37
- data[WORKFLOW_STATUS_SOLR] += [status]
38
- end
39
-
40
- def error=(message)
41
- data[WORKFLOW_ERROR_SOLR] += [message]
42
- end
43
-
44
- # Add to the field that indexes workflow name, process status then process name
45
- def add_wps(*messages)
46
- data[WORKFLOW_WPS_SOLR] += messages
47
- end
48
-
49
- # Add to the field that indexes workflow name, process name then process status
50
- def add_wsp(*messages)
51
- data[WORKFLOW_WSP_SOLR] += messages
52
- end
53
-
54
- # Add to the field that indexes process status, workflow name then process name
55
- def add_swp(*messages)
56
- data[WORKFLOW_SWP_SOLR] += messages
57
- end
58
-
59
- # Add the processes data_time attribute to the solr document
60
- # @param [String] wf_name
61
- # @param [String] process_name
62
- # @param [Time] time
63
- def add_process_time(wf_name, process_name, time)
64
- data["wf_#{wf_name}_#{process_name}_dttsi"] = time.utc.iso8601
65
- end
66
-
67
- def to_h
68
- KEYS_TO_MERGE.each { |k| data[k].uniq! }
69
- data
70
- end
71
-
72
- delegate :except, :[], to: :data
73
-
74
- # @param [WorkflowSolrDocument] doc
75
- def merge!(doc)
76
- # This is going to get the date fields, e.g. `wf_assemblyWF_jp2-create_dttsi'
77
- @data.merge!(doc.except(*KEYS_TO_MERGE))
78
-
79
- # Combine the non-unique fields together
80
- KEYS_TO_MERGE.each do |k|
81
- data[k] += doc[k]
82
- end
83
- end
84
-
85
- private
86
-
87
- attr_reader :data
88
-
89
- def empty_document
90
- KEYS_TO_MERGE.each_with_object({}) { |k, obj| obj[k] = [] }
91
- end
92
- end
93
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dor
4
- module ReleaseTags
5
- extend ActiveSupport::Autoload
6
-
7
- eager_autoload do
8
- autoload :PurlClient
9
- autoload :Purl
10
- autoload :IdentityMetadata
11
- end
12
- end
13
- end
@@ -1,145 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dor
4
- module ReleaseTags
5
- class IdentityMetadata
6
- # Determine projects in which an item is released
7
- # @param [Dor::Item] item to get the release tags for
8
- # @return [Hash{String => Boolean}] all namespaces, keys are Project name Strings, values are Boolean
9
- def self.for(item)
10
- new(item)
11
- end
12
-
13
- def initialize(item)
14
- @item = item
15
- end
16
-
17
- # Called in Dor::UpdateMarcRecordService (in dor-services-app too)
18
- # Determine projects in which an item is released
19
- # @param [Hash{String => Boolean}] the released hash to add tags to
20
- # @return [Hash{String => Boolean}] all namespaces, keys are Project name Strings, values are Boolean
21
- def released_for(released_hash)
22
- # Get the most recent self tag for all targets and retain their result since most recent self always trumps any other non self tags
23
- latest_self_tags = newest_release_tag self_release_tags(release_tags)
24
- latest_self_tags.each do |key, payload|
25
- released_hash[key] = { 'release' => payload['release'] }
26
- end
27
-
28
- # With Self Tags resolved we now need to deal with tags on all sets this object is part of.
29
- # Get all release tags on the item and strip out the what = self ones, we've already processed all the self tags on this item.
30
- # This will be where we store all tags that apply, regardless of their timestamp:
31
- potential_applicable_release_tags = tags_for_what_value(release_tags_for_item_and_all_governing_sets, 'collection')
32
- administrative_tags = item.tags # Get admin tags once here and pass them down
33
-
34
- # We now have the keys for all potential releases, we need to check the tags: the most recent timestamp with an explicit true or false wins.
35
- # In a nil case, the lack of an explicit false tag we do nothing.
36
- # Don't bother checking if already added to the release hash, they were added due to a self tag so that has won
37
- (potential_applicable_release_tags.keys - released_hash.keys).each do |key|
38
- latest_tag = latest_applicable_release_tag_in_array(potential_applicable_release_tags[key], administrative_tags)
39
- next if latest_tag.nil? # Otherwise, we have a valid tag, record it
40
-
41
- released_hash[key] = { 'release' => latest_tag['release'] }
42
- end
43
- released_hash
44
- end
45
-
46
- # Take an item and get all of its release tags and all tags on collections it is a member of it
47
- # @return [Hash] a hash of all tags
48
- def release_tags_for_item_and_all_governing_sets
49
- return_tags = release_tags || {}
50
- item.collections.each do |collection|
51
- next if collection.id == item.id # recursive, so parents of parents are found, but we need to avoid an infinite loop if the collection references itself (i.e. bad data)
52
-
53
- release_service = self.class.for(collection)
54
- return_tags = combine_two_release_tag_hashes(return_tags, release_service.release_tags_for_item_and_all_governing_sets)
55
- end
56
- return_tags
57
- end
58
-
59
- # Take a hash of tags as obtained via Dor::Item.release_tags and returns the newest tag for each namespace
60
- # @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
61
- # @return [Hash] a hash of latest tags for each to value
62
- def newest_release_tag(tags)
63
- Hash[tags.map { |key, val| [key, newest_release_tag_in_an_array(val)] }]
64
- end
65
-
66
- private
67
-
68
- delegate :release_tags, to: :item
69
-
70
- # Take a hash of tags as obtained via Dor::Item.release_tags and returns all self tags
71
- # @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
72
- # @return [Hash] a hash of self tags for each to value
73
- def self_release_tags(tags)
74
- tags_for_what_value(tags, 'self')
75
- end
76
-
77
- # Take a hash of tags and return all tags with the matching what target
78
- # @param tags [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
79
- # @param what_target [String] the target for the 'what' key, self or collection
80
- # @return [Hash] a hash of self tags for each to value
81
- def tags_for_what_value(tags, what_target)
82
- return_hash = {}
83
- tags.keys.each do |key|
84
- self_tags = tags[key].select { |tag| tag['what'].casecmp(what_target) == 0 }
85
- return_hash[key] = self_tags unless self_tags.empty?
86
- end
87
- return_hash
88
- end
89
-
90
- # Take two hashes of tags and combine them, will not overwrite but will enforce uniqueness of the tags
91
- # @param hash_one [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
92
- # @param hash_two [Hash] a hash of tags obtained via Dor::Item.release_tags or matching format
93
- # @return [Hash] the combined hash with uniquiness enforced
94
- def combine_two_release_tag_hashes(hash_one, hash_two)
95
- hash_two.keys.each do |key|
96
- hash_one[key] = hash_two[key] if hash_one[key].nil?
97
- hash_one[key] = (hash_one[key] + hash_two[key]).uniq unless hash_one[key].nil?
98
- end
99
- hash_one
100
- end
101
-
102
- # Takes an array of release tags and returns the most recent one
103
- # @param array_of_tags [Array] an array of hashes, each hash a release tag
104
- # @return [Hash] the most recent tag
105
- def newest_release_tag_in_an_array(array_of_tags)
106
- latest_tag_in_array = array_of_tags[0] || {}
107
- array_of_tags.each do |tag|
108
- latest_tag_in_array = tag if tag['when'] > latest_tag_in_array['when']
109
- end
110
- latest_tag_in_array
111
- end
112
-
113
- # Takes a tag and returns true or false if it applies to the specific item
114
- # @param release_tag [Hash] the tag in a hashed form
115
- # @param admin_tags [Array] the administrative tags on an item, if not supplied it will attempt to retrieve them
116
- # @return [Boolean] true or false if it applies (not true or false if it is released, that is the release_tag data)
117
- def does_release_tag_apply(release_tag, admin_tags = false)
118
- # Is the tag global or restricted
119
- return true if release_tag['tag'].nil? # no specific tag specificied means this tag is global to all members of the collection
120
-
121
- admin_tags ||= item.tags # We use false instead of [], since an item can have no admin_tags at which point we'd be passing this var as [] and would not attempt to retrieve it
122
- admin_tags.include?(release_tag['tag'])
123
- end
124
-
125
- # Takes an array of release tags and returns the most recent one that applies to this item
126
- # @param release_tags [Array] an array of release tags in hashed form
127
- # @param admin_tags [Array] the administrative tags on an on item
128
- # @return [Hash] the tag, or nil if none applicable
129
- def latest_applicable_release_tag_in_array(release_tags, admin_tags)
130
- newest_tag = newest_release_tag_in_an_array(release_tags)
131
- return newest_tag if does_release_tag_apply(newest_tag, admin_tags)
132
-
133
- # The latest tag wasn't applicable, slice it off and try again
134
- # This could be optimized by reordering on the timestamp and just running down it instead of constantly resorting, at least if we end up getting numerous release tags on an item
135
- release_tags.slice!(release_tags.index(newest_tag))
136
-
137
- return latest_applicable_release_tag_in_array(release_tags, admin_tags) unless release_tags.empty? # Try again after dropping the inapplicable
138
-
139
- nil # We're out of tags, no applicable ones
140
- end
141
-
142
- attr_reader :item
143
- end
144
- end
145
- end