pubid 2.0.0.pre.alpha.2 → 2.0.0.pre.alpha.4

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 (473) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +25 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +4 -55
  6. data/lib/pubid/amca/identifiers/base.rb +58 -47
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -21
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -17
  9. data/lib/pubid/amca/identifiers/standard.rb +0 -4
  10. data/lib/pubid/amca/renderer.rb +82 -0
  11. data/lib/pubid/amca/single_identifier.rb +0 -23
  12. data/lib/pubid/amca/urn_generator.rb +2 -1
  13. data/lib/pubid/amca/urn_parser.rb +28 -0
  14. data/lib/pubid/amca.rb +42 -1
  15. data/lib/pubid/ansi/builder.rb +5 -3
  16. data/lib/pubid/ansi/identifier.rb +1 -43
  17. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  18. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  19. data/lib/pubid/ansi/renderer.rb +53 -0
  20. data/lib/pubid/ansi/single_identifier.rb +2 -31
  21. data/lib/pubid/ansi/urn_generator.rb +3 -38
  22. data/lib/pubid/ansi/urn_parser.rb +23 -0
  23. data/lib/pubid/ansi.rb +38 -3
  24. data/lib/pubid/api/builder.rb +33 -74
  25. data/lib/pubid/api/identifier.rb +5 -52
  26. data/lib/pubid/api/identifiers/base.rb +2 -14
  27. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  28. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  29. data/lib/pubid/api/identifiers/mpms.rb +0 -20
  30. data/lib/pubid/api/identifiers/publication.rb +0 -2
  31. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  32. data/lib/pubid/api/identifiers/specification.rb +0 -2
  33. data/lib/pubid/api/identifiers/standard.rb +0 -2
  34. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  35. data/lib/pubid/api/identifiers/typeless_standard.rb +0 -16
  36. data/lib/pubid/api/identifiers.rb +18 -0
  37. data/lib/pubid/api/renderer.rb +89 -0
  38. data/lib/pubid/api/single_identifier.rb +5 -20
  39. data/lib/pubid/api/urn_generator.rb +0 -18
  40. data/lib/pubid/api/urn_parser.rb +35 -0
  41. data/lib/pubid/api.rb +51 -5
  42. data/lib/pubid/ashrae/builder.rb +3 -3
  43. data/lib/pubid/ashrae/identifier.rb +7 -55
  44. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  45. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  46. data/lib/pubid/ashrae/identifiers/base.rb +29 -15
  47. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  48. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  49. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  50. data/lib/pubid/ashrae/parser.rb +4 -0
  51. data/lib/pubid/ashrae/renderer.rb +117 -0
  52. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  53. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  54. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  55. data/lib/pubid/ashrae.rb +46 -1
  56. data/lib/pubid/asme/components/code.rb +10 -2
  57. data/lib/pubid/asme/identifier.rb +0 -46
  58. data/lib/pubid/asme/identifiers/base.rb +0 -60
  59. data/lib/pubid/asme/renderer.rb +66 -0
  60. data/lib/pubid/asme/single_identifier.rb +3 -1
  61. data/lib/pubid/asme/urn_parser.rb +31 -0
  62. data/lib/pubid/asme.rb +42 -1
  63. data/lib/pubid/astm/components/code.rb +9 -0
  64. data/lib/pubid/{jis → astm}/components.rb +1 -1
  65. data/lib/pubid/astm/identifier.rb +0 -77
  66. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  67. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  68. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  69. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  70. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  71. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  72. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  73. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  74. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  75. data/lib/pubid/astm/identifiers.rb +18 -0
  76. data/lib/pubid/astm/renderer.rb +172 -0
  77. data/lib/pubid/astm/single_identifier.rb +3 -11
  78. data/lib/pubid/astm/urn_parser.rb +30 -0
  79. data/lib/pubid/astm.rb +39 -27
  80. data/lib/pubid/bsi/builder.rb +21 -12
  81. data/lib/pubid/bsi/identifier.rb +5 -85
  82. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -36
  83. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +8 -48
  84. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +8 -39
  85. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +2 -55
  86. data/lib/pubid/bsi/identifiers/amendment.rb +2 -22
  87. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -6
  88. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  89. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -87
  90. data/lib/pubid/bsi/identifiers/committee_document.rb +0 -16
  91. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -87
  92. data/lib/pubid/bsi/identifiers/corrigendum.rb +2 -10
  93. data/lib/pubid/bsi/identifiers/detailed_specification.rb +0 -36
  94. data/lib/pubid/bsi/identifiers/disc.rb +0 -29
  95. data/lib/pubid/bsi/identifiers/draft_document.rb +2 -46
  96. data/lib/pubid/bsi/identifiers/electronic_book.rb +2 -38
  97. data/lib/pubid/bsi/identifiers/expert_commentary.rb +2 -18
  98. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +0 -47
  99. data/lib/pubid/bsi/identifiers/flex.rb +0 -35
  100. data/lib/pubid/bsi/identifiers/handbook.rb +1 -15
  101. data/lib/pubid/bsi/identifiers/index.rb +0 -32
  102. data/lib/pubid/bsi/identifiers/method.rb +0 -41
  103. data/lib/pubid/bsi/identifiers/national_annex.rb +4 -29
  104. data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -6
  105. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +2 -54
  106. data/lib/pubid/bsi/identifiers/published_document.rb +2 -54
  107. data/lib/pubid/bsi/identifiers/section.rb +0 -30
  108. data/lib/pubid/bsi/identifiers/set.rb +3 -20
  109. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +0 -9
  110. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -24
  111. data/lib/pubid/bsi/identifiers/supplementary_index.rb +0 -46
  112. data/lib/pubid/bsi/identifiers/technical_specification.rb +2 -47
  113. data/lib/pubid/bsi/identifiers/test_method.rb +0 -32
  114. data/lib/pubid/bsi/identifiers/value_added_publication.rb +2 -17
  115. data/lib/pubid/bsi/identifiers.rb +0 -1
  116. data/lib/pubid/bsi/renderer.rb +1050 -0
  117. data/lib/pubid/bsi/single_identifier.rb +33 -78
  118. data/lib/pubid/bsi/urn_generator.rb +2 -3
  119. data/lib/pubid/bsi/urn_parser.rb +52 -0
  120. data/lib/pubid/bsi.rb +232 -2
  121. data/lib/pubid/builder/base.rb +57 -10
  122. data/lib/pubid/bundled_identifier.rb +0 -1
  123. data/lib/pubid/ccsds/builder.rb +4 -3
  124. data/lib/pubid/ccsds/identifier.rb +53 -68
  125. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  126. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  127. data/lib/pubid/ccsds/parser.rb +4 -2
  128. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  129. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  130. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  131. data/lib/pubid/ccsds.rb +39 -1
  132. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  133. data/lib/pubid/cen_cenelec/identifier.rb +11 -40
  134. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +9 -4
  135. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +0 -10
  136. data/lib/pubid/cen_cenelec/identifiers/base.rb +2 -45
  137. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +0 -27
  140. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +0 -15
  141. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +2 -8
  143. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +0 -4
  145. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  146. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  147. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  148. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  149. data/lib/pubid/cen_cenelec/single_identifier.rb +9 -90
  150. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  151. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  152. data/lib/pubid/cen_cenelec.rb +172 -1
  153. data/lib/pubid/cie/components/code.rb +8 -0
  154. data/lib/pubid/cie/identifier.rb +10 -57
  155. data/lib/pubid/cie/single_identifier.rb +4 -4
  156. data/lib/pubid/cie/urn_parser.rb +28 -0
  157. data/lib/pubid/cie.rb +47 -1
  158. data/lib/pubid/components/adoption.rb +104 -0
  159. data/lib/pubid/components/code.rb +22 -8
  160. data/lib/pubid/components/date.rb +23 -16
  161. data/lib/pubid/components/edition.rb +9 -6
  162. data/lib/pubid/components/iteration.rb +32 -0
  163. data/lib/pubid/components/language.rb +6 -4
  164. data/lib/pubid/components/locality.rb +10 -1
  165. data/lib/pubid/components/publisher.rb +9 -6
  166. data/lib/pubid/components/relationship.rb +151 -0
  167. data/lib/pubid/components/stage.rb +5 -14
  168. data/lib/pubid/components/supplement.rb +184 -0
  169. data/lib/pubid/components/type.rb +5 -15
  170. data/lib/pubid/components/typed_stage.rb +10 -11
  171. data/lib/pubid/components.rb +4 -1
  172. data/lib/pubid/core/update_codes.rb +28 -7
  173. data/lib/pubid/csa/identifier.rb +9 -59
  174. data/lib/pubid/csa/identifiers/base.rb +0 -123
  175. data/lib/pubid/csa/identifiers/cec.rb +0 -103
  176. data/lib/pubid/csa/identifiers/series.rb +0 -104
  177. data/lib/pubid/csa/renderer.rb +292 -0
  178. data/lib/pubid/csa/single_identifier.rb +1 -1
  179. data/lib/pubid/csa/urn_generator.rb +1 -1
  180. data/lib/pubid/csa/urn_parser.rb +33 -0
  181. data/lib/pubid/csa.rb +46 -1
  182. data/lib/pubid/etsi/components/code.rb +10 -9
  183. data/lib/pubid/etsi/components/version.rb +0 -5
  184. data/lib/pubid/etsi/identifier.rb +4 -55
  185. data/lib/pubid/etsi/identifiers/base.rb +31 -27
  186. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +1 -11
  187. data/lib/pubid/etsi/renderer.rb +42 -0
  188. data/lib/pubid/etsi/urn_parser.rb +34 -0
  189. data/lib/pubid/etsi.rb +44 -1
  190. data/lib/pubid/export/exporter.rb +4 -46
  191. data/lib/pubid/export/flavor_exporter.rb +111 -278
  192. data/lib/pubid/export.rb +0 -6
  193. data/lib/pubid/identifier.rb +92 -18
  194. data/lib/pubid/identifier_metadata.rb +1 -1
  195. data/lib/pubid/idf/builder.rb +3 -3
  196. data/lib/pubid/idf/identifier.rb +7 -66
  197. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  198. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  199. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  200. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  201. data/lib/pubid/idf/parser.rb +3 -2
  202. data/lib/pubid/idf/renderer.rb +84 -0
  203. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  204. data/lib/pubid/idf/urn_generator.rb +4 -39
  205. data/lib/pubid/idf/urn_parser.rb +25 -0
  206. data/lib/pubid/idf.rb +55 -1
  207. data/lib/pubid/iec/builder.rb +46 -64
  208. data/lib/pubid/iec/components/code.rb +8 -32
  209. data/lib/pubid/iec/components/publisher.rb +0 -1
  210. data/lib/pubid/iec/components.rb +14 -0
  211. data/lib/pubid/iec/identifier.rb +251 -213
  212. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  213. data/lib/pubid/iec/identifiers/base.rb +5 -33
  214. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  215. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  216. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +23 -26
  217. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  218. data/lib/pubid/iec/identifiers/fragment_identifier.rb +35 -24
  219. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  220. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  221. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  222. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  223. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  224. data/lib/pubid/iec/identifiers/sheet_identifier.rb +17 -11
  225. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  226. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  227. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  228. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  229. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  230. data/lib/pubid/iec/identifiers/test_report_form.rb +3 -35
  231. data/lib/pubid/iec/identifiers/vap_identifier.rb +24 -21
  232. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  233. data/lib/pubid/iec/identifiers/working_document.rb +2 -50
  234. data/lib/pubid/iec/identifiers.rb +30 -0
  235. data/lib/pubid/iec/parser.rb +13 -12
  236. data/lib/pubid/iec/renderer.rb +254 -0
  237. data/lib/pubid/iec/single_identifier.rb +6 -12
  238. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  239. data/lib/pubid/iec/urn_generator.rb +3 -3
  240. data/lib/pubid/iec/urn_parser.rb +3 -3
  241. data/lib/pubid/iec.rb +43 -67
  242. data/lib/pubid/ieee/builder.rb +12 -12
  243. data/lib/pubid/ieee/components/code.rb +8 -0
  244. data/lib/pubid/ieee/components/draft.rb +14 -0
  245. data/lib/pubid/ieee/components/relationship.rb +5 -149
  246. data/lib/pubid/ieee/identifier.rb +5 -52
  247. data/lib/pubid/ieee/identifiers/adopted_standard.rb +0 -9
  248. data/lib/pubid/ieee/identifiers/base.rb +221 -556
  249. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +0 -10
  250. data/lib/pubid/ieee/identifiers/corrigendum.rb +0 -12
  251. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +0 -10
  252. data/lib/pubid/ieee/identifiers/dual_identifier.rb +0 -4
  253. data/lib/pubid/ieee/identifiers/dual_published.rb +0 -4
  254. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +0 -9
  255. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +0 -10
  256. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  257. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +0 -18
  258. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +0 -6
  259. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  260. data/lib/pubid/ieee/identifiers/redlined_standard.rb +0 -7
  261. data/lib/pubid/ieee/identifiers/si_standard.rb +0 -38
  262. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  263. data/lib/pubid/ieee/pre_parser.rb +301 -0
  264. data/lib/pubid/ieee/renderer.rb +307 -0
  265. data/lib/pubid/ieee/urn_parser.rb +34 -0
  266. data/lib/pubid/ieee.rb +66 -1
  267. data/lib/pubid/ieee_debug.rb +0 -1
  268. data/lib/pubid/iho/builder.rb +2 -2
  269. data/lib/pubid/iho/identifier.rb +7 -59
  270. data/lib/pubid/iho/identifiers/base.rb +64 -31
  271. data/lib/pubid/iho/parser.rb +3 -3
  272. data/lib/pubid/iho/renderer.rb +30 -0
  273. data/lib/pubid/iho/urn_generator.rb +2 -2
  274. data/lib/pubid/iho/urn_parser.rb +58 -0
  275. data/lib/pubid/iho.rb +52 -1
  276. data/lib/pubid/iso/builder.rb +55 -53
  277. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  278. data/lib/pubid/iso/components/code.rb +7 -19
  279. data/lib/pubid/iso/components/publisher.rb +10 -8
  280. data/lib/pubid/iso/components.rb +2 -4
  281. data/lib/pubid/iso/identifier.rb +219 -252
  282. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  283. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  284. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  285. data/lib/pubid/iso/identifiers/data.rb +0 -1
  286. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  287. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  288. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  289. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  290. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  291. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  292. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  293. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  294. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  295. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  296. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  297. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  298. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  299. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  300. data/lib/pubid/iso/identifiers.rb +0 -1
  301. data/lib/pubid/iso/normalizer.rb +89 -0
  302. data/lib/pubid/iso/parser.rb +22 -4
  303. data/lib/pubid/iso/single_identifier.rb +0 -4
  304. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  305. data/lib/pubid/iso/urn_generator.rb +66 -182
  306. data/lib/pubid/iso/urn_parser.rb +12 -7
  307. data/lib/pubid/iso.rb +177 -2
  308. data/lib/pubid/itu/builder.rb +0 -12
  309. data/lib/pubid/itu/components/code.rb +9 -7
  310. data/lib/pubid/itu/components/sector.rb +15 -4
  311. data/lib/pubid/itu/components/series.rb +0 -4
  312. data/lib/pubid/itu/components.rb +11 -0
  313. data/lib/pubid/itu/identifier.rb +4 -116
  314. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  315. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  316. data/lib/pubid/itu/identifiers/base.rb +124 -128
  317. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  318. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  319. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  320. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  321. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  322. data/lib/pubid/itu/urn_parser.rb +23 -0
  323. data/lib/pubid/itu.rb +44 -1
  324. data/lib/pubid/jcgm/builder.rb +16 -8
  325. data/lib/pubid/jcgm/identifier.rb +0 -43
  326. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -9
  327. data/lib/pubid/jcgm/identifiers/gum_guide.rb +0 -12
  328. data/lib/pubid/jcgm/renderer.rb +68 -0
  329. data/lib/pubid/jcgm/single_identifier.rb +0 -8
  330. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  331. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  332. data/lib/pubid/jcgm.rb +43 -2
  333. data/lib/pubid/jis/builder.rb +44 -52
  334. data/lib/pubid/jis/identifier.rb +120 -46
  335. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  336. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  337. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  338. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  339. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  340. data/lib/pubid/jis/identifiers.rb +1 -1
  341. data/lib/pubid/jis/parser.rb +31 -5
  342. data/lib/pubid/jis/renderer.rb +69 -0
  343. data/lib/pubid/jis/single_identifier.rb +6 -12
  344. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  345. data/lib/pubid/jis/urn_parser.rb +23 -0
  346. data/lib/pubid/jis.rb +42 -2
  347. data/lib/pubid/nist/builder.rb +63 -1871
  348. data/lib/pubid/nist/caster.rb +1272 -0
  349. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  350. data/lib/pubid/nist/components/code.rb +9 -20
  351. data/lib/pubid/nist/components/supplement.rb +2 -2
  352. data/lib/pubid/nist/components.rb +0 -1
  353. data/lib/pubid/nist/identifier.rb +8 -60
  354. data/lib/pubid/nist/identifiers/base.rb +564 -492
  355. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  356. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  357. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  358. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  359. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  360. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  361. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  362. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  363. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  364. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  365. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  366. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  367. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  368. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  369. data/lib/pubid/nist/identifiers/report.rb +4 -2
  370. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  371. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  372. data/lib/pubid/nist/identifiers.rb +1 -0
  373. data/lib/pubid/nist/parser.rb +62 -452
  374. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  375. data/lib/pubid/nist/preprocessor.rb +428 -0
  376. data/lib/pubid/nist/renderer.rb +43 -0
  377. data/lib/pubid/nist/router.rb +148 -0
  378. data/lib/pubid/nist/series/base.rb +58 -0
  379. data/lib/pubid/nist/series/crpl.rb +13 -0
  380. data/lib/pubid/nist/series/fips.rb +14 -0
  381. data/lib/pubid/nist/series/ir.rb +60 -0
  382. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  383. data/lib/pubid/nist/series/mono.rb +19 -0
  384. data/lib/pubid/nist/series/ncstar.rb +20 -0
  385. data/lib/pubid/nist/series.rb +49 -0
  386. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  387. data/lib/pubid/nist/urn_parser.rb +67 -0
  388. data/lib/pubid/nist.rb +86 -4
  389. data/lib/pubid/oiml/builder.rb +21 -3
  390. data/lib/pubid/oiml/components/code.rb +17 -0
  391. data/lib/pubid/oiml/identifier.rb +40 -46
  392. data/lib/pubid/oiml/identifiers/annex.rb +13 -46
  393. data/lib/pubid/oiml/identifiers/errata.rb +15 -0
  394. data/lib/pubid/oiml/identifiers.rb +1 -1
  395. data/lib/pubid/oiml/parser.rb +59 -12
  396. data/lib/pubid/oiml/renderer.rb +171 -0
  397. data/lib/pubid/oiml/single_identifier.rb +61 -42
  398. data/lib/pubid/oiml/supplement_identifier.rb +31 -17
  399. data/lib/pubid/oiml/urn_generator.rb +0 -8
  400. data/lib/pubid/oiml/urn_parser.rb +22 -0
  401. data/lib/pubid/oiml.rb +42 -1
  402. data/lib/pubid/plateau/identifier.rb +4 -55
  403. data/lib/pubid/plateau/identifiers/base.rb +45 -36
  404. data/lib/pubid/plateau/identifiers/handbook.rb +0 -6
  405. data/lib/pubid/plateau/identifiers/technical_report.rb +0 -4
  406. data/lib/pubid/plateau/renderer.rb +51 -0
  407. data/lib/pubid/plateau/supplement_identifier.rb +0 -4
  408. data/lib/pubid/plateau/urn_parser.rb +43 -0
  409. data/lib/pubid/plateau.rb +43 -1
  410. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  411. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  412. data/lib/pubid/renderers/human_readable.rb +18 -7
  413. data/lib/pubid/rendering/context.rb +28 -19
  414. data/lib/pubid/rendering.rb +0 -3
  415. data/lib/pubid/sae/components/date.rb +8 -0
  416. data/lib/pubid/sae/components/type.rb +5 -1
  417. data/lib/pubid/sae/identifier.rb +4 -35
  418. data/lib/pubid/sae/identifiers/base.rb +26 -31
  419. data/lib/pubid/sae/renderer.rb +36 -0
  420. data/lib/pubid/sae/urn_generator.rb +2 -10
  421. data/lib/pubid/sae/urn_parser.rb +36 -0
  422. data/lib/pubid/sae.rb +42 -1
  423. data/lib/pubid/urn_generator/base.rb +12 -12
  424. data/lib/pubid/urn_parser/base.rb +81 -0
  425. data/lib/pubid/urn_parser/errors.rb +9 -0
  426. data/lib/pubid/urn_parser.rb +14 -0
  427. data/lib/pubid/version.rb +1 -1
  428. data/lib/pubid.rb +45 -7
  429. data/lib/tasks/export.rake +6 -5
  430. data/lib/tasks/website-data.json +1940 -1882
  431. metadata +75 -45
  432. data/lib/pubid/amca/scheme.rb +0 -16
  433. data/lib/pubid/ansi/scheme.rb +0 -15
  434. data/lib/pubid/api/scheme.rb +0 -66
  435. data/lib/pubid/ashrae/scheme.rb +0 -53
  436. data/lib/pubid/asme/scheme.rb +0 -37
  437. data/lib/pubid/astm/scheme.rb +0 -55
  438. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  439. data/lib/pubid/bsi/scheme.rb +0 -243
  440. data/lib/pubid/ccsds/scheme.rb +0 -57
  441. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  442. data/lib/pubid/cie/scheme.rb +0 -64
  443. data/lib/pubid/components/factory.rb +0 -50
  444. data/lib/pubid/csa/scheme.rb +0 -44
  445. data/lib/pubid/etsi/scheme.rb +0 -42
  446. data/lib/pubid/export/data_class_exporter.rb +0 -59
  447. data/lib/pubid/export/ieee_exporter.rb +0 -78
  448. data/lib/pubid/export/itu_exporter.rb +0 -66
  449. data/lib/pubid/export/nist_exporter.rb +0 -64
  450. data/lib/pubid/export/registry_exporter.rb +0 -90
  451. data/lib/pubid/export/scheme_exporter.rb +0 -70
  452. data/lib/pubid/identifier_registry.rb +0 -198
  453. data/lib/pubid/idf/scheme.rb +0 -61
  454. data/lib/pubid/iec/scheme.rb +0 -71
  455. data/lib/pubid/ieee/scheme.rb +0 -90
  456. data/lib/pubid/iho/scheme.rb +0 -29
  457. data/lib/pubid/iso/identifiers/base.rb +0 -115
  458. data/lib/pubid/iso/scheme.rb +0 -193
  459. data/lib/pubid/itu/scheme.rb +0 -174
  460. data/lib/pubid/jcgm/scheme.rb +0 -60
  461. data/lib/pubid/jis/components/code.rb +0 -59
  462. data/lib/pubid/jis/identifiers/base.rb +0 -72
  463. data/lib/pubid/jis/scheme.rb +0 -49
  464. data/lib/pubid/nist/components/publisher.rb +0 -24
  465. data/lib/pubid/nist/scheme.rb +0 -199
  466. data/lib/pubid/oiml/identifiers/base.rb +0 -36
  467. data/lib/pubid/oiml/scheme.rb +0 -46
  468. data/lib/pubid/plateau/scheme.rb +0 -45
  469. data/lib/pubid/rendering/base.rb +0 -73
  470. data/lib/pubid/rendering/common.rb +0 -211
  471. data/lib/pubid/rendering/format.rb +0 -25
  472. data/lib/pubid/sae/scheme.rb +0 -47
  473. data/lib/pubid/scheme.rb +0 -219
