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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +27 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -0
  6. data/lib/pubid/amca/identifiers/base.rb +0 -26
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -17
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -13
  9. data/lib/pubid/amca/renderer.rb +82 -0
  10. data/lib/pubid/amca/single_identifier.rb +0 -23
  11. data/lib/pubid/amca/urn_parser.rb +28 -0
  12. data/lib/pubid/amca.rb +42 -1
  13. data/lib/pubid/ansi/builder.rb +5 -3
  14. data/lib/pubid/ansi/identifier.rb +1 -1
  15. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  16. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  17. data/lib/pubid/ansi/renderer.rb +53 -0
  18. data/lib/pubid/ansi/single_identifier.rb +2 -31
  19. data/lib/pubid/ansi/urn_generator.rb +3 -38
  20. data/lib/pubid/ansi/urn_parser.rb +23 -0
  21. data/lib/pubid/ansi.rb +38 -3
  22. data/lib/pubid/api/builder.rb +29 -74
  23. data/lib/pubid/api/identifier.rb +0 -4
  24. data/lib/pubid/api/identifiers/base.rb +0 -2
  25. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  26. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  27. data/lib/pubid/api/identifiers/mpms.rb +1 -17
  28. data/lib/pubid/api/identifiers/publication.rb +0 -2
  29. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  30. data/lib/pubid/api/identifiers/specification.rb +0 -2
  31. data/lib/pubid/api/identifiers/standard.rb +0 -2
  32. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  33. data/lib/pubid/api/identifiers/typeless_standard.rb +1 -14
  34. data/lib/pubid/api/identifiers.rb +18 -0
  35. data/lib/pubid/api/renderer.rb +89 -0
  36. data/lib/pubid/api/single_identifier.rb +1 -13
  37. data/lib/pubid/api/urn_generator.rb +0 -18
  38. data/lib/pubid/api/urn_parser.rb +35 -0
  39. data/lib/pubid/api.rb +51 -5
  40. data/lib/pubid/ashrae/builder.rb +3 -3
  41. data/lib/pubid/ashrae/identifier.rb +6 -0
  42. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  43. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  44. data/lib/pubid/ashrae/identifiers/base.rb +3 -0
  45. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  46. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  47. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  48. data/lib/pubid/ashrae/renderer.rb +117 -0
  49. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  50. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  51. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  52. data/lib/pubid/ashrae.rb +42 -1
  53. data/lib/pubid/asme/components/code.rb +10 -2
  54. data/lib/pubid/asme/identifiers/base.rb +0 -60
  55. data/lib/pubid/asme/renderer.rb +66 -0
  56. data/lib/pubid/asme/urn_parser.rb +31 -0
  57. data/lib/pubid/asme.rb +42 -1
  58. data/lib/pubid/astm/components/code.rb +9 -0
  59. data/lib/pubid/{jis → astm}/components.rb +1 -1
  60. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  61. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  62. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  63. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  64. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  65. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  66. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  67. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  68. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  69. data/lib/pubid/astm/identifiers.rb +18 -0
  70. data/lib/pubid/astm/renderer.rb +172 -0
  71. data/lib/pubid/astm/single_identifier.rb +0 -10
  72. data/lib/pubid/astm/urn_parser.rb +30 -0
  73. data/lib/pubid/astm.rb +39 -27
  74. data/lib/pubid/bsi/builder.rb +21 -12
  75. data/lib/pubid/bsi/identifier.rb +8 -2
  76. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  77. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  78. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  79. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  80. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  81. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  82. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  83. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  84. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  85. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  87. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  88. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  89. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  90. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  91. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  92. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  93. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  94. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  95. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  96. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  97. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  98. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  99. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  100. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  101. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  102. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  103. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  104. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  105. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  106. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  107. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  108. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  109. data/lib/pubid/bsi/identifiers.rb +0 -1
  110. data/lib/pubid/bsi/renderer.rb +1050 -0
  111. data/lib/pubid/bsi/single_identifier.rb +6 -70
  112. data/lib/pubid/bsi/urn_generator.rb +2 -3
  113. data/lib/pubid/bsi/urn_parser.rb +52 -0
  114. data/lib/pubid/bsi.rb +224 -1
  115. data/lib/pubid/builder/base.rb +57 -10
  116. data/lib/pubid/bundled_identifier.rb +0 -1
  117. data/lib/pubid/ccsds/builder.rb +4 -3
  118. data/lib/pubid/ccsds/identifier.rb +66 -1
  119. data/lib/pubid/ccsds/identifiers/base.rb +11 -50
  120. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  121. data/lib/pubid/ccsds/parser.rb +4 -2
  122. data/lib/pubid/ccsds/single_identifier.rb +4 -1
  123. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  124. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  125. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  126. data/lib/pubid/ccsds.rb +39 -1
  127. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  128. data/lib/pubid/cen_cenelec/identifier.rb +8 -2
  129. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  130. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  131. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  132. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  133. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  135. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  136. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  137. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  138. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  140. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  141. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  143. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  144. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  145. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  146. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  147. data/lib/pubid/cen_cenelec.rb +168 -1
  148. data/lib/pubid/cie/components/code.rb +8 -0
  149. data/lib/pubid/cie/identifier.rb +6 -4
  150. data/lib/pubid/cie/urn_parser.rb +28 -0
  151. data/lib/pubid/cie.rb +43 -1
  152. data/lib/pubid/components/adoption.rb +104 -0
  153. data/lib/pubid/components/code.rb +22 -8
  154. data/lib/pubid/components/date.rb +23 -16
  155. data/lib/pubid/components/edition.rb +9 -6
  156. data/lib/pubid/components/iteration.rb +32 -0
  157. data/lib/pubid/components/language.rb +6 -4
  158. data/lib/pubid/components/locality.rb +10 -1
  159. data/lib/pubid/components/publisher.rb +9 -6
  160. data/lib/pubid/components/relationship.rb +151 -0
  161. data/lib/pubid/components/stage.rb +5 -14
  162. data/lib/pubid/components/supplement.rb +184 -0
  163. data/lib/pubid/components/type.rb +5 -15
  164. data/lib/pubid/components/typed_stage.rb +11 -8
  165. data/lib/pubid/components.rb +4 -0
  166. data/lib/pubid/core/update_codes.rb +28 -7
  167. data/lib/pubid/csa/identifier.rb +0 -3
  168. data/lib/pubid/csa/identifiers/base.rb +2 -122
  169. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  170. data/lib/pubid/csa/identifiers/series.rb +2 -102
  171. data/lib/pubid/csa/renderer.rb +292 -0
  172. data/lib/pubid/csa/urn_generator.rb +1 -1
  173. data/lib/pubid/csa/urn_parser.rb +33 -0
  174. data/lib/pubid/csa.rb +42 -1
  175. data/lib/pubid/etsi/components/code.rb +9 -2
  176. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  177. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  178. data/lib/pubid/etsi/renderer.rb +42 -0
  179. data/lib/pubid/etsi/urn_parser.rb +34 -0
  180. data/lib/pubid/etsi.rb +42 -1
  181. data/lib/pubid/export/exporter.rb +4 -46
  182. data/lib/pubid/export/flavor_exporter.rb +111 -278
  183. data/lib/pubid/export.rb +0 -6
  184. data/lib/pubid/identifier.rb +10 -18
  185. data/lib/pubid/identifier_facade.rb +114 -0
  186. data/lib/pubid/identifier_metadata.rb +1 -1
  187. data/lib/pubid/idf/builder.rb +3 -3
  188. data/lib/pubid/idf/identifier.rb +3 -6
  189. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  190. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  191. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  192. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  193. data/lib/pubid/idf/parser.rb +3 -2
  194. data/lib/pubid/idf/renderer.rb +84 -0
  195. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  196. data/lib/pubid/idf/urn_generator.rb +4 -39
  197. data/lib/pubid/idf/urn_parser.rb +25 -0
  198. data/lib/pubid/idf.rb +51 -1
  199. data/lib/pubid/iec/builder.rb +48 -65
  200. data/lib/pubid/iec/components/code.rb +9 -32
  201. data/lib/pubid/iec/components/publisher.rb +1 -1
  202. data/lib/pubid/iec/components.rb +14 -0
  203. data/lib/pubid/iec/identifier.rb +276 -3
  204. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  205. data/lib/pubid/iec/identifiers/base.rb +8 -28
  206. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  207. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  208. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -30
  209. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  210. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -26
  211. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  212. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  213. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  214. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  215. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  216. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -15
  217. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  218. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  219. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  220. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  222. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  223. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -23
  224. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  225. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  226. data/lib/pubid/iec/identifiers.rb +30 -0
  227. data/lib/pubid/iec/parser.rb +20 -14
  228. data/lib/pubid/iec/renderer.rb +254 -0
  229. data/lib/pubid/iec/single_identifier.rb +6 -12
  230. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  231. data/lib/pubid/iec/urn_generator.rb +57 -171
  232. data/lib/pubid/iec/urn_parser.rb +53 -252
  233. data/lib/pubid/iec.rb +40 -68
  234. data/lib/pubid/ieee/builder.rb +12 -12
  235. data/lib/pubid/ieee/components/code.rb +8 -0
  236. data/lib/pubid/ieee/components/draft.rb +14 -0
  237. data/lib/pubid/ieee/components/relationship.rb +5 -149
  238. data/lib/pubid/ieee/identifier.rb +6 -0
  239. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  240. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  241. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  242. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  243. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  245. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  246. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  247. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  248. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  249. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  250. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  251. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  252. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  253. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  254. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  255. data/lib/pubid/ieee/pre_parser.rb +301 -0
  256. data/lib/pubid/ieee/renderer.rb +307 -0
  257. data/lib/pubid/ieee/urn_parser.rb +34 -0
  258. data/lib/pubid/ieee.rb +62 -1
  259. data/lib/pubid/ieee_debug.rb +0 -1
  260. data/lib/pubid/iho/builder.rb +2 -2
  261. data/lib/pubid/iho/identifier.rb +8 -0
  262. data/lib/pubid/iho/identifiers/base.rb +49 -10
  263. data/lib/pubid/iho/identifiers/bibliographic.rb +0 -4
  264. data/lib/pubid/iho/identifiers/circular_letter.rb +0 -4
  265. data/lib/pubid/iho/identifiers/miscellaneous.rb +0 -4
  266. data/lib/pubid/iho/identifiers/publication.rb +0 -4
  267. data/lib/pubid/iho/identifiers/standard.rb +0 -4
  268. data/lib/pubid/iho/parser.rb +3 -3
  269. data/lib/pubid/iho/renderer.rb +30 -0
  270. data/lib/pubid/iho/urn_generator.rb +3 -3
  271. data/lib/pubid/iho/urn_parser.rb +58 -0
  272. data/lib/pubid/iho.rb +50 -1
  273. data/lib/pubid/iso/builder.rb +59 -53
  274. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  275. data/lib/pubid/iso/components/code.rb +7 -19
  276. data/lib/pubid/iso/components/publisher.rb +10 -8
  277. data/lib/pubid/iso/components.rb +2 -4
  278. data/lib/pubid/iso/identifier.rb +233 -6
  279. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  280. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  281. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  282. data/lib/pubid/iso/identifiers/data.rb +0 -1
  283. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  284. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  285. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  286. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  287. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  288. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  289. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  290. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  291. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  292. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  293. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  294. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  295. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  296. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  297. data/lib/pubid/iso/identifiers.rb +0 -1
  298. data/lib/pubid/iso/normalizer.rb +89 -0
  299. data/lib/pubid/iso/parser.rb +26 -6
  300. data/lib/pubid/iso/single_identifier.rb +6 -3
  301. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  302. data/lib/pubid/iso/urn_generator.rb +74 -176
  303. data/lib/pubid/iso/urn_parser.rb +28 -9
  304. data/lib/pubid/iso.rb +173 -2
  305. data/lib/pubid/itu/builder.rb +0 -12
  306. data/lib/pubid/itu/components/code.rb +8 -0
  307. data/lib/pubid/itu/components.rb +11 -0
  308. data/lib/pubid/itu/identifier.rb +6 -39
  309. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  310. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  311. data/lib/pubid/itu/identifiers/base.rb +0 -6
  312. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  313. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  314. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  315. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  316. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  317. data/lib/pubid/itu/urn_parser.rb +23 -0
  318. data/lib/pubid/itu.rb +42 -1
  319. data/lib/pubid/jcgm/builder.rb +16 -8
  320. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  321. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  322. data/lib/pubid/jcgm/renderer.rb +68 -0
  323. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  324. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  325. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  326. data/lib/pubid/jcgm.rb +43 -2
  327. data/lib/pubid/jis/builder.rb +44 -52
  328. data/lib/pubid/jis/identifier.rb +132 -3
  329. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  330. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  331. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  332. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  333. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  334. data/lib/pubid/jis/identifiers.rb +1 -1
  335. data/lib/pubid/jis/parser.rb +31 -5
  336. data/lib/pubid/jis/renderer.rb +69 -0
  337. data/lib/pubid/jis/single_identifier.rb +6 -12
  338. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  339. data/lib/pubid/jis/urn_parser.rb +23 -0
  340. data/lib/pubid/jis.rb +42 -2
  341. data/lib/pubid/nist/builder.rb +122 -1761
  342. data/lib/pubid/nist/caster.rb +1272 -0
  343. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  344. data/lib/pubid/nist/components/code.rb +9 -20
  345. data/lib/pubid/nist/components/edition.rb +16 -0
  346. data/lib/pubid/nist/components/supplement.rb +88 -21
  347. data/lib/pubid/nist/components.rb +0 -1
  348. data/lib/pubid/nist/identifier.rb +25 -0
  349. data/lib/pubid/nist/identifiers/base.rb +206 -64
  350. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  351. data/lib/pubid/nist/identifiers/circular_supplement.rb +3 -2
  352. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  353. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  354. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  355. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -11
  356. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  357. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +17 -16
  358. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  359. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  360. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  361. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  362. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  363. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  364. data/lib/pubid/nist/identifiers/report.rb +4 -3
  365. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  366. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  367. data/lib/pubid/nist/identifiers.rb +1 -0
  368. data/lib/pubid/nist/parser.rb +67 -424
  369. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  370. data/lib/pubid/nist/preprocessor.rb +416 -0
  371. data/lib/pubid/nist/renderer.rb +43 -0
  372. data/lib/pubid/nist/router.rb +148 -0
  373. data/lib/pubid/nist/series/base.rb +58 -0
  374. data/lib/pubid/nist/series/crpl.rb +13 -0
  375. data/lib/pubid/nist/series/fips.rb +14 -0
  376. data/lib/pubid/nist/series/ir.rb +60 -0
  377. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  378. data/lib/pubid/nist/series/mono.rb +19 -0
  379. data/lib/pubid/nist/series/ncstar.rb +20 -0
  380. data/lib/pubid/nist/series.rb +49 -0
  381. data/lib/pubid/nist/supplement_identifier.rb +11 -25
  382. data/lib/pubid/nist/urn_generator.rb +14 -8
  383. data/lib/pubid/nist/urn_parser.rb +67 -0
  384. data/lib/pubid/nist.rb +83 -4
  385. data/lib/pubid/oiml/components/code.rb +10 -0
  386. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  387. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  388. data/lib/pubid/oiml/renderer.rb +161 -0
  389. data/lib/pubid/oiml/single_identifier.rb +6 -45
  390. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  391. data/lib/pubid/oiml/urn_generator.rb +0 -8
  392. data/lib/pubid/oiml/urn_parser.rb +22 -0
  393. data/lib/pubid/oiml.rb +42 -1
  394. data/lib/pubid/plateau/identifier.rb +23 -0
  395. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  396. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  397. data/lib/pubid/plateau/renderer.rb +51 -0
  398. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  399. data/lib/pubid/plateau/urn_parser.rb +43 -0
  400. data/lib/pubid/plateau.rb +44 -1
  401. data/lib/pubid/renderers/base.rb +34 -0
  402. data/lib/pubid/renderers/directives_renderer.rb +27 -14
  403. data/lib/pubid/renderers/guide_renderer.rb +7 -1
  404. data/lib/pubid/renderers/human_readable.rb +31 -8
  405. data/lib/pubid/renderers/iwa_renderer.rb +5 -1
  406. data/lib/pubid/renderers/supplement_renderer.rb +4 -1
  407. data/lib/pubid/rendering/context.rb +33 -21
  408. data/lib/pubid/rendering.rb +0 -3
  409. data/lib/pubid/sae/components/date.rb +8 -0
  410. data/lib/pubid/sae/components/type.rb +5 -1
  411. data/lib/pubid/sae/identifiers/base.rb +2 -16
  412. data/lib/pubid/sae/renderer.rb +36 -0
  413. data/lib/pubid/sae/urn_generator.rb +2 -10
  414. data/lib/pubid/sae/urn_parser.rb +36 -0
  415. data/lib/pubid/sae.rb +42 -1
  416. data/lib/pubid/urn_generator/base.rb +12 -12
  417. data/lib/pubid/urn_parser/base.rb +81 -0
  418. data/lib/pubid/urn_parser/errors.rb +9 -0
  419. data/lib/pubid/urn_parser.rb +14 -0
  420. data/lib/pubid/version.rb +1 -1
  421. data/lib/pubid.rb +29 -7
  422. data/lib/tasks/website-data.json +1940 -1882
  423. metadata +77 -43
  424. data/lib/pubid/amca/scheme.rb +0 -16
  425. data/lib/pubid/ansi/scheme.rb +0 -15
  426. data/lib/pubid/api/scheme.rb +0 -66
  427. data/lib/pubid/ashrae/scheme.rb +0 -53
  428. data/lib/pubid/asme/scheme.rb +0 -37
  429. data/lib/pubid/astm/scheme.rb +0 -55
  430. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  431. data/lib/pubid/bsi/scheme.rb +0 -243
  432. data/lib/pubid/ccsds/scheme.rb +0 -57
  433. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  434. data/lib/pubid/cie/scheme.rb +0 -64
  435. data/lib/pubid/csa/scheme.rb +0 -44
  436. data/lib/pubid/etsi/scheme.rb +0 -42
  437. data/lib/pubid/export/data_class_exporter.rb +0 -59
  438. data/lib/pubid/export/ieee_exporter.rb +0 -78
  439. data/lib/pubid/export/itu_exporter.rb +0 -66
  440. data/lib/pubid/export/nist_exporter.rb +0 -64
  441. data/lib/pubid/export/registry_exporter.rb +0 -90
  442. data/lib/pubid/export/scheme_exporter.rb +0 -70
  443. data/lib/pubid/identifier_registry.rb +0 -198
  444. data/lib/pubid/idf/scheme.rb +0 -61
  445. data/lib/pubid/iec/scheme.rb +0 -71
  446. data/lib/pubid/ieee/scheme.rb +0 -90
  447. data/lib/pubid/iho/scheme.rb +0 -29
  448. data/lib/pubid/iso/identifiers/base.rb +0 -115
  449. data/lib/pubid/iso/scheme.rb +0 -187
  450. data/lib/pubid/itu/scheme.rb +0 -174
  451. data/lib/pubid/jcgm/scheme.rb +0 -60
  452. data/lib/pubid/jis/components/code.rb +0 -59
  453. data/lib/pubid/jis/identifiers/base.rb +0 -72
  454. data/lib/pubid/jis/scheme.rb +0 -49
  455. data/lib/pubid/nist/components/publisher.rb +0 -24
  456. data/lib/pubid/nist/scheme.rb +0 -199
  457. data/lib/pubid/oiml/scheme.rb +0 -46
  458. data/lib/pubid/plateau/scheme.rb +0 -45
  459. data/lib/pubid/rendering/base.rb +0 -73
  460. data/lib/pubid/rendering/common.rb +0 -211
  461. data/lib/pubid/rendering/format.rb +0 -25
  462. data/lib/pubid/sae/scheme.rb +0 -47
  463. data/lib/pubid/scheme.rb +0 -207
