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
@@ -2,7 +2,57 @@
2
2
 
3
3
  module Pubid
4
4
  module Ccsds
5
- module Identifier
5
+ # Abstract root for every CCSDS identifier AND the flavor's parse entry
6
+ # point — mirrors Pubid::Iso::Identifier / Pubid::Jis::Identifier. Concrete
7
+ # identifiers (Identifiers::Base, Identifiers::Corrigendum) descend from this
8
+ # class, so a parsed CCSDS id is an instance of Pubid::Ccsds::Identifier and
9
+ # relaton-index can pass this class as `pubid_class` for from_hash/to_hash.
10
+ #
11
+ # Keeping the root abstract (it is never itself a serialized type, so it is
12
+ # absent from CCSDS_TYPE_MAP) is what breaks the polymorphic recursion a
13
+ # supplement's `base_identifier` would otherwise hit if it pointed at a
14
+ # concrete type that is also its own superclass.
15
+ class Identifier < ::Pubid::Identifier
16
+ # CCSDS stores every code component as a plain string (the Builder passes
17
+ # strings, never Components::Code/Edition objects), so override the
18
+ # inherited Components::Code/Edition attribute types with :string. This
19
+ # both matches the runtime values and yields a lean, round-trippable
20
+ # key_value (`to_hash`) serialization instead of nested component hashes.
21
+ # `type` (single book-color letter B/G/M/R/Y/O), `suffix`, and `language`
22
+ # are likewise CCSDS-specific plain strings.
23
+ attribute :number, :string
24
+ attribute :part, :string
25
+ attribute :edition, :string
26
+ attribute :type, :string
27
+ attribute :suffix, :string
28
+ attribute :language, :string
29
+
30
+ # Polymorphic type map for lutaml::Model key_value (de)serialization,
31
+ # mapping each concrete class's polymorphic_name to its class name.
32
+ CCSDS_TYPE_MAP = {
33
+ "pubid:ccsds:base" => "Pubid::Ccsds::Identifiers::Base",
34
+ "pubid:ccsds:corrigendum" => "Pubid::Ccsds::Identifiers::Corrigendum",
35
+ }.freeze
36
+
37
+ # The shared Pubid::Identifier no longer auto-maps attributes, so the
38
+ # flavor's root declares the full key_value mapping; subclasses
39
+ # (SupplementIdentifier/Corrigendum) merge their own blocks on top. Every
40
+ # value is a plain string, so a direct `to:` map round-trips.
41
+ key_value do
42
+ map "_type", to: :_type, polymorphic_map: CCSDS_TYPE_MAP
43
+ map "number", to: :number
44
+ map "part", to: :part
45
+ map "edition", to: :edition
46
+ map "type", to: :type
47
+ map "suffix", to: :suffix
48
+ map "language", to: :language
49
+ end
50
+
51
+ def publisher
52
+ "CCSDS"
53
+ end
54
+
55
+ # Parse a CCSDS identifier string into the appropriate identifier object.
6
56
  def self.parse(identifier)
7
57
  # Apply legacy update_codes normalization first
8
58
  normalized = Core::UpdateCodes.apply(identifier, :ccsds)
@@ -12,73 +62,8 @@ module Pubid
12
62
  raise "Failed to parse CCSDS identifier '#{identifier}': #{e.message}"
13
63
  end
14
64
 
