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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +25 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +4 -55
  6. data/lib/pubid/amca/identifiers/base.rb +58 -47
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -21
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -17
  9. data/lib/pubid/amca/identifiers/standard.rb +0 -4
  10. data/lib/pubid/amca/renderer.rb +82 -0
  11. data/lib/pubid/amca/single_identifier.rb +0 -23
  12. data/lib/pubid/amca/urn_generator.rb +2 -1
  13. data/lib/pubid/amca/urn_parser.rb +28 -0
  14. data/lib/pubid/amca.rb +42 -1
  15. data/lib/pubid/ansi/builder.rb +5 -3
  16. data/lib/pubid/ansi/identifier.rb +1 -43
  17. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  18. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  19. data/lib/pubid/ansi/renderer.rb +53 -0
  20. data/lib/pubid/ansi/single_identifier.rb +2 -31
  21. data/lib/pubid/ansi/urn_generator.rb +3 -38
  22. data/lib/pubid/ansi/urn_parser.rb +23 -0
  23. data/lib/pubid/ansi.rb +38 -3
  24. data/lib/pubid/api/builder.rb +33 -74
  25. data/lib/pubid/api/identifier.rb +5 -52
  26. data/lib/pubid/api/identifiers/base.rb +2 -14
  27. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  28. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  29. data/lib/pubid/api/identifiers/mpms.rb +0 -20
  30. data/lib/pubid/api/identifiers/publication.rb +0 -2
  31. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  32. data/lib/pubid/api/identifiers/specification.rb +0 -2
  33. data/lib/pubid/api/identifiers/standard.rb +0 -2
  34. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  35. data/lib/pubid/api/identifiers/typeless_standard.rb +0 -16
  36. data/lib/pubid/api/identifiers.rb +18 -0
  37. data/lib/pubid/api/renderer.rb +89 -0
  38. data/lib/pubid/api/single_identifier.rb +5 -20
  39. data/lib/pubid/api/urn_generator.rb +0 -18
  40. data/lib/pubid/api/urn_parser.rb +35 -0
  41. data/lib/pubid/api.rb +51 -5
  42. data/lib/pubid/ashrae/builder.rb +3 -3
  43. data/lib/pubid/ashrae/identifier.rb +7 -55
  44. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  45. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  46. data/lib/pubid/ashrae/identifiers/base.rb +29 -15
  47. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  48. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  49. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  50. data/lib/pubid/ashrae/parser.rb +4 -0
  51. data/lib/pubid/ashrae/renderer.rb +117 -0
  52. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  53. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  54. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  55. data/lib/pubid/ashrae.rb +46 -1
  56. data/lib/pubid/asme/components/code.rb +10 -2
  57. data/lib/pubid/asme/identifier.rb +0 -46
  58. data/lib/pubid/asme/identifiers/base.rb +0 -60
  59. data/lib/pubid/asme/renderer.rb +66 -0
  60. data/lib/pubid/asme/single_identifier.rb +3 -1
  61. data/lib/pubid/asme/urn_parser.rb +31 -0
  62. data/lib/pubid/asme.rb +42 -1
  63. data/lib/pubid/astm/components/code.rb +9 -0
  64. data/lib/pubid/{jis → astm}/components.rb +1 -1
  65. data/lib/pubid/astm/identifier.rb +0 -77
  66. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  67. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  68. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  69. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  70. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  71. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  72. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  73. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  74. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  75. data/lib/pubid/astm/identifiers.rb +18 -0
  76. data/lib/pubid/astm/renderer.rb +172 -0
  77. data/lib/pubid/astm/single_identifier.rb +3 -11
  78. data/lib/pubid/astm/urn_parser.rb +30 -0
  79. data/lib/pubid/astm.rb +39 -27
  80. data/lib/pubid/bsi/builder.rb +21 -12
  81. data/lib/pubid/bsi/identifier.rb +5 -85
  82. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -36
  83. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +8 -48
  84. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +8 -39
  85. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +2 -55
  86. data/lib/pubid/bsi/identifiers/amendment.rb +2 -22
  87. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -6
  88. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  89. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -87
  90. data/lib/pubid/bsi/identifiers/committee_document.rb +0 -16
  91. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -87
  92. data/lib/pubid/bsi/identifiers/corrigendum.rb +2 -10
  93. data/lib/pubid/bsi/identifiers/detailed_specification.rb +0 -36
  94. data/lib/pubid/bsi/identifiers/disc.rb +0 -29
  95. data/lib/pubid/bsi/identifiers/draft_document.rb +2 -46
  96. data/lib/pubid/bsi/identifiers/electronic_book.rb +2 -38
  97. data/lib/pubid/bsi/identifiers/expert_commentary.rb +2 -18
  98. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +0 -47
  99. data/lib/pubid/bsi/identifiers/flex.rb +0 -35
  100. data/lib/pubid/bsi/identifiers/handbook.rb +1 -15
  101. data/lib/pubid/bsi/identifiers/index.rb +0 -32
  102. data/lib/pubid/bsi/identifiers/method.rb +0 -41
  103. data/lib/pubid/bsi/identifiers/national_annex.rb +4 -29
  104. data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -6
  105. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +2 -54
  106. data/lib/pubid/bsi/identifiers/published_document.rb +2 -54
  107. data/lib/pubid/bsi/identifiers/section.rb +0 -30
  108. data/lib/pubid/bsi/identifiers/set.rb +3 -20
  109. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +0 -9
  110. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -24
  111. data/lib/pubid/bsi/identifiers/supplementary_index.rb +0 -46
  112. data/lib/pubid/bsi/identifiers/technical_specification.rb +2 -47
  113. data/lib/pubid/bsi/identifiers/test_method.rb +0 -32
  114. data/lib/pubid/bsi/identifiers/value_added_publication.rb +2 -17
  115. data/lib/pubid/bsi/identifiers.rb +0 -1
  116. data/lib/pubid/bsi/renderer.rb +1050 -0
  117. data/lib/pubid/bsi/single_identifier.rb +33 -78
  118. data/lib/pubid/bsi/urn_generator.rb +2 -3
  119. data/lib/pubid/bsi/urn_parser.rb +52 -0
  120. data/lib/pubid/bsi.rb +232 -2
  121. data/lib/pubid/builder/base.rb +57 -10
  122. data/lib/pubid/bundled_identifier.rb +0 -1
  123. data/lib/pubid/ccsds/builder.rb +4 -3
  124. data/lib/pubid/ccsds/identifier.rb +53 -68
  125. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  126. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  127. data/lib/pubid/ccsds/parser.rb +4 -2
  128. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  129. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  130. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  131. data/lib/pubid/ccsds.rb +39 -1
  132. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  133. data/lib/pubid/cen_cenelec/identifier.rb +11 -40
  134. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +9 -4
  135. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +0 -10
  136. data/lib/pubid/cen_cenelec/identifiers/base.rb +2 -45
  137. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +0 -27
  140. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +0 -15
  141. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +2 -8
  143. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +0 -4
  145. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  146. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  147. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  148. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  149. data/lib/pubid/cen_cenelec/single_identifier.rb +9 -90
  150. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  151. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  152. data/lib/pubid/cen_cenelec.rb +172 -1
  153. data/lib/pubid/cie/components/code.rb +8 -0
  154. data/lib/pubid/cie/identifier.rb +10 -57
  155. data/lib/pubid/cie/single_identifier.rb +4 -4
  156. data/lib/pubid/cie/urn_parser.rb +28 -0
  157. data/lib/pubid/cie.rb +47 -1
  158. data/lib/pubid/components/adoption.rb +104 -0
  159. data/lib/pubid/components/code.rb +22 -8
  160. data/lib/pubid/components/date.rb +23 -16
  161. data/lib/pubid/components/edition.rb +9 -6
  162. data/lib/pubid/components/iteration.rb +32 -0
  163. data/lib/pubid/components/language.rb +6 -4
  164. data/lib/pubid/components/locality.rb +10 -1
  165. data/lib/pubid/components/publisher.rb +9 -6
  166. data/lib/pubid/components/relationship.rb +151 -0
  167. data/lib/pubid/components/stage.rb +5 -14
  168. data/lib/pubid/components/supplement.rb +184 -0
  169. data/lib/pubid/components/type.rb +5 -15
  170. data/lib/pubid/components/typed_stage.rb +10 -11
  171. data/lib/pubid/components.rb +4 -1
  172. data/lib/pubid/core/update_codes.rb +28 -7
  173. data/lib/pubid/csa/identifier.rb +9 -59
  174. data/lib/pubid/csa/identifiers/base.rb +0 -123
  175. data/lib/pubid/csa/identifiers/cec.rb +0 -103
  176. data/lib/pubid/csa/identifiers/series.rb +0 -104
  177. data/lib/pubid/csa/renderer.rb +292 -0
  178. data/lib/pubid/csa/single_identifier.rb +1 -1
  179. data/lib/pubid/csa/urn_generator.rb +1 -1
  180. data/lib/pubid/csa/urn_parser.rb +33 -0
  181. data/lib/pubid/csa.rb +46 -1
  182. data/lib/pubid/etsi/components/code.rb +10 -9
  183. data/lib/pubid/etsi/components/version.rb +0 -5
  184. data/lib/pubid/etsi/identifier.rb +4 -55
  185. data/lib/pubid/etsi/identifiers/base.rb +31 -27
  186. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +1 -11
  187. data/lib/pubid/etsi/renderer.rb +42 -0
  188. data/lib/pubid/etsi/urn_parser.rb +34 -0
  189. data/lib/pubid/etsi.rb +44 -1
  190. data/lib/pubid/export/exporter.rb +4 -46
  191. data/lib/pubid/export/flavor_exporter.rb +111 -278
  192. data/lib/pubid/export.rb +0 -6
  193. data/lib/pubid/identifier.rb +92 -18
  194. data/lib/pubid/identifier_metadata.rb +1 -1
  195. data/lib/pubid/idf/builder.rb +3 -3
  196. data/lib/pubid/idf/identifier.rb +7 -66
  197. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  198. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  199. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  200. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  201. data/lib/pubid/idf/parser.rb +3 -2
  202. data/lib/pubid/idf/renderer.rb +84 -0
  203. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  204. data/lib/pubid/idf/urn_generator.rb +4 -39
  205. data/lib/pubid/idf/urn_parser.rb +25 -0
  206. data/lib/pubid/idf.rb +55 -1
  207. data/lib/pubid/iec/builder.rb +46 -64
  208. data/lib/pubid/iec/components/code.rb +8 -32
  209. data/lib/pubid/iec/components/publisher.rb +0 -1
  210. data/lib/pubid/iec/components.rb +14 -0
  211. data/lib/pubid/iec/identifier.rb +251 -213
  212. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  213. data/lib/pubid/iec/identifiers/base.rb +5 -33
  214. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  215. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  216. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +23 -26
  217. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  218. data/lib/pubid/iec/identifiers/fragment_identifier.rb +35 -24
  219. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  220. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  221. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  222. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  223. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  224. data/lib/pubid/iec/identifiers/sheet_identifier.rb +17 -11
  225. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  226. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  227. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  228. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  229. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  230. data/lib/pubid/iec/identifiers/test_report_form.rb +3 -35
  231. data/lib/pubid/iec/identifiers/vap_identifier.rb +24 -21
  232. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  233. data/lib/pubid/iec/identifiers/working_document.rb +2 -50
  234. data/lib/pubid/iec/identifiers.rb +30 -0
  235. data/lib/pubid/iec/parser.rb +13 -12
  236. data/lib/pubid/iec/renderer.rb +254 -0
  237. data/lib/pubid/iec/single_identifier.rb +6 -12
  238. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  239. data/lib/pubid/iec/urn_generator.rb +3 -3
  240. data/lib/pubid/iec/urn_parser.rb +3 -3
  241. data/lib/pubid/iec.rb +43 -67
  242. data/lib/pubid/ieee/builder.rb +12 -12
  243. data/lib/pubid/ieee/components/code.rb +8 -0
  244. data/lib/pubid/ieee/components/draft.rb +14 -0
  245. data/lib/pubid/ieee/components/relationship.rb +5 -149
  246. data/lib/pubid/ieee/identifier.rb +5 -52
  247. data/lib/pubid/ieee/identifiers/adopted_standard.rb +0 -9
  248. data/lib/pubid/ieee/identifiers/base.rb +221 -556
  249. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +0 -10
  250. data/lib/pubid/ieee/identifiers/corrigendum.rb +0 -12
  251. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +0 -10
  252. data/lib/pubid/ieee/identifiers/dual_identifier.rb +0 -4
  253. data/lib/pubid/ieee/identifiers/dual_published.rb +0 -4
  254. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +0 -9
  255. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +0 -10
  256. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  257. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +0 -18
  258. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +0 -6
  259. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  260. data/lib/pubid/ieee/identifiers/redlined_standard.rb +0 -7
  261. data/lib/pubid/ieee/identifiers/si_standard.rb +0 -38
  262. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  263. data/lib/pubid/ieee/pre_parser.rb +301 -0
  264. data/lib/pubid/ieee/renderer.rb +307 -0
  265. data/lib/pubid/ieee/urn_parser.rb +34 -0
  266. data/lib/pubid/ieee.rb +66 -1
  267. data/lib/pubid/ieee_debug.rb +0 -1
  268. data/lib/pubid/iho/builder.rb +2 -2
  269. data/lib/pubid/iho/identifier.rb +7 -59
  270. data/lib/pubid/iho/identifiers/base.rb +64 -31
  271. data/lib/pubid/iho/parser.rb +3 -3
  272. data/lib/pubid/iho/renderer.rb +30 -0
  273. data/lib/pubid/iho/urn_generator.rb +2 -2
  274. data/lib/pubid/iho/urn_parser.rb +58 -0
  275. data/lib/pubid/iho.rb +52 -1
  276. data/lib/pubid/iso/builder.rb +55 -53
  277. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  278. data/lib/pubid/iso/components/code.rb +7 -19
  279. data/lib/pubid/iso/components/publisher.rb +10 -8
  280. data/lib/pubid/iso/components.rb +2 -4
  281. data/lib/pubid/iso/identifier.rb +219 -252
  282. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  283. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  284. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  285. data/lib/pubid/iso/identifiers/data.rb +0 -1
  286. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  287. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  288. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  289. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  290. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  291. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  292. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  293. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  294. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  295. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  296. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  297. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  298. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  299. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  300. data/lib/pubid/iso/identifiers.rb +0 -1
  301. data/lib/pubid/iso/normalizer.rb +89 -0
  302. data/lib/pubid/iso/parser.rb +22 -4
  303. data/lib/pubid/iso/single_identifier.rb +0 -4
  304. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  305. data/lib/pubid/iso/urn_generator.rb +66 -182
  306. data/lib/pubid/iso/urn_parser.rb +12 -7
  307. data/lib/pubid/iso.rb +177 -2
  308. data/lib/pubid/itu/builder.rb +0 -12
  309. data/lib/pubid/itu/components/code.rb +9 -7
  310. data/lib/pubid/itu/components/sector.rb +15 -4
  311. data/lib/pubid/itu/components/series.rb +0 -4
  312. data/lib/pubid/itu/components.rb +11 -0
  313. data/lib/pubid/itu/identifier.rb +4 -116
  314. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  315. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  316. data/lib/pubid/itu/identifiers/base.rb +124 -128
  317. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  318. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  319. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  320. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  321. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  322. data/lib/pubid/itu/urn_parser.rb +23 -0
  323. data/lib/pubid/itu.rb +44 -1
  324. data/lib/pubid/jcgm/builder.rb +16 -8
  325. data/lib/pubid/jcgm/identifier.rb +0 -43
  326. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -9
  327. data/lib/pubid/jcgm/identifiers/gum_guide.rb +0 -12
  328. data/lib/pubid/jcgm/renderer.rb +68 -0
  329. data/lib/pubid/jcgm/single_identifier.rb +0 -8
  330. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  331. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  332. data/lib/pubid/jcgm.rb +43 -2
  333. data/lib/pubid/jis/builder.rb +44 -52
  334. data/lib/pubid/jis/identifier.rb +120 -46
  335. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  336. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  337. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  338. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  339. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  340. data/lib/pubid/jis/identifiers.rb +1 -1
  341. data/lib/pubid/jis/parser.rb +31 -5
  342. data/lib/pubid/jis/renderer.rb +69 -0
  343. data/lib/pubid/jis/single_identifier.rb +6 -12
  344. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  345. data/lib/pubid/jis/urn_parser.rb +23 -0
  346. data/lib/pubid/jis.rb +42 -2
  347. data/lib/pubid/nist/builder.rb +63 -1871
  348. data/lib/pubid/nist/caster.rb +1272 -0
  349. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  350. data/lib/pubid/nist/components/code.rb +9 -20
  351. data/lib/pubid/nist/components/supplement.rb +2 -2
  352. data/lib/pubid/nist/components.rb +0 -1
  353. data/lib/pubid/nist/identifier.rb +8 -60
  354. data/lib/pubid/nist/identifiers/base.rb +564 -492
  355. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  356. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  357. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  358. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  359. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  360. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  361. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  362. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  363. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  364. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  365. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  366. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  367. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  368. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  369. data/lib/pubid/nist/identifiers/report.rb +4 -2
  370. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  371. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  372. data/lib/pubid/nist/identifiers.rb +1 -0
  373. data/lib/pubid/nist/parser.rb +62 -452
  374. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  375. data/lib/pubid/nist/preprocessor.rb +428 -0
  376. data/lib/pubid/nist/renderer.rb +43 -0
  377. data/lib/pubid/nist/router.rb +148 -0
  378. data/lib/pubid/nist/series/base.rb +58 -0
  379. data/lib/pubid/nist/series/crpl.rb +13 -0
  380. data/lib/pubid/nist/series/fips.rb +14 -0
  381. data/lib/pubid/nist/series/ir.rb +60 -0
  382. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  383. data/lib/pubid/nist/series/mono.rb +19 -0
  384. data/lib/pubid/nist/series/ncstar.rb +20 -0
  385. data/lib/pubid/nist/series.rb +49 -0
  386. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  387. data/lib/pubid/nist/urn_parser.rb +67 -0
  388. data/lib/pubid/nist.rb +86 -4
  389. data/lib/pubid/oiml/builder.rb +21 -3
  390. data/lib/pubid/oiml/components/code.rb +17 -0
  391. data/lib/pubid/oiml/identifier.rb +40 -46
  392. data/lib/pubid/oiml/identifiers/annex.rb +13 -46
  393. data/lib/pubid/oiml/identifiers/errata.rb +15 -0
  394. data/lib/pubid/oiml/identifiers.rb +1 -1
  395. data/lib/pubid/oiml/parser.rb +59 -12
  396. data/lib/pubid/oiml/renderer.rb +171 -0
  397. data/lib/pubid/oiml/single_identifier.rb +61 -42
  398. data/lib/pubid/oiml/supplement_identifier.rb +31 -17
  399. data/lib/pubid/oiml/urn_generator.rb +0 -8
  400. data/lib/pubid/oiml/urn_parser.rb +22 -0
  401. data/lib/pubid/oiml.rb +42 -1
  402. data/lib/pubid/plateau/identifier.rb +4 -55
  403. data/lib/pubid/plateau/identifiers/base.rb +45 -36
  404. data/lib/pubid/plateau/identifiers/handbook.rb +0 -6
  405. data/lib/pubid/plateau/identifiers/technical_report.rb +0 -4
  406. data/lib/pubid/plateau/renderer.rb +51 -0
  407. data/lib/pubid/plateau/supplement_identifier.rb +0 -4
  408. data/lib/pubid/plateau/urn_parser.rb +43 -0
  409. data/lib/pubid/plateau.rb +43 -1
  410. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  411. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  412. data/lib/pubid/renderers/human_readable.rb +18 -7
  413. data/lib/pubid/rendering/context.rb +28 -19
  414. data/lib/pubid/rendering.rb +0 -3
  415. data/lib/pubid/sae/components/date.rb +8 -0
  416. data/lib/pubid/sae/components/type.rb +5 -1
  417. data/lib/pubid/sae/identifier.rb +4 -35
  418. data/lib/pubid/sae/identifiers/base.rb +26 -31
  419. data/lib/pubid/sae/renderer.rb +36 -0
  420. data/lib/pubid/sae/urn_generator.rb +2 -10
  421. data/lib/pubid/sae/urn_parser.rb +36 -0
  422. data/lib/pubid/sae.rb +42 -1
  423. data/lib/pubid/urn_generator/base.rb +12 -12
  424. data/lib/pubid/urn_parser/base.rb +81 -0
  425. data/lib/pubid/urn_parser/errors.rb +9 -0
  426. data/lib/pubid/urn_parser.rb +14 -0
  427. data/lib/pubid/version.rb +1 -1
  428. data/lib/pubid.rb +45 -7
  429. data/lib/tasks/export.rake +6 -5
  430. data/lib/tasks/website-data.json +1940 -1882
  431. metadata +75 -45
  432. data/lib/pubid/amca/scheme.rb +0 -16
  433. data/lib/pubid/ansi/scheme.rb +0 -15
  434. data/lib/pubid/api/scheme.rb +0 -66
  435. data/lib/pubid/ashrae/scheme.rb +0 -53
  436. data/lib/pubid/asme/scheme.rb +0 -37
  437. data/lib/pubid/astm/scheme.rb +0 -55
  438. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  439. data/lib/pubid/bsi/scheme.rb +0 -243
  440. data/lib/pubid/ccsds/scheme.rb +0 -57
  441. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  442. data/lib/pubid/cie/scheme.rb +0 -64
  443. data/lib/pubid/components/factory.rb +0 -50
  444. data/lib/pubid/csa/scheme.rb +0 -44
  445. data/lib/pubid/etsi/scheme.rb +0 -42
  446. data/lib/pubid/export/data_class_exporter.rb +0 -59
  447. data/lib/pubid/export/ieee_exporter.rb +0 -78
  448. data/lib/pubid/export/itu_exporter.rb +0 -66
  449. data/lib/pubid/export/nist_exporter.rb +0 -64
  450. data/lib/pubid/export/registry_exporter.rb +0 -90
  451. data/lib/pubid/export/scheme_exporter.rb +0 -70
  452. data/lib/pubid/identifier_registry.rb +0 -198
  453. data/lib/pubid/idf/scheme.rb +0 -61
  454. data/lib/pubid/iec/scheme.rb +0 -71
  455. data/lib/pubid/ieee/scheme.rb +0 -90
  456. data/lib/pubid/iho/scheme.rb +0 -29
  457. data/lib/pubid/iso/identifiers/base.rb +0 -115
  458. data/lib/pubid/iso/scheme.rb +0 -193
  459. data/lib/pubid/itu/scheme.rb +0 -174
  460. data/lib/pubid/jcgm/scheme.rb +0 -60
  461. data/lib/pubid/jis/components/code.rb +0 -59
  462. data/lib/pubid/jis/identifiers/base.rb +0 -72
  463. data/lib/pubid/jis/scheme.rb +0 -49
  464. data/lib/pubid/nist/components/publisher.rb +0 -24
  465. data/lib/pubid/nist/scheme.rb +0 -199
  466. data/lib/pubid/oiml/identifiers/base.rb +0 -36
  467. data/lib/pubid/oiml/scheme.rb +0 -46
  468. data/lib/pubid/plateau/scheme.rb +0 -45
  469. data/lib/pubid/rendering/base.rb +0 -73
  470. data/lib/pubid/rendering/common.rb +0 -211
  471. data/lib/pubid/rendering/format.rb +0 -25
  472. data/lib/pubid/sae/scheme.rb +0 -47
  473. data/lib/pubid/scheme.rb +0 -219