@@ -4,6 +4,9 @@ module Pubid
4
4
  module Iso
5
5
  # Generates RFC 5141-bis compliant URNs from ISO identifiers
6
6
  #
7
+ # Components render themselves via `component.render(context: URN_CONTEXT)`;
8
+ # this class orchestrates them into the URN string structure.
9
+ #
7
10
  # RFC 5141-bis extensions implemented:
8
11
  # - Explicit language specification (explicit > implicit)
9
12
  # - Extended copublisher syntax (dynamic combinations)
@@ -12,44 +15,39 @@ module Pubid
12
15
  # - Supplement chain ordering semantics
13
16
  # - Bundled identifier syntax
14
17
  class UrnGenerator
18
+ URN_CONTEXT = Rendering::RenderingContext.urn.freeze
19
+ private_constant :URN_CONTEXT
20
+
15
21
  # Stage code mapping for RFC 5141-bis typed stages
16
- # Maps TypedStage stage_code to URN stage abbreviation
17
22
  TYPED_STAGE_MAP = {
18
- wd: "WD", # Working Draft
19
- wds: "WDS", # Working Draft Study
20
- cd: "CD", # Committee Draft
21
- cdv: "CDV", # Committee Draft for Vote
22
- dis: "DIS", # Draft International Standard
23
- fdis: "FDIS", # Final Draft International Standard
24
- pdam: "PDAM", # Proposed Draft Amendment
25
- dam: "DAM", # Draft Amendment
26
- fdamd: "FDAM", # Final Draft Amendment (note: stage_code is fdamd)
27
- dcor: "DCOR", # Draft Corrigendum
28
- fdcor: "FDCOR", # Final Draft Corrigendum
29
- cdts: "CDTS", # Committee Draft Technical Specification
30
- dts: "DTS", # Draft Technical Specification
31
- fdts: "FDTS", # Final Draft Technical Specification
23
+ wd: "WD",
24
+ wds: "WDS",
25
+ cd: "CD",
26
+ cdv: "CDV",
27
+ dis: "DIS",
28
+ fdis: "FDIS",
29
+ pdam: "PDAM",
30
+ dam: "DAM",
31
+ fdamd: "FDAM",
32
+ dcor: "DCOR",
33
+ fdcor: "FDCOR",
34
+ cdts: "CDTS",
35
+ dts: "DTS",
36
+ fdts: "FDTS",
32
37
  }.freeze
