pubid 2.0.0.pre.alpha.1 → 2.0.0.pre.alpha.3

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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +27 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -0
  6. data/lib/pubid/amca/identifiers/base.rb +0 -26
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -17
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -13
  9. data/lib/pubid/amca/renderer.rb +82 -0
  10. data/lib/pubid/amca/single_identifier.rb +0 -23
  11. data/lib/pubid/amca/urn_parser.rb +28 -0
  12. data/lib/pubid/amca.rb +42 -1
  13. data/lib/pubid/ansi/builder.rb +5 -3
  14. data/lib/pubid/ansi/identifier.rb +1 -1
  15. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  16. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  17. data/lib/pubid/ansi/renderer.rb +53 -0
  18. data/lib/pubid/ansi/single_identifier.rb +2 -31
  19. data/lib/pubid/ansi/urn_generator.rb +3 -38
  20. data/lib/pubid/ansi/urn_parser.rb +23 -0
  21. data/lib/pubid/ansi.rb +38 -3
  22. data/lib/pubid/api/builder.rb +29 -74
  23. data/lib/pubid/api/identifier.rb +0 -4
  24. data/lib/pubid/api/identifiers/base.rb +0 -2
  25. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  26. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  27. data/lib/pubid/api/identifiers/mpms.rb +1 -17
  28. data/lib/pubid/api/identifiers/publication.rb +0 -2
  29. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  30. data/lib/pubid/api/identifiers/specification.rb +0 -2
  31. data/lib/pubid/api/identifiers/standard.rb +0 -2
  32. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  33. data/lib/pubid/api/identifiers/typeless_standard.rb +1 -14
  34. data/lib/pubid/api/identifiers.rb +18 -0
  35. data/lib/pubid/api/renderer.rb +89 -0
  36. data/lib/pubid/api/single_identifier.rb +1 -13
  37. data/lib/pubid/api/urn_generator.rb +0 -18
  38. data/lib/pubid/api/urn_parser.rb +35 -0
  39. data/lib/pubid/api.rb +51 -5
  40. data/lib/pubid/ashrae/builder.rb +3 -3
  41. data/lib/pubid/ashrae/identifier.rb +6 -0
  42. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  43. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  44. data/lib/pubid/ashrae/identifiers/base.rb +3 -0
  45. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  46. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  47. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  48. data/lib/pubid/ashrae/renderer.rb +117 -0
  49. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  50. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  51. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  52. data/lib/pubid/ashrae.rb +42 -1
  53. data/lib/pubid/asme/components/code.rb +10 -2
  54. data/lib/pubid/asme/identifiers/base.rb +0 -60
  55. data/lib/pubid/asme/renderer.rb +66 -0
  56. data/lib/pubid/asme/urn_parser.rb +31 -0
  57. data/lib/pubid/asme.rb +42 -1
  58. data/lib/pubid/astm/components/code.rb +9 -0
  59. data/lib/pubid/{jis → astm}/components.rb +1 -1
  60. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  61. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  62. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  63. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  64. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  65. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  66. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  67. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  68. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  69. data/lib/pubid/astm/identifiers.rb +18 -0
  70. data/lib/pubid/astm/renderer.rb +172 -0
  71. data/lib/pubid/astm/single_identifier.rb +0 -10
  72. data/lib/pubid/astm/urn_parser.rb +30 -0
  73. data/lib/pubid/astm.rb +39 -27
  74. data/lib/pubid/bsi/builder.rb +21 -12
  75. data/lib/pubid/bsi/identifier.rb +8 -2
  76. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  77. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  78. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  79. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  80. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  81. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  82. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  83. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  84. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  85. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  87. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  88. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  89. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  90. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  91. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  92. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  93. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  94. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  95. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  96. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  97. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  98. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  99. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  100. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  101. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  102. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  103. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  104. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  105. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  106. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  107. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  108. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  109. data/lib/pubid/bsi/identifiers.rb +0 -1
  110. data/lib/pubid/bsi/renderer.rb +1050 -0
  111. data/lib/pubid/bsi/single_identifier.rb +6 -70
  112. data/lib/pubid/bsi/urn_generator.rb +2 -3
  113. data/lib/pubid/bsi/urn_parser.rb +52 -0
  114. data/lib/pubid/bsi.rb +224 -1
  115. data/lib/pubid/builder/base.rb +57 -10
  116. data/lib/pubid/bundled_identifier.rb +0 -1
  117. data/lib/pubid/ccsds/builder.rb +4 -3
  118. data/lib/pubid/ccsds/identifier.rb +66 -1
  119. data/lib/pubid/ccsds/identifiers/base.rb +11 -50
  120. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  121. data/lib/pubid/ccsds/parser.rb +4 -2
  122. data/lib/pubid/ccsds/single_identifier.rb +4 -1
  123. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  124. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  125. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  126. data/lib/pubid/ccsds.rb +39 -1
  127. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  128. data/lib/pubid/cen_cenelec/identifier.rb +8 -2
  129. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  130. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  131. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  132. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  133. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  135. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  136. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  137. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  138. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  140. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  141. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  143. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  144. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  145. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  146. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  147. data/lib/pubid/cen_cenelec.rb +168 -1
  148. data/lib/pubid/cie/components/code.rb +8 -0
  149. data/lib/pubid/cie/identifier.rb +6 -4
  150. data/lib/pubid/cie/urn_parser.rb +28 -0
  151. data/lib/pubid/cie.rb +43 -1
  152. data/lib/pubid/components/adoption.rb +104 -0
  153. data/lib/pubid/components/code.rb +22 -8
  154. data/lib/pubid/components/date.rb +23 -16
  155. data/lib/pubid/components/edition.rb +9 -6
  156. data/lib/pubid/components/iteration.rb +32 -0
  157. data/lib/pubid/components/language.rb +6 -4
  158. data/lib/pubid/components/locality.rb +10 -1
  159. data/lib/pubid/components/publisher.rb +9 -6
  160. data/lib/pubid/components/relationship.rb +151 -0
  161. data/lib/pubid/components/stage.rb +5 -14
  162. data/lib/pubid/components/supplement.rb +184 -0
  163. data/lib/pubid/components/type.rb +5 -15
  164. data/lib/pubid/components/typed_stage.rb +11 -8
  165. data/lib/pubid/components.rb +4 -0
  166. data/lib/pubid/core/update_codes.rb +28 -7
  167. data/lib/pubid/csa/identifier.rb +0 -3
  168. data/lib/pubid/csa/identifiers/base.rb +2 -122
  169. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  170. data/lib/pubid/csa/identifiers/series.rb +2 -102
  171. data/lib/pubid/csa/renderer.rb +292 -0
  172. data/lib/pubid/csa/urn_generator.rb +1 -1
  173. data/lib/pubid/csa/urn_parser.rb +33 -0
  174. data/lib/pubid/csa.rb +42 -1
  175. data/lib/pubid/etsi/components/code.rb +9 -2
  176. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  177. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  178. data/lib/pubid/etsi/renderer.rb +42 -0
  179. data/lib/pubid/etsi/urn_parser.rb +34 -0
  180. data/lib/pubid/etsi.rb +42 -1
  181. data/lib/pubid/export/exporter.rb +4 -46
  182. data/lib/pubid/export/flavor_exporter.rb +111 -278
  183. data/lib/pubid/export.rb +0 -6
  184. data/lib/pubid/identifier.rb +10 -18
  185. data/lib/pubid/identifier_facade.rb +114 -0
  186. data/lib/pubid/identifier_metadata.rb +1 -1
  187. data/lib/pubid/idf/builder.rb +3 -3
  188. data/lib/pubid/idf/identifier.rb +3 -6
  189. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  190. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  191. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  192. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  193. data/lib/pubid/idf/parser.rb +3 -2
  194. data/lib/pubid/idf/renderer.rb +84 -0
  195. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  196. data/lib/pubid/idf/urn_generator.rb +4 -39
  197. data/lib/pubid/idf/urn_parser.rb +25 -0
  198. data/lib/pubid/idf.rb +51 -1
  199. data/lib/pubid/iec/builder.rb +48 -65
  200. data/lib/pubid/iec/components/code.rb +9 -32
  201. data/lib/pubid/iec/components/publisher.rb +1 -1
  202. data/lib/pubid/iec/components.rb +14 -0
  203. data/lib/pubid/iec/identifier.rb +276 -3
  204. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  205. data/lib/pubid/iec/identifiers/base.rb +8 -28
  206. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  207. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  208. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -30
  209. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  210. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -26
  211. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  212. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  213. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  214. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  215. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  216. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -15
  217. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  218. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  219. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  220. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  222. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  223. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -23
  224. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  225. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  226. data/lib/pubid/iec/identifiers.rb +30 -0
  227. data/lib/pubid/iec/parser.rb +20 -14
  228. data/lib/pubid/iec/renderer.rb +254 -0
  229. data/lib/pubid/iec/single_identifier.rb +6 -12
  230. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  231. data/lib/pubid/iec/urn_generator.rb +57 -171
  232. data/lib/pubid/iec/urn_parser.rb +53 -252
  233. data/lib/pubid/iec.rb +40 -68
  234. data/lib/pubid/ieee/builder.rb +12 -12
  235. data/lib/pubid/ieee/components/code.rb +8 -0
  236. data/lib/pubid/ieee/components/draft.rb +14 -0
  237. data/lib/pubid/ieee/components/relationship.rb +5 -149
  238. data/lib/pubid/ieee/identifier.rb +6 -0
  239. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  240. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  241. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  242. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  243. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  245. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  246. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  247. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  248. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  249. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  250. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  251. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  252. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  253. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  254. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  255. data/lib/pubid/ieee/pre_parser.rb +301 -0
  256. data/lib/pubid/ieee/renderer.rb +307 -0
  257. data/lib/pubid/ieee/urn_parser.rb +34 -0
  258. data/lib/pubid/ieee.rb +62 -1
  259. data/lib/pubid/ieee_debug.rb +0 -1
  260. data/lib/pubid/iho/builder.rb +2 -2
  261. data/lib/pubid/iho/identifier.rb +8 -0
  262. data/lib/pubid/iho/identifiers/base.rb +49 -10
  263. data/lib/pubid/iho/identifiers/bibliographic.rb +0 -4
  264. data/lib/pubid/iho/identifiers/circular_letter.rb +0 -4
  265. data/lib/pubid/iho/identifiers/miscellaneous.rb +0 -4
  266. data/lib/pubid/iho/identifiers/publication.rb +0 -4
  267. data/lib/pubid/iho/identifiers/standard.rb +0 -4
  268. data/lib/pubid/iho/parser.rb +3 -3
  269. data/lib/pubid/iho/renderer.rb +30 -0
  270. data/lib/pubid/iho/urn_generator.rb +3 -3
  271. data/lib/pubid/iho/urn_parser.rb +58 -0
  272. data/lib/pubid/iho.rb +50 -1
  273. data/lib/pubid/iso/builder.rb +59 -53
  274. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  275. data/lib/pubid/iso/components/code.rb +7 -19
  276. data/lib/pubid/iso/components/publisher.rb +10 -8
  277. data/lib/pubid/iso/components.rb +2 -4
  278. data/lib/pubid/iso/identifier.rb +233 -6
  279. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  280. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  281. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  282. data/lib/pubid/iso/identifiers/data.rb +0 -1
  283. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  284. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  285. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  286. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  287. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  288. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  289. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  290. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  291. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  292. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  293. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  294. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  295. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  296. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  297. data/lib/pubid/iso/identifiers.rb +0 -1
  298. data/lib/pubid/iso/normalizer.rb +89 -0
  299. data/lib/pubid/iso/parser.rb +26 -6
  300. data/lib/pubid/iso/single_identifier.rb +6 -3
  301. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  302. data/lib/pubid/iso/urn_generator.rb +74 -176
  303. data/lib/pubid/iso/urn_parser.rb +28 -9
  304. data/lib/pubid/iso.rb +173 -2
  305. data/lib/pubid/itu/builder.rb +0 -12
  306. data/lib/pubid/itu/components/code.rb +8 -0
  307. data/lib/pubid/itu/components.rb +11 -0
  308. data/lib/pubid/itu/identifier.rb +6 -39
  309. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  310. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  311. data/lib/pubid/itu/identifiers/base.rb +0 -6
  312. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  313. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  314. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  315. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  316. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  317. data/lib/pubid/itu/urn_parser.rb +23 -0
  318. data/lib/pubid/itu.rb +42 -1
  319. data/lib/pubid/jcgm/builder.rb +16 -8
  320. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  321. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  322. data/lib/pubid/jcgm/renderer.rb +68 -0
  323. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  324. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  325. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  326. data/lib/pubid/jcgm.rb +43 -2
  327. data/lib/pubid/jis/builder.rb +44 -52
  328. data/lib/pubid/jis/identifier.rb +132 -3
  329. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  330. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  331. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  332. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  333. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  334. data/lib/pubid/jis/identifiers.rb +1 -1
  335. data/lib/pubid/jis/parser.rb +31 -5
  336. data/lib/pubid/jis/renderer.rb +69 -0
  337. data/lib/pubid/jis/single_identifier.rb +6 -12
  338. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  339. data/lib/pubid/jis/urn_parser.rb +23 -0
  340. data/lib/pubid/jis.rb +42 -2
  341. data/lib/pubid/nist/builder.rb +122 -1761
  342. data/lib/pubid/nist/caster.rb +1272 -0
  343. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  344. data/lib/pubid/nist/components/code.rb +9 -20
  345. data/lib/pubid/nist/components/edition.rb +16 -0
  346. data/lib/pubid/nist/components/supplement.rb +88 -21
  347. data/lib/pubid/nist/components.rb +0 -1
  348. data/lib/pubid/nist/identifier.rb +25 -0
  349. data/lib/pubid/nist/identifiers/base.rb +206 -64
  350. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  351. data/lib/pubid/nist/identifiers/circular_supplement.rb +3 -2
  352. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  353. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  354. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  355. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -11
  356. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  357. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +17 -16
  358. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  359. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  360. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  361. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  362. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  363. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  364. data/lib/pubid/nist/identifiers/report.rb +4 -3
  365. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  366. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  367. data/lib/pubid/nist/identifiers.rb +1 -0
  368. data/lib/pubid/nist/parser.rb +67 -424
  369. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  370. data/lib/pubid/nist/preprocessor.rb +416 -0
  371. data/lib/pubid/nist/renderer.rb +43 -0
  372. data/lib/pubid/nist/router.rb +148 -0
  373. data/lib/pubid/nist/series/base.rb +58 -0
  374. data/lib/pubid/nist/series/crpl.rb +13 -0
  375. data/lib/pubid/nist/series/fips.rb +14 -0
  376. data/lib/pubid/nist/series/ir.rb +60 -0
  377. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  378. data/lib/pubid/nist/series/mono.rb +19 -0
  379. data/lib/pubid/nist/series/ncstar.rb +20 -0
  380. data/lib/pubid/nist/series.rb +49 -0
  381. data/lib/pubid/nist/supplement_identifier.rb +11 -25
  382. data/lib/pubid/nist/urn_generator.rb +14 -8
  383. data/lib/pubid/nist/urn_parser.rb +67 -0
  384. data/lib/pubid/nist.rb +83 -4
  385. data/lib/pubid/oiml/components/code.rb +10 -0
  386. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  387. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  388. data/lib/pubid/oiml/renderer.rb +161 -0
  389. data/lib/pubid/oiml/single_identifier.rb +6 -45
  390. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  391. data/lib/pubid/oiml/urn_generator.rb +0 -8
  392. data/lib/pubid/oiml/urn_parser.rb +22 -0
  393. data/lib/pubid/oiml.rb +42 -1
  394. data/lib/pubid/plateau/identifier.rb +23 -0
  395. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  396. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  397. data/lib/pubid/plateau/renderer.rb +51 -0
  398. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  399. data/lib/pubid/plateau/urn_parser.rb +43 -0
  400. data/lib/pubid/plateau.rb +44 -1
  401. data/lib/pubid/renderers/base.rb +34 -0
  402. data/lib/pubid/renderers/directives_renderer.rb +27 -14
  403. data/lib/pubid/renderers/guide_renderer.rb +7 -1
  404. data/lib/pubid/renderers/human_readable.rb +31 -8
  405. data/lib/pubid/renderers/iwa_renderer.rb +5 -1
  406. data/lib/pubid/renderers/supplement_renderer.rb +4 -1
  407. data/lib/pubid/rendering/context.rb +33 -21
  408. data/lib/pubid/rendering.rb +0 -3
  409. data/lib/pubid/sae/components/date.rb +8 -0
  410. data/lib/pubid/sae/components/type.rb +5 -1
  411. data/lib/pubid/sae/identifiers/base.rb +2 -16
  412. data/lib/pubid/sae/renderer.rb +36 -0
  413. data/lib/pubid/sae/urn_generator.rb +2 -10
  414. data/lib/pubid/sae/urn_parser.rb +36 -0
  415. data/lib/pubid/sae.rb +42 -1
  416. data/lib/pubid/urn_generator/base.rb +12 -12
  417. data/lib/pubid/urn_parser/base.rb +81 -0
  418. data/lib/pubid/urn_parser/errors.rb +9 -0
  419. data/lib/pubid/urn_parser.rb +14 -0
  420. data/lib/pubid/version.rb +1 -1
  421. data/lib/pubid.rb +29 -7
  422. data/lib/tasks/website-data.json +1940 -1882
  423. metadata +77 -43
  424. data/lib/pubid/amca/scheme.rb +0 -16
  425. data/lib/pubid/ansi/scheme.rb +0 -15
  426. data/lib/pubid/api/scheme.rb +0 -66
  427. data/lib/pubid/ashrae/scheme.rb +0 -53
  428. data/lib/pubid/asme/scheme.rb +0 -37
  429. data/lib/pubid/astm/scheme.rb +0 -55
  430. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  431. data/lib/pubid/bsi/scheme.rb +0 -243
  432. data/lib/pubid/ccsds/scheme.rb +0 -57
  433. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  434. data/lib/pubid/cie/scheme.rb +0 -64
  435. data/lib/pubid/csa/scheme.rb +0 -44
  436. data/lib/pubid/etsi/scheme.rb +0 -42
  437. data/lib/pubid/export/data_class_exporter.rb +0 -59
  438. data/lib/pubid/export/ieee_exporter.rb +0 -78
  439. data/lib/pubid/export/itu_exporter.rb +0 -66
  440. data/lib/pubid/export/nist_exporter.rb +0 -64
  441. data/lib/pubid/export/registry_exporter.rb +0 -90
  442. data/lib/pubid/export/scheme_exporter.rb +0 -70
  443. data/lib/pubid/identifier_registry.rb +0 -198
  444. data/lib/pubid/idf/scheme.rb +0 -61
  445. data/lib/pubid/iec/scheme.rb +0 -71
  446. data/lib/pubid/ieee/scheme.rb +0 -90
  447. data/lib/pubid/iho/scheme.rb +0 -29
  448. data/lib/pubid/iso/identifiers/base.rb +0 -115
  449. data/lib/pubid/iso/scheme.rb +0 -187
  450. data/lib/pubid/itu/scheme.rb +0 -174
  451. data/lib/pubid/jcgm/scheme.rb +0 -60
  452. data/lib/pubid/jis/components/code.rb +0 -59
  453. data/lib/pubid/jis/identifiers/base.rb +0 -72
  454. data/lib/pubid/jis/scheme.rb +0 -49
  455. data/lib/pubid/nist/components/publisher.rb +0 -24
  456. data/lib/pubid/nist/scheme.rb +0 -199
  457. data/lib/pubid/oiml/scheme.rb +0 -46
  458. data/lib/pubid/plateau/scheme.rb +0 -45
  459. data/lib/pubid/rendering/base.rb +0 -73
  460. data/lib/pubid/rendering/common.rb +0 -211
  461. data/lib/pubid/rendering/format.rb +0 -25
  462. data/lib/pubid/sae/scheme.rb +0 -47
  463. data/lib/pubid/scheme.rb +0 -207
