datacite 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +118 -17
- data/README.md +20 -0
- data/datacite.gemspec +2 -0
- data/lib/datacite/mapping/from_cocina/alternate_identifiers.rb +30 -0
- data/lib/datacite/mapping/from_cocina/attributes.rb +74 -0
- data/lib/datacite/mapping/from_cocina/contributor_attributes.rb +209 -0
- data/lib/datacite/mapping/from_cocina/date.rb +198 -0
- data/lib/datacite/mapping/from_cocina/descriptions.rb +41 -0
- data/lib/datacite/mapping/from_cocina/identifiers.rb +28 -0
- data/lib/datacite/mapping/from_cocina/related_resource.rb +168 -0
- data/lib/datacite/mapping/from_cocina/rights_list.rb +36 -0
- data/lib/datacite/mapping/from_cocina/subject.rb +68 -0
- data/lib/datacite/mapping/from_cocina/titles.rb +32 -0
- data/lib/datacite/mapping/from_cocina/types.rb +81 -0
- data/lib/datacite/schema/datacite-v4.6.json +643 -0
- data/lib/datacite/validators/attributes_validator.rb +43 -0
- data/lib/datacite/validators/cocina_validator.rb +26 -0
- data/lib/datacite/version.rb +1 -1
- metadata +45 -3
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::DRO.description.event attributes to appropriate DataCite attributes
|
|
7
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
8
|
+
class Date # rubocop:disable Metrics/ClassLength
|
|
9
|
+
# @param [Cocina::Models::DRO] cocina_object
|
|
10
|
+
def self.build(...)
|
|
11
|
+
new(...).call
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(cocina_object:)
|
|
15
|
+
@cocina_object = cocina_object
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# DataCite publicationYear is the year (YYYY) the object is published to purl, and is either:
|
|
19
|
+
## The embargo end date, if present (cocina event type release, date type publication)
|
|
20
|
+
## The deposit date (cocina event type deposit, date type publication)
|
|
21
|
+
#
|
|
22
|
+
# @return [String] publication year, conforming to the expectations of HTTP PUT request to DataCite
|
|
23
|
+
def pub_year # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
24
|
+
if embargo?
|
|
25
|
+
embargo_release_date = cocina_dro_access&.embargo&.releaseDate
|
|
26
|
+
embargo_release_date&.year&.to_s
|
|
27
|
+
elsif deposit_event_publication_date_value
|
|
28
|
+
DateTime.parse(deposit_event_publication_date_value).year&.to_s
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# H2 publisher role > same cocina event as publication date > see DataCite contributor mappings
|
|
33
|
+
# Add Stanford Digital Repository as publisher to cocina release event if present, otherwise deposit event
|
|
34
|
+
#
|
|
35
|
+
# sdr is the publisher for the event where the content becomes public via purl -- deposit if no embargo,
|
|
36
|
+
# release if embargo present.
|
|
37
|
+
# if it's not public via purl, sdr should not be the publisher;
|
|
38
|
+
# the user may enter someone with the publisher role in h2, referring to publication in another venue,
|
|
39
|
+
# regardless of the purl status.
|
|
40
|
+
def publisher
|
|
41
|
+
# TODO: implement this
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# DataCite date (YYYY-MM-DD) is repeatable and each DataCite data has an associated type attribute
|
|
45
|
+
# @return [Array<Hash>] DataCite date hashs, conforming to the expectations of HTTP PUT request to DataCite
|
|
46
|
+
def call # rubocop:disable Metrics/AbcSize
|
|
47
|
+
[].tap do |dates|
|
|
48
|
+
dates << submitted_date if submitted_date.present?
|
|
49
|
+
dates << available_date if available_date.present?
|
|
50
|
+
dates << issued_date if issued_date.present?
|
|
51
|
+
dates << created_date if created_date.present?
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
attr_reader :cocina_object
|
|
58
|
+
|
|
59
|
+
def embargo?
|
|
60
|
+
cocina_dro_access&.embargo&.releaseDate.presence
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# If embargo,
|
|
64
|
+
# Cocina event type deposit, date type deposit maps to DataCite date type Submitted
|
|
65
|
+
# If no embargo
|
|
66
|
+
# Cocina event type deposit, date type publication maps to DataCite date type Submitted
|
|
67
|
+
# If no embargo and no deposit event with date type publication,
|
|
68
|
+
# Cocina event type publication, date type publication maps to DataCite date type Submitted
|
|
69
|
+
def submitted_date # rubocop:disable Metrics/AbcSize
|
|
70
|
+
@submitted_date ||= {}.tap do |submitted_date|
|
|
71
|
+
if embargo? && deposit_event_deposit_date_value.present?
|
|
72
|
+
submitted_date[:date] = deposit_event_deposit_date_value
|
|
73
|
+
elsif deposit_event_publication_date_value.present? # no embargo
|
|
74
|
+
submitted_date[:date] = deposit_event_publication_date_value
|
|
75
|
+
elsif publication_event_publication_date_value.present? # no embargo
|
|
76
|
+
submitted_date[:date] = publication_event_publication_date_value
|
|
77
|
+
end
|
|
78
|
+
submitted_date[:dateType] = 'Submitted' if submitted_date.present?
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# from Arcadia:
|
|
83
|
+
# Cocina event type release, date type publication maps to DataCite date type Available
|
|
84
|
+
# In actuality:
|
|
85
|
+
# embargo release date is in DROAccess, not in an event
|
|
86
|
+
def available_date
|
|
87
|
+
return unless embargo?
|
|
88
|
+
|
|
89
|
+
@available_date ||=
|
|
90
|
+
{
|
|
91
|
+
date: cocina_dro_access&.embargo&.releaseDate.to_s,
|
|
92
|
+
dateType: 'Available'
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Cocina event type publication, date type publication maps to DataCite date type Issued
|
|
97
|
+
def issued_date
|
|
98
|
+
return if publication_event_publication_date_value.blank?
|
|
99
|
+
|
|
100
|
+
@issued_date ||=
|
|
101
|
+
{
|
|
102
|
+
date: publication_event_publication_date_value,
|
|
103
|
+
dateType: 'Issued'
|
|
104
|
+
}
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Cocina event type creation, date type creation maps to DataCite date type Created
|
|
108
|
+
def created_date # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
109
|
+
return if creation_event_creation_date.blank?
|
|
110
|
+
|
|
111
|
+
@created_date ||= begin
|
|
112
|
+
created_date = {
|
|
113
|
+
dateType: 'Created'
|
|
114
|
+
}
|
|
115
|
+
if creation_event_creation_date.value
|
|
116
|
+
created_date[:date] = creation_event_creation_date.value
|
|
117
|
+
if creation_event_creation_date.qualifier.present?
|
|
118
|
+
created_date[:dateInformation] =
|
|
119
|
+
creation_event_creation_date.qualifier
|
|
120
|
+
end
|
|
121
|
+
else
|
|
122
|
+
created_date.merge!(structured_date_result(creation_event_creation_date))
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
created_date
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def deposit_event_deposit_date_value
|
|
130
|
+
@deposit_event_deposit_date_value ||= deposit_event&.date&.find { |date| date&.type == 'deposit' }&.value
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def deposit_event_publication_date_value
|
|
134
|
+
@deposit_event_publication_date_value ||= deposit_event&.date&.find do |date|
|
|
135
|
+
date&.type == 'publication'
|
|
136
|
+
end&.value
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def deposit_event
|
|
140
|
+
@deposit_event ||= cocina_events&.find { |event| event&.type == 'deposit' }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def publication_event_publication_date_value
|
|
144
|
+
@publication_event_publication_date_value ||= publication_event&.date&.find do |date|
|
|
145
|
+
date&.type == 'publication'
|
|
146
|
+
end&.value
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def publication_event
|
|
150
|
+
@publication_event ||= cocina_events&.find { |event| event&.type == 'publication' }
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def creation_event_creation_date
|
|
154
|
+
@creation_event_creation_date ||= creation_event&.date&.find { |date| date&.type == 'creation' }
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def creation_event
|
|
158
|
+
@creation_event ||= cocina_events&.find { |event| event&.type == 'creation' }
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def structured_date_result(date) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
162
|
+
return unless date.structuredValue
|
|
163
|
+
|
|
164
|
+
start_date, end_date, = ''
|
|
165
|
+
info = date.qualifier if date.qualifier.present?
|
|
166
|
+
date.structuredValue.each do |structured_val|
|
|
167
|
+
start_date = structured_val.value if structured_val.type == 'start'
|
|
168
|
+
end_date = structured_val.value if structured_val.type == 'end'
|
|
169
|
+
info = structured_val.qualifier if structured_val.qualifier
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
result_date = if start_date.present? && end_date.present?
|
|
173
|
+
"#{start_date}/#{end_date}"
|
|
174
|
+
elsif start_date.present?
|
|
175
|
+
start_date
|
|
176
|
+
elsif end_date.present?
|
|
177
|
+
end_date
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
{
|
|
181
|
+
date: result_date
|
|
182
|
+
}.tap do |attributes|
|
|
183
|
+
attributes[:dateInformation] = info if info.present? && result_date.present?
|
|
184
|
+
end.compact
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def cocina_events
|
|
188
|
+
@cocina_events ||= cocina_object.description.event
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# embargo is in Cocina::Models::DROAccess -- the top level access, not description.access
|
|
192
|
+
def cocina_dro_access
|
|
193
|
+
@cocina_dro_access ||= cocina_object.access
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::Description note attributes to the DataCite descriptions attributes
|
|
7
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
8
|
+
class Descriptions
|
|
9
|
+
# @param [Cocina::Models::Description] cocina_desc
|
|
10
|
+
# @return [NilClass, Array<Hash>] list of DataCite descriptions attributes, conforming to the expectations of
|
|
11
|
+
# HTTP PUT request to DataCite
|
|
12
|
+
def self.build(...)
|
|
13
|
+
new(...).call
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(description:)
|
|
17
|
+
@description = description
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [NilClass, Array<Hash>] list of DataCite descriptions attributes, conforming to the expectations of
|
|
21
|
+
# HTTP PUT request to DataCite
|
|
22
|
+
def call
|
|
23
|
+
return unless abstract
|
|
24
|
+
|
|
25
|
+
[{
|
|
26
|
+
description: abstract,
|
|
27
|
+
descriptionType: 'Abstract'
|
|
28
|
+
}]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :description
|
|
34
|
+
|
|
35
|
+
def abstract
|
|
36
|
+
@abstract ||= Array(description.note).find { |cocina_note| cocina_note.type == 'abstract' }&.value
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::Identification to the DataCite identifier attributes
|
|
7
|
+
class Identifiers
|
|
8
|
+
# @param [Cocina::Models::Identification] identification
|
|
9
|
+
def self.build(...)
|
|
10
|
+
new(...).call
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(identification:)
|
|
14
|
+
@identification = identification
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :identification
|
|
18
|
+
|
|
19
|
+
def call
|
|
20
|
+
[{
|
|
21
|
+
identifier: identification.doi,
|
|
22
|
+
identifierType: 'DOI'
|
|
23
|
+
}]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::Description relatedResource attributes to the DataCite relatedItem attributes
|
|
7
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
8
|
+
class RelatedResource # rubocop:disable Metrics/ClassLength
|
|
9
|
+
RELATION_TYPE_MAP = {
|
|
10
|
+
'supplement to' => 'IsSupplementTo',
|
|
11
|
+
'supplemented by' => 'IsSupplementedBy',
|
|
12
|
+
'referenced by' => 'IsReferencedBy',
|
|
13
|
+
'references' => 'References',
|
|
14
|
+
'derived from' => 'IsDerivedFrom',
|
|
15
|
+
'source of' => 'IsSourceOf',
|
|
16
|
+
'version of record' => 'IsVersionOf',
|
|
17
|
+
'identical to' => 'IsIdenticalTo',
|
|
18
|
+
'has version' => 'HasVersion',
|
|
19
|
+
'preceded by' => 'Continues',
|
|
20
|
+
'succeeded by' => 'IsContinuedBy',
|
|
21
|
+
'part of' => 'IsPartOf',
|
|
22
|
+
'has part' => 'HasPart'
|
|
23
|
+
}.freeze
|
|
24
|
+
|
|
25
|
+
# @param [Cocina::Models::RelatedResource] related_resource
|
|
26
|
+
# @return [Hash] Hash of DataCite relatedItem attributes, conforming to the expectations of HTTP PUT
|
|
27
|
+
# request to DataCite or nil if blank
|
|
28
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
29
|
+
def self.related_item_attributes(...)
|
|
30
|
+
new(...).related_item_attributes
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @param [Cocina::Models::RelatedResource] related_resource
|
|
34
|
+
# @return [Hash] Hash of DataCite relatedIdentifier attributes, conforming to the expectations of HTTP PUT
|
|
35
|
+
# request to DataCite or nil if blank
|
|
36
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
37
|
+
def self.related_identifier_attributes(...)
|
|
38
|
+
new(...).related_identifier_attributes
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize(related_resource:)
|
|
42
|
+
@related_resource = related_resource
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [Hash,nil] Array of DataCite relatedItem attributes, conforming to the expectations of HTTP PUT
|
|
46
|
+
# request to DataCite or nil if blank
|
|
47
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
48
|
+
def related_item_attributes # rubocop:disable Metrics/MethodLength
|
|
49
|
+
return if related_resource_blank?
|
|
50
|
+
|
|
51
|
+
titles = related_item_title ? [title: related_item_title] : []
|
|
52
|
+
id, type = unpack_related_uri_and_type
|
|
53
|
+
|
|
54
|
+
if id && type
|
|
55
|
+
{
|
|
56
|
+
relatedItemType: 'Other',
|
|
57
|
+
titles: titles,
|
|
58
|
+
relationType: relation_type,
|
|
59
|
+
relatedItemIdentifier: {
|
|
60
|
+
relatedItemIdentifier: id,
|
|
61
|
+
relatedItemIdentifierType: type
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
{
|
|
66
|
+
relatedItemType: 'Other',
|
|
67
|
+
titles: titles,
|
|
68
|
+
relationType: relation_type
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @return [Hash,nil] Array of DataCite relatedIdentifier attributes, conforming to the expectations of HTTP PUT
|
|
74
|
+
# request to DataCite or nil if blank or the identifier lacks a URI or Type
|
|
75
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
76
|
+
def related_identifier_attributes
|
|
77
|
+
return if related_identifier_blank?
|
|
78
|
+
|
|
79
|
+
id, type = unpack_related_uri_and_type
|
|
80
|
+
return unless id && type
|
|
81
|
+
|
|
82
|
+
{
|
|
83
|
+
resourceTypeGeneral: 'Other',
|
|
84
|
+
relationType: relation_type,
|
|
85
|
+
relatedIdentifier: id,
|
|
86
|
+
relatedIdentifierType: type
|
|
87
|
+
}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
private
|
|
91
|
+
|
|
92
|
+
attr_reader :related_resource
|
|
93
|
+
|
|
94
|
+
def relation_type
|
|
95
|
+
related_resource.dataCiteRelationType || RELATION_TYPE_MAP.fetch(related_resource.type, 'References')
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def related_resource_blank?
|
|
99
|
+
return true if related_resource.blank?
|
|
100
|
+
|
|
101
|
+
related_resource_hash = related_resource.to_h.slice(:note, :title, :access, :identifier)
|
|
102
|
+
related_resource_hash.blank? || related_resource_hash.each_value.all?(&:blank?)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def related_identifier_blank?
|
|
106
|
+
return true if related_resource.blank?
|
|
107
|
+
|
|
108
|
+
related_resource_hash = related_resource.to_h.slice(:access, :identifier)
|
|
109
|
+
related_resource_hash.blank? || related_resource_hash.each_value.all?(&:blank?)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def related_item_title
|
|
113
|
+
@related_item_title ||= preferred_citation || other_title \
|
|
114
|
+
|| related_item_doi || related_item_arxiv || related_item_pmid \
|
|
115
|
+
|| related_item_identifier_url
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def preferred_citation
|
|
119
|
+
Array(related_resource.note).find do |note|
|
|
120
|
+
note.type == 'preferred citation' && note.value.present?
|
|
121
|
+
end&.value
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def other_title
|
|
125
|
+
Array(related_resource.title).find do |title|
|
|
126
|
+
title.value.present?
|
|
127
|
+
end&.value
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def related_item_doi
|
|
131
|
+
Array(related_resource.identifier).find do |identifier|
|
|
132
|
+
identifier.type == 'doi' && identifier.uri.present?
|
|
133
|
+
end&.uri
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def related_item_arxiv
|
|
137
|
+
Array(related_resource.identifier).find do |identifier|
|
|
138
|
+
identifier.type == 'arxiv' && identifier.uri.present?
|
|
139
|
+
end&.uri
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def related_item_pmid
|
|
143
|
+
Array(related_resource.identifier).find do |identifier|
|
|
144
|
+
identifier.type == 'pmid' && identifier.uri.present?
|
|
145
|
+
end&.uri
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def related_item_identifier_url
|
|
149
|
+
@related_item_identifier_url ||= Array(related_resource.access&.url).find do |url|
|
|
150
|
+
url.value.present?
|
|
151
|
+
end&.value
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def unpack_related_uri_and_type
|
|
155
|
+
if related_item_doi
|
|
156
|
+
[related_item_doi, 'DOI']
|
|
157
|
+
elsif related_item_arxiv
|
|
158
|
+
[related_item_arxiv, 'arXiv']
|
|
159
|
+
elsif related_item_pmid
|
|
160
|
+
[related_item_pmid, 'PMID']
|
|
161
|
+
elsif related_item_identifier_url
|
|
162
|
+
[related_item_identifier_url, 'URL']
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::DROAccess attributes to the DataCite rightsList attributes
|
|
7
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
8
|
+
class RightsList
|
|
9
|
+
# @param [Cocina::Models::DROAccess] cocina_item_access
|
|
10
|
+
# @return [NilClass,Array<Hash>] list of DataCite rightsList attributes, conforming to the expectations of
|
|
11
|
+
# HTTP PUT request to DataCite
|
|
12
|
+
def self.build(...)
|
|
13
|
+
new(...).call
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(access:)
|
|
17
|
+
@access = access
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [NilClass,Array<Hash>] list of DataCite rightsList attributes, conforming to the expectations of
|
|
21
|
+
# HTTP PUT request to DataCite
|
|
22
|
+
def call
|
|
23
|
+
return if access&.license.blank?
|
|
24
|
+
|
|
25
|
+
[{
|
|
26
|
+
rightsUri: access&.license
|
|
27
|
+
}]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
attr_reader :access
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::Description subjects attributes to the DataCite subjects attributes
|
|
7
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
8
|
+
class Subject
|
|
9
|
+
# @param [Cocina::Models::Description] description
|
|
10
|
+
# @return [NilClass,Array<Hash>] list of DataCite subjects attributes, conforming to the expectations of
|
|
11
|
+
# HTTP PUT request to DataCite
|
|
12
|
+
def self.build(...)
|
|
13
|
+
new(...).call
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(description:)
|
|
17
|
+
@description = description
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [NilClass,Array<Hash>] list of DataCite subjects attributes, conforming to the expectations of
|
|
21
|
+
# HTTP PUT request to DataCite
|
|
22
|
+
def call
|
|
23
|
+
return if description&.subject.blank?
|
|
24
|
+
|
|
25
|
+
results = description.subject.map do |cocina_subject|
|
|
26
|
+
subject(cocina_subject)
|
|
27
|
+
end
|
|
28
|
+
results.compact.presence
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :description
|
|
34
|
+
|
|
35
|
+
def subject(cocina_subject)
|
|
36
|
+
return if cocina_subject.blank?
|
|
37
|
+
|
|
38
|
+
if fast?(cocina_subject)
|
|
39
|
+
fast_subject(cocina_subject)
|
|
40
|
+
else
|
|
41
|
+
non_fast_subject(cocina_subject)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def fast_subject(cocina_subject)
|
|
46
|
+
{
|
|
47
|
+
subjectScheme: 'fast',
|
|
48
|
+
schemeUri: 'http://id.worldcat.org/fast/'
|
|
49
|
+
|
|
50
|
+
}.tap do |attribs|
|
|
51
|
+
attribs[:subject] = cocina_subject.value if cocina_subject.value.present?
|
|
52
|
+
attribs[:valueUri] = cocina_subject.uri if cocina_subject.uri.present?
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def non_fast_subject(cocina_subject)
|
|
57
|
+
return if cocina_subject.value.blank?
|
|
58
|
+
|
|
59
|
+
{ subject: cocina_subject.value }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def fast?(cocina_subject)
|
|
63
|
+
cocina_subject&.source&.code == 'fast'
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::Description title attributes to attributes for one DataCite title
|
|
7
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
8
|
+
class Titles
|
|
9
|
+
# @param [Cocina::Models::Description] description
|
|
10
|
+
# @return [Array<Hash>] list of titles for DataCite, conforming to the expectations of HTTP PUT request
|
|
11
|
+
# to DataCite
|
|
12
|
+
def self.build(...)
|
|
13
|
+
new(...).call
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(description:)
|
|
17
|
+
@description = description
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [Array<Hash>] list of titles for DataCite, conforming to the expectations of HTTP PUT request
|
|
21
|
+
# to DataCite
|
|
22
|
+
def call
|
|
23
|
+
[{ title: description.title.first.value }]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
attr_reader :description
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Datacite
|
|
4
|
+
module Mapping
|
|
5
|
+
module FromCocina
|
|
6
|
+
# Transform the Cocina::Models::Description form attributes to the DataCite types attributes
|
|
7
|
+
# see https://support.datacite.org/reference/dois-2#put_dois-id
|
|
8
|
+
class Types
|
|
9
|
+
# @param [Cocina::Models::Description] description
|
|
10
|
+
# @return [NilClass, Hash] the DataCite types attributes, conforming to the expectations of HTTP PUT request
|
|
11
|
+
# to DataCite
|
|
12
|
+
def self.build(...)
|
|
13
|
+
new(...).call
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(description:)
|
|
17
|
+
@description = description
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [NilClass, Hash] the DataCite types attributes, conforming to the expectations of HTTP PUT request
|
|
21
|
+
# to DataCite
|
|
22
|
+
def call
|
|
23
|
+
return unless resource_type_general || resource_type
|
|
24
|
+
|
|
25
|
+
{
|
|
26
|
+
resourceTypeGeneral: resource_type_general,
|
|
27
|
+
resourceType: resource_type || ''
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :description
|
|
34
|
+
|
|
35
|
+
# @return String DataCite resourceTypeGeneral value
|
|
36
|
+
def resource_type_general
|
|
37
|
+
@resource_type_general ||= Array(description.form).find do |cocina_form|
|
|
38
|
+
datacite_resource_types_form?(cocina_form)
|
|
39
|
+
end&.value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [String] DataCite resourceType value
|
|
43
|
+
def resource_type
|
|
44
|
+
@resource_type ||= begin
|
|
45
|
+
self_deposit_form = Array(description.form).find { |cocina_form| self_deposit_form?(cocina_form) }
|
|
46
|
+
|
|
47
|
+
subtypes = self_deposit_subtypes(self_deposit_form)
|
|
48
|
+
if subtypes.blank?
|
|
49
|
+
self_deposit_type(self_deposit_form)
|
|
50
|
+
else
|
|
51
|
+
subtypes.select { |subtype| subtype if subtype != resource_type_general }.join('; ')
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# call with cocina form element for Stanford self deposit resource types
|
|
57
|
+
# @return String the value from the structuredValue when the type is 'type' for the cocina form element
|
|
58
|
+
def self_deposit_type(cocina_self_deposit_form)
|
|
59
|
+
cocina_self_deposit_form&.structuredValue&.each do |struct_val|
|
|
60
|
+
return struct_val.value if struct_val.type == 'type'
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def self_deposit_subtypes(cocina_self_deposit_form)
|
|
65
|
+
cocina_self_deposit_form&.structuredValue&.filter_map do |struct_val|
|
|
66
|
+
struct_val.value if struct_val.type == 'subtype'
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def self_deposit_form?(cocina_form)
|
|
71
|
+
cocina_form.type == 'resource type' &&
|
|
72
|
+
cocina_form.source&.value == 'Stanford self-deposit resource types'
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def datacite_resource_types_form?(cocina_form)
|
|
76
|
+
cocina_form.source&.value == 'DataCite resource types'
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|