bolognese 0.4.3 → 2.6.1

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 (326) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/build.yml +9 -0
  3. data/.github/workflows/changelog.yml +36 -0
  4. data/.github/workflows/ci.yml +22 -0
  5. data/.github/workflows/pull-request.yml +9 -0
  6. data/.github/workflows/release.yml +32 -0
  7. data/.gitignore +4 -0
  8. data/.rubocop.yml +658 -0
  9. data/CHANGELOG.md +1864 -0
  10. data/CITATION +17 -0
  11. data/Gemfile +1 -1
  12. data/Gemfile.lock +250 -98
  13. data/README.md +963 -21
  14. data/Rakefile +1 -0
  15. data/bin/bolognese +5 -1
  16. data/bolognese.gemspec +33 -21
  17. data/lib/bolognese/array.rb +13 -0
  18. data/lib/bolognese/author_utils.rb +147 -33
  19. data/lib/bolognese/citeproc_extensions.rb +48 -0
  20. data/lib/bolognese/cli.rb +28 -21
  21. data/lib/bolognese/datacite_utils.rb +292 -104
  22. data/lib/bolognese/doi_utils.rb +44 -20
  23. data/lib/bolognese/metadata.rb +249 -23
  24. data/lib/bolognese/metadata_utils.rb +228 -0
  25. data/lib/bolognese/pubmed.rb +2 -0
  26. data/lib/bolognese/readers/bibtex_reader.rb +100 -0
  27. data/lib/bolognese/readers/citeproc_reader.rb +125 -0
  28. data/lib/bolognese/readers/codemeta_reader.rb +108 -0
  29. data/lib/bolognese/readers/crosscite_reader.rb +17 -0
  30. data/lib/bolognese/readers/crossref_reader.rb +413 -0
  31. data/lib/bolognese/readers/datacite_json_reader.rb +17 -0
  32. data/lib/bolognese/readers/datacite_reader.rb +341 -0
  33. data/lib/bolognese/readers/npm_reader.rb +115 -0
  34. data/lib/bolognese/readers/ris_reader.rb +114 -0
  35. data/lib/bolognese/readers/schema_org_reader.rb +264 -0
  36. data/lib/bolognese/string.rb +3 -1
  37. data/lib/bolognese/utils.rb +1463 -25
  38. data/lib/bolognese/version.rb +1 -1
  39. data/lib/bolognese/whitelist_scrubber.rb +47 -0
  40. data/lib/bolognese/writers/bibtex_writer.rb +32 -0
  41. data/lib/bolognese/writers/citation_writer.rb +14 -0
  42. data/lib/bolognese/writers/citeproc_writer.rb +11 -0
  43. data/lib/bolognese/writers/codemeta_writer.rb +29 -0
  44. data/lib/bolognese/writers/crosscite_writer.rb +11 -0
  45. data/lib/bolognese/writers/crossref_writer.rb +11 -0
  46. data/lib/bolognese/writers/csv_writer.rb +24 -0
  47. data/lib/bolognese/writers/datacite_json_writer.rb +13 -0
  48. data/lib/bolognese/writers/datacite_writer.rb +12 -0
  49. data/lib/bolognese/writers/jats_writer.rb +137 -0
  50. data/lib/bolognese/writers/rdf_xml_writer.rb +11 -0
  51. data/lib/bolognese/writers/ris_writer.rb +29 -0
  52. data/lib/bolognese/writers/schema_org_writer.rb +55 -0
  53. data/lib/bolognese/writers/turtle_writer.rb +11 -0
  54. data/lib/bolognese.rb +19 -5
  55. data/package.json +12 -0
  56. data/resources/2008/09/xsd.xsl +997 -0
  57. data/resources/datacite-contributorType-v4.xsd +35 -0
  58. data/resources/datacite-dateType-v4.xsd +25 -0
  59. data/resources/datacite-descriptionType-v4.xsd +19 -0
  60. data/resources/datacite-funderIdentifierType-v4.xsd +15 -0
  61. data/resources/datacite-nameType-v4.xsd +10 -0
  62. data/resources/datacite-relatedIdentifierType-v4.xsd +34 -0
  63. data/resources/datacite-relationType-v4.xsd +49 -0
  64. data/resources/datacite-resourceType-v4.xsd +28 -0
  65. data/resources/datacite-titleType-v4.xsd +14 -0
  66. data/resources/kernel-2.1/include/datacite-contributorType-v1.1.xsd +22 -0
  67. data/resources/kernel-2.1/include/datacite-contributorType-v2.xsd +3 -0
  68. data/resources/kernel-2.1/include/datacite-dateType-v1.1.xsd +31 -0
  69. data/resources/kernel-2.1/include/datacite-dateType-v2.xsd +3 -0
  70. data/resources/kernel-2.1/include/datacite-descriptionType-v1.1.xsd +14 -0
  71. data/resources/kernel-2.1/include/datacite-descriptionType-v2.xsd +3 -0
  72. data/resources/kernel-2.1/include/datacite-relatedIdentifierType-v1.1.xsd +24 -0
  73. data/resources/kernel-2.1/include/datacite-relatedIdentifierType-v2.xsd +3 -0
  74. data/resources/kernel-2.1/include/datacite-relationType-v1.1.xsd +29 -0
  75. data/resources/kernel-2.1/include/datacite-relationType-v2.xsd +3 -0
  76. data/resources/kernel-2.1/include/datacite-resourceType-v1.1.xsd +22 -0
  77. data/resources/kernel-2.1/include/datacite-resourceType-v2.xsd +3 -0
  78. data/resources/kernel-2.1/include/datacite-titleType-v1.1.xsd +11 -0
  79. data/resources/kernel-2.1/include/datacite-titleType-v2.xsd +3 -0
  80. data/resources/kernel-2.1/metadata.xsd +315 -0
  81. data/resources/kernel-2.2/include/datacite-contributorType-v2.xsd +29 -0
  82. data/resources/kernel-2.2/include/datacite-dateType-v2.xsd +21 -0
  83. data/resources/kernel-2.2/include/datacite-descriptionType-v2.xsd +15 -0
  84. data/resources/kernel-2.2/include/datacite-relatedIdentifierType-v2.xsd +25 -0
  85. data/resources/kernel-2.2/include/datacite-relationType-v2.xsd +29 -0
  86. data/resources/kernel-2.2/include/datacite-resourceType-v2.xsd +23 -0
  87. data/resources/kernel-2.2/include/datacite-titleType-v2.xsd +10 -0
  88. data/resources/kernel-2.2/metadata.xsd +316 -0
  89. data/resources/kernel-3/include/datacite-contributorType-v3.1.xsd +35 -0
  90. data/resources/kernel-3/include/datacite-dateType-v3.xsd +21 -0
  91. data/resources/kernel-3/include/datacite-descriptionType-v3.xsd +17 -0
  92. data/resources/kernel-3/include/datacite-relatedIdentifierType-v3.1.xsd +30 -0
  93. data/resources/kernel-3/include/datacite-relationType-v3.1.xsd +38 -0
  94. data/resources/kernel-3/include/datacite-resourceType-v3.xsd +26 -0
  95. data/resources/kernel-3/include/datacite-titleType-v3.xsd +12 -0
  96. data/resources/kernel-3/include/xml.xsd +286 -0
  97. data/resources/kernel-3/metadata.xsd +380 -0
  98. data/resources/kernel-3.0/include/datacite-contributorType-v3.xsd +33 -0
  99. data/resources/kernel-3.0/include/datacite-dateType-v3.xsd +21 -0
  100. data/resources/kernel-3.0/include/datacite-descriptionType-v3.xsd +17 -0
  101. data/resources/kernel-3.0/include/datacite-relatedIdentifierType-v3.xsd +27 -0
  102. data/resources/kernel-3.0/include/datacite-relationType-v3.xsd +33 -0
  103. data/resources/kernel-3.0/include/datacite-resourceType-v3.xsd +26 -0
  104. data/resources/kernel-3.0/include/datacite-titleType-v3.xsd +12 -0
  105. data/resources/kernel-3.0/include/xml.xsd +286 -0
  106. data/resources/kernel-3.0/metadata.xsd +377 -0
  107. data/resources/kernel-3.1/include/datacite-contributorType-v3.1.xsd +35 -0
  108. data/resources/kernel-3.1/include/datacite-dateType-v3.xsd +21 -0
  109. data/resources/kernel-3.1/include/datacite-descriptionType-v3.xsd +17 -0
  110. data/resources/kernel-3.1/include/datacite-relatedIdentifierType-v3.1.xsd +30 -0
  111. data/resources/kernel-3.1/include/datacite-relationType-v3.1.xsd +38 -0
  112. data/resources/kernel-3.1/include/datacite-resourceType-v3.xsd +26 -0
  113. data/resources/kernel-3.1/include/datacite-titleType-v3.xsd +12 -0
  114. data/resources/kernel-3.1/include/xml.xsd +286 -0
  115. data/resources/kernel-3.1/metadata.xsd +380 -0
  116. data/resources/kernel-4/include/datacite-contributorType-v4.xsd +37 -0
  117. data/resources/kernel-4/include/datacite-dateType-v4.xsd +27 -0
  118. data/resources/kernel-4/include/datacite-descriptionType-v4.xsd +19 -0
  119. data/resources/kernel-4/include/datacite-funderIdentifierType-v4.xsd +16 -0
  120. data/resources/kernel-4/include/datacite-nameType-v4.xsd +10 -0
  121. data/resources/kernel-4/include/datacite-numberType-v4.xsd +12 -0
  122. data/resources/kernel-4/include/datacite-relatedIdentifierType-v4.xsd +39 -0
  123. data/resources/kernel-4/include/datacite-relationType-v4.xsd +59 -0
  124. data/resources/kernel-4/include/datacite-resourceType-v4.xsd +52 -0
  125. data/resources/kernel-4/include/datacite-titleType-v4.xsd +14 -0
  126. data/resources/kernel-4/include/xml.xsd +286 -0
  127. data/resources/kernel-4/metadata.xsd +715 -0
  128. data/resources/kernel-4.0/include/datacite-contributorType-v4.xsd +1 -1
  129. data/resources/kernel-4.0/include/datacite-dateType-v4.xsd +1 -1
  130. data/resources/kernel-4.0/include/datacite-descriptionType-v4.xsd +1 -1
  131. data/resources/kernel-4.0/include/datacite-funderIdentifierType-v4.xsd +1 -1
  132. data/resources/kernel-4.0/include/datacite-relatedIdentifierType-v4.xsd +1 -1
  133. data/resources/kernel-4.0/include/datacite-relationType-v4.xsd +1 -1
  134. data/resources/kernel-4.0/include/datacite-resourceType-v4.xsd +1 -1
  135. data/resources/kernel-4.0/include/datacite-titleType-v4.xsd +1 -1
  136. data/resources/kernel-4.0/include/xml.xsd +286 -0
  137. data/resources/kernel-4.0/metadata.xsd +2 -2
  138. data/resources/kernel-4.1/include/datacite-contributorType-v4.xsd +35 -0
  139. data/resources/kernel-4.1/include/datacite-dateType-v4.1.xsd +23 -0
  140. data/resources/kernel-4.1/include/datacite-descriptionType-v4.xsd +19 -0
  141. data/resources/kernel-4.1/include/datacite-funderIdentifierType-v4.xsd +15 -0
  142. data/resources/kernel-4.1/include/datacite-nameType-v4.1.xsd +10 -0
  143. data/resources/kernel-4.1/include/datacite-relatedIdentifierType-v4.xsd +32 -0
  144. data/resources/kernel-4.1/include/datacite-relationType-v4.1.xsd +46 -0
  145. data/resources/kernel-4.1/include/datacite-resourceType-v4.1.xsd +28 -0
  146. data/resources/kernel-4.1/include/datacite-titleType-v4.xsd +14 -0
  147. data/resources/kernel-4.1/include/xml.xsd +286 -0
  148. data/resources/kernel-4.1/metadata.xsd +483 -0
  149. data/resources/kernel-4.2/include/datacite-contributorType-v4.xsd +35 -0
  150. data/resources/kernel-4.2/include/datacite-dateType-v4.xsd +25 -0
  151. data/resources/kernel-4.2/include/datacite-descriptionType-v4.xsd +19 -0
  152. data/resources/kernel-4.2/include/datacite-funderIdentifierType-v4.xsd +15 -0
  153. data/resources/kernel-4.2/include/datacite-nameType-v4.xsd +10 -0
  154. data/resources/kernel-4.2/include/datacite-relatedIdentifierType-v4.xsd +34 -0
  155. data/resources/kernel-4.2/include/datacite-relationType-v4.xsd +49 -0
  156. data/resources/kernel-4.2/include/datacite-resourceType-v4.xsd +28 -0
  157. data/resources/kernel-4.2/include/datacite-titleType-v4.xsd +14 -0
  158. data/resources/kernel-4.2/include/xml.xsd +286 -0
  159. data/resources/kernel-4.2/metadata.xsd +479 -0
  160. data/resources/kernel-4.3/include/datacite-contributorType-v4.xsd +35 -0
  161. data/resources/kernel-4.3/include/datacite-dateType-v4.xsd +25 -0
  162. data/resources/kernel-4.3/include/datacite-descriptionType-v4.xsd +19 -0
  163. data/resources/kernel-4.3/include/datacite-funderIdentifierType-v4.xsd +16 -0
  164. data/resources/kernel-4.3/include/datacite-nameType-v4.xsd +10 -0
  165. data/resources/kernel-4.3/include/datacite-relatedIdentifierType-v4.xsd +34 -0
  166. data/resources/kernel-4.3/include/datacite-relationType-v4.xsd +49 -0
  167. data/resources/kernel-4.3/include/datacite-resourceType-v4.xsd +28 -0
  168. data/resources/kernel-4.3/include/datacite-titleType-v4.xsd +14 -0
  169. data/resources/kernel-4.3/include/xml.xsd +286 -0
  170. data/resources/kernel-4.3/metadata.xsd +515 -0
  171. data/resources/kernel-4.4/include/datacite-contributorType-v4.xsd +35 -0
  172. data/resources/kernel-4.4/include/datacite-dateType-v4.xsd +25 -0
  173. data/resources/kernel-4.4/include/datacite-descriptionType-v4.xsd +19 -0
  174. data/resources/kernel-4.4/include/datacite-funderIdentifierType-v4.xsd +16 -0
  175. data/resources/kernel-4.4/include/datacite-nameType-v4.xsd +10 -0
  176. data/resources/kernel-4.4/include/datacite-numberType-v4.xsd +12 -0
  177. data/resources/kernel-4.4/include/datacite-relatedIdentifierType-v4.xsd +34 -0
  178. data/resources/kernel-4.4/include/datacite-relationType-v4.xsd +51 -0
  179. data/resources/kernel-4.4/include/datacite-resourceType-v4.xsd +43 -0
  180. data/resources/kernel-4.4/include/datacite-titleType-v4.xsd +14 -0
  181. data/resources/kernel-4.4/include/xml.xsd +286 -0
  182. data/resources/kernel-4.4/metadata.xsd +707 -0
  183. data/resources/kernel-4.5/include/datacite-contributorType-v4.xsd +35 -0
  184. data/resources/kernel-4.5/include/datacite-dateType-v4.xsd +25 -0
  185. data/resources/kernel-4.5/include/datacite-descriptionType-v4.xsd +19 -0
  186. data/resources/kernel-4.5/include/datacite-funderIdentifierType-v4.xsd +16 -0
  187. data/resources/kernel-4.5/include/datacite-nameType-v4.xsd +10 -0
  188. data/resources/kernel-4.5/include/datacite-numberType-v4.xsd +12 -0
  189. data/resources/kernel-4.5/include/datacite-relatedIdentifierType-v4.xsd +34 -0
  190. data/resources/kernel-4.5/include/datacite-relationType-v4.xsd +53 -0
  191. data/resources/kernel-4.5/include/datacite-resourceType-v4.xsd +45 -0
  192. data/resources/kernel-4.5/include/datacite-titleType-v4.xsd +14 -0
  193. data/resources/kernel-4.5/include/xml.xsd +286 -0
  194. data/resources/kernel-4.5/metadata.xsd +711 -0
  195. data/resources/kernel-4.6/include/datacite-contributorType-v4.xsd +37 -0
  196. data/resources/kernel-4.6/include/datacite-dateType-v4.xsd +27 -0
  197. data/resources/kernel-4.6/include/datacite-descriptionType-v4.xsd +19 -0
  198. data/resources/kernel-4.6/include/datacite-funderIdentifierType-v4.xsd +16 -0
  199. data/resources/kernel-4.6/include/datacite-nameType-v4.xsd +10 -0
  200. data/resources/kernel-4.6/include/datacite-numberType-v4.xsd +12 -0
  201. data/resources/kernel-4.6/include/datacite-relatedIdentifierType-v4.xsd +37 -0
  202. data/resources/kernel-4.6/include/datacite-relationType-v4.xsd +57 -0
  203. data/resources/kernel-4.6/include/datacite-resourceType-v4.xsd +49 -0
  204. data/resources/kernel-4.6/include/datacite-titleType-v4.xsd +14 -0
  205. data/resources/kernel-4.6/include/xml.xsd +286 -0
  206. data/resources/kernel-4.6/metadata.xsd +712 -0
  207. data/resources/kernel-4.7/include/datacite-contributorType-v4.xsd +37 -0
  208. data/resources/kernel-4.7/include/datacite-dateType-v4.xsd +27 -0
  209. data/resources/kernel-4.7/include/datacite-descriptionType-v4.xsd +19 -0
  210. data/resources/kernel-4.7/include/datacite-funderIdentifierType-v4.xsd +16 -0
  211. data/resources/kernel-4.7/include/datacite-nameType-v4.xsd +10 -0
  212. data/resources/kernel-4.7/include/datacite-numberType-v4.xsd +12 -0
  213. data/resources/kernel-4.7/include/datacite-relatedIdentifierType-v4.xsd +39 -0
  214. data/resources/kernel-4.7/include/datacite-relationType-v4.xsd +59 -0
  215. data/resources/kernel-4.7/include/datacite-resourceType-v4.xsd +52 -0
  216. data/resources/kernel-4.7/include/datacite-titleType-v4.xsd +14 -0
  217. data/resources/kernel-4.7/include/xml.xsd +286 -0
  218. data/resources/kernel-4.7/metadata.xsd +715 -0
  219. data/resources/oecd/dfg-mappings.json +1866 -0
  220. data/resources/oecd/for-mappings.json +1101 -0
  221. data/resources/oecd/fos-mappings.json +198 -0
  222. data/resources/schema_org/jsonldcontext.json +7477 -0
  223. data/resources/spdx/licenses.json +5297 -0
  224. data/resources/xml.xsd +286 -0
  225. metadata +466 -179
  226. data/.travis.yml +0 -23
  227. data/lib/bolognese/crossref.rb +0 -233
  228. data/lib/bolognese/datacite.rb +0 -176
  229. data/lib/bolognese/date_utils.rb +0 -48
  230. data/lib/bolognese/github.rb +0 -106
  231. data/lib/bolognese/orcid.rb +0 -24
  232. data/lib/bolognese/schema_org.rb +0 -170
  233. data/spec/cli_spec.rb +0 -56
  234. data/spec/crossref_spec.rb +0 -190
  235. data/spec/datacite_spec.rb +0 -93
  236. data/spec/datacite_utils_spec.rb +0 -159
  237. data/spec/doi_utils_spec.rb +0 -89
  238. data/spec/fixtures/crossref.xml +0 -742
  239. data/spec/fixtures/datacite.xml +0 -40
  240. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_crossref.yml +0 -760
  241. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_datacite.yml +0 -1476
  242. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/crossref/as_schema_org.yml +0 -1476
  243. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/datacite/as_datacite.yml +0 -214
  244. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/datacite/as_schema_org.yml +0 -384
  245. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/schema_org/as_datacite.yml +0 -653
  246. data/spec/fixtures/vcr_cassettes/Bolognese_CLI/read/schema_org/as_schema_org.yml +0 -653
  247. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/crossref.yml +0 -971
  248. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/datacite.yml +0 -971
  249. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/medra.yml +0 -971
  250. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/doi_registration_agency/not_found.yml +0 -971
  251. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_ORCID_ID.yml +0 -506
  252. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_SICI_DOI.yml +0 -214
  253. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/DOI_with_data_citation.yml +0 -901
  254. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/date_in_future.yml +0 -305
  255. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/journal_article.yml +0 -1080
  256. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/not_found_error.yml +0 -183
  257. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata/posted_content.yml +0 -389
  258. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/DOI_with_ORCID_ID.yml +0 -506
  259. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/DOI_with_data_citation.yml +0 -901
  260. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/with_ORCID_ID.yml +0 -366
  261. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/with_data_citation.yml +0 -719
  262. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_datacite_xml/with_editor.yml +0 -930
  263. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/get_metadata_as_string/DOI_with_data_citation.yml +0 -719
  264. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/SICI_doi.yml +0 -930
  265. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi.yml +0 -930
  266. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_from_url_without_doi_proxy.yml +0 -930
  267. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_prefix_too_long.yml +0 -930
  268. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_prefix_with_string.yml +0 -930
  269. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/doi_with_protocol.yml +0 -930
  270. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/dx_doi_org_url.yml +0 -930
  271. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/https_url.yml +0 -930
  272. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_doi/not_valid_doi_prefix.yml +0 -930
  273. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_ids/doi.yml +0 -930
  274. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_ids/url.yml +0 -930
  275. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_url/doi.yml +0 -930
  276. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/normalize_url/url.yml +0 -930
  277. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/array.yml +0 -930
  278. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/hash.yml +0 -930
  279. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/nil.yml +0 -930
  280. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attribute/string.yml +0 -930
  281. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/array.yml +0 -930
  282. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/hash.yml +0 -930
  283. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/nil.yml +0 -930
  284. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/parse_attributes/string.yml +0 -930
  285. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/validate_url/DOI.yml +0 -930
  286. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/validate_url/URL.yml +0 -930
  287. data/spec/fixtures/vcr_cassettes/Bolognese_Crossref/validate_url/string.yml +0 -930
  288. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/BlogPosting.yml +0 -477
  289. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/Dataset.yml +0 -1925
  290. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata/Date.yml +0 -458
  291. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/get_metadata_as_string/Dataset.yml +0 -173
  292. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_alternate_identifiers/insert.yml +0 -173
  293. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_contributors/insert.yml +0 -173
  294. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_contributors/none.yml +0 -173
  295. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_creators/insert.yml +0 -173
  296. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_dates/insert.yml +0 -173
  297. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_descriptions/insert.yml +0 -155
  298. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_identifier/doi.yml +0 -173
  299. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_person/creator.yml +0 -173
  300. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_person/creator_given_and_family_name.yml +0 -173
  301. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_person/creator_only_name.yml +0 -173
  302. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_publication_year/insert.yml +0 -173
  303. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_publisher/insert.yml +0 -173
  304. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_related_identifiers/get_related_identifier_type.yml +0 -173
  305. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_related_identifiers/get_related_identifier_type_DOI.yml +0 -173
  306. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_related_identifiers/get_related_identifier_type_URL.yml +0 -173
  307. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_related_identifiers/insert.yml +0 -173
  308. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_related_identifiers/rel_identifiers.yml +0 -173
  309. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_resource_type/insert.yml +0 -173
  310. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_rights_list/insert.yml +0 -173
  311. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_subjects/insert.yml +0 -173
  312. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_titles/doi.yml +0 -173
  313. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_titles/insert.yml +0 -173
  314. data/spec/fixtures/vcr_cassettes/Bolognese_Datacite/insert_version/insert.yml +0 -173
  315. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/crossref.yml +0 -44
  316. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/crossref_doi_not_url.yml +0 -44
  317. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/datacite.yml +0 -44
  318. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/datacite_doi_http.yml +0 -44
  319. data/spec/fixtures/vcr_cassettes/Bolognese_Metadata/find_PID_provider/orcid.yml +0 -44
  320. data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata/BlogPosting.yml +0 -632
  321. data/spec/fixtures/vcr_cassettes/Bolognese_SchemaOrg/get_metadata/not_found_error.yml +0 -93
  322. data/spec/metadata_spec.rb +0 -41
  323. data/spec/orcid_spec.rb +0 -23
  324. data/spec/schema_org_spec.rb +0 -33
  325. data/spec/spec_helper.rb +0 -88
  326. data/spec/utils_spec.rb +0 -107