33
38
 
34
- # Document type mapping for RFC 5141-bis extended types
35
39
  TYPE_CODE_MAP = {
36
- dir: "dir", # Directive
37
- dir_sup: "dir-sup", # Directive Supplement
38
- iwa_sup: "iwa-sup", # IWA Supplement
40
+ dir: "dir",
41
+ dir_sup: "dir-sup",
42
+ iwa_sup: "iwa-sup",
39
43
  }.freeze
40
44
 
41
45
  attr_reader :identifier
42
46
 
43
- # Initialize URN generator
44
- #
45
- # @param identifier [Identifier] The ISO identifier to generate URN for
46
47
  def initialize(identifier)
47
48
  @identifier = identifier
48
49
  end
49
50
 
50
- # Generate complete URN string
51
- #
52
- # @return [String] The URN in format urn:iso:std:...
53
51
  def generate
54
52
  if identifier.is_a?(SupplementIdentifier)
55
53
  generate_supplement_urn
@@ -60,111 +58,63 @@ module Pubid
60
58
 
61
59
  protected
62
60
 
63
- # Generate URN for base identifier (SingleIdentifier)
64
61
  def generate_base_urn
65
62
  parts = ["urn", "iso", "std"]
66
-
67
- # Publisher (lowercase, hyphen-separated)
68
63
  parts << originator_component
