briard 2.4.2 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codeql-analysis.yml +72 -0
  3. data/.github/workflows/rubocop.yml +50 -0
  4. data/.rubocop.yml +144 -620
  5. data/.rubocop_todo.yml +76 -0
  6. data/CHANGELOG.md +18 -0
  7. data/Gemfile +2 -0
  8. data/Gemfile.lock +40 -6
  9. data/Rakefile +1 -1
  10. data/{bolognese.gemspec → briard.gemspec} +46 -39
  11. data/lib/briard/array.rb +2 -2
  12. data/lib/briard/author_utils.rb +79 -71
  13. data/lib/briard/cli.rb +12 -13
  14. data/lib/briard/crossref_utils.rb +73 -61
  15. data/lib/briard/datacite_utils.rb +132 -106
  16. data/lib/briard/doi_utils.rb +10 -10
  17. data/lib/briard/metadata.rb +96 -106
  18. data/lib/briard/metadata_utils.rb +87 -78
  19. data/lib/briard/readers/bibtex_reader.rb +65 -65
  20. data/lib/briard/readers/cff_reader.rb +88 -70
  21. data/lib/briard/readers/citeproc_reader.rb +90 -84
  22. data/lib/briard/readers/codemeta_reader.rb +68 -50
  23. data/lib/briard/readers/crosscite_reader.rb +2 -2
  24. data/lib/briard/readers/crossref_reader.rb +249 -210
  25. data/lib/briard/readers/datacite_json_reader.rb +3 -3
  26. data/lib/briard/readers/datacite_reader.rb +225 -189
  27. data/lib/briard/readers/npm_reader.rb +49 -42
  28. data/lib/briard/readers/ris_reader.rb +82 -80
  29. data/lib/briard/readers/schema_org_reader.rb +182 -159
  30. data/lib/briard/string.rb +1 -1
  31. data/lib/briard/utils.rb +4 -4
  32. data/lib/briard/version.rb +3 -1
  33. data/lib/briard/whitelist_scrubber.rb +11 -4
  34. data/lib/briard/writers/bibtex_writer.rb +14 -8
  35. data/lib/briard/writers/cff_writer.rb +33 -26
  36. data/lib/briard/writers/codemeta_writer.rb +19 -15
  37. data/lib/briard/writers/csv_writer.rb +6 -4
  38. data/lib/briard/writers/datacite_json_writer.rb +8 -2
  39. data/lib/briard/writers/jats_writer.rb +33 -28
  40. data/lib/briard/writers/rdf_xml_writer.rb +1 -1
  41. data/lib/briard/writers/ris_writer.rb +30 -18
  42. data/lib/briard/writers/turtle_writer.rb +1 -1
  43. data/lib/briard.rb +6 -6
  44. data/rubocop.sarif +0 -0
  45. data/spec/array_spec.rb +5 -5
  46. data/spec/author_utils_spec.rb +151 -132
  47. data/spec/datacite_utils_spec.rb +135 -83
  48. data/spec/doi_utils_spec.rb +168 -164
  49. data/spec/find_from_format_spec.rb +69 -69
  50. data/spec/fixtures/vcr_cassettes/Briard_Metadata/sanitize/onlies_keep_specific_tags.yml +65 -0
  51. data/spec/fixtures/vcr_cassettes/Briard_Metadata/sanitize/removes_a_tags.yml +65 -0
  52. data/spec/metadata_spec.rb +91 -90
  53. data/spec/readers/bibtex_reader_spec.rb +43 -38
  54. data/spec/readers/cff_reader_spec.rb +165 -153
  55. data/spec/readers/citeproc_reader_spec.rb +45 -40
  56. data/spec/readers/codemeta_reader_spec.rb +128 -115
  57. data/spec/readers/crosscite_reader_spec.rb +34 -24
  58. data/spec/readers/crossref_reader_spec.rb +1098 -939
  59. data/spec/readers/datacite_json_reader_spec.rb +53 -40
  60. data/spec/readers/datacite_reader_spec.rb +1541 -1337
  61. data/spec/readers/npm_reader_spec.rb +48 -43
  62. data/spec/readers/ris_reader_spec.rb +53 -47
  63. data/spec/readers/schema_org_reader_spec.rb +329 -267
  64. data/spec/spec_helper.rb +6 -5
  65. data/spec/utils_spec.rb +371 -347
  66. data/spec/writers/bibtex_writer_spec.rb +143 -143
  67. data/spec/writers/cff_writer_spec.rb +96 -90
  68. data/spec/writers/citation_writer_spec.rb +34 -33
  69. data/spec/writers/citeproc_writer_spec.rb +226 -224
  70. data/spec/writers/codemeta_writer_spec.rb +18 -16
  71. data/spec/writers/crosscite_writer_spec.rb +91 -73
  72. data/spec/writers/crossref_writer_spec.rb +99 -91
  73. data/spec/writers/csv_writer_spec.rb +70 -70
  74. data/spec/writers/datacite_json_writer_spec.rb +78 -68
  75. data/spec/writers/datacite_writer_spec.rb +417 -322
  76. data/spec/writers/jats_writer_spec.rb +177 -161
  77. data/spec/writers/rdf_xml_writer_spec.rb +68 -63
  78. data/spec/writers/ris_writer_spec.rb +162 -162
  79. data/spec/writers/turtle_writer_spec.rb +47 -47
  80. metadata +242 -166
  81. data/.github/workflows/release.yml +0 -47