@@ -1,50 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bolognese
2
4
  module DataciteUtils
3
-
4
- SO_TO_DC_TRANSLATIONS = {
5
- "VideoObject" => "Audiovisual",
6
- "Collection" => "Collection",
7
- "Dataset" => "Dataset",
8
- "Event" => "Event",
9
- "ImageObject" => "Image",
10
- "Service" => "Service",
11
- "SoftwareSourceCode" => "Software",
12
- "AudioObject" => "Sound",
13
- "ScholarlyArticle" => "Text",
14
- "CreativeWork" => "Other"
15
- }
16
-
17
- LICENSE_NAMES = {
18
- "http://creativecommons.org/publicdomain/zero/1.0/" => "Public Domain (CC0 1.0)",
19
- "http://creativecommons.org/licenses/by/3.0/" => "Creative Commons Attribution 3.0 (CC-BY 3.0)",
20
- "http://creativecommons.org/licenses/by/4.0/" => "Creative Commons Attribution 4.0 (CC-BY 4.0)",
21
- "http://creativecommons.org/licenses/by-nc/4.0/" => "Creative Commons Attribution Noncommercial 4.0 (CC-BY-NC 4.0)",
22
- "http://creativecommons.org/licenses/by-sa/4.0/" => "Creative Commons Attribution Share Alike 4.0 (CC-BY-SA 4.0)",
23
- "http://creativecommons.org/licenses/by-nc-nd/4.0/" => "Creative Commons Attribution Noncommercial No Derivaties 4.0 (CC-BY-NC-ND 4.0)"
24
- }
25
-
26
- SCHEMA = File.expand_path("../../../resources/kernel-4.0/metadata.xsd", __FILE__)
27
-
28
- def schema
29
- Nokogiri::XML::Schema(open(SCHEMA))
30
- end
31
-
32
5
  def datacite_xml