@@ -0,0 +1,307 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Ieee
5
+ # Human-readable renderer for IEEE identifiers.
6
+ #
7
+ # Produces strings like:
8
+ # "IEEE Std 802.11-2020"
9
+ # "IEEE Std 535-2013/Cor. 1-2017"
10
+ # "ANSI C37.61-1973 and IEEE Std 321-1973"
11
+ #
12
+ # The renderer is registered as the +:human+ format in the IEEE format
13
+ # registry and invoked via +render(format: :human)+.
14
+ #
15
+ # For wrapper types (DualPublished, AdoptedStandard, etc.) the renderer
16
+ # composes child identifiers. For simple identifiers it delegates to the
17
+ # identifier's own publisher/code/relationship helpers.
18
+ class Renderer < ::Pubid::Renderers::Base
19
+ def render(context: nil, **opts)
20
+ id = @id
21
+
22
+ case id
23
+ when Identifiers::DualPublished
24
+ render_dual_published(id)
25
+ when Identifiers::DualIdentifier
26
+ render_dual_identifier(id)
27
+ when Identifiers::AdoptedStandard
28
+ render_adopted_standard(id)
29
+ when Identifiers::RedlinedStandard
30
+ render_redlined_standard(id)
31
+ when Identifiers::Corrigendum
32
+ render_corrigendum(id)
33
+ when Identifiers::InterpretationIdentifier
34
+ render_interpretation(id)
35
+ when Identifiers::ConformanceIdentifier
36
+ render_conformance(id)
37
+ when Identifiers::MultiNumberedIdentifier
38
+ render_multi_numbered(id)
39
+ when Identifiers::ParentheticalIdentifier
40
+ render_parenthetical(id)
41
+ when Identifiers::CsaDualPublished
42
+ render_csa_dual_published(id)
43
+ when Identifiers::IecIeeeCopublished
44
+ render_iec_ieee_copublished(id)
45
+ when Identifiers::SiStandard
46
+ render_si_standard(id)
47
+ when Identifiers::JointDevelopment
48
+ id.to_s
49
+ else
50
+ render_base(id)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # ------------------------------------------------------------------
57
+ # Base IEEE identifier rendering
58
+ # ------------------------------------------------------------------
59
+
60
+ def render_base(id)
61
+ parts = []
62
+
63
+ # Publisher(s) - handle copublisher array properly
64
+ if id.copublisher && !id.copublisher.empty?
65
+ parts << [id.publisher, *id.copublisher].join("/")
66
+ else
67
+ parts << id.publisher
68
+ end
69
+
70
+ # Draft status
71
+ parts << id.draft_status if id.draft_status
72
+
73
+ # Type - only render for IEEE/AIEE publishers, and only for non-projects
74
+ should_render_type = id.publisher&.match?(/^(IEEE|AIEE)/)
75
+
76
+ if should_render_type && !id.typed_stage&.project_status && id.type && !id.type.to_s.strip.empty? && id.type != "P"
77
+ type_str = id.type.dup
78
+ type_str = type_str.sub(/^P/, "") if type_str.start_with?("P")
79
+ parts << type_str unless type_str.strip.empty?
80
+ end
81
+
82
+ # Code - with P prefix for projects (concatenated, not separated)
83
+ if id.code_obj
84
+ result = id.code_obj.to_s
85
+
86
+ # Prepend P if this is a project AND code doesn't already have P
87
+ if id.typed_stage&.project_status && should_render_type && !result.start_with?("P")
88
+ result = "P#{result}"
89
+ end
90
+
91
+ # Only attach year to code if there's no edition, no month, and no draft
92
+ result += "-#{id.year}" if id.year && !id.draft_obj && !id.edition && !id.month
93
+
94
+ # Append draft to code - with or without space based on original format
95
+ if id.draft_obj
96
+ result += id.space_before_draft ? " #{id.draft_obj}" : id.draft_obj.to_s
97
+ end
98
+
99
+ # Append interpretation notation (/INT)
100
+ result += "/INT" if id.interpretation
101
+
102
+ # Append conformance notation (/ConformanceNN-YYYY)
103
+ if id.conf_number
104
+ result += "/Conformance#{id.conf_number}"
105
+ result += "-#{id.conf_year}" if id.conf_year
106
+ end
107
+
108
+ # Append ASHRAE joint publication (/ASHRAE Guideline NN-YYYY)
109
+ if id.ashrae_number
110
+ result += "/ASHRAE Guideline #{id.ashrae_number}"
111
+ result += "-#{id.ashrae_year}" if id.ashrae_year
112
+ end
113
+
114
+ # Append IEEE cross-reference (/C62.22.1-1996)
115
+ result += id.crossref if id.crossref
116
+
117
+ parts << result
118
+ elsif should_render_type && id.typed_stage&.project_status
119
+ # No code but is a project - add standalone P
120
+ parts << "P"
121
+ end
122
+
123
+ # Edition - with year if present (IEC style)
124
+ if id.edition
125
+ edition_str = "Edition #{id.edition}"
126
+ if id.year
127
+ edition_str += " #{id.year}"
128
+ edition_str += "-#{id.edition_month}" if id.edition_month
129
+ end
130
+ parts << edition_str
131
+ end
132
+
133
+ # Build the main identifier (without month yet)
134
+ result = parts.join(" ")
135
+
136
+ # Month/Day - append directly to avoid extra space before comma
137
+ if id.month
138
+ result += ", #{id.month}"
139
+ result += " #{id.day}" if id.day
140
+ if id.year && !id.edition
141
+ result += ", #{id.year}"
142
+ end
143
+ end
144
+
145
+ # Add parenthetical content if present
146
+ parentheticals = []
147
+
148
+ reaff = id.reaffirmed
149
+ if reaff && !reaff.to_s.strip.empty?
150
+ parentheticals << "(R#{reaff})"
151
+ end
152
+
153
+ if id.parenthetical_content
154
+ parentheticals << "(#{id.parenthetical_content})"
155
+ elsif id.relationships && !id.relationships.empty?
156
+ relationship_str = id.relationships.join(" / ")
157
+ parentheticals << "(#{relationship_str})"
158
+ elsif id.revision_of
159
+ parentheticals << "(Revision of IEEE Std #{id.revision_of})"
160
+ elsif id.amendment_to
161
+ parentheticals << "(Amendment to IEEE Std #{id.amendment_to})"
162
+ elsif id.adoption
163
+ parentheticals << "(Adoption of #{id.adoption})"
164
+ elsif id.note && !id.note.to_s.strip.empty?
165
+ parentheticals << "(#{id.note})"
166
+ end
167
+
168
+ result += " #{parentheticals.join(' ')}" unless parentheticals.empty?
169
+
170
+ # Book nickname - outside parentheses in square brackets
171
+ result += " [#{id.nickname}]" if id.nickname && !id.nickname.to_s.strip.empty?
172
+
173
+ # Redline suffix
174
+ result += " - Redline" if id.redline
175
+
176
+ result
177
+ end
178
+
179
+ # ------------------------------------------------------------------
180
+ # Wrapper types
181
+ # ------------------------------------------------------------------
182
+
183
+ def render_dual_published(id)
184
+ "#{id.first_identifier} and #{id.second_identifier}"
185
+ end
186
+
187
+ def render_dual_identifier(id)
188
+ "#{id.first_identifier} and #{id.second_identifier}"
189
+ end
190
+
191
+ def render_adopted_standard(id)
192
+ result = id.ieee_identifier.to_s
193
+ if id.adopted_identifiers && !id.adopted_identifiers.empty?
194
+ adopted_strs = id.adopted_identifiers.map(&:to_s)
195
+ result += " (#{adopted_strs.join(' and ')})"
196
+ end
197
+ result
198
+ end
199
+
200
+ def render_redlined_standard(id)
201
+ result = id.base_identifier.to_s
202
+ result += " (Revision of #{id.revision_of})" if id.revision_of
203
+ result += " - Redline" if id.redline
204
+ result
205
+ end
206
+
207
+ def render_corrigendum(id)
208
+ return render_base(id) unless id.base_identifier
209
+
210
+ result = id.base_identifier.to_s
211
+ result += "/Cor"
212
+ result += ". " if id.cor_number # Add period and space for formal format
213
+ result += id.cor_number if id.cor_number
214
+ result += "-#{id.cor_year}" if id.cor_year
215
+ result
216
+ end
217
+
218
+ def render_interpretation(id)
219
+ return render_base(id) unless id.base_identifier
220
+
221
+ result = id.base_identifier.to_s
222
+ result += "/INT"
223
+ result += "-#{id.int_year}" if id.int_year
224
+ result
225
+ end
226
+
227
+ def render_conformance(id)
228
+ return render_base(id) unless id.base_identifier
229
+
230
+ result = id.base_identifier.to_s
231
+ result += "/Conformance#{id.conf_number}" if id.conf_number
232
+ result += "-#{id.conf_year}" if id.conf_year
233
+ result
234
+ end
235
+
236
+ def render_multi_numbered(id)
237
+ return id.primary_identifier.to_s unless id.secondary_identifier
238
+
239
+ secondary_code = id.secondary_identifier.code.to_s
240
+ if secondary_code.start_with?("C") && secondary_code.match?(/^C\d+\./)
241
+ "#{id.primary_identifier}/#{id.secondary_identifier}"
242
+ else
243
+ "#{id.primary_identifier} and #{id.secondary_identifier}"
244
+ end
245
+ end
246
+
247
+ def render_parenthetical(id)
248
+ result = id.base_identifier.to_s
249
+ result += " (#{id.parenthetical_identifier})" if id.parenthetical_identifier
250
+ result
251
+ end
252
+
253
+ def render_csa_dual_published(id)
254
+ csa_str = id.csa_identifier.to_s
255
+ csa_str = "CSA #{csa_str}" unless csa_str.start_with?("CSA", "CAN/")
256
+
257
+ "#{id.ieee_identifier}/#{csa_str}"
258
+ end
259
+
260
+ def render_iec_ieee_copublished(id)
261
+ result = "IEC/IEEE"
262
+ result += " #{id.copublished_number}" if id.copublished_number
263
+ result += id.draft_info if id.draft_info
264
+ result += " IEC:#{id.iec_year}" if id.iec_year
265
+ result += " #{id.date_info}" if id.date_info
266
+ result
267
+ end
268
+
269
+ def render_si_standard(id)
270
+ parts = []
271
+
272
+ # Publisher (IEEE/ASTM)
273
+ parts << "IEEE/ASTM"
274
+
275
+ # Type (SI or PSI based on typed_stage)
276
+ parts << if id.typed_stage&.abbr&.include?("PSI")
277
+ "PSI"
278
+ else
279
+ "SI"
280
+ end
281
+
282
+ # Code (number) with draft version for PSI
283
+ code_part = id.code.to_s
284
+ if id.draft_obj
285
+ code_part += "/D#{id.draft_obj.version}"
286
+ end
287
+ parts << code_part if id.code
288
+
289
+ # Date
290
+ if id.month && id.year
291
+ parts << ", #{id.month} #{id.year}"
292
+ elsif id.year
293
+ parts << "-#{id.year}"
294
+ end
295
+
296
+ # Relationships (if present)
297
+ result = parts.join(" ")
298
+ if id.relationships && !id.relationships.empty?
299
+ rel_strs = id.relationships.map(&:to_s)
300
+ result += " (#{rel_strs.join(' / ')})"
301
+ end
302
+
303
+ result
304
+ end
305
+ end
306
+ end
307
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Ieee
5
+ # Parses IEEE URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits many fields; this parser handles the common
8
+ # published-standard shape:
9
+ # urn:ieee:{publisher}:{code}:{year}
10
+ #
11
+ # publisher is the lowercase publisher (with optional copublishers
12
+ # joined by `-`). code is the alphanumeric designation (period is the
13
+ # part separator within the code). The year separator in human-readable
14
+ # form is `-`.
15
+ #
16
+ # Examples:
17
+ # - urn:ieee:ieee:802.3:2018 → IEEE Std 802.3-2018
18
+ # - urn:ieee:ieee:1018:2019 → IEEE Std 1018-2019
19
+ class UrnParser < Pubid::UrnParser::Base
20
+ PUBLISHER_LABEL = "IEEE"
21
+
22
+ def parse_urn(urn)
23
+ body = strip_namespace(urn)
24
+ parts = split_parts(body)
25
+
26
+ _publisher, code, year = parts
27
+
28
+ text = "#{PUBLISHER_LABEL} Std #{code}"
29
+ text += "-#{year}" if year
30
+ flavor_parse(text)
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/pubid/ieee.rb CHANGED
@@ -9,9 +9,11 @@ module Pubid
9
9
  autoload :Ire, "#{__dir__}/ieee/ire"
