relaton 2.1.0 → 3.0.0.pre.alpha.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 (625) hide show
  1. checksums.yaml +4 -4
  2. data/{docs/README.adoc → README.adoc} +109 -38
  3. data/lib/relaton/3gpp/bibdata.rb +9 -0
  4. data/lib/relaton/3gpp/bibitem.rb +9 -0
  5. data/lib/relaton/3gpp/bibliography.rb +48 -0
  6. data/lib/relaton/3gpp/data_fetcher.rb +255 -0
  7. data/lib/relaton/3gpp/doctype.rb +9 -0
  8. data/lib/relaton/3gpp/ext.rb +31 -0
  9. data/lib/relaton/3gpp/item.rb +12 -0
  10. data/lib/relaton/3gpp/item_data.rb +15 -0
  11. data/lib/relaton/3gpp/parser.rb +400 -0
  12. data/lib/relaton/3gpp/processor.rb +68 -0
  13. data/lib/relaton/3gpp/release.rb +34 -0
  14. data/lib/relaton/3gpp/util.rb +8 -0
  15. data/lib/relaton/3gpp.rb +25 -0
  16. data/lib/relaton/bib/converter/asciibib/to_asciibib.rb +663 -0
  17. data/lib/relaton/bib/converter/asciibib.rb +13 -0
  18. data/lib/relaton/bib/converter/bibtex/from_bibtex.rb +245 -0
  19. data/lib/relaton/bib/converter/bibtex/to_bibtex.rb +341 -0
  20. data/lib/relaton/bib/converter/bibtex.rb +23 -0
  21. data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +386 -0
  22. data/lib/relaton/bib/converter/bibxml/from_rfcxml_referencegroup.rb +71 -0
  23. data/lib/relaton/bib/converter/bibxml/to_rfcxml.rb +308 -0
  24. data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +52 -0
  25. data/lib/relaton/bib/converter/bibxml.rb +51 -0
  26. data/lib/relaton/bib/hash_parser_v1.rb +767 -0
  27. data/lib/relaton/bib/item_data.rb +229 -0
  28. data/lib/relaton/bib/model/abstract.rb +16 -0
  29. data/lib/relaton/bib/model/address.rb +22 -0
  30. data/lib/relaton/bib/model/affiliation.rb +16 -0
  31. data/lib/relaton/bib/model/bibdata.rb +11 -0
  32. data/lib/relaton/bib/model/bibdata_shared.rb +12 -0
  33. data/lib/relaton/bib/model/bibitem.rb +11 -0
  34. data/lib/relaton/bib/model/bibitem_shared.rb +12 -0
  35. data/lib/relaton/bib/model/contact.rb +18 -0
  36. data/lib/relaton/bib/model/contribution_info.rb +15 -0
  37. data/lib/relaton/bib/model/contributor.rb +29 -0
  38. data/lib/relaton/bib/model/copyright.rb +27 -0
  39. data/lib/relaton/bib/model/date.rb +31 -0
  40. data/lib/relaton/bib/model/depiction.rb +16 -0
  41. data/lib/relaton/bib/model/docidentifier.rb +34 -0
  42. data/lib/relaton/bib/model/doctype.rb +14 -0
  43. data/lib/relaton/bib/model/edition.rb +14 -0
  44. data/lib/relaton/bib/model/ext.rb +39 -0
  45. data/lib/relaton/bib/model/extent.rb +16 -0
  46. data/lib/relaton/bib/model/formattedref.rb +43 -0
  47. data/lib/relaton/bib/model/full_name_type.rb +64 -0
  48. data/lib/relaton/bib/model/fullname.rb +11 -0
  49. data/lib/relaton/bib/model/ics.rb +49 -0
  50. data/lib/relaton/bib/model/image.rb +28 -0
  51. data/lib/relaton/bib/model/item.rb +96 -0
  52. data/lib/relaton/bib/model/item_base.rb +20 -0
  53. data/lib/relaton/bib/model/item_shared.rb +88 -0
  54. data/lib/relaton/bib/model/keyword.rb +30 -0
  55. data/lib/relaton/bib/model/locality.rb +18 -0
  56. data/lib/relaton/bib/model/locality_stack.rb +14 -0
  57. data/lib/relaton/bib/model/localized_string.rb +48 -0
  58. data/lib/relaton/bib/model/localized_string_attrs.rb +24 -0
  59. data/lib/relaton/bib/model/logo.rb +14 -0
  60. data/lib/relaton/bib/model/medium.rb +22 -0
  61. data/lib/relaton/bib/model/note.rb +16 -0
  62. data/lib/relaton/bib/model/organization.rb +13 -0
  63. data/lib/relaton/bib/model/organization_type.rb +42 -0
  64. data/lib/relaton/bib/model/person.rb +36 -0
  65. data/lib/relaton/bib/model/phone.rb +14 -0
  66. data/lib/relaton/bib/model/place.rb +33 -0
  67. data/lib/relaton/bib/model/price.rb +14 -0
  68. data/lib/relaton/bib/model/relation.rb +43 -0
  69. data/lib/relaton/bib/model/series.rb +34 -0
  70. data/lib/relaton/bib/model/size.rb +23 -0
  71. data/lib/relaton/bib/model/source_locality_stack.rb +14 -0
  72. data/lib/relaton/bib/model/status.rb +27 -0
  73. data/lib/relaton/bib/model/structured_identifier.rb +48 -0
  74. data/lib/relaton/bib/model/subdivision.rb +16 -0
  75. data/lib/relaton/bib/model/title.rb +56 -0
  76. data/lib/relaton/bib/model/type/plain_date.rb +16 -0
  77. data/lib/relaton/bib/model/type/string_date.rb +48 -0
  78. data/lib/relaton/bib/model/uri.rb +18 -0
  79. data/lib/relaton/bib/model/validity.rb +16 -0
  80. data/lib/relaton/bib/model/version.rb +43 -0
  81. data/lib/relaton/bib/namespace_helper.rb +21 -0
  82. data/lib/relaton/bib/sanitizer.rb +68 -0
  83. data/lib/relaton/bib/util.rb +18 -0
  84. data/lib/relaton/bib/versions.json +35 -0
  85. data/lib/relaton/bib.rb +48 -0
  86. data/lib/relaton/bipm/bibliography.rb +82 -0
  87. data/lib/relaton/bipm/converter/asciibib.rb +64 -0
  88. data/lib/relaton/bipm/data_fetcher.rb +57 -0
  89. data/lib/relaton/bipm/data_outcomes_parser.rb +657 -0
  90. data/lib/relaton/bipm/id_parser.rb +277 -0
  91. data/lib/relaton/bipm/item_data.rb +47 -0
  92. data/lib/relaton/bipm/model/bibdata.rb +9 -0
  93. data/lib/relaton/bipm/model/bibitem.rb +9 -0
  94. data/lib/relaton/bipm/model/comment_period.rb +13 -0
  95. data/lib/relaton/bipm/model/doctype.rb +12 -0
  96. data/lib/relaton/bipm/model/ext.rb +38 -0
  97. data/lib/relaton/bipm/model/item.rb +11 -0
  98. data/lib/relaton/bipm/model/structured_identifier.rb +15 -0
  99. data/lib/relaton/bipm/processor.rb +69 -0
  100. data/lib/relaton/bipm/rawdata_bipm_metrologia/affiliations.rb +111 -0
  101. data/lib/relaton/bipm/rawdata_bipm_metrologia/fetcher.rb +174 -0
  102. data/lib/relaton/bipm/rawdata_bipm_metrologia/niso_jats_parser.rb +353 -0
  103. data/lib/relaton/bipm/si_brochure_parser.rb +186 -0
  104. data/lib/relaton/bipm/util.rb +8 -0
  105. data/lib/relaton/bipm.rb +32 -0
  106. data/lib/relaton/bsi/bibliography.rb +124 -0
  107. data/lib/relaton/bsi/hit.rb +14 -0
  108. data/lib/relaton/bsi/hit_collection.rb +114 -0
  109. data/lib/relaton/bsi/item_data.rb +13 -0
  110. data/lib/relaton/bsi/model/bibdata.rb +8 -0
  111. data/lib/relaton/bsi/model/bibitem.rb +8 -0
  112. data/lib/relaton/bsi/model/docidentifier.rb +9 -0
  113. data/lib/relaton/bsi/model/doctype.rb +14 -0
  114. data/lib/relaton/bsi/model/ext.rb +17 -0
  115. data/lib/relaton/bsi/model/item.rb +17 -0
  116. data/lib/relaton/bsi/model/item_base.rb +22 -0
  117. data/lib/relaton/bsi/model/relation.rb +9 -0
  118. data/lib/relaton/bsi/processor.rb +42 -0
  119. data/lib/relaton/bsi/schema.json +24882 -0
  120. data/lib/relaton/bsi/scraper.rb +288 -0
  121. data/lib/relaton/bsi/util.rb +8 -0
  122. data/lib/relaton/bsi.rb +25 -0
  123. data/lib/relaton/calconnect/bibliography.rb +95 -0
  124. data/lib/relaton/calconnect/data_fetcher.rb +106 -0
  125. data/lib/relaton/calconnect/hit.rb +14 -0
  126. data/lib/relaton/calconnect/hit_collection.rb +84 -0
  127. data/lib/relaton/calconnect/item_data.rb +12 -0
  128. data/lib/relaton/calconnect/model/bibdata.rb +8 -0
  129. data/lib/relaton/calconnect/model/bibitem.rb +8 -0
  130. data/lib/relaton/calconnect/model/doctype.rb +11 -0
  131. data/lib/relaton/calconnect/model/ext.rb +11 -0
  132. data/lib/relaton/calconnect/model/item.rb +13 -0
  133. data/lib/relaton/calconnect/processor.rb +66 -0
  134. data/lib/relaton/calconnect/scraper.rb +87 -0
  135. data/lib/relaton/calconnect/util.rb +8 -0
  136. data/lib/relaton/calconnect.rb +26 -0
  137. data/lib/relaton/ccsds/bibliography.rb +63 -0
  138. data/lib/relaton/ccsds/data/fetcher.rb +247 -0
  139. data/lib/relaton/ccsds/data/iso_references.rb +30 -0
  140. data/lib/relaton/ccsds/data/parser.rb +194 -0
  141. data/lib/relaton/ccsds/hit.rb +24 -0
  142. data/lib/relaton/ccsds/hit_collection.rb +42 -0
  143. data/lib/relaton/ccsds/item_data.rb +9 -0
  144. data/lib/relaton/ccsds/model/bibdata.rb +8 -0
  145. data/lib/relaton/ccsds/model/bibitem.rb +8 -0
  146. data/lib/relaton/ccsds/model/doctype.rb +9 -0
  147. data/lib/relaton/ccsds/model/ext.rb +19 -0
  148. data/lib/relaton/ccsds/model/item.rb +13 -0
  149. data/lib/relaton/ccsds/processor.rb +68 -0
  150. data/lib/relaton/ccsds/util.rb +10 -0
  151. data/lib/relaton/ccsds.rb +33 -0
  152. data/lib/relaton/cen/bibliography.rb +121 -0
  153. data/lib/relaton/cen/committees.yaml +66 -0
  154. data/lib/relaton/cen/hit.rb +16 -0
  155. data/lib/relaton/cen/hit_collection.rb +68 -0
  156. data/lib/relaton/cen/item_data.rb +7 -0
  157. data/lib/relaton/cen/model/bibdata.rb +8 -0
  158. data/lib/relaton/cen/model/bibitem.rb +8 -0
  159. data/lib/relaton/cen/model/docidentifier.rb +9 -0
  160. data/lib/relaton/cen/model/ext.rb +11 -0
  161. data/lib/relaton/cen/model/item.rb +14 -0
  162. data/lib/relaton/cen/model/structured_identifier.rb +9 -0
  163. data/lib/relaton/cen/processor.rb +40 -0
  164. data/lib/relaton/cen/scraper.rb +210 -0
  165. data/lib/relaton/cen/util.rb +8 -0
  166. data/lib/relaton/cen.rb +29 -0
  167. data/lib/relaton/cie/bibdata.rb +8 -0
  168. data/lib/relaton/cie/bibitem.rb +8 -0
  169. data/lib/relaton/cie/bibliography.rb +31 -0
  170. data/lib/relaton/cie/data_fetcher.rb +355 -0
  171. data/lib/relaton/cie/ext.rb +7 -0
  172. data/lib/relaton/cie/item.rb +11 -0
  173. data/lib/relaton/cie/item_data.rb +6 -0
  174. data/lib/relaton/cie/processor.rb +66 -0
  175. data/lib/relaton/cie/scrapper.rb +39 -0
  176. data/lib/relaton/cie/util.rb +8 -0
  177. data/lib/relaton/cie.rb +28 -0
  178. data/lib/relaton/core/array_wrapper.rb +20 -0
  179. data/lib/relaton/core/data_fetcher.rb +97 -0
  180. data/lib/relaton/core/date_parser.rb +42 -0
  181. data/lib/relaton/core/hash_keys_sybolizer.rb +19 -0
  182. data/lib/relaton/core/hit.rb +49 -0
  183. data/lib/relaton/core/hit_collection.rb +118 -0
  184. data/lib/relaton/core/processor.rb +48 -0
  185. data/lib/relaton/core/workers_pool.rb +45 -0
  186. data/lib/relaton/core.rb +9 -0
  187. data/lib/relaton/db/cache.rb +232 -0
  188. data/lib/relaton/db/config.rb +24 -0
  189. data/lib/relaton/db/registry.rb +119 -0
  190. data/lib/relaton/db/util.rb +9 -0
  191. data/lib/relaton/db/workers_pool.rb +22 -0
  192. data/lib/relaton/db.rb +20 -206
  193. data/lib/relaton/doi/crossref.rb +72 -0
  194. data/lib/relaton/doi/parser.rb +827 -0
  195. data/lib/relaton/doi/processor.rb +65 -0
  196. data/lib/relaton/doi/util.rb +8 -0
  197. data/lib/relaton/doi.rb +20 -0
  198. data/lib/relaton/ecma/bibdata.rb +8 -0
  199. data/lib/relaton/ecma/bibitem.rb +8 -0
  200. data/lib/relaton/ecma/bibliography.rb +81 -0
  201. data/lib/relaton/ecma/data_fetcher.rb +103 -0
  202. data/lib/relaton/ecma/data_parser.rb +49 -0
  203. data/lib/relaton/ecma/edition_parser.rb +80 -0
  204. data/lib/relaton/ecma/ext.rb +7 -0
  205. data/lib/relaton/ecma/item.rb +11 -0
  206. data/lib/relaton/ecma/item_data.rb +6 -0
  207. data/lib/relaton/ecma/memento_parser.rb +60 -0
  208. data/lib/relaton/ecma/page_fetcher.rb +27 -0
  209. data/lib/relaton/ecma/parser_common.rb +33 -0
  210. data/lib/relaton/ecma/processor.rb +66 -0
  211. data/lib/relaton/ecma/standard_parser.rb +134 -0
  212. data/lib/relaton/ecma/util.rb +8 -0
  213. data/lib/relaton/ecma.rb +24 -0
  214. data/lib/relaton/etsi/bibdata.rb +10 -0
  215. data/lib/relaton/etsi/bibitem.rb +10 -0
  216. data/lib/relaton/etsi/bibliography.rb +46 -0
  217. data/lib/relaton/etsi/data_fetcher.rb +128 -0
  218. data/lib/relaton/etsi/data_parser.rb +208 -0
  219. data/lib/relaton/etsi/doctype.rb +30 -0
  220. data/lib/relaton/etsi/ext.rb +31 -0
  221. data/lib/relaton/etsi/item.rb +15 -0
  222. data/lib/relaton/etsi/item_data.rb +6 -0
  223. data/lib/relaton/etsi/processor.rb +69 -0
  224. data/lib/relaton/etsi/pubid.rb +37 -0
  225. data/lib/relaton/etsi/status.rb +13 -0
  226. data/lib/relaton/etsi/util.rb +8 -0
  227. data/lib/relaton/etsi.rb +25 -0
  228. data/lib/relaton/gb/bibdata.rb +8 -0
  229. data/lib/relaton/gb/bibitem.rb +8 -0
  230. data/lib/relaton/gb/bibliography.rb +145 -0
  231. data/lib/relaton/gb/ccs.rb +14 -0
  232. data/lib/relaton/gb/committee.rb +13 -0
  233. data/lib/relaton/gb/docidentifier.rb +23 -0
  234. data/lib/relaton/gb/doctype.rb +9 -0
  235. data/lib/relaton/gb/ext.rb +36 -0
  236. data/lib/relaton/gb/gb_scraper.rb +61 -0
  237. data/lib/relaton/gb/gb_type.rb +20 -0
  238. data/lib/relaton/gb/hit.rb +48 -0
  239. data/lib/relaton/gb/hit_collection.rb +19 -0
  240. data/lib/relaton/gb/item.rb +13 -0
  241. data/lib/relaton/gb/item_data.rb +6 -0
  242. data/lib/relaton/gb/processor.rb +46 -0
  243. data/lib/relaton/gb/project_number.rb +38 -0
  244. data/lib/relaton/gb/scraper.rb +204 -0
  245. data/lib/relaton/gb/sec_scraper.rb +92 -0
  246. data/lib/relaton/gb/stage_name.rb +13 -0
  247. data/lib/relaton/gb/structured_identifier.rb +26 -0
  248. data/lib/relaton/gb/t_scraper.rb +126 -0
  249. data/lib/relaton/gb/util.rb +8 -0
  250. data/lib/relaton/gb/yaml/prefixes.yaml +200 -0
  251. data/lib/relaton/gb.rb +33 -0
  252. data/lib/relaton/iana/bibdata.rb +8 -0
  253. data/lib/relaton/iana/bibitem.rb +8 -0
  254. data/lib/relaton/iana/bibliography.rb +47 -0
  255. data/lib/relaton/iana/data_fetcher.rb +71 -0
  256. data/lib/relaton/iana/item.rb +7 -0
  257. data/lib/relaton/iana/item_data.rb +6 -0
  258. data/lib/relaton/iana/parser.rb +146 -0
  259. data/lib/relaton/iana/processor.rb +68 -0
  260. data/lib/relaton/iana/util.rb +8 -0
  261. data/lib/relaton/iana.rb +29 -0
  262. data/lib/relaton/iec/bibliography.rb +283 -0
  263. data/lib/relaton/iec/data_fetcher.rb +216 -0
  264. data/lib/relaton/iec/data_parser.rb +391 -0
  265. data/lib/relaton/iec/hit.rb +26 -0
  266. data/lib/relaton/iec/hit_collection.rb +138 -0
  267. data/lib/relaton/iec/item_data.rb +7 -0
  268. data/lib/relaton/iec/model/bibdata.rb +8 -0
  269. data/lib/relaton/iec/model/bibitem.rb +8 -0
  270. data/lib/relaton/iec/model/docidentifier.rb +131 -0
  271. data/lib/relaton/iec/model/doctype.rb +12 -0
  272. data/lib/relaton/iec/model/ext.rb +53 -0
  273. data/lib/relaton/iec/model/item.rb +20 -0
  274. data/lib/relaton/iec/model/item_base.rb +12 -0
  275. data/lib/relaton/iec/model/relation.rb +7 -0
  276. data/lib/relaton/iec/model/stage_name.rb +13 -0
  277. data/lib/relaton/iec/processor.rb +73 -0
  278. data/lib/relaton/iec/statuses.yml +199 -0
  279. data/lib/relaton/iec/util.rb +8 -0
  280. data/lib/relaton/iec.rb +98 -0
  281. data/lib/relaton/ieee/balloting_group.rb +13 -0
  282. data/lib/relaton/ieee/bibdata.rb +8 -0
  283. data/lib/relaton/ieee/bibitem.rb +8 -0
  284. data/lib/relaton/ieee/bibliography.rb +51 -0
  285. data/lib/relaton/ieee/converter/bibxml/from_rfcxml.rb +10 -0
  286. data/lib/relaton/ieee/converter/bibxml/from_rfcxml_referencegroup.rb +10 -0
  287. data/lib/relaton/ieee/converter/bibxml.rb +20 -0
  288. data/lib/relaton/ieee/data_fetcher.rb +630 -0
  289. data/lib/relaton/ieee/doctype.rb +9 -0
  290. data/lib/relaton/ieee/editorial_group.rb +19 -0
  291. data/lib/relaton/ieee/ext.rb +36 -0
  292. data/lib/relaton/ieee/idams_parser.rb +323 -0
  293. data/lib/relaton/ieee/item.rb +11 -0
  294. data/lib/relaton/ieee/item_data.rb +7 -0
  295. data/lib/relaton/ieee/processor.rb +68 -0
  296. data/lib/relaton/ieee/pub_id.rb +161 -0
  297. data/lib/relaton/ieee/rawbib_id_parser.rb +548 -0
  298. data/lib/relaton/ieee/util.rb +8 -0
  299. data/lib/relaton/ieee.rb +29 -0
  300. data/lib/relaton/ietf/bibdata.rb +8 -0
  301. data/lib/relaton/ietf/bibitem.rb +8 -0
  302. data/lib/relaton/ietf/bibliography.rb +35 -0
  303. data/lib/relaton/ietf/bibxml_parser.rb +232 -0
  304. data/lib/relaton/ietf/data_fetcher.rb +278 -0
  305. data/lib/relaton/ietf/doctype.rb +9 -0
  306. data/lib/relaton/ietf/ext.rb +63 -0
  307. data/lib/relaton/ietf/item.rb +16 -0
  308. data/lib/relaton/ietf/item_base.rb +18 -0
  309. data/lib/relaton/ietf/item_data.rb +6 -0
  310. data/lib/relaton/ietf/processing_instructions.rb +79 -0
  311. data/lib/relaton/ietf/processor.rb +68 -0
  312. data/lib/relaton/ietf/relation.rb +9 -0
  313. data/lib/relaton/ietf/rfc/abstract.rb +19 -0
  314. data/lib/relaton/ietf/rfc/author.rb +21 -0
  315. data/lib/relaton/ietf/rfc/entry.rb +410 -0
  316. data/lib/relaton/ietf/rfc/entry_date.rb +21 -0
  317. data/lib/relaton/ietf/rfc/format.rb +19 -0
  318. data/lib/relaton/ietf/rfc/index.rb +46 -0
  319. data/lib/relaton/ietf/rfc/is_also.rb +21 -0
  320. data/lib/relaton/ietf/rfc/keywords.rb +19 -0
  321. data/lib/relaton/ietf/rfc/rfc_index_namespace.rb +11 -0
  322. data/lib/relaton/ietf/scraper.rb +68 -0
  323. data/lib/relaton/ietf/util.rb +8 -0
  324. data/lib/relaton/ietf/wg_name_resolver.rb +42 -0
  325. data/lib/relaton/ietf.rb +27 -0
  326. data/lib/relaton/iho/bibdata.rb +8 -0
  327. data/lib/relaton/iho/bibitem.rb +8 -0
  328. data/lib/relaton/iho/bibliography.rb +114 -0
  329. data/lib/relaton/iho/comment_period.rb +13 -0
  330. data/lib/relaton/iho/docidentifier.rb +31 -0
  331. data/lib/relaton/iho/doctype.rb +10 -0
  332. data/lib/relaton/iho/ext.rb +20 -0
  333. data/lib/relaton/iho/hash_parser_v1.rb +144 -0
  334. data/lib/relaton/iho/item.rb +20 -0
  335. data/lib/relaton/iho/item_base.rb +18 -0
  336. data/lib/relaton/iho/item_data.rb +6 -0
  337. data/lib/relaton/iho/processor.rb +54 -0
  338. data/lib/relaton/iho/relation.rb +9 -0
  339. data/lib/relaton/iho/structured_identifier.rb +20 -0
  340. data/lib/relaton/iho/util.rb +8 -0
  341. data/lib/relaton/iho.rb +27 -0
  342. data/lib/relaton/index/config.rb +52 -0
  343. data/lib/relaton/index/file_io.rb +305 -0
  344. data/lib/relaton/index/file_storage.rb +61 -0
  345. data/lib/relaton/index/id_number.rb +30 -0
  346. data/lib/relaton/index/pool.rb +41 -0
  347. data/lib/relaton/index/type.rb +159 -0
  348. data/lib/relaton/index/util.rb +18 -0
  349. data/lib/relaton/index.rb +60 -0
  350. data/lib/relaton/isbn/isbn.rb +61 -0
  351. data/lib/relaton/isbn/open_library.rb +43 -0
  352. data/lib/relaton/isbn/parser.rb +88 -0
  353. data/lib/relaton/isbn/processor.rb +48 -0
  354. data/lib/relaton/isbn/util.rb +8 -0
  355. data/lib/relaton/isbn.rb +19 -0
  356. data/lib/relaton/iso/bibliography.rb +407 -0
  357. data/lib/relaton/iso/data_fetcher.rb +338 -0
  358. data/lib/relaton/iso/data_parser.rb +444 -0
  359. data/lib/relaton/iso/hash_parser_v1.rb +177 -0
  360. data/lib/relaton/iso/hit.rb +57 -0
  361. data/lib/relaton/iso/hit_collection.rb +184 -0
  362. data/lib/relaton/iso/item_data.rb +28 -0
  363. data/lib/relaton/iso/model/bibdata.rb +10 -0
  364. data/lib/relaton/iso/model/bibitem.rb +8 -0
  365. data/lib/relaton/iso/model/contributor.rb +6 -0
  366. data/lib/relaton/iso/model/contributor_info.rb +9 -0
  367. data/lib/relaton/iso/model/docidentifier.rb +134 -0
  368. data/lib/relaton/iso/model/doctype.rb +13 -0
  369. data/lib/relaton/iso/model/ext.rb +35 -0
  370. data/lib/relaton/iso/model/item.rb +17 -0
  371. data/lib/relaton/iso/model/item_base.rb +22 -0
  372. data/lib/relaton/iso/model/organization.rb +9 -0
  373. data/lib/relaton/iso/model/project_number.rb +22 -0
  374. data/lib/relaton/iso/model/relation.rb +9 -0
  375. data/lib/relaton/iso/model/stagename.rb +14 -0
  376. data/lib/relaton/iso/model/structured_identifier.rb +31 -0
  377. data/lib/relaton/iso/processor.rb +84 -0
  378. data/lib/relaton/iso/scraper.rb +619 -0
  379. data/lib/relaton/iso/type/pubid.rb +50 -0
  380. data/lib/relaton/iso/util.rb +8 -0
  381. data/lib/relaton/iso.rb +30 -0
  382. data/lib/relaton/itu/bibliography.rb +90 -0
  383. data/lib/relaton/itu/data_fetcher.rb +104 -0
  384. data/lib/relaton/itu/data_parser_r.rb +140 -0
  385. data/lib/relaton/itu/hit.rb +22 -0
  386. data/lib/relaton/itu/hit_collection.rb +127 -0
  387. data/lib/relaton/itu/item_data.rb +6 -0
  388. data/lib/relaton/itu/model/approval_stage.rb +13 -0
  389. data/lib/relaton/itu/model/bibdata.rb +8 -0
  390. data/lib/relaton/itu/model/bibitem.rb +8 -0
  391. data/lib/relaton/itu/model/docidentifier.rb +9 -0
  392. data/lib/relaton/itu/model/doctype.rb +13 -0
  393. data/lib/relaton/itu/model/ext.rb +47 -0
  394. data/lib/relaton/itu/model/item.rb +13 -0
  395. data/lib/relaton/itu/model/meeting.rb +13 -0
  396. data/lib/relaton/itu/model/meeting_date.rb +15 -0
  397. data/lib/relaton/itu/model/question.rb +13 -0
  398. data/lib/relaton/itu/model/recommendation_status.rb +11 -0
  399. data/lib/relaton/itu/model/structured_identifier.rb +19 -0
  400. data/lib/relaton/itu/processor.rb +66 -0
  401. data/lib/relaton/itu/pubid.rb +177 -0
  402. data/lib/relaton/itu/radio_regulations_parser.rb +70 -0
  403. data/lib/relaton/itu/recommendation_parser.rb +161 -0
  404. data/lib/relaton/itu/scraper.rb +193 -0
  405. data/lib/relaton/itu/util.rb +8 -0
  406. data/lib/relaton/itu.rb +33 -0
  407. data/lib/relaton/jis/bibdata.rb +8 -0
  408. data/lib/relaton/jis/bibitem.rb +8 -0
  409. data/lib/relaton/jis/bibliography.rb +75 -0
  410. data/lib/relaton/jis/data_fetcher.rb +181 -0
  411. data/lib/relaton/jis/docidentifier.rb +21 -0
  412. data/lib/relaton/jis/doctype.rb +9 -0
  413. data/lib/relaton/jis/ext.rb +13 -0
  414. data/lib/relaton/jis/hit.rb +93 -0
  415. data/lib/relaton/jis/hit_collection.rb +127 -0
  416. data/lib/relaton/jis/item.rb +22 -0
  417. data/lib/relaton/jis/item_base.rb +26 -0
  418. data/lib/relaton/jis/item_data.rb +8 -0
  419. data/lib/relaton/jis/processor.rb +55 -0
  420. data/lib/relaton/jis/relation.rb +11 -0
  421. data/lib/relaton/jis/scraper.rb +232 -0
  422. data/lib/relaton/jis/structured_identifier.rb +13 -0
  423. data/lib/relaton/jis/util.rb +8 -0
  424. data/lib/relaton/jis.rb +33 -0
  425. data/lib/relaton/logger/channels/gh_issue.rb +78 -0
  426. data/lib/relaton/logger/config.rb +34 -0
  427. data/lib/relaton/logger/formatter_json.rb +8 -0
  428. data/lib/relaton/logger/formatter_string.rb +12 -0
  429. data/lib/relaton/logger/log.rb +64 -0
  430. data/lib/relaton/logger/log_device.rb +27 -0
  431. data/lib/relaton/logger/pool.rb +24 -0
  432. data/lib/relaton/logger.rb +18 -0
  433. data/lib/relaton/nist/bibdata.rb +8 -0
  434. data/lib/relaton/nist/bibitem.rb +8 -0
  435. data/lib/relaton/nist/bibliography.rb +191 -0
  436. data/lib/relaton/nist/comment_period.rb +15 -0
  437. data/lib/relaton/nist/data_fetcher.rb +84 -0
  438. data/lib/relaton/nist/date.rb +7 -0
  439. data/lib/relaton/nist/doctype.rb +7 -0
  440. data/lib/relaton/nist/ext.rb +16 -0
  441. data/lib/relaton/nist/hit.rb +18 -0
  442. data/lib/relaton/nist/hit_collection.rb +362 -0
  443. data/lib/relaton/nist/item.rb +17 -0
  444. data/lib/relaton/nist/item_data.rb +6 -0
  445. data/lib/relaton/nist/mods_parser.rb +276 -0
  446. data/lib/relaton/nist/processor.rb +68 -0
  447. data/lib/relaton/nist/pubs_export.rb +69 -0
  448. data/lib/relaton/nist/relation.rb +7 -0
  449. data/lib/relaton/nist/scraper.rb +290 -0
  450. data/lib/relaton/nist/series.yaml +49 -0
  451. data/lib/relaton/nist/util.rb +8 -0
  452. data/lib/relaton/nist.rb +34 -0
  453. data/lib/relaton/oasis/bibdata.rb +8 -0
  454. data/lib/relaton/oasis/bibitem.rb +8 -0
  455. data/lib/relaton/oasis/bibliography.rb +60 -0
  456. data/lib/relaton/oasis/browser_agent.rb +71 -0
  457. data/lib/relaton/oasis/data_fetcher.rb +94 -0
  458. data/lib/relaton/oasis/data_parser.rb +305 -0
  459. data/lib/relaton/oasis/data_parser_utils.rb +296 -0
  460. data/lib/relaton/oasis/data_part_parser.rb +239 -0
  461. data/lib/relaton/oasis/doctype.rb +7 -0
  462. data/lib/relaton/oasis/ext.rb +19 -0
  463. data/lib/relaton/oasis/item.rb +11 -0
  464. data/lib/relaton/oasis/item_data.rb +6 -0
  465. data/lib/relaton/oasis/processor.rb +68 -0
  466. data/lib/relaton/oasis/util.rb +8 -0
  467. data/lib/relaton/oasis.rb +28 -0
  468. data/lib/relaton/ogc/bibdata.rb +8 -0
  469. data/lib/relaton/ogc/bibitem.rb +8 -0
  470. data/lib/relaton/ogc/bibliography.rb +64 -0
  471. data/lib/relaton/ogc/data_fetcher.rb +110 -0
  472. data/lib/relaton/ogc/docidentifier.rb +6 -0
  473. data/lib/relaton/ogc/doctype.rb +12 -0
  474. data/lib/relaton/ogc/ext.rb +15 -0
  475. data/lib/relaton/ogc/hit.rb +18 -0
  476. data/lib/relaton/ogc/hit_collection.rb +36 -0
  477. data/lib/relaton/ogc/item.rb +13 -0
  478. data/lib/relaton/ogc/item_data.rb +6 -0
  479. data/lib/relaton/ogc/processor.rb +58 -0
  480. data/lib/relaton/ogc/scraper.rb +225 -0
  481. data/lib/relaton/ogc/util.rb +8 -0
  482. data/lib/relaton/ogc.rb +26 -0
  483. data/lib/relaton/oiml/bibdata.rb +8 -0
  484. data/lib/relaton/oiml/bibitem.rb +8 -0
  485. data/lib/relaton/oiml/bibliography.rb +94 -0
  486. data/lib/relaton/oiml/docidentifier.rb +33 -0
  487. data/lib/relaton/oiml/doctype.rb +13 -0
  488. data/lib/relaton/oiml/ext.rb +42 -0
  489. data/lib/relaton/oiml/item.rb +20 -0
  490. data/lib/relaton/oiml/item_base.rb +18 -0
  491. data/lib/relaton/oiml/item_data.rb +6 -0
  492. data/lib/relaton/oiml/processor.rb +54 -0
  493. data/lib/relaton/oiml/relation.rb +9 -0
  494. data/lib/relaton/oiml/util.rb +8 -0
  495. data/lib/relaton/oiml.rb +24 -0
  496. data/lib/relaton/omg/bibdata.rb +8 -0
  497. data/lib/relaton/omg/bibitem.rb +8 -0
  498. data/lib/relaton/omg/bibliography.rb +31 -0
  499. data/lib/relaton/omg/ext.rb +7 -0
  500. data/lib/relaton/omg/item.rb +8 -0
  501. data/lib/relaton/omg/item_data.rb +6 -0
  502. data/lib/relaton/omg/processor.rb +34 -0
  503. data/lib/relaton/omg/scraper.rb +141 -0
  504. data/lib/relaton/omg/util.rb +8 -0
  505. data/lib/relaton/omg.rb +24 -0
  506. data/lib/relaton/plateau/bibdata.rb +8 -0
  507. data/lib/relaton/plateau/bibitem.rb +8 -0
  508. data/lib/relaton/plateau/bibliography.rb +24 -0
  509. data/lib/relaton/plateau/data_fetcher.rb +153 -0
  510. data/lib/relaton/plateau/doctype.rb +7 -0
  511. data/lib/relaton/plateau/ext.rb +23 -0
  512. data/lib/relaton/plateau/handbook_parser.rb +95 -0
  513. data/lib/relaton/plateau/hit.rb +13 -0
  514. data/lib/relaton/plateau/hit_collection.rb +59 -0
  515. data/lib/relaton/plateau/item.rb +12 -0
  516. data/lib/relaton/plateau/item_data.rb +6 -0
  517. data/lib/relaton/plateau/parser.rb +101 -0
  518. data/lib/relaton/plateau/processor.rb +49 -0
  519. data/lib/relaton/plateau/technical_report_parser.rb +91 -0
  520. data/lib/relaton/plateau/util.rb +8 -0
  521. data/lib/relaton/plateau.rb +28 -0
  522. data/lib/relaton/un/bibdata.rb +8 -0
  523. data/lib/relaton/un/bibitem.rb +8 -0
  524. data/lib/relaton/un/bibliography.rb +48 -0
  525. data/lib/relaton/un/doctype.rb +10 -0
  526. data/lib/relaton/un/ext.rb +30 -0
  527. data/lib/relaton/un/hit.rb +56 -0
  528. data/lib/relaton/un/hit_collection.rb +61 -0
  529. data/lib/relaton/un/item.rb +11 -0
  530. data/lib/relaton/un/item_data.rb +6 -0
  531. data/lib/relaton/un/parser.rb +108 -0
  532. data/lib/relaton/un/processor.rb +38 -0
  533. data/lib/relaton/un/session.rb +25 -0
  534. data/lib/relaton/un/token_generator.rb +105 -0
  535. data/lib/relaton/un/util.rb +8 -0
  536. data/lib/relaton/un/wasm/decoder.rb +434 -0
  537. data/lib/relaton/un/wasm/instance.rb +101 -0
  538. data/lib/relaton/un/wasm/interpreter.rb +613 -0
  539. data/lib/relaton/un/wasm/memory.rb +112 -0
  540. data/lib/relaton/un/wasm/module.rb +47 -0
  541. data/lib/relaton/un/wasm.rb +17 -0
  542. data/lib/relaton/un/wasm_v_bg.wasm +0 -0
  543. data/lib/relaton/un.rb +28 -0
  544. data/lib/relaton/version.rb +1 -1
  545. data/lib/relaton/w3c/bibdata.rb +8 -0
  546. data/lib/relaton/w3c/bibitem.rb +8 -0
  547. data/lib/relaton/w3c/bibliography.rb +54 -0
  548. data/lib/relaton/w3c/data_fetcher.rb +309 -0
  549. data/lib/relaton/w3c/data_parser.rb +379 -0
  550. data/lib/relaton/w3c/doctype.rb +7 -0
  551. data/lib/relaton/w3c/ext.rb +11 -0
  552. data/lib/relaton/w3c/item.rb +12 -0
  553. data/lib/relaton/w3c/item_data.rb +6 -0
  554. data/lib/relaton/w3c/processor.rb +49 -0
  555. data/lib/relaton/w3c/pubid.rb +73 -0
  556. data/lib/relaton/w3c/safe_realize.rb +59 -0
  557. data/lib/relaton/w3c/util.rb +8 -0
  558. data/lib/relaton/w3c.rb +25 -0
  559. data/lib/relaton/xsf/bibdata.rb +8 -0
  560. data/lib/relaton/xsf/bibitem.rb +8 -0
  561. data/lib/relaton/xsf/bibliography.rb +24 -0
  562. data/lib/relaton/xsf/data_fetcher.rb +56 -0
  563. data/lib/relaton/xsf/hit.rb +17 -0
  564. data/lib/relaton/xsf/hit_collection.rb +24 -0
  565. data/lib/relaton/xsf/item.rb +7 -0
  566. data/lib/relaton/xsf/item_data.rb +6 -0
  567. data/lib/relaton/xsf/processor.rb +50 -0
  568. data/lib/relaton/xsf/util.rb +9 -0
  569. data/lib/relaton/xsf.rb +30 -0
  570. data/lib/relaton-core.rb +1 -0
  571. data/lib/relaton.rb +44 -9
  572. metadata +708 -150
  573. data/.github/workflows/rake.yml +0 -14
  574. data/.github/workflows/release.yml +0 -24
  575. data/.github/workflows/rubocop.yml +0 -48
  576. data/.gitignore +0 -12
  577. data/.rspec +0 -3
  578. data/.rubocop.yml +0 -12
  579. data/CLAUDE.md +0 -70
  580. data/Gemfile +0 -21
  581. data/Rakefile +0 -6
  582. data/docs/CHANGELOG.adoc +0 -16
  583. data/docs/VERSIONING_POLICY.adoc +0 -38
  584. data/docs/navigation.adoc +0 -6
  585. data/lib/relaton/config.rb +0 -24
  586. data/lib/relaton/db_cache.rb +0 -230
  587. data/lib/relaton/registry.rb +0 -118
  588. data/lib/relaton/util.rb +0 -7
  589. data/lib/relaton/workers_pool.rb +0 -21
  590. data/relaton.gemspec +0 -61
  591. data/spec/relaton/config_spec.rb +0 -10
  592. data/spec/relaton/db_cache_spec.rb +0 -51
  593. data/spec/relaton/db_spec.rb +0 -556
  594. data/spec/relaton/registry_spec.rb +0 -178
  595. data/spec/relaton/util_spec.rb +0 -3
  596. data/spec/relaton_spec.rb +0 -725
  597. data/spec/spec_helper.rb +0 -45
  598. data/spec/support/gb_t_20223_2006.xml +0 -33
  599. data/spec/support/iso_111111119115_1.xml +0 -0
  600. data/spec/support/iso_19115_1.xml +0 -115
  601. data/spec/support/iso_19115_2.xml +0 -95
  602. data/spec/support/rfc_8341.xml +0 -46
  603. data/spec/vcr_cassetes/3gpp_tr_00_01u_umts_3_0_0.yml +0 -12720
  604. data/spec/vcr_cassetes/api_relaton_org.yml +0 -121
  605. data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +0 -143
  606. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +0 -199
  607. data/spec/vcr_cassetes/cie_001_1980.yml +0 -401
  608. data/spec/vcr_cassetes/cipm_meeting_43.yml +0 -1513
  609. data/spec/vcr_cassetes/doi_10_6028_nist_ir_8245.yml +0 -86
  610. data/spec/vcr_cassetes/ecma_6.yml +0 -112
  611. data/spec/vcr_cassetes/en_10160_1999.yml +0 -13624
  612. data/spec/vcr_cassetes/gb_t_20223_2006.yml +0 -733
  613. data/spec/vcr_cassetes/ieee_528_2019.yml +0 -2786
  614. data/spec/vcr_cassetes/iso_111111119115_1.yml +0 -12951
  615. data/spec/vcr_cassetes/iso_19115_1.yml +0 -13177
  616. data/spec/vcr_cassetes/iso_19115_1_2.yml +0 -369
  617. data/spec/vcr_cassetes/iso_19115_1_std.yml +0 -13177
  618. data/spec/vcr_cassetes/iso_19115_all_parts.yml +0 -229
  619. data/spec/vcr_cassetes/iso_19133_2005.yml +0 -148
  620. data/spec/vcr_cassetes/iso_combined_applied.yml +0 -364
  621. data/spec/vcr_cassetes/iso_combined_included.yml +0 -364
  622. data/spec/vcr_cassetes/iso_dis.yml +0 -157
  623. data/spec/vcr_cassetes/ogc_19_025r1.yml +0 -371
  624. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +0 -317
  625. data/spec/vcr_cassetes/rfc_8341.yml +0 -1272