data/lib/pubid/iso.rb CHANGED
@@ -11,9 +11,9 @@ module Pubid
11
11
  autoload :FormatResolver, "#{__dir__}/iso/format_resolver"
12
12
  autoload :Identifier, "#{__dir__}/iso/identifier"
13
13
  autoload :Identifiers, "#{__dir__}/iso/identifiers"
14
+ autoload :Normalizer, "#{__dir__}/iso/normalizer"
14
15
  autoload :Parser, "#{__dir__}/iso/parser"
15
16
  autoload :RenderingStyle, "#{__dir__}/iso/rendering_style"
16
- autoload :Scheme, "#{__dir__}/iso/scheme"
17
17
  autoload :SingleIdentifier, "#{__dir__}/iso/single_identifier"
18
18
  autoload :SupplementIdentifier, "#{__dir__}/iso/supplement_identifier"
19
19
  autoload :UrnGenerator, "#{__dir__}/iso/urn_generator"
@@ -33,10 +33,78 @@ module Pubid
33
33
  when :mr_string
34
34
  Pubid::Parsers::MrString.parse(identifier)
35
35
  else
36
- Scheme.parse(identifier)
36
+ Normalizer.apply(identifier)
37
37
  end
38
38
  end
39
39
 
40
+ # Build an ISO identifier from attributes.
41
+ #
42
+ # This is the public seam: callers in other flavors should never reach
43
+ # into `Pubid::Iso::Identifiers::*` or `Pubid::Iso::Components::*`
44
+ # directly — go through this method so the internal class registry can
45
+ # change without breaking callers.
46
+ #
47
+ # Accepts either raw values (Strings/Integers) or pre-built components.
48
+ # Raw values are wrapped in the appropriate ISO component internally.
49
+ #
50
+ # @param type [Symbol] the type key (e.g. :is, :tr, :ts, :guide)
51
+ # @param publisher [String, Pubid::Iso::Components::Publisher] primary publisher
52
+ # @param copublishers [Array<String>, Array<Pubid::Components::Publisher>]
53
+ # @param number [String, Integer, Pubid::Iso::Components::Code]
54
+ # @param year [String, Integer, Pubid::Components::Date, nil]
55
+ # @param attrs [Hash] additional identifier attributes
56
+ # @return [Pubid::Iso::Identifier]
57
+ def self.build(type:, publisher: nil, copublishers: nil, number: nil,
58
+ year: nil, **attrs)
59
+ klass = locate_type(type) || raise(ArgumentError, "unknown ISO type: #{type.inspect}")
60
+
61
+ copub_list = Array(copublishers)
62
+ attrs[:publisher] = build_publisher(publisher, copub_list) if publisher || copub_list.any?
63
+ attrs[:copublishers] = build_copublishers(copub_list) if copub_list.any?
64
+ attrs[:number] = build_code(number) if number
65
+ attrs[:date] = build_date(year) if year
66
+
67
+ klass.new(attrs)
68
+ end
69
+
70
+ # @!visibility private
71
+ def self.build_publisher(value, copublishers = [])
72
+ return value if value.is_a?(Components::Publisher) && copublishers.empty?
73
+
74
+ copub_strings = copublishers.map { |cp| cp.is_a?(Components::Publisher) ? cp.publisher : cp.to_s }
75
+ Components::Publisher.new(
76
+ publisher: value.is_a?(Components::Publisher) ? value.publisher : value.to_s,
77
+ copublisher: copub_strings,
78
+ )
79
+ end
80
+ private_class_method :build_publisher
81
+
82
+ # @!visibility private
83
+ def self.build_copublishers(list)
84
+ Array(list).map do |cp|
85
+ next cp if cp.is_a?(Components::Publisher)
86
+
87
+ Components::Publisher.new(publisher: cp.to_s)
88
+ end
89
+ end
90
+ private_class_method :build_copublishers
91
+
92
+ # @!visibility private
93
+ def self.build_code(value)
94
+ return value if value.is_a?(Components::Code)
95
+
96
+ Components::Code.new(value: value.to_s)
97
+ end
98
+ private_class_method :build_code
99
+
100
+ # @!visibility private
101
+ def self.build_date(value)
102
+ return value if value.is_a?(::Pubid::Components::Date)
103
+
104
+ ::Pubid::Components::Date.new(year: value.to_s)
105
+ end
106
+ private_class_method :build_date
107
+
40
108
  # Parse an ISO URN string