33
- Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
6
+ @datacite_xml ||= Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml|
34
7
  xml.resource(root_attributes) do
35
8
  insert_work(xml)
36
9
  end
37
10
  end.to_xml
38
11
  end
39
12
 
40
- def as_datacite
41
- if schema.validate(Nokogiri::XML(datacite_xml))
42
- datacite_xml
13
+ def datacite_errors(xml: nil, schema_version: nil)
14
+ if xml.present?
15
+ namespaces = Nokogiri::XML(xml, nil, 'UTF-8').root.namespaces
16
+ schema_version = namespaces.fetch('xmlns',nil).presence || namespaces.fetch('xmlns:ns0',nil).presence
17
+ else
18
+ schema_version = schema_version.to_s.start_with?("http://datacite.org/schema/kernel") ? schema_version : "http://datacite.org/schema/kernel-4"
43
19
  end
44
- end
45
20
 
46
- def validation_errors
47
- @validation_errors ||= schema.validate(Nokogiri::XML(datacite_xml))
21
+ kernel = schema_version.to_s.split("/").last
22
+ filepath = File.expand_path("../../../resources/#{kernel}/metadata.xsd", __FILE__)
23
+ schema = Nokogiri::XML::Schema(open(filepath))
24
+
25
+ schema.validate(Nokogiri::XML(xml, nil, 'UTF-8')).map { |error| error.to_s }.unwrap
26
+ rescue Nokogiri::XML::SyntaxError => e
27
+ e.message
48
28
  end
