relaton 2.2.0.pre.alpha.1 → 3.0.0.pre.alpha.2

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 (702) hide show
  1. checksums.yaml +4 -4
  2. data/{docs/README.adoc → README.adoc} +165 -38
  3. data/bin/console +0 -1
  4. data/lib/relaton/3gpp/bibdata.rb +9 -0
  5. data/lib/relaton/3gpp/bibitem.rb +9 -0
  6. data/lib/relaton/3gpp/bibliography.rb +123 -0
  7. data/lib/relaton/3gpp/data_fetcher.rb +303 -0
  8. data/lib/relaton/3gpp/docidentifier.rb +114 -0
  9. data/lib/relaton/3gpp/doctype.rb +9 -0
  10. data/lib/relaton/3gpp/ext.rb +31 -0
  11. data/lib/relaton/3gpp/item.rb +18 -0
  12. data/lib/relaton/3gpp/item_data.rb +15 -0
  13. data/lib/relaton/3gpp/parser.rb +400 -0
  14. data/lib/relaton/3gpp/processor.rb +71 -0
  15. data/lib/relaton/3gpp/release.rb +34 -0
  16. data/lib/relaton/3gpp/util.rb +8 -0
  17. data/lib/relaton/3gpp.rb +29 -0
  18. data/lib/relaton/adobe/bibdata.rb +8 -0
  19. data/lib/relaton/adobe/bibitem.rb +8 -0
  20. data/lib/relaton/adobe/bibliography.rb +92 -0
  21. data/lib/relaton/adobe/docidentifier.rb +49 -0
  22. data/lib/relaton/adobe/doctype.rb +14 -0
  23. data/lib/relaton/adobe/ext.rb +32 -0
  24. data/lib/relaton/adobe/item.rb +15 -0
  25. data/lib/relaton/adobe/item_base.rb +18 -0
  26. data/lib/relaton/adobe/item_data.rb +6 -0
  27. data/lib/relaton/adobe/processor.rb +45 -0
  28. data/lib/relaton/adobe/util.rb +8 -0
  29. data/lib/relaton/adobe.rb +37 -0
  30. data/lib/relaton/bib/converter/asciibib/to_asciibib.rb +663 -0
  31. data/lib/relaton/bib/converter/asciibib.rb +13 -0
  32. data/lib/relaton/bib/converter/bibtex/from_bibtex.rb +245 -0
  33. data/lib/relaton/bib/converter/bibtex/to_bibtex.rb +341 -0
  34. data/lib/relaton/bib/converter/bibtex.rb +23 -0
  35. data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +386 -0
  36. data/lib/relaton/bib/converter/bibxml/from_rfcxml_referencegroup.rb +71 -0
  37. data/lib/relaton/bib/converter/bibxml/to_rfcxml.rb +308 -0
  38. data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +52 -0
  39. data/lib/relaton/bib/converter/bibxml.rb +51 -0
  40. data/lib/relaton/bib/hash_parser_v1.rb +767 -0
  41. data/lib/relaton/bib/item_data.rb +229 -0
  42. data/lib/relaton/bib/model/abstract.rb +16 -0
  43. data/lib/relaton/bib/model/address.rb +22 -0
  44. data/lib/relaton/bib/model/affiliation.rb +16 -0
  45. data/lib/relaton/bib/model/bibdata.rb +11 -0
  46. data/lib/relaton/bib/model/bibdata_shared.rb +12 -0
  47. data/lib/relaton/bib/model/bibitem.rb +11 -0
  48. data/lib/relaton/bib/model/bibitem_shared.rb +12 -0
  49. data/lib/relaton/bib/model/contact.rb +18 -0
  50. data/lib/relaton/bib/model/contribution_info.rb +15 -0
  51. data/lib/relaton/bib/model/contributor.rb +29 -0
  52. data/lib/relaton/bib/model/copyright.rb +27 -0
  53. data/lib/relaton/bib/model/date.rb +31 -0
  54. data/lib/relaton/bib/model/depiction.rb +16 -0
  55. data/lib/relaton/bib/model/docidentifier.rb +49 -0
  56. data/lib/relaton/bib/model/doctype.rb +14 -0
  57. data/lib/relaton/bib/model/edition.rb +14 -0
  58. data/lib/relaton/bib/model/ext.rb +39 -0
  59. data/lib/relaton/bib/model/extent.rb +16 -0
  60. data/lib/relaton/bib/model/formattedref.rb +43 -0
  61. data/lib/relaton/bib/model/full_name_type.rb +64 -0
  62. data/lib/relaton/bib/model/fullname.rb +11 -0
  63. data/lib/relaton/bib/model/ics.rb +49 -0
  64. data/lib/relaton/bib/model/image.rb +28 -0
  65. data/lib/relaton/bib/model/item.rb +96 -0
  66. data/lib/relaton/bib/model/item_base.rb +20 -0
  67. data/lib/relaton/bib/model/item_shared.rb +88 -0
  68. data/lib/relaton/bib/model/keyword.rb +30 -0
  69. data/lib/relaton/bib/model/locality.rb +18 -0
  70. data/lib/relaton/bib/model/locality_stack.rb +14 -0
  71. data/lib/relaton/bib/model/localized_string.rb +48 -0
  72. data/lib/relaton/bib/model/localized_string_attrs.rb +24 -0
  73. data/lib/relaton/bib/model/logo.rb +14 -0
  74. data/lib/relaton/bib/model/medium.rb +22 -0
  75. data/lib/relaton/bib/model/note.rb +16 -0
  76. data/lib/relaton/bib/model/organization.rb +13 -0
  77. data/lib/relaton/bib/model/organization_type.rb +42 -0
  78. data/lib/relaton/bib/model/person.rb +36 -0
  79. data/lib/relaton/bib/model/phone.rb +14 -0
  80. data/lib/relaton/bib/model/place.rb +33 -0
  81. data/lib/relaton/bib/model/price.rb +14 -0
  82. data/lib/relaton/bib/model/relation.rb +43 -0
  83. data/lib/relaton/bib/model/series.rb +34 -0
  84. data/lib/relaton/bib/model/size.rb +23 -0
  85. data/lib/relaton/bib/model/source_locality_stack.rb +14 -0
  86. data/lib/relaton/bib/model/status.rb +27 -0
  87. data/lib/relaton/bib/model/structured_identifier.rb +49 -0
  88. data/lib/relaton/bib/model/subdivision.rb +16 -0
  89. data/lib/relaton/bib/model/title.rb +56 -0
  90. data/lib/relaton/bib/model/type/plain_date.rb +16 -0
  91. data/lib/relaton/bib/model/type/string_date.rb +48 -0
  92. data/lib/relaton/bib/model/uri.rb +18 -0
  93. data/lib/relaton/bib/model/validity.rb +16 -0
  94. data/lib/relaton/bib/model/version.rb +43 -0
  95. data/lib/relaton/bib/namespace_helper.rb +21 -0
  96. data/lib/relaton/bib/sanitizer.rb +264 -0
  97. data/lib/relaton/bib/util.rb +18 -0
  98. data/lib/relaton/bib/versions.json +35 -0
  99. data/lib/relaton/bib.rb +46 -0
  100. data/lib/relaton/bipm/bibliography.rb +231 -0
  101. data/lib/relaton/bipm/converter/asciibib.rb +64 -0
  102. data/lib/relaton/bipm/data_fetcher.rb +81 -0
  103. data/lib/relaton/bipm/data_outcomes_parser.rb +656 -0
  104. data/lib/relaton/bipm/id_parser.rb +278 -0
  105. data/lib/relaton/bipm/item_data.rb +47 -0
  106. data/lib/relaton/bipm/model/bibdata.rb +9 -0
  107. data/lib/relaton/bipm/model/bibitem.rb +9 -0
  108. data/lib/relaton/bipm/model/comment_period.rb +13 -0
  109. data/lib/relaton/bipm/model/doctype.rb +12 -0
  110. data/lib/relaton/bipm/model/ext.rb +38 -0
  111. data/lib/relaton/bipm/model/item.rb +11 -0
  112. data/lib/relaton/bipm/model/structured_identifier.rb +36 -0
  113. data/lib/relaton/bipm/processor.rb +69 -0
  114. data/lib/relaton/bipm/rawdata_bipm_metrologia/affiliations.rb +111 -0
  115. data/lib/relaton/bipm/rawdata_bipm_metrologia/fetcher.rb +172 -0
  116. data/lib/relaton/bipm/rawdata_bipm_metrologia/niso_jats_parser.rb +353 -0
  117. data/lib/relaton/bipm/si_brochure_parser.rb +188 -0
  118. data/lib/relaton/bipm/util.rb +8 -0
  119. data/lib/relaton/bipm.rb +38 -0
  120. data/lib/relaton/bsi/bibliography.rb +196 -0
  121. data/lib/relaton/bsi/hit.rb +28 -0
  122. data/lib/relaton/bsi/hit_collection.rb +113 -0
  123. data/lib/relaton/bsi/item_data.rb +13 -0
  124. data/lib/relaton/bsi/model/bibdata.rb +8 -0
  125. data/lib/relaton/bsi/model/bibitem.rb +8 -0
  126. data/lib/relaton/bsi/model/docidentifier.rb +107 -0
  127. data/lib/relaton/bsi/model/doctype.rb +14 -0
  128. data/lib/relaton/bsi/model/ext.rb +17 -0
  129. data/lib/relaton/bsi/model/item.rb +17 -0
  130. data/lib/relaton/bsi/model/item_base.rb +22 -0
  131. data/lib/relaton/bsi/model/relation.rb +9 -0
  132. data/lib/relaton/bsi/processor.rb +43 -0
  133. data/lib/relaton/bsi/schema.json +24882 -0
  134. data/lib/relaton/bsi/scraper.rb +288 -0
  135. data/lib/relaton/bsi/util.rb +8 -0
  136. data/lib/relaton/bsi.rb +25 -0
  137. data/lib/relaton/calconnect/bibliography.rb +93 -0
  138. data/lib/relaton/calconnect/data_fetcher.rb +174 -0
  139. data/lib/relaton/calconnect/docidentifier.rb +80 -0
  140. data/lib/relaton/calconnect/hit.rb +14 -0
  141. data/lib/relaton/calconnect/hit_collection.rb +92 -0
  142. data/lib/relaton/calconnect/item_data.rb +12 -0
  143. data/lib/relaton/calconnect/model/bibdata.rb +8 -0
  144. data/lib/relaton/calconnect/model/bibitem.rb +8 -0
  145. data/lib/relaton/calconnect/model/doctype.rb +11 -0
  146. data/lib/relaton/calconnect/model/ext.rb +11 -0
  147. data/lib/relaton/calconnect/model/item.rb +20 -0
  148. data/lib/relaton/calconnect/processor.rb +72 -0
  149. data/lib/relaton/calconnect/scraper.rb +87 -0
  150. data/lib/relaton/calconnect/util.rb +8 -0
  151. data/lib/relaton/calconnect.rb +36 -0
  152. data/lib/relaton/ccsds/bibliography.rb +63 -0
  153. data/lib/relaton/ccsds/data/fetcher.rb +252 -0
  154. data/lib/relaton/ccsds/data/iso_references.rb +30 -0
  155. data/lib/relaton/ccsds/data/parser.rb +194 -0
  156. data/lib/relaton/ccsds/hit.rb +24 -0
  157. data/lib/relaton/ccsds/hit_collection.rb +47 -0
  158. data/lib/relaton/ccsds/item_data.rb +9 -0
  159. data/lib/relaton/ccsds/model/bibdata.rb +8 -0
  160. data/lib/relaton/ccsds/model/bibitem.rb +8 -0
  161. data/lib/relaton/ccsds/model/docidentifier.rb +121 -0
  162. data/lib/relaton/ccsds/model/doctype.rb +9 -0
  163. data/lib/relaton/ccsds/model/ext.rb +19 -0
  164. data/lib/relaton/ccsds/model/item.rb +15 -0
  165. data/lib/relaton/ccsds/processor.rb +68 -0
  166. data/lib/relaton/ccsds/util.rb +10 -0
  167. data/lib/relaton/ccsds.rb +33 -0
  168. data/lib/relaton/cen/bibliography.rb +149 -0
  169. data/lib/relaton/cen/committees.yaml +66 -0
  170. data/lib/relaton/cen/hit.rb +31 -0
  171. data/lib/relaton/cen/hit_collection.rb +116 -0
  172. data/lib/relaton/cen/item_data.rb +7 -0
  173. data/lib/relaton/cen/model/bibdata.rb +8 -0
  174. data/lib/relaton/cen/model/bibitem.rb +8 -0
  175. data/lib/relaton/cen/model/docidentifier.rb +100 -0
  176. data/lib/relaton/cen/model/ext.rb +11 -0
  177. data/lib/relaton/cen/model/item.rb +14 -0
  178. data/lib/relaton/cen/model/structured_identifier.rb +9 -0
  179. data/lib/relaton/cen/processor.rb +45 -0
  180. data/lib/relaton/cen/scraper.rb +218 -0
  181. data/lib/relaton/cen/util.rb +8 -0
  182. data/lib/relaton/cen.rb +30 -0
  183. data/lib/relaton/cie/bibdata.rb +8 -0
  184. data/lib/relaton/cie/bibitem.rb +8 -0
  185. data/lib/relaton/cie/bibliography.rb +31 -0
  186. data/lib/relaton/cie/data_fetcher.rb +540 -0
  187. data/lib/relaton/cie/ext.rb +7 -0
  188. data/lib/relaton/cie/item.rb +11 -0
  189. data/lib/relaton/cie/item_data.rb +6 -0
  190. data/lib/relaton/cie/processor.rb +68 -0
  191. data/lib/relaton/cie/scrapper.rb +52 -0
  192. data/lib/relaton/cie/util.rb +8 -0
  193. data/lib/relaton/cie.rb +29 -0
  194. data/lib/relaton/core/array_wrapper.rb +20 -0
  195. data/lib/relaton/core/data_fetcher.rb +244 -0
  196. data/lib/relaton/core/date_parser.rb +42 -0
  197. data/lib/relaton/core/governor.rb +320 -0
  198. data/lib/relaton/core/hash_keys_sybolizer.rb +19 -0
  199. data/lib/relaton/core/hit.rb +49 -0
  200. data/lib/relaton/core/hit_collection.rb +118 -0
  201. data/lib/relaton/core/pacer.rb +134 -0
  202. data/lib/relaton/core/processor.rb +67 -0
  203. data/lib/relaton/core/request_error.rb +14 -0
  204. data/lib/relaton/core/workers_pool.rb +45 -0
  205. data/lib/relaton/core.rb +12 -0
  206. data/lib/relaton/db/registry.rb +44 -4
  207. data/lib/relaton/db.rb +0 -1
  208. data/lib/relaton/doi/crossref.rb +89 -0
  209. data/lib/relaton/doi/parser.rb +921 -0
  210. data/lib/relaton/doi/processor.rb +65 -0
  211. data/lib/relaton/doi/util.rb +8 -0
  212. data/lib/relaton/doi.rb +20 -0
  213. data/lib/relaton/easc/bibdata.rb +8 -0
  214. data/lib/relaton/easc/bibitem.rb +8 -0
  215. data/lib/relaton/easc/bibliography.rb +95 -0
  216. data/lib/relaton/easc/docidentifier.rb +100 -0
  217. data/lib/relaton/easc/doctype.rb +14 -0
  218. data/lib/relaton/easc/ext.rb +44 -0
  219. data/lib/relaton/easc/item.rb +13 -0
  220. data/lib/relaton/easc/item_base.rb +18 -0
  221. data/lib/relaton/easc/item_data.rb +6 -0
  222. data/lib/relaton/easc/processor.rb +46 -0
  223. data/lib/relaton/easc/util.rb +8 -0
  224. data/lib/relaton/easc.rb +35 -0
  225. data/lib/relaton/ecma/bibdata.rb +8 -0
  226. data/lib/relaton/ecma/bibitem.rb +8 -0
  227. data/lib/relaton/ecma/bibliography.rb +149 -0
  228. data/lib/relaton/ecma/data_fetcher.rb +162 -0
  229. data/lib/relaton/ecma/data_parser.rb +49 -0
  230. data/lib/relaton/ecma/docidentifier.rb +124 -0
  231. data/lib/relaton/ecma/edition_parser.rb +80 -0
  232. data/lib/relaton/ecma/ext.rb +7 -0
  233. data/lib/relaton/ecma/item.rb +13 -0
  234. data/lib/relaton/ecma/item_data.rb +6 -0
  235. data/lib/relaton/ecma/memento_parser.rb +60 -0
  236. data/lib/relaton/ecma/page_fetcher.rb +39 -0
  237. data/lib/relaton/ecma/parser_common.rb +33 -0
  238. data/lib/relaton/ecma/processor.rb +69 -0
  239. data/lib/relaton/ecma/standard_parser.rb +134 -0
  240. data/lib/relaton/ecma/util.rb +8 -0
  241. data/lib/relaton/ecma.rb +33 -0
  242. data/lib/relaton/etsi/bibdata.rb +10 -0
  243. data/lib/relaton/etsi/bibitem.rb +10 -0
  244. data/lib/relaton/etsi/bibliography.rb +111 -0
  245. data/lib/relaton/etsi/data_fetcher.rb +167 -0
  246. data/lib/relaton/etsi/data_parser.rb +208 -0
  247. data/lib/relaton/etsi/doctype.rb +30 -0
  248. data/lib/relaton/etsi/ext.rb +31 -0
  249. data/lib/relaton/etsi/item.rb +15 -0
  250. data/lib/relaton/etsi/item_data.rb +6 -0
  251. data/lib/relaton/etsi/processor.rb +71 -0
  252. data/lib/relaton/etsi/pubid.rb +37 -0
  253. data/lib/relaton/etsi/status.rb +13 -0
  254. data/lib/relaton/etsi/util.rb +8 -0
  255. data/lib/relaton/etsi.rb +26 -0
  256. data/lib/relaton/gb/bibdata.rb +8 -0
  257. data/lib/relaton/gb/bibitem.rb +8 -0
  258. data/lib/relaton/gb/bibliography.rb +171 -0
  259. data/lib/relaton/gb/ccs.rb +14 -0
  260. data/lib/relaton/gb/committee.rb +13 -0
  261. data/lib/relaton/gb/docidentifier.rb +72 -0
  262. data/lib/relaton/gb/doctype.rb +9 -0
  263. data/lib/relaton/gb/ext.rb +36 -0
  264. data/lib/relaton/gb/gb_scraper.rb +61 -0
  265. data/lib/relaton/gb/gb_type.rb +20 -0
  266. data/lib/relaton/gb/hit.rb +48 -0
  267. data/lib/relaton/gb/hit_collection.rb +19 -0
  268. data/lib/relaton/gb/item.rb +13 -0
  269. data/lib/relaton/gb/item_data.rb +6 -0
  270. data/lib/relaton/gb/processor.rb +49 -0
  271. data/lib/relaton/gb/project_number.rb +38 -0
  272. data/lib/relaton/gb/scraper.rb +221 -0
  273. data/lib/relaton/gb/sec_scraper.rb +92 -0
  274. data/lib/relaton/gb/stage_name.rb +13 -0
  275. data/lib/relaton/gb/structured_identifier.rb +26 -0
  276. data/lib/relaton/gb/t_scraper.rb +126 -0
  277. data/lib/relaton/gb/util.rb +8 -0
  278. data/lib/relaton/gb/yaml/prefixes.yaml +200 -0
  279. data/lib/relaton/gb.rb +33 -0
  280. data/lib/relaton/gost/bibdata.rb +8 -0
  281. data/lib/relaton/gost/bibitem.rb +8 -0
  282. data/lib/relaton/gost/bibliography.rb +107 -0
  283. data/lib/relaton/gost/docidentifier.rb +80 -0
  284. data/lib/relaton/gost/doctype.rb +16 -0
  285. data/lib/relaton/gost/ext.rb +46 -0
  286. data/lib/relaton/gost/item.rb +15 -0
  287. data/lib/relaton/gost/item_base.rb +18 -0
  288. data/lib/relaton/gost/item_data.rb +6 -0
  289. data/lib/relaton/gost/processor.rb +49 -0
  290. data/lib/relaton/gost/util.rb +8 -0
  291. data/lib/relaton/gost.rb +36 -0
  292. data/lib/relaton/iala/bibdata.rb +8 -0
  293. data/lib/relaton/iala/bibitem.rb +8 -0
  294. data/lib/relaton/iala/bibliography.rb +146 -0
  295. data/lib/relaton/iala/docidentifier.rb +89 -0
  296. data/lib/relaton/iala/doctype.rb +18 -0
  297. data/lib/relaton/iala/ext.rb +32 -0
  298. data/lib/relaton/iala/item.rb +21 -0
  299. data/lib/relaton/iala/item_base.rb +18 -0
  300. data/lib/relaton/iala/item_data.rb +6 -0
  301. data/lib/relaton/iala/processor.rb +43 -0
  302. data/lib/relaton/iala/relation.rb +7 -0
  303. data/lib/relaton/iala/util.rb +8 -0
  304. data/lib/relaton/iala.rb +35 -0
  305. data/lib/relaton/iana/bibdata.rb +8 -0
  306. data/lib/relaton/iana/bibitem.rb +8 -0
  307. data/lib/relaton/iana/bibliography.rb +100 -0
  308. data/lib/relaton/iana/data_fetcher.rb +101 -0
  309. data/lib/relaton/iana/item.rb +7 -0
  310. data/lib/relaton/iana/item_data.rb +6 -0
  311. data/lib/relaton/iana/parser.rb +146 -0
  312. data/lib/relaton/iana/processor.rb +70 -0
  313. data/lib/relaton/iana/util.rb +8 -0
  314. data/lib/relaton/iana.rb +40 -0
  315. data/lib/relaton/iec/bibliography.rb +283 -0
  316. data/lib/relaton/iec/data_fetcher.rb +222 -0
  317. data/lib/relaton/iec/data_parser.rb +391 -0
  318. data/lib/relaton/iec/hit.rb +26 -0
  319. data/lib/relaton/iec/hit_collection.rb +138 -0
  320. data/lib/relaton/iec/item_data.rb +7 -0
  321. data/lib/relaton/iec/model/bibdata.rb +8 -0
  322. data/lib/relaton/iec/model/bibitem.rb +8 -0
  323. data/lib/relaton/iec/model/docidentifier.rb +135 -0
  324. data/lib/relaton/iec/model/doctype.rb +12 -0
  325. data/lib/relaton/iec/model/ext.rb +53 -0
  326. data/lib/relaton/iec/model/item.rb +20 -0
  327. data/lib/relaton/iec/model/item_base.rb +12 -0
  328. data/lib/relaton/iec/model/relation.rb +7 -0
  329. data/lib/relaton/iec/model/stage_name.rb +13 -0
  330. data/lib/relaton/iec/processor.rb +74 -0
  331. data/lib/relaton/iec/statuses.yml +199 -0
  332. data/lib/relaton/iec/util.rb +8 -0
  333. data/lib/relaton/iec.rb +98 -0
  334. data/lib/relaton/ieee/balloting_group.rb +13 -0
  335. data/lib/relaton/ieee/bibdata.rb +8 -0
  336. data/lib/relaton/ieee/bibitem.rb +8 -0
  337. data/lib/relaton/ieee/bibliography.rb +73 -0
  338. data/lib/relaton/ieee/converter/bibxml/from_rfcxml.rb +10 -0
  339. data/lib/relaton/ieee/converter/bibxml/from_rfcxml_referencegroup.rb +10 -0
  340. data/lib/relaton/ieee/converter/bibxml.rb +20 -0
  341. data/lib/relaton/ieee/data_fetcher.rb +771 -0
  342. data/lib/relaton/ieee/doctype.rb +9 -0
  343. data/lib/relaton/ieee/editorial_group.rb +19 -0
  344. data/lib/relaton/ieee/ext.rb +36 -0
  345. data/lib/relaton/ieee/idams_parser.rb +330 -0
  346. data/lib/relaton/ieee/item.rb +11 -0
  347. data/lib/relaton/ieee/item_data.rb +7 -0
  348. data/lib/relaton/ieee/processor.rb +71 -0
  349. data/lib/relaton/ieee/rawbib_id_parser.rb +753 -0
  350. data/lib/relaton/ieee/util.rb +8 -0
  351. data/lib/relaton/ieee.rb +30 -0
  352. data/lib/relaton/ietf/bibdata.rb +8 -0
  353. data/lib/relaton/ietf/bibitem.rb +8 -0
  354. data/lib/relaton/ietf/bibliography.rb +35 -0
  355. data/lib/relaton/ietf/bibxml_parser.rb +232 -0
  356. data/lib/relaton/ietf/data_fetcher.rb +561 -0
  357. data/lib/relaton/ietf/doctype.rb +9 -0
  358. data/lib/relaton/ietf/ext.rb +63 -0
  359. data/lib/relaton/ietf/item.rb +16 -0
  360. data/lib/relaton/ietf/item_base.rb +18 -0
  361. data/lib/relaton/ietf/item_data.rb +6 -0
  362. data/lib/relaton/ietf/processing_instructions.rb +79 -0
  363. data/lib/relaton/ietf/processor.rb +72 -0
  364. data/lib/relaton/ietf/relation.rb +9 -0
  365. data/lib/relaton/ietf/rfc/abstract.rb +19 -0
  366. data/lib/relaton/ietf/rfc/author.rb +21 -0
  367. data/lib/relaton/ietf/rfc/entry.rb +446 -0
  368. data/lib/relaton/ietf/rfc/entry_date.rb +21 -0
  369. data/lib/relaton/ietf/rfc/format.rb +19 -0
  370. data/lib/relaton/ietf/rfc/index.rb +46 -0
  371. data/lib/relaton/ietf/rfc/is_also.rb +21 -0
  372. data/lib/relaton/ietf/rfc/keywords.rb +19 -0
  373. data/lib/relaton/ietf/rfc/rfc_index_namespace.rb +11 -0
  374. data/lib/relaton/ietf/scraper.rb +101 -0
  375. data/lib/relaton/ietf/util.rb +8 -0
  376. data/lib/relaton/ietf/wg_name_resolver.rb +42 -0
  377. data/lib/relaton/ietf.rb +30 -0
  378. data/lib/relaton/iho/bibdata.rb +8 -0
  379. data/lib/relaton/iho/bibitem.rb +8 -0
  380. data/lib/relaton/iho/bibliography.rb +114 -0
  381. data/lib/relaton/iho/comment_period.rb +13 -0
  382. data/lib/relaton/iho/docidentifier.rb +31 -0
  383. data/lib/relaton/iho/doctype.rb +10 -0
  384. data/lib/relaton/iho/ext.rb +20 -0
  385. data/lib/relaton/iho/hash_parser_v1.rb +144 -0
  386. data/lib/relaton/iho/item.rb +20 -0
  387. data/lib/relaton/iho/item_base.rb +18 -0
  388. data/lib/relaton/iho/item_data.rb +6 -0
  389. data/lib/relaton/iho/processor.rb +54 -0
  390. data/lib/relaton/iho/relation.rb +9 -0
  391. data/lib/relaton/iho/structured_identifier.rb +20 -0
  392. data/lib/relaton/iho/util.rb +8 -0
  393. data/lib/relaton/iho.rb +27 -0
  394. data/lib/relaton/index/config.rb +52 -0
  395. data/lib/relaton/index/file_io.rb +305 -0
  396. data/lib/relaton/index/file_storage.rb +66 -0
  397. data/lib/relaton/index/pool.rb +46 -0
  398. data/lib/relaton/index/shard_source.rb +201 -0
  399. data/lib/relaton/index/type.rb +210 -0
  400. data/lib/relaton/index/util.rb +18 -0
  401. data/lib/relaton/index.rb +61 -0
  402. data/lib/relaton/isbn/isbn.rb +61 -0
  403. data/lib/relaton/isbn/open_library.rb +43 -0
  404. data/lib/relaton/isbn/parser.rb +88 -0
  405. data/lib/relaton/isbn/processor.rb +48 -0
  406. data/lib/relaton/isbn/util.rb +8 -0
  407. data/lib/relaton/isbn.rb +19 -0
  408. data/lib/relaton/iso/bibliography.rb +412 -0
  409. data/lib/relaton/iso/data_fetcher.rb +338 -0
  410. data/lib/relaton/iso/data_parser.rb +458 -0
  411. data/lib/relaton/iso/hash_parser_v1.rb +177 -0
  412. data/lib/relaton/iso/hit.rb +57 -0
  413. data/lib/relaton/iso/hit_collection.rb +196 -0
  414. data/lib/relaton/iso/item_data.rb +50 -0
  415. data/lib/relaton/iso/model/bibdata.rb +10 -0
  416. data/lib/relaton/iso/model/bibitem.rb +8 -0
  417. data/lib/relaton/iso/model/contributor.rb +6 -0
  418. data/lib/relaton/iso/model/contributor_info.rb +9 -0
  419. data/lib/relaton/iso/model/docidentifier.rb +146 -0
  420. data/lib/relaton/iso/model/doctype.rb +13 -0
  421. data/lib/relaton/iso/model/ext.rb +35 -0
  422. data/lib/relaton/iso/model/item.rb +17 -0
  423. data/lib/relaton/iso/model/item_base.rb +22 -0
  424. data/lib/relaton/iso/model/organization.rb +9 -0
  425. data/lib/relaton/iso/model/project_number.rb +22 -0
  426. data/lib/relaton/iso/model/relation.rb +9 -0
  427. data/lib/relaton/iso/model/stagename.rb +14 -0
  428. data/lib/relaton/iso/model/structured_identifier.rb +31 -0
  429. data/lib/relaton/iso/processor.rb +85 -0
  430. data/lib/relaton/iso/scraper.rb +635 -0
  431. data/lib/relaton/iso/type/pubid.rb +50 -0
  432. data/lib/relaton/iso/util.rb +8 -0
  433. data/lib/relaton/iso.rb +30 -0
  434. data/lib/relaton/itu/bibliography.rb +95 -0
  435. data/lib/relaton/itu/data_crawler_r.rb +664 -0
  436. data/lib/relaton/itu/data_fetcher.rb +550 -0
  437. data/lib/relaton/itu/data_merge_r.rb +149 -0
  438. data/lib/relaton/itu/data_parser_r.rb +214 -0
  439. data/lib/relaton/itu/data_parser_t.rb +228 -0
  440. data/lib/relaton/itu/family_cache.rb +177 -0
  441. data/lib/relaton/itu/governor.rb +56 -0
  442. data/lib/relaton/itu/hit.rb +28 -0
  443. data/lib/relaton/itu/hit_collection.rb +299 -0
  444. data/lib/relaton/itu/item_data.rb +6 -0
  445. data/lib/relaton/itu/model/approval_stage.rb +13 -0
  446. data/lib/relaton/itu/model/bibdata.rb +8 -0
  447. data/lib/relaton/itu/model/bibitem.rb +8 -0
  448. data/lib/relaton/itu/model/docidentifier.rb +75 -0
  449. data/lib/relaton/itu/model/doctype.rb +13 -0
  450. data/lib/relaton/itu/model/ext.rb +47 -0
  451. data/lib/relaton/itu/model/item.rb +13 -0
  452. data/lib/relaton/itu/model/meeting.rb +13 -0
  453. data/lib/relaton/itu/model/meeting_date.rb +15 -0
  454. data/lib/relaton/itu/model/question.rb +13 -0
  455. data/lib/relaton/itu/model/recommendation_status.rb +11 -0
  456. data/lib/relaton/itu/model/structured_identifier.rb +38 -0
  457. data/lib/relaton/itu/processor.rb +72 -0
  458. data/lib/relaton/itu/pubid.rb +199 -0
  459. data/lib/relaton/itu/radio_regulations_parser.rb +70 -0
  460. data/lib/relaton/itu/recommendation_fields.rb +334 -0
  461. data/lib/relaton/itu/recommendation_parser.rb +30 -0
  462. data/lib/relaton/itu/scraper.rb +203 -0
  463. data/lib/relaton/itu/util.rb +8 -0
  464. data/lib/relaton/itu.rb +34 -0
  465. data/lib/relaton/jcgm/bibdata.rb +8 -0
  466. data/lib/relaton/jcgm/bibitem.rb +8 -0
  467. data/lib/relaton/jcgm/bibliography.rb +97 -0
  468. data/lib/relaton/jcgm/data_fetcher.rb +81 -0
  469. data/lib/relaton/jcgm/docidentifier.rb +102 -0
  470. data/lib/relaton/jcgm/doctype.rb +12 -0
  471. data/lib/relaton/jcgm/ext.rb +23 -0
  472. data/lib/relaton/jcgm/item.rb +20 -0
  473. data/lib/relaton/jcgm/item_base.rb +18 -0
  474. data/lib/relaton/jcgm/item_data.rb +6 -0
  475. data/lib/relaton/jcgm/meetings_parser.rb +175 -0
  476. data/lib/relaton/jcgm/processor.rb +71 -0
  477. data/lib/relaton/jcgm/relation.rb +9 -0
  478. data/lib/relaton/jcgm/structured_identifier.rb +40 -0
  479. data/lib/relaton/jcgm/util.rb +8 -0
  480. data/lib/relaton/jcgm.rb +24 -0
  481. data/lib/relaton/jis/bibdata.rb +8 -0
  482. data/lib/relaton/jis/bibitem.rb +8 -0
  483. data/lib/relaton/jis/bibliography.rb +73 -0
  484. data/lib/relaton/jis/data_fetcher.rb +183 -0
  485. data/lib/relaton/jis/docidentifier.rb +120 -0
  486. data/lib/relaton/jis/doctype.rb +9 -0
  487. data/lib/relaton/jis/ext.rb +13 -0
  488. data/lib/relaton/jis/hit.rb +88 -0
  489. data/lib/relaton/jis/hit_collection.rb +128 -0
  490. data/lib/relaton/jis/item.rb +22 -0
  491. data/lib/relaton/jis/item_base.rb +26 -0
  492. data/lib/relaton/jis/item_data.rb +8 -0
  493. data/lib/relaton/jis/processor.rb +55 -0
  494. data/lib/relaton/jis/relation.rb +11 -0
  495. data/lib/relaton/jis/scraper.rb +232 -0
  496. data/lib/relaton/jis/structured_identifier.rb +13 -0
  497. data/lib/relaton/jis/util.rb +8 -0
  498. data/lib/relaton/jis.rb +32 -0
  499. data/lib/relaton/logger/channels/gh_issue.rb +143 -0
  500. data/lib/relaton/logger/config.rb +34 -0
  501. data/lib/relaton/logger/formatter_json.rb +8 -0
  502. data/lib/relaton/logger/formatter_string.rb +12 -0
  503. data/lib/relaton/logger/log.rb +64 -0
  504. data/lib/relaton/logger/log_device.rb +27 -0
  505. data/lib/relaton/logger/pool.rb +24 -0
  506. data/lib/relaton/logger.rb +18 -0
  507. data/lib/relaton/nist/bibdata.rb +8 -0
  508. data/lib/relaton/nist/bibitem.rb +8 -0
  509. data/lib/relaton/nist/bibliography.rb +191 -0
  510. data/lib/relaton/nist/comment_period.rb +15 -0
  511. data/lib/relaton/nist/data_fetcher.rb +134 -0
  512. data/lib/relaton/nist/date.rb +7 -0
  513. data/lib/relaton/nist/docidentifier.rb +165 -0
  514. data/lib/relaton/nist/doctype.rb +7 -0
  515. data/lib/relaton/nist/ext.rb +16 -0
  516. data/lib/relaton/nist/hit.rb +18 -0
  517. data/lib/relaton/nist/hit_collection.rb +362 -0
  518. data/lib/relaton/nist/item.rb +19 -0
  519. data/lib/relaton/nist/item_base.rb +16 -0
  520. data/lib/relaton/nist/item_data.rb +6 -0
  521. data/lib/relaton/nist/mods_parser.rb +302 -0
  522. data/lib/relaton/nist/processor.rb +69 -0
  523. data/lib/relaton/nist/pubs_export.rb +69 -0
  524. data/lib/relaton/nist/relation.rb +10 -0
  525. data/lib/relaton/nist/scraper.rb +293 -0
  526. data/lib/relaton/nist/series.yaml +49 -0
  527. data/lib/relaton/nist/util.rb +8 -0
  528. data/lib/relaton/nist.rb +34 -0
  529. data/lib/relaton/oasis/bibdata.rb +8 -0
  530. data/lib/relaton/oasis/bibitem.rb +8 -0
  531. data/lib/relaton/oasis/bibliography.rb +201 -0
  532. data/lib/relaton/oasis/browser_agent.rb +71 -0
  533. data/lib/relaton/oasis/data_fetcher.rb +130 -0
  534. data/lib/relaton/oasis/data_parser.rb +305 -0
  535. data/lib/relaton/oasis/data_parser_utils.rb +330 -0
  536. data/lib/relaton/oasis/data_part_parser.rb +239 -0
  537. data/lib/relaton/oasis/docidentifier.rb +54 -0
  538. data/lib/relaton/oasis/doctype.rb +7 -0
  539. data/lib/relaton/oasis/ext.rb +19 -0
  540. data/lib/relaton/oasis/item.rb +14 -0
  541. data/lib/relaton/oasis/item_data.rb +6 -0
  542. data/lib/relaton/oasis/processor.rb +74 -0
  543. data/lib/relaton/oasis/util.rb +8 -0
  544. data/lib/relaton/oasis.rb +41 -0
  545. data/lib/relaton/ogc/bibdata.rb +8 -0
  546. data/lib/relaton/ogc/bibitem.rb +8 -0
  547. data/lib/relaton/ogc/bibliography.rb +64 -0
  548. data/lib/relaton/ogc/data_fetcher.rb +131 -0
  549. data/lib/relaton/ogc/docidentifier.rb +111 -0
  550. data/lib/relaton/ogc/doctype.rb +12 -0
  551. data/lib/relaton/ogc/ext.rb +15 -0
  552. data/lib/relaton/ogc/hit.rb +18 -0
  553. data/lib/relaton/ogc/hit_collection.rb +111 -0
  554. data/lib/relaton/ogc/item.rb +13 -0
  555. data/lib/relaton/ogc/item_data.rb +6 -0
  556. data/lib/relaton/ogc/processor.rb +59 -0
  557. data/lib/relaton/ogc/scraper.rb +225 -0
  558. data/lib/relaton/ogc/util.rb +8 -0
  559. data/lib/relaton/ogc.rb +30 -0
  560. data/lib/relaton/oiml/bibdata.rb +8 -0
  561. data/lib/relaton/oiml/bibitem.rb +8 -0
  562. data/lib/relaton/oiml/bibliography.rb +169 -0
  563. data/lib/relaton/oiml/docidentifier.rb +48 -0
  564. data/lib/relaton/oiml/doctype.rb +13 -0
  565. data/lib/relaton/oiml/ext.rb +42 -0
  566. data/lib/relaton/oiml/item.rb +20 -0
  567. data/lib/relaton/oiml/item_base.rb +18 -0
  568. data/lib/relaton/oiml/item_data.rb +6 -0
  569. data/lib/relaton/oiml/processor.rb +54 -0
  570. data/lib/relaton/oiml/relation.rb +9 -0
  571. data/lib/relaton/oiml/util.rb +8 -0
  572. data/lib/relaton/oiml.rb +24 -0
  573. data/lib/relaton/omg/bibdata.rb +8 -0
  574. data/lib/relaton/omg/bibitem.rb +8 -0
  575. data/lib/relaton/omg/bibliography.rb +31 -0
  576. data/lib/relaton/omg/docidentifier.rb +67 -0
  577. data/lib/relaton/omg/ext.rb +7 -0
  578. data/lib/relaton/omg/item.rb +9 -0
  579. data/lib/relaton/omg/item_data.rb +6 -0
  580. data/lib/relaton/omg/processor.rb +35 -0
  581. data/lib/relaton/omg/scraper.rb +186 -0
  582. data/lib/relaton/omg/util.rb +8 -0
  583. data/lib/relaton/omg.rb +25 -0
  584. data/lib/relaton/plateau/bibdata.rb +8 -0
  585. data/lib/relaton/plateau/bibitem.rb +8 -0
  586. data/lib/relaton/plateau/bibliography.rb +31 -0
  587. data/lib/relaton/plateau/data_fetcher.rb +176 -0
  588. data/lib/relaton/plateau/doctype.rb +7 -0
  589. data/lib/relaton/plateau/ext.rb +23 -0
  590. data/lib/relaton/plateau/handbook_parser.rb +102 -0
  591. data/lib/relaton/plateau/hit.rb +21 -0
  592. data/lib/relaton/plateau/hit_collection.rb +79 -0
  593. data/lib/relaton/plateau/item.rb +12 -0
  594. data/lib/relaton/plateau/item_data.rb +6 -0
  595. data/lib/relaton/plateau/parser.rb +101 -0
  596. data/lib/relaton/plateau/processor.rb +51 -0
  597. data/lib/relaton/plateau/technical_report_parser.rb +98 -0
  598. data/lib/relaton/plateau/util.rb +8 -0
  599. data/lib/relaton/plateau.rb +29 -0
  600. data/lib/relaton/sdo/config.rb +34 -0
  601. data/lib/relaton/sdo/fetcher.rb +52 -0
  602. data/lib/relaton/sdo/logo.rb +95 -0
  603. data/lib/relaton/sdo/name.rb +26 -0
  604. data/lib/relaton/sdo/organization.rb +71 -0
  605. data/lib/relaton/sdo/store.rb +49 -0
  606. data/lib/relaton/sdo.rb +29 -0
  607. data/lib/relaton/un/bibdata.rb +8 -0
  608. data/lib/relaton/un/bibitem.rb +8 -0
  609. data/lib/relaton/un/bibliography.rb +48 -0
  610. data/lib/relaton/un/doctype.rb +10 -0
  611. data/lib/relaton/un/ext.rb +30 -0
  612. data/lib/relaton/un/hit.rb +56 -0
  613. data/lib/relaton/un/hit_collection.rb +61 -0
  614. data/lib/relaton/un/item.rb +11 -0
  615. data/lib/relaton/un/item_data.rb +6 -0
  616. data/lib/relaton/un/parser.rb +108 -0
  617. data/lib/relaton/un/processor.rb +38 -0
  618. data/lib/relaton/un/session.rb +25 -0
  619. data/lib/relaton/un/token_generator.rb +105 -0
  620. data/lib/relaton/un/util.rb +8 -0
  621. data/lib/relaton/un/wasm/decoder.rb +434 -0
  622. data/lib/relaton/un/wasm/instance.rb +101 -0
  623. data/lib/relaton/un/wasm/interpreter.rb +613 -0
  624. data/lib/relaton/un/wasm/memory.rb +112 -0
  625. data/lib/relaton/un/wasm/module.rb +47 -0
  626. data/lib/relaton/un/wasm.rb +17 -0
  627. data/lib/relaton/un/wasm_v_bg.wasm +0 -0
  628. data/lib/relaton/un.rb +28 -0
  629. data/lib/relaton/version.rb +1 -1
  630. data/lib/relaton/w3c/bibdata.rb +8 -0
  631. data/lib/relaton/w3c/bibitem.rb +8 -0
  632. data/lib/relaton/w3c/bibliography.rb +174 -0
  633. data/lib/relaton/w3c/data_fetcher.rb +487 -0
  634. data/lib/relaton/w3c/data_parser.rb +379 -0
  635. data/lib/relaton/w3c/docidentifier.rb +48 -0
  636. data/lib/relaton/w3c/doctype.rb +7 -0
  637. data/lib/relaton/w3c/ext.rb +11 -0
  638. data/lib/relaton/w3c/governor.rb +32 -0
  639. data/lib/relaton/w3c/item.rb +15 -0
  640. data/lib/relaton/w3c/item_data.rb +6 -0
  641. data/lib/relaton/w3c/processor.rb +49 -0
  642. data/lib/relaton/w3c/pubid.rb +85 -0
  643. data/lib/relaton/w3c/safe_realize.rb +148 -0
  644. data/lib/relaton/w3c/util.rb +8 -0
  645. data/lib/relaton/w3c.rb +36 -0
  646. data/lib/relaton/xsf/bibdata.rb +8 -0
  647. data/lib/relaton/xsf/bibitem.rb +8 -0
  648. data/lib/relaton/xsf/bibliography.rb +84 -0
  649. data/lib/relaton/xsf/data_fetcher.rb +106 -0
  650. data/lib/relaton/xsf/docidentifier.rb +46 -0
  651. data/lib/relaton/xsf/hit.rb +17 -0
  652. data/lib/relaton/xsf/hit_collection.rb +52 -0
  653. data/lib/relaton/xsf/item.rb +13 -0
  654. data/lib/relaton/xsf/item_data.rb +6 -0
  655. data/lib/relaton/xsf/processor.rb +51 -0
  656. data/lib/relaton/xsf/util.rb +9 -0
  657. data/lib/relaton/xsf.rb +34 -0
  658. data/lib/relaton-core.rb +1 -0
  659. data/lib/relaton.rb +85 -0
  660. metadata +775 -161
  661. data/.github/workflows/rake.yml +0 -14
  662. data/.github/workflows/release.yml +0 -24
  663. data/.github/workflows/rubocop.yml +0 -48
  664. data/.gitignore +0 -12
  665. data/.rspec +0 -3
  666. data/CLAUDE.md +0 -78
  667. data/Gemfile +0 -29
  668. data/Rakefile +0 -6
  669. data/docs/CHANGELOG.adoc +0 -16
  670. data/docs/VERSIONING_POLICY.adoc +0 -38
  671. data/docs/navigation.adoc +0 -6
  672. data/lib/relaton/db/version.rb +0 -5
  673. data/relaton.gemspec +0 -72
  674. data/spec/relaton/config_spec.rb +0 -10
  675. data/spec/relaton/db_cache_spec.rb +0 -51
  676. data/spec/relaton/db_spec.rb +0 -567
  677. data/spec/relaton/registry_spec.rb +0 -178
  678. data/spec/relaton/util_spec.rb +0 -3
  679. data/spec/relaton_meta_spec.rb +0 -25
  680. data/spec/relaton_spec.rb +0 -800
  681. data/spec/spec_helper.rb +0 -45
  682. data/spec/support/gb_t_20223_2006.xml +0 -33
  683. data/spec/support/iso_111111119115_1.xml +0 -0
  684. data/spec/support/iso_19115_1.xml +0 -115
  685. data/spec/support/iso_19115_2.xml +0 -95
  686. data/spec/support/rfc_8341.xml +0 -46
  687. data/spec/vcr_cassetes/api_relaton_org.yml +0 -121
  688. data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +0 -140
  689. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +0 -202
  690. data/spec/vcr_cassetes/cipm_meeting_43.yml +0 -1505
  691. data/spec/vcr_cassetes/gb_t_20223_2006.yml +0 -729
  692. data/spec/vcr_cassetes/iso_111111119115_1.yml +0 -12951
  693. data/spec/vcr_cassetes/iso_19115_1.yml +0 -17334
  694. data/spec/vcr_cassetes/iso_19115_1_2.yml +0 -322
  695. data/spec/vcr_cassetes/iso_19115_1_std.yml +0 -17334
  696. data/spec/vcr_cassetes/iso_19115_all_parts.yml +0 -185
  697. data/spec/vcr_cassetes/iso_19133_2005.yml +0 -144
  698. data/spec/vcr_cassetes/iso_combined_applied.yml +0 -318
  699. data/spec/vcr_cassetes/iso_combined_included.yml +0 -318
  700. data/spec/vcr_cassetes/ogc_19_025r1.yml +0 -374
  701. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +0 -317
  702. data/spec/vcr_cassetes/rfc_8341.yml +0 -1278