@@ -1,154 +1,150 @@
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
- module Identifiers
12
- # Base class for all ITU identifiers
13
- class Base < Pubid::Identifier
14
- # Long-form ITU single-letter language code map. The parser produces
15
- # single-letter codes (E/F/S/R/A/C); API callers (e.g. metanorma-itu)
16
- # pass long-form (en/fr/es/ru/ar/zh). Storage is normalized to the
17
- # single-letter form. Languages with no canonical letter (e.g. "de")
18
- # pass through unchanged and produce no trailing suffix.
19
- LANGUAGES = {
20
- "fr" => "F", "es" => "S", "ru" => "R",
21
- "ar" => "A", "zh" => "C", "en" => "E",
22
- "F" => "F", "S" => "S", "R" => "R",
23
- "A" => "A", "C" => "C", "E" => "E"
24
- }.freeze
25
-
26
- attribute :sector, Pubid::Itu::Components::Sector
27
- attribute :series, Pubid::Itu::Components::Series
28
- attribute :code, Pubid::Itu::Components::Code
29
- attribute :date, Pubid::Components::Date
30
- attribute :language, :string
31
-
32
- def initialize(**kwargs)
33
- if kwargs[:language]
34
- kwargs = kwargs.merge(language: normalize_language(kwargs[:language]))
35
- end
36
-
37
- super
38
-
39
- validate_ob_no_sector!
40
- end
5
+ # Base class for all ITU identifiers. Canonical name Pubid::Itu::Identifier
6
+ # (Identifiers::Base is a back-compat alias).
7
+ class Identifier < ::Pubid::Identifier
8
+ # Parse an ITU identifier string into an identifier object.
9
+ def self.parse(identifier)
10
+ parsed = Parser.parse(identifier)
11
+ Builder.build(parsed)
12
+ rescue Parslet::ParseFailed => e
13
+ raise "Failed to parse ITU identifier '#{identifier}': #{e.message}"
14
+ end
41
15
 