10
10
  autoload :Nesc, "#{__dir__}/ieee/nesc"
11
11
  autoload :Parser, "#{__dir__}/ieee/parser"
12
- autoload :Scheme, "#{__dir__}/ieee/scheme"
12
+ autoload :PreParser, "#{__dir__}/ieee/pre_parser"
13
+ autoload :Renderer, "#{__dir__}/ieee/renderer"
13
14
  autoload :TypedStages, "#{__dir__}/ieee/typed_stages"
14
15
  autoload :UrnGenerator, "#{__dir__}/ieee/urn_generator"
16
+ autoload :UrnParser, "#{__dir__}/ieee/urn_parser"
15
17
 
16
18
  # Components submodule
17
19
  module Components
@@ -23,10 +25,73 @@ module Pubid
23
25
 
24
26
  class << self
25
27
  def parse(input)
28
+ if input.length > Pubid::MAX_INPUT_LENGTH
29
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
30
+ end
31
+
26
32
  Identifier.parse(input)
27
33
  end
34
+
35
+ # Auto-discover all identifier types from the Identifiers namespace
36
+ # @return [Array<Class>] identifier classes that define a self.type Hash
37
+ def identifier_types
38
+ @identifier_types ||= Identifiers.constants
39
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
40
+ .select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
41
+ .select { |c| c.type.is_a?(Hash) }
42
+ end
43
+
44
+ # Build typed stage index from TypedStages module
45
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
46
+ def all_typed_stages
47
+ @all_typed_stages ||= TypedStages::TYPED_STAGES
48
+ end
49
+
50
+ # Lookup: type code -> identifier class
51
+ # @param code [String, Symbol] the type key to find
52
+ # @return [Class, nil] the matching identifier class
53
+ def locate_type(code)
54
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
55
+ end
56
+
57
+ # Lookup: abbreviation -> typed stage
58
+ # @param abbr [String, Symbol] the abbreviation to find
59
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
60
+ def locate_stage(abbr)
61
+ abbr_str = abbr.to_s.upcase
62
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
63
+ end
64
+
65
+ # Lookup: IEEE draft notation -> typed stage
66
+ # @param draft [String] IEEE draft notation (e.g., "D1", "D5", "P")
67
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
68
+ def locate_stage_by_ieee_draft(draft)
69
+ return nil if draft.nil? || draft.to_s.strip.empty?
70
+
71
+ draft_str = draft.to_s.strip
72
+
73
+ # Try exact match on abbreviation first
74
+ ts = all_typed_stages.find { |t| t.abbr.include?(draft_str) }
75
+ return ts if ts
76
+
77
+ # Try match on ieee_draft_equivalent
78
+ all_typed_stages.find { |t| t.ieee_draft_equivalent == draft_str }
79
+ end
80
+
81
+ # Lookup: ISO stage code -> typed stage
82
+ # @param stage [String] ISO stage code (e.g., "WD", "CD", "DIS", "FDIS")
83
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
84
+ def locate_stage_by_iso_stage(stage)
85
+ return nil if stage.nil? || stage.to_s.strip.empty?
86
+
87
+ all_typed_stages.find { |ts| ts.iso_stage_equivalent == stage.to_s.strip }
88
+ end
28
89
  end