15
- # Factory that builds a CCSDS identifier from a hash of primitives.
16
- #
17
- # Accepts the field shape used by relaton-data-ccsds index entries:
18
- # `:publisher`, `:number`, `:series`, `:part`, `:book_color`,
19
- # `:retired`, `:edition`, plus the parsed-shape fields `:type`,
20
- # `:suffix`, `:language`. CCSDS 2.x maps these as:
21
- #
22
- # * `:series` + `:number` → combined number ("A" + "20" → "A20")
23
- # * `:book_color` → `:type` (B/G/M/R/Y/O)
24
- # * `:publisher` → ignored (hardcoded "CCSDS")
25
- # * `:retired` → ignored (no 2.x field)
26
- #
27
- # Supplement subclasses (currently just Corrigendum, via `type: :cor`)
28
- # raise ArgumentError until `base:` kwarg is wired through.
29
- def self.create(type: nil, **opts)
30
- if type
31
- type_sym = type.to_sym
32
- base_type_key = Identifiers::Base.type[:key].to_sym
33
-
34
- if type_sym != base_type_key
35
- supplement = supplement_klass_for(type_sym)
36
- if supplement
37
- # TODO(create-shim): supplement subclasses (Corrigendum)
38
- # require a base_identifier. Wire `base:` kwarg through once
39
- # a caller needs it.
40
- raise ArgumentError, "#{supplement} requires a " \
41
- "base_identifier; Identifier.create " \
42
- "cannot build supplements yet"
43
- end
44
-
45
- # Not a class-dispatch key — treat as book_color data
46
- # (e.g. `type: "G"` for Green Book) and merge back into opts.
47
- opts = opts.merge(type: type)
48
- end
49
- end
50
-
51
- Identifiers::Base.new(**coerce_create_attrs(opts))
52
- end
53
-
54
- def self.supplement_klass_for(type_sym)
55
- Scheme.supplement_identifiers.find do |k|
56
- k.type[:key].to_sym == type_sym
57
- end
58
- end
59
-
60
- def self.coerce_create_attrs(opts)
61
- attrs = {}
62
-
63
- if opts[:number]
64
- num = opts[:number].to_s
65
- attrs[:number] =
66
- opts[:series] ? "#{opts[:series]}#{num}" : num
67
- end
68
-
69
- attrs[:type] = opts[:book_color].to_s if opts[:book_color]
70
- # Allow caller to pass :type as data when no :book_color given
71
- # (parsed identifiers expose it via Base#type attribute).
72
- attrs[:type] = opts[:type].to_s if opts[:type] && !attrs[:type]
73
-
74
- %i[part edition suffix language].each do |k|
75
- v = opts[k]
76
- attrs[k] = v.to_s unless v.nil?
77
- end
78
-
79
- attrs
80
- end
81
- private_class_method :supplement_klass_for, :coerce_create_attrs
65
+ # from_hash is the shared polymorphic dispatch on Pubid::Identifier.
66
+ # CCSDS_TYPE_MAP remains as the key_value polymorphic_map.
82
67
  end
83
68
  end
84
69
  end
@@ -3,12 +3,15 @@
3
3
  module Pubid
4
4
  module Ccsds
5
5
  module Identifiers
6
- # CCSDS identifier
7
- # Format: CCSDS NUMBER.PART-TYPE-EDITION[-SUFFIX]
8
- # Example: CCSDS 120.0-G-4, CCSDS 100.0-G-1-S
9
- class Base < Lutaml::Model::Serializable
10
- # CCSDS uses a simple architecture without typed stages
11
- # TYPED_STAGES includes default stage for base identifiers
6
+ # CCSDS base identifier (a published standard).
7
+ #
8
+ # Format: CCSDS NUMBER.PART-TYPE-EDITION[-SUFFIX][ - LANGUAGE Translated]
9
+ # Examples: CCSDS 120.0-G-4, CCSDS 100.0-G-1-S, CCSDS 551.1-O-2 - Russian Translated
10
+ #
11
+ # Attributes, the key_value mapping and from_hash dispatch live on the
12
+ # abstract root Pubid::Ccsds::Identifier; this concrete type only carries
13
+ # its typed stage and rendering.
14
+ class Base < Pubid::Ccsds::Identifier
12
15
  TYPED_STAGES = [
13
16
  Pubid::Components::TypedStage.new(
14
17
  abbr: [""],
@@ -17,72 +20,19 @@ module Pubid
17
20
  ),
18
21
  ].freeze
19
22
 
20
- # Type information for this identifier class
21
- #
22
- # @return [Hash] Type information with key, title, and short form
23
23
  def self.type
24
- { key: :base, title: "Base Standard", short: nil }
24
+ { key: :base, web: :base, title: "Base Standard", short: nil }
25
25
  end