42
- # Generate URN for this identifier
43
- #
44
- # @return [String] URN representation
45
-
46
- # Override base_hash to handle ITU-specific attributes
47
- def base_hash
48
- hash = super
49
- # ITU Series has a 'series' attribute, not 'number'
50
- if hash[:series].is_a?(Hash) && series
51
- hash[:series] = series.series
52
- end
53
- # Add sector (ITU-specific, has a 'sector' attribute)
54
- hash[:sector] = sector.sector if sector
55
- hash
16
+ # Long-form ITU single-letter language code map. The parser produces
17
+ # single-letter codes (E/F/S/R/A/C); API callers (e.g. metanorma-itu)
18
+ # pass long-form (en/fr/es/ru/ar/zh). Storage is normalized to the
19
+ # single-letter form. Languages with no canonical letter (e.g. "de")
20
+ # pass through unchanged and produce no trailing suffix.
21
+ LANGUAGES = {
22
+ "fr" => "F", "es" => "S", "ru" => "R",
23
+ "ar" => "A", "zh" => "C", "en" => "E",
24
+ "F" => "F", "S" => "S", "R" => "R",
25
+ "A" => "A", "C" => "C", "E" => "E"
26
+ }.freeze
27
+
28
+ attribute :sector, Pubid::Itu::Components::Sector
29
+ attribute :series, Pubid::Itu::Components::Series
30
+ attribute :code, Pubid::Itu::Components::Code
31
+ attribute :date, Pubid::Components::Date
32
+ attribute :language, :string
33
+
34
+ def initialize(**kwargs)
35
+ if kwargs[:language]
36
+ kwargs = kwargs.merge(language: normalize_language(kwargs[:language]))
56
37
  end