41
109
  # @param urn [String] the URN string to parse
42
110
  # @return [Identifier] the parsed identifier
@@ -44,6 +112,109 @@ module Pubid
44
112
  def self.parse_urn(urn)
45
113
  UrnParser.parse(urn)
46
114
  end
115
+
116
+ # Build an ISO identifier from a Parslet parse-tree hash (used by other
117
+ # flavors when parsing joint identifiers, e.g. IEC's `IEC … | ISO …` form).
118
+ #
119
+ # This is the public seam: callers should never reach into
120
+ # `Pubid::Iso::Builder` directly.
121
+ #
122
+ # @param hash [Hash] parse tree for an ISO identifier
123
+ # @return [Pubid::Iso::Identifier]
124
+ def self.build_from_parse(hash)
125
+ builder.build(hash)
126
+ end
127
+
128
+ # Return the named Parslet rule atom from the ISO parser, for embedding in
129
+ # another flavor's grammar (e.g. IEC joint identifiers).
130
+ #
131
+ # This is the public seam: callers should never instantiate
132
+ # `Pubid::Iso::Parser` directly.
133
+ #
134
+ # @param rule_name [Symbol] the parser rule to expose
135
+ # @return [Parslet::Atoms::Base]
136
+ def self.joint_grammar_atom(rule_name)
137
+ parser.public_send(rule_name)
138
+ end
139
+
140
+ # Auto-discover all identifier types from the Identifiers namespace
141
+ # @return [Array<Class>] identifier classes that define a self.type Hash
142
+ def self.identifier_types
143
+ @identifier_types ||= Identifiers.constants
144
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
145
+ .select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
146
+ .select { |c| c.type.is_a?(Hash) }
147
+ end
148
+
149
+ # Build typed stage index from identifier types
150
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
151
+ def self.all_typed_stages
152
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
153
+ if klass.const_defined?(:TYPED_STAGES)
154
+ klass.const_get(:TYPED_STAGES)
155
+ else
156
+ []
157
+ end
158
+ end
159
+ end
160
+
161
+ # Memoized builder instance used by Normalizer / URN parser
162
+ # @return [Pubid::Iso::Builder]
163
+ def self.builder
164
+ @builder ||= Builder.new
165
+ end
166
+
167
+ # Memoized parser instance used by Normalizer
168
+ # @return [Pubid::Iso::Parser]
169
+ def self.parser
170
+ @parser ||= Parser.new
171
+ end
172
+
173
+ # Lookup: type code -> identifier class
174
+ # @param code [String, Symbol] the type key to find
175
+ # @return [Class, nil] the matching identifier class
176
+ def self.locate_type(code)
177
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
178
+ end
179
+
180
+ # Lookup: abbreviation -> typed stage
181
+ # @param abbr [String, Symbol] the abbreviation to find
182
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
183
+ def self.locate_stage(abbr)
184
+ abbr_str = abbr.to_s.upcase
185
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
186
+ end
187
+
188
+ # Lookup: stage code -> typed stage
189
+ # @param stage_code [String, Symbol]
190
+ # @return [Pubid::Components::TypedStage, nil]
191
+ def self.locate_stage_by_stage_code(stage_code)
192
+ stage_code_sym = stage_code.to_sym
193
+ all_typed_stages.find { |s| s.stage_code.to_sym == stage_code_sym }
194
+ end
195
+
196
+ # Lookup: per-typed-stage code -> typed stage
197
+ # @param code [String, Symbol]
198
+ # @return [Pubid::Components::TypedStage, nil]
199
+ def self.locate_stage_by_code(code)
200
+ code_sym = code.to_sym
201
+ all_typed_stages.find { |s| s.code&.to_sym == code_sym }
202
+ end
203
+
204
+ # Lookup: harmonized stage code -> typed stage
205
+ # @param harmonized_code [String]
206
+ # @return [Pubid::Components::TypedStage, nil]
207
+ def self.locate_stage_by_harmonized_code(harmonized_code)
208
+ harmonized_str = harmonized_code.to_s
209
+ all_typed_stages.find { |s| s.harmonized_stages&.include?(harmonized_str) }
210
+ end
211
+
212
+ # Default typed stage used when no type_with_stage is present
213
+ # (e.g., the bare International Standard published stage)
214
+ # @return [Pubid::Components::TypedStage]
215
+ def self.default_typed_stage
216
+ locate_stage("") || all_typed_stages.first
217
+ end
47
218
  end