29
90
  end
30
91
  end
31
92
 
32
93
  Pubid::Registry.register(:ieee, Pubid::Ieee)
94
+
95
+ # Per-flavor format registry: inherits global formats, overrides :human
96
+ Pubid::Ieee::Identifiers::Base.format_registry = Pubid::FormatRegistry.new(parent: Pubid::Identifier.format_registry)
97
+ Pubid::Ieee::Identifiers::Base.format_registry.register(:human, renderer: Pubid::Ieee::Renderer)
@@ -10,7 +10,6 @@ module Pubid
10
10
  autoload :Ire, "#{__dir__}/ire"
11
11
  autoload :Nesc, "#{__dir__}/nesc"
12
12
  autoload :Parser, "#{__dir__}/parser"
13
- autoload :Scheme, "#{__dir__}/scheme"
14
13
  autoload :TypedStages, "#{__dir__}/typed_stages"
15
14
  autoload :UrnGenerator, "#{__dir__}/urn_generator"
16
15
 
@@ -9,7 +9,7 @@ module Pubid
9
9
  type_letter = stringify(hash[:type])
10
10
 
11
11
  attrs = {
12
- code: stringify(hash[:code]),
12
+ number: stringify(hash[:number]),
13
13
  appendix: stringify(hash[:appendix]),
14
14
  part: stringify(hash[:part]),
15
15
  annex: stringify(hash[:annex]),
@@ -17,7 +17,7 @@ module Pubid
17
17
  version: stringify(hash[:version]),
18
18
  }.compact