57
38
 
58
- def publisher
59
- "ITU"
60
- end
39
+ super
61
40
 
62
- # Render identifier as a string.
63
- #
64
- # @param i18n_lang [Symbol, String] language for identifier text
65
- # translation (e.g. :fr renders "Annex to" as "Annexe au"). Distinct
66
- # from the identifier's `language` attribute, which is the document's
67
- # own language and produces the trailing suffix like "-F".
68
- # @param language [Symbol, String] deprecated alias for i18n_lang.
69
- # @param format [Symbol] :long for title-style rendering of supported
70
- # identifiers, otherwise the default short form.
71
- def to_s(**opts)
72
- opts = self.class.normalize_to_s_opts(opts)
73
- render_base(**opts) + render_language_suffix
74
- end
41
+ validate_ob_no_sector!
42
+ end
75
43
 
76
- def render_base(**_opts)
77
- result = "#{publisher}-#{sector}"
44
+ # Generate URN for this identifier
45
+ #
46
+ # @return [String] URN representation
47
+
48
+ # Stored as a plain string (always "ITU") so it round-trips through
49
+ # to_hash/from_hash. Was a `def publisher` method, which made lutaml
50
+ # serialize a String against the Components::Publisher attribute.
51
+ attribute :publisher, :string, default: -> { "ITU" }
52
+
53
+ # Render identifier as a string.
54
+ #
55
+ # @param i18n_lang [Symbol, String] language for identifier text
56
+ # translation (e.g. :fr renders "Annex to" as "Annexe au"). Distinct
57
+ # from the identifier's `language` attribute, which is the document's
58
+ # own language and produces the trailing suffix like "-F".
59
+ # @param language [Symbol, String] deprecated alias for i18n_lang.
60
+ # @param format [Symbol] :long for title-style rendering of supported
61
+ # identifiers, otherwise the default short form.
62
+ def to_s(**opts)
63
+ opts = self.class.normalize_to_s_opts(opts)
64
+ render_base(**opts) + render_language_suffix
65
+ end
78
66
 