49
29
 
50
30
  def insert_work(xml)
@@ -54,14 +34,20 @@ module Bolognese
54
34
  insert_publisher(xml)
55
35
  insert_publication_year(xml)
56
36
  insert_resource_type(xml)
57
- insert_alternate_identifiers(xml)
58
37
  insert_subjects(xml)
59
38
  insert_contributors(xml)
60
39
  insert_dates(xml)
40
+ insert_language(xml)
41
+ insert_alternate_identifiers(xml)
61
42
  insert_related_identifiers(xml)
43
+ insert_related_items(xml)
44
+ insert_sizes(xml)
45
+ insert_formats(xml)
62
46
  insert_version(xml)
63
47
  insert_rights_list(xml)
64
48
  insert_descriptions(xml)
49
+ insert_geo_locations(xml)
50
+ insert_funding_references(xml)
65
51
  end
66
52
 
67
53
  def insert_identifier(xml)
@@ -70,154 +56,357 @@ module Bolognese
70
56
 
71
57
  def insert_creators(xml)
72
58
  xml.creators do
73
- Array.wrap(author).each do |creator|
59
+ Array.wrap(creators).each do |au|
74
60
  xml.creator do
75
- insert_person(xml, creator, "creator")
61
+ insert_person(xml, au, "creator")
76
62
  end