69
-
70
- # Type (for non-IS types like TR, TS, Guide)
71
64
  type_comp = type_component
72
65
  parts << type_comp if type_comp
73
-
74
- # Number
75
- parts << identifier.number.value if identifier.number
76
-
77
- # Part (with colon-dash prefix)
66
+ parts << identifier.number.render(context: URN_CONTEXT) if identifier.number
78
67
  part_comp = part_component
79
68
  parts << part_comp if part_comp
80
-
81
- # Stage (only for non-published documents)
82
69
  stage_comp = stage_component
83
- parts << stage_comp if stage_comp
84
-
85
- # Year (for published documents and when edition is present)
70
+ parts << stage_comp if stage_comp && !identifier.all_parts
86
71
  year_comp = year_component
87
72
  parts << year_comp if year_comp
88
-
89
- # Edition
90
73
  edition_comp = edition_component
91
74
  parts << edition_comp if edition_comp
92
-
93
- # Language (RFC 5141-bis: explicit specification)
94
75
  lang_comp = language_component
95
76
  parts << lang_comp if lang_comp
96
-
77
+ parts << "ser" if identifier.all_parts
97
78
  parts.join(":")
98
79
  end
99
80
 
100
- # Generate URN for supplement identifier
101
- # Handles multi-level supplements by walking up the chain
102
81
  def generate_supplement_urn