@@ -0,0 +1,201 @@
1
+ require "json"
2
+ require "net/http"
3
+ require "openssl"
4
+ require "zlib"
5
+
6
+ module Relaton
7
+ module Index
8
+ #
9
+ # Reads a flavor's machine index from its GitHub Pages site (relaton#189).
10
+ #
11
+ # `index/manifest.json` gives the lookup rule, and a query reads only the
12
+ # one `index/shard-NNNNN.json` its document family lives in, in place of the
13
+ # whole `index-vN.zip`. The shard key is `crc32(id.root.number.to_s) %
14
+ # shards`, the expression the relaton-cli producer (`MachineIndex`) writes
15
+ # and `Type#candidates_by_number` narrows on. See
16
+ # `docs/data-repository-format.adoc`, "The machine index on the Pages site".
17
+ #
18
+ # Everything is held in memory for TTL seconds and never written to the
19
+ # storage. A shard 404 is a definitive "not found" (empty buckets are not
20
+ # published). A transport failure raises `Relaton::RequestError`, which
21
+ # `Relaton::Db#net_retry` retries; a machine index this client cannot read
22
+ # raises `Relaton::Index::Error`. Neither falls back to the monolith: the
23
+ # whole index is read only when the manifest publishes no shards, or when
24
+ # the query has no root number to key on.
25
+ #
26
+ class ShardSource
27
+ TTL = 24 * 60 * 60
28
+ VERSION = 2
29
+ KEY = "root-number".freeze
30
+ ALGORITHM = "crc32".freeze
31
+
32
+ NET_ERRORS = [
33
+ SocketError, Timeout::Error, IOError, SystemCallError, OpenSSL::SSL::SSLError,
34
+ Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
35
+ Zlib::Error # a truncated gzip body, which Net::HTTP inflates
36
+
37
+ ].freeze
38
+
39
+ attr_reader :pages_url
40
+
41
+ #
42
+ # @param [String] dir flavor directory name, used in log messages
43
+ # @param [String] pages_url base URL of the Pages site, with a trailing `/`
44
+ # @param [Class] pubid_class the flavor's pubid identifier class
45
+ #
46
+ def initialize(dir, pages_url, pubid_class)
47
+ @pages_url = pages_url.end_with?("/") ? pages_url : "#{pages_url}/"
48
+ # Only the deserialization helpers are used: this FileIO reads and
49
+ # writes no file.
50
+ @file_io = FileIO.new(dir, nil, nil, nil, pubid_class)
51
+ @mutex = Mutex.new
52
+ @state = nil
53
+ end
54
+
55
+ #
56
+ # Rows of the shard that holds the document family of `id`.
57
+ #
58
+ # @param [Pubid::Identifier] id parsed query
59
+ #
60
+ # @return [Array<Hash>] `{ id:, file: }` rows, empty when not found
61
+ #
62
+ def rows(id)
63
+ number = id.root.number.to_s
64
+ state = current_state
65
+ shards = manifest(state)["shards"]
66
+ return load_whole_index(state) if shards.zero? || number.empty?
67
+
68
+ n = Zlib.crc32(number) % shards
69
+ once(state, n) { fetch_shard(n) }
70
+ end
71
+
72
+ #
73
+ # Every row, from the monolith the manifest names (`<index>.zip` on the
74
+ # Pages site). Needed by a String query and a block-only search.
75
+ #
76
+ # @return [Array<Hash>] `{ id:, file: }` rows, sorted by root number
77
+ #
78
+ def whole_index
79
+ load_whole_index current_state
80
+ end
81
+
82
+ private
83
+
84
+ # One generation of cached data. It is replaced as a whole when it
85
+ # expires, so a fetch that finishes late stores into its own generation
86
+ # and never mixes an old shard with a new manifest.
87
+ def new_state
88
+ { created: Time.now, data: {}, locks: {} }
89
+ end
90
+
91
+ def current_state
92
+ @mutex.synchronize do
93
+ @state = new_state if @state.nil? || Time.now - @state[:created] > TTL
94
+ @state
95
+ end
96
+ end
97
+
98
+ # Runs the block once for each key in a generation. The network call is
99
+ # made under a lock for that key only, so lookups of other shards (from
100
+ # the `Relaton::Db` workers pool) do not wait for it. A raise stores
101
+ # nothing, so the next call tries again.
102
+ def once(state, key)
103
+ lock = @mutex.synchronize { state[:locks][key] ||= Mutex.new }
104
+ lock.synchronize do
105
+ data = state[:data]
106
+ return @mutex.synchronize { data[key] } if @mutex.synchronize { data.key?(key) }
107
+
108
+ value = yield
109
+ @mutex.synchronize { data[key] = value }
110
+ end
111
+ end
112
+
113
+ def manifest(state)
114
+ once(state, :manifest) do
115
+ body = get("index/manifest.json")
116
+ raise Error, "no machine index manifest at `#{url('index/manifest.json')}`" unless body
117
+
118
+ check_manifest parse_json(body, "index/manifest.json")
119
+ end
120
+ end
121
+
122
+ def check_manifest(data)
123
+ unless data.is_a?(Hash) && data["version"] == VERSION &&
124
+ data["key"] == KEY && data["algorithm"] == ALGORITHM &&
125
+ data["shards"].is_a?(Integer) && !data["shards"].negative? &&
126
+ data["index"].is_a?(String) && !data["index"].empty?
127
+ raise Error, "unsupported machine index manifest at " \
128
+ "`#{url('index/manifest.json')}`: #{data.inspect}"
129
+ end
130
+
131
+ data
132
+ end
133
+
134
+ def fetch_shard(num)
135
+ path = format("index/shard-%05d.json", num)
136
+ body = get(path)
137
+ return [] unless body
138
+
139
+ data = parse_json(body, path)
140
+ raise Error, "shard `#{url(path)}` is not an array" unless data.is_a?(Array)
141
+
142
+ data.map { |r| { id: deserialize(r["id"], path), file: r["file"] } }
143
+ end
144
+
145
+ def load_whole_index(state)
146
+ path = "#{manifest(state)['index']}.zip"
147
+ once(state, :whole_index) do
148
+ body = get(path)
149
+ raise Error, "no whole index at `#{url(path)}`" unless body
150
+
151
+ yaml = unzip(body)
152
+ raise Error, "empty archive at `#{url(path)}`" unless yaml
153
+
154
+ index = YAML.safe_load(yaml, permitted_classes: [Symbol])
155
+ raise Error, "wrong structure of `#{url(path)}`" unless @file_io.check_basic_format(index)
156
+
157
+ @file_io.deserialize_pubid(index)
158
+ rescue FileIO::InvalidIndexError, Psych::SyntaxError, Zip::Error, Zlib::Error => e
159
+ raise Error, "cannot read `#{url(path)}`: #{e.message}"
160
+ end
161
+ end
162
+
163
+ def unzip(body)
164
+ yaml = nil
165
+ # `open_buffer` does not return the block's value.
166
+ Zip::File.open_buffer(body) { |zip| yaml = zip.entries.first&.get_input_stream&.read }
167
+ yaml
168
+ end
169
+
170
+ def deserialize(raw, path)
171
+ @file_io.deserialize_id(raw)
172
+ rescue FileIO::InvalidIndexError => e
173
+ raise Error, "cannot read shard `#{url(path)}`: #{e.message}"
174
+ end
175
+
176
+ def parse_json(body, path)
177
+ JSON.parse(body)
178
+ rescue JSON::ParserError => e
179
+ raise Error, "cannot parse `#{url(path)}`: #{e.message}"
180
+ end
181
+
182
+ def url(path)
183
+ "#{@pages_url}#{path}"
184
+ end
185
+
186
+ #
187
+ # @return [String, nil] the body, or nil for a 404
188
+ #
189
+ def get(path)
190
+ resp = Net::HTTP.get_response(URI.parse(url(path)))
191
+ case resp.code
192
+ when "200" then resp.body
193
+ when "404" then nil
194
+ else raise Relaton::RequestError, "Could not access #{url(path)}: HTTP #{resp.code}"
195
+ end
196
+ rescue *NET_ERRORS => e
197
+ raise Relaton::RequestError, "Could not access #{url(path)}: #{e.message}"
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,210 @@
1
+ module Relaton
2
+ module Index
3
+ #
4
+ # Relaton::Index::Type is a class for indexing Relaton files.
5
+ #
6
+ class Type
7
+ #
8
+ # Initialize a new Relaton::Index::Type object
9
+ #
10
+ # @param [String, Symbol] type type of index (ISO, IEC, etc.)
11
+ # @param [String, nil] url external URL to index, used to fetch index for searching files
12
+ # @param [String, nil] file output file name
13
+ # @param [Array<Symbol>] id_keys keys of identifier to be used for sorting index
14
+ # format of index file is checked if id_keys all is provided at least in one of the IDs
15
+ # @param [Pubid::Identifier, nil] pubid class for deserialization
16
+ # @param [String, nil] pages_url base URL of the Pages site that serves
17
+ # the machine index. With it the type reads the index from there, in
18
+ # memory (see ShardSource), and a parsed query fetches one shard only.
19
+ #
20
+ def initialize(type, url = nil, file = nil, id_keys = nil, pubid_class = nil, # rubocop:disable Metrics/ParameterLists
21
+ pages_url: nil)
22
+ @file = file
23
+ @dir = type.to_s.downcase
24
+ @pubid_class = pubid_class
25
+ @pages_url = pages_url
26
+ filename = file || Index.config.filename
27
+ @file_io = FileIO.new @dir, url, filename, id_keys, pubid_class
28
+ @source = new_source
29
+ end
30
+
31
+ # With a Pages source the whole index is not kept here: the source holds
32
+ # it, and drops it when its 24 h expire.
33
+ def index
34
+ return @source.whole_index if @source
35
+
36
+ @index ||= @file_io.read
37
+ end
38
+
39
+ #
40
+ # Check if index is actual. If url or file is given, check if it is equal to
41
+ # index url or file.
42
+ #
43
+ # @param [Hash] **args arguments
44
+ # @option args [String, nil] :url external URL to index, used to fetch index for searching files
45
+ # @option args [String, nil] :file output file name
46
+ # @option args [String, nil] :pages_url base URL of the Pages site
47
+ #
48
+ # @return [Boolean] true if index is actual, false otherwise
49
+ #
50
+ def actual?(**args)
51
+ (!args.key?(:url) || args[:url] == @file_io.url) &&
52
+ (!args.key?(:file) || args[:file] == @file) &&
53
+ (!args.key?(:pages_url) || args[:pages_url] == @pages_url)
54
+ end
55
+
56
+ #
57
+ # Add or update index item
58
+ #
59
+ # @param [Pubid::Identifier] id document ID
60
+ # @param [String] file file name of the document
61
+ #
62
+ # @return [void]
63
+ #
64
+ def add_or_update(id, file)
65
+ key = id.to_s
66
+ item = id_lookup[key]
67
+ if item
68
+ item[:file] = file
69
+ else
70
+ new_item = { id: id, file: file }
71
+ index << new_item
72
+ id_lookup[key] = new_item
73
+ @file_io.sorted = false
74
+ end
75
+ end
76
+
77
+ #
78
+ # Search index for a given ID.
79
+ #
80
+ # Without a block, two identifiers are matched with pubid's asymmetric
81
+ # subset match `id === item[:id]` (`Pubid::SubsetMatch`): the query is the
82
+ # reference, and a component it leaves nil or empty matches any value, so
83
+ # `OGC 12-128` answers with `12-128r19`. That is what a search by
84
+ # reference means. A caller that needs **exact** equality passes
85
+ # `exact: true`, which selects the rows with `item[:id] == id`. A nil
86
+ # component is a wildcard for `===`, not "the document has none": over
87
+ # the fixture indexes the subset match accepts 260 CCSDS pairs (the `-S`
88
+ # suffix) and 20,513 IETF pairs (a draft slug matches each of its
89
+ # versions) that `==` rejects. `Relaton::Ccsds` and `Relaton::Ietf` are
90
+ # the two callers that pass it.
91
+ #
92
+ # A String query keeps the substring match it always had, unless it is
93
+ # `exact:`.
94
+ #
95
+ # @param [String, Pubid::Identifier] id ID to search for
96
+ # @param [Boolean] exact match with `==` instead of the subset match
97
+ #
98
+ # @return [Array<Hash>] search results
99
+ #
100
+ def search(id = nil, exact: false, &block)
101
+ raise ArgumentError, "search takes exact: or a block, not both" if exact && block
102
+
103
+ items = search_candidates(id)
104
+ return items.select(&block) if block
105
+ return items.select { |i| i[:id] == id } if exact
106
+
107
+ items.select { |i| match_item(i, id) }
108
+ end
109
+
110
+ #
111
+ # Save index to storage
112
+ #
113
+ # @return [void]
114
+ #
115
+ def save
116
+ @file_io.save(@index || [])
117
+ end
118
+
119
+ #
120
+ # Remove index file from storage and clear index
121
+ #
122
+ # @return [void]
123
+ #
124
+ def remove_file
125
+ # A Pages source has no file: its FileIO would resolve the default
126
+ # filename against the working directory.
127
+ @file_io.remove unless @source
128
+ @source = new_source
129
+ @index = nil
130
+ @id_lookup = nil
131
+ end
132
+
133
+ #
134
+ # Remove all index items
135
+ #
136
+ # @return [void]
137
+ #
138
+ def remove_all
139
+ @index = []
140
+ @id_lookup = nil
141
+ @file_io.sorted = true
142
+ end
143
+
144
+ private
145
+
146
+ def id_lookup
147
+ @id_lookup ||= index.each_with_object({}) do |item, h|
148
+ h[item[:id].to_s] = item
149
+ end
150
+ end
151
+
152
+ def new_source
153
+ ShardSource.new(@dir, @pages_url, @pubid_class) if @pages_url
154
+ end
155
+
156
+ def search_candidates(id)
157
+ # A parsed query reads only its own shard. `@index`, once loaded, is
158
+ # never refreshed, so the shards stay the fresher answer.
159
+ return @source.rows(id) if @source && id && !id.is_a?(String)
160
+
161
+ # index needs to be created to check if sorted
162
+ idx = index
163
+ if @file_io.sorted && id && !id.is_a?(String)
164
+ candidates_by_number(id)
165
+ else
166
+ idx
167
+ end
168
+ end
169
+
170
+ # Narrowing key: the base *document's* number as a string. `#root` walks a
171
+ # supplement/amendment/corrigendum's `.base` chain to the origin (and
172
+ # returns self for a base document), so a document and all its wrappers
173
+ # share one key and cluster together. `.to_s` because the key is compared
174
+ # as a string (a pubid number Component is not `<`/`>`-comparable), and
175
+ # FileIO sorts the index by this exact same key so bsearch stays valid.
176
+ def candidates_by_number(id)
177
+ target = id.root.number.to_s
178
+ left = bsearch_left(target)
179
+ return [] unless left
180
+
181
+ right = bsearch_right(target)
182
+ index[left...right]
183
+ end
184
+
185
+ def bsearch_left(target)
186
+ index.bsearch_index do |item|
187
+ item[:id].root.number.to_s >= target
188
+ end
189
+ end
190
+
191
+ def bsearch_right(target)
192
+ index.bsearch_index do |item|
193
+ item[:id].root.number.to_s > target
194
+ end || index.size
195
+ end
196
+
197
+ # The query is the reference, so two identifiers take the subset match.
198
+ # See #search for the exact-equality escape hatch.
199
+ def match_item(item, id)
200
+ if item[:id].is_a?(String)
201
+ item[:id].include?(id.is_a?(String) ? id : id.to_s)
202
+ elsif id.is_a?(String)
203
+ item[:id].to_s.include?(id)
204
+ else
205
+ id === item[:id]
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,18 @@
1
+ module Relaton
2
+ module Index
3
+ module Util
4
+ extend self
5
+
6
+ PROGNAME = "relaton-index".freeze
7
+
8
+ def method_missing(method_name, msg = nil, prog = nil, **opts, &block)
9
+ prog ||= self::PROGNAME
10
+ Relaton.logger_pool.send method_name, msg, prog, **opts, &block
11
+ end
12
+
13
+ def respond_to_missing?(method_name, include_private = false)
14
+ Relaton.logger_pool.respond_to?(method_name) || super
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "zip"
5
+ require "relaton/logger"
6
+
7
+ require_relative "version"
8
+ require_relative "core/request_error"
9
+ require_relative "index/file_storage"
10
+ require_relative "index/config"
11
+ require_relative "index/util"
12
+ require_relative "index/pool"
13
+ require_relative "index/type"
14
+ require_relative "index/file_io"
15
+ require_relative "index/shard_source"
16
+
17
+ module Relaton
18
+ module Index
19
+ class Error < StandardError; end
20
+
21
+ class << self
22
+ #
23
+ # Proxy for Pool#type
24
+ #
25
+ def find_or_create(type, **args)
26
+ pool.type(type, **args)
27
+ end
28
+
29
+ def close(type)
30
+ pool.remove type
31
+ end
32
+
33
+ #
34
+ # Create new index pool object or return existing
35
+ #
36
+ # @return [Relaton::Index::Pool] index pool
37
+ #
38
+ def pool
39
+ @pool ||= Pool.new
40
+ end
41
+
42
+ #
43
+ # Create new config object or return existing
44
+ #
45
+ # @return [Relaton::Index::Config] config object
46
+ #
47
+ def config
48
+ @config ||= Config.new
49
+ end
50
+
51
+ #
52
+ # Configure Relaton::Index
53
+ #
54
+ # @return [void]
55
+ #
56
+ def configure
57
+ yield config
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,61 @@
1
+ module Relaton
2
+ module Isbn
3
+ class Isbn
4
+ #
5
+ # Create ISBN object.
6
+ #
7
+ # @param [String] isbn ISBN 13 number
8
+ #
9
+ def initialize(isbn)
10
+ @isbn = isbn&.delete("-")&.sub(/^ISBN[\s:]/i, "")
11
+ end
12
+
13
+ def parse
14
+ convert_to13
15
+ end
16
+
17
+ def check?
18
+ case @isbn
19
+ when /^\d{9}[\dX]$/i then check10?
20
+ when /^\d{13}$/ then check13?
21
+ else false
22
+ end
23
+ end
24
+
25
+ def check10?
26
+ @isbn[9] == calc_check_digit10
27
+ end
28
+
29
+ def check13?
30
+ @isbn[12] == calc_check_digit13
31
+ end
32
+
33
+ def calc_check_digit10
34
+ sum = 0
35
+ @isbn[..-2].chars.each_with_index do |c, i|
36
+ sum += c.to_i * (10 - i)
37
+ end
38
+ chk = (11 - sum % 11) % 11
39
+ chk == 10 ? "X" : chk.to_s
40
+ end
41
+
42
+ def calc_check_digit13
43
+ sum = 0
44
+ @isbn[..-2].chars.each_with_index do |c, i|
45
+ sum += c.to_i * (i.even? ? 1 : 3)
46
+ end
47
+ ((10 - sum % 10) % 10).to_s
48
+ end
49
+
50
+ def convert_to13
51
+ return unless check?
52
+
53
+ return @isbn if @isbn.size == 13
54
+
55
+ @isbn = "978#{@isbn}"
56
+ @isbn[12] = calc_check_digit13
57
+ @isbn
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,43 @@
1
+ module Relaton
2
+ module Isbn
3
+ #
4
+ # Search ISBN in Openlibrary.
5
+ #
6
+ module OpenLibrary
7
+ extend self
8
+
9
+ ENDPOINT = "http://openlibrary.org/api/volumes/brief/isbn/".freeze
10
+
11
+ def get(ref, _date = nil, _opts = {}) # rubocop:disable Metrics/MethodLength
12
+ Util.info "Fetching from OpenLibrary ...", key: ref
13
+
14
+ isbn = Isbn.new(ref).parse
15
+ unless isbn
16
+ Util.info "Incorrect ISBN.", key: ref
17
+ return
18
+ end
19
+
20
+ resp = request_api isbn
21
+ unless resp
22
+ Util.info "Not found.", key: ref
23
+ return
24
+ end
25
+
26
+ bib = Parser.parse resp
27
+ Util.info "Found: `#{bib.docidentifier.first.content}`", key: ref
28
+ bib
29
+ end
30
+
31
+ def request_api(isbn)
32
+ uri = URI "#{ENDPOINT}#{isbn}.json"
33
+ response = Net::HTTP.get_response uri
34
+ return unless response.is_a? Net::HTTPSuccess
35
+
36
+ data = JSON.parse response.body
37
+ return unless data["records"]&.any?
38
+
39
+ data["records"].first.last
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,88 @@
1
+ module Relaton
2
+ module Isbn
3
+ #
4
+ # OpenLibrary document parser.
5
+ #
6
+ class Parser
7
+ ATTRS = %i[fetched title docidentifier source contributor date place ext].freeze
8
+
9
+ def initialize(doc)
10
+ @doc = doc
11
+ end
12
+
13
+ def self.parse(doc)
14
+ new(doc).parse
15
+ end
16
+
17
+ def parse
18
+ args = ATTRS.each_with_object({}) { |a, h| h[a] = send(a) }
19
+ Bib::ItemData.new(**args)
20
+ end
21
+
22
+ private
23
+
24
+ def fetched = Date.today.to_s
25
+
26
+ def title
27
+ t = [Bib::Title.new(content: @doc["data"]["title"], type: "main")]
28
+ if @doc["data"]["subtitle"]
29
+ t << Bib::Title.new(content: @doc["data"]["subtitle"], type: "subtitle")
30
+ end
31
+ t
32
+ end
33
+
34
+ def docidentifier
35
+ isbn = @doc["details"]["bib_key"].split(":").last
36
+ [Bib::Docidentifier.new(content: isbn, type: "ISBN", primary: true)]
37
+ end
38
+
39
+ def source
40
+ [Bib::Uri.new(content: @doc["recordURL"], type: "src")]
41
+ end
42
+
43
+ def contributor
44
+ create_authors + creaate_publishers
45
+ end
46
+
47
+ def create_authors
48
+ @doc["data"]["authors"].map do |a|
49
+ name = Bib::FullName.new(
50
+ completename: Bib::LocalizedString.new(content: a["name"]),
51
+ )
52
+ person = Bib::Person.new(
53
+ name: name,
54
+ uri: a["url"] ? [Bib::Uri.new(content: a["url"])] : [],
55
+ )
56
+ Bib::Contributor.new(
57
+ person: person,
58
+ role: [Bib::Contributor::Role.new(type: "author")],
59
+ )
60
+ end
61
+ end
62
+
63
+ def creaate_publishers
64
+ @doc["data"]["publishers"].map do |p|
65
+ org = Bib::Organization.new(
66
+ name: [Bib::TypedLocalizedString.new(content: p["name"])],
67
+ )
68
+ Bib::Contributor.new(
69
+ organization: org,
70
+ role: [Bib::Contributor::Role.new(type: "publisher")],
71
+ )
72
+ end
73
+ end
74
+
75
+ def date
76
+ @doc["publishDates"].map { Bib::Date.new type: "published", at: _1 }
77
+ end
78
+
79
+ def place
80
+ @doc["data"]["publish_places"]&.map { Bib::Place.new city: _1["name"] }
81
+ end
82
+
83
+ def ext
84
+ Bib::Ext.new(flavor: "isbn")
85
+ end
86
+ end
87
+ end
88
+ end