26
26
 
27
- # Return a copy of this identifier with the named attributes
28
- # nil'd. Mirrors the {Pubid::Identifier#exclude} convenience.
29
- # CCSDS Base extends Lutaml::Model::Serializable directly (not
30
- # Pubid::Identifier), so the method is defined here too.
31
- def exclude(*args)
32
- attrs = self.class.attributes.each_with_object({}) do |(name, _), h|
33
- h[name] = args.include?(name) ? nil : send(name)
34
- end
35
- self.class.new(attrs)
36
- end
37
-
38
- # Generate URN for this identifier
39
- #
40
- # @return [String] URN representation
41
-
42
- # Include CCSDS-specific attributes in serialization
43
- def base_hash
44
- hash = super
45
- # CCSDS uses plain strings for type, edition, suffix
46
- hash[:type] = type if type
47
- hash[:suffix] = suffix if suffix
48
- hash[:language] = language if language
49
- hash
50
- end
51
-
52
- attribute :number, :string
53
- attribute :part, :string
54
- attribute :type, :string # B, G, M, R, Y, O, etc.
55
- attribute :edition, :string
56
- attribute :suffix, :string # Optional suffix like -S
57
- attribute :language, :string # Language metadata (e.g., "French", "Russian")
58
-
59
- def publisher
60
- "CCSDS"
61
- end
62
-
63
- def to_s
27
+ def to_s(**_opts)
64
28
  result = "#{publisher} #{number}"
65
29
  result += ".#{part}" if part
66
30
  result += "-#{type}" if type
67
31
  result += "-#{edition}" if edition
68
32
  result += "-#{suffix}" if suffix
69
-
70
- # Add language metadata
71
33
  result += " - #{language} Translated" if language
72
-
73
34
  result
74
35
  end
75
-
76
- def ==(other)
77
- return false unless other.is_a?(Base)
78
-
79
- number == other.number &&
80
- part == other.part &&
81
- type == other.type &&
82
- edition == other.edition &&
83
- suffix == other.suffix &&
84
- language == other.language
85
- end
86
36
  end
87
37
  end
88
38
  end
@@ -17,21 +17,22 @@ module Pubid
17
17
  #
18
18
  # @return [Hash] Type information with key, title, and short form
19
19
  def self.type
20
- { key: :cor, title: "Corrigendum", short: "Cor" }
20
+ { key: :cor,
21
+ web: :corrigendum, title: "Corrigendum", short: "Cor" }
21
22
  end
22
23
 
23
- attribute :cor_number, :integer
24
-
24
+ # The corrigendum sequence number is stored in the inherited `number`
25
+ # attribute (mirroring ISO), so it serializes via Base's key_value as
26
+ # { _type, number: '1', base: {...} } with no corrigendum-specific map.
25
27
  def to_s
26
28
  base_str = base_identifier.to_s
27
- "#{base_str} Cor. #{cor_number}"
29
+ "#{base_str} Cor. #{number}"
28
30
  end
29
31
 
30
32
  def ==(other)
31
33
  return false unless other.is_a?(Corrigendum)
32
34
 
33
- base_identifier == other.base_identifier &&
34
- cor_number == other.cor_number
35
+ base_identifier == other.base_identifier && number == other.number
35
36
  end
36
37
  end
37
38
  end
@@ -25,8 +25,10 @@ module Pubid
25
25
  # Type (all possible type letters)
26
26
  rule(:type) { dash >> match["A-Z"].as(:type) }
27
27
 
28
- # Edition (can have dots like 4.1)
29
- rule(:edition) { dash >> match["0-9."].repeat(1).as(:edition) }
28
+ # Edition (can have dots like 4.1, and a trailing draft letter like 1.99h)
29
+ rule(:edition) do
30
+ dash >> (match["0-9."].repeat(1) >> match["A-Za-z"].maybe).as(:edition)
31
+ end
30
32
 
31
33
  # Suffix (like -S)
32
34
  rule(:suffix) { dash >> match["A-Z"].as(:suffix) }