79
- # Add series and code
80
- result += if series
81
- " #{series}.#{code}"
82
- else
83
- " #{code}"
84
- end
67
+ def render_base(**_opts)
68
+ result = "#{publisher}-#{sector}"
85
69
 
86
- # Add date if present
87
- if date
88
- result += if date.month
89
- " (#{date.month}/#{date.year})"
90
- else
91
- " (#{date.year})"
92
- end
93
- end
70
+ # Add series and code
71
+ result += if series
72
+ " #{series}.#{code}"
73
+ else
74
+ " #{code}"
75
+ end
94
76
 
95
- result
77
+ # Add date if present
78
+ if date
79
+ result += if date.month
80
+ " (#{date.month}/#{date.year})"
81
+ else
82
+ " (#{date.year})"
83
+ end
96
84
  end
97
85
 
98
- def render_language_suffix
99
- return "" unless language
100
- # Only render canonical single-letter ITU language codes
101
- # (e.g. "F", "S"). Languages with no mapping (e.g. "de") get
102
- # no suffix — matches v1 PR #38 render_language behavior.
103
- return "" unless LANGUAGES.value?(language)
86
+ result
87
+ end
104
88
 
105
- "-#{language}"
106
- end
89
+ def render_language_suffix
90
+ return "" unless language
91
+ # Only render canonical single-letter ITU language codes
92
+ # (e.g. "F", "S"). Languages with no mapping (e.g. "de") get
93
+ # no suffix — matches v1 PR #38 render_language behavior.
94
+ return "" unless LANGUAGES.value?(language)
95
+
96
+ "-#{language}"
97
+ end
107
98
 