103
- # Walk up supplement chain to collect all supplements
104
82
  current = identifier
105
83
  supplement_chain = []
106
84
 
107
85
  while current.is_a?(SupplementIdentifier)
108
- supplement_chain.unshift(current) # Add to front (reverse order)
86
+ supplement_chain.unshift(current)
109
87
  current = current.base_identifier
110
88
  end
111
89
 
112
- # Now 'current' is the base document (not a supplement)
113
90
  base_id = current
114
-
115
- # Build URN from base identifier
116
91
  parts = ["urn", "iso", "std"]
117
92
 
118
93
  if base_id
119
94
  base_gen = self.class.new(base_id)
120
-
121
- # Publisher
122
95
  parts << base_gen.originator_component
123
-
124
- # Type (for non-IS types like TR, TS, Guide)
125
96
  type_comp = base_gen.type_component
126
97
  parts << type_comp if type_comp
127
-
128
- # Number
129
- parts << base_id.number.value if base_id.number
130
-
131
- # Part
98
+ parts << base_id.number.render(context: URN_CONTEXT) if base_id.number
132
99
  part_comp = base_gen.part_component
133
100
  parts << part_comp if part_comp
134
101
 
135
- # Collect ALL editions (base + supplements) and add them here
136
- # This ensures editions come before all supplement chains
137
102
  all_editions = []
138
-
139
- # Base edition first
140
103
  edition_comp = base_gen.edition_component
141
104
  all_editions << edition_comp if edition_comp
142
-
143
- # Then supplement editions
144
105
  supplement_chain.each do |supp|
145
106
  if supp.edition&.number
146
- all_editions << "ed-#{supp.edition.number}"
107
+ all_editions << supp.edition.render(context: URN_CONTEXT)
147
108
  end
148
109
  end
149
-
150
- # Add all editions to parts
151
110
  parts.concat(all_editions)
152
111
 
153
- # Base stage logic:
154
- # - Include if base is proposal stage (10.xx) and supplement has different stage
155
- # - Don't include if base is approval/publication stage (50.xx, 60.xx)
156
- # - Don't include if supplement has same stage as base
157
112
  base_stage_comp = base_gen.stage_component
158
113
  if base_stage_comp
159
- # Check if any supplement has a stage
160
114
  supplement_stages = supplement_chain.filter_map do |supp|
161
- supp_gen = self.class.new(supp)
162
- supp_gen.stage_component
115
+ self.class.new(supp).stage_component
163
116
  end
164
117
 
165
- # Only include base stage if:
166
- # 1. No supplements have a stage, OR
167
- # 2. Base is proposal stage (starts with "stage-10.") AND supplements don't duplicate it
168
118
  if supplement_stages.empty?
169
119
  parts << base_stage_comp
170
120
  elsif base_stage_comp.start_with?("stage-10.") && !supplement_stages.include?(base_stage_comp)
@@ -172,127 +122,96 @@ module Pubid
172
122
  end
173
123
  end
174
124
 
175
- # Base language (if present)
176
125
  if base_id.languages&.any?
177
- lang_comp = base_id.languages.map(&:code).join(",")
178
- parts << lang_comp
126
+ parts << language_segment(base_id.languages)
179
127
  end
180
128
  end
181
129
 
