pubid 2.0.0.pre.alpha.2 → 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 (458) 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 +7 -39
  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 -43
  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 -51
  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 -39
  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/identifier.rb +0 -46
  55. data/lib/pubid/asme/identifiers/base.rb +0 -60
  56. data/lib/pubid/asme/renderer.rb +66 -0
  57. data/lib/pubid/asme/urn_parser.rb +31 -0
  58. data/lib/pubid/asme.rb +42 -1
  59. data/lib/pubid/astm/components/code.rb +9 -0
  60. data/lib/pubid/{jis → astm}/components.rb +1 -1
  61. data/lib/pubid/astm/identifier.rb +0 -77
  62. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  63. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  64. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  65. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  66. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  67. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  68. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  69. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  70. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  71. data/lib/pubid/astm/identifiers.rb +18 -0
  72. data/lib/pubid/astm/renderer.rb +172 -0
  73. data/lib/pubid/astm/single_identifier.rb +0 -10
  74. data/lib/pubid/astm/urn_parser.rb +30 -0
  75. data/lib/pubid/astm.rb +39 -27
  76. data/lib/pubid/bsi/builder.rb +21 -12
  77. data/lib/pubid/bsi/identifier.rb +8 -62
  78. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  79. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  80. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  81. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  82. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  83. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  84. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  85. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  87. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  88. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  89. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  90. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  91. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  92. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  93. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  94. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  95. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  96. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  97. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  98. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  99. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  100. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  101. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  102. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  103. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  104. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  105. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  106. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  107. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  108. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  109. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  110. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  111. data/lib/pubid/bsi/identifiers.rb +0 -1
  112. data/lib/pubid/bsi/renderer.rb +1050 -0
  113. data/lib/pubid/bsi/single_identifier.rb +6 -70
  114. data/lib/pubid/bsi/urn_generator.rb +2 -3
  115. data/lib/pubid/bsi/urn_parser.rb +52 -0
  116. data/lib/pubid/bsi.rb +224 -1
  117. data/lib/pubid/builder/base.rb +57 -10
  118. data/lib/pubid/bundled_identifier.rb +0 -1
  119. data/lib/pubid/ccsds/builder.rb +4 -3
  120. data/lib/pubid/ccsds/identifier.rb +63 -66
  121. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  122. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  123. data/lib/pubid/ccsds/parser.rb +4 -2
  124. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  125. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  126. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  127. data/lib/pubid/ccsds.rb +39 -1
  128. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  129. data/lib/pubid/cen_cenelec/identifier.rb +7 -38
  130. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  131. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  132. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  133. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  135. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  136. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  137. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  139. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  140. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  141. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  143. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  145. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  146. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  147. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  148. data/lib/pubid/cen_cenelec.rb +168 -1
  149. data/lib/pubid/cie/components/code.rb +8 -0
  150. data/lib/pubid/cie/identifier.rb +6 -57
  151. data/lib/pubid/cie/urn_parser.rb +28 -0
  152. data/lib/pubid/cie.rb +43 -1
  153. data/lib/pubid/components/adoption.rb +104 -0
  154. data/lib/pubid/components/code.rb +22 -8
  155. data/lib/pubid/components/date.rb +23 -16
  156. data/lib/pubid/components/edition.rb +9 -6
  157. data/lib/pubid/components/iteration.rb +32 -0
  158. data/lib/pubid/components/language.rb +6 -4
  159. data/lib/pubid/components/locality.rb +10 -1
  160. data/lib/pubid/components/publisher.rb +9 -6
  161. data/lib/pubid/components/relationship.rb +151 -0
  162. data/lib/pubid/components/stage.rb +5 -14
  163. data/lib/pubid/components/supplement.rb +184 -0
  164. data/lib/pubid/components/type.rb +5 -15
  165. data/lib/pubid/components/typed_stage.rb +10 -11
  166. data/lib/pubid/components.rb +4 -1
  167. data/lib/pubid/core/update_codes.rb +28 -7
  168. data/lib/pubid/csa/identifier.rb +0 -59
  169. data/lib/pubid/csa/identifiers/base.rb +2 -122
  170. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  171. data/lib/pubid/csa/identifiers/series.rb +2 -102
  172. data/lib/pubid/csa/renderer.rb +292 -0
  173. data/lib/pubid/csa/urn_generator.rb +1 -1
  174. data/lib/pubid/csa/urn_parser.rb +33 -0
  175. data/lib/pubid/csa.rb +42 -1
  176. data/lib/pubid/etsi/components/code.rb +9 -2
  177. data/lib/pubid/etsi/identifier.rb +0 -43
  178. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  179. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  180. data/lib/pubid/etsi/renderer.rb +42 -0
  181. data/lib/pubid/etsi/urn_parser.rb +34 -0
  182. data/lib/pubid/etsi.rb +42 -1
  183. data/lib/pubid/export/exporter.rb +4 -46
  184. data/lib/pubid/export/flavor_exporter.rb +111 -278
  185. data/lib/pubid/export.rb +0 -6
  186. data/lib/pubid/identifier.rb +2 -17
  187. data/lib/pubid/identifier_facade.rb +114 -0
  188. data/lib/pubid/identifier_metadata.rb +1 -1
  189. data/lib/pubid/idf/builder.rb +3 -3
  190. data/lib/pubid/idf/identifier.rb +3 -66
  191. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  192. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  193. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  194. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  195. data/lib/pubid/idf/parser.rb +3 -2
  196. data/lib/pubid/idf/renderer.rb +84 -0
  197. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  198. data/lib/pubid/idf/urn_generator.rb +4 -39
  199. data/lib/pubid/idf/urn_parser.rb +25 -0
  200. data/lib/pubid/idf.rb +51 -1
  201. data/lib/pubid/iec/builder.rb +46 -64
  202. data/lib/pubid/iec/components/code.rb +8 -32
  203. data/lib/pubid/iec/components/publisher.rb +0 -1
  204. data/lib/pubid/iec/components.rb +14 -0
  205. data/lib/pubid/iec/identifier.rb +251 -213
  206. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  207. data/lib/pubid/iec/identifiers/base.rb +8 -32
  208. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  209. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  210. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -26
  211. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  212. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -22
  213. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  214. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  215. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  216. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  217. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  218. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -11
  219. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  220. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  222. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  223. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  224. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  225. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -19
  226. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  227. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  228. data/lib/pubid/iec/identifiers.rb +30 -0
  229. data/lib/pubid/iec/parser.rb +13 -12
  230. data/lib/pubid/iec/renderer.rb +254 -0
  231. data/lib/pubid/iec/single_identifier.rb +6 -12
  232. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  233. data/lib/pubid/iec/urn_generator.rb +3 -3
  234. data/lib/pubid/iec/urn_parser.rb +3 -3
  235. data/lib/pubid/iec.rb +40 -68
  236. data/lib/pubid/ieee/builder.rb +12 -12
  237. data/lib/pubid/ieee/components/code.rb +8 -0
  238. data/lib/pubid/ieee/components/draft.rb +14 -0
  239. data/lib/pubid/ieee/components/relationship.rb +5 -149
  240. data/lib/pubid/ieee/identifier.rb +6 -41
  241. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  242. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  243. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  245. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  246. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  247. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  248. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  249. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  250. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  251. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  252. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  253. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  254. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  255. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  256. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  257. data/lib/pubid/ieee/pre_parser.rb +301 -0
  258. data/lib/pubid/ieee/renderer.rb +307 -0
  259. data/lib/pubid/ieee/urn_parser.rb +34 -0
  260. data/lib/pubid/ieee.rb +62 -1
  261. data/lib/pubid/ieee_debug.rb +0 -1
  262. data/lib/pubid/iho/builder.rb +2 -2
  263. data/lib/pubid/iho/identifier.rb +8 -42
  264. data/lib/pubid/iho/identifiers/base.rb +49 -10
  265. data/lib/pubid/iho/parser.rb +3 -3
  266. data/lib/pubid/iho/renderer.rb +30 -0
  267. data/lib/pubid/iho/urn_generator.rb +2 -2
  268. data/lib/pubid/iho/urn_parser.rb +58 -0
  269. data/lib/pubid/iho.rb +50 -1
  270. data/lib/pubid/iso/builder.rb +55 -53
  271. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  272. data/lib/pubid/iso/components/code.rb +7 -19
  273. data/lib/pubid/iso/components/publisher.rb +10 -8
  274. data/lib/pubid/iso/components.rb +2 -4
  275. data/lib/pubid/iso/identifier.rb +218 -252
  276. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  277. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  278. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  279. data/lib/pubid/iso/identifiers/data.rb +0 -1
  280. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  281. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  282. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  283. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  284. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  285. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  286. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  287. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  288. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  289. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  290. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  291. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  292. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  293. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  294. data/lib/pubid/iso/identifiers.rb +0 -1
  295. data/lib/pubid/iso/normalizer.rb +89 -0
  296. data/lib/pubid/iso/parser.rb +22 -4
  297. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  298. data/lib/pubid/iso/urn_generator.rb +66 -182
  299. data/lib/pubid/iso/urn_parser.rb +12 -7
  300. data/lib/pubid/iso.rb +173 -2
  301. data/lib/pubid/itu/builder.rb +0 -12
  302. data/lib/pubid/itu/components/code.rb +8 -0
  303. data/lib/pubid/itu/components.rb +11 -0
  304. data/lib/pubid/itu/identifier.rb +6 -104
  305. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  306. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  307. data/lib/pubid/itu/identifiers/base.rb +0 -6
  308. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  309. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  310. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  311. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  312. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  313. data/lib/pubid/itu/urn_parser.rb +23 -0
  314. data/lib/pubid/itu.rb +42 -1
  315. data/lib/pubid/jcgm/builder.rb +16 -8
  316. data/lib/pubid/jcgm/identifier.rb +0 -43
  317. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  318. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  319. data/lib/pubid/jcgm/renderer.rb +68 -0
  320. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  321. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  322. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  323. data/lib/pubid/jcgm.rb +43 -2
  324. data/lib/pubid/jis/builder.rb +44 -52
  325. data/lib/pubid/jis/identifier.rb +132 -46
  326. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  327. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  328. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  329. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  330. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  331. data/lib/pubid/jis/identifiers.rb +1 -1
  332. data/lib/pubid/jis/parser.rb +31 -5
  333. data/lib/pubid/jis/renderer.rb +69 -0
  334. data/lib/pubid/jis/single_identifier.rb +6 -12
  335. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  336. data/lib/pubid/jis/urn_parser.rb +23 -0
  337. data/lib/pubid/jis.rb +42 -2
  338. data/lib/pubid/nist/builder.rb +63 -1871
  339. data/lib/pubid/nist/caster.rb +1272 -0
  340. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  341. data/lib/pubid/nist/components/code.rb +9 -20
  342. data/lib/pubid/nist/components/supplement.rb +2 -2
  343. data/lib/pubid/nist/components.rb +0 -1
  344. data/lib/pubid/nist/identifier.rb +11 -48
  345. data/lib/pubid/nist/identifiers/base.rb +110 -47
  346. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  347. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  348. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  349. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  350. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  351. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  352. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  353. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  354. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  355. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  356. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  357. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  358. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  359. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  360. data/lib/pubid/nist/identifiers/report.rb +4 -2
  361. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  362. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  363. data/lib/pubid/nist/identifiers.rb +1 -0
  364. data/lib/pubid/nist/parser.rb +62 -452
  365. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  366. data/lib/pubid/nist/preprocessor.rb +416 -0
  367. data/lib/pubid/nist/renderer.rb +43 -0
  368. data/lib/pubid/nist/router.rb +148 -0
  369. data/lib/pubid/nist/series/base.rb +58 -0
  370. data/lib/pubid/nist/series/crpl.rb +13 -0
  371. data/lib/pubid/nist/series/fips.rb +14 -0
  372. data/lib/pubid/nist/series/ir.rb +60 -0
  373. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  374. data/lib/pubid/nist/series/mono.rb +19 -0
  375. data/lib/pubid/nist/series/ncstar.rb +20 -0
  376. data/lib/pubid/nist/series.rb +49 -0
  377. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  378. data/lib/pubid/nist/urn_parser.rb +67 -0
  379. data/lib/pubid/nist.rb +82 -4
  380. data/lib/pubid/oiml/components/code.rb +10 -0
  381. data/lib/pubid/oiml/identifier.rb +0 -50
  382. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  383. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  384. data/lib/pubid/oiml/renderer.rb +161 -0
  385. data/lib/pubid/oiml/single_identifier.rb +6 -45
  386. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  387. data/lib/pubid/oiml/urn_generator.rb +0 -8
  388. data/lib/pubid/oiml/urn_parser.rb +22 -0
  389. data/lib/pubid/oiml.rb +42 -1
  390. data/lib/pubid/plateau/identifier.rb +7 -41
  391. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  392. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  393. data/lib/pubid/plateau/renderer.rb +51 -0
  394. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  395. data/lib/pubid/plateau/urn_parser.rb +43 -0
  396. data/lib/pubid/plateau.rb +43 -1
  397. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  398. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  399. data/lib/pubid/renderers/human_readable.rb +18 -7
  400. data/lib/pubid/rendering/context.rb +28 -19
  401. data/lib/pubid/rendering.rb +0 -3
  402. data/lib/pubid/sae/components/date.rb +8 -0
  403. data/lib/pubid/sae/components/type.rb +5 -1
  404. data/lib/pubid/sae/identifier.rb +0 -23
  405. data/lib/pubid/sae/identifiers/base.rb +2 -16
  406. data/lib/pubid/sae/renderer.rb +36 -0
  407. data/lib/pubid/sae/urn_generator.rb +2 -10
  408. data/lib/pubid/sae/urn_parser.rb +36 -0
  409. data/lib/pubid/sae.rb +42 -1
  410. data/lib/pubid/urn_generator/base.rb +12 -12
  411. data/lib/pubid/urn_parser/base.rb +81 -0
  412. data/lib/pubid/urn_parser/errors.rb +9 -0
  413. data/lib/pubid/urn_parser.rb +14 -0
  414. data/lib/pubid/version.rb +1 -1
  415. data/lib/pubid.rb +29 -7
  416. data/lib/tasks/website-data.json +1940 -1882
  417. metadata +75 -44
  418. data/lib/pubid/amca/scheme.rb +0 -16
  419. data/lib/pubid/ansi/scheme.rb +0 -15
  420. data/lib/pubid/api/scheme.rb +0 -66
  421. data/lib/pubid/ashrae/scheme.rb +0 -53
  422. data/lib/pubid/asme/scheme.rb +0 -37
  423. data/lib/pubid/astm/scheme.rb +0 -55
  424. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  425. data/lib/pubid/bsi/scheme.rb +0 -243
  426. data/lib/pubid/ccsds/scheme.rb +0 -57
  427. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  428. data/lib/pubid/cie/scheme.rb +0 -64
  429. data/lib/pubid/components/factory.rb +0 -50
  430. data/lib/pubid/csa/scheme.rb +0 -44
  431. data/lib/pubid/etsi/scheme.rb +0 -42
  432. data/lib/pubid/export/data_class_exporter.rb +0 -59
  433. data/lib/pubid/export/ieee_exporter.rb +0 -78
  434. data/lib/pubid/export/itu_exporter.rb +0 -66
  435. data/lib/pubid/export/nist_exporter.rb +0 -64
  436. data/lib/pubid/export/registry_exporter.rb +0 -90
  437. data/lib/pubid/export/scheme_exporter.rb +0 -70
  438. data/lib/pubid/identifier_registry.rb +0 -198
  439. data/lib/pubid/idf/scheme.rb +0 -61
  440. data/lib/pubid/iec/scheme.rb +0 -71
  441. data/lib/pubid/ieee/scheme.rb +0 -90
  442. data/lib/pubid/iho/scheme.rb +0 -29
  443. data/lib/pubid/iso/identifiers/base.rb +0 -115
  444. data/lib/pubid/iso/scheme.rb +0 -193
  445. data/lib/pubid/itu/scheme.rb +0 -174
  446. data/lib/pubid/jcgm/scheme.rb +0 -60
  447. data/lib/pubid/jis/components/code.rb +0 -59
  448. data/lib/pubid/jis/identifiers/base.rb +0 -72
  449. data/lib/pubid/jis/scheme.rb +0 -49
  450. data/lib/pubid/nist/components/publisher.rb +0 -24
  451. data/lib/pubid/nist/scheme.rb +0 -199
  452. data/lib/pubid/oiml/scheme.rb +0 -46
  453. data/lib/pubid/plateau/scheme.rb +0 -45
  454. data/lib/pubid/rendering/base.rb +0 -73
  455. data/lib/pubid/rendering/common.rb +0 -211
  456. data/lib/pubid/rendering/format.rb +0 -25
  457. data/lib/pubid/sae/scheme.rb +0 -47
  458. data/lib/pubid/scheme.rb +0 -219
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,103 +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 pubid 1.x's `Pubid::Itu::Identifier.create` API.
21
- # Dispatch on `:type`:
22
- # * nil → Recommendation (or SpecialPublication for series "OB")
23
- # * :recommendation → Identifiers::Recommendation
24
- # * :annex → Identifiers::Annex
25
- # * :special_publication → Identifiers::SpecialPublication
26
- #
27
- # Component-typed kwargs are accepted as primitives and coerced:
28
- # * sector: "T" → Components::Sector.new(sector: "T")
29
- # * series: "X" → Components::Series.new(series: "X")
30
- # * number: "509" → Components::Code.new(number: "509")
31
- # * year: "2020" → Pubid::Components::Date.new(year: "2020")
32
- TYPE_KEY_TO_KLASS = {
33
- recommendation: "Recommendation",
34
- annex: "Annex",
35
- special_publication: "SpecialPublication",
36
- }.freeze
37
-
38
- def self.create(type: nil, **kwargs)
39
- # Backward-compat: nil type + series "OB" → SpecialPublication.
40
- if type.nil? && kwargs[:series].to_s == "OB"
41
- return create_special_publication(**kwargs)
42
- end
43
-
44
- klass = resolve_create_class(type)
45
- klass.new(**coerce_create_attrs(kwargs, klass: klass))
46
- end
47
-
48
- def self.resolve_create_class(type)
49
- return Identifiers::Recommendation if type.nil?
50
-
51
- klass_name = TYPE_KEY_TO_KLASS[type.to_sym]
52
- raise ArgumentError, "Unknown ITU type: #{type.inspect}" unless klass_name
53
-
54
- Identifiers.const_get(klass_name)
55
- end
56
-
57
- # Backward-compat helper retained for the OB-series shortcut.
58
- def self.create_special_publication(number:, series: "OB", date: nil,
59
- language: nil)
60
- Identifiers::SpecialPublication.new(
61
- series: Components::Series.new(series: series.to_s),
62
- code: Components::Code.new(number: number.to_s),
63
- date: date,
64
- language: language&.to_s,
65
- )
66
- end
67
-
68
- def self.coerce_create_attrs(opts, klass: nil)
69
- attrs = {}
70
- if (v = opts[:sector])
71
- attrs[:sector] = if v.is_a?(Components::Sector)
72
- v
73
- else
74
- Components::Sector.new(sector: v.to_s.upcase)
75
- end
76
- end
77
- if (v = opts[:series])
78
- attrs[:series] = if v.is_a?(Components::Series)
79
- v
80
- else
81
- Components::Series.new(series: v.to_s)
82
- end
83
- end
84
- if opts[:number] || opts[:code]
85
- code_value = opts[:code]
86
- if code_value.is_a?(Components::Code)
87
- attrs[:code] = code_value
88
- else
89
- attrs[:code] = Components::Code.new(
90
- number: (opts[:number] || code_value).to_s,
91
- subseries: opts[:subseries]&.to_s,
92
- parts: opts[:parts] ? Array(opts[:parts]).map(&:to_s) : nil,
93
- )
94
- end
95
- end
96
- if (v = opts[:year])
97
- attrs[:date] = Pubid::Components::Date.new(year: v.to_s)
98
- end
99
- attrs[:date] = opts[:date] if opts[:date].is_a?(Pubid::Components::Date)
100
- attrs[:language] = opts[:language].to_s if opts[:language]
101
-
102
- # Pass through any subclass-specific kwarg the chosen class
103
- # declares (e.g. Annex#base) — preserves callers that already pass
104
- # an explicit attribute that our coercion table doesn't cover.
105
- if klass
106
- consumed = %i[sector series number code subseries parts year date
107
- language]
108
- opts.each do |k, v|
109
- next if consumed.include?(k) || attrs.key?(k)
110
- attrs[k] = v if klass.attributes.key?(k)
111
- end
112
- end
113
- attrs
114
- end
115
- private_class_method :resolve_create_class, :coerce_create_attrs
116
18
  end
117
19
  end
118
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
@@ -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
@@ -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