108
- # Translate `language:` opt to `i18n_lang:` opt. v1 PR #38 introduced
109
- # `i18n_lang:` to disambiguate "rendering language" from the document
110
- # language attribute; `language:` remains a deprecated alias.
111
- def self.normalize_to_s_opts(opts)
112
- opts = opts.dup
113
- if opts.key?(:language) && !opts.key?(:i18n_lang)
114
- opts[:i18n_lang] = opts.delete(:language)
115
- else
116
- opts.delete(:language)
117
- end
118
- opts
99
+ # Translate `language:` opt to `i18n_lang:` opt. v1 PR #38 introduced
100
+ # `i18n_lang:` to disambiguate "rendering language" from the document
101
+ # language attribute; `language:` remains a deprecated alias.
102
+ def self.normalize_to_s_opts(opts)
103
+ opts = opts.dup
104
+ if opts.key?(:language) && !opts.key?(:i18n_lang)
105
+ opts[:i18n_lang] = opts.delete(:language)
106
+ else
107
+ opts.delete(:language)
119
108
  end
109
+ opts
110
+ end
120
111
 
121
- def ==(other)
122
- return false unless other.is_a?(Base)
112
+ def ==(other)
113
+ return false unless other.is_a?(Pubid::Itu::Identifier)
123
114
 
