bolognese 1.0.29 → 1.0.30

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/lib/bolognese/author_utils.rb +33 -56
  4. data/lib/bolognese/datacite_utils.rb +15 -7
  5. data/lib/bolognese/metadata.rb +13 -18
  6. data/lib/bolognese/metadata_utils.rb +41 -20
  7. data/lib/bolognese/readers/bibtex_reader.rb +21 -17
  8. data/lib/bolognese/readers/citeproc_reader.rb +28 -7
  9. data/lib/bolognese/readers/codemeta_reader.rb +21 -8
  10. data/lib/bolognese/readers/crossref_reader.rb +31 -23
  11. data/lib/bolognese/readers/datacite_json_reader.rb +1 -47
  12. data/lib/bolognese/readers/datacite_reader.rb +26 -16
  13. data/lib/bolognese/readers/ris_reader.rb +20 -13
  14. data/lib/bolognese/readers/schema_org_reader.rb +26 -22
  15. data/lib/bolognese/utils.rb +139 -39
  16. data/lib/bolognese/version.rb +1 -1
  17. data/lib/bolognese/writers/bibtex_writer.rb +7 -5
  18. data/lib/bolognese/writers/citation_writer.rb +1 -1
  19. data/lib/bolognese/writers/codemeta_writer.rb +2 -2
  20. data/lib/bolognese/writers/crosscite_writer.rb +1 -34
  21. data/lib/bolognese/writers/datacite_json_writer.rb +1 -29
  22. data/lib/bolognese/writers/jats_writer.rb +9 -9
  23. data/lib/bolognese/writers/ris_writer.rb +5 -5
  24. data/lib/bolognese/writers/schema_org_writer.rb +9 -9
  25. data/spec/author_utils_spec.rb +17 -47
  26. data/spec/cli_spec.rb +1 -1
  27. data/spec/fixtures/crosscite.json +10 -4
  28. data/spec/fixtures/datacite-example-polygon-v4.1.xml +163 -0
  29. data/spec/fixtures/datacite-seriesinformation.xml +41 -0
  30. data/spec/fixtures/datacite.json +12 -8
  31. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/get_series_information/only_title.yml +37 -0
  32. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/get_series_information/title_and_pages.yml +37 -0
  33. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/get_series_information/title_volume_and_pages.yml +37 -0
  34. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/get_series_information/title_volume_issue_and_pages.yml +37 -0
  35. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/is_personal_name_/has_orcid_id.yml +37 -0
  36. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/to_schema_org_identifiers/with_identifiers.yml +37 -0
  37. data/spec/readers/bibtex_reader_spec.rb +5 -5
  38. data/spec/readers/citeproc_reader_spec.rb +4 -4
  39. data/spec/readers/codemeta_reader_spec.rb +39 -18
  40. data/spec/readers/crosscite_reader_spec.rb +2 -2
  41. data/spec/readers/crossref_reader_spec.rb +26 -32
  42. data/spec/readers/datacite_json_reader_spec.rb +2 -2
  43. data/spec/readers/datacite_reader_spec.rb +156 -101
  44. data/spec/readers/ris_reader_spec.rb +7 -7
  45. data/spec/readers/schema_org_reader_spec.rb +34 -28
  46. data/spec/utils_spec.rb +37 -6
  47. data/spec/writers/bibtex_writer_spec.rb +1 -0
  48. data/spec/writers/codemeta_writer_spec.rb +1 -1
  49. data/spec/writers/crosscite_writer_spec.rb +13 -6
  50. data/spec/writers/datacite_json_writer_spec.rb +13 -5
  51. data/spec/writers/datacite_writer_spec.rb +18 -18
  52. data/spec/writers/schema_org_writer_spec.rb +40 -14
  53. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4687acb1f204f7cea2f87698c0dc2a2a1dcd65d0ce129287623ade20dc812cd9
