datacite 0.6.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.
@@ -0,0 +1,209 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datacite
4
+ module Mapping
5
+ module FromCocina
6
+ # Transform the Cocina::Models::Description to contributor attributes
7
+ # see https://support.datacite.org/reference/dois-2#put_dois-id
8
+ class ContributorAttributes # rubocop:disable Metrics/ClassLength
9
+ DATACITE_PERSON_CONTRIBUTOR_TYPES = {
10
+ 'copyright holder' => 'RightsHolder',
11
+ 'compiler' => 'DataCollector',
12
+ 'editor' => 'Editor',
13
+ 'organizer' => 'Supervisor',
14
+ 'research team head' => 'ProjectLeader',
15
+ 'researcher' => 'Researcher'
16
+ }.freeze
17
+
18
+ DATACITE_ORGANIZATION_CONTRIBUTOR_TYPES = {
19
+ 'copyright holder' => 'RightsHolder',
20
+ 'compiler' => 'DataCollector',
21
+ 'distributor' => 'Distributor',
22
+ 'host institution' => 'HostingInstitution',
23
+ 'issuing body' => 'Distributor',
24
+ 'publisher' => 'Distributor',
25
+ 'researcher' => 'ResearchGroup',
26
+ 'sponsor' => 'Sponsor'
27
+ }.freeze
28
+
29
+ # @param [Cocina::Models::Description] description
30
+ # @return [Hash] Hash of DataCite attributes containing creators, contributors, and fundingReferences keys
31
+ def self.build(...)
32
+ new(...).call
33
+ end
34
+
35
+ def initialize(description:)
36
+ @description = description
37
+ end
38
+
39
+ # @return [Hash] Hash of DataCite attributes containing creators, contributors, and fundingReferences keys
40
+ def call
41
+ {
42
+ creators: datacite_creators,
43
+ contributors: datacite_contributors,
44
+ fundingReferences: datacite_funders
45
+ }
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :description
51
+
52
+ def cocina_creators
53
+ @cocina_creators ||= Array(description.contributor).select do |cocina_contributor|
54
+ datacite_creator?(cocina_contributor)
55
+ end
56
+ end
57
+
58
+ def cocina_contributors
59
+ @cocina_contributors ||= Array(description.contributor).select do |cocina_contributor|
60
+ datacite_contributor?(cocina_contributor)
61
+ end
62
+ end
63
+
64
+ def cocina_funders
65
+ @cocina_funders ||= Array(description.contributor).select do |cocina_contributor|
66
+ datacite_funder?(cocina_contributor)
67
+ end
68
+ end
69
+
70
+ def datacite_creator?(cocina_contributor)
71
+ !datacite_funder?(cocina_contributor) && !datacite_contributor?(cocina_contributor)
72
+ end
73
+
74
+ def datacite_funder?(cocina_contributor)
75
+ marc_relator(cocina_contributor) == 'funder'
76
+ end
77
+
78
+ def datacite_contributor?(cocina_contributor)
79
+ marc_relator(cocina_contributor) == 'publisher' || degree_committee_member?(cocina_contributor)
80
+ end
81
+
82
+ def datacite_creators
83
+ @datacite_creators ||= cocina_creators.map { |cocina_creator| datacite_creator(cocina_creator) }.uniq
84
+ end
85
+
86
+ def datacite_contributors
87
+ @datacite_contributors ||= cocina_contributors.map do |cocina_contributor|
88
+ datacite_contributor(cocina_contributor)
89
+ end.uniq
90
+ end
91
+
92
+ def datacite_funders
93
+ @datacite_funders ||= cocina_funders.map { |cocina_funder| { funderName: cocina_funder.name.first.value } }
94
+ end
95
+
96
+ def datacite_creator(cocina_contributor)
97
+ return personal_name(cocina_contributor) if person?(cocina_contributor)
98
+
99
+ organizational_name(cocina_contributor)
100
+ end
101
+
102
+ def person?(cocina_contributor)
103
+ cocina_contributor.type == 'person'
104
+ end
105
+
106
+ def datacite_contributor(cocina_contributor)
107
+ datacite_creator(cocina_contributor).merge({ contributorType: contributor_type(cocina_contributor) })
108
+ end
109
+
110
+ def personal_name(cocina_contributor) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
111
+ {
112
+ nameType: 'Personal',
113
+ nameIdentifiers: name_identifiers(cocina_contributor).presence,
114
+ affiliation: affiliations(cocina_contributor).presence
115
+ }.tap do |name_hash|
116
+ # NOTE: This is needed for ETDs, for which we do not receive structured
117
+ # contributor names from Axess for ETD readers
118
+ if cocina_contributor.name.first.structuredValue.empty?
119
+ name_hash[:name] = cocina_contributor.name.first.value
120
+ elsif (name = cocina_contributor.name.first.structuredValue.find { |part| part.type == 'name' }).present?
121
+ name_hash[:name] = name.value
122
+ else
123
+ forename = cocina_contributor.name.first.structuredValue.find { |part| part.type == 'forename' }
124
+ surname = cocina_contributor.name.first.structuredValue.find { |part| part.type == 'surname' }
125
+
126
+ name_hash[:name] = "#{surname.value}, #{forename.value}"
127
+ name_hash[:givenName] = forename.value
128
+ name_hash[:familyName] = surname.value
129
+ end
130
+ end
131
+ .compact
132
+ end
133
+
134
+ def organizational_name(cocina_contributor)
135
+ name = cocina_contributor.name.first.structuredValue.first || cocina_contributor.name.first
136
+ {
137
+ name: name.value,
138
+ nameType: 'Organizational',
139
+ nameIdentifiers: name_identifiers(name).presence
140
+ }.compact
141
+ end
142
+
143
+ def name_identifiers(cocina_contributor)
144
+ Array(cocina_contributor.identifier).map do |identifier|
145
+ {
146
+ nameIdentifier: identifier.value || identifier.uri,
147
+ nameIdentifierScheme: identifier.type,
148
+ schemeURI: identifier.source.uri
149
+ }.compact
150
+ end
151
+ end
152
+
153
+ def affiliations(cocina_contributor) # rubocop:disable Metrics/MethodLength
154
+ Array(cocina_contributor.affiliation).map do |affiliation|
155
+ institution = affiliation.structuredValue.find { |descriptive_value| descriptive_value.identifier.present? }
156
+ institution ||= affiliation # if no structured value with identifier, use the affiliation itself
157
+ identifier = institution.identifier.find { |id| id.type == 'ROR' }
158
+ next unless identifier&.uri
159
+
160
+ {
161
+ affiliationIdentifier: identifier.uri,
162
+ affiliationIdentifierScheme: 'ROR',
163
+ name: institution.value,
164
+ schemeUri: 'https://ror.org/'
165
+ }.compact
166
+ end
167
+ end
168
+
169
+ def contributor_type(cocina_contributor)
170
+ if person?(cocina_contributor)
171
+ return DATACITE_PERSON_CONTRIBUTOR_TYPES.fetch(marc_relator(cocina_contributor),
172
+ 'Other')
173
+ end
174
+
175
+ DATACITE_ORGANIZATION_CONTRIBUTOR_TYPES.fetch(marc_relator(cocina_contributor), 'Other')
176
+ end
177
+
178
+ # NOTE: This is how ETDs map to Cocina by way of MARC21 to MODS, where the
179
+ # 700$e and 700$4 subfields cannot be interpreted as pertaining to
180
+ # the same role, so the Cocina winds up expressing this as two
181
+ # roles, e.g.:
182
+ #
183
+ # role: [
184
+ # {
185
+ # value: "degree committee member",
186
+ # },
187
+ # {
188
+ # code: "ths",
189
+ # source: {
190
+ # code: "marcrelator",
191
+ # },
192
+ # }
193
+ # ]
194
+ def degree_committee_member?(cocina_contributor)
195
+ cocina_contributor.role.any? { |contrib_role| contrib_role.value == 'degree committee member' } &&
196
+ cocina_contributor.role.any? do |contrib_role|
197
+ contrib_role.code == 'ths' && contrib_role.source.code == 'marcrelator'
198
+ end
199
+ end
200
+
201
+ def marc_relator(cocina_contributor)
202
+ Array(cocina_contributor.role).find do |role|
203
+ role&.source&.code == 'marcrelator'
204
+ end&.value
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
@@ -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