48
219
  end
49
220
 
@@ -1,17 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../components/date"
4
- require_relative "components/sector"
5
- require_relative "components/series"
6
- require_relative "components/code"
7
- require_relative "identifiers/recommendation"
8
- require_relative "identifiers/combined_identifier"
9
- require_relative "identifiers/supplement"
10
- require_relative "identifiers/amendment"
11
- require_relative "identifiers/corrigendum"
12
- require_relative "identifiers/special_publication"
13
- require_relative "identifiers/annex"
14
-
15
3
  module Pubid
16
4
  module Itu
17
5
  class Builder
@@ -8,6 +8,10 @@ module Pubid
8
8
  # ITU Code component
9
9
  # Format: NUMBER[.SUBSERIES][-PART]
10
10
  # Examples: 1234, 1234.5, 1234-1, 1234.5-2
11
+ #
12
+ # Stays independent of Pubid::Components::Code because ITU uses
13
+ # +subseries+ (dot-separated, flavor-specific) and +parts+
14
+ # (dash-separated).
11
15
  class Code < Lutaml::Model::Serializable
12
16
  attribute :number, :string
13
17
  attribute :subseries, :string
@@ -26,6 +30,10 @@ module Pubid
26
30
  result
27
31
  end
28
32
 
33
+ def render(context: nil)
34
+ to_s
35
+ end
36
+
29
37
  def ==(other)