@@ -2,18 +2,22 @@
2
2
 
3
3
  module Pubid
4
4
  module Ccsds
5
- # Base class for CCSDS supplements (corrigenda, amendments, etc.)
6
- # Following ISO pattern: inherits from Base and uses Lutaml::Model
7
- class SupplementIdentifier < Identifiers::Base
8
- attribute :base_identifier, Identifiers::Base, polymorphic: true
5
+ # Base class for CCSDS supplements (corrigenda, amendments, etc.).
6
+ # Descends from the abstract root (not the concrete Base) and points
7
+ # `base_identifier` at the root, so the polymorphic attribute never
8
+ # resolves to its own superclass — which is what prevents lutaml from
9
+ # recursing forever while building a supplement from a hash.
10
+ class SupplementIdentifier < Identifier
11
+ attribute :base_identifier, Identifier, polymorphic: true
9
12
 
10
- # Delegate methods to base_identifier for convenient access
11
- def publisher
12
- base_identifier&.publisher
13
- end
14
-
15
- def number
16
- base_identifier&.number
13
+ # Serialize the supplemented identifier under "base" (matches ISO/JIS).
14
+ # The key stays `base_identifier` for the attribute/getter, which
15
+ # relaton-index's get_id_number relies on. A supplement's own code
16
+ # attributes (number/part/edition/...) stay nil — they live inside
17
+ # `base` — so the merged root key_value omits them here, keeping the
18
+ # serialization lean and non-duplicated.
19
+ key_value do
20
+ map "base", to: :base_identifier
17
21
  end
18
22
 
19
23
  def <=>(other)
@@ -47,7 +47,7 @@ module Pubid
47
47
  edition = maybe(:edition)
48
48
  if edition
49
49
  e = if edition.is_a?(Pubid::Components::Edition)
50
- edition.number || edition.value
50
+ edition.number
51
51
  else
52
52
  edition.to_s
53
53
  end
@@ -101,8 +101,8 @@ module Pubid
101
101
  parts << base_identifier_part
102
102
 
103
103
  supplement_chain.each do |supp|
104
- if supp.number&.value
105
- parts << "cor.#{supp.number.value}"
104
+ if supp.number && !supp.number.to_s.empty?
105
+ parts << "cor.#{supp.number}"
106
106
  elsif supp.typed_stage
107
107
  parts << supp.typed_stage.type_code.to_s
108
108
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Ccsds
5
+ # Parses CCSDS URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits: `urn:ccsds:{code}` where the code is the full
8
+ # identifier suffix after "CCSDS " (e.g., "120.0-G-4").
9
+ #
10
+ # Examples:
11
+ # - urn:ccsds:120.0-G-4 → CCSDS 120.0-G-4
12
+ # - urn:ccsds:100.0-G-1-S → CCSDS 100.0-G-1-S
13
+ class UrnParser < Pubid::UrnParser::Base
14
+ def parse_urn(urn)
15
+ body = strip_namespace(urn)
16
+ flavor_parse("CCSDS #{body}")
17
+ end
18
+ end
19
+ end
20
+ end
data/lib/pubid/ccsds.rb CHANGED
@@ -6,14 +6,52 @@ module Pubid
6
6
  autoload :Identifier, "#{__dir__}/ccsds/identifier"
7
7
  autoload :Identifiers, "#{__dir__}/ccsds/identifiers"
8
8
  autoload :Parser, "#{__dir__}/ccsds/parser"
9
- autoload :Scheme, "#{__dir__}/ccsds/scheme"
10
9
  autoload :SingleIdentifier, "#{__dir__}/ccsds/single_identifier"
11
10
  autoload :SupplementIdentifier, "#{__dir__}/ccsds/supplement_identifier"
12
11
  autoload :UrnGenerator, "#{__dir__}/ccsds/urn_generator"
12
+ autoload :UrnParser, "#{__dir__}/ccsds/urn_parser"
13
13
 
14
14
  def self.parse(identifier)
15
15
  Identifier.parse(identifier)