@@ -3,97 +3,97 @@
3
3
  module Briard
4
4
  module Readers
5
5
  module BibtexReader
6
- BIB_TO_CP_TRANSLATIONS = {
7
- "article" => "article-journal",
8
- "phdthesis" => "thesis"
9
- }
6
+ BIB_TO_CP_TRANSLATIONS = { 'article' => 'article-journal', 'phdthesis' => 'thesis' }.freeze
10
7
 
11
8
  BIB_TO_RIS_TRANSLATIONS = {
12
- "article" => "JOUR",
13
- "book" => "BOOK",
14
- "inbook" => "CHAP",
15
- "inproceedings" => "CPAPER",
16
- "manual" => nil,
17
- "misc" => "GEN",
18
- "phdthesis" => "THES",
19
- "proceedings" => "CONF",
20
- "techreport" => "RPRT",
21
- "unpublished" => "UNPD"
22
- }
9
+ 'article' => 'JOUR',
10
+ 'book' => 'BOOK',
11
+ 'inbook' => 'CHAP',
12
+ 'inproceedings' => 'CPAPER',
13
+ 'manual' => nil,
14
+ 'misc' => 'GEN',
15
+ 'phdthesis' => 'THES',
16
+ 'proceedings' => 'CONF',
17
+ 'techreport' => 'RPRT',
18
+ 'unpublished' => 'UNPD'
19
+ }.freeze
23
20
 
24
- BIB_TO_SO_TRANSLATIONS = {
25
- "article" => "ScholarlyArticle",
26
- "phdthesis" => "Thesis"
27
- }
21
+ BIB_TO_SO_TRANSLATIONS = { 'article' => 'ScholarlyArticle', 'phdthesis' => 'Thesis' }.freeze
28
22
 
29
23
  def read_bibtex(string: nil, **options)
30
- read_options = ActiveSupport::HashWithIndifferentAccess.new(options.except(:doi, :id, :url, :sandbox, :validate, :ra))
24
+ read_options = ActiveSupport::HashWithIndifferentAccess.new(options.except(:doi, :id, :url,
25
+ :sandbox, :validate, :ra))
31
26
 
32
27
  meta = string.present? ? BibTeX.parse(string).first : OpenStruct.new
33
28
 
34
29
  bibtex_type = meta.try(:type).to_s
35
- schema_org = BIB_TO_SO_TRANSLATIONS[bibtex_type] || "ScholarlyArticle"
30
+ schema_org = BIB_TO_SO_TRANSLATIONS[bibtex_type] || 'ScholarlyArticle'
36
31
  types = {
37
- "resourceTypeGeneral" => Metadata::BIB_TO_DC_TRANSLATIONS[bibtex_type],
38
- "resourceType" => Briard::Utils::BIB_TO_CR_TRANSLATIONS[meta.try(:type).to_s] || meta.try(:type).to_s,
39
- "schemaOrg" => schema_org,
40
- "bibtex" => bibtex_type,
41
- "citeproc" => BIB_TO_CP_TRANSLATIONS[meta.try(:type).to_s] || "misc",
42
- "ris" => BIB_TO_RIS_TRANSLATIONS[meta.try(:type).to_s] || "GEN"
32
+ 'resourceTypeGeneral' => Metadata::BIB_TO_DC_TRANSLATIONS[bibtex_type],
33
+ 'resourceType' => Briard::Utils::BIB_TO_CR_TRANSLATIONS[meta.try(:type).to_s] || meta.try(:type).to_s,
34
+ 'schemaOrg' => schema_org,
35
+ 'bibtex' => bibtex_type,
36
+ 'citeproc' => BIB_TO_CP_TRANSLATIONS[meta.try(:type).to_s] || 'misc',
37
+ 'ris' => BIB_TO_RIS_TRANSLATIONS[meta.try(:type).to_s] || 'GEN'
43
38
  }.compact