182
- # Now flatten all supplements in order
183
130
  supplement_chain.each do |supp|
184
131
  supp_gen = self.class.new(supp)
185
-
186
- # Supplement stage (for draft supplements)
187
- # Note: editions are added at base level, not here
188
132
  stage_comp = supp_gen.stage_component
189
133
  parts << stage_comp if stage_comp
190
-
191
- # Supplement type code (amd, cor, sup)
192
134
  suppl_type = supp_gen.supplement_type_component
193
135
  parts << suppl_type if suppl_type
194
136
 
195
- # Year and version (following RFC 5141-bis supplement semantics)
196
137
  if supp.date
197
- # With date: year:vN
198
- parts << supp.date.year.to_s
199
-
200
- # Version with "v" prefix
201
- # Amendments/Corrigenda keep iteration, generic Supplements don't
138
+ parts << supp.date.render(context: URN_CONTEXT)
202
139
  if supp.number
203
140
  if supp.stage_iteration && !supp.is_a?(Pubid::Iso::Identifiers::Supplement)
204
- parts << "v#{supp.number.value}.#{supp.stage_iteration.value}"
141
+ parts << "v#{supp.number.render(context: URN_CONTEXT)}.#{supp.stage_iteration.render(context: URN_CONTEXT)}"
205
142
  else
206
- parts << "v#{supp.number.value}"
143
+ parts << "v#{supp.number.render(context: URN_CONTEXT)}"
207
144
  end
208
145
  end
209
146
  else
210
- # Without date: N:v1 (number directly, then "v1")
211
- if supp.number
212
- parts << supp.number.value
213
- end
214
-
215
- # Always add "v1" when no date
216
- # Amendments/Corrigenda keep iteration, generic Supplements don't
147
+ parts << supp.number.render(context: URN_CONTEXT) if supp.number
217
148
  if supp.stage_iteration && !supp.is_a?(Pubid::Iso::Identifiers::Supplement)
218
- parts << "v1.#{supp.stage_iteration.value}"
149
+ parts << "v1.#{supp.stage_iteration.render(context: URN_CONTEXT)}"
219
150
  else
220
151
  parts << "v1"
221
152
  end
222
153
  end
223
154
 
224
- # Supplement language (RFC 5141-bis: explicit specification)
225
155
  if supp.languages&.any?
226
- lang_comp = supp.languages.map(&:code).join(",")
227
- parts << lang_comp
156
+ parts << language_segment(supp.languages)
228
157
  end
229
158
  end
230
159
 
160
+ parts << "ser" if identifier.all_parts
231
161
  parts.join(":")
232
162
  end
233
163
 
234
- # Generate originator component (publisher with copublishers)
235
- # RFC 5141-bis: supports dynamic copublisher combinations
236
164
  def originator_component
237
- # For identifiers like IWA that don't render publisher, default to "iso"
238
165
  return "iso" unless identifier.publisher
239
166
 
240
167
  copubs = identifier.copublishers || []
241
-
242
- # Collect all publishers in order
243
168
  publishers = [identifier.publisher] + copubs
169
+ publishers.map { |p| p.render(context: URN_CONTEXT) }.join("-")
170
+ end
244
171
 
245
- # Convert to lowercase and join with hyphen
246
- # Keep original order (not alphabetical) for backward compatibility
247
- publishers.map(&:body).map(&:downcase).join("-")
172
+ def document_type_code
173
+ klass = identifier.class
174
+ if klass.respond_to?(:type) && klass.type.is_a?(Hash) && klass.type[:key]
175
+ klass.type[:key]
176
+ else
177
+ identifier.typed_stage&.type_code
178
+ end
248
179
  end
249
180
 
250
- # Generate type component
251
- # RFC 5141-bis: supports extended document types (dir, dir-sup, iwa-sup)
252
181
  def type_component
253
182
  return nil unless identifier.typed_stage
254
183
 
255
- type_code = identifier.typed_stage.type_code
256
- # International Standard is default (skip it)
184
+ type_code = document_type_code
257
185
  return nil if !type_code || type_code.to_s == "is"
258
186
 
259
- # Check for extended type codes first (RFC 5141-bis)
260
187
  type_code_sym = type_code.to_sym
261
188
  extended_type = TYPE_CODE_MAP[type_code_sym]
262
189
  return extended_type if extended_type
263
190
 
264
- # Use urn_type_code override if available (e.g., Recommendation uses 'r')
265
191
  urn_override = identifier.urn_type_code
266
192
  return urn_override if urn_override
267
193
 
268
- # Default: use type_code as-is (already a string)
269
194
  type_code.to_s
270
195
  end
271
196
 
272
- # Generate part component
273
197
  def part_component
274
198
  return nil unless identifier.part
275
199
 
276
- result = "-#{identifier.part.value}"
277
- result += "-#{identifier.subpart.value}" if identifier.subpart
200
+ result = "-#{identifier.part.render(context: URN_CONTEXT)}"
201
+ result += "-#{identifier.subpart.render(context: URN_CONTEXT)}" if identifier.subpart
278
202
  result
279
203
  end
280
204
 
281
- # Generate stage component
282
- # RFC 5141-bis: supports typed stage codes (WD, CD, DIS, FDIS, etc.)
283
205
  def stage_component
284
206
  return nil unless identifier.typed_stage
285
207
 
286
208
  stage_code = identifier.typed_stage.stage_code
287
209
  return nil if !stage_code || stage_code == :published
288
210
 
289
- # Try combined stage+type code first (e.g., "cdts" for CD+TS)
290
- # This handles typed stages where stage_code differs from the full typed stage code
291
211
  combined_key = nil