16
16
  end
17
+
18
+ # Auto-discover all identifier types from the Identifiers namespace.
19
+ # CCSDS identifier classes extend Lutaml::Model::Serializable directly
20
+ # but do define self.type returning a Hash.
21
+ # @return [Array<Class>] identifier classes that define a self.type Hash
22
+ def self.identifier_types
23
+ @identifier_types ||= Identifiers.constants
24
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
25
+ .select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
26
+ .select { |c| c.type.is_a?(Hash) }
27
+ end
28
+
29
+ # Build typed stage index from identifier types
30
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
31
+ def self.all_typed_stages
32
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
33
+ if klass.const_defined?(:TYPED_STAGES)
34
+ klass.const_get(:TYPED_STAGES)
35
+ else
36
+ []
37
+ end
38
+ end
39
+ end
40
+
41
+ # Lookup: type code -> identifier class
42
+ # @param code [String, Symbol] the type key to find
43
+ # @return [Class, nil] the matching identifier class
44
+ def self.locate_type(code)
45
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
46
+ end
47
+
48
+ # Lookup: abbreviation -> typed stage
49
+ # @param abbr [String, Symbol] the abbreviation to find
50
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
51
+ def self.locate_stage(abbr)
52
+ abbr_str = abbr.to_s.upcase
53
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
54
+ end
17
55
  end
18
56
  end
19
57
 
@@ -3,12 +3,8 @@
3
3
  module Pubid
4
4
  module CenCenelec
5
5
  class Builder < Pubid::Builder::Base
6
- def initialize(scheme)
7
- @scheme = scheme
8
- end
9
-
10
- def self.build(parsed_data, scheme = Scheme.new)
11
- new(scheme).build(parsed_data)
6
+ def self.build(parsed_data)
7
+ new.build(parsed_data)
12
8
  end
13
9
 
14
10
  def build(data)
@@ -40,7 +36,7 @@ module Pubid
40
36
  # Extract supplements before building base identifier (only plus/bundled)
41
37
  supplements_data = extract_supplements(data)
42
38
 
43
- # Determine identifier class using Scheme
39
+ # Determine identifier class using the module's lookup helpers
44
40
  identifier = locate_identifier_klass(data).new
45
41
  assign_attributes(identifier, data)
46
42
 
@@ -83,21 +79,23 @@ module Pubid
83
79
  # Check if publisher is actually a type code (CWA, HD, ES, CR, ENV act as publisher)
84
80
  publisher_str = parsed_hash[:publisher].to_s
85
81
  if %w[CWA HD ES CR ENV].include?(publisher_str)
86
- typed_stage = @scheme.locate_typed_stage_by_abbr(publisher_str)
87
- return @scheme.locate_identifier_klass_by_type_code(typed_stage.type_code)
82
+ typed_stage = CenCenelec.locate_stage(publisher_str)
83
+ if (klass = CenCenelec.locate_type(typed_stage.type_code))
84
+ return klass
85
+ end
88
86
  end
89
87
 
90
- # Use type or stage to determine class via Scheme
88
+ # Use type or stage to determine class via the module's registry
91
89
  type_or_stage = parsed_hash[:type_with_stage] || parsed_hash[:type] || parsed_hash[:stage] || ""
92
- typed_stage = @scheme.locate_typed_stage_by_abbr(type_or_stage)
93
- @scheme.locate_identifier_klass_by_type_code(typed_stage.type_code)
90
+ typed_stage = CenCenelec.locate_stage(type_or_stage) || CenCenelec::DEFAULT_TYPED_STAGE
91
+ CenCenelec.locate_type(typed_stage.type_code) || Identifiers::EuropeanNorm
94
92
  end
95
93
 
96
94
  def cast(type, value)
97
95
  case type
98
96
  when :type_with_stage
99
97
  # Lookup from register