124
- sector == other.sector &&
125
- series == other.series &&
126
- code == other.code &&
127
- date == other.date &&
128
- language == other.language
129
- end
115
+ sector == other.sector &&
116
+ series == other.series &&
117
+ code == other.code &&
118
+ date == other.date &&
119
+ language == other.language
120
+ end
130
121
 
131
- private
122
+ private
132
123
 
133
- def normalize_language(value)
134
- str = value.to_s
135
- LANGUAGES[str] || str
136
- end
124
+ def normalize_language(value)
125
+ str = value.to_s
126
+ LANGUAGES[str] || str
127
+ end
137
128
 
138
- # OB (Operational Bulletin) is a cross-bureau ITU publication and
139
- # must not have a sector. Direct construction with both raises;
140
- # the parser silently drops sector for legacy strings like
141
- # "ITU-T OB.X" (handled in Builder).
142
- def validate_ob_no_sector!
143
- return unless series&.series == "OB"
144
- return if sector.nil?
145
- return if sector.is_a?(Components::Sector) && (sector.sector.nil? || sector.sector.to_s.empty?)
146
-
147
- raise ArgumentError,
148
- "OB (Operational Bulletin) is a cross-bureau ITU publication; " \
149
- "sector must not be set"
150
- end
129
+ # OB (Operational Bulletin) is a cross-bureau ITU publication and
130
+ # must not have a sector. Direct construction with both raises;
131
+ # the parser silently drops sector for legacy strings like
132
+ # "ITU-T OB.X" (handled in Builder).
133
+ def validate_ob_no_sector!
134
+ return unless series&.series == "OB"
135
+ return if sector.nil?
136
+ return if sector.is_a?(Components::Sector) && (sector.sector.nil? || sector.sector.to_s.empty?)
137
+
138
+ raise ArgumentError,
139
+ "OB (Operational Bulletin) is a cross-bureau ITU publication; " \
140
+ "sector must not be set"
151
141
  end