77
63
  end
78
64
  end
79
65
  end
80
66
 
81
67
  def insert_contributors(xml)
82
- return xml unless editor.present?
68
+ return xml unless contributors.present?
83
69
 
84
70
  xml.contributors do
85
- Array.wrap(editor).each do |contributor|
86
- xml.contributor("contributorType" => "Editor") do
87
- insert_person(xml, contributor, "contributor")
71
+ Array.wrap(contributors).each do |con|
72
+ xml.contributor("contributorType" => con["contributorType"]) do
73
+ insert_person(xml, con, "contributor")
88
74
  end
89
75
  end
90
76
  end
91
77
  end
92
78
 
93
79
  def insert_person(xml, person, type)
94
- person_name = person["name"].presence || [person["familyName"], person["givenName"]].compact.join(", ")
95
-
96
- xml.send(type + "Name", person_name)
80
+ person_name = person["familyName"].present? ? [person["familyName"], person["givenName"]].compact.join(", ") : person["name"]
81
+ attributes = { "nameType" => person["nameType"] }.compact
82
+ xml.send(type + "Name", person_name, attributes)
97
83
  xml.givenName(person["givenName"]) if person["givenName"].present?
98
84
  xml.familyName(person["familyName"]) if person["familyName"].present?
99
- xml.nameIdentifier(person["@id"], 'schemeURI' => 'http://orcid.org/', 'nameIdentifierScheme' => 'ORCID') if person["@id"].present?
85
+ Array.wrap(person["nameIdentifiers"]).each do |ni|
86
+ xml.nameIdentifier(ni["nameIdentifier"], 'nameIdentifierScheme' => ni["nameIdentifierScheme"], 'schemeURI' => ni["schemeUri"])
87
+ end
88
+ Array.wrap(person["affiliation"]).each do |affiliation|
89
+ attributes = { "affiliationIdentifier" => affiliation["affiliationIdentifier"], "affiliationIdentifierScheme" => affiliation["affiliationIdentifierScheme"], "schemeURI" => affiliation["schemeUri"] }.compact
90
+ xml.affiliation(affiliation["name"], attributes)
91
+ end
100
92
  end
101
93
 
102
94
  def insert_titles(xml)
103
95
  xml.titles do
104
- insert_title(xml)
105
- end
106
- end
96
+ Array.wrap(titles).each do |title|
97
+ if title.is_a?(Hash)
98
+ t = title
99
+ else
100
+ t = {}
101
+ t["title"] = title
102
+ end
107
103
 
108
- def insert_title(xml)
109
- xml.title(name)
104
+ attributes = { 'titleType' => t["titleType"], 'xml:lang' => t["lang"] }.compact
105
+ xml.title(t["title"], attributes)
106
+ end
107
+ end
110
108
  end
111
-
109
+
112
110
  def insert_publisher(xml)
113
- xml.publisher(container_title)
111
+ if publisher.is_a?(Hash)
112
+ attributes = {
113
+ 'publisherIdentifier' => publisher["publisherIdentifier"],
114
+ 'publisherIdentifierScheme' => publisher["publisherIdentifierScheme"],
115
+ 'schemeURI' => publisher["schemeUri"],
116
+ "xml:lang" => publisher["lang"]
117
+ }.compact
118
+ xml.publisher(publisher["name"] || container && container["title"], attributes)
119
+ else
120
+ xml.publisher(publisher || container && container["title"])
121
+ end
114
122
  end