19
19
 
20
- Scheme.identifier_klass_for_type_letter(type_letter).new(**attrs)
20
+ Pubid::Iho.identifier_klass_for_type_letter(type_letter).new(**attrs)
21
21
  end
22
22
 
23
23
  def self.build(parsed)
@@ -1,61 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Pubid
4
- module Iho
5
- # Entry point for parsing IHO identifiers.
6
- module Identifier
7
- # Parse an IHO identifier string into an identifier object
8
- # @param identifier [String] The IHO identifier string to parse
9
- # @return [Pubid::Iho::Identifiers::Base] The appropriate identifier object
10
- # @raise [Parslet::ParseFailed] If parsing fails
11
- def self.parse(identifier)
12
- parsed = Parser.parse(identifier)
13
- Builder.build(parsed)
14
- rescue Parslet::ParseFailed => e
15
- raise "Failed to parse IHO identifier '#{identifier}': #{e.message}"
16
- end
17
-
18
- # Factory that builds an IHO identifier from a hash of primitives.
19
- #
20
- # IHO identifiers are simpler than ISO/IEC: attributes are plain
21
- # strings (no Component wrapping), so coercion just calls #to_s.
22
- #
23
- # Dispatch:
24
- # * `type:` accepts the type key (`:standard`, `:publication`,
25
- # `:miscellaneous`, `:bibliographic`, `:circular_letter`) or
26
- # the IHO series letter (`"S"`, `"P"`, `"M"`, `"B"`, `"C"`).
27
- # * Default is {Identifiers::Standard}.
28
- #
29
- # @param type [Symbol, String, nil]
30
- # @param opts [Hash] :publisher (default "IHO"), :code, :appendix,
31
- # :part, :annex, :supplement, :version
32
- def self.create(type: nil, **opts)
33
- klass = resolve_create_class(type)
34
- klass.new(**coerce_create_attrs(opts))
35
- end
36
-
37
- def self.resolve_create_class(type)
38
- return Identifiers::Standard if type.nil?
39
-
40
- by_key = Scheme::IDENTIFIERS.to_h { |k| [k.type[:key], k] }
41
- return by_key[type.to_sym] if by_key.key?(type.to_sym)
42
-
43
- begin
44
- Scheme.identifier_klass_for_type_letter(type.to_s.upcase)
45
- rescue KeyError
46
- raise ArgumentError, "Unknown IHO type: #{type.inspect}"
47
- end
48
- end
49
-
50
- def self.coerce_create_attrs(opts)
51
- attrs = {}
52
- %i[publisher code appendix part annex supplement version].each do |k|
53
- v = opts[k]
54
- attrs[k] = v.to_s unless v.nil?
55
- end
56
- attrs
57
- end
58
- private_class_method :resolve_create_class, :coerce_create_attrs
59
- end
60
- end
61
- end
3
+ # The IHO flavor base class is Pubid::Iho::Identifier — a real Pubid::Identifier
4
+ # subclass that every concrete IHO identifier descends from, so `is_a?` identity
5
+ # and the shared polymorphic `from_hash` work natively (no facade needed). Its
6
+ # body, `.parse`, and the Identifiers::Base back-compat alias live in
7
+ # identifiers/base.rb; this file just ensures it is loaded when a consumer
8
+ # references Pubid::Iho::Identifier directly.
9
+ require_relative "identifiers/base"
@@ -2,40 +2,73 @@
2
2
 