30
38
  return false unless other.is_a?(Code)
31
39
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Itu
5
+ module Components
6
+ autoload :Sector, "#{__dir__}/components/sector"
7
+ autoload :Series, "#{__dir__}/components/series"
8
+ autoload :Code, "#{__dir__}/components/code"
9
+ end
10
+ end
11
+ end
@@ -1,14 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "parser"
4
- require_relative "builder"
5
- require_relative "identifiers"
6
- require_relative "components/sector"
7
- require_relative "components/series"
8
- require_relative "components/code"
9
-
10
3
  module Pubid
11
4
  module Itu
5
+ # NOTE: intentionally does NOT `extend Pubid::IdentifierFacade`. ITU's
6
+ # `to_hash` currently raises (publisher stored as a String, not a Publisher
7
+ # component), so enabling the facade's identity check would route ITU ids
8
+ # through a consumer's `to_hash` (e.g. relaton-index#save) and crash.
9
+ # Re-enable once ITU serialization round-trips cleanly. See
10
+ # identifier_facade.rb.
12
11
  module Identifier
13
12
  def self.parse(identifier)
14
13
  parsed = Parser.parse(identifier)
@@ -16,38 +15,6 @@ module Pubid
16
15
  rescue Parslet::ParseFailed => e
17
16
  raise "Failed to parse ITU identifier '#{identifier}': #{e.message}"