115
123
 
116
124
  def insert_publication_year(xml)
117
- xml.publicationYear(date_published[0..3])
125
+ xml.publicationYear(publication_year)
118
126
  end
119
127
 
120
128
  def insert_resource_type(xml)
121
- return xml unless type.present?
129
+ return xml unless types.is_a?(Hash) && (types["schemaOrg"].present? || types["resourceTypeGeneral"])
122
130
 
123
- xml.resourceType(additional_type, 'resourceTypeGeneral' => SO_TO_DC_TRANSLATIONS[type])
131
+ xml.resourceType(types["resourceType"],
132
+ 'resourceTypeGeneral' => types["resourceTypeGeneral"] || Metadata::SO_TO_DC_TRANSLATIONS[types["schemaOrg"]] || "Other")
124
133
  end
125
134
 
126
135
  def insert_alternate_identifiers(xml)
127
- return xml unless alternate_name.present?
136
+ alternate_identifiers = Array.wrap(identifiers).select { |r| r["identifierType"] != "DOI" }
137
+ return xml unless alternate_identifiers.present?
128
138
 
129
139
  xml.alternateIdentifiers do
130
- xml.alternateIdentifier(alternate_name, 'alternateIdentifierType' => "Local accession number")
140
+ Array.wrap(alternate_identifiers).each do |alternate_identifier|
141
+ xml.alternateIdentifier(alternate_identifier["identifier"], 'alternateIdentifierType' => alternate_identifier["identifierType"])
142
+ end
131
143
  end
132
144
  end
133
145
 
134
146
  def insert_dates(xml)
147
+ return xml unless Array.wrap(dates).present?
148
+
135
149
  xml.dates do
136
- insert_date(xml, date_created, 'Created') if date_created.present?
137
- insert_date(xml, date_published, 'Issued') if date_published.present?
138
- insert_date(xml, date_modified, 'Updated') if date_modified.present?
150
+ Array.wrap(dates).each do |date|
151
+ attributes = { 'dateType' => date["dateType"] || "Issued", 'dateInformation' => date["dateInformation"] }.compact
152
+ xml.date(date["date"], attributes)
153
+ end
139
154
  end
140
155
  end
141
156
 
142
- def insert_date(xml, date, date_type)
143
- xml.date(date, 'dateType' => date_type)
157
+ def insert_funding_references(xml)
158
+ return xml unless Array.wrap(funding_references).present?
159
+
160
+ xml.fundingReferences do
161
+ Array.wrap(funding_references).each do |funding_reference|
162
+ xml.fundingReference do
163
+ xml.funderName(funding_reference["funderName"])
164
+ xml.funderIdentifier(funding_reference["funderIdentifier"], { "funderIdentifierType" => funding_reference["funderIdentifierType"] }.compact) if funding_reference["funderIdentifier"].present?
165
+ xml.awardNumber(funding_reference["awardNumber"], { "awardURI" => funding_reference["awardUri"] }.compact) if funding_reference["awardNumber"].present? || funding_reference["awardUri"].present?
166
+ xml.awardTitle(funding_reference["awardTitle"]) if funding_reference["awardTitle"].present?
167
+ end
168
+ end
169
+ end
144
170
  end
145
171
 
146
172
  def insert_subjects(xml)
147
- return xml unless keywords.present?
173
+ return xml unless subjects.present?
148
174
 
149
175
  xml.subjects do
150
- keywords.split(", ").each do |subject|
151
- xml.subject(subject)
176
+ subjects.each do |subject|
177
+ if subject.is_a?(Hash)
178
+ s = subject
179
+ else
180
+ s = {}
181
+ s["subject"] = subject
182
+ end
183
+
184
+ attributes = { "subjectScheme" => s["subjectScheme"], "schemeURI" => s["schemeUri"], "valueURI" => s["valueUri"], "classificationCode" => s["classificationCode"], "xml:lang" => s["lang"] }.compact
185
+
186
+ xml.subject(s["subject"], attributes)
152
187
  end
153
188
  end
154
189
  end
155
190
 
156
191
  def insert_version(xml)
157
- return xml unless version.present?
192
+ return xml unless version_info.present?
158
193
 
159
- xml.version(version)
194
+ xml.version(version_info)
160
195
  end
161
196
 
162
- def rel_identifiers
163
- ipo = Array.wrap(is_part_of).map do |i|
164
- {
165
- "text" => i["@id"],
166
- "related_identifier_type" => validate_url(i["@id"]),
167
- "relation_type" => "IsPartOf" }
168
- end.select { |i| i["related_identifier_type"].present? }
169
197
 
170
- hp = Array.wrap(has_part).map do |i|
171
- {
172
- "text" => i["@id"],
173
- "related_identifier_type" => validate_url(i["@id"]),
174
- "relation_type" => "HasPart" }
175
- end.select { |i| i["related_identifier_type"].present? }
198
+ def insert_language(xml)
199
+ return xml unless language.present?
176
200
 
177
- c = Array.wrap(citation).map do |i|
178
- {
179
- "text" => i["@id"],
180
- "related_identifier_type" => validate_url(i["@id"]),
181
- "relation_type" => "References" }
182
- end.select { |i| i["related_identifier_type"].present? }
183
-
184
- ipo + hp + c
201
+ xml.language(language)
185
202
  end
186
203
 
187
204
  def insert_related_identifiers(xml)
188
- return xml unless rel_identifiers.present?
205
+ return xml unless related_identifiers.present?
189
206
 
190
207
  xml.relatedIdentifiers do
