dor-services 6.6.2 → 6.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/dev_console_env.rb.example +1 -1
- data/lib/dor-services.rb +3 -0
- data/lib/dor/datastreams/workflow_ds.rb +6 -4
- data/lib/dor/exceptions.rb +3 -0
- data/lib/dor/indexers/workflow_indexer.rb +67 -10
- data/lib/dor/indexers/workflows_indexer.rb +28 -0
- data/lib/dor/models/admin_policy_object.rb +1 -1
- data/lib/dor/models/collection.rb +1 -1
- data/lib/dor/models/concerns/contentable.rb +3 -14
- data/lib/dor/models/concerns/versionable.rb +2 -2
- data/lib/dor/models/item.rb +1 -1
- data/lib/dor/models/set.rb +1 -1
- data/lib/dor/models/workflow_object.rb +1 -1
- data/lib/dor/models/workflow_solr_document.rb +93 -0
- data/lib/dor/services/cleanup_reset_service.rb +1 -1
- data/lib/dor/services/cleanup_service.rb +1 -1
- data/lib/dor/services/decommission_service.rb +31 -0
- data/lib/dor/services/metadata_handlers/catalog_handler.rb +5 -4
- data/lib/dor/services/metadata_service.rb +12 -29
- data/lib/dor/services/status_service.rb +1 -1
- data/lib/dor/services/version_service.rb +4 -4
- data/lib/dor/version.rb +1 -1
- data/lib/dor/workflow/document.rb +0 -73
- metadata +7 -25
- data/lib/dor/services/registration_service.rb +0 -202
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49efa35d39eee0748121dad21f44e871d6ea38eff28dc1719f7d13061eaab269
|
4
|
+
data.tar.gz: d1e0418a853a958966e7247e9c2ca0ceaf0739784ee3da2e3a0ab1a4f8a2f67d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37ac6a9d98625fb2272a5e541d6cf99d4b3f6d7e615c000b22aa6c51b49ed917b912a30f77c293da356107f2418fa60d5c70a5a3b84f31bb52fa149b13f3601d
|
7
|
+
data.tar.gz: 2401c8bfef4aa070e5672227e67c53a29dee353dbe58fa73922f4a3409d1b23f0ad8baf9d5e30fa4c4e0d87062e0c38d37fbc0ac74cf31fd740d6d33fba84fea
|
data/lib/dor-services.rb
CHANGED
@@ -91,6 +91,7 @@ module Dor
|
|
91
91
|
autoload :ProcessableIndexer
|
92
92
|
autoload :ReleasableIndexer
|
93
93
|
autoload :WorkflowIndexer
|
94
|
+
autoload :WorkflowsIndexer
|
94
95
|
end
|
95
96
|
|
96
97
|
# datastreams
|
@@ -144,6 +145,7 @@ module Dor
|
|
144
145
|
autoload :Collection
|
145
146
|
autoload :AdminPolicyObject
|
146
147
|
autoload :WorkflowObject
|
148
|
+
autoload :WorkflowSolrDocument
|
147
149
|
end
|
148
150
|
end
|
149
151
|
|
@@ -155,6 +157,7 @@ module Dor
|
|
155
157
|
autoload :CreateWorkflowService
|
156
158
|
autoload :CreativeCommonsLicenseService
|
157
159
|
autoload :DatastreamBuilder
|
160
|
+
autoload :DecommissionService
|
158
161
|
autoload :DigitalStacksService
|
159
162
|
autoload :DublinCoreService
|
160
163
|
autoload :FileMetadataMergeService
|
@@ -35,7 +35,7 @@ module Dor
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def get_workflow(wf, repo = 'dor')
|
38
|
-
xml = Dor::Config.workflow.client.
|
38
|
+
xml = Dor::Config.workflow.client.workflow_xml(repo, pid, wf)
|
39
39
|
xml = Nokogiri::XML(xml)
|
40
40
|
return nil if xml.xpath('workflow').length == 0
|
41
41
|
|
@@ -55,14 +55,16 @@ module Dor
|
|
55
55
|
# service directly
|
56
56
|
def content(refresh = false)
|
57
57
|
@content = nil if refresh
|
58
|
-
@content ||= Dor::Config.workflow.client.
|
58
|
+
@content ||= Dor::Config.workflow.client.all_workflows_xml pid
|
59
59
|
rescue Dor::WorkflowException => e
|
60
|
+
# TODO: I don't understand when this would be useful as this block ends up calling the workflow service too.
|
61
|
+
# Why not just raise an exception here?
|
60
62
|
Dor.logger.warn "Unable to connect to the workflow service #{e}. Falling back to placeholder XML"
|
61
63
|
xml = Nokogiri::XML(%(<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<workflows objectId="#{pid}"/>))
|
62
64
|
digital_object.datastreams.keys.each do |dsid|
|
63
65
|
next unless dsid =~ /WF$/
|
64
66
|
|
65
|
-
ds_content = Nokogiri::XML(Dor::Config.workflow.client.
|
67
|
+
ds_content = Nokogiri::XML(Dor::Config.workflow.client.workflow_xml('dor', pid, dsid))
|
66
68
|
xml.root.add_child(ds_content.root)
|
67
69
|
end
|
68
70
|
@content ||= xml.to_xml
|
@@ -83,7 +85,7 @@ module Dor
|
|
83
85
|
end
|
84
86
|
|
85
87
|
def to_solr(solr_doc = {}, *_args)
|
86
|
-
# noop - indexing is done by the
|
88
|
+
# noop - indexing is done by the WorkflowsIndexer
|
87
89
|
solr_doc
|
88
90
|
end
|
89
91
|
|
data/lib/dor/exceptions.rb
CHANGED
@@ -11,6 +11,9 @@ module Dor
|
|
11
11
|
# rubocop:disable Lint/InheritException
|
12
12
|
# See https://github.com/rubocop-hq/rubocop/issues/6770
|
13
13
|
class VersionAlreadyOpenError < Exception; end
|
14
|
+
|
15
|
+
# Raised when we can't get a response from the catalog
|
16
|
+
class BadResponseFromCatalog < Exception; end
|
14
17
|
# rubocop:enable Lint/InheritException
|
15
18
|
|
16
19
|
class DuplicateIdError < RuntimeError
|
@@ -3,25 +3,82 @@
|
|
3
3
|
module Dor
|
4
4
|
# Indexes the objects position in workflows
|
5
5
|
class WorkflowIndexer
|
6
|
-
|
6
|
+
ERROR_OMISSION = '... (continued)'
|
7
|
+
private_constant :ERROR_OMISSION
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
# see https://lucene.apache.org/core/7_3_1/core/org/apache/lucene/util/BytesRefHash.MaxBytesLengthExceededException.html
|
10
|
+
MAX_ERROR_LENGTH = 32_768 - 2 - ERROR_OMISSION.length
|
11
|
+
private_constant :MAX_ERROR_LENGTH
|
12
|
+
|
13
|
+
# @param [Dor::WorkflowDocument] document the workflow document to index
|
14
|
+
def initialize(document:)
|
15
|
+
@document = document
|
11
16
|
end
|
12
17
|
|
13
|
-
# @return [Hash] the partial solr document for workflow
|
18
|
+
# @return [Hash] the partial solr document for the workflow document
|
14
19
|
def to_solr
|
15
|
-
|
16
|
-
|
20
|
+
WorkflowSolrDocument.new do |solr_doc|
|
21
|
+
wf_name = document.workflowId.first
|
22
|
+
solr_doc.name = wf_name
|
23
|
+
errors = processes.count(&:error?)
|
24
|
+
|
25
|
+
repo = document.repository.first
|
26
|
+
solr_doc.status = [wf_name, workflow_status, errors, repo].join('|')
|
27
|
+
|
28
|
+
processes.each do |process|
|
29
|
+
index_process(solr_doc, wf_name, process)
|
30
|
+
end
|
17
31
|
end
|
18
32
|
end
|
19
33
|
|
20
34
|
private
|
21
35
|
|
22
|
-
|
23
|
-
|
24
|
-
|
36
|
+
attr_reader :document
|
37
|
+
delegate :processes, to: :document
|
38
|
+
|
39
|
+
def index_process(solr_doc, wf_name, process)
|
40
|
+
return unless process.status.present?
|
41
|
+
|
42
|
+
# add a record of the robot having operated on this item, so we can track robot activity
|
43
|
+
solr_doc.add_process_time(wf_name, process.name, Time.parse(process.date_time)) if process_has_time?(process)
|
44
|
+
|
45
|
+
index_error_message(solr_doc, wf_name, process)
|
46
|
+
|
47
|
+
# workflow name, process status then process name
|
48
|
+
solr_doc.add_wps("#{wf_name}:#{process.status}", "#{wf_name}:#{process.status}:#{process.name}")
|
49
|
+
|
50
|
+
# workflow name, process name then process status
|
51
|
+
solr_doc.add_wps("#{wf_name}:#{process.name}", "#{wf_name}:#{process.name}:#{process.status}")
|
52
|
+
|
53
|
+
# process status, workflowname then process name
|
54
|
+
solr_doc.add_swp(process.status.to_s, "#{process.status}:#{wf_name}", "#{process.status}:#{wf_name}:#{process.name}")
|
55
|
+
return if process.state == process.status
|
56
|
+
|
57
|
+
solr_doc.add_wsp("#{wf_name}:#{process.state}:#{process.name}")
|
58
|
+
solr_doc.add_wps("#{wf_name}:#{process.name}:#{process.state}")
|
59
|
+
solr_doc.add_swp(process.state.to_s, "#{process.state}:#{wf_name}", "#{process.state}:#{wf_name}:#{process.name}")
|
60
|
+
end
|
61
|
+
|
62
|
+
def process_has_time?(process)
|
63
|
+
!process.date_time.blank? && process.status && (process.status == 'completed' || process.status == 'error')
|
64
|
+
end
|
65
|
+
|
66
|
+
def workflow_status
|
67
|
+
return 'empty' if processes.empty?
|
68
|
+
|
69
|
+
workflow_should_show_completed?(processes) ? 'completed' : 'active'
|
70
|
+
end
|
71
|
+
|
72
|
+
def workflow_should_show_completed?(processes)
|
73
|
+
processes.all? { |p| ['skipped', 'completed', '', nil].include?(p.status) }
|
74
|
+
end
|
75
|
+
|
76
|
+
# index the error message without the druid so we hopefully get some overlap
|
77
|
+
# truncate to avoid org.apache.lucene.util.BytesRefHash$MaxBytesLengthExceededException
|
78
|
+
def index_error_message(solr_doc, wf_name, process)
|
79
|
+
return unless process.error_message
|
80
|
+
|
81
|
+
solr_doc.error = "#{wf_name}:#{process.name}:#{process.error_message}".truncate(MAX_ERROR_LENGTH, omission: ERROR_OMISSION)
|
25
82
|
end
|
26
83
|
end
|
27
84
|
end
|
@@ -0,0 +1,28 @@
|
|
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(document: wf).to_solr
|
16
|
+
combined_doc.merge!(doc)
|
17
|
+
end
|
18
|
+
end.to_h
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# @return [Array<Dor::WorkflowDocument>]
|
24
|
+
def workflows
|
25
|
+
resource.workflows.workflows
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -15,7 +15,7 @@ module Dor
|
|
15
15
|
EditableIndexer,
|
16
16
|
IdentifiableIndexer,
|
17
17
|
ProcessableIndexer,
|
18
|
-
|
18
|
+
WorkflowsIndexer
|
19
19
|
)
|
20
20
|
|
21
21
|
CREATIVE_COMMONS_USE_LICENSES = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('CREATIVE_COMMONS_USE_LICENSES', 'Dor::CreativeCommonsLicenseService')
|
@@ -170,27 +170,16 @@ module Dor
|
|
170
170
|
# Clears RELS-EXT relationships, sets the isGovernedBy relationship to the SDR Graveyard APO
|
171
171
|
# @param [String] tag optional String of text that is concatenated to the identityMetadata/tag "Decommissioned : "
|
172
172
|
def decommission(tag)
|
173
|
-
|
174
|
-
clear_relationship :is_member_of
|
175
|
-
clear_relationship :is_member_of_collection
|
176
|
-
# remove isGovernedBy relationship
|
177
|
-
clear_relationship :is_governed_by
|
178
|
-
# add isGovernedBy to graveyard APO druid:sw909tc7852
|
179
|
-
# SEARCH BY dc title for 'SDR Graveyard'
|
180
|
-
add_relationship :is_governed_by, ActiveFedora::Base.find(Dor::SearchService.sdr_graveyard_apo_druid)
|
181
|
-
# eliminate contentMetadata. set it to <contentMetadata/> ?
|
182
|
-
contentMetadata.content = '<contentMetadata/>'
|
183
|
-
# eliminate rightsMetadata. set it to <rightsMetadata/> ?
|
184
|
-
rightsMetadata.content = '<rightsMetadata/>'
|
185
|
-
TagService.add self, "Decommissioned : #{tag}"
|
173
|
+
DecommissionService.new(self).decommission(tag)
|
186
174
|
end
|
175
|
+
deprecation_deprecate decommission: 'Use DecommissionService#decommission instead'
|
187
176
|
|
188
|
-
# TODO: Move to Dor-Utils.
|
189
177
|
# Adds a RELS-EXT constituent relationship to the given druid
|
190
178
|
# @param [String] druid the parent druid of the constituent relationship
|
191
179
|
# e.g.: <fedora:isConstituentOf rdf:resource="info:fedora/druid:hj097bm8879" />
|
192
180
|
def add_constituent(druid)
|
193
181
|
add_relationship :is_constituent_of, ActiveFedora::Base.find(druid)
|
194
182
|
end
|
183
|
+
deprecation_deprecate add_constituent: 'Use add_relationship :is_constituent_of instead'
|
195
184
|
end
|
196
185
|
end
|
@@ -49,9 +49,9 @@ module Dor
|
|
49
49
|
# @return [Boolean] true if the object is in a state that allows it to be modified.
|
50
50
|
# States that will allow modification are: has not been submitted for accessioning, has an open version or has sdr-ingest set to hold
|
51
51
|
def allows_modification?
|
52
|
-
if Dor::Config.workflow.client.
|
52
|
+
if Dor::Config.workflow.client.lifecycle('dor', pid, 'submitted') &&
|
53
53
|
!VersionService.new(self).open? &&
|
54
|
-
Dor::Config.workflow.client.
|
54
|
+
Dor::Config.workflow.client.workflow_status('dor', pid, 'accessionWF', 'sdr-ingest-transfer') != 'hold'
|
55
55
|
false
|
56
56
|
else
|
57
57
|
true
|
data/lib/dor/models/item.rb
CHANGED
data/lib/dor/models/set.rb
CHANGED
@@ -0,0 +1,93 @@
|
|
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
|
@@ -19,7 +19,7 @@ module Dor
|
|
19
19
|
last_version = druid_obj.current_version.to_i
|
20
20
|
|
21
21
|
# if the current version is still open, avoid this versioned directory
|
22
|
-
last_version -= 1 if Dor::Config.workflow.client.
|
22
|
+
last_version -= 1 if Dor::Config.workflow.client.lifecycle('dor', druid, 'accessioned').nil?
|
23
23
|
last_version
|
24
24
|
end
|
25
25
|
|
@@ -70,7 +70,7 @@ module Dor
|
|
70
70
|
|
71
71
|
def self.remove_active_workflows(druid)
|
72
72
|
%w(dor sdr).each do |repo|
|
73
|
-
dor_wfs = Dor::Config.workflow.client.
|
73
|
+
dor_wfs = Dor::Config.workflow.client.workflows(druid, repo)
|
74
74
|
dor_wfs.each { |wf| Dor::Config.workflow.client.delete_workflow(repo, druid, wf) }
|
75
75
|
end
|
76
76
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dor
|
4
|
+
# Responsible for decommissioning objects
|
5
|
+
class DecommissionService
|
6
|
+
# @param [Dor::Item] object
|
7
|
+
def initialize(object)
|
8
|
+
@object = object
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :object
|
12
|
+
|
13
|
+
# Clears RELS-EXT relationships, sets the isGovernedBy relationship to the SDR Graveyard APO
|
14
|
+
# @param [String] tag optional String of text that is concatenated to the identityMetadata/tag "Decommissioned : "
|
15
|
+
def decommission(tag)
|
16
|
+
# remove isMemberOf and isMemberOfCollection relationships
|
17
|
+
object.clear_relationship :is_member_of
|
18
|
+
object.clear_relationship :is_member_of_collection
|
19
|
+
# remove isGovernedBy relationship
|
20
|
+
object.clear_relationship :is_governed_by
|
21
|
+
# add isGovernedBy to graveyard APO druid:sw909tc7852
|
22
|
+
# SEARCH BY dc title for 'SDR Graveyard'
|
23
|
+
object.add_relationship :is_governed_by, ActiveFedora::Base.find(Dor::SearchService.sdr_graveyard_apo_druid)
|
24
|
+
# eliminate contentMetadata. set it to <contentMetadata/> ?
|
25
|
+
object.contentMetadata.content = '<contentMetadata/>'
|
26
|
+
# eliminate rightsMetadata. set it to <rightsMetadata/> ?
|
27
|
+
object.rightsMetadata.content = '<rightsMetadata/>'
|
28
|
+
TagService.add object, "Decommissioned : #{tag}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -2,12 +2,15 @@
|
|
2
2
|
|
3
3
|
require 'rest-client'
|
4
4
|
|
5
|
-
|
5
|
+
class CatalogHandler
|
6
6
|
def fetch(prefix, identifier)
|
7
7
|
client = RestClient::Resource.new(Dor::Config.metadata.catalog.url,
|
8
8
|
Dor::Config.metadata.catalog.user,
|
9
9
|
Dor::Config.metadata.catalog.pass)
|
10
|
-
|
10
|
+
params = "?#{prefix.chomp}=#{identifier.chomp}"
|
11
|
+
client[params].get
|
12
|
+
rescue RestClient::Exception => e
|
13
|
+
raise BadResponseFromCatalog, "#{e.class} - when contacting (with BasicAuth hidden): #{Dor::Config.metadata.catalog.url}#{params}"
|
11
14
|
end
|
12
15
|
|
13
16
|
def label(metadata)
|
@@ -20,5 +23,3 @@ handler = Class.new do
|
|
20
23
|
%w(catkey barcode)
|
21
24
|
end
|
22
25
|
end
|
23
|
-
|
24
|
-
Dor::MetadataService.register(handler)
|
@@ -1,37 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'cache'
|
4
|
+
require 'dor/services/metadata_handlers/catalog_handler'
|
4
5
|
|
5
6
|
module Dor
|
6
7
|
class MetadataError < RuntimeError; end
|
7
8
|
|
8
|
-
# class MetadataHandler
|
9
|
-
#
|
10
|
-
# def fetch(prefix, identifier)
|
11
|
-
# ### Return metadata for prefix/identifier combo
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# def label(metadata)
|
15
|
-
# ### Return a Fedora-compatible label from the metadata format returned by #fetch
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# end
|
19
|
-
|
20
9
|
class MetadataService
|
21
10
|
class << self
|
22
11
|
@@cache = Cache.new(nil, nil, 250, 300)
|
23
12
|
|
24
|
-
def register(handler_class)
|
25
|
-
%w(fetch label prefixes).each do |method|
|
26
|
-
raise TypeError, "Metadata handlers must define ##{method}" unless handler_class.instance_methods.include?(method) || handler_class.instance_methods.include?(method.to_sym)
|
27
|
-
end
|
28
|
-
handler = handler_class.new
|
29
|
-
handler.prefixes.each do |prefix|
|
30
|
-
handlers[prefix.to_sym] = handler
|
31
|
-
end
|
32
|
-
handler
|
33
|
-
end
|
34
|
-
|
35
13
|
def known_prefixes
|
36
14
|
handlers.keys
|
37
15
|
end
|
@@ -62,7 +40,7 @@ module Dor
|
|
62
40
|
|
63
41
|
def handler_for(prefix)
|
64
42
|
handler = handlers[prefix.to_sym]
|
65
|
-
raise MetadataError, "
|
43
|
+
raise MetadataError, "Unknown metadata prefix: #{prefix}" if handler.nil?
|
66
44
|
|
67
45
|
handler
|
68
46
|
end
|
@@ -70,12 +48,17 @@ module Dor
|
|
70
48
|
private
|
71
49
|
|
72
50
|
def handlers
|
73
|
-
@handlers ||= {}
|
51
|
+
@handlers ||= {}.tap do |md_handlers|
|
52
|
+
# There's only one. If additional handlers are added, will need to be registered here.
|
53
|
+
register(CatalogHandler.new, md_handlers)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def register(handler, md_handlers)
|
58
|
+
handler.prefixes.each do |prefix|
|
59
|
+
md_handlers[prefix.to_sym] = handler
|
60
|
+
end
|
74
61
|
end
|
75
62
|
end
|
76
63
|
end
|
77
64
|
end
|
78
|
-
|
79
|
-
Dir[File.join(File.dirname(__FILE__), 'metadata_handlers', '*.rb')].each do |handler_file|
|
80
|
-
load handler_file
|
81
|
-
end
|
@@ -24,9 +24,9 @@ module Dor
|
|
24
24
|
def open(opts = {})
|
25
25
|
# During local development, we need a way to open a new version even if the object has not been accessioned.
|
26
26
|
raise(Dor::Exception, 'Object net yet accessioned') unless
|
27
|
-
opts[:assume_accessioned] || Dor::Config.workflow.client.
|
27
|
+
opts[:assume_accessioned] || Dor::Config.workflow.client.lifecycle('dor', work.pid, 'accessioned')
|
28
28
|
raise Dor::VersionAlreadyOpenError, 'Object already opened for versioning' if open?
|
29
|
-
raise Dor::Exception, 'Object currently being accessioned' if Dor::Config.workflow.client.
|
29
|
+
raise Dor::Exception, 'Object currently being accessioned' if Dor::Config.workflow.client.active_lifecycle('dor', work.pid, 'submitted')
|
30
30
|
|
31
31
|
sdr_version = Sdr::Client.current_version work.pid
|
32
32
|
|
@@ -67,14 +67,14 @@ module Dor
|
|
67
67
|
|
68
68
|
raise Dor::Exception, 'latest version in versionMetadata requires tag and description before it can be closed' unless work.versionMetadata.current_version_closeable?
|
69
69
|
raise Dor::Exception, 'Trying to close version on an object not opened for versioning' unless open?
|
70
|
-
raise Dor::Exception, 'accessionWF already created for versioned object' if Dor::Config.workflow.client.
|
70
|
+
raise Dor::Exception, 'accessionWF already created for versioned object' if Dor::Config.workflow.client.active_lifecycle('dor', work.pid, 'submitted')
|
71
71
|
|
72
72
|
Dor::Config.workflow.client.close_version 'dor', work.pid, opts.fetch(:start_accession, true) # Default to creating accessionWF when calling close_version
|
73
73
|
end
|
74
74
|
|
75
75
|
# @return [Boolean] true if 'opened' lifecycle is active, false otherwise
|
76
76
|
def open?
|
77
|
-
return true if Dor::Config.workflow.client.
|
77
|
+
return true if Dor::Config.workflow.client.active_lifecycle('dor', work.pid, 'opened')
|
78
78
|
|
79
79
|
false
|
80
80
|
end
|
data/lib/dor/version.rb
CHANGED
@@ -4,21 +4,8 @@ module Dor
|
|
4
4
|
module Workflow
|
5
5
|
class Document
|
6
6
|
extend Deprecation
|
7
|
-
include SolrDocHelper
|
8
7
|
include ::OM::XML::Document
|
9
8
|
|
10
|
-
ERROR_OMISSION = '... (continued)'
|
11
|
-
private_constant :ERROR_OMISSION
|
12
|
-
|
13
|
-
# see https://lucene.apache.org/core/7_3_1/core/org/apache/lucene/util/BytesRefHash.MaxBytesLengthExceededException.html
|
14
|
-
MAX_ERROR_LENGTH = 32_768 - 2 - ERROR_OMISSION.length
|
15
|
-
private_constant :MAX_ERROR_LENGTH
|
16
|
-
|
17
|
-
WF_SOLR_TYPE = :string
|
18
|
-
private_constant :WF_SOLR_TYPE
|
19
|
-
WF_SOLR_ATTRS = [:symbol].freeze
|
20
|
-
private_constant :WF_SOLR_ATTRS
|
21
|
-
|
22
9
|
set_terminology do |t|
|
23
10
|
t.root(path: 'workflow')
|
24
11
|
t.repository(path: { attribute: 'repository' })
|
@@ -93,69 +80,9 @@ module Dor
|
|
93
80
|
end
|
94
81
|
end
|
95
82
|
|
96
|
-
def workflow_should_show_completed?(processes)
|
97
|
-
processes.all? { |p| ['skipped', 'completed', '', nil].include?(p.status) }
|
98
|
-
end
|
99
|
-
|
100
|
-
def to_solr(solr_doc = {}, *_args)
|
101
|
-
wf_name = workflowId.first
|
102
|
-
repo = repository.first
|
103
|
-
|
104
|
-
add_solr_value(solr_doc, 'wf', wf_name, WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
105
|
-
add_solr_value(solr_doc, 'wf_wps', wf_name, WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
106
|
-
add_solr_value(solr_doc, 'wf_wsp', wf_name, WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
107
|
-
status = processes.empty? ? 'empty' : (workflow_should_show_completed?(processes) ? 'completed' : 'active')
|
108
|
-
errors = processes.count(&:error?)
|
109
|
-
add_solr_value(solr_doc, 'workflow_status', [wf_name, status, errors, repo].join('|'), WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
110
|
-
|
111
|
-
processes.each do |process|
|
112
|
-
next unless process.status.present?
|
113
|
-
|
114
|
-
# add a record of the robot having operated on this item, so we can track robot activity
|
115
|
-
if !process.date_time.blank? && process.status && (process.status == 'completed' || process.status == 'error')
|
116
|
-
solr_doc["wf_#{wf_name}_#{process.name}_dttsi"] = Time.parse(process.date_time).utc.iso8601
|
117
|
-
end
|
118
|
-
|
119
|
-
index_error_message(solr_doc, wf_name, process)
|
120
|
-
|
121
|
-
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.status}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
122
|
-
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.status}:#{process.name}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
123
|
-
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
124
|
-
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}:#{process.status}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
125
|
-
add_solr_value(solr_doc, 'wf_swp', process.status.to_s, WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
126
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
127
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.status}:#{wf_name}:#{process.name}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
128
|
-
next unless process.state != process.status
|
129
|
-
|
130
|
-
add_solr_value(solr_doc, 'wf_wsp', "#{wf_name}:#{process.state}:#{process.name}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
131
|
-
add_solr_value(solr_doc, 'wf_wps', "#{wf_name}:#{process.name}:#{process.state}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
132
|
-
add_solr_value(solr_doc, 'wf_swp', process.state.to_s, WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
133
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.state}:#{wf_name}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
134
|
-
add_solr_value(solr_doc, 'wf_swp', "#{process.state}:#{wf_name}:#{process.name}", WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
135
|
-
end
|
136
|
-
|
137
|
-
solr_doc[Solrizer.solr_name('wf_wps', :symbol)]&.uniq!
|
138
|
-
solr_doc[Solrizer.solr_name('wf_wsp', :symbol)]&.uniq!
|
139
|
-
solr_doc[Solrizer.solr_name('wf_swp', :symbol)]&.uniq!
|
140
|
-
solr_doc['workflow_status']&.uniq!
|
141
|
-
|
142
|
-
solr_doc
|
143
|
-
end
|
144
|
-
|
145
83
|
def inspect
|
146
84
|
"#<#{self.class.name}:#{object_id}>"
|
147
85
|
end
|
148
|
-
|
149
|
-
private
|
150
|
-
|
151
|
-
# index the error message without the druid so we hopefully get some overlap
|
152
|
-
# truncate to avoid org.apache.lucene.util.BytesRefHash$MaxBytesLengthExceededException
|
153
|
-
def index_error_message(solr_doc, wf_name, process)
|
154
|
-
return unless process.error_message
|
155
|
-
|
156
|
-
error_message = "#{wf_name}:#{process.name}:#{process.error_message}".truncate(MAX_ERROR_LENGTH, omission: ERROR_OMISSION)
|
157
|
-
add_solr_value(solr_doc, 'wf_error', error_message, WF_SOLR_TYPE, WF_SOLR_ATTRS)
|
158
|
-
end
|
159
86
|
end
|
160
87
|
end
|
161
88
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dor-services
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Klein
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2019-03
|
17
|
+
date: 2019-04-03 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: active-fedora
|
@@ -290,20 +290,6 @@ dependencies:
|
|
290
290
|
- - "~>"
|
291
291
|
- !ruby/object:Gem::Version
|
292
292
|
version: '2.6'
|
293
|
-
- !ruby/object:Gem::Dependency
|
294
|
-
name: uuidtools
|
295
|
-
requirement: !ruby/object:Gem::Requirement
|
296
|
-
requirements:
|
297
|
-
- - "~>"
|
298
|
-
- !ruby/object:Gem::Version
|
299
|
-
version: 2.1.4
|
300
|
-
type: :runtime
|
301
|
-
prerelease: false
|
302
|
-
version_requirements: !ruby/object:Gem::Requirement
|
303
|
-
requirements:
|
304
|
-
- - "~>"
|
305
|
-
- !ruby/object:Gem::Version
|
306
|
-
version: 2.1.4
|
307
293
|
- !ruby/object:Gem::Dependency
|
308
294
|
name: retries
|
309
295
|
requirement: !ruby/object:Gem::Requirement
|
@@ -344,20 +330,14 @@ dependencies:
|
|
344
330
|
requirements:
|
345
331
|
- - "~>"
|
346
332
|
- !ruby/object:Gem::Version
|
347
|
-
version: '2.
|
348
|
-
- - ">="
|
349
|
-
- !ruby/object:Gem::Version
|
350
|
-
version: 2.0.1
|
333
|
+
version: '2.11'
|
351
334
|
type: :runtime
|
352
335
|
prerelease: false
|
353
336
|
version_requirements: !ruby/object:Gem::Requirement
|
354
337
|
requirements:
|
355
338
|
- - "~>"
|
356
339
|
- !ruby/object:Gem::Version
|
357
|
-
version: '2.
|
358
|
-
- - ">="
|
359
|
-
- !ruby/object:Gem::Version
|
360
|
-
version: 2.0.1
|
340
|
+
version: '2.11'
|
361
341
|
- !ruby/object:Gem::Dependency
|
362
342
|
name: druid-tools
|
363
343
|
requirement: !ruby/object:Gem::Requirement
|
@@ -624,6 +604,7 @@ files:
|
|
624
604
|
- lib/dor/indexers/processable_indexer.rb
|
625
605
|
- lib/dor/indexers/releasable_indexer.rb
|
626
606
|
- lib/dor/indexers/workflow_indexer.rb
|
607
|
+
- lib/dor/indexers/workflows_indexer.rb
|
627
608
|
- lib/dor/models/abstract.rb
|
628
609
|
- lib/dor/models/admin_policy_object.rb
|
629
610
|
- lib/dor/models/agreement.rb
|
@@ -647,6 +628,7 @@ files:
|
|
647
628
|
- lib/dor/models/item.rb
|
648
629
|
- lib/dor/models/set.rb
|
649
630
|
- lib/dor/models/workflow_object.rb
|
631
|
+
- lib/dor/models/workflow_solr_document.rb
|
650
632
|
- lib/dor/rest_resource_factory.rb
|
651
633
|
- lib/dor/services/ability.rb
|
652
634
|
- lib/dor/services/cleanup_reset_service.rb
|
@@ -654,6 +636,7 @@ files:
|
|
654
636
|
- lib/dor/services/create_workflow_service.rb
|
655
637
|
- lib/dor/services/creative_commons_license_service.rb
|
656
638
|
- lib/dor/services/datastream_builder.rb
|
639
|
+
- lib/dor/services/decommission_service.rb
|
657
640
|
- lib/dor/services/digital_stacks_service.rb
|
658
641
|
- lib/dor/services/dublin_core_service.rb
|
659
642
|
- lib/dor/services/file_metadata_merge_service.rb
|
@@ -667,7 +650,6 @@ files:
|
|
667
650
|
- lib/dor/services/public_desc_metadata_service.rb
|
668
651
|
- lib/dor/services/public_xml_service.rb
|
669
652
|
- lib/dor/services/publish_metadata_service.rb
|
670
|
-
- lib/dor/services/registration_service.rb
|
671
653
|
- lib/dor/services/release_tag_service.rb
|
672
654
|
- lib/dor/services/reset_workspace_service.rb
|
673
655
|
- lib/dor/services/sdr_ingest_service.rb
|
@@ -1,202 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'uuidtools'
|
4
|
-
|
5
|
-
module Dor
|
6
|
-
class RegistrationService
|
7
|
-
class << self
|
8
|
-
# @TODO: Why isn't all this logic in, for example, Dor::Item.create? or Dor::Base.create? or Dor::Creatable.create?
|
9
|
-
# @TODO: these duplicate checks could be combined into 1 query
|
10
|
-
|
11
|
-
# @param [String] pid an ID to check, if desired. If not passed (or nil), a new ID is minted
|
12
|
-
# @return [String] a pid you can use immidately, either freshly minted or your checked value
|
13
|
-
# @raise [Dor::DuplicateIdError]
|
14
|
-
def unduplicated_pid(pid = nil)
|
15
|
-
return Dor::SuriService.mint_id unless pid
|
16
|
-
|
17
|
-
existing_pid = SearchService.query_by_id(pid).first
|
18
|
-
raise Dor::DuplicateIdError.new(existing_pid), "An object with the PID #{pid} has already been registered." unless existing_pid.nil?
|
19
|
-
|
20
|
-
pid
|
21
|
-
end
|
22
|
-
|
23
|
-
# @param [String] source_id_string a fully qualified source:val or empty string
|
24
|
-
# @return [String] the same qualified source:id for immediate use
|
25
|
-
# @raise [Dor::DuplicateIdError]
|
26
|
-
def check_source_id(source_id_string)
|
27
|
-
return '' if source_id_string == ''
|
28
|
-
unless SearchService.query_by_id(source_id_string.to_s).first.nil?
|
29
|
-
raise Dor::DuplicateIdError.new(source_id_string), "An object with the source ID '#{source_id_string}' has already been registered."
|
30
|
-
end
|
31
|
-
|
32
|
-
source_id_string
|
33
|
-
end
|
34
|
-
|
35
|
-
# @param [Hash{Symbol => various}] params
|
36
|
-
# @option params [String] :object_type required
|
37
|
-
# @option params [String] :label required
|
38
|
-
# @option params [String] :admin_policy required
|
39
|
-
# @option params [String] :metadata_source
|
40
|
-
# @option params [String] :rights
|
41
|
-
# @option params [String] :collection
|
42
|
-
# @option params [Hash{String => String}] :source_id Primary ID from another system, max one key/value pair!
|
43
|
-
# @option params [Hash] :other_ids including :uuid if known
|
44
|
-
# @option params [String] :pid Fully qualified PID if you don't want one generated for you
|
45
|
-
# @option params [Integer] :workflow_priority]
|
46
|
-
# @option params [Array<String>] :seed_datastream datastream_names
|
47
|
-
# @option params [Array<String>] :initiate_workflow workflow_ids
|
48
|
-
# @option params [Array] :tags
|
49
|
-
def register_object(params = {})
|
50
|
-
%i[object_type label].each do |required_param|
|
51
|
-
raise Dor::ParameterError, "#{required_param.inspect} must be specified in call to #{name}.register_object" unless params[required_param]
|
52
|
-
end
|
53
|
-
metadata_source = params[:metadata_source]
|
54
|
-
raise Dor::ParameterError, "label cannot be empty to call #{name}.register_object" if params[:label].length < 1 && %w[label none].include?(metadata_source)
|
55
|
-
|
56
|
-
object_type = params[:object_type]
|
57
|
-
item_class = Dor.registered_classes[object_type]
|
58
|
-
raise Dor::ParameterError, "Unknown item type: '#{object_type}'" if item_class.nil?
|
59
|
-
|
60
|
-
# content_model = params[:content_model]
|
61
|
-
# parent = params[:parent]
|
62
|
-
label = params[:label]
|
63
|
-
source_id = params[:source_id] || {}
|
64
|
-
other_ids = params[:other_ids] || {}
|
65
|
-
tags = params[:tags] || []
|
66
|
-
collection = params[:collection]
|
67
|
-
|
68
|
-
# Check for sourceId conflict *before* potentially minting PID
|
69
|
-
source_id_string = check_source_id [source_id.keys.first, source_id[source_id.keys.first]].compact.join(':')
|
70
|
-
pid = unduplicated_pid(params[:pid])
|
71
|
-
|
72
|
-
raise ArgumentError, ":source_id Hash can contain at most 1 pair: recieved #{source_id.size}" if source_id.size > 1
|
73
|
-
|
74
|
-
rights = nil
|
75
|
-
if params[:rights]
|
76
|
-
rights = params[:rights]
|
77
|
-
raise Dor::ParameterError, "Unknown rights setting '#{rights}' when calling #{name}.register_object" unless rights == 'default' || RightsMetadataDS.valid_rights_type?(rights)
|
78
|
-
end
|
79
|
-
|
80
|
-
other_ids[:uuid] = UUIDTools::UUID.timestamp_create.to_s if (other_ids.key?(:uuid) || other_ids.key?('uuid')) == false
|
81
|
-
apo_object = Dor.find(params[:admin_policy])
|
82
|
-
new_item = item_class.new(pid: pid)
|
83
|
-
new_item.label = label.length > 254 ? label[0, 254] : label
|
84
|
-
idmd = new_item.identityMetadata
|
85
|
-
idmd.sourceId = source_id_string
|
86
|
-
idmd.add_value(:objectId, pid)
|
87
|
-
idmd.add_value(:objectCreator, 'DOR')
|
88
|
-
idmd.add_value(:objectLabel, label)
|
89
|
-
idmd.add_value(:objectType, object_type)
|
90
|
-
other_ids.each_pair { |name, value| idmd.add_otherId("#{name}:#{value}") }
|
91
|
-
tags.each { |tag| idmd.add_value(:tag, tag) }
|
92
|
-
new_item.admin_policy_object = apo_object
|
93
|
-
|
94
|
-
apo_object.administrativeMetadata.ng_xml.xpath('/administrativeMetadata/relationships/*').each do |rel|
|
95
|
-
short_predicate = ActiveFedora::RelsExtDatastream.short_predicate rel.namespace.href + rel.name
|
96
|
-
if short_predicate.nil?
|
97
|
-
ix = 0
|
98
|
-
ix += 1 while ActiveFedora::Predicates.predicate_mappings[rel.namespace.href].key?(short_predicate = :"extra_predicate_#{ix}")
|
99
|
-
ActiveFedora::Predicates.predicate_mappings[rel.namespace.href][short_predicate] = rel.name
|
100
|
-
end
|
101
|
-
new_item.add_relationship short_predicate, rel['rdf:resource']
|
102
|
-
end
|
103
|
-
new_item.add_collection(collection) if collection
|
104
|
-
if rights && %w(item collection).include?(object_type)
|
105
|
-
rights_xml = apo_object.defaultObjectRights.ng_xml
|
106
|
-
new_item.datastreams['rightsMetadata'].content = rights_xml.to_s
|
107
|
-
new_item.set_read_rights(rights) unless rights == 'default' # already defaulted to default!
|
108
|
-
end
|
109
|
-
# create basic mods from the label
|
110
|
-
build_desc_metadata_from_label(new_item, label) if metadata_source == 'label'
|
111
|
-
|
112
|
-
workflow_priority = params[:workflow_priority] ? params[:workflow_priority].to_i : 0
|
113
|
-
|
114
|
-
seed_datastreams(Array(params[:seed_datastream]), new_item)
|
115
|
-
initiate_workflow(workflows: Array(params[:initiate_workflow]), item: new_item, priority: workflow_priority)
|
116
|
-
|
117
|
-
new_item.class.ancestors.select { |x| x.respond_to?(:to_class_uri) && x != ActiveFedora::Base }.each do |parent_class|
|
118
|
-
new_item.add_relationship(:has_model, parent_class.to_class_uri)
|
119
|
-
end
|
120
|
-
|
121
|
-
new_item.save
|
122
|
-
new_item
|
123
|
-
end
|
124
|
-
|
125
|
-
# @param [Hash] params
|
126
|
-
# @see register_object similar but different
|
127
|
-
def create_from_request(params)
|
128
|
-
other_ids = Array(params[:other_id]).map do |id|
|
129
|
-
if id =~ /^symphony:(.+)$/
|
130
|
-
"#{$1.length < 14 ? 'catkey' : 'barcode'}:#{$1}"
|
131
|
-
else
|
132
|
-
id
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
if params[:label] == ':auto'
|
137
|
-
params.delete(:label)
|
138
|
-
params.delete('label')
|
139
|
-
metadata_id = Dor::MetadataService.resolvable(other_ids).first
|
140
|
-
params[:label] = Dor::MetadataService.label_for(metadata_id)
|
141
|
-
end
|
142
|
-
|
143
|
-
dor_params = {
|
144
|
-
pid: params[:pid],
|
145
|
-
admin_policy: params[:admin_policy],
|
146
|
-
content_model: params[:model],
|
147
|
-
label: params[:label],
|
148
|
-
object_type: params[:object_type],
|
149
|
-
other_ids: ids_to_hash(other_ids),
|
150
|
-
parent: params[:parent],
|
151
|
-
source_id: ids_to_hash(params[:source_id]),
|
152
|
-
tags: params[:tag] || [],
|
153
|
-
seed_datastream: params[:seed_datastream],
|
154
|
-
initiate_workflow: Array(params[:initiate_workflow]) + Array(params[:workflow_id]),
|
155
|
-
rights: params[:rights],
|
156
|
-
metadata_source: params[:metadata_source],
|
157
|
-
collection: params[:collection],
|
158
|
-
workflow_priority: params[:workflow_priority]
|
159
|
-
}
|
160
|
-
dor_params.delete_if { |_k, v| v.nil? }
|
161
|
-
|
162
|
-
dor_obj = register_object(dor_params)
|
163
|
-
pid = dor_obj.pid
|
164
|
-
location = URI.parse(Dor::Config.fedora.safeurl.sub(/\/*$/, '/')).merge("objects/#{pid}").to_s
|
165
|
-
dor_params.dup.merge(location: location, pid: pid)
|
166
|
-
end
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
def ids_to_hash(ids)
|
171
|
-
return nil if ids.nil?
|
172
|
-
|
173
|
-
Hash[Array(ids).map { |id| id.split(':', 2) }]
|
174
|
-
end
|
175
|
-
|
176
|
-
def seed_datastreams(names, item)
|
177
|
-
names.each do |datastream_name|
|
178
|
-
item.build_datastream(datastream_name)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def initiate_workflow(workflows:, item:, priority:)
|
183
|
-
workflows.each do |workflow_id|
|
184
|
-
Dor::CreateWorkflowService.create_workflow(item, name: workflow_id,
|
185
|
-
create_ds: !item.new_record?,
|
186
|
-
priority: priority)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def build_desc_metadata_from_label(new_item, label)
|
191
|
-
builder = Nokogiri::XML::Builder.new do |xml|
|
192
|
-
xml.mods(Dor::DescMetadataDS::MODS_HEADER_CONFIG) do
|
193
|
-
xml.titleInfo do
|
194
|
-
xml.title label
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
new_item.descMetadata.content = builder.to_xml
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|