3
3
  module Pubid
4
4
  module Iho
5
- module Identifiers
6
- # Base class for all IHO identifiers.
7
- #
8
- # IHO identifiers have the form:
9
- # IHO {S|P|M|B|C}-{code}[ Ap. {appendix}][ Part {part}][ Annex {annex}][ Suppl {supplement}][ {version}]
10
- #
11
- # The leading IHO publisher prefix is optional on input but always
12
- # emitted on output.
13
- class Base < Pubid::Identifier
14
- attribute :publisher, :string, default: "IHO"
15
- attribute :code, :string
16
- attribute :appendix, :string
17
- attribute :part, :string
18
- attribute :annex, :string
19
- attribute :supplement, :string
20
- attribute :version, :string
5
+ # Base class for all IHO identifiers. Canonical name Pubid::Iho::Identifier;
6
+ # every concrete IHO identifier (Identifiers::*) descends from it, and
7
+ # Identifiers::Base — aliased at the foot of this file — points back to it.
8
+ #
9
+ # IHO identifiers have the form:
10
+ # IHO {S|P|M|B|C}-{number}[ Ap. {appendix}][ Part {part}][ Annex {annex}][ Suppl {supplement}][ {version}]
11
+ #
12
+ # The leading IHO publisher prefix is optional on input but always
13
+ # emitted on output.
14
+ class Identifier < ::Pubid::Identifier
15
+ # Parse an IHO identifier string into an identifier object
16
+ # @param identifier [String] The IHO identifier string to parse
17
+ # @return [Pubid::Iho::Identifier] The appropriate identifier object
18
+ # @raise [Parslet::ParseFailed] If parsing fails
19
+ def self.parse(identifier)
20
+ parsed = Parser.parse(identifier)
21
+ Builder.build(parsed)
22
+ rescue Parslet::ParseFailed => e
23
+ raise "Failed to parse IHO identifier '#{identifier}': #{e.message}"
24
+ end
21
25
 
