stash-merritt 0.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 +7 -0
- data/.gitignore +193 -0
- data/.rubocop.yml +32 -0
- data/.ruby-version +1 -0
- data/.travis.yml +12 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +326 -0
- data/LICENSE.md +22 -0
- data/README.md +53 -0
- data/Rakefile +49 -0
- data/lib/datacite/mapping/datacite_xml_factory.rb +212 -0
- data/lib/stash/merritt/ezid_helper.rb +50 -0
- data/lib/stash/merritt/module_info.rb +12 -0
- data/lib/stash/merritt/repository.rb +17 -0
- data/lib/stash/merritt/submission_job.rb +90 -0
- data/lib/stash/merritt/submission_package/data_one_manifest_builder.rb +41 -0
- data/lib/stash/merritt/submission_package/merritt_datacite_builder.rb +22 -0
- data/lib/stash/merritt/submission_package/merritt_delete_builder.rb +25 -0
- data/lib/stash/merritt/submission_package/merritt_oaidc_builder.rb +130 -0
- data/lib/stash/merritt/submission_package/stash_wrapper_builder.rb +59 -0
- data/lib/stash/merritt/submission_package.rb +125 -0
- data/lib/stash/merritt/sword_helper.rb +58 -0
- data/lib/stash/merritt.rb +5 -0
- data/lib/stash.rb +5 -0
- data/spec/.rubocop.yml +10 -0
- data/spec/config/app_config.yml +3 -0
- data/spec/config/database.yml +7 -0
- data/spec/config/licenses.yml +18 -0
- data/spec/data/archive/mrt-datacite.xml +121 -0
- data/spec/data/archive/mrt-dataone-manifest.txt +32 -0
- data/spec/data/archive/mrt-oaidc.xml +38 -0
- data/spec/data/archive/stash-wrapper.xml +213 -0
- data/spec/data/archive.zip +0 -0
- data/spec/data/dc4-with-funding-references.xml +123 -0
- data/spec/db/datacite/mapping/datacite_xml_factory_spec.rb +56 -0
- data/spec/db/stash/merritt/merritt_oaidc_builder_spec.rb +72 -0
- data/spec/db/stash/merritt/submission_package_spec.rb +174 -0
- data/spec/db/stash/merritt/sword_helper_spec.rb +162 -0
- data/spec/db_spec_helper.rb +31 -0
- data/spec/rspec_custom_matchers.rb +92 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/unit/stash/merritt/ezid_helper_spec.rb +88 -0
- data/spec/unit/stash/merritt/repository_spec.rb +19 -0
- data/spec/unit/stash/merritt/submission_job_spec.rb +127 -0
- data/spec/util/resource_builder.rb +333 -0
- data/stash-merritt.gemspec +48 -0
- data/stash-merritt.iml +147 -0
- data/stash-merritt.ipr +127 -0
- data/travis-local-deps.sh +43 -0
- metadata +337 -0
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'datacite/mapping'
|
2
|
+
|
3
|
+
module Datacite
|
4
|
+
module Mapping
|
5
|
+
class DataciteXMLFactory # rubocop:disable Metrics/ClassLength
|
6
|
+
attr_reader :doi_value
|
7
|
+
attr_reader :se_resource_id
|
8
|
+
attr_reader :total_size_bytes
|
9
|
+
attr_reader :version
|
10
|
+
|
11
|
+
def initialize(doi_value:, se_resource_id:, total_size_bytes:, version:)
|
12
|
+
@doi_value = doi_value
|
13
|
+
@se_resource_id = se_resource_id
|
14
|
+
@total_size_bytes = total_size_bytes
|
15
|
+
@version = version && version.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def build_datacite_xml(datacite_3: false)
|
19
|
+
dcs_resource = build_resource(datacite_3: datacite_3)
|
20
|
+
|
21
|
+
return dcs_resource.write_xml(mapping: :datacite_3) if datacite_3
|
22
|
+
dcs_resource.write_xml
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_resource(datacite_3: false) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
26
|
+
pub_year = se_resource.publication_years[0] # TODO: make this has_one instead of has_many
|
27
|
+
|
28
|
+
dcs_resource = Resource.new(
|
29
|
+
identifier: Identifier.from_doi(doi_value),
|
30
|
+
creators: se_resource.creators.map do |c|
|
31
|
+
Creator.new(
|
32
|
+
name: c.creator_full_name,
|
33
|
+
identifier: to_dcs_identifier(c.name_identifier),
|
34
|
+
affiliations: c.affiliations.map(&:smart_name)
|
35
|
+
)
|
36
|
+
end,
|
37
|
+
titles: se_resource.titles.map { |t| Title.new(value: t.title, type: t.title_type_mapping_obj) },
|
38
|
+
publisher: to_dcs_publisher(se_resource.publisher),
|
39
|
+
publication_year: to_dcs_pub_year(pub_year)
|
40
|
+
)
|
41
|
+
|
42
|
+
dcs_resource.language = 'en'
|
43
|
+
dcs_resource.resource_type = to_dcs_type(se_resource.resource_type)
|
44
|
+
dcs_resource.sizes = ["#{total_size_bytes} bytes"]
|
45
|
+
dcs_resource.formats = se_resource.formats.map(&:format)
|
46
|
+
dcs_resource.version = version
|
47
|
+
|
48
|
+
add_subjects(dcs_resource)
|
49
|
+
add_contributors(dcs_resource)
|
50
|
+
add_dates(dcs_resource)
|
51
|
+
add_alt_ids(dcs_resource)
|
52
|
+
add_related_ids(dcs_resource)
|
53
|
+
add_rights(dcs_resource)
|
54
|
+
add_descriptions(dcs_resource)
|
55
|
+
add_locations(dcs_resource)
|
56
|
+
add_funding(dcs_resource, datacite_3: datacite_3)
|
57
|
+
|
58
|
+
dcs_resource
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def se_resource
|
64
|
+
@se_resource ||= StashEngine::Resource.find(se_resource_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_dcs_type(sd_resource_type)
|
68
|
+
ResourceType.new(resource_type_general: sd_resource_type.resource_type_general_mapping_obj,
|
69
|
+
value: sd_resource_type.resource_type)
|
70
|
+
end
|
71
|
+
|
72
|
+
def add_locations(dcs_resource)
|
73
|
+
dcs_resource.geo_locations = se_resource.geolocations.map do |l|
|
74
|
+
GeoLocation.new(
|
75
|
+
place: l.datacite_mapping_place,
|
76
|
+
point: l.datacite_mapping_point,
|
77
|
+
box: l.datacite_mapping_box
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def add_descriptions(dcs_resource)
|
83
|
+
se_resource.descriptions.where.not(description: nil).each do |d|
|
84
|
+
next if d.description.blank?
|
85
|
+
dcs_resource.descriptions << Description.new(
|
86
|
+
value: d.description,
|
87
|
+
type: d.description_type_mapping_obj
|
88
|
+
)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_rights(dcs_resource)
|
93
|
+
dcs_resource.rights_list = se_resource.rights.map do |r|
|
94
|
+
Rights.new(
|
95
|
+
value: r.rights,
|
96
|
+
uri: to_uri(r.rights_uri)
|
97
|
+
)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def add_related_ids(dcs_resource)
|
102
|
+
dcs_resource.related_identifiers = se_resource.related_identifiers.completed.map do |id|
|
103
|
+
RelatedIdentifier.new(
|
104
|
+
relation_type: id.relation_type_mapping_obj,
|
105
|
+
value: id.related_identifier,
|
106
|
+
identifier_type: id.related_identifier_type_mapping_obj,
|
107
|
+
related_metadata_scheme: id.related_metadata_scheme,
|
108
|
+
scheme_uri: to_uri(id.scheme_URI),
|
109
|
+
scheme_type: id.scheme_type
|
110
|
+
)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_alt_ids(dcs_resource)
|
115
|
+
dcs_resource.alternate_identifiers = se_resource.alternate_identifiers.map do |id|
|
116
|
+
AlternateIdentifier.new(
|
117
|
+
value: id.alternate_identifier,
|
118
|
+
type: id.alternate_identifier_type
|
119
|
+
)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def add_dates(dcs_resource)
|
124
|
+
dcs_resource.dates = se_resource.datacite_dates.where.not(date: nil).map do |d|
|
125
|
+
sd_date = d.date
|
126
|
+
Date.new(
|
127
|
+
type: d.date_type_mapping_obj,
|
128
|
+
value: sd_date
|
129
|
+
)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def add_subjects(dcs_resource)
|
134
|
+
dcs_resource.subjects = se_resource.subjects.map { |s| Subject.new(value: s.subject) }
|
135
|
+
end
|
136
|
+
|
137
|
+
def add_contributors(dcs_resource)
|
138
|
+
se_resource.contributors.completed.where.not(contributor_type: 'funder').each do |c|
|
139
|
+
dcs_resource.contributors << Contributor.new(
|
140
|
+
name: c.contributor_name,
|
141
|
+
identifier: to_dcs_identifier(c.name_identifier),
|
142
|
+
type: c.contributor_type_mapping_obj,
|
143
|
+
affiliations: c.affiliations.map(&:long_name)
|
144
|
+
)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def add_funding(dcs_resource, datacite_3: false)
|
149
|
+
datacite_3 ? add_dc3_funders(dcs_resource) : add_funding_references(dcs_resource)
|
150
|
+
end
|
151
|
+
|
152
|
+
def sd_funder_contribs
|
153
|
+
se_resource.contributors.completed.where(contributor_type: 'funder')
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_dc3_funders(dcs_resource)
|
157
|
+
sd_funder_contribs.each do |contrib|
|
158
|
+
dcs_resource.descriptions << to_funding_desc(contrib)
|
159
|
+
dcs_resource.contributors << to_dcs_funder(contrib)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def add_funding_references(dcs_resource)
|
164
|
+
dcs_resource.funding_references = sd_funder_contribs.map do |c|
|
165
|
+
FundingReference.new(
|
166
|
+
name: c.contributor_name,
|
167
|
+
award_number: c.award_number
|
168
|
+
)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def to_dcs_funder(contrib)
|
173
|
+
Contributor.new(
|
174
|
+
name: contrib.contributor_name,
|
175
|
+
identifier: to_dcs_identifier(contrib.name_identifier),
|
176
|
+
type: ContributorType::FUNDER
|
177
|
+
)
|
178
|
+
end
|
179
|
+
|
180
|
+
def to_funding_desc(contrib)
|
181
|
+
award_num = contrib.award_number
|
182
|
+
desc_text = "Data were created with funding from #{contrib.contributor_name}"
|
183
|
+
desc_text << " under grant(s) #{award_num}." if award_num
|
184
|
+
Description.new(type: DescriptionType::OTHER, value: desc_text)
|
185
|
+
end
|
186
|
+
|
187
|
+
def to_dcs_identifier(sd_name_ident)
|
188
|
+
return unless sd_name_ident
|
189
|
+
sd_scheme_uri = sd_name_ident.scheme_URI
|
190
|
+
NameIdentifier.new(
|
191
|
+
scheme: sd_name_ident.name_identifier_scheme,
|
192
|
+
scheme_uri: sd_scheme_uri && to_uri(sd_scheme_uri),
|
193
|
+
value: sd_name_ident.name_identifier
|
194
|
+
)
|
195
|
+
end
|
196
|
+
|
197
|
+
def to_dcs_publisher(sd_publisher)
|
198
|
+
return 'unknown' unless sd_publisher
|
199
|
+
sd_publisher.publisher
|
200
|
+
end
|
201
|
+
|
202
|
+
def to_dcs_pub_year(sd_pub_year)
|
203
|
+
return ::Date.today.year unless sd_pub_year
|
204
|
+
sd_pub_year.publication_year
|
205
|
+
end
|
206
|
+
|
207
|
+
def to_uri(uri_or_str)
|
208
|
+
::XML::MappingExtensions.to_uri(uri_or_str)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'stash_ezid/client'
|
2
|
+
|
3
|
+
module Stash
|
4
|
+
module Merritt
|
5
|
+
class EzidHelper
|
6
|
+
attr_reader :resource
|
7
|
+
attr_reader :url_helpers
|
8
|
+
|
9
|
+
def initialize(resource:, url_helpers:)
|
10
|
+
@resource = resource
|
11
|
+
@url_helpers = url_helpers
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [String] the identifier (DOI, ARK, or URN)
|
15
|
+
def ensure_identifier
|
16
|
+
identifier_str = resource.identifier_str
|
17
|
+
return identifier_str if identifier_str
|
18
|
+
|
19
|
+
new_identifier_str = ezid_client.mint_id
|
20
|
+
resource.ensure_identifier(new_identifier_str)
|
21
|
+
new_identifier_str
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_metadata(dc3_xml:)
|
25
|
+
identifier_str = resource.identifier_str
|
26
|
+
landing_page_url = url_helpers.show_path(identifier_str)
|
27
|
+
ezid_client.update_metadata(identifier_str, dc3_xml, landing_page_url)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def tenant
|
33
|
+
resource.tenant
|
34
|
+
end
|
35
|
+
|
36
|
+
def ezid_client
|
37
|
+
@ezid_client ||= begin
|
38
|
+
id_params = tenant.identifier_service
|
39
|
+
StashEzid::Client.new(
|
40
|
+
shoulder: id_params.shoulder,
|
41
|
+
account: id_params.account,
|
42
|
+
password: id_params.password,
|
43
|
+
owner: id_params.owner,
|
44
|
+
id_scheme: id_params.scheme
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Stash
|
2
|
+
module Merritt
|
3
|
+
# The name of this gem
|
4
|
+
NAME = 'stash-merritt'.freeze
|
5
|
+
|
6
|
+
# The version of this gem
|
7
|
+
VERSION = '0.0.1'.freeze
|
8
|
+
|
9
|
+
# The copyright notice for this gem
|
10
|
+
COPYRIGHT = 'Copyright (c) 2017 The Regents of the University of California'.freeze
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'stash/repo'
|
2
|
+
require 'stash/merritt/submission_job'
|
3
|
+
|
4
|
+
module Stash
|
5
|
+
module Merritt
|
6
|
+
class Repository < Stash::Repo::Repository
|
7
|
+
|
8
|
+
def initialize(url_helpers:)
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_submission_job(resource_id:)
|
13
|
+
SubmissionJob.new(resource_id: resource_id, url_helpers: url_helpers)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'stash/repo'
|
2
|
+
require 'stash/merritt/ezid_helper'
|
3
|
+
require 'stash/merritt/submission_package'
|
4
|
+
require 'stash/merritt/sword_helper'
|
5
|
+
|
6
|
+
module Stash
|
7
|
+
module Merritt
|
8
|
+
class SubmissionJob < Stash::Repo::SubmissionJob
|
9
|
+
attr_reader :resource_id
|
10
|
+
attr_reader :url_helpers
|
11
|
+
|
12
|
+
def initialize(resource_id:, url_helpers:)
|
13
|
+
@resource_id = resource_id
|
14
|
+
@url_helpers = url_helpers
|
15
|
+
end
|
16
|
+
|
17
|
+
def submit!
|
18
|
+
log.info("#{Time.now.xmlschema} #{description}")
|
19
|
+
do_submit!
|
20
|
+
rescue => e
|
21
|
+
Stash::Repo::SubmissionResult.failure(resource_id: resource_id, request_desc: description, error: e)
|
22
|
+
end
|
23
|
+
|
24
|
+
def description
|
25
|
+
@description ||= begin
|
26
|
+
resource = StashEngine::Resource.find(resource_id)
|
27
|
+
description_for(resource)
|
28
|
+
rescue => e
|
29
|
+
log.error("Can't find resource #{resource_id}: #{e}\n#{e.backtrace.join("\n")}")
|
30
|
+
"#{self.class} for missing resource #{resource_id}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def do_submit!
|
37
|
+
package = create_package
|
38
|
+
submit(package)
|
39
|
+
update_metadata(package.dc3_xml)
|
40
|
+
cleanup(package)
|
41
|
+
Stash::Repo::SubmissionResult.success(resource_id: resource_id, request_desc: description, message: 'Success')
|
42
|
+
end
|
43
|
+
|
44
|
+
def resource
|
45
|
+
@resource ||= StashEngine::Resource.find(resource_id)
|
46
|
+
end
|
47
|
+
|
48
|
+
def ezid_helper
|
49
|
+
@ezid_helper ||= EzidHelper.new(resource: resource, url_helpers: url_helpers)
|
50
|
+
end
|
51
|
+
|
52
|
+
def ensure_identifier
|
53
|
+
log.info("#{Time.now.xmlschema} #{self.class}: ensuring identifier for resource #{resource_id} (#{resource.identifier_str})")
|
54
|
+
ezid_helper.ensure_identifier
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_package
|
58
|
+
ensure_identifier
|
59
|
+
log.info("#{Time.now.xmlschema} #{self.class}: creating package for resource #{resource_id} (#{resource.identifier_str})")
|
60
|
+
SubmissionPackage.new(resource: resource)
|
61
|
+
end
|
62
|
+
|
63
|
+
def submit(package)
|
64
|
+
log.info("#{Time.now.xmlschema} #{self.class}: submitting resource #{resource_id} (#{resource.identifier_str})")
|
65
|
+
sword_helper = SwordHelper.new(package: package, logger: log)
|
66
|
+
sword_helper.submit!
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_metadata(dc3_xml)
|
70
|
+
log.info("#{Time.now.xmlschema} #{self.class}: updating identifier metadata for resource #{resource_id} (#{resource.identifier_str})")
|
71
|
+
ezid_helper.update_metadata(dc3_xml: dc3_xml)
|
72
|
+
end
|
73
|
+
|
74
|
+
def cleanup(package)
|
75
|
+
log.info("#{Time.now.xmlschema} #{self.class}: cleaning up temporary files for resource #{resource_id} (#{resource.identifier_str})")
|
76
|
+
package.cleanup!
|
77
|
+
end
|
78
|
+
|
79
|
+
def description_for(resource)
|
80
|
+
msg = "#{self.class} for resource #{resource_id} (#{resource.identifier_str}): "
|
81
|
+
msg << if (update_uri = resource.update_uri)
|
82
|
+
"posting update to #{update_uri}"
|
83
|
+
else
|
84
|
+
"posting new object to #{resource.tenant.sword_params[:collection_uri]}"
|
85
|
+
end
|
86
|
+
msg << " (tenant: #{resource.tenant_id})"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'stash/repo/file_builder'
|
2
|
+
|
3
|
+
module Stash
|
4
|
+
module Merritt
|
5
|
+
class SubmissionPackage
|
6
|
+
class DataONEManifestBuilder < Stash::Repo::FileBuilder
|
7
|
+
HEADER = [
|
8
|
+
'#%dataonem_0.1',
|
9
|
+
'#%profile | http://uc3.cdlib.org/registry/ingest/manifest/mrt-dataone-manifest',
|
10
|
+
'#%prefix | dom: | http://uc3.cdlib.org/ontology/dataonem',
|
11
|
+
'#%prefix | mrt: | http://uc3.cdlib.org/ontology/mom',
|
12
|
+
'#%fields | dom:scienceMetadataFile | dom:scienceMetadataFormat | dom:scienceDataFile | mrt:mimeType'
|
13
|
+
].join("\n").freeze
|
14
|
+
|
15
|
+
METADATA_FILES = {
|
16
|
+
'mrt-datacite.xml' => 'http://datacite.org/schema/kernel-3.1',
|
17
|
+
'mrt-oaidc.xml' => 'http://dublincore.org/schemas/xmls/qdc/2008/02/11/qualifieddc.xsd'
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
attr_reader :uploads
|
21
|
+
|
22
|
+
# @param uploads [Array[StashEngine::FileUpload]] a list of file uploads
|
23
|
+
def initialize(uploads)
|
24
|
+
super(file_name: 'mrt-dataone-manifest.txt')
|
25
|
+
@uploads = uploads
|
26
|
+
end
|
27
|
+
|
28
|
+
def contents
|
29
|
+
content = [HEADER]
|
30
|
+
uploads.each do |upload|
|
31
|
+
METADATA_FILES.each do |md_filename, md_schema|
|
32
|
+
content << "#{md_filename} | #{md_schema} | #{upload.upload_file_name} | #{upload.upload_content_type}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
content << "#%eof\n"
|
36
|
+
content.join("\n")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'datacite/mapping/datacite_xml_factory'
|
2
|
+
require 'stash/repo/file_builder'
|
3
|
+
|
4
|
+
module Stash
|
5
|
+
module Merritt
|
6
|
+
class SubmissionPackage
|
7
|
+
class MerrittDataciteBuilder < Stash::Repo::FileBuilder
|
8
|
+
attr_reader :factory
|
9
|
+
|
10
|
+
# @param factory [DataciteXMLFactory] the Datacite XML factory
|
11
|
+
def initialize(factory)
|
12
|
+
super(file_name: 'mrt-datacite.xml')
|
13
|
+
@factory = factory
|
14
|
+
end
|
15
|
+
|
16
|
+
def contents
|
17
|
+
factory.build_datacite_xml(datacite_3: true)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'stash/repo/file_builder'
|
2
|
+
|
3
|
+
module Stash
|
4
|
+
module Merritt
|
5
|
+
class SubmissionPackage
|
6
|
+
class MerrittDeleteBuilder < Stash::Repo::FileBuilder
|
7
|
+
attr_reader :resource_id
|
8
|
+
|
9
|
+
def initialize(resource_id:)
|
10
|
+
super(file_name: 'mrt-delete.txt')
|
11
|
+
@resource_id = resource_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def resource
|
15
|
+
@resource ||= StashEngine::Resource.find(resource_id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def contents
|
19
|
+
del_files = resource.file_uploads.deleted
|
20
|
+
del_files.blank? ? nil : del_files.map(&:upload_file_name).join("\n")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'stash/repo/file_builder'
|
2
|
+
|
3
|
+
module Stash
|
4
|
+
module Merritt
|
5
|
+
class SubmissionPackage
|
6
|
+
class MerrittOAIDCBuilder < Stash::Repo::FileBuilder
|
7
|
+
ROOT_ATTRIBUTES = {
|
8
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
9
|
+
'xsi:noNamespaceSchemaLocation' => 'http://dublincore.org/schemas/xmls/qdc/2008/02/11/qualifieddc.xsd',
|
10
|
+
'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
|
11
|
+
'xmlns:dcterms' => 'http://purl.org/dc/terms/'
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
DC_RELATION_TYPES = {
|
15
|
+
'cites' => 'references',
|
16
|
+
'iscitedby' => 'isReferencedBy',
|
17
|
+
'isnewversionof' => 'isVersionOf',
|
18
|
+
'ispreviousversionof' => 'hasVersion',
|
19
|
+
'ispartof' => 'isPartOf',
|
20
|
+
'haspart' => 'hasPart'
|
21
|
+
}.freeze
|
22
|
+
|
23
|
+
attr_reader :resource_id
|
24
|
+
|
25
|
+
def initialize(resource_id:)
|
26
|
+
super(file_name: 'mrt-oaidc.xml')
|
27
|
+
@resource_id = resource_id
|
28
|
+
end
|
29
|
+
|
30
|
+
def contents # rubocop:disable Metrics/MethodLength
|
31
|
+
Nokogiri::XML::Builder.new do |xml|
|
32
|
+
xml.qualifieddc(ROOT_ATTRIBUTES) do
|
33
|
+
add_creators(xml)
|
34
|
+
add_contributors(xml)
|
35
|
+
add_title(xml)
|
36
|
+
add_publisher(xml)
|
37
|
+
add_pub_year(xml)
|
38
|
+
add_subjects(xml)
|
39
|
+
add_resource_type(xml)
|
40
|
+
add_rights(xml)
|
41
|
+
add_descriptions(xml)
|
42
|
+
add_related_identifiers(xml)
|
43
|
+
end
|
44
|
+
end.to_xml.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def resource
|
50
|
+
@resource ||= StashEngine::Resource.find(resource_id)
|
51
|
+
end
|
52
|
+
|
53
|
+
def tenant
|
54
|
+
resource.tenant
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_creators(xml)
|
58
|
+
resource.creators.each { |c| xml.send(:'dc:creator', c.creator_full_name.delete("\r").to_s) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_pub_year(xml)
|
62
|
+
pub_year = resource.publication_years.first
|
63
|
+
xml.send(:'dc:date', pub_year.publication_year) if pub_year
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_publisher(xml)
|
67
|
+
xml.send(:'dc:publisher', (tenant.short_name || tenant.long_name || 'unknown').to_s)
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_title(xml)
|
71
|
+
xml.send(:'dc:title', resource.titles.where(title_type: nil).first.title.to_s)
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_contributors(xml)
|
75
|
+
# Funder contributors are handled under 'add_descriptions' below
|
76
|
+
resource.contributors.where.not(contributor_type: 'funder').each do |c|
|
77
|
+
if (contrib_name = c.contributor_name) && !contrib_name.blank?
|
78
|
+
xml.send(:'dc:contributor', contrib_name.strip)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_subjects(xml)
|
84
|
+
resource.subjects.each { |s| xml.send(:'dc:subject', s.subject.delete("\r").to_s) }
|
85
|
+
end
|
86
|
+
|
87
|
+
def add_resource_type(xml)
|
88
|
+
resource_type = (rt = resource.resource_type) && rt.resource_type_general
|
89
|
+
xml.send(:'dc:type', resource_type.strip) unless resource_type.blank?
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_rights(xml)
|
93
|
+
resource.rights.each do |r|
|
94
|
+
xml.send(:'dc:rights', r.rights.to_s)
|
95
|
+
xml.send(:'dcterms:license', r.rights_uri.to_s, 'xsi:type' => 'dcterms:URI')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def add_descriptions(xml)
|
100
|
+
strip_desc_linefeeds(xml)
|
101
|
+
resource.contributors.where(contributor_type: 'funder').each do |c|
|
102
|
+
xml.send(:'dc:description', to_dc_description(c))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_dc_description(contributor)
|
107
|
+
contrib_name = contributor.contributor_name
|
108
|
+
award_num = contributor.award_number
|
109
|
+
desc_text = 'Data were created'
|
110
|
+
desc_text << " with funding from #{contrib_name}" unless contrib_name.blank?
|
111
|
+
desc_text << " under grant(s) #{award_num}" unless award_num.blank?
|
112
|
+
end
|
113
|
+
|
114
|
+
def strip_desc_linefeeds(xml)
|
115
|
+
resource.descriptions.each do |d|
|
116
|
+
desc_text = d.description.to_s.delete("\r")
|
117
|
+
xml.send(:'dc:description', desc_text.to_s) unless desc_text.blank?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def add_related_identifiers(xml)
|
122
|
+
resource.related_identifiers.each do |r|
|
123
|
+
dc_relation_type = DC_RELATION_TYPES[r.relation_type] || 'relation'
|
124
|
+
xml.send(:"dcterms:#{dc_relation_type}", "#{r.related_identifier_type_friendly}: #{r.related_identifier}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'stash/wrapper'
|
2
|
+
require 'stash/repo/file_builder'
|
3
|
+
|
4
|
+
module Stash
|
5
|
+
module Merritt
|
6
|
+
class SubmissionPackage
|
7
|
+
class StashWrapperBuilder < Stash::Repo::FileBuilder
|
8
|
+
include Stash::Wrapper
|
9
|
+
attr_reader :dcs_resource
|
10
|
+
attr_reader :uploads
|
11
|
+
attr_reader :version_number
|
12
|
+
|
13
|
+
def initialize(dcs_resource:, version_number:, uploads:)
|
14
|
+
super(file_name: 'stash-wrapper.xml')
|
15
|
+
@dcs_resource = dcs_resource
|
16
|
+
@version_number = version_number
|
17
|
+
@uploads = uploads
|
18
|
+
end
|
19
|
+
|
20
|
+
def contents
|
21
|
+
StashWrapper.new(
|
22
|
+
identifier: to_sw_identifier(dcs_resource.identifier),
|
23
|
+
version: Version.new(number: version_number, date: Date.today),
|
24
|
+
license: to_sw_license(dcs_resource.rights_list),
|
25
|
+
inventory: to_sw_inventory(uploads),
|
26
|
+
descriptive_elements: [dcs_resource.save_to_xml]
|
27
|
+
).write_xml
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def to_sw_identifier(dcs_identifier)
|
33
|
+
return unless dcs_identifier
|
34
|
+
raise "Invalid identifier type; expected DOI, was #{dcs_identifier.identifier_type}" unless dcs_identifier.identifier_type == 'DOI'
|
35
|
+
Identifier.new(type: IdentifierType::DOI, value: dcs_identifier.value)
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_sw_license(dcs_rights_list)
|
39
|
+
return unless dcs_rights_list && !dcs_rights_list.empty?
|
40
|
+
dcs_rights = dcs_rights_list[0]
|
41
|
+
License.new(name: dcs_rights.value, uri: dcs_rights.uri)
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_sw_inventory(uploads)
|
45
|
+
return unless uploads
|
46
|
+
Inventory.new(files: uploads.map { |upload| to_stash_file(upload) })
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_stash_file(upload)
|
50
|
+
StashFile.new(
|
51
|
+
pathname: upload.upload_file_name,
|
52
|
+
size_bytes: upload.upload_file_size,
|
53
|
+
mime_type: upload.upload_content_type
|
54
|
+
)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|