4
- data.tar.gz: 2e0630eb9f1325afad5a18f3887924397f713627d7101db54611a0be0eff58f4
3
+ metadata.gz: 968c22fa1751729204364c0b2e5bf39b7718402122babccde0f6eaf0ccca71a6
4
+ data.tar.gz: fded31c2e41b95272b2bcb42ccd3a6e7760c82ed98dbceea022d2d7b90cd5029
5
5
  SHA512:
6
- metadata.gz: 20c58ca184e77626ead3101a5d7cda2e77812413a200435a4908140a1559db398375ab129fc31dc956aa9246f1e7b50ab30ebb19737e854b1e5d20592a98c34a
7
- data.tar.gz: 6613ff4527370e1683fb345e64cc41060c038f5ab732011ebfc568df4c25caf3eb1d6e797166e613bc41b61aaa859bb1c8ea0cb371ce0552ff887558a6388db5
6
+ metadata.gz: 7e67269661948b71dc7c398594835e800eab6261aed23abe970125d68c19dfcfd30476993ac923bd23923e1a5f8d6fb66a766fadf93cfd1c42745811f36ed8e7
7
+ data.tar.gz: 81fd6cd2910f372d232c329e8187a85d3e89ffa039dc769df56d104f1d6314b15cbb80d4d9b08dab900389c5f2600446016458d141cfec37d251f653a1de95b1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bolognese (1.0.29)
4
+ bolognese (1.0.30)
5
5
  activesupport (>= 4.2.5, < 6)
6
6
  benchmark_methods (~> 0.7)
7
7
  bibtex-ruby (~> 4.1)
@@ -120,7 +120,7 @@ GEM
120
120
  rack (2.0.6)
121
121
  rack-test (0.8.3)
122
122
  rack (>= 1.0, < 3)
123
- rake (12.3.1)
123
+ rake (12.3.2)
124
124
  rdf (3.0.7)
125
125
  hamster (~> 3.0)
126
126
  link_header (~> 0.0, >= 0.0.8)
@@ -13,36 +13,42 @@ module Bolognese
13
13
  }
14
14
 
15
15
  def get_one_author(author)
16
- if author.fetch("creatorName", nil).is_a?(Array)
17
- # malformed XML
18
- return nil
19
- elsif author.fetch("type", nil).present?
20
- type = author.fetch("type").titleize
21
- elsif author.fetch("creatorName", nil).is_a?(Hash)
22
- type = author.dig("creatorName", "nameType") == "Organizational" ? "Organization" : "Person"
23
- else
24
- type = nil
25
- end
16
+ # malformed XML
17
+ return nil if author.fetch("creatorName", nil).is_a?(Array)
26
18
 
27
- name_identifiers = get_name_identifiers(author)
28
- id = author.fetch("id", nil).presence || name_identifiers.first
29
- identifier = name_identifiers.length > 1 ? name_identifiers.unwrap : nil
30
19
  name = parse_attributes(author.fetch("creatorName", nil)) ||
31
- parse_attributes(author.fetch("contributorName", nil)) ||
32
- author.fetch("name", nil)
33
-
20
+ parse_attributes(author.fetch("contributorName", nil))
34
21
  given_name = parse_attributes(author.fetch("givenName", nil))
35
22
  family_name = parse_attributes(author.fetch("familyName", nil))
36
23
  name = cleanup_author(name)
37
- name = [family_name, given_name].join(", ") if name.blank? && family_name.present?
24
+ name = [family_name, given_name].join(", ") if family_name.present? && given_name.present?
38
25
  contributor_type = parse_attributes(author.fetch("contributorType", nil))
39
26
 