18
17
  end
19
-
20
- # Factory mirroring v1's Pubid::Itu::Identifier.create API. The v1 form
21
- # accepts a `type:` discriminator plus attribute kwargs; this v2
22
- # implementation supports the subset needed by metanorma-itu PR #497:
23
- # * type: :annex — builds Identifiers::Annex
24
- # * series: "OB" (with no type:) — builds Identifiers::SpecialPublication
25
- def self.create(type: nil, **kwargs)
26
- case type
27
- when :annex
28
- Identifiers::Annex.new(**kwargs)
29
- when nil
30
- if kwargs[:series].to_s == "OB"
31
- create_special_publication(**kwargs)
32
- else
33
- raise ArgumentError,
34
- "Identifier.create without :type requires series: 'OB'"
35
- end
36
- else
37
- raise ArgumentError,
38
- "Unsupported type for Identifier.create: #{type.inspect}"
39
- end
40
- end
41
-
42
- def self.create_special_publication(number:, series: "OB", date: nil,
43
- language: nil)
44
- Identifiers::SpecialPublication.new(
45
- series: Components::Series.new(series: series.to_s),
46
- code: Components::Code.new(number: number.to_s),
47
- date: date,
48
- language: language&.to_s,
49
- )
50
- end
51
18
  end
52
19
  end
53
20
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "supplement"
4
-
5
3
  module Pubid
6
4
  module Itu
7
5
  module Identifiers
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module Pubid
6
4
  module Itu