22
- def self.parse(string)
23
- Iho::Identifier.parse(string)
24
- end
26
+ # `number` overrides the generic Components::Code attribute with a plain
27
+ # string (same pattern as `part` below); it holds the IHO document
28
+ # number (e.g. "100", "1/21"). Kept as the generic `number` so the
29
+ # relaton index sorts/binary-searches on it natively via `id.number`.
30
+ attribute :number, :string
31
+ attribute :publisher, :string, default: "IHO"
32
+ attribute :appendix, :string
33
+ attribute :part, :string
34
+ attribute :annex, :string
35
+ attribute :supplement, :string
36
+ attribute :version, :string
25
37
 
26
- # Render the identifier as a string in canonical IHO form.
27
- # @return [String]
28
- def to_s
29
- letter = self.class.type[:short]
30
- rendered = "#{publisher} #{letter}-#{code}"
31
- rendered << " Ap. #{appendix}" if appendix
32
- rendered << " Part #{part}" if part
33
- rendered << " Annex #{annex}" if annex
34
- rendered << " Suppl #{supplement}" if supplement
35
- rendered << " #{version}" if version
36
- rendered
37
- end
38
+ # Polymorphic type map for lutaml::Model key_value serialization: maps
39
+ # each subclass's polymorphic_name to its class name so `from_hash` can
40
+ # re-instantiate the concrete type from `_type`.
41
+ IHO_TYPE_MAP = {
42
+ "pubid:iho:standard" => "Pubid::Iho::Identifiers::Standard",
43
+ "pubid:iho:publication" => "Pubid::Iho::Identifiers::Publication",
44
+ "pubid:iho:miscellaneous" => "Pubid::Iho::Identifiers::Miscellaneous",
45
+ "pubid:iho:bibliographic" => "Pubid::Iho::Identifiers::Bibliographic",
46
+ "pubid:iho:circular-letter" => "Pubid::Iho::Identifiers::CircularLetter",
47
+ }.freeze
48
+
49
+ # The base Pubid::Identifier no longer auto-maps attributes, so each
50
+ # flavor's top class must declare its own key_value mapping. IHO
51
+ # attributes are plain strings, so they map directly. `publisher` is
52
+ # intentionally omitted: it is always the "IHO" default and is restored
53
+ # on load.
54
+ key_value do
55
+ map "_type", to: :_type, polymorphic_map: IHO_TYPE_MAP
56
+ map "number", to: :number
57
+ map "appendix", to: :appendix
58
+ map "part", to: :part
59
+ map "annex", to: :annex
60
+ map "supplement", to: :supplement
61
+ map "version", to: :version
38
62
  end