292
- if identifier.typed_stage.type_code &&
293
- identifier.typed_stage.type_code != "is" &&
294
- identifier.typed_stage.type_code.to_s != ""
295
- combined_key = :"#{stage_code}#{identifier.typed_stage.type_code}"
212
+ dtc = document_type_code&.to_s
213
+ if dtc && dtc != "is" && dtc != ""
214
+ combined_key = :"#{stage_code}#{dtc}"
296
215
  end
297
216
 
298
217
  stage_abbr = if combined_key && TYPED_STAGE_MAP.key?(combined_key)
@@ -302,104 +221,83 @@ module Pubid
302
221
  end
303
222
 
304
223
  if stage_abbr
305
-
306
- # Add iteration if present (no 'v' prefix for iterations)
307
224
  if identifier.stage_iteration
308
- return "#{stage_abbr}.#{identifier.stage_iteration.value}"
225
+ return "#{stage_abbr}.#{identifier.stage_iteration.render(context: URN_CONTEXT)}"
309
226
  end
310
227
 
311
228
  return stage_abbr
312
229
  end
313
230
 
314
- # Fallback: use harmonized stage codes for unmapped stages
315
- # This handles stages like PWI, NP, AWI, PRF that don't have typed abbreviations
316
231
  harmonized_codes = identifier.typed_stage.harmonized_stages
317
232
  return nil unless harmonized_codes&.any?
318
233
 
319
- # Use first harmonized code from the array
320
234
  harmonized_code = harmonized_codes.first
321
235
 
322
- # Skip published documents (60.00, 60.60) EXCEPT for PRF (Proof) stage
323
- # PRF is at 60.00 but should still be included in URNs
324
236
  if harmonized_code.start_with?("60.") && stage_code.to_s != "prf"
325
237
  return nil
326
238
  end
327
239
 
328
- # Format as stage-XX.XX
329
- stage_part = "stage-#{harmonized_code}"
240
+ stage_part = if stage_code.to_s == "prf" && identifier.stage_iteration
241
+ "stage-draft"
242
+ else
243
+ "stage-#{harmonized_code}"
244
+ end
330
245
 
331
- # For base identifiers (not supplements), include iteration in stage code
332
- # For supplements, iteration goes in the version part (v1.2)
333
246
  if identifier.stage_iteration && !identifier.is_a?(SupplementIdentifier)
334
- stage_part += ".v#{identifier.stage_iteration.value}"
247
+ stage_part += ".v#{identifier.stage_iteration.render(context: URN_CONTEXT)}"
335
248
  end
336
249
 
337
250
  stage_part
338
251
  end
339
252
 
340
- # Generate edition component
341
253
  def edition_component
342
254
  return nil unless identifier.edition&.number
343
255
 
344
- "ed-#{identifier.edition.number}"
256
+ identifier.edition.render(context: URN_CONTEXT)
345
257
  end
346
258
 
347
- # Generate year component
348
259
  def year_component
349
- return nil unless identifier.date&.year
350
-
351
- # ISO base identifiers (SingleIdentifier) use undated URN format (no year)
352
- # Supplements include their own year in the supplement section
260
+ return nil unless identifier.date&.present?
353
261
  return nil if identifier.is_a?(Pubid::Iso::SingleIdentifier)
354
262
 
355
- identifier.date.year.to_s
263
+ identifier.date.render(context: URN_CONTEXT)
356
264
  end
357
265
 
358
- # Generate language component
359
- # RFC 5141-bis: explicit specification guidance (explicit > implicit)
360
- # URN spec: all values in lowercase
361
266
  def language_component
362
267
  return nil unless identifier.languages&.any?
363
268
 
364
- identifier.languages.map(&:code).map(&:downcase).join(",")
269
+ language_segment(identifier.languages)
270
+ end
271
+
272
+ def language_segment(languages)
273
+ languages.map { |l| l.render(context: URN_CONTEXT) }.join(",")
365
274
  end
366
275
 
367
- # Generate supplement type component
368
276
  def supplement_type_component
369
277
  return nil unless identifier.typed_stage
370
278
 
371
279
  urn_override = identifier.urn_supplement_type
372
280
  return urn_override if urn_override
373
281
 
374
- identifier.typed_stage.type_code.to_s
282
+ document_type_code.to_s
375
283
  end
376
284
 
377
- # Generate supplement year/version components
378
- # Returns array of parts to be joined with ":"
379
285
  def supplement_year_version_components
380
286
  parts = []
381
287
 
382
288
  if identifier.date
383
- # With year: year:version
384
- parts << identifier.date.year.to_s
385
-
386
- # Version number with "v" prefix
289
+ parts << identifier.date.render(context: URN_CONTEXT)
387
290
  if identifier.number
388
291
  parts << if identifier.stage_iteration
389
- "v#{identifier.number.value}.#{identifier.stage_iteration.value}"
292
+ "v#{identifier.number.render(context: URN_CONTEXT)}.#{identifier.stage_iteration.render(context: URN_CONTEXT)}"
390
293
  else
391
- "v#{identifier.number.value}"
294
+ "v#{identifier.number.render(context: URN_CONTEXT)}"
392
295
  end
393
296
  end
394
297
  else
395
- # Without year: number directly or "v1"
396
- if identifier.number
397
- parts << identifier.number.value
398
- end
399
-
400
- # Version with iteration if present
298
+ parts << identifier.number.render(context: URN_CONTEXT) if identifier.number
401
299
  parts << if identifier.stage_iteration
402
- "v1.#{identifier.stage_iteration.value}"
300
+ "v1.#{identifier.stage_iteration.render(context: URN_CONTEXT)}"
403
301
  else
404
302
  "v1"
405
303
  end
@@ -71,6 +71,15 @@ module Pubid
71
71
 
72
72
  parts = urn.sub("urn:iso:std:", "").split(":")