7
5
  module Identifiers
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../../components/date"
4
- require_relative "../components/sector"
5
- require_relative "../components/series"
6
- require_relative "../components/code"
7
- require_relative "../i18n"
8
-
9
3
  module Pubid
10
4
  module Itu
11
5
  module Identifiers
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module Pubid
6
4
  module Itu
7
5
  module Identifiers
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "supplement"
4
-
5
3
  module Pubid
6
4
  module Itu
7
5
  module Identifiers
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module Pubid
6
4
  module Itu
7
5
  module Identifiers
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module Pubid
6
4
  module Itu
7
5
  module Identifiers
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "base"
4
-
5
3
  module Pubid
6
4
  module Itu
7
5
  module Identifiers
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Itu
5
+ # Parses ITU URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits: `urn:itu:{sector}:{code}` where sector is the
8
+ # lowercase ITU sector letter (t for ITU-T, r for ITU-R, d for ITU-D)
9
+ # and code is the document code (e.g., "BO.1073-1").
10
+ #
11
+ # Examples:
12
+ # - urn:itu:t:BO.1073-1 → ITU-T BO.1073-1
13
+ # - urn:itu:r:BO.500 → ITU-R BO.500
14
+ class UrnParser < Pubid::UrnParser::Base
15
+ def parse_urn(urn)
16
+ body = strip_namespace(urn)
17
+ parts = split_parts(body)
18
+ sector, code = parts
19
+ flavor_parse("ITU-#{sector.upcase} #{code}")
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/pubid/itu.rb CHANGED
@@ -5,16 +5,57 @@ require "lutaml/model"
5
5
  module Pubid
6
6
  module Itu
7
7
  autoload :Builder, "#{__dir__}/itu/builder"
8
+ autoload :Components, "#{__dir__}/itu/components"
8
9
  autoload :Identifier, "#{__dir__}/itu/identifier"
9
10
  autoload :Identifiers, "#{__dir__}/itu/identifiers"
10
11
  autoload :Parser, "#{__dir__}/itu/parser"
11
- autoload :Scheme, "#{__dir__}/itu/scheme"
12
12
  autoload :UrnGenerator, "#{__dir__}/itu/urn_generator"
13
+ autoload :UrnParser, "#{__dir__}/itu/urn_parser"
13
14
  autoload :Model, "#{__dir__}/itu/model"
14
15
 
16
+ # I18N is a YAML-loaded constant (not a class), so autoload cannot be used.
17
+ # It is loaded eagerly when the ITU module is first referenced.
18
+ require "#{__dir__}/itu/i18n"
19
+
15
20
  def self.parse(identifier)
16
21
  Identifier.parse(identifier)
17
22
  end
23
+
24
+ # Auto-discover all identifier types from the Identifiers namespace
25
+ # @return [Array<Class>] identifier classes (Pubid::Identifier subclasses)
26
+ def self.identifier_types
27
+ @identifier_types ||= Identifiers.constants
28
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
29
+ .select { |c| c.is_a?(Class) && c < Pubid::Identifier }
30
+ .reject { |c| c.name&.split("::")&.last == "Base" }
31
+ end
32
+
33
+ # Build typed stage index from identifier types
34
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
35
+ def self.all_typed_stages
36
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
37
+ if klass.const_defined?(:TYPED_STAGES)
38
+ klass.const_get(:TYPED_STAGES)
39
+ else
40
+ []
41
+ end
42
+ end
43
+ end
44
+
45
+ # Lookup: type code -> identifier class
46
+ # @param code [String, Symbol] the type key to find
47
+ # @return [Class, nil] the matching identifier class
48
+ def self.locate_type(code)
49
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
50
+ end
51
+
52
+ # Lookup: abbreviation -> typed stage
53
+ # @param abbr [String, Symbol] the abbreviation to find
54
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
55
+ def self.locate_stage(abbr)
56
+ abbr_str = abbr.to_s.upcase
57
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
58
+ end
18
59
  end
19
60
  end
20
61
 
@@ -3,21 +3,22 @@
3
3
  module Pubid
4
4
  module Jcgm
5
5
  class Builder < Pubid::Builder::Base
6
- def initialize(scheme)
7
- @scheme = scheme
8
- end
9
-
10
6
  def locate_identifier_klass(parsed_hash)
11
7
  if parsed_hash[:base_identifier]
12
- return @scheme.locate_identifier_klass_by_type_code(:amendment)
8
+ return Jcgm.locate_type(:amendment)
13
9
  end
14
10
 
15
11
  if parsed_hash[:gum_number]
16
- return @scheme.locate_identifier_klass_by_type_code(:gum_guide)
12
+ return Jcgm.locate_type(:gum_guide)
17
13
  end
18
14
 
15
+ # Standard guide (no type_with_stage, no gum_number).
16
+ # Don't use locate_stage("") — Guide and GumGuide both have
17
+ # abbr: [""], so the result depends on constant iteration order.
18
+ return Jcgm.locate_type(:guide) unless parsed_hash[:type_with_stage]
19
+
19
20
  typed_stage = locate_typed_stage(parsed_hash[:type_with_stage])
20
- @scheme.locate_identifier_klass_by_type_code(typed_stage.type_code)
21
+ Jcgm.locate_type(typed_stage.type_code)
21
22
  end
22
23
 
23
24
  def build(parsed_hash)
@@ -25,7 +26,8 @@ module Pubid
25
26
  assign_attributes(identifier, parsed_hash)
26
27
 
27
28
  if identifier.class.attributes.key?(:typed_stage) && identifier.typed_stage.nil?
