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,149 @@
1
+ require_relative "../itu"
2
+
3
+ module Relaton
4
+ module Itu
5
+ # Incremental write path for harvested ITU-R records (issue #75).
6
+ #
7
+ # The ITU-R dataset cannot be rebuilt from scratch — DataCrawlerR reads the
8
+ # pages ITU still serves, and those expose **less** than the decommissioned
9
+ # RunSearch feed did. Two consequences drive this module:
10
+ #
11
+ # 1. **A published date must never be rewritten.** A Recommendation page
12
+ # carries only its approval date, while the preserved record holds the
13
+ # publication date RunSearch served — measured on the whole BO series,
14
+ # those differ for every record and the *year* differs for 59% of them.
15
+ # Overwriting would change which edition answers a dated reference. (A
16
+ # Report page does carry the publication date, so reports reproduce it;
17
+ # the rule costs nothing there.)
18
+ # 2. **A harvest is a partial view.** Only the families the crawler
19
+ # implements are seen, so a run must add and backfill, never delete, and
20
+ # must leave untouched records byte-identical so the data repo's diff
21
+ # shows only what actually changed.
22
+ #
23
+ # Merge rules, applied per record: `date` is kept as published, always;
24
+ # `title` and `source` are filled in only when the published record has
25
+ # none; everything else is left alone. A record whose published counterpart
26
+ # has a **different doctype** is a collision — an ITU-R report and
27
+ # recommendation in the same series can share a docidentifier, and therefore
28
+ # a filename — so it is reported and skipped rather than silently
29
+ # overwriting the other document.
30
+ module DataMergeR
31
+ extend self
32
+
33
+ #
34
+ # Merge harvested records into the dataset the fetcher writes to.
35
+ #
36
+ # @param items [Array<Relaton::Itu::ItemData>] as DataCrawlerR#harvest returns
37
+ # @param fetcher [Relaton::Itu::DataFetcher] supplies output_file/write_file
38
+ # and the index, so harvested records get the same pubid guard and
39
+ # unparseable-id reporting as the ITU-T harvest
40
+ #
41
+ # @return [Hash] { added:, backfilled:, unchanged:, skipped:,
42
+ # collisions: [[file, published_doctype, harvested_doctype], …] }
43
+ #
44
+ def write_all(items, fetcher)
45
+ stats = { added: 0, backfilled: 0, unchanged: 0, skipped: 0, collisions: [] }
46
+ seen = {}
47
+ items.each do |bib|
48
+ id = primary_id(bib)
49
+ unless id
50
+ stats[:skipped] += 1
51
+ Util.error "ITU-R merge: record with no primary docidentifier skipped"
52
+ next
53
+ end
54
+
55
+ file = fetcher.output_file id
56
+ # First writer of a filename keeps it; a later claimant is reported and
57
+ # dropped, never merged into a document it isn't.
58
+ if (other = seen[file])
59
+ record_collision stats, file, other, "#{id} (#{doctype bib})", "this harvest"
60
+ next
61
+ end
62
+ seen[file] = "#{id} (#{doctype bib})"
63
+ merge_one bib, id, file, fetcher, stats
64
+ rescue => e # rubocop:disable Style/RescueStandardError
65
+ # One unreadable published file must not discard an hour of crawling.
66
+ stats[:skipped] += 1
67
+ Util.error "ITU-R merge: #{id || '(no id)'} skipped: #{e.message}"
68
+ end
69
+ stats
70
+ end
71
+
72
+ private
73
+
74
+ # @return [void]
75
+ def merge_one(bib, id, file, fetcher, stats)
76
+ unless File.exist? file
77
+ fetcher.write_file bib
78
+ stats[:added] += 1
79
+ return
80
+ end
81
+
82
+ published = Item.from_yaml File.read(file, encoding: "UTF-8")
83
+ published_id = primary_id published
84
+ # Both halves matter: a different doctype means a report and a
85
+ # recommendation share a filename, and a different id means two docids
86
+ # sanitize to one filename (`output_file` collapses `.`, `/` and spaces
87
+ # alike, so `ITU-R BO.4/BL/4` and `ITU-R BO.4-BL-4` would meet here).
88
+ if doctype(published) != doctype(bib) || published_id != id
89
+ record_collision stats, file, "#{published_id} (#{doctype published})",
90
+ "#{id} (#{doctype bib})", "the published dataset"
91
+ return
92
+ end
93
+
94
+ if backfill published, bib
95
+ fetcher.write_file published
96
+ stats[:backfilled] += 1
97
+ else
98
+ # Not rewritten: an identical re-serialization would churn the data
99
+ # repo's diff. Index it anyway — the index is rebuilt from scratch on
100
+ # every run, so a record that is not written still has to be in it.
101
+ # Indexed by the id the *file* carries, as #index_files does.
102
+ fetcher.index_primary published_id, file
103
+ stats[:unchanged] += 1
104
+ end
105
+ end
106
+
107
+ # Fill only what the published record is missing. `date` is deliberately
108
+ # absent from this list — see the module comment.
109
+ #
110
+ # @param published [Relaton::Itu::Item] mutated in place
111
+ # @param bib [Relaton::Itu::ItemData] the harvested record
112
+ # @return [Boolean] whether anything was filled in
113
+ def backfill(published, bib)
114
+ filled = false
115
+ if published.source.nil? || published.source.empty?
116
+ published.source = bib.source
117
+ filled ||= !(bib.source.nil? || bib.source.empty?)
118
+ end
119
+ if published.title.nil? || published.title.empty?
120
+ published.title = bib.title
121
+ filled ||= !(bib.title.nil? || bib.title.empty?)
122
+ end
123
+ filled
124
+ end
125
+
126
+ # @return [void]
127
+ def record_collision(stats, file, kept, dropped, where)
128
+ stats[:skipped] += 1
129
+ stats[:collisions] << [file, kept, dropped]
130
+ Util.error "ITU-R merge: filename collision on #{file} — #{kept} in #{where} vs " \
131
+ "harvested #{dropped}; not overwritten"
132
+ end
133
+
134
+ # Strictly the primary docid: DataFetcher#write_file reads
135
+ # `docidentifier.find(&:primary).content` with no fallback, so a record
136
+ # without one has nowhere to be written and is skipped here instead.
137
+ #
138
+ # @return [String, nil]
139
+ def primary_id(bib)
140
+ bib.docidentifier.find(&:primary)&.content
141
+ end
142
+
143
+ # @return [String, nil]
144
+ def doctype(bib)
145
+ bib.ext&.doctype&.content
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,214 @@
1
+ module Relaton
2
+ module Itu
3
+ # Map one normalized ITU-R row to an ItemData.
4
+ #
5
+ # The row comes from DataCrawlerR's three-level `/pub` + `/rec` crawl (issue
6
+ # #75), which replaced the decommissioned RunSearch result hash this module
7
+ # used to consume. The split mirrors DataParserT: the crawler owns the HTTP
8
+ # and the page scraping, this module owns the mapping, so it stays a pure
9
+ # unit with no network in its specs. Row keys:
10
+ #
11
+ # :id "R-REC-BO.1130-5-202602-I" page id
12
+ # :code "BO.1130-5 (02/2026)" displayed code -> primary docid
13
+ # :title English title
14
+ # :status "In force (Main)" | "Superseded" | … (scraped, not modelled)
15
+ # :date "2026-02-18" | "2026-02" approval date for a Recommendation,
16
+ # publication date for a Report
17
+ # :url the record's landing page
18
+ # :pdf absolute dms_pubrec/dms_pub URL
19
+ # :family "R-REC" | "R-REP" | "R-QUE" | "R-RES" | "R-HDB"
20
+ module DataParserR
21
+ extend self
22
+
23
+ FAMILY_DOCTYPE = {
24
+ "R-REC" => "recommendation",
25
+ "R-REP" => "technical-report",
26
+ "R-QUE" => "question",
27
+ "R-RES" => "resolution",
28
+ "R-HDB" => "handbook",
29
+ }.freeze
30
+
31
+ #
32
+ # Parse an ITU-R document from a normalized crawler row.
33
+ #
34
+ # @param row [Hash] see the key list above
35
+ # @param errors [Hash] shared error tally, `&&=`-narrowed per field so a
36
+ # field that succeeded once is never reported as missing
37
+ #
38
+ # @return [Relaton::Itu::ItemData, nil] nil when the family is unknown
39
+ #
40
+ def parse(row, errors = {})
41
+ doctype = fetch_doctype(row, errors)
42
+ return unless doctype
43
+
44
+ docid = fetch_docid(row, errors)
45
+ # A record with no primary docid can't be written or indexed —
46
+ # DataFetcher#write_file reads `docidentifier.find(&:primary).content` —
47
+ # so drop it here, as DataParserT does.
48
+ return if docid.empty?
49
+
50
+ Relaton::Itu::ItemData.new(
51
+ docidentifier: docid, title: fetch_title(row, errors),
52
+ date: fetch_date(row, errors), language: ["en"],
53
+ source: fetch_source(row, errors), script: ["Latn"],
54
+ type: "standard", ext: Relaton::Itu::Ext.new(doctype: doctype, flavor: "itu"),
55
+ )
56
+ end
57
+
58
+ # Each ITU-R family spells its identifier differently, and the published
59
+ # dataset is the authority on which spelling. Verified against
60
+ # relaton-data-itu:
61
+ #
62
+ # R-REC the displayed code "BO.1130-5 (02/2026)" -> ITU-R BO.1130-5
63
+ # R-REP the same, prefixed "BO.1227-2 (1998)" -> Report ITU-R BO.1227-2
64
+ # R-QUE the same, + a colon "202-2/1" -> ITU-R 202-2/1:
65
+ # R-RES the **page id** R-RES-R.1-9-2023 -> ITU-R R.1-9
66
+ # R-HDB the **page id** R-HDB-43-2013 -> ITU-R 43.HDB (2013)
67
+ #
68
+ # Three of those need saying out loud. A **Report** is prefixed because
69
+ # Recommendations and Reports number independently, so `ITU-R BT.2020-1`
70
+ # alone names two different documents (pubid #327 types the prefixed form
71
+ # `pubid:itu:report`, and `output_file` sends it to `report-itu-r-*.yaml`
72
+ # instead of colliding). A **Resolution** cannot use its displayed code at
73
+ # all: the page renders "Res.1-9 (2023)" while the published record is
74
+ # `ITU-R R.1-9`, which only the id carries. A **Handbook** likewise: the
75
+ # index lists its *title* and the leaf shows only a year — see
76
+ # #handbook_docid.
77
+ #
78
+ # The code is NBSP-folded first — the cells are padded with `&nbsp;`, which
79
+ # neither `\s` nor String#strip match, and an NBSP left in a docid
80
+ # sanitizes into the filename and defeats `Pubid::Itu`.
81
+ #
82
+ # @param row [Hash]
83
+ # @return [String, nil] nil when the row carries nothing to build from
84
+ def family_docid(row)
85
+ # " " spelled as an escape on purpose: a literal NBSP here is invisible
86
+ # and has been silently lost by tooling before.
87
+ #
88
+ # The date suffix is cut at the bare `(`, leaving the space before it to
89
+ # #strip. A leading `\s*` would make this polynomial-time (CodeQL
90
+ # rb/polynomial-redos): unanchored, it can start matching anywhere in a
91
+ # run of spaces, so a code that never reaches a `(` costs one pass per
92
+ # space. Same result, no ambiguity.
93
+ code = row[:code].to_s.tr(" ", " ").sub(/\(.*\z/m, "").strip
94
+ # The two id-derived families, before `code` gets a say.
95
+ return "ITU-R #{resolution_number row}" if row[:family] == "R-RES"
96
+ return handbook_docid(row) if row[:family] == "R-HDB"
97
+ return nil if code.empty?
98
+
99
+ case row[:family]
100
+ when "R-REP" then "Report ITU-R #{code}"
101
+ when "R-QUE" then "ITU-R #{code}:"
102
+ else "ITU-R #{code}"
103
+ end
104
+ end
105
+
106
+ # "R-HDB-43-2013" -> "ITU-R 43.HDB (2013)".
107
+ #
108
+ # The displayed code is unusable twice over: the index cell holds the
109
+ # handbook's *title*, and the leaf holds a year that can disagree with its
110
+ # own id (`R-HDB-43-2013` displays "2014"). The id is the only consistent
111
+ # source, so the year comes from there.
112
+ #
113
+ # Keyed **per edition** because ITU publishes several per handbook (43 has
114
+ # 2002, 2013 and 2026) and `Pubid::Itu` models the year, so they stay
115
+ # distinct records. The bare `ITU-R 43` that four published records carry
116
+ # parses as a *recommendation*, claiming a number that is not its own —
117
+ # this is what replaces it.
118
+ #
119
+ # @param row [Hash]
120
+ # @return [String, nil]
121
+ def handbook_docid(row)
122
+ m = row[:id].to_s.match(/\AR-HDB-(?<number>\d+)(?:-(?<year>(?:19|20)\d{2}))?/)
123
+ return nil unless m
124
+
125
+ m[:year] ? "ITU-R #{m[:number]}.HDB (#{m[:year]})" : "ITU-R #{m[:number]}.HDB"
126
+ end
127
+
128
+ # "R-RES-R.1-9-2023" -> "R.1-9"
129
+ #
130
+ # @param row [Hash]
131
+ # @return [String, nil]
132
+ def resolution_number(row)
133
+ n = row[:id].to_s.sub(/\AR-RES-/, "").sub(/-(?:19|20)\d{2}\z/, "")
134
+ n.empty? ? nil : n
135
+ end
136
+
137
+ # @param row [Hash]
138
+ # @return [Array<Relaton::Bib::Docidentifier>]
139
+ def fetch_docid(row, errors = {})
140
+ content = family_docid row
141
+ if content.nil? || content == "ITU-R "
142
+ errors[:docid] &&= true
143
+ return []
144
+ end
145
+
146
+ r = [Docidentifier.new(type: "ITU", content: content, primary: true)]
147
+ errors[:docid] &&= r.empty?
148
+ r
149
+ end
150
+
151
+ # @param row [Hash]
152
+ # @return [Array<Relaton::Bib::Title>]
153
+ def fetch_title(row, errors = {})
154
+ content = row[:title].to_s.strip
155
+ if content.empty?
156
+ errors[:title] &&= true
157
+ return []
158
+ end
159
+
160
+ r = [Relaton::Bib::Title.new(type: "main", content: content, language: "en", script: "Latn")]
161
+ errors[:title] &&= r.empty?
162
+ r
163
+ end
164
+
165
+ # Whatever date the crawler could see: for a **Recommendation** that is the
166
+ # approval date — *not* the publication date the preserved records carry,
167
+ # which died with RunSearch (issue #75), which is why DataMergeR never
168
+ # rewrites one — and for a **Report** it is the publication date itself,
169
+ # read off the edition page's posted files. Day precision when it comes
170
+ # from the page, month or year precision when derived from the page id.
171
+ #
172
+ # @param row [Hash]
173
+ # @return [Array<Relaton::Bib::Date>]
174
+ def fetch_date(row, errors = {})
175
+ date = row[:date].to_s.strip
176
+ if date.empty?
177
+ errors[:date] &&= true
178
+ return []
179
+ end
180
+
181
+ r = [Relaton::Bib::Date.new(type: "published", at: date)]
182
+ errors[:date] &&= r.empty?
183
+ r
184
+ end
185
+
186
+ # @param row [Hash]
187
+ # @return [Array<Relaton::Bib::Uri>]
188
+ def fetch_source(row, errors = {})
189
+ pdf = row[:pdf].to_s.strip
190
+ if pdf.empty?
191
+ errors[:source] &&= true
192
+ return []
193
+ end
194
+
195
+ r = [Relaton::Bib::Uri.new(type: "pdf", content: pdf)]
196
+ errors[:source] &&= r.empty?
197
+ r
198
+ end
199
+
200
+ # @param row [Hash]
201
+ # @return [Relaton::Itu::Doctype, nil]
202
+ def fetch_doctype(row, errors = {})
203
+ mapped = FAMILY_DOCTYPE[row[:family]]
204
+ unless mapped
205
+ errors[:doctype] &&= true
206
+ return
207
+ end
208
+
209
+ errors[:doctype] &&= false
210
+ Doctype.new(content: mapped)
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,228 @@
1
+ require_relative "../itu"
2
+ require_relative "recommendation_parser"
3
+
4
+ module Relaton
5
+ module Itu
6
+ # Parse a single row of the ITU-T recommendation index returned by the
7
+ # mws/api/recommendations/searchRecs endpoint (see DataFetcher#search_recs)
8
+ # into an ItemData. Recommendations and supplements share one row schema and
9
+ # are distinguished by "Suppl" in rec_name; each edition is its own row, so
10
+ # the docid keeps the (MM/YYYY) edition date (e.g. "ITU-T A.1 (10/2000)") —
11
+ # which Pubid::Itu parses per edition, keeping index rows and filenames
12
+ # unique across editions. Mirrors DataParserR (the ITU-R row parser).
13
+ #
14
+ # The searchRecs row is metadata-thin (docid/title/date/source/doctype). When
15
+ # an `agent` is given, each record is **enriched** with the same
16
+ # `getRecHdrDetail`-sourced fields the live runtime path emits — abstract,
17
+ # ISO/IEC co-identifier, editorial-group contributors, status — via the shared
18
+ # `RecommendationFields` (through `RecommendationParser`), so the harvested
19
+ # record matches a live `Bibliography.get`. Enrichment is best-effort: a
20
+ # detail-fetch failure degrades to the thin record rather than losing it.
21
+ module DataParserT
22
+ extend self
23
+
24
+ # rec_name markers → Doctype. Ordered; first match wins. A plain edition
25
+ # (no marker) is a "recommendation". Values are members of Doctype::TYPES.
26
+ DOCTYPE_MARKERS = {
27
+ /\bSuppl\b/ => "recommendation-supplement",
28
+ /\bAmd\b/ => "recommendation-amendment",
29
+ /\bCor\b/ => "recommendation-corrigendum",
30
+ /\bAnnex\b/ => "recommendation-annex",
31
+ }.freeze
32
+
33
+ # The `errors` hash is threaded through the fetch_* helpers rather than
34
+ # held in an ivar: this module is `extend self`, so an ivar would be state
35
+ # shared by every caller — and DataFetcher#fetch_recommendations parses
36
+ # rows from a pool of threads.
37
+ #
38
+ # @param row [Hash] single row from searchRecs Data
39
+ # @param agent [Mechanize, nil] when present, enrich via getRecHdrDetail
40
+ # @param errors [Hash]
41
+ # @return [Relaton::Itu::ItemData, nil]
42
+ def parse(row, agent = nil, errors = {}, cache: NullCache.instance)
43
+ docid = fetch_docid(row, errors)
44
+ return if docid.empty?
45
+
46
+ enr = enrichment(row, agent, cache)
47
+ date = fetch_date(row, errors)
48
+ row_source = fetch_source(row, errors)
49
+ Relaton::Itu::ItemData.new(
50
+ docidentifier: docid + enr.fetch(:iso, []),
51
+ title: fetch_title(row, errors),
52
+ edition: enr[:edition],
53
+ abstract: enr.fetch(:abstract, []),
54
+ date: date, language: ["en"],
55
+ status: enr[:status],
56
+ relation: enr.fetch(:relation, []),
57
+ contributor: enr.fetch(:contributor, []),
58
+ copyright: fetch_copyright(date),
59
+ place: [Relaton::Bib::Place.new(city: "Geneva")],
60
+ source: enr[:source] || row_source, script: ["Latn"],
61
+ type: "standard",
62
+ ext: Relaton::Itu::Ext.new(doctype: fetch_doctype(row, errors), flavor: "itu"),
63
+ )
64
+ end
65
+
66
+ # Best-effort getRecHdrDetail enrichment for one record. Returns {} when
67
+ # there is no agent or the detail fetch fails, so the record still gets its
68
+ # thin fields. ITU-T records are always sector T → abbreviation "ITU",
69
+ # bureau "T".
70
+ #
71
+ # @param row [Hash]
72
+ # @param agent [Mechanize, nil]
73
+ # @param cache [#fetch, #warm] shared across the worker pool, so the
74
+ # family-invariant endpoints are fetched once per recommendation rather
75
+ # than once per edition. Like `errors`, it is threaded through as a
76
+ # parameter rather than held as state — DataParserT is `extend self`.
77
+ # The source is the handle URI and the PDF URI, as on the live path. It
78
+ # is nil when the header has no handle_id, so the row source is used.
79
+ # @return [Hash] { iso:, abstract:, status:, edition:, relation:,
80
+ # contributor:, source: }
81
+ def enrichment(row, agent, cache = NullCache.instance)
82
+ return {} unless agent && row["idrec"]
83
+
84
+ f = RecommendationParser.new(agent, row["idrec"], false, cache: cache)
85
+ ed = f.fetch_edition
86
+ {
87
+ iso: Array(f.iso_docid),
88
+ abstract: f.fetch_abstract,
89
+ status: f.fetch_status,
90
+ edition: (Relaton::Bib::Edition.new(content: ed) if ed),
91
+ relation: f.fetch_relations,
92
+ contributor: [f.publisher("ITU"), f.editorial_group("T")].compact,
93
+ source: (f.fetch_source if f.doc["handle_id"]),
94
+ }
95
+ rescue StandardError => e
96
+ Util.warn "ITU-T enrichment failed for idrec=#{row['idrec']}: #{e.message}"
97
+ {}
98
+ end
99
+
100
+ # The ITU copyright, from the record's own publication year — no detail
101
+ # fetch needed, so a thin (un-enriched) record carries it too. Mirrors
102
+ # `Scraper#fetch_copyright` on the live path.
103
+ #
104
+ # @param date [Array<Relaton::Bib::Date>] the record's dates
105
+ # @return [Array<Relaton::Bib::Copyright>]
106
+ def fetch_copyright(date)
107
+ year = date.first&.at.to_s[/\d{4}/]
108
+ return [] unless year
109
+
110
+ org = Relaton::Bib::Organization.new(
111
+ name: [Relaton::Bib::TypedLocalizedString.new(content: "International Telecommunication Union")],
112
+ abbreviation: Relaton::Bib::LocalizedString.new(content: "ITU"),
113
+ uri: [Relaton::Bib::Uri.new(content: "www.itu.int")],
114
+ )
115
+ owner = [Relaton::Bib::ContributionInfo.new(organization: org)]
116
+ [Relaton::Bib::Copyright.new(from: year, owner: owner)]
117
+ end
118
+
119
+ # The primary docid is the rec_name prefixed with "ITU-T", keeping the
120
+ # trailing " (MM/YYYY)" edition date so Pubid::Itu identifies each edition
121
+ # distinctly (matches the existing "ITU-T L.163 (11/2018)" convention).
122
+ #
123
+ # @param row [Hash]
124
+ # @return [Array<Relaton::Itu::Docidentifier>]
125
+ def fetch_docid(row, errors = {})
126
+ name = normalize_rec_name row["rec_name"]
127
+ if name.empty?
128
+ errors[:docid] &&= true
129
+ return []
130
+ end
131
+
132
+ r = [Docidentifier.new(type: "ITU", content: "ITU-T #{name}", primary: true)]
133
+ errors[:docid] &&= r.empty?
134
+ r
135
+ end
136
+
137
+ # One rule, for the one spelling `::Pubid::Itu` deliberately will not take:
138
+ # a space where the series dot belongs ("G 231 (10/1976)"). pubid rejects it
139
+ # on purpose, because a space there is ambiguous against the series-only
140
+ # supplement form ("G Suppl. 1"), so relaton canonicalises it rather than
141
+ # leaving 4 records unindexed. `#index_primary` drops ids pubid rejects, and
142
+ # a dropped record is written but never indexed — reachable only through the
143
+ # live `rec.aspx` fallback.
144
+ #
145
+ # This changes **no filename**: `Core::DataFetcher#output_file` collapses
146
+ # runs of whitespace and punctuation alike, so `"G 231 (10/1976)"` and
147
+ # `"G.231 (10/1976)"` both yield `itu-t-g-231-10-1976.yaml`. The affected
148
+ # records simply gain an index row.
149
+ #
150
+ # Everything else searchRecs spells oddly — the doubled space, `Suppl.1` run
151
+ # into its number, and bare `v10`/`V2`/`v.1` versions — **parses natively**
152
+ # as of pubid #325, so the rules that used to rewrite those are gone: pubid
153
+ # now canonicalises on `to_s` itself and ITU's own spelling is kept in the
154
+ # docid. Forms pubid cannot parse are still left alone; guessing a spelling
155
+ # would invent identifiers rather than canonicalise them.
156
+ #
157
+ # @param rec_name [String, nil]
158
+ # @return [String]
159
+ def normalize_rec_name(rec_name)
160
+ rec_name.to_s.strip.sub(/\A([A-Z]+) (\d)/, '\1.\2')
161
+ end
162
+
163
+ # @param row [Hash]
164
+ # @return [Array<Relaton::Bib::Title>]
165
+ def fetch_title(row, errors = {})
166
+ content = row["title"].to_s.strip
167
+ r = content.empty? ? [] : [Relaton::Bib::Title.new(type: "main", content: content, language: "en", script: "Latn")]
168
+ errors[:title] &&= r.empty?
169
+ r
170
+ end
171
+
172
+ # Prefer a full day-precision approval_date (YYYY-MM-DD, matching the live
173
+ # runtime path); fall back to the (MM/YYYY) edition date in rec_name; and
174
+ # only then to a coarser (year / year-month) approval_date. Ordering this way
175
+ # means a coarse or malformed approval_date never downgrades precision below
176
+ # the always-well-formed rec_name edition date.
177
+ #
178
+ # @param row [Hash]
179
+ # @return [Array<Relaton::Bib::Date>]
180
+ def fetch_date(row, errors = {})
181
+ approval = row["approval_date"].to_s
182
+ date = approval[/\d{4}-\d{2}-\d{2}/] || rec_name_date(row["rec_name"]) || approval[/\d{4}(-\d{2})?/]
183
+ if date.nil? || date.empty?
184
+ errors[:date] &&= true
185
+ return []
186
+ end
187
+
188
+ r = [Relaton::Bib::Date.new(type: "published", at: date)]
189
+ errors[:date] &&= r.empty?
190
+ r
191
+ end
192
+
193
+ # @param row [Hash]
194
+ # @return [Array<Relaton::Bib::Uri>]
195
+ def fetch_source(row, errors = {})
196
+ link = row["dms_link"].to_s.strip
197
+ if link.empty? || link == "-"
198
+ errors[:source] &&= true
199
+ return []
200
+ end
201
+
202
+ r = [Relaton::Bib::Uri.new(type: "src", content: link)]
203
+ errors[:source] &&= r.empty?
204
+ r
205
+ end
206
+
207
+ # @param row [Hash]
208
+ # @return [Relaton::Itu::Doctype]
209
+ def fetch_doctype(row, errors = {})
210
+ name = row["rec_name"].to_s
211
+ content = DOCTYPE_MARKERS.find { |re, _| name.match?(re) }&.last || "recommendation"
212
+ errors[:doctype] &&= false
213
+ Doctype.new(content: content)
214
+ end
215
+
216
+ private
217
+
218
+ # "A.1 (10/2000)" -> "2000-10"
219
+ # @param name [String, nil]
220
+ # @return [String, nil]
221
+ def rec_name_date(name)
222
+ return unless name =~ %r{\((\d{2})/(\d{4})\)}
223
+
224
+ "#{$2}-#{$1}"
225
+ end
226
+ end
227
+ end
228
+ end