73
73
 
74
+ # Series suffix: a trailing "ser" marks an all-parts identifier. Strip
75
+ # it before component parsing so it is not misread as a language or
76
+ # supplement token (which previously rendered as "(SER)").
77
+ all_parts = false
78
+ if parts.last == "ser"
79
+ parts.pop
80
+ all_parts = true
81
+ end
82
+
74
83
  # Parse publisher(s) - first part
75
84
  publishers = parse_publisher(parts.shift)
76
85
 
@@ -212,7 +221,8 @@ module Pubid
212
221
 
213
222
  # Build the identifier hash
214
223
  build_identifier(publishers, number, part, subpart, type_code, stage_code, stage_iteration,
215
- harmonized_stage_code, stage_from_abbr, year, edition, languages, supplements)
224
+ harmonized_stage_code, stage_from_abbr, year, edition, languages, supplements,
225
+ all_parts)
216
226
  end
217
227
 
218
228
  private
@@ -221,7 +231,7 @@ module Pubid
221
231
  # Used when URN doesn't specify a type code (defaults to IS)
222
232
  # Prefers the most specific (non-published) stage
223
233
  def scheme_is_typed_stage_by_harmonized(harmonized_code)
224
- candidates = Pubid::Iso::Scheme.instance.all_typed_stages.select do |ts|
234
+ candidates = Pubid::Iso.all_typed_stages.select do |ts|
225
235
  ts.type_code.to_s == "is" && ts.harmonized_stages&.include?(harmonized_code)
226
236
  end
227
237
 
@@ -302,7 +312,8 @@ module Pubid
302
312
 
303
313
  # Build identifier from parsed components
304
314
  def build_identifier(publishers, number, part, subpart, type_code, stage_code, stage_iteration,
305
- harmonized_stage_code, stage_from_abbr, year, edition, languages, supplements)
315
+ harmonized_stage_code, stage_from_abbr, year, edition, languages, supplements,
316
+ all_parts = false)
306
317
  # Start with base document hash
307
318
  base_hash = {
308
319
  publisher: publishers.first,
@@ -325,6 +336,11 @@ module Pubid
325
336
  # Add type_with_stage if type_code is present
326
337
  if type_code && type_code != :is
327
338
  base_hash[:type_with_stage] = type_code.to_s.upcase
339
+ # Pin the document class to the explicit URN type token. The stage
340
+ # block below may overwrite :type_with_stage with the stage's abbr
341
+ # (e.g. "WDA" for 90.93, which only exists as an IS-typed stage), so
342
+ # the builder needs this hint to keep e.g. TR a TechnicalReport.
343
+ base_hash[:document_type] = type_code.to_s.upcase
328
344
  end
329
345
 
330
346
  # Add stage if present
@@ -337,9 +353,9 @@ module Pubid
337
353
  # The stage_from_abbr is the value from TYPED_STAGE_REVERSE_MAP
338
354
  # We need to find the reverse to get the original abbreviation
339
355
  abbr_str = TYPED_STAGE_REVERSE_MAP.key(stage_from_abbr)
340
- typed_stage = Scheme.locate_typed_stage_by_abbr(abbr_str) if abbr_str
356
+ typed_stage = Pubid::Iso.locate_stage(abbr_str) if abbr_str
341
357
  # If no exact match, fall back to stage_code lookup
342
- typed_stage ||= Scheme.locate_typed_stage_by_stage_code(stage_from_abbr)
358
+ typed_stage ||= Pubid::Iso.locate_stage_by_stage_code(stage_from_abbr)
343
359
  else
344
360
  # Stage came from a harmonized code (e.g., stage-20.20)
345
361
  # Look up by harmonized stage code
@@ -349,12 +365,12 @@ module Pubid
349
365
  end
350
366
 
351
367
  # Fall back to any typed stage if IS not found or type_code is specified
352
- typed_stage ||= Scheme.locate_typed_stage_by_harmonized_code(stage_code.to_s)
368
+ typed_stage ||= Pubid::Iso.locate_stage_by_harmonized_code(stage_code.to_s)
353
369
 
354
370
  # Special handling for stage "40.00": prefer DIS over FCD when parsing from URN
355
371
  # This is because FCD is a legacy stage that maps to DIS in URN format
356
372
  if stage_code.to_s == "40.00" && typed_stage && typed_stage.stage_code.to_s == "fcd"
357
- dis_stage = Scheme.instance.all_typed_stages.detect do |ts|
373
+ dis_stage = Pubid::Iso.all_typed_stages.detect do |ts|
358
374
  ts.stage_code.to_s == "dis" && ts.harmonized_stages&.include?("40.00")
359
375
  end
360
376
  typed_stage = dis_stage if dis_stage
@@ -384,7 +400,7 @@ module Pubid
384
400
  supp_hash = {}
385
401
 
386
402
  if supp[:stage]
387
- typed_stage = Scheme.locate_typed_stage_by_stage_code(supp[:stage])
403
+ typed_stage = Pubid::Iso.locate_stage_by_stage_code(supp[:stage])
388
404
  supp_hash[:type_with_stage] = if
389
405
  typed_stage
390
406
  typed_stage.abbr.is_a?(Array) ? typed_stage.abbr.first : typed_stage.abbr
@@ -414,8 +430,11 @@ typed_stage
414
430
  }
415
431
  end
416
432
 
433
+ # all_parts belongs on the outermost identifier (after any supplement wrapping)
434
+ base_hash[:all_parts] = true if all_parts
435
+
417
436
  # Build the final identifier
418
- builder = Pubid::Iso::Builder.new(Pubid::Iso::Scheme.new)
437
+ builder = Pubid::Iso::Builder.new
419
438
  builder.build(base_hash)
420
439
  end
421
440
  end