44
39
  doi = meta.try(:doi).to_s.presence || options[:doi]
45
40
 
46
41
  creators = Array(meta.try(:author)).map do |a|
47
- { "nameType" => "Personal",
48
- "name" => [a.last, a.first].join(", "),
49
- "givenName" => a.first,
50
- "familyName" => a.last }.compact
42
+ { 'nameType' => 'Personal',
43
+ 'name' => [a.last, a.first].join(', '),
44
+ 'givenName' => a.first,
45
+ 'familyName' => a.last }.compact
51
46
  end
52
47
 
53
48
  related_identifiers = if meta.try(:journal).present? && meta.try(:issn).to_s.presence
54
- [{ "type" => "Periodical",
55
- "relationType" => "IsPartOf",
56
- "relatedIdentifierType" => "ISSN",
57
- "title" => meta.journal.to_s,
58
- "relatedIdentifier" => meta.try(:issn).to_s.presence }.compact]
49
+ [{ 'type' => 'Periodical',
50
+ 'relationType' => 'IsPartOf',
51
+ 'relatedIdentifierType' => 'ISSN',
52
+ 'title' => meta.journal.to_s,
53
+ 'relatedIdentifier' => meta.try(:issn).to_s.presence }.compact]
59
54
  end
60
55
 
61
56
  container = if meta.try(:journal).present?
62
- first_page = meta.try(:pages).present? ? meta.try(:pages).split("-").map(&:strip)[0] : nil
63
- last_page = meta.try(:pages).present? ? meta.try(:pages).split("-").map(&:strip)[1] : nil
57
+ first_page = meta.try(:pages).present? ? meta.try(:pages).split('-').map(&:strip)[0] : nil
58
+ last_page = meta.try(:pages).present? ? meta.try(:pages).split('-').map(&:strip)[1] : nil
64
59
 
65
- { "type" => "Journal",
66
- "title" => meta.journal.to_s,
67
- "identifier" => meta.try(:issn).to_s.presence,
68
- "identifierType" => meta.try(:issn).present? ? "ISSN" : nil,
69
- "volume" => meta.try(:volume).to_s.presence,
70
- "firstPage" => first_page,
71
- "lastPage" => last_page }.compact
60
+ { 'type' => 'Journal',
61
+ 'title' => meta.journal.to_s,
62
+ 'identifier' => meta.try(:issn).to_s.presence,
63
+ 'identifierType' => meta.try(:issn).present? ? 'ISSN' : nil,
64
+ 'volume' => meta.try(:volume).to_s.presence,
65
+ 'firstPage' => first_page,
66
+ 'lastPage' => last_page }.compact
72
67
  end
73
68
 
74
- state = meta.try(:doi).to_s.present? || read_options.present? ? "findable" : "not_found"
69
+ state = meta.try(:doi).to_s.present? || read_options.present? ? 'findable' : 'not_found'
75
70
  dates = if meta.try(:date).present? && Date.edtf(meta.date.to_s).present?
76
- [{ "date" => meta.date.to_s,
77
- "dateType" => "Issued" }]
71
+ [{ 'date' => meta.date.to_s,
72
+ 'dateType' => 'Issued' }]
78
73
  end
79
- publication_year = meta.try(:date).present? ? meta.date.to_s[0..3] : nil
80
- rights_list = meta.try(:copyright).present? ? [hsh_to_spdx("rightsURI" => meta[:copyright])] : []
74
+ publication_year = meta.try(:date).present? ? meta.date.to_s[0..3] : nil
75
+ rights_list = meta.try(:copyright).present? ? [hsh_to_spdx('rightsURI' => meta[:copyright])] : []
81
76
 
82
- { "id" => normalize_doi(doi),
83
- "types" => types,
84
- "doi" => doi,
85
- "url" => meta.try(:url).to_s.presence,
86
- "titles" => meta.try(:title).present? ? [{ "title" => meta.try(:title).to_s }] : [],
87
- "creators" => creators,
88
- "container" => container,
89
- "publisher" => meta.try(:publisher).to_s.presence,
90
- "related_identifiers" => related_identifiers,
91
- "dates" => dates,
92
- "publication_year" => publication_year,
93
- "descriptions" => meta.try(:abstract).present? ? [{ "description" => meta.try(:abstract) && sanitize(meta.abstract.to_s).presence, "descriptionType" => "Abstract" }] : [],
94
- "rights_list" => rights_list,
95
- "state" => state
96
- }.merge(read_options)
77
+ { 'id' => normalize_doi(doi),
78
+ 'types' => types,
79
+ 'doi' => doi,
80
+ 'url' => meta.try(:url).to_s.presence,
81
+ 'titles' => meta.try(:title).present? ? [{ 'title' => meta.try(:title).to_s }] : [],
82
+ 'creators' => creators,
83
+ 'container' => container,
84
+ 'publisher' => meta.try(:publisher).to_s.presence,
85
+ 'related_identifiers' => related_identifiers,
86
+ 'dates' => dates,
87
+ 'publication_year' => publication_year,
88
+ 'descriptions' => if meta.try(:abstract).present?
89
+ [{
90
+ 'description' => meta.try(:abstract) && sanitize(meta.abstract.to_s).presence, 'descriptionType' => 'Abstract'
91
+ }]
92
+ else
93
+ []
94
+ end,
95
+ 'rights_list' => rights_list,
96
+ 'state' => state }.merge(read_options)
97
97
  end