40
- author = { "type" => type || "Person",
41
- "id" => id,
27
+ name_type = parse_attributes(author.fetch("creatorName", nil), content: "nameType", first: true) || parse_attributes(author.fetch("contributorName", nil), content: "nameType", first: true)
28
+ name_type = family_name.present? ? "Personal" : nil if name_type.blank?
29
+
30
+ name_identifiers = Array.wrap(author.fetch("nameIdentifier", nil)).map do |ni|
31
+ if ni["nameIdentifierScheme"] == "ORCID"
32
+ {
33
+ "nameIdentifier" => normalize_orcid(ni["__content__"]),
34
+ "nameIdentifierScheme" => "ORCID" }.compact
35
+ elsif ni["schemeURI"].present?
36
+ {
37
+ "nameIdentifier" => ni["schemeURI"].to_s + ni["__content__"].to_s,
38
+ "nameIdentifierScheme" => ni["nameIdentifierScheme"] }.compact
39
+ else
40
+ {
41
+ "nameIdentifier" => ni["__content__"],
42
+ "nameIdentifierScheme" => ni["nameIdentifierScheme"] }.compact
43
+ end
44
+ end.presence
45
+
46
+ author = { "nameType" => name_type,
42
47
  "name" => name,
43
48
  "givenName" => given_name,
44
49
  "familyName" => family_name,
45
- "identifier" => identifier,
50
+ "nameIdentifiers" => name_identifiers,
51
+ "affiliation" => parse_attributes(author.fetch("affiliation", nil), first: true),
46
52
  "contributorType" => contributor_type }.compact
47
53
 
48
54
  return author if family_name.present?
@@ -54,21 +60,21 @@ module Bolognese
54
60
  if parsed_name.present?
55
61
  given_name = parsed_name.given
56
62
  family_name = parsed_name.family
57
- name = [given_name, family_name].join(" ")
63
+ name = [family_name, given_name].join(", ")
58
64
  else
59
65
  given_name = nil
60
66
  family_name = nil
61
67
  end
62
68
 
63
- { "type" => "Person",
64
- "id" => id,
69
+ { "nameType" => "Personal",
65
70
  "name" => name,
66
71
  "givenName" => given_name,
67
72
  "familyName" => family_name,
68
- "identifier" => identifier,
73
+ "nameIdentifiers" => name_identifiers,
74
+ "affiliation" => parse_attributes(author.fetch("affiliation", nil), first: true),
69
75
  "contributorType" => contributor_type }.compact
70
76
  else
71
- { "type" => type, "name" => name }.compact
77
+ { "nameType" => name_type, "name" => name }.compact
72
78
  end
73
79
  end
74
80
 
@@ -87,8 +93,8 @@ module Bolognese
87
93
  end
88
94
 
89
95
  def is_personal_name?(author)
90
- return false if author.fetch("type", "").downcase == "organization"
91
- return true if author.fetch("id", "").start_with?("https://orcid.org") ||
96
+ return false if author.fetch("nameType", nil) == "Organizational"
97
+ return true if Array.wrap(author.fetch("nameIdentifiers", nil)).find { |a| a["nameIdentifierScheme"] == "ORCID" }.present? ||
92
98
  author.fetch("familyName", "").present? ||
93
99
  (author.fetch("name", "").include?(",") &&
94
100
  author.fetch("name", "").exclude?(";")) ||
@@ -108,35 +114,6 @@ module Bolognese
108
114
  Array.wrap(authors).map { |author| get_one_author(author) }.compact
109
115
  end
110
116
 
111
- # parse nameIdentifier from DataCite
112
- def get_name_identifiers(author)
113
- name_identifiers = Array.wrap(author.fetch("nameIdentifier", nil)).reduce([]) do |sum, n|
114
- n = { "__content__" => n } if n.is_a?(String)
115
-
116
- scheme = n.fetch("nameIdentifierScheme", nil)
117
- scheme_uri = n.fetch("schemeURI", nil) || IDENTIFIER_SCHEME_URIS.fetch(scheme, "https://orcid.org")
118
- scheme_uri = "https://orcid.org/" if validate_orcid_scheme(scheme_uri)
119
- scheme_uri << '/' unless scheme_uri.present? && scheme_uri.end_with?('/')
120
-
121
- identifier = n.fetch("__content__", nil)
122
- if scheme_uri == "https://orcid.org/"
123
- identifier = validate_orcid(identifier)
124
- else
125
- identifier = identifier.gsub(" ", "-")
126
- end
127
-
128
- if identifier.present? && scheme_uri.present?
129
- sum << scheme_uri + identifier
130
- else
131
- sum
132
- end
133
- end
134
-
135
- # return array of name identifiers, ORCID ID is first element if multiple
136
- name_identifiers.select { |n| n.start_with?("https://orcid.org") } +
137
- name_identifiers.reject { |n| n.start_with?("https://orcid.org") }
138
- end
139
-
140
117
  def authors_as_string(authors)
141
118
  Array.wrap(authors).map do |a|
142
119
  if a["familyName"].present?
@@ -67,12 +67,14 @@ module Bolognese
67
67
 
68
68
  def insert_person(xml, person, type)
69
69
  person_name = person["familyName"].present? ? [person["familyName"], person["givenName"]].compact.join(", ") : person["name"]
70
- attributes = person["type"].present? ? { "nameType" => person["type"] + "al" } : {}
70
+ attributes = { "nameType" => person["nameType"] }.compact
71
71
 
72
72
  xml.send(type + "Name", person_name, attributes)
73
73
  xml.givenName(person["givenName"]) if person["givenName"].present?
74
74
  xml.familyName(person["familyName"]) if person["familyName"].present?
75
- xml.nameIdentifier(person["id"], 'schemeURI' => 'http://orcid.org/', 'nameIdentifierScheme' => 'ORCID') if person["id"].present?
75
+ Array.wrap(person["nameIdentifiers"]).each do |ni|
76
+ xml.nameIdentifier(ni["nameIdentifier"], 'nameIdentifierScheme' => ni["nameIdentifierScheme"])
77
+ end
76
78
  end
77
79
 
78
80
  def insert_titles(xml)
@@ -92,7 +94,7 @@ module Bolognese
92
94
  end
93
95
 
94
96
  def insert_publisher(xml)
95
- xml.publisher(publisher || periodical && periodical["title"])
97
+ xml.publisher(publisher || container && container["title"])
96
98
  end
97
99
 
98
100
  def insert_publication_year(xml)
@@ -107,11 +109,12 @@ module Bolognese
107
109
  end
108
110
 
109
111
  def insert_alternate_identifiers(xml)
112
+ alternate_identifiers = Array.wrap(identifiers).select { |r| r["identifierType"] != "DOI" }
110
113
  return xml unless alternate_identifiers.present?
111
114
 
112
115
  xml.alternateIdentifiers do
113
116
  Array.wrap(alternate_identifiers).each do |alternate_identifier|
114
- xml.alternateIdentifier(alternate_identifier["alternateIdentifier"], 'alternateIdentifierType' => alternate_identifier["alternateIdentifierType"])
117
+ xml.alternateIdentifier(alternate_identifier["identifier"], 'alternateIdentifierType' => alternate_identifier["identifierType"])
115
118
  end
116
119
  end
117
120
  end
@@ -207,11 +210,16 @@ module Bolognese
207
210
  end
208
211
 
209
212
  def insert_descriptions(xml)
210
- return xml unless descriptions.present? || periodical && periodical["title"].present?
213
+ return xml unless descriptions.present? || container && container["title"].present?
211
214
 
212
215
  xml.descriptions do
213
- if periodical && periodical["title"].present?
214
- xml.description(periodical["title"], 'descriptionType' => "SeriesInformation")
216
+ if container && container["title"].present?
217
+ title = [container["title"]]
218
+ volume = "#{container["volume"]}" if container["volume"].present?
219
+ volume += "(#{container["issue"]})" if container["issue"].present?
220
+ pages = [container["firstPage"], container["lastPage"]].compact.join("-") if container["firstPage"].present?
221
+ series_information = [title, volume, pages].compact.join(", ")
222
+ xml.description(series_information, 'descriptionType' => "SeriesInformation")
215
223
  end
216
224
 
217
225
  Array.wrap(descriptions).each do |description|
@@ -8,10 +8,10 @@ module Bolognese
8
8
 
9
9
  attr_accessor :string, :from, :sandbox, :meta, :regenerate, :issue
10
10
  attr_reader :doc, :page_start, :page_end
11
- attr_writer :id, :provider_id, :client_id, :doi, :identifier, :creators, :contributors, :titles, :publisher,
11
+ attr_writer :id, :provider_id, :client_id, :doi, :identifiers, :creators, :contributors, :titles, :publisher,
12
12
  :rights_list, :dates, :publication_year, :volume, :url, :version_info,
13
- :subjects, :contributor, :descriptions, :alternate_identifiers, :language, :sizes,
14
- :formats, :schema_version, :meta, :periodical, :agency,
13
+ :subjects, :contributor, :descriptions, :language, :sizes,
14
+ :formats, :schema_version, :meta, :container, :agency,
15
15
  :format, :funding_references, :state, :geo_locations,
16
16
  :types, :content_url, :related_identifiers, :style, :locale
17
17
 
@@ -49,7 +49,7 @@ module Bolognese
49
49
  "client_id" => options[:client_id],
50
50
  "content_url" => options[:content_url],
51
51
  "creators" => options[:creators],
52
- "contributors" => options[:creators],
52
+ "contributors" => options[:contributors],
53
53
  "titles" => options[:titles],
54
54
  "publisher" => options[:publisher],
55
55
  "publication_year" => options[:publication_year] }
@@ -83,8 +83,8 @@ module Bolognese
83
83
  :contributors,
84
84
  :titles,
85
85
  :types,
86
- :alternate_identifiers,
87
- :periodical,
86
+ :identifiers,
87
+ :container,
88
88
  :publisher,
89
89
  :funding_references,
90
90
  :dates,
@@ -101,8 +101,7 @@ module Bolognese
101
101
  ).compact
