Module: Briard::CrossrefUtils

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

Instance Method Summary collapse

Instance Method Details

#crossref_errors(xml: nil) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/briard/crossref_utils.rb', line 28

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

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

#crossref_root_attributesObject



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

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

#crossref_xmlObject

To configure the writing of Crossref metadata, use environmental variables CROSSREF_DEPOSITOR_NAME, CROSSREF_DEPOSITOR_EMAIL and CROSSREF_REGISTRANT, e.g. in a .env file



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/briard/crossref_utils.rb', line 8

def 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(ENV.fetch('CROSSREF_DEPOSITOR_NAME', nil))
          xml.email_address(ENV.fetch('CROSSREF_DEPOSITOR_EMAIL', nil))
        end
        xml.registrant(ENV.fetch('CROSSREF_REGISTRANT', nil))
      end
      xml.body do
        insert_crossref_work(xml)
      end
    end
  end.to_xml
end

#insert_citation_list(xml) ⇒ Object



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

def insert_citation_list(xml)
  # filter out references
  references = related_identifiers.find_all { |ri| ri['relationType'] == 'References' }
  return xml if references.blank?

  xml.citation_list do
    references.each do |ref|
      xml.citation do
        xml.doi(ref['relatedIdentifier'])
      end
    end
  end
end

#insert_crossref_abstract(xml) ⇒ Object



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

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



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

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

  rights_uri = Array.wrap(rights_list).map { |l| l['rightsUri'] }.first

  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



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

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

  xml.item_number(alternate_identifier['identifier'],
                  'item_number_type' => alternate_identifier['identifierType'])
end

#insert_crossref_creators(xml) ⇒ Object



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

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



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

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



229
230
231
232
233
# File 'lib/briard/crossref_utils.rb', line 229

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

  xml.language(language)
end

#insert_crossref_person(xml, person) ⇒ Object



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

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('nameIdentifiers', 0, 'nameIdentifierScheme') == 'ORCID'
    xml.ORCID(person.dig('nameIdentifiers', 0, 'nameIdentifier'))
  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



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

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_rights_list(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
306
# File 'lib/briard/crossref_utils.rb', line 282

def insert_crossref_rights_list(xml)
  return xml unless rights_list.present?

  xml.rightsList do
    Array.wrap(rights_list).each do |rights|
      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
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



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

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



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

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



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

def insert_crossref_work(xml)
  return xml if doi.blank?

  case types['resourceTypeGeneral']
  when 'JournalArticle'
    insert_journal(xml)
  when 'Preprint'
    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/briard/crossref_utils.rb', line 268

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

  xml.doi_data do
    xml.doi(doi)
    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



90
91
92
93
94
# File 'lib/briard/crossref_utils.rb', line 90

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/briard/crossref_utils.rb', line 260

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

  xml.institution do
    xml.institution_name(publisher)
  end
end

#insert_journal(xml) ⇒ Object



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

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



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

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



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

def insert_posted_date(xml)
  date_posted = get_date(dates, 'Issued')
  return xml if date_posted.blank?

  date = get_datetime_from_iso8601(date_posted)

  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