98
98
  end
99
99
  end
@@ -3,119 +3,137 @@
3
3
  module Briard
4
4
  module Readers
5
5
  module CffReader
6
- def get_cff(id: nil, **options)
7
- return { "string" => nil, "state" => "not_found" } unless id.present?
6
+ def get_cff(id: nil, **_options)
7
+ return { 'string' => nil, 'state' => 'not_found' } unless id.present?
8
+
8
9
  id = normalize_id(id)
9
- response = Maremma.get(github_as_cff_url(id), accept: "json", raw: true)
10
- data = response.body.fetch("data", nil)
10
+ response = Maremma.get(github_as_cff_url(id), accept: 'json', raw: true)
11
+ data = response.body.fetch('data', nil)
11
12
  # Dates are parsed to date object, need to convert to iso8601 later
12
13
  string = Psych.safe_load(data, permitted_classes: [Date])
13
- { "string" => string }
14
+ { 'string' => string }
14
15
  end
15
16
 
16
17
  def read_cff(string: nil, **options)
17
- read_options = ActiveSupport::HashWithIndifferentAccess.new(options.except(:doi, :id, :url, :sandbox, :validate, :ra))
18
+ read_options = ActiveSupport::HashWithIndifferentAccess.new(options.except(:doi, :id, :url,
19
+ :sandbox, :validate, :ra))
18
20
  meta = string.is_a?(String) ? Psych.safe_load(string, permitted_classes: [Date]) : string
19
21
 
20
- identifiers = Array.wrap(meta.fetch("identifiers", nil)).map do |r|
22
+ identifiers = Array.wrap(meta.fetch('identifiers', nil)).map do |r|
21
23
  r = normalize_id(r) if r.is_a?(String)
22
- if r.is_a?(String) && !r.start_with?("https://doi.org")
23
- { "identifierType" => "URL", "identifier" => r }
24
+ if r.is_a?(String) && URI(r).host != 'doi.org'
25
+ { 'identifierType' => 'URL', 'identifier' => r }
24
26
  elsif r.is_a?(Hash)
25
- { "identifierType" => get_identifier_type(r["propertyID"]), "identifier" => r["value"] }
27
+ { 'identifierType' => get_identifier_type(r['propertyID']), 'identifier' => r['value'] }
26
28
  end
27
29
  end.compact.uniq
28
30
 
29
- id = normalize_id(options[:doi] || meta.fetch("doi", nil) || Array.wrap(meta.fetch("identifiers", nil)).find { |i| i["type"] == "doi"}.fetch("value", nil))
30
- url = normalize_id(meta.fetch("repository-code", nil))
31
- creators = cff_creators(Array.wrap(meta.fetch("authors", nil)))
31
+ id = normalize_id(options[:doi] || meta.fetch('doi',
32
+ nil) || Array.wrap(meta.fetch('identifiers', nil)).find do |i|
33
+ i['type'] == 'doi'
34
+ end.fetch('value', nil))
35
+ url = normalize_id(meta.fetch('repository-code', nil))
36
+ creators = cff_creators(Array.wrap(meta.fetch('authors', nil)))
32
37
 
33
38
  dates = []
