Module: Commonmeta::CrossrefUtils

Included in:
MetadataUtils
Defined in:
lib/commonmeta/crossref_utils.rb

Instance Method Summary collapse

Instance Method Details

#crossref_errors(xml: nil) ⇒ Object



25
26
27
28
29
30
31
32
33
34
# File 'lib/commonmeta/crossref_utils.rb', line 25

def crossref_errors(xml: nil)
  filepath = File.expand_path('../../resources/crossref/crossref5.3.1.xsd', __dir__)
  File.open(filepath, 'r') do |f|
    schema = Nokogiri::XML::Schema(f)
  end

  schema.validate(Nokogiri::XML(xml, nil, 'UTF-8')).map(&:to_s).unwrap
rescue Nokogiri::XML::SyntaxError => e
  e.message
end

#crossref_root_attributesObject



332
333
334
335
336
337
338
339
340
# File 'lib/commonmeta/crossref_utils.rb', line 332

def crossref_root_attributes
  { 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
    'xsi:schemaLocation': 'http://www.crossref.org/schema/5.3.1 https://www.crossref.org/schemas/crossref5.3.1.xsd',
    xmlns: 'http://www.crossref.org/schema/5.3.1',
    'xmlns:jats': 'http://www.ncbi.nlm.nih.gov/JATS1',
    'xmlns:fr': 'http://www.crossref.org/fundref.xsd',
    'xmlns:mml': 'http://www.w3.org/1998/Math/MathML',
    version: '5.3.1' }
end

#insert_citation_list(xml) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/commonmeta/crossref_utils.rb', line 131

def insert_citation_list(xml)
  xml.citation_list do
    Array.wrap(references).each do |ref|
      xml.citation('key' => ref['key']) do
        xml.journal_article(ref['journal_title'])
        xml.author(ref['author'])
        xml.volume(ref['volume'])
        xml.first_page(ref['first_page'])
        xml.cYear(ref['cYear'])
        xml.article_title(ref['article_title'])
        xml.doi(ref['doi']) if ref['doi'].present?
      end
    end
  end
end

#insert_crossref_abstract(xml) ⇒ Object



317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/commonmeta/crossref_utils.rb', line 317

def insert_crossref_abstract(xml)
  return xml if descriptions.blank?

  if descriptions.first.is_a?(Hash)
    d = descriptions.first
  else
    d = {}
    d['description'] = descriptions.first
  end

  xml.abstract('xmlns' => 'http://www.ncbi.nlm.nih.gov/JATS1') do
    xml.p(d['description'])
  end
end

#insert_crossref_access_indicators(xml) ⇒ Object



172
173
174
175
176
177
178
179
180
181
182
# File 'lib/commonmeta/crossref_utils.rb', line 172

def insert_crossref_access_indicators(xml)
  return xml if license.blank?

  rights_uri = license['url']

  xml.program('xmlns' => 'http://www.crossref.org/AccessIndicators.xsd',
              'name' => 'AccessIndicators') do
    xml.license_ref(rights_uri, 'applies_to' => 'vor')
    xml.license_ref(rights_uri, 'applies_to' => 'tdm')
  end
end

#insert_crossref_alternate_identifiers(xml) ⇒ Object

xml.resourceType(types || types,

'resourceTypeGeneral' => types["resourceTypeGeneral"] || Metadata::SO_TO_DC_TRANSLATIONS[types["schemaOrg"]] || "Other")

end



162
163
164
165
166
167
168
169
170
# File 'lib/commonmeta/crossref_utils.rb', line 162

def insert_crossref_alternate_identifiers(xml)
  alternate_identifier = Array.wrap(alternate_identifiers).reject do |r|
    %w[DOI, URL].include?(r['alternate_identifier_type'])
  end.first
  return xml if alternate_identifier.blank?

  xml.item_number(alternate_identifier['alternateIdentifier'],
                  'item_number_type' => alternate_identifier['alternateIdentifierType'])
end

#insert_crossref_creators(xml) ⇒ Object



95
96
97
98
99
100
101
102
103
104
# File 'lib/commonmeta/crossref_utils.rb', line 95