@@ -0,0 +1,94 @@
1
+ require_relative "../oasis"
2
+ require_relative "browser_agent"
3
+ require_relative "data_parser_utils"
4
+ require_relative "data_parser"
5
+ require_relative "data_part_parser"
6
+
7
+ module Relaton
8
+ module Oasis
9
+ class DataFetcher < Core::DataFetcher
10
+ STANDARDS_URL = "https://www.oasis-open.org/standards/".freeze
11
+ RETRIABLE_ERRORS = [
12
+ SocketError,
13
+ Ferrum::TimeoutError,
14
+ Ferrum::PendingConnectionsError,
15
+ Ferrum::StatusError,
16
+ ].freeze
17
+
18
+ def log_error(msg)
19
+ Util.error msg
20
+ end
21
+
22
+ def fetch(_source = nil)
23
+ doc = with_retry { agent.get(STANDARDS_URL) }
24
+ doc.xpath("//details").map do |item|
25
+ save_doc DataParser.new(item, @errors, agent: agent).parse
26
+ fetch_parts item
27
+ end
28
+ index.save
29
+ report_errors
30
+ ensure
31
+ @agent&.quit
32
+ end
33
+
34
+ private
35
+
36
+ def agent
37
+ @agent ||= BrowserAgent.new
38
+ end
39
+
40
+ def with_retry
41
+ tries = 0
42
+ begin
43
+ tries += 1
44
+ yield
45
+ rescue *RETRIABLE_ERRORS => e
46
+ retry if tries < 4
47
+ raise e
48
+ end
49
+ end
50
+
51
+ def index
52
+ @index ||= Relaton::Index.find_or_create(
53
+ :oasis, file: "#{INDEXFILE}.yaml"
54
+ )
55
+ end
56
+
57
+ def fetch_parts(item)
58
+ xpath = "./div/div/div[contains(@class, " \
59
+ "'standard__grid--cite-as')]" \
60
+ "/p[strong or span/strong]"
61
+ parts = item.xpath(xpath)
62
+ return unless parts.size > 1
63
+
64
+ parts.each do |part|
65
+ save_doc DataPartParser.new(part, @errors, agent: agent).parse
66
+ end
67
+ end
68
+
69
+ def save_doc(doc) # rubocop:disable Metrics/AbcSize
70
+ id = doc.docidentifier.find(&:primary) || doc.docidentifier.first
71
+ file = output_file(id.content)
72
+ if @files.include? file
73
+ Util.warn "File #{file} already exists. Document: #{id.content}"
74
+ else
75
+ @files << file
76
+ end
77
+ index.add_or_update id.content, file
78
+ File.write file, serialize(doc), encoding: "UTF-8"
79
+ end
80
+
81
+ def to_xml(bib)
82
+ bib.to_xml(bibdata: true)
83
+ end
84
+
85
+ def to_yaml(bib)
86
+ bib.to_yaml
87
+ end
88
+
89
+ def to_bibxml(bib)
90
+ bib.to_rfcxml
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,305 @@
1
+ module Relaton
2
+ module Oasis
3
+ # Parser for OASIS document.
4
+ class DataParser
5
+ include DataParserUtils
6
+
7
+ #
8
+ # Initialize parser.
9
+ #
10
+ # @param [Nokogiri::HTML::Element] node document node
11
+ #
12
+ def initialize(node, errors = {}, agent: nil)
13
+ @node = node
14
+ @errors = errors
15
+ @agent = agent
16
+ end
17
+
18
+ def title
19
+ @title ||= @node.at("./summary/div/h2").text
20
+ end
21
+
22
+ def text
23
+ xpath = "./div/div/div[contains(@class, " \
24
+ "'standard__grid--cite-as')]" \
25
+ "/p[em or i or a or span]"
26
+ @text ||= @node.at(xpath)&.text&.strip
27
+ end
28
+
29
+ #
30
+ # Parse document.
31
+ #
32
+ # @return [ItemData] bibliographic item data
33
+ #
34
+ def parse # rubocop:disable Metrics/MethodLength
35
+ ItemData.new(
36
+ type: "standard",
37
+ title: parse_title,
38
+ docidentifier: parse_docid,
39
+ source: parse_link,
40
+ docnumber: parse_docnumber,
41
+ date: parse_date,
42
+ contributor: parse_contributor,
43
+ abstract: parse_abstract,
44
+ language: ["en"],
45
+ script: ["Latn"],
46
+ relation: parse_relation,
47
+ ext: create_ext,
48
+ )
49
+ end
50
+
51
+ #
52
+ # Parse title.
53
+ #
54
+ # @return [Array<Bib::Title>] title
55
+ #
56
+ def parse_title
57
+ result = [Bib::Title.new(type: "main", content: title, language: "en",
58
+ script: "Latn")]
59
+ @errors[:title] &&= result.empty?
60
+ result
61
+ end
62
+
63
+ #
64
+ # Parse date.
65
+ #
66
+ # @return [Array<Bib::Date>] date
67
+ #
68
+ def parse_date
69
+ xpath = "./summary/div/time[@class='standard__date']"
70
+ result = @node.xpath(xpath).map do |d|
71
+ date_str = d.text.match(/\d{2}\s\w+\s\d{4}/).to_s
72
+ date = Date.parse(date_str).to_s
73
+ Bib::Date.new(at: date, type: "issued")
74
+ end
75
+ @errors[:date] &&= result.empty?
76
+ result
77
+ end
78
+
79
+ #
80
+ # Parse abstract.
81
+ #
82
+ # @return [Array<Bib::LocalizedMarkedUpString>] abstract
83
+ #
84
+ def parse_abstract
85
+ c = @node.xpath(
86
+ "./summary/div/div[@class='standard__description']/p",
87
+ ).map { |a| a.text.gsub(/[\n\t]+/, " ").strip }.join("\n")
88
+ result = if c.empty?
89
+ []
90
+ else
91
+ [Bib::Abstract.new(
92
+ content: c, language: "en", script: "Latn",
93
+ )]
94
+ end
95
+ @errors[:abstract] &&= result.empty?
96
+ result
97
+ end
98
+
99
+ #
100
+ # Parse editorial group as contributors.
101
+ #
102
+ # @return [Array<Bib::Contributor>] editorial group contributors
103
+ #
104
+ def parse_editorialgroup_contributor # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
105
+ tcs = @node.xpath("./div[@class='standard__details']/a")
106
+ if tcs.empty?
107
+ result = []
108
+ else
109
+ subdivisions = tcs.map do |a|
110
+ name = [Bib::TypedLocalizedString.new(content: a.text.strip)]
111
+ Bib::Subdivision.new(type: "technical-committee",
112
+ name: name)
113
+ end
114
+ org = Bib::Organization.new(
115
+ name: [Bib::TypedLocalizedString.new(content: "OASIS")],
116
+ subdivision: subdivisions,
117
+ )
118
+ desc = [Bib::LocalizedMarkedUpString.new(content: "committee")]
119
+ role = Bib::Contributor::Role.new(
120
+ type: "author", description: desc,
121
+ )
122
+ result = [Bib::Contributor.new(organization: org, role: [role])]
123
+ end
124
+ @errors[:editorialgroup_contributor] &&= result.empty?
125
+ result
126
+ end
127
+
128
+ def parse_authorizer # rubocop:disable Metrics/MethodLength
129
+ result = @node.xpath("./div[@class='standard__details']/a").map do |a|
130
+ org = Bib::Organization.new(
131
+ name: [Bib::TypedLocalizedString.new(content: a.text.strip)],
132
+ uri: [Bib::Uri.new(type: "uri", content: a[:href])],
133
+ )
134
+ desc = [Bib::LocalizedMarkedUpString.new(content: "Committee")]
135
+ role = Bib::Contributor::Role.new(type: "authorizer",
136
+ description: desc)
137
+ Bib::Contributor.new(organization: org, role: [role])
138
+ end
139
+ @errors[:authorizer] &&= result.empty?
140
+ result
141
+ end
142
+
143
+ def link_node
144
+ xpath = "./div/div/div[contains(@class, " \
145
+ "'standard__grid--cite-as')]" \
146
+ "/p[strong or span/strong]/a"
147
+ @link_node ||= @node.at(xpath)
148
+ end
149
+
150
+ #
151
+ # Parse relation.
152
+ #
153
+ # @return [Array<Bib::Relation>] relation
154
+ #
155
+ def parse_relation # rubocop:disable Metrics/MethodLength
156
+ xpath = "./div/div/div[contains(@class, " \
157
+ "'standard__grid--cite-as')]" \
158
+ "/p[strong or span/strong or b/span]"
159
+ rels = @node.xpath(xpath)
160
+ result = if rels.size > 1
161
+ rels.map do |r|
162
+ docid = DataPartParser.new(r, @errors, agent: @agent).parse_docid
163
+ bib = ItemData.new(formattedref: Bib::Formattedref.new(content: docid[0].content))
164
+ Bib::Relation.new(type: "hasPart", bibitem: bib)
165
+ end
166
+ else
167
+ []
168
+ end
169
+ @errors[:relation] &&= result.empty?
170
+ result
171
+ end
172
+
173
+ #
174
+ # Look for "Cite as" references.
175
+ #
176
+ # @return [Array<String>] document part references
177
+ #
178
+ def document_part_refs
179
+ @node.css(
180
+ ".standard__grid--cite-as > p > strong",
181
+ "span.Refterm", "span.abbrev", "span.citationLabel > strong"
182
+ ).map { |p| p.text.gsub(/^\[{1,2}|\]$/, "").strip }
183
+ end
184
+
185
+ def parse_link # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
186
+ result = if parts.size > 1
187
+ []
188
+ else
189
+ links.map do |l|
190
+ type = l[:href].match(/\.(\w+)$/)&.captures&.first
191
+ type ||= "src"
192
+ type.sub!("docx", "doc")
193
+ type.sub!("html", "src")
194
+ Bib::Uri.new(type: type, content: l[:href])
195
+ end
196
+ end
197
+ @errors[:link] &&= result.empty?
198
+ result
199
+ end
200
+
201
+ def parts
202
+ xpath = "./div/div/div[contains(@class, " \
203
+ "'standard__grid--cite-as')]" \
204
+ "/p[strong or span/strong]"
205
+ @parts ||= @node.xpath(xpath)
206
+ end
207
+
208
+ def links
209
+ l = @node.xpath("./div/div/div[1]/p[1]/a[@href]")
210
+ l = @node.xpath("./div/div/div[1]/p[2]/a[@href]") if l.empty?
211
+ l
212
+ end
213
+
214
+ #
215
+ # Parse document number.
216
+ #
217
+ # @return [String] document number
218
+ #
219
+ def parse_docnumber
220
+ parts = document_part_refs
221
+ result = case parts.size
222
+ when 0
223
+ txt = @node.at("./summary/div/h2").text
224
+ parse_spec title_to_docid(txt)
225
+ when 1 then parse_part parse_spec(parts[0])
226
+ else parts_to_docid parts
227
+ end
228
+ @errors[:docnumber] &&= result.nil?
229
+ result
230
+ end
231
+
232
+ #
233
+ # Create document identifier from parts references.
234
+ #
235
+ # @param [Array<String>] parts parts references
236
+ #
237
+ # @return [String] document identifier
238
+ #
239
+ def parts_to_docid(parts) # rubocop:disable Metrics/AbcSize
240
+ id = parts[1..].each_with_object(parts[0].split("-")) do |part, acc|
241
+ chunks = part.split "-"
242
+ chunks.each.with_index do |chunk, idx|
243
+ unless chunk.casecmp(acc[idx])&.zero?
244
+ acc.slice!(idx..-1)
245
+ break
246
+ end
247
+ end
248
+ end.join("-")
249
+ parse_part parse_spec(id)
250
+ end
251
+
252
+ #
253
+ # Create document identifier from title.
254
+ #
255
+ # @param [String] title title
256
+ #
257
+ # @return [String] document identifier
258
+ #
259
+ def title_to_docid(title) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
260
+ abbrs = title.scan(/(?<=\()[^)]+(?=\))/)
261
+ if abbrs.any?
262
+ id = abbrs.map { |abbr| abbr.split.join("-") }.join "-"
263
+ /(?:Version\s|v)(?<ver>[\d.]+)/ =~ title
264
+ id += "-v#{ver}" if ver
265
+ /(?<eb>ebXML|ebMS)/ =~ title
266
+ id = "#{eb}-#{id}" if eb
267
+ id
268
+ else
269
+ series_end = false
270
+ title.sub(/\s\[OASIS\s\d+\]$/,
271
+ "").split(/[,:]?\s|-|(?<=[a-z])(?=[A-Z][a-z])/)
272
+ .each_with_object([""]) do |word, acc|
273
+ if word =~ /^v[\d.]+/
274
+ acc << $MATCH.to_s
275
+ series_end = true
276
+ elsif word.match?(/^Version/)
277
+ acc << "v"
278
+ series_end = false
279
+ elsif word.match?(/^\d|ebXML|ebMS/)
280
+ series_end ? acc << word : acc[-1] += word
281
+ series_end = true
282
+ elsif word.match?(/^\w+$/) && word == word.upcase
283
+ series_end ? acc << word : acc[-1] = word
284
+ series_end = true
285
+ elsif word.match?(/[A-Z]+[a-z]+/)
286
+ series_end ? acc << word[0] : acc[-1] += word[0]
287
+ series_end = false
288
+ end
289
+ end.join "-"
290
+ end
291
+ end
292
+
293
+ #
294
+ # Parse technology areas.
295
+ #
296
+ # @return [Array<String>] technology areas
297
+ #
298
+ def parse_technology_area
299
+ result = super(@node)
300
+ @errors[:technology_area] &&= result.empty?
301
+ result
302
+ end
303
+ end
304
+ end
305
+ end
@@ -0,0 +1,296 @@
1
+ require "mechanize"
2
+ require_relative "browser_agent"
3
+
4
+ module Relaton
5
+ module Oasis
6
+ # Common methods for document and part parsers.
7
+ module DataParserUtils
8
+ RETRIABLE_PAGE_ERRORS = [
9
+ Errno::ETIMEDOUT,
10
+ Net::OpenTimeout,
11
+ Ferrum::TimeoutError,
12
+ Ferrum::PendingConnectionsError,
13
+ Ferrum::StatusError,
14
+ ].freeze
15
+ #
16
+ # Parse contributor.
17
+ #
18
+ # @return [Array<Bib::Contributor>] contributors
19
+ #
20
+ def parse_contributor
21
+ result = publisher_oasis + parse_authorizer +
22
+ parse_editorialgroup_contributor +
23
+ parse_chairs + parse_editors
24
+ @errors[:contributor] &&= result.empty?
25
+ result
26
+ end
27
+
28
+ def publisher_oasis
29
+ org = Bib::Organization.new(
30
+ name: [Bib::TypedLocalizedString.new(content: "OASIS")],
31
+ uri: [Bib::Uri.new(type: "uri", content: "https://www.oasis-open.org/")],
32
+ )
33
+ role = [
34
+ Bib::Contributor::Role.new(
35
+ type: "authorizer",
36
+ description: [Bib::LocalizedMarkedUpString.new(
37
+ content: "Standards Development Organization",
38
+ )],
39
+ ),
40
+ Bib::Contributor::Role.new(type: "publisher"),
41
+ ]
42
+ [Bib::Contributor.new(organization: org, role: role)]
43
+ end
44
+
45
+ def parse_editors_from_text # rubocop:disable Metrics/MethodLength
46
+ result = if text
47
+ text.match(/(?<=Edited\sby\s)[^.]+/).to_s
48
+ .split(/,?\sand\s|,\s/).map do |c|
49
+ role = [Bib::Contributor::Role.new(type: "editor")]
50
+ Bib::Contributor.new(role: role,
51
+ person: create_person(c))
52
+ end
53
+ else
54
+ []
55
+ end
56
+ @errors[:editors] &&= result.empty?
57
+ result
58
+ end
59
+
60
+ def page
61
+ return @page if defined? @page
62
+
63
+ @page = nil
64
+ return @page unless link_node && link_node[:href].match?(/\.html$/)
65
+
66
+ if @agent
67
+ doc = retry_page(link_node[:href], @agent)
68
+ @page = doc if doc && @agent.last_status == 200
69
+ else
70
+ # No injected agent (e.g. unit tests with VCR cassettes): fall back
71
+ # to a Mechanize request — VCR can intercept it.
72
+ agent = Mechanize.new
73
+ agent.agent.allowed_error_codes = [403, 404, 503]
74
+ resp = retry_page(link_node[:href], agent)
75
+ @page = resp if resp && resp.code == "200"
76
+ end
77
+ end
78
+
79
+ #
80
+ # Retry to get page.
81
+ #
82
+ # @param [String] url page URL
83
+ # @param [#get] agent HTTP client responding to #get(url)
84
+ # @param [Integer] retries number of retries
85
+ #
86
+ # @return [Nokogiri::HTML::Document, Mechanize::Page, nil] page or nil
87
+ #
88
+ def retry_page(url, agent, retries = 3)
89
+ sleep 1 # to avoid 429 error
90
+ agent.get url
91
+ rescue *RETRIABLE_PAGE_ERRORS => e
92
+ retry if (retries -= 1).positive?
93
+ Util.error "Failed to get page `#{url}`\n#{e.message}"
94
+ nil
95
+ end
96
+
97
+ def parse_chairs # rubocop:disable Metrics/MethodLength
98
+ result = if page
99
+ xpath = "//p[preceding-sibling::p" \
100
+ "[starts-with(., 'Chair')]]" \
101
+ "[following-sibling::p" \
102
+ "[starts-with(., 'Editor')]]"
103
+ page.xpath(xpath).map do |p|
104
+ create_contribution_info(p, "editor", ["Chair"])
105
+ end.compact
106
+ else
107
+ []
108
+ end
109
+ @errors[:chairs] &&= result.empty?
110
+ result
111
+ end
112
+
113
+ def parse_editors # rubocop:disable Metrics/MethodLength
114
+ result = if page
115
+ xpath = "//p[contains(@class, 'Contributor')]" \
116
+ "[preceding-sibling::p" \
117
+ "[starts-with(., 'Editor')]]" \
118
+ "[following-sibling::p" \
119
+ "[contains(@class, 'Title')]]"
120
+ page.xpath(xpath).map do |p|
121
+ create_contribution_info(p, "editor")
122
+ end.compact
123
+ else
124
+ parse_editors_from_text
125
+ end
126
+ @errors[:editors] &&= result.empty?
127
+ result
128
+ end
129
+
130
+ def create_contribution_info(person_node, type, description = [])
131
+ name = person_node.text.match(/^[^(]+/).to_s.strip
132
+ return nil if name.empty? || !name.match?(/\A\p{L}/) ||
133
+ name.match?(%r{\A(?:https?://|urn:)})
134
+
135
+ email, org = person_node.xpath ".//a[@href]"
136
+ entity = create_person name, email, org
137
+ desc = description.map { |d| Bib::LocalizedMarkedUpString.new(content: d) }
138
+ role = Bib::Contributor::Role.new(type: type, description: desc)
139
+ Bib::Contributor.new(role: [role], person: entity)
140
+ end
141
+
142
+ def create_person(name, email = nil, org = nil)
143
+ forename, surname = name.split
144
+ fn = Bib::FullNameType::Forename.new(content: forename, language: "en",
145
+ script: "Latn")
146
+ sn = Bib::LocalizedString.new(content: surname, language: "en",
147
+ script: "Latn")
148
+ fullname = Bib::FullName.new(surname: sn, forename: [fn])
149
+ Bib::Person.new(name: fullname, email: person_email(email),
150
+ affiliation: person_affiliation(org))
151
+ end
152
+
153
+ def person_email(email)
154
+ return [] unless email
155
+
156
+ href = email[:href]
157
+ if href.start_with?("mailto:")
158
+ [href.split(":")[1]]
159
+ elsif (cf_email = email.at(".//span[@data-cfemail]"))
160
+ decoded = decode_cf_email(cf_email["data-cfemail"])
161
+ return [] if decoded.empty?
162
+
163
+ # Cloudflare obfuscates ASCII email characters in the data-cfemail
164
+ # span but leaves non-ASCII characters (e.g. the Latin "fl" ligature
165
+ # U+FB02) as plain text outside the span. Concatenate any sibling
166
+ # text and NFKC-normalize so ligatures become their ASCII equivalent.
167
+ prefix = cf_email.xpath("./preceding-sibling::node()").map(&:text).join
168
+ suffix = cf_email.xpath("./following-sibling::node()").map(&:text).join
169
+ [(prefix + decoded + suffix).unicode_normalize(:nfkc)]
170
+ else
171
+ []
172
+ end
173
+ end
174
+
175
+ def decode_cf_email(encoded)
176
+ bytes = [encoded].pack("H*").bytes
177
+ key = bytes.first
178
+ bytes[1..].map { |b| (b ^ key).chr }.join
179
+ end
180
+
181
+ def person_affiliation(org)
182
+ return [] unless org
183
+
184
+ org_name = org.text.gsub(/[\r\n]+/, " ")
185
+ organization = Bib::Organization.new(
186
+ name: [Bib::TypedLocalizedString.new(content: org_name)],
187
+ uri: [Bib::Uri.new(type: "uri", content: org[:href])],
188
+ )
189
+ [Bib::Affiliation.new(organization: organization)]
190
+ end
191
+
192
+ #
193
+ # Parse document identifier specification.
194
+ #
195
+ # @param [String] num document number
196
+ #
197
+ # @return [String] document identifier with specification if needed
198
+ #
199
+ def parse_spec(num)
200
+ case text
201
+ when /OASIS Project Specification (\d+)/ then "#{num}-PS#{$1}"
202
+ when /Committee Specification (\d+)/ then "#{num}-CS#{$1}"
203
+ else num
204
+ end
205
+ end
206
+
207
+ #
208
+ # Parse document identifier part.
209
+ #
210
+ # @param [String] docid document identifier
211
+ #
212
+ # @return [String] document identifier with part if needed
213
+ #
214
+ def parse_part(docid)
215
+ return docid if docid.match?(/(?:Part|Pt)\d+/i)
216
+
217
+ case title
218
+ when /Part\s(\d+)/ then "#{docid}-Pt#{$1}"
219
+ else docid
220
+ end
221
+ end
222
+
223
+ #
224
+ # Parse document identifier errata.
225
+ #
226
+ # @param [String] id document identifier
227
+ #
228
+ # @return [String] document identifier with errata if needed
229
+ #
230
+ def parse_errata(id)
231
+ return id.sub("errata", "Errata") if id.match?(/errata\d+/i)
232
+
233
+ case title
234
+ when /Plus\sErrata\s(\d+)/ then "#{id}-plus-Errata#{$1}"
235
+ when /Errata\s(\d+)/ then "#{id}-Errata#{$1}"
236
+ else id
237
+ end
238
+ end
239
+
240
+ #
241
+ # Parse document identifier.
242
+ #
243
+ # @return [Array<Bib::Docidentifier>] document identifier
244
+ #
245
+ def parse_docid
246
+ id = "OASIS #{parse_docnumber}"
247
+ result = [Bib::Docidentifier.new(type: "OASIS", content: id,
248
+ primary: true)]
249
+ @errors[:docid] &&= result.empty?
250
+ result
251
+ end
252
+
253
+ #
254
+ # Parse document type.
255
+ #
256
+ # @return [Doctype] document type
257
+ #
258
+ def parse_doctype
259
+ type = case text
260
+ when /OASIS Project Specification/, /Committee Specification/
261
+ "specification"
262
+ when /Technical Memorandum/ then "memorandum"
263
+ when /Technical Resolution/ then "resolution"
264
+ else "standard"
265
+ end
266
+ result = Doctype.new(content: type)
267
+ @errors[:doctype] &&= result.nil?
268
+ result
269
+ end
270
+
271
+ #
272
+ # Parse technology area.
273
+ #
274
+ # @return [Array<String>] technology areas
275
+ #
276
+ def parse_technology_area(node)
277
+ xpath = "./summary/div/div" \
278
+ "/ul[@class='technology-areas__list']/li/a"
279
+ result = node.xpath(xpath).map do |ta|
280
+ ta.text.strip.gsub(/\s/, "-")
281
+ .sub("development", "Development")
282
+ end
283
+ @errors[:technology_area] &&= result.empty?
284
+ result
285
+ end
286
+
287
+ def create_ext
288
+ Ext.new(
289
+ doctype: parse_doctype,
290
+ flavor: "oasis",
291
+ technology_area: parse_technology_area,
292
+ )
293
+ end
294
+ end
295
+ end
296
+ end