34
- dates << { "date" => meta.fetch("date-released", nil).iso8601, "dateType" => "Issued" } if meta.fetch("date-released", nil).present?
35
- publication_year = meta.fetch("date-released").iso8601[0..3] if meta.fetch("date-released", nil).present?
36
- publisher = url.to_s.starts_with?("https://github.com") ? "GitHub" : nil
37
- state = meta.present? || read_options.present? ? "findable" : "not_found"
39
+ if meta.fetch('date-released', nil).present?
40
+ dates << { 'date' => meta.fetch('date-released', nil).iso8601, 'dateType' => 'Issued' }
41
+ end
42
+ publication_year = meta.fetch('date-released').iso8601[0..3] if meta.fetch('date-released',
43
+ nil).present?
44
+ publisher = url.to_s.starts_with?('https://github.com') ? 'GitHub' : nil
45
+ state = meta.present? || read_options.present? ? 'findable' : 'not_found'
38
46
  types = {
39
- "resourceTypeGeneral" => "Software",
40
- "resourceType" => nil,
41
- "schemaOrg" => "SoftwareSourceCode",
42
- "citeproc" => "article-journal",
43
- "bibtex" => "misc",
44
- "ris" => "COMP"
47
+ 'resourceTypeGeneral' => 'Software',
48
+ 'resourceType' => nil,
49
+ 'schemaOrg' => 'SoftwareSourceCode',
50
+ 'citeproc' => 'article-journal',
51
+ 'bibtex' => 'misc',
52
+ 'ris' => 'COMP'
45
53
  }.compact
46
- subjects = Array.wrap(meta.fetch("keywords", nil)).reduce([]) do |sum, subject|
54
+ subjects = Array.wrap(meta.fetch('keywords', nil)).reduce([]) do |sum, subject|
47
55
  sum += name_to_fos(subject)
48
56
 
49
57
  sum
50
58
  end
51
59
 
52
- titles = meta.fetch("title", nil).present? ? [{ "title" => meta.fetch("title", nil) }] : []
53
- related_identifiers = Array.wrap(cff_references(meta.fetch("references", nil)))
54
- rights_list = meta.fetch("license", nil).present? ? [hsh_to_spdx("rightsIdentifier" => meta.fetch("license"))] : nil
60
+ titles = if meta.fetch('title', nil).present?
61
+ [{ 'title' => meta.fetch('title', nil) }]
62
+ else
63
+ []
64
+ end
65
+ related_identifiers = Array.wrap(cff_references(meta.fetch('references', nil)))
66
+ rights_list = if meta.fetch('license', nil).present?
67
+ [hsh_to_spdx('rightsIdentifier' => meta.fetch('license'))]
68
+ end
55
69
 
56
- { "id" => id,
57
- "types" => types,
58
- "identifiers" => identifiers,
59
- "doi" => doi_from_url(id),
60
- "url" => url,
61
- "titles" => titles,
62
- "creators" => creators,
63
- "publisher" => publisher,
64
- "related_identifiers" => related_identifiers,
65
- "dates" => dates,
66
- "publication_year" => publication_year,
67
- "descriptions" => meta.fetch("abstract", nil).present? ? [{ "description" => sanitize(meta.fetch("abstract")), "descriptionType" => "Abstract" }] : nil,
68
- "rights_list" => rights_list,
69
- "version_info" => meta.fetch("version", nil),
70
- "subjects" => subjects,
71
- "state" => state
72
- }.merge(read_options)
70
+ { 'id' => id,
71
+ 'types' => types,
72
+ 'identifiers' => identifiers,
73
+ 'doi' => doi_from_url(id),
74
+ 'url' => url,
75
+ 'titles' => titles,
76
+ 'creators' => creators,
77
+ 'publisher' => publisher,
78
+ 'related_identifiers' => related_identifiers,
79
+ 'dates' => dates,
80
+ 'publication_year' => publication_year,
81
+ 'descriptions' => if meta.fetch('abstract', nil).present?
82
+ [{ 'description' => sanitize(meta.fetch('abstract')),
83
+ 'descriptionType' => 'Abstract' }]
84
+ end,
85
+ 'rights_list' => rights_list,
86
+ 'version_info' => meta.fetch('version', nil),
87
+ 'subjects' => subjects,
88
+ 'state' => state }.merge(read_options)
73
89
  end
74
90
 
75
91
  def cff_creators(creators)
76
92
  Array.wrap(creators).map do |a|
77
- name_identifiers = normalize_orcid(parse_attributes(a["orcid"])).present? ? [{ "nameIdentifier" => normalize_orcid(parse_attributes(a["orcid"])), "nameIdentifierScheme" => "ORCID", "schemeUri"=>"https://orcid.org" }] : nil
78
- if a["given-names"].present? || a["family-names"].present? || name_identifiers.present?
79
- given_name = parse_attributes(a["given-names"])
80
- family_name = parse_attributes(a["family-names"])
81
- affiliation = Array.wrap(a["affiliation"]).map do |a|
93
+ name_identifiers = if normalize_orcid(parse_attributes(a['orcid'])).present?
94
+ [{
95
+ 'nameIdentifier' => normalize_orcid(parse_attributes(a['orcid'])), 'nameIdentifierScheme' => 'ORCID', 'schemeUri' => 'https://orcid.org'
96
+ }]
97
+ end
98
+ if a['given-names'].present? || a['family-names'].present? || name_identifiers.present?
99
+ given_name = parse_attributes(a['given-names'])
100
+ family_name = parse_attributes(a['family-names'])
101
+ affiliation = Array.wrap(a['affiliation']).map do |a|
82
102
  if a.is_a?(Hash)