63
+
64
+ # from_hash is the shared polymorphic dispatch on Pubid::Identifier.
65
+ # IHO_TYPE_MAP remains as the key_value polymorphic_map.
66
+ end
67
+
68
+ module Identifiers
69
+ # Backward-compatible alias: IHO's base class used to be
70
+ # Pubid::Iho::Identifiers::Base. It is now Pubid::Iho::Identifier.
71
+ Base = Pubid::Iho::Identifier
39
72
  end
40
73
  end
41
74
  end
@@ -19,8 +19,8 @@ module Pubid
19
19
  (str(":") >> digits) | (str("/") >> digits) | (dash >> digits) | match("[A-Z]")
20
20
  end
21
21
 
22
- rule(:code) do
23
- (digits >> number_suffix.maybe).as(:code)
22
+ rule(:number) do
23
+ (digits >> number_suffix.maybe).as(:number)
24
24
  end
25
25
 
26
26
  rule(:appendix) do
@@ -54,7 +54,7 @@ module Pubid
54
54
 
55
55
  rule(:identifier) do
56
56
  (str("IHO") >> space).maybe >>
57
- series >> dash >> code >>
57
+ series >> dash >> number >>
58
58
  appendix.maybe >> part.maybe >> annex.maybe >> supplement.maybe >> version.maybe
59
59
  end
60
60
 
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Iho
5
+ # Human-readable renderer for IHO identifiers.
6
+ #
7
+ # Produces strings like:
8
+ # "IHO S-44 5.0.0"
9
+ # "IHO P-1/21 1.0.0"
10
+ # "IHO S-100 Part 4a 1.0.0"
11
+ # "IHO S-65 Ap. A 1.0.0"
12
+ #
13
+ # The renderer is registered as the `:human` format in the IHO format
14
+ # registry and invoked via `render(format: :human)`.
15
+ class Renderer < ::Pubid::Renderers::Base
16
+ def render(context: nil, **opts)
17
+ id = @id
18
+
19
+ letter = id.class.type[:short]
20
+ rendered = "#{id.publisher} #{letter}-#{id.number}"
21
+ rendered << " Ap. #{id.appendix}" if id.appendix
22
+ rendered << " Part #{id.part}" if id.part
23
+ rendered << " Annex #{id.annex}" if id.annex
24
+ rendered << " Suppl #{id.supplement}" if id.supplement
25
+ rendered << " #{id.version}" if id.version
26
+ rendered
27
+ end
28
+ end
29
+ end
30
+ end