100
- typed_stage = @scheme.locate_typed_stage_by_abbr(value || "")
98
+ typed_stage = CenCenelec.locate_stage(value.to_s) || CenCenelec::DEFAULT_TYPED_STAGE
101
99
  {
102
100
  stage: typed_stage.to_stage,
103
101
  type: typed_stage.to_type,
@@ -150,7 +148,7 @@ module Pubid
150
148
 
151
149
  when :stage
152
150
  # Lookup stage in TYPED_STAGES register
153
- typed_stage = @scheme.locate_typed_stage_by_abbr(value.to_s)
151
+ typed_stage = CenCenelec.locate_stage(value.to_s) || CenCenelec::DEFAULT_TYPED_STAGE
154
152
  {
155
153
  stage: typed_stage.to_stage,
156
154
  typed_stage: typed_stage,
@@ -1,52 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../components/factory"
4
-
5
3
  module Pubid
6
4
  module CenCenelec
7
- module Identifier
5
+ # Common base class for all CEN/CENELEC identifiers. CEN/CENELEC has a split
6
+ # hierarchy — some concrete types descend from Identifiers::Base, others from
7
+ # SingleIdentifier — so this class is the shared parent of BOTH, making every
8
+ # CEN/CENELEC identifier `is_a?(Pubid::CenCenelec::Identifier)` natively (and
9
+ # giving them the shared polymorphic `from_hash`). No facade needed.
10
+ class Identifier < ::Pubid::Identifier
8
11
  def self.parse(identifier)
9
- scheme = Scheme.new
12
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
13
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
14
+ end
15
+
10
16
  parsed = Parser.parse(identifier)
11
- Builder.new(scheme).build(parsed)
17
+ Builder.new.build(parsed)
12
18
  rescue Parslet::ParseFailed => e
13
19
  raise "Failed to parse CEN identifier '#{identifier}': #{e.message}"
14
20
  end
15
-
16
- # Factory mirroring pubid 1.x's `Pubid::Cen::Identifier.create` API.
17
- # Dispatches via {Pubid::CenCenelec::Scheme}'s IDENTIFIER_CLASS_MAP
18
- # and TYPED_STAGES_REGISTRY. Default is EuropeanNorm.
19
- def self.create(type: nil, stage: nil, **opts)
20
- klass = resolve_create_class(type: type, stage: stage)
21
- attrs = ::Pubid::Components::Factory.from_hash(opts)
22
- ts = resolve_create_typed_stage(klass, stage)
23
- attrs[:typed_stage] = ts if ts
24
- klass.new(**attrs)
25
- end
26
-
27
- def self.resolve_create_class(type:, stage:)
28
- scheme = Scheme.new
29
- klass = nil
30
- if type
31
- klass = scheme.locate_identifier_klass_by_type_code(type)
32
- elsif stage
33
- ts = scheme.locate_typed_stage_by_abbr(stage.to_s)
34
- klass = scheme.locate_identifier_klass_by_type_code(ts.type_code) if ts
35
- end
36
- klass || Identifiers::EuropeanNorm
37
- end
38
-
39
- def self.resolve_create_typed_stage(klass, stage)
40
- if stage
41
- Scheme.new.locate_typed_stage_by_abbr(stage.to_s)
42
- elsif klass.const_defined?(:TYPED_STAGES)
43
- klass.const_get(:TYPED_STAGES).find do |ts|
44
- ts.stage_code.to_sym == :published
45
- end
46
- end
47
- end
48
- private_class_method :resolve_create_class,
49
- :resolve_create_typed_stage
50
21
  end
51
22
  end
52
23
  end
@@ -8,10 +8,15 @@ module Pubid
8
8
  class AdoptedEuropeanNorm < EuropeanNorm
9
9
  attribute :adopted_identifier, Base, polymorphic: true # ISO/IEC/IEEE object
10
10
 
11
- def to_s
12
- result = publisher.is_a?(Array) ? publisher.join("/") : publisher.join("/")
13
- result += " #{adopted_identifier}" if adopted_identifier
14
- result
11
+ # Override self.type to return nil so that AdoptedEuropeanNorm is NOT
12
+ # registered as a type in CenCenelec.identifier_types. The class is a
13
+ # polymorphic wrapper that wraps an adopted ISO/IEC identifier under an
14
+ # EN publisher; it is constructed explicitly by Builder#build_adopted_identifier,
15
+ # not selected via type-code lookup. Returning nil here prevents
16
+ # identifier_types auto-discovery from shadowing EuropeanNorm (which
17
+ # also reports :en) in CenCenelec.locate_type(:en).
18
+ def self.type
19
+ nil
15
20
  end
16
21
 
17
22
  # Delegate common methods to adopted identifier
@@ -10,16 +10,6 @@ module Pubid
10
10
  attribute :amendment_number, :string
11
11
  attribute :amendment_year, :integer
12
12
 
13
- def to_s
14
- result = if base_identifier
15
- "#{base_identifier}/A#{amendment_number}"
16
- else
17
- "/A#{amendment_number}"
18
- end
19
- result += ":#{amendment_year}" if amendment_year
20
- result
21
- end
22
-
23
13
  def publisher
24
14
  base_identifier&.publisher
25
15
  end
@@ -3,9 +3,9 @@
3
3
  module Pubid
4
4
  module CenCenelec
5
5
  module Identifiers
6
- # Base CEN identifier
6
+ # Base CEN identifier (one of two roots; see Pubid::CenCenelec::Identifier).
7
7
  # Format: {PUBLISHER} NUMBER[-PART]:YEAR
8
- class Base < Pubid::Identifier
8
+ class Base < Pubid::CenCenelec::Identifier
9
9
  # Generate URN for this identifier
10
10
  #
11
11
  # @return [String] URN representation
@@ -20,49 +20,6 @@ module Pubid
20
20
  attribute :adopted_identifier, Base, polymorphic: true # Nested identifier object (ISO, IEC, etc.)
21
21
  attribute :edition, :string # Edition number
22
22
 
23
- def to_s
24
- result = ""
25
-
26
- # Stage or Publisher
27
- if stage
28
- result += stage
29
- elsif publisher&.any?
30
- result += publisher.join("/")
31
- end
32
-
33
- # If we have adopted_identifier, render it (contains all info)
34
- if adopted_identifier
35
- result += " #{adopted_identifier}"
36
- # Don't add our own number/parts/year - they're in adopted_identifier
37
- else
38
- # Only render our own fields if no adoption
39
- # Type - use space for Guide, slash for TR/TS
40
- if type
41
- sep = type == "Guide" ? " " : "/"
42
- result += "#{sep}#{type}"
43
- end
44
-
45
- result += " #{number}"
46
- result += parts.map { |p| "-#{p}" }.join if parts&.any?
47
- result += ":#{year}" if year
48
-
49
- # Supplements
50
- if supplements&.any?
51
- supplements.each do |supp|
52
- sep = supp[:type] == :amendment ? "/" : "+"
53
- result += "#{sep}#{supp[:type] == :amendment ? 'A' : 'AC'}"
54
- result += supp[:number] if supp[:number] && !supp[:number].empty?
55
- result += ":#{supp[:year]}" if supp[:year]
56
- end
57
- end
58
-
59
- # Edition
60
- result += " ED#{edition}" if edition
61
- end
62
-
63
- result
64
- end
65
-
66
23
  def ==(other)
67
24
  return false unless other.is_a?(Base)
68
25
 
@@ -20,7 +20,8 @@ module Pubid
20
20
  ].freeze
21
21
 
22
22
  def self.type
23
- { key: :cr, title: "CEN Report", short: "CR" }
23
+ { key: :cr,
24
+ web: :cen_report, title: "CEN Report", short: "CR" }
24
25
  end
25
26
  end
26
27
  end
@@ -19,7 +19,8 @@ module Pubid
19
19
  ].freeze
20
20
 
21
21
  def self.type
22
- { key: :cwa, title: "CEN Workshop Agreement", short: "CWA" }
22
+ { key: :cwa,
23
+ web: :cen_workshop_agreement, title: "CEN Workshop Agreement", short: "CWA" }
23
24
  end
24
25
  end
25
26
  end