102
102
 
103
103
  # generate name for method to call dynamically
104
- @meta = @from.present? ? send("read_" + @from, { string: string, sandbox: options[:sandbox] }.merge(read_options)) : {}
105
- @identifier = normalize_doi(options[:doi] || input, options) || @meta.fetch("id", nil) || @meta.fetch("identifier", nil)
104
+ @meta = @from.present? ? send("read_" + @from, { string: string, sandbox: options[:sandbox], doi: options[:doi], id: id }.merge(read_options)) : {}
106
105
  end
107
106
 
108
107
  def id
@@ -110,7 +109,7 @@ module Bolognese
110
109
  end
111
110
 
112
111
  def doi
113
- @doi ||= @identifier.present? ? doi_from_url(@identifier) : meta.fetch("doi", nil)
112
+ @doi ||= meta.fetch("doi", nil)
114
113
  end
115
114
 
116
115
  def provider_id
@@ -122,7 +121,7 @@ module Bolognese
122
121
  end
123
122
 
124
123
  def exists?
125
- (@state || meta.fetch("state", "not_found")) != "not_found"
124
+ (@state || meta.fetch("state", nil)) != "not_found"
126
125
  end
127
126
 
128
127
  def valid?
@@ -182,8 +181,8 @@ module Bolognese
182
181
  @publication_year ||= meta.fetch("publication_year", nil)