191
- rel_identifiers.each do |related_identifier|
192
- xml.relatedIdentifier(related_identifier["text"], 'relatedIdentifierType' => related_identifier["related_identifier_type"], 'relationType' => related_identifier["relation_type"])
208
+ related_identifiers.each do |related_identifier|
209
+ attributes = {
210
+ 'relatedIdentifierType' => related_identifier["relatedIdentifierType"],
211
+ 'relationType' => related_identifier["relationType"],
212
+ 'relationTypeInformation' => related_identifier["relationTypeInformation"],
213
+ 'resourceTypeGeneral' => related_identifier["resourceTypeGeneral",
214
+ ] }.compact
215
+
216
+ attributes.merge({ 'relatedMetadataScheme' => related_identifier["relatedMetadataSchema"],
217
+ 'schemeURI' => related_identifier["schemeUri"],
218
+ 'schemeType' => related_identifier["schemeType"]}.compact) if %w(HasMetadata IsMetadataFor).include?(related_identifier["relationType"])
219
+
220
+ xml.relatedIdentifier(related_identifier["relatedIdentifier"], attributes)
221
+ end
222
+ end
223
+ end
224
+
225
+ def insert_related_items(xml)
226
+ return xml unless related_items.present?
227
+
228
+ xml.relatedItems do
229
+ related_items.each do |related_item|
230
+ attributes = {
231
+ 'relatedItemType' => related_item["relatedItemType"],
232
+ 'relationType' => related_item["relationType"],
233
+ 'relationTypeInformation' => related_item["relationTypeInformation"],
234
+ }.compact
235
+
236
+ xml.relatedItem(related_item["relatedItem"], attributes) do
237
+
238
+ if related_item["relatedItemIdentifier"].present?
239
+ xml.relatedItemIdentifier(related_item["relatedItemIdentifier"]['relatedItemIdentifier'],
240
+ {
241
+ 'relatedItemIdentifierType' => related_item["relatedItemIdentifier"]["relatedItemIdentifierType"],
242
+ 'relatedMetadataScheme' => related_item["relatedItemIdentifier"]["relatedMetadataScheme"],
243
+ 'schemeURI' => related_item["relatedItemIdentifier"]["schemeURI"],
244
+ 'schemeType' => related_item["relatedItemIdentifier"]["schemeType"],
245
+ }.compact
246
+ )
247
+ end
248
+
249
+ if related_item["creators"].present?
250
+ xml.creators do
251
+ Array.wrap(related_item['creators']).each do |au|
252
+ xml.creator do
253
+ insert_person(xml, au, "creator")
254
+ end
255
+ end
256
+ end
257
+ end
258
+
259
+ xml.titles do
260
+ Array.wrap(related_item['titles']).each do |title|
261
+ if title.is_a?(Hash)
262
+ t = title
263
+ else
264
+ t = {}
265
+ t["title"] = title
266
+ end
267
+
268
+ attributes = { 'titleType' => t["titleType"], 'xml:lang' => t["lang"] }.compact
269
+ xml.title(t["title"], attributes)
270
+ end
271
+ end
272
+
273
+ xml.publicationYear(related_item['publicationYear']) if related_item["publicationYear"].present?
274
+ xml.volume(related_item['volume']) if related_item["volume"].present?
275
+ xml.issue(related_item['issue']) if related_item["issue"].present?
276
+ xml.number(related_item['number'], {'numberType' => related_item['numberType']}.compact) if related_item["number"].present?
277
+ xml.firstPage(related_item['firstPage']) if related_item["firstPage"].present?
278
+ xml.lastPage(related_item['lastPage']) if related_item["lastPage"].present?
279
+ xml.publisher(related_item['publisher']) if related_item["publisher"].present?
280
+ xml.edition(related_item['edition']) if related_item["edition"].present?
281
+
282
+ if related_item["contributors"].present?
283
+ xml.contributors do
284
+ Array.wrap(related_item["contributors"]).each do |con|
285
+ xml.contributor("contributorType" => con["contributorType"] || "Other") do
286
+ insert_person(xml, con, "contributor")
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ end
293
+ end
294
+ end
295
+ end
296
+
297
+ def insert_sizes(xml)
298
+ xml.sizes do
299
+ Array.wrap(sizes).each do |s|
300
+ xml.size(s)
301
+ end
302
+ end
303
+ end
304
+
305
+ def insert_formats(xml)
306
+ xml.formats do
307
+ Array.wrap(formats).each do |f|
308
+ xml.format(f)
193
309
  end
194
310
  end
195
311
  end
196
312
 
197
313
  def insert_rights_list(xml)
198
- return xml unless license.present?
314
+ return xml unless rights_list.present?
199
315
 
200
316
  xml.rightsList do
201
- xml.rights(LICENSE_NAMES[license], 'rightsURI' => license)
317
+ Array.wrap(rights_list).each do |rights|
318
+ if rights.is_a?(Hash)
319
+ r = rights
320
+ else
321
+ r = {}
322
+ r["rights"] = rights
323
+ r["rightsUri"] = normalize_id(rights)
324
+ end
325
+
326
+ attributes = {
327
+ "rightsURI" => r["rightsUri"],
328
+ "rightsIdentifier" => r["rightsIdentifier"],
329
+ "rightsIdentifierScheme" => r["rightsIdentifierScheme"],
330
+ "schemeURI" => r["schemeUri"],
331
+ "xml:lang" => r["lang"]
332
+ }.compact
333
+
334
+ xml.rights(r["rights"], attributes)
335
+ end
202
336
  end
203
337
  end
204
338
 
205
339
  def insert_descriptions(xml)
206
- return xml unless description.present?
340
+ return xml unless descriptions.present? || container && container["title"].present?
207
341
 
208
342
  xml.descriptions do
209
- xml.description(description, 'descriptionType' => "Abstract")
343
+ if (respond_to?(:from) && !from.to_s.include?("datacite")) && container && container["title"].present?
344
+ issue = container["issue"].present? ? "(#{container["issue"]})" : nil
345
+ volume_issue = container["volume"].present? ? [container["volume"], issue].join("") : nil
346
+ pages = [container["firstPage"], container["lastPage"]].compact.join("-") if container["firstPage"].present?
347
+ series_information = [container["title"], volume_issue, pages].compact.join(", ")
348
+ xml.description(series_information, 'descriptionType' => "SeriesInformation")
349
+ end
350
+
351
+ Array.wrap(descriptions).each do |description|
352
+ if description.is_a?(Hash)
353
+ d = description
354
+ else
355
+ d = {}
356
+ d["description"] = description
357
+ d["descriptionType"] = "Abstract"
358
+ end
359
+
360
+ attributes = { 'xml:lang' => d["lang"], 'descriptionType' => d["descriptionType"] || "Abstract" }.compact
361
+
362
+ xml.description(d["description"], attributes)
363
+ end
210
364
  end
211
365
  end
212
366
 