152
142
  end
143
+
144
+ module Identifiers
145
+ # Backward-compatible alias: ITU's base class used to be
146
+ # Pubid::Itu::Identifiers::Base. It is now Pubid::Itu::Identifier.
147
+ Base = Pubid::Itu::Identifier
148
+ end
153
149
  end
154
150
  end
@@ -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,59 @@ 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
+ # Exclude the flavor base itself by identity (Identifiers::Base is now an
31
+ # alias for Pubid::Itu::Identifier, so name-based matching misses it).
32
+ .reject { |c| c == Identifiers::Base }
33
+ end
34
+
35
+ # Build typed stage index from identifier types
36
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
37
+ def self.all_typed_stages
38
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
39
+ if klass.const_defined?(:TYPED_STAGES)
40
+ klass.const_get(:TYPED_STAGES)
41
+ else
42
+ []
43
+ end
44
+ end
45
+ end
46
+
47
+ # Lookup: type code -> identifier class
48
+ # @param code [String, Symbol] the type key to find
49
+ # @return [Class, nil] the matching identifier class
50
+ def self.locate_type(code)
51
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
52
+ end
53
+
54
+ # Lookup: abbreviation -> typed stage
55
+ # @param abbr [String, Symbol] the abbreviation to find
56
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
57
+ def self.locate_stage(abbr)
58
+ abbr_str = abbr.to_s.upcase
59
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
60
+ end
18
61
  end
19
62
  end
20
63
 
@@ -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
@@ -6,49 +6,6 @@ module Pubid
6
6
  def self.parse(string)
7
7
  Pubid::Jcgm.parse(string)
8
8
  end
9
-
10
- # Factory mirroring pubid 1.x's `Pubid::Jcgm::Identifier.create` API.
11
- # Dispatches `:guide` (default) → Guide, `:gum_guide` → GumGuide.
12
- TYPE_KEY_TO_KLASS = {
13
- guide: "Guide",
14
- gum_guide: "GumGuide",
15
- }.freeze
16
-
17
- def self.create(type: nil, **opts)
18
- klass = resolve_create_class(type)
19
- attrs = coerce_create_attrs(opts)
20
- ts = klass.const_defined?(:TYPED_STAGES) &&
21
- klass.const_get(:TYPED_STAGES).find do |t|
22
- t.stage_code&.to_sym == :published
23
- end
24
- attrs[:typed_stage] = ts if ts
25
- klass.new(**attrs)
26
- end
27
-
28
- def self.resolve_create_class(type)
29
- return Identifiers::Guide if type.nil?
30
-
31
- klass_name = TYPE_KEY_TO_KLASS[type.to_sym]
32
- raise ArgumentError, "Unknown JCGM type: #{type.inspect}" unless klass_name
33
-
34
- Identifiers.const_get(klass_name)
35
- end
36
-
37
- def self.coerce_create_attrs(opts)
38
- attrs = {
39
- publisher: Pubid::Jcgm::Components::Publisher.new(
40
- publisher: (opts[:publisher] || "JCGM").to_s,
41
- ),
42
- }
43
- if (v = opts[:number])
44
- attrs[:number] = Pubid::Components::Code.new(value: v.to_s)
45
- end
46
- if (v = opts[:year])
47
- attrs[:date] = Pubid::Components::Date.new(year: v.to_s)
48
- end
49
- attrs
50
- end
51
- private_class_method :resolve_create_class, :coerce_create_attrs
52
9
  end
53
10
  end
54
11
  end
@@ -20,15 +20,6 @@ module Pubid
20
20
  def self.type
21
21
  { key: :amendment, title: "Amendment", short: "Amd" }
22
22
  end
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
31
- end
32
23
  end
33
24
  end
34
25
  end
@@ -22,18 +22,6 @@ 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
35
- end
36
-
37
25
  private
38
26
 
39
27
  def language_portion
@@ -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
@@ -35,14 +35,6 @@ module Pubid
35
35
  ")",
36
36
  ].join
37
37
  end
38
-
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
45
- end
46
38
  end
47
39
  end
48
40
  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"