183
182
  end
184
183
 
185
- def periodical
186
- @periodical ||= meta.fetch("periodical", nil)
184
+ def container
185
+ @container ||= meta.fetch("container", nil)
187
186
  end
188
187
 
189
188
  def geo_locations
@@ -198,8 +197,8 @@ module Bolognese
198
197
  @publisher ||= meta.fetch("publisher", nil)
199
198
  end
200
199
 
201
- def alternate_identifiers
202
- @alternate_identifiers ||= meta.fetch("alternate_identifiers", nil)
200
+ def identifiers
201
+ @identifiers ||= meta.fetch("identifiers", nil)
203
202
  end
204
203
 
205
204
  def content_url
@@ -214,10 +213,6 @@ module Bolognese
214
213
  @state ||= meta.fetch("state", nil)
215
214
  end
216
215
 
217
- def identifier
218
- @identifier ||= meta.fetch("id", nil)
219
- end
220
-
221
216
  def types
222
217
  @types ||= meta.fetch("types", nil)
223
218
  end
@@ -62,7 +62,6 @@ module Bolognese
62
62
  include Bolognese::Writers::TurtleWriter
63
63
 
64
64
  attr_reader :name_detector, :reverse
65
- attr_writer :first_page, :last_page
66
65
 
67
66
  # replace DOI in XML if provided in options