def insert_crossref_creators(xml)
  xml.contributors do
    Array.wrap(creators).each_with_index do |person, index|
      xml.person_name('contributor_role' => 'author',
                      'sequence' => index.zero? ? 'first' : 'additional') do
        insert_crossref_person(xml, person)
      end
    end
  end
end

#insert_crossref_issn(xml) ⇒ Object



307
308
309
310
311
312
313
314
315
# File 'lib/commonmeta/crossref_utils.rb', line 307

def insert_crossref_issn(xml)
  issn = if container.to_h.fetch('identifierType', nil) == 'ISSN'
           container.to_h.fetch('identifier', nil)
         end

  return xml if issn.blank?

  xml.issn(issn)
end

#insert_crossref_language(xml) ⇒ Object

xml.version(version_info) end



230
231
232
233
234
# File 'lib/commonmeta/crossref_utils.rb', line 230

def insert_crossref_language(xml)
  return xml unless language.present?

  xml.language(language)
end

#insert_crossref_license(xml) ⇒ Object



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/commonmeta/crossref_utils.rb', line 282

def insert_crossref_license(xml)
  return xml unless license.present?

  xml.license do
    rights = license
    if rights.is_a?(Hash)
      r = rights
    else
      r = {}
      r['rights'] = rights
      r['rightsUri'] = normalize_id(rights)
    end

    attributes = {
      'rightsURI' => r['rightsUri'],
      'rightsIdentifier' => r['rightsIdentifier'],
      'rightsIdentifierScheme' => r['rightsIdentifierScheme'],
      'schemeURI' => r['schemeUri'],
      'xml:lang' => r['lang']
    }.compact

    xml.rights(r['rights'], attributes)
  end
end

#insert_crossref_person(xml, person) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/commonmeta/crossref_utils.rb', line 106

def insert_crossref_person(xml, person)
  xml.given_name(person['givenName']) if person['givenName'].present?
  xml.surname(person['familyName']) if person['familyName'].present?
  if person.dig('id') && URI.parse(person.dig('id')).host == 'orcid.org'
    xml.ORCID(person.dig('id'))
  end
  Array.wrap(person['affiliation']).each do |affiliation|
    attributes = { 'affiliationIdentifier' => affiliation['affiliationIdentifier'],
                   'affiliationIdentifierScheme' => affiliation['affiliationIdentifierScheme'], 'schemeURI' => affiliation['schemeUri'] }.compact
    xml.affiliation(affiliation['name'], attributes)
  end
end

#insert_crossref_publication_date(xml) ⇒ Object



236
237
238
239
240
241
242
243
244
245
246
# File 'lib/commonmeta/crossref_utils.rb', line 236

def insert_crossref_publication_date(xml)
  return xml if date['registered'].blank?

  date_ = get_datetime_from_iso8601(date['registered'])

  xml.publication_date('media_type' => 'online') do
    xml.month(date_.month) if date_.month.present?
    xml.day(date_.day) if date_.day.present?
    xml.year(date_.year) if date_.year.present?
  end
end

#insert_crossref_subjects(xml) ⇒ Object

xml.fundingReferences do

  Array.wrap(funding_references).each do |funding_reference|
    xml.fundingReference do
      xml.funderName(funding_reference["funderName"])
      xml.funderIdentifier(funding_reference["funderIdentifier"], { "funderIdentifierType" => funding_reference["funderIdentifierType"] }.compact) if funding_reference["funderIdentifier"].present?
      xml.awardNumber(funding_reference["awardNumber"], { "awardURI" => funding_reference["awardUri"] }.compact) if funding_reference["awardNumber"].present? || funding_reference["awardUri"].present?
      xml.awardTitle(funding_reference["awardTitle"]) if funding_reference["awardTitle"].present?
    end
  end
end

end



210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/commonmeta/crossref_utils.rb', line 210

def insert_crossref_subjects(xml)
  return xml unless subjects.present?

  xml.subjects do
    subjects.each do |subject|
      if subject.is_a?(Hash)
        xml.subject(subject['subject'])
      else
        xml.subject(subject)
      end
    end
  end
end

#insert_crossref_titles(xml) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/commonmeta/crossref_utils.rb', line 119