213
- def without_control(s)
214
- r = ''
215
- s.each_codepoint do |c|
216
- if c >= 32
217
- r << c
367
+ def insert_geo_locations(xml)
368
+ return xml unless geo_locations.present?
369
+
370
+ xml.geoLocations do
371
+ geo_locations.each do |geo_location|
372
+ xml.geoLocation do
373
+ xml.geoLocationPlace(geo_location["geoLocationPlace"]) if geo_location["geoLocationPlace"]
374
+
375
+ if geo_location["geoLocationPoint"]
376
+ xml.geoLocationPoint do
377
+ xml.pointLatitude(geo_location.dig("geoLocationPoint", "pointLatitude"))
378
+ xml.pointLongitude(geo_location.dig("geoLocationPoint", "pointLongitude"))
379
+ end
380
+ end
381
+
382
+ if geo_location["geoLocationBox"]
383
+ xml.geoLocationBox do
384
+ xml.westBoundLongitude(geo_location.dig("geoLocationBox", "westBoundLongitude"))
385
+ xml.eastBoundLongitude(geo_location.dig("geoLocationBox", "eastBoundLongitude"))
386
+ xml.southBoundLatitude(geo_location.dig("geoLocationBox", "southBoundLatitude"))
387
+ xml.northBoundLatitude(geo_location.dig("geoLocationBox", "northBoundLatitude"))
388
+ end
389
+ end
390
+ if geo_location["geoLocationPolygon"]
391
+ xml.geoLocationPolygon do
392
+ Array.wrap(geo_location["geoLocationPolygon"]).each do |polygon_point|
393
+ if polygon_point.has_key?("polygonPoint")
394
+ xml.polygonPoint do
395
+ xml.pointLatitude(polygon_point.dig("polygonPoint", "pointLatitude"))
396
+ xml.pointLongitude(polygon_point.dig("polygonPoint", "pointLongitude"))
397
+ end
398
+ else
399
+ xml.inPolygonPoint do
400
+ xml.pointLatitude(polygon_point.dig("inPolygonPoint", "pointLatitude"))
401
+ xml.pointLongitude(polygon_point.dig("inPolygonPoint", "pointLongitude"))
402
+ end
403
+ end
404
+ end
405
+ end
406
+ end
407
+ end
218
408
  end
219
409
  end
220
- r
221
410
  end
222
411
 
223
412
  def root_attributes
@@ -227,4 +416,3 @@ module Bolognese
227
416
  end
228
417
  end
229
418
  end
230
-
@@ -1,45 +1,69 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bolognese
2
4
  module DoiUtils
5
+ class << self
6
+ include DoiUtils
7
+ end
8
+
3
9
  def validate_doi(doi)
4
- Array(/\A(?:(http|https):\/\/(dx\.)?doi.org\/)?(doi:)?(10\.\d{4,5}\/.+)\z/.match(doi)).last
10
+ doi = Array(/\A(?:(http|https):\/(\/)?(dx\.)?(doi.org|handle.stage.datacite.org|handle.test.datacite.org)\/)?(doi:)?(10\.\d{4,5}\/.+)\z/.match(doi)).last
11
+ # remove non-printing whitespace and downcase
12
+ doi.delete("\u200B").downcase if doi.present?
5
13
  end
6
14
 
7
- def normalize_doi(doi)
8
- doi = validate_doi(doi)
9
- return nil unless doi.present?
15
+ def validate_funder_doi(doi)
16
+ doi = Array(/\A(?:(http|https):\/(\/)?(dx\.)?(doi.org|handle.stage.datacite.org|handle.test.datacite.org)\/)?(doi:)?(10\.13039\/)?([1-9]\d+)\z/.match(doi)).last
10
17
 
11
18
  # remove non-printing whitespace and downcase
12
- doi = doi.gsub(/\u200B/, '').downcase
19
+ if doi.present?
20
+ doi.delete("\u200B").downcase
21
+ "https://doi.org/10.13039/#{doi}"
22
+ end
23
+ end
24
+
25
+ def validate_prefix(doi)
26
+ Array(/\A(?:(http|https):\/(\/)?(dx\.)?(doi.org|handle.stage.datacite.org|handle.test.datacite.org)\/)?(doi:)?(10\.\d{4,5}).*\z/.match(doi)).last
27
+ end
28
+
29
+ def doi_resolver(doi, options = {})
30
+ sandbox = Array(/handle.stage.datacite.org/.match(doi)).last
31
+ sandbox.present? || options[:sandbox] ? "https://handle.stage.datacite.org/" : "https://doi.org/"
32
+ end
33
+
34
+ def doi_api_url(doi, options = {})
35
+ sandbox = Array(/handle.stage.datacite.org/.match(doi)).last
36
+ sandbox.present? || options[:sandbox] ? "https://api.stage.datacite.org/dois/#{doi_from_url(doi)}?include=media,client" : "https://api.datacite.org/dois/#{doi_from_url(doi)}?include=media,client"
37
+ end
38
+
39
+ def normalize_doi(doi, options = {})
40
+ doi_str = validate_doi(doi)
41
+ return nil unless doi_str.present?
13
42
 
14
43
  # turn DOI into URL, escape unsafe characters
15
- "https://doi.org/" + Addressable::URI.encode(doi)
44
+ doi_resolver(doi, options) + Addressable::URI.encode(doi_str)
16
45
  end
17
46
 
18
47
  def doi_from_url(url)
19
- if /\A(?:(http|https):\/\/(dx\.)?doi.org\/)?(doi:)?(10\.\d{4,5}\/.+)\z/.match(url)
48
+ if /\A(?:(http|https):\/\/(dx\.)?(doi.org|handle.stage.datacite.org|handle.test.datacite.org)\/)?(doi:)?(10\.\d{4,5}\/.+)\z/.match(url)
20
49
  uri = Addressable::URI.parse(url)
21
- uri.path[1..-1].downcase
50
+ uri.path.gsub(/^\//, '').downcase
22
51
  end
23
52
  end
24
53
 
25
54
  def doi_as_url(doi)
26
- "https://doi.org/#{clean_doi(doi)}" if doi.present?
55
+ "https://doi.org/#{doi}" if doi.present?
27
56
  end
28
57
 
29
- # get DOI registration agency, assume a normalized DOI
58
+ # get DOI registration agency
30
59
  def get_doi_ra(doi)
31
- return {} if doi.blank?
60
+ prefix = validate_prefix(doi)
61
+ return nil if prefix.blank?
32
62
 
33
- url = "https://doi.crossref.org/doiRA/#{doi_from_url(doi)}"
34
- response = Maremma.get(url, host: true, timeout: 120)
63
+ url = "https://doi.org/ra/#{prefix}"
64
+ result = Maremma.get(url)
35
65
 
36
- ra = response.body.fetch("data", {}).first.fetch("RA", nil)
37
- if ra.present?
38
- { "id" => ra.downcase,
39
- "name" => ra }
40
- else
41
- { "errors" => response.body.fetch("errors", nil) || response.body.fetch("data", nil) }
42
- end
66
+ result.body.dig("data", 0, "RA")
43
67
  end
44
68
  end
45
69
  end