83
103
  a
84
- elsif a.is_a?(Hash) && a.key?("__content__") && a["__content__"].strip.blank?
104
+ elsif a.is_a?(Hash) && a.key?('__content__') && a['__content__'].strip.blank?
85
105
  nil
86
- elsif a.is_a?(Hash) && a.key?("__content__")
87
- { "name" => a["__content__"] }
106
+ elsif a.is_a?(Hash) && a.key?('__content__')
107
+ { 'name' => a['__content__'] }
88
108
  elsif a.strip.blank?
89
109
  nil
90
110
  elsif a.is_a?(String)
91
- { "name" => a }
111
+ { 'name' => a }
92
112
  end
93
113
  end.compact
94
114
 
95
- { "nameType" => "Personal",
96
- "nameIdentifiers" => name_identifiers,
97
- "name" => [family_name, given_name].compact.join(", "),
98
- "givenName" => given_name,
99
- "familyName" => family_name,
100
- "affiliation" => affiliation.presence }.compact
115
+ { 'nameType' => 'Personal',
116
+ 'nameIdentifiers' => name_identifiers,
117
+ 'name' => [family_name, given_name].compact.join(', '),
118
+ 'givenName' => given_name,
119
+ 'familyName' => family_name,
120
+ 'affiliation' => affiliation.presence }.compact
101
121
  else
102
- { "nameType" => "Organizational",
103
- "name" => a["name"] || a["__content__"] }
122
+ { 'nameType' => 'Organizational',
123
+ 'name' => a['name'] || a['__content__'] }
104
124
  end
105
125
  end
106
126
  end
107
127
 
108
128
  def cff_references(references)
109
129
  Array.wrap(references).map do |r|
110
- identifier = Array.wrap(r["identifiers"]).find { |i| i["type"] == "doi" }
111
-
112
- if identifier.present?
113
- { "relatedIdentifier" => normalize_id(parse_attributes(identifier["value"])),
114
- "relationType" => "References",
115
- "relatedIdentifierType" => "DOI" }.compact
116
- else
117
- nil
118
- end
130
+ identifier = Array.wrap(r['identifiers']).find { |i| i['type'] == 'doi' }
131
+
132
+ next unless identifier.present?
133
+
134
+ { 'relatedIdentifier' => normalize_id(parse_attributes(identifier['value'])),
135
+ 'relationType' => 'References',
136
+ 'relatedIdentifierType' => 'DOI' }.compact
119
137
  end.compact.unwrap
120
138
  end
121
139
  end
@@ -4,115 +4,121 @@ module Briard
4
4
  module Readers
5
5
  module CiteprocReader
6
6
  CP_TO_SO_TRANSLATIONS = {
7
- "song" => "AudioObject",
8
- "post-weblog" => "BlogPosting",
9
- "dataset" => "Dataset",
10
- "graphic" => "ImageObject",
11
- "motion_picture" => "Movie",
12
- "article-journal" => "ScholarlyArticle",
13
- "broadcast" => "VideoObject",
14
- "webpage" => "WebPage"
15
- }
7
+ 'song' => 'AudioObject',
8
+ 'post-weblog' => 'BlogPosting',
9
+ 'dataset' => 'Dataset',
10
+ 'graphic' => 'ImageObject',
11
+ 'motion_picture' => 'Movie',
12
+ 'article-journal' => 'ScholarlyArticle',
13
+ 'broadcast' => 'VideoObject',
14
+ 'webpage' => 'WebPage'
15
+ }.freeze
16
16
 
17
17
  CP_TO_RIS_TRANSLATIONS = {
18
- "post-weblog" => "BLOG",
19
- "dataset" => "DATA",
20
- "graphic" => "FIGURE",
21
- "book" => "BOOK",
22
- "motion_picture" => "MPCT",
23
- "article-journal" => "JOUR",
24
- "broadcast" => "MPCT",
25
- "webpage" => "ELEC"
26
- }
18
+ 'post-weblog' => 'BLOG',
19
+ 'dataset' => 'DATA',
20
+ 'graphic' => 'FIGURE',
21
+ 'book' => 'BOOK',
22
+ 'motion_picture' => 'MPCT',
23
+ 'article-journal' => 'JOUR',
24
+ 'broadcast' => 'MPCT',
25
+ 'webpage' => 'ELEC'
26
+ }.freeze
27
27
 