def insert_crossref_titles(xml)
  xml.titles do
    Array.wrap(titles).each do |title|
      if title.is_a?(Hash)
        xml.title(title['title'])
      else
        xml.title(title)
      end
    end
  end
end

#insert_crossref_work(xml) ⇒ Object



36
37
38
39
40
41
42
43
44
45
# File 'lib/commonmeta/crossref_utils.rb', line 36

def insert_crossref_work(xml)
  return xml if doi_from_url(id).blank?

  case type
  when 'JournalArticle'
    insert_journal(xml)
  when 'Article'
    insert_posted_content(xml)
  end
end

#insert_doi_data(xml) ⇒ Object



268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/commonmeta/crossref_utils.rb', line 268

def insert_doi_data(xml)
  return xml if doi_from_url(id).blank? || url.blank?

  xml.doi_data do
    xml.doi(doi_from_url(id).downcase)
    xml.resource(url)
    xml.collection('property' => 'text-mining') do
      xml.item do
        xml.resource(url, 'mime_type' => 'text/html')
      end
    end
  end
end

#insert_group_title(xml) ⇒ Object



89
90
91
92
93
# File 'lib/commonmeta/crossref_utils.rb', line 89

def insert_group_title(xml)
  return xml if subjects.blank?

  xml.group_title(subjects.first['subject'].titleize)
end

#insert_institution(xml) ⇒ Object



260
261
262
263
264
265
266
# File 'lib/commonmeta/crossref_utils.rb', line 260

def insert_institution(xml)
  return xml if publisher.blank?

  xml.institution do
    xml.institution_name(publisher['name'])
  end
end

#insert_journal(xml) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/commonmeta/crossref_utils.rb', line 47

def insert_journal(xml)
  xml.journal do
    if language.present?
      xml.('language' => language[0..1]) do
        xml.full_title(container['title'])
      end
    else
      xml. do
        xml.full_title(container['title'])
      end
    end
    xml.journal_article('publication_type' => 'full_text') do
      insert_crossref_titles(xml)
      insert_crossref_creators(xml)
      insert_crossref_publication_date(xml)
      insert_crossref_abstract(xml)
      insert_crossref_issn(xml)
      insert_crossref_alternate_identifiers(xml)
      insert_crossref_access_indicators(xml)
      insert_doi_data(xml)
      insert_citation_list(xml)
    end
  end
end

#insert_posted_content(xml) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/commonmeta/crossref_utils.rb', line 72

def insert_posted_content(xml)
  posted_content = { 'type' => 'other', 'language' => language ? language[0..1] : nil }.compact

  xml.posted_content(posted_content) do
    insert_group_title(xml)
    insert_crossref_creators(xml)
    insert_crossref_titles(xml)
    insert_posted_date(xml)
    insert_institution(xml)
    insert_crossref_abstract(xml)
    insert_crossref_alternate_identifiers(xml)
    insert_crossref_access_indicators(xml)
    insert_doi_data(xml)
    insert_citation_list(xml)
  end
end

#insert_posted_date(xml) ⇒ Object



248
249
250
251
252
253
254
255
256
257
258
# File 'lib/commonmeta/crossref_utils.rb', line 248

def insert_posted_date(xml)
  return xml if date['published'].blank?

  date_ = get_datetime_from_iso8601(date['published'])

  xml.posted_date do
    xml.month(date_.month) if date_.month.present?
    xml.day(date_.day) if date_.day.present?
    xml.year(date_.year) if date_.year.present?
  end
end

#write_crossref_xmlObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/commonmeta/crossref_utils.rb', line 5

def write_crossref_xml
  @crossref_xml ||= Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
    xml.doi_batch(crossref_root_attributes) do
      xml.head do
        # we use a uuid as batch_id
        xml.doi_batch_id(SecureRandom.uuid)
        xml.timestamp(Time.now.utc.strftime('%Y%m%d%H%M%S'))
        xml.depositor do
          xml.depositor_name(depositor)
          xml.email_address(email)
        end
        xml.registrant(registrant)
      end
      xml.body do
        insert_crossref_work(xml)
      end
    end
  end.to_xml
end