68
67
  def raw
@@ -79,21 +78,9 @@ module Bolognese
79
78
  (from == "datacite") && regenerate.blank? && raw.present?
80
79
  end
81
80
 
82
- def volume
83
- @volume ||= meta.fetch("volume", nil)
84
- end
85
-
86
- def first_page
87
- @first_page ||= meta.fetch("first_page", nil)
88
- end
89
-
90
- def last_page
91
- @last_page ||= meta.fetch("last_page", nil)
92
- end
93
-
94
81
  def container_title
95
- if periodical.present?
96
- periodical["title"]
82
+ if container.present?
83
+ container["title"]
97
84
  elsif types["citeproc"] == "article-journal"
98
85
  publisher
99
86
  else
@@ -124,9 +111,11 @@ module Bolognese
124
111
  end
125
112
 
126
113
  def citeproc_hsh
114
+ page = container.to_h["firstPage"].present? ? [container["firstPage"], container["lastPage"]].join("-") : nil
115
+
127
116
  {
128
117
  "type" => types["citeproc"],
129
- "id" => identifier,
118
+ "id" => id,
130
119
  "categories" => Array.wrap(subjects).map { |k| parse_attributes(k, content: "subject", first: true) }.presence,
131
120
  "language" => language,
132
121
  "author" => to_citeproc(creators),
@@ -136,16 +125,48 @@ module Bolognese
136
125
  "abstract" => parse_attributes(descriptions, content: "description", first: true),
137
126
  "container-title" => container_title,
138
127
  "DOI" => doi,
139
- "issue" => issue,
140
- "page" => [first_page, last_page].compact.join("-").presence,
128
+ "volume" => container.to_h["volume"],
129
+ "issue" => container.to_h["issue"],
130
+ "page" => page,
141
131
  "publisher" => publisher,
142
132
  "title" => parse_attributes(titles, content: "title", first: true),
143
133
  "URL" => url,
144
- "version" => version_info,
145
- "volume" => volume
134
+ "version" => version_info
146
135
  }.compact.symbolize_keys
147
136
  end
148
137
 
138
+ def crosscite_hsh
139
+ {
140
+ "id" => id,
141
+ "doi" => doi,
142
+ "url" => url,
143
+ "types" => types,
144
+ "creators" => creators,
145
+ "titles" => titles,
146
+ "publisher" => publisher,
147
+ "container" => container,
148
+ "subjects" => subjects,
149
+ "contributors" => contributors,
150
+ "dates" => dates,
151
+ "publication_year" => publication_year,
152
+ "language" => language,
153
+ "identifiers" => identifiers,
154
+ "sizes" => sizes,
155
+ "formats" => formats,
156
+ "version" => version_info,
157
+ "rights_list" => rights_list,
158
+ "descriptions" => descriptions,
159
+ "geo_locations" => geo_locations,
160
+ "funding_references" => funding_references,
161
+ "related_identifiers" => related_identifiers,
162
+ "schema_version" => schema_version,
163
+ "provider_id" => provider_id,
164
+ "client_id" => client_id,
165
+ "agency" => agency,
166
+ "state" => state
167
+ }.compact
168
+ end
169
+
149
170
  def style
150
171
  @style ||= "apa"