28
- default_typed_stage = @scheme.locate_typed_stage_by_abbr("")
29
+ default_typed_stage = Jcgm.locate_stage("") ||
30
+ raise(ArgumentError, "Unknown type abbreviation: ''")
29
31
  identifier.typed_stage = default_typed_stage
30
32
  identifier.stage = default_typed_stage.to_stage if identifier.class.attributes.key?(:stage)
31
33
  identifier.type = default_typed_stage.to_type if identifier.class.attributes.key?(:type)
@@ -40,6 +42,12 @@ module Pubid
40
42
  Identifiers::Guide
41
43
  end
42
44
 
45
+ def locate_typed_stage(typed_stage_string)
46
+ typed_stage_string = "" if typed_stage_string.nil?
47
+ Jcgm.locate_stage(typed_stage_string) ||
48
+ raise(ArgumentError, "Unknown type abbreviation: '#{typed_stage_string}'")
49
+ end
50
+
43
51
  def cast(type, value)
44
52
  case type
45
53
  when :base_identifier
@@ -21,13 +21,8 @@ module Pubid
21
21
  { key: :amendment, title: "Amendment", short: "Amd" }
22
22
  end
23
23
 
24
- def to_s(lang: :en, lang_single: false, with_edition: false,
25
- format: nil, stage_format_long: nil, with_date: nil)
26
- result = base_identifier.to_s if base_identifier
27
- result += "/Amd"
28
- result += " #{iteration.value}" if iteration
29
- result += ":#{date}" if date
30
- result
24
+ def to_s(**opts)
25
+ render(format: :human, **opts)
31
26
  end
32
27
  end
33
28
  end
@@ -22,16 +22,8 @@ module Pubid
22
22
  { key: :gum_guide, title: "GUM Guide", short: "GUM" }
23
23
  end
24
24
 
25
- def to_s(lang: :en, lang_single: false, with_edition: false,
26
- format: nil, stage_format_long: nil, with_date: nil)
27
- parts = []
28
- parts << publisher.publisher if publisher
29
- parts << "GUM-#{gum_number.value}" if gum_number
30
-
31
- result = parts.join(" ")
32
- result += ":#{date}" if date
33
- result += language_portion if languages&.any?
34
- result
25
+ def to_s(**opts)
26
+ render(format: :human, **opts)
35
27
  end
36
28
 
37
29
  private
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Jcgm
5
+ # Human-readable renderer for JCGM identifiers.
6
+ #
7
+ # Produces strings like:
8
+ # "JCGM 100:2008"
9
+ # "JCGM 100:2008/Amd 1:2023"
10
+ # "JCGM GUM-6:2020"
11
+ #
12
+ # The renderer is registered as the `:human` format in the JCGM format
13
+ # registry and invoked via `render(format: :human)`.
14
+ class Renderer < ::Pubid::Renderers::Base
15
+ def render(context: nil, **opts)
16
+ id = @id
17
+
18
+ case id
19
+ when Identifiers::Amendment
20
+ render_amendment(id, context)
21
+ when Identifiers::GumGuide
22
+ render_gum_guide(id, context)
23
+ else
24
+ render_single(id)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def render_single(id)
31
+ parts = [id.publisher_portion]
32
+ parts << id.number_portion unless id.number_portion.empty?
33
+ result = parts.join(" ")
34
+ result += id.language_portion if id.languages&.any?
35
+ result
36
+ end
37
+
38
+ def render_amendment(id, context)
39
+ result = id.base_identifier.to_s if id.base_identifier
40
+ result += "/Amd"
41
+ result += " #{id.iteration.render(context:)}" if id.iteration
42
+ result += ":#{id.date}" if id.date
43
+ result
44
+ end
45
+
46
+ def render_gum_guide(id, context)
47
+ parts = []
48
+ parts << id.publisher.publisher if id.publisher
49
+ parts << "GUM-#{id.gum_number.render(context:)}" if id.gum_number
50
+
51
+ result = parts.join(" ")
52
+ result += ":#{id.date}" if id.date
53
+ result += gum_language_portion(id) if id.languages&.any?
54
+ result
55
+ end
56
+
57
+ def gum_language_portion(id)
58
+ return "" unless id.languages&.any?
59
+
60
+ codes = id.languages.map do |lang|
61
+ lang.original_code || lang.code
62
+ end
63
+
64
+ "(#{codes.join('/')})"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -37,11 +37,7 @@ module Pubid
37
37
  end
38
38
 
39
39
  def to_s
40
- parts = [publisher_portion]
41
- parts << number_portion unless number_portion.empty?
42
- result = parts.join(" ")
43
- result += language_portion
44
- result
40
+ render(format: :human)
45
41
  end
46
42
  end
47
43
  end
@@ -37,9 +37,8 @@ module Pubid
37
37
  parts << "-#{sp}"
38
38
  end
39
39
 
40
- if identifier.date
41
- year = identifier.date.year
42
- parts << year.to_s
40
+ if identifier.date&.is_a?(::Pubid::Components::Date) && identifier.date.present?
41
+ parts << identifier.date.render(context: URN_CONTEXT)
43
42
  elsif maybe(:year)
44
43
  parts << maybe(:year).to_s
45
44
  end
@@ -95,9 +94,8 @@ module Pubid
95
94
  parts << iter
96
95
  end
97
96
 
98
- if identifier.date
99
- year = identifier.date.year
100
- parts << year.to_s
97
+ if identifier.date&.is_a?(::Pubid::Components::Date) && identifier.date.present?
98
+ parts << identifier.date.render(context: URN_CONTEXT)
101
99
  end
102
100
  else
103
101
  parts << "unknown"