28
28
  def read_citeproc(string: nil, **options)
29
29
  if string.present?
30
30
  errors = jsonlint(string)
31
- return { "errors" => errors } if errors.present?
31
+ return { 'errors' => errors } if errors.present?
32
32
  end
33
33
 
34
- read_options = ActiveSupport::HashWithIndifferentAccess.new(options.except(:doi, :id, :url, :sandbox, :validate, :ra))
34
+ read_options = ActiveSupport::HashWithIndifferentAccess.new(options.except(:doi, :id, :url,
35
+ :sandbox, :validate, :ra))
35
36
 
36
37
  meta = string.present? ? Maremma.from_json(string) : {}
37
38
 
38
- citeproc_type = meta.fetch("type", nil)
39
- schema_org = CP_TO_SO_TRANSLATIONS[citeproc_type] || "CreativeWork"
39
+ citeproc_type = meta.fetch('type', nil)
40
+ schema_org = CP_TO_SO_TRANSLATIONS[citeproc_type] || 'CreativeWork'
40
41
  types = {
41
- "resourceTypeGeneral" => Briard::Utils::CP_TO_DC_TRANSLATIONS[citeproc_type],
42
- "reourceType" => meta.fetch("additionalType", nil),
43
- "schemaOrg" => schema_org,
44
- "citeproc" => citeproc_type,
45
- "bibtex" => Briard::Utils::SO_TO_BIB_TRANSLATIONS[schema_org] || "misc",
46
- "ris" => CP_TO_RIS_TRANSLATIONS[schema_org] || "GEN"
42
+ 'resourceTypeGeneral' => Briard::Utils::CP_TO_DC_TRANSLATIONS[citeproc_type],
43
+ 'reourceType' => meta.fetch('additionalType', nil),
44
+ 'schemaOrg' => schema_org,
45
+ 'citeproc' => citeproc_type,
46
+ 'bibtex' => Briard::Utils::SO_TO_BIB_TRANSLATIONS[schema_org] || 'misc',
47
+ 'ris' => CP_TO_RIS_TRANSLATIONS[schema_org] || 'GEN'
47
48
  }.compact
48
49
 
49
- creators = if meta.fetch("author", nil).present?
50
- get_authors(from_citeproc(Array.wrap(meta.fetch("author", nil))))
51
- else
52
- [{ "nameType" => "Organizational", "name" => ":(unav)" }]
53
- end
54
- contributors = get_authors(from_citeproc(Array.wrap(meta.fetch("editor", nil))))
55
- dates = if date = get_date_from_date_parts(meta.fetch("issued", nil))
56
- if Date.edtf(date).present?
57
- [{ "date" => date,
58
- "dateType" => "Issued" }]
59
- end
50
+ creators = if meta.fetch('author', nil).present?
51
+ get_authors(from_citeproc(Array.wrap(meta.fetch('author', nil))))
52
+ else
53
+ [{ 'nameType' => 'Organizational', 'name' => ':(unav)' }]
54
+ end
55
+ contributors = get_authors(from_citeproc(Array.wrap(meta.fetch('editor', nil))))
56
+ dates = if (date = get_date_from_date_parts(meta.fetch('issued',
57
+ nil))) && Date.edtf(date).present?
58
+ [{ 'date' => date,
59
+ 'dateType' => 'Issued' }]
60
60
  end
61
- publication_year = get_date_from_date_parts(meta.fetch("issued", nil)).to_s[0..3]
62
- rights_list = if meta.fetch("copyright", nil)
63
- [hsh_to_spdx("rightsURI" => meta.fetch("copyright"))]
61
+ publication_year = get_date_from_date_parts(meta.fetch('issued', nil)).to_s[0..3]
62
+ rights_list = if meta.fetch('copyright', nil)
63
+ [hsh_to_spdx('rightsURI' => meta.fetch('copyright'))]
64
64
  end
65
- related_identifiers = if meta.fetch("container-title", nil).present? && meta.fetch("ISSN", nil).present?
66
- [{ "type" => "Periodical",
67
- "relationType" => "IsPartOf",
68
- "relatedIdentifierType" => "ISSN",
69
- "title" => meta.fetch("container-title", nil),
70
- "relatedIdentifier" => meta.fetch("ISSN", nil) }.compact]
65
+ related_identifiers = if meta.fetch('container-title',
66
+ nil).present? && meta.fetch('ISSN', nil).present?
67
+ [{ 'type' => 'Periodical',
68
+ 'relationType' => 'IsPartOf',
69
+ 'relatedIdentifierType' => 'ISSN',
70
+ 'title' => meta.fetch('container-title', nil),
71
+ 'relatedIdentifier' => meta.fetch('ISSN', nil) }.compact]
71
72
  end