151
172
  end
@@ -40,14 +40,14 @@ module Bolognese
40
40
  "citeproc" => BIB_TO_CP_TRANSLATIONS[meta.try(:type).to_s] || "misc",
41
41
  "ris" => BIB_TO_RIS_TRANSLATIONS[meta.try(:type).to_s] || "GEN"
42
42
  }.compact
43
- doi = meta.try(:doi).to_s.presence
43
+ doi = meta.try(:doi).to_s.presence || options[:doi]
44
44
 
45
- author = Array(meta.try(:author)).map do |a|
46
- { "type" => "Person",
47
- "name" => [a.first, a.last].join(" "),
48
- "givenName" => a.first,
49
- "familyName" => a.last }.compact
50
- end
45
+ creators = Array(meta.try(:author)).map do |a|
46
+ { "nameType" => "Personal",
47
+ "name" => [a.last, a.first].join(", "),
48
+ "givenName" => a.first,
49
+ "familyName" => a.last }.compact
50
+ end
51
51
 
52
52
  related_identifiers = if meta.try(:journal).present? && meta.try(:issn).to_s.presence
53
53
  [{ "type" => "Periodical",
@@ -59,16 +59,22 @@ module Bolognese
59
59
  nil
60
60
  end
61
61
 
62
- periodical = if meta.try(:journal).present?
63
- { "type" => "Periodical",
62
+ container = if meta.try(:journal).present?
63
+ first_page = meta.try(:pages).present? ? meta.try(:pages).split("-").map(&:strip).first : nil
64
+ last_page = meta.try(:pages).present? ? meta.try(:pages).split("-").map(&:strip).last : nil
65
+
66
+ { "type" => "Journal",
64
67
  "title" => meta.journal.to_s,
65
- "issn" => meta.try(:issn).to_s.presence }.compact
68
+ "identifier" => meta.try(:issn).to_s.presence,
69
+ "identifierType" => meta.try(:issn).present? ? "ISSN" : nil,
70
+ "volume" => meta.try(:volume).to_s.presence,
71
+ "firstPage" => first_page,
72
+ "lastPage" => last_page }.compact
66
73
  else
67
74
  nil
68
75
  end
69
76
 
70
- page_first, page_last = meta.try(:pages).to_s.split("-")
71
- state = doi.present? || read_options.present? ? "findable" : "not_found"
77
+ state = meta.try(:doi).to_s.present? || read_options.present? ? "findable" : "not_found"
72
78
  dates = if meta.try(:date).present?
73
79
  [{ "date" => meta.date.to_s,
74
80
  "dateType" => "Issued" }]
@@ -79,18 +85,16 @@ module Bolognese
79
85
 
80
86
  { "id" => normalize_doi(doi),
81
87
  "types" => types,
88
+ "identifiers" => [{ "identifier" => normalize_doi(doi), "identifierType" => "DOI" }],
82
89
  "doi" => doi,
83
90
  "url" => meta.try(:url).to_s.presence,
84
91
  "titles" => meta.try(:title).present? ? [{ "title" => meta.try(:title).to_s }] : [],
85
- "creators" => author,
86
- "periodical" => periodical,
92
+ "creators" => creators,
93
+ "container" => container,
87
94
  "publisher" => meta.try(:publisher).to_s.presence,
88
95
  "related_identifiers" => related_identifiers,
89
96
  "dates" => dates,
90
97
  "publication_year" => publication_year,
91
- "volume" => meta.try(:volume).to_s.presence,
92
- "page_first" => page_first,
93
- "page_last" => page_last,
94
98
  "descriptions" => meta.try(:abstract).present? ? [{ "description" => meta.try(:abstract) && sanitize(meta.abstract.to_s).presence, "descriptionType" => "Abstract" }] : [],
95
99
  "rights_list" => meta.try(:copyright).present? ? [{ "rightsUri" => meta.try(:copyright).to_s.presence }.compact] : [],
96
100
  "state" => state