72
- container = if meta.fetch("container-title", nil).present?
73
- first_page = meta.fetch("page", nil).present? ? meta.fetch("page").split("-").map(&:strip)[0] : nil
74
- last_page = meta.fetch("page", nil).present? ? meta.fetch("page").split("-").map(&:strip)[1] : nil
73
+ container = if meta.fetch('container-title', nil).present?
74
+ first_page = if meta.fetch('page', nil).present?
75
+ meta.fetch('page').split('-').map(&:strip)[0]
76
+ end
77
+ last_page = if meta.fetch('page', nil).present?
78
+ meta.fetch('page').split('-').map(&:strip)[1]
79
+ end
75
80
 
76
- { "type" => "Periodical",
77
- "title" => meta.fetch("container-title", nil),
78
- "identifier" => meta.fetch("ISSN", nil),
79
- "identifierType" => meta.fetch("ISSN", nil).present? ? "ISSN" : nil,
80
- "volume" => meta.fetch("volume", nil),
81
- "issue" => meta.fetch("issue", nil),
82
- "firstPage" => first_page,
83
- "lastPage" => last_page
84
- }.compact
85
- else
86
- nil
87
- end
81
+ { 'type' => 'Periodical',
82
+ 'title' => meta.fetch('container-title', nil),
83
+ 'identifier' => meta.fetch('ISSN', nil),
84
+ 'identifierType' => meta.fetch('ISSN', nil).present? ? 'ISSN' : nil,
85
+ 'volume' => meta.fetch('volume', nil),
86
+ 'issue' => meta.fetch('issue', nil),
87
+ 'firstPage' => first_page,
88
+ 'lastPage' => last_page }.compact
89
+ end
88
90
 
89
- id = normalize_id(meta.fetch("id", nil) || meta.fetch("DOI", nil))
91
+ id = normalize_id(meta.fetch('id', nil) || meta.fetch('DOI', nil))
90
92
 
91
- state = id.present? || read_options.present? ? "findable" : "not_found"
92
- subjects = Array.wrap(meta.fetch("categories", nil)).reduce([]) do |sum, subject|
93
+ state = id.present? || read_options.present? ? 'findable' : 'not_found'
94
+ subjects = Array.wrap(meta.fetch('categories', nil)).reduce([]) do |sum, subject|
93
95
  sum += name_to_fos(subject)
94
96
 
95
97
  sum
96
98
  end
97
99
 
98
- { "id" => id,
99
- "types" => types,
100
- "doi" => doi_from_url(id),
101
- "url" => normalize_id(meta.fetch("URL", nil)),
102
- "titles" => [{ "title" => meta.fetch("title", nil) }],
103
- "creators" => creators,
104
- "contributors" => contributors,
105
- "container" => container,
106
- "publisher" => meta.fetch("publisher", nil),
107
- "related_identifiers" => related_identifiers,
108
- "dates" => dates,
109
- "publication_year" => publication_year,
110
- "descriptions" => meta.fetch("abstract", nil).present? ? [{ "description" => sanitize(meta.fetch("abstract")), "descriptionType" => "Abstract" }] : [],
111
- "rights_list" => rights_list,
112
- "version_info" => meta.fetch("version", nil),
113
- "subjects" => subjects,
114
- "state" => state
115
- }.merge(read_options)
100
+ { 'id' => id,
101
+ 'types' => types,
102
+ 'doi' => doi_from_url(id),
103
+ 'url' => normalize_id(meta.fetch('URL', nil)),
104
+ 'titles' => [{ 'title' => meta.fetch('title', nil) }],
105
+ 'creators' => creators,
106
+ 'contributors' => contributors,
107
+ 'container' => container,
108
+ 'publisher' => meta.fetch('publisher', nil),
109
+ 'related_identifiers' => related_identifiers,
110
+ 'dates' => dates,
111
+ 'publication_year' => publication_year,
112
+ 'descriptions' => if meta.fetch('abstract', nil).present?
113
+ [{ 'description' => sanitize(meta.fetch('abstract')),
114
+ 'descriptionType' => 'Abstract' }]
115
+ else
116
+ []
117
+ end,
118
+ 'rights_list' => rights_list,
119
+ 'version_info' => meta.fetch('version', nil),
120
+ 'subjects' => subjects,
121
+ 'state' => state }.merge(read_options)
116
122
  end
117
123
  end
118
124
  end