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
@@ -6,16 +6,187 @@ module Pubid
6
6
  autoload :Identifier, "#{__dir__}/cen_cenelec/identifier"
7
7
  autoload :Identifiers, "#{__dir__}/cen_cenelec/identifiers"
8
8
  autoload :Parser, "#{__dir__}/cen_cenelec/parser"
9
- autoload :Scheme, "#{__dir__}/cen_cenelec/scheme"
9
+ autoload :Renderer, "#{__dir__}/cen_cenelec/renderer"
10
10
  autoload :SingleIdentifier, "#{__dir__}/cen_cenelec/single_identifier"
11
11
  autoload :SupplementIdentifier,
12
12
  "#{__dir__}/cen_cenelec/supplement_identifier"
13
13
  autoload :UrnGenerator, "#{__dir__}/cen_cenelec/urn_generator"
14
+ autoload :UrnParser, "#{__dir__}/cen_cenelec/urn_parser"
15
+
16
+ # TYPED_STAGES_REGISTRY for native CEN types
17
+ TYPED_STAGES_REGISTRY = [
18
+ # European Norm (EN)
19
+ Pubid::Components::TypedStage.new(
20
+ code: :puben,
21
+ stage_code: :published,
22
+ type_code: :en,
23
+ abbr: ["EN"],
24
+ name: "European Norm",
25
+ harmonized_stages: %w[60.00 60.60],
26
+ ),
27
+ Pubid::Components::TypedStage.new(
28
+ code: :pren,
29
+ stage_code: :proposal,
30
+ type_code: :en,
31
+ abbr: ["prEN"],
32
+ name: "Proposal European Norm",
33
+ harmonized_stages: %w[30.00 30.20 30.60 30.92 30.98 30.99],
34
+ ),
35
+ Pubid::Components::TypedStage.new(
36
+ code: :fpren,
37
+ stage_code: :final_proposal,
38
+ type_code: :en,
39
+ abbr: ["FprEN"],
40
+ name: "Final Proposal European Norm",
41
+ harmonized_stages: %w[40.00 40.20 40.60 40.92 40.98 40.99],
42
+ ),
43
+
44
+ # Technical Specification (TS)
45
+ Pubid::Components::TypedStage.new(
46
+ code: :pubts,
47
+ stage_code: :published,
48
+ type_code: :ts,
49
+ abbr: ["TS"],
50
+ name: "Technical Specification",
51
+ harmonized_stages: %w[60.00 60.60],
52
+ ),
53
+ Pubid::Components::TypedStage.new(
54
+ code: :prts,
55
+ stage_code: :proposal,
56
+ type_code: :ts,
57
+ abbr: ["prTS"],
58
+ name: "Proposal Technical Specification",
59
+ harmonized_stages: %w[30.00 30.20 30.60 30.92 30.98 30.99],
60
+ ),
61
+
62
+ # Technical Report (TR)
63
+ Pubid::Components::TypedStage.new(
64
+ code: :pubtr,
65
+ stage_code: :published,
66
+ type_code: :tr,
67
+ abbr: ["TR"],
68
+ name: "Technical Report",
69
+ harmonized_stages: %w[60.00 60.60],
70
+ ),
71
+
72
+ # CEN Workshop Agreement (CWA)
73
+ Pubid::Components::TypedStage.new(
74
+ code: :pubcwa,
75
+ stage_code: :published,
76
+ type_code: :cwa,
77
+ abbr: ["CWA"],
78
+ name: "CEN Workshop Agreement",
79
+ harmonized_stages: %w[60.00 60.60],
80
+ ),
81
+
82
+ # Guide
83
+ Pubid::Components::TypedStage.new(
84
+ code: :pubguide,
85
+ stage_code: :published,
86
+ type_code: :guide,
87
+ abbr: ["Guide"],
88
+ name: "Guide",
89
+ harmonized_stages: %w[60.00 60.60],
90
+ ),
91
+
92
+ # Harmonization Document (HD)
93
+ Pubid::Components::TypedStage.new(
94
+ code: :pubhd,
95
+ stage_code: :published,
96
+ type_code: :hd,
97
+ abbr: ["HD"],
98
+ name: "Harmonization Document",
99
+ harmonized_stages: %w[60.00 60.60],
100
+ ),
101
+
102
+ # European Specification (ES)
103
+ Pubid::Components::TypedStage.new(
104
+ code: :pubes,
105
+ stage_code: :published,
106
+ type_code: :es,
107
+ abbr: ["ES"],
108
+ name: "European Specification",
109
+ harmonized_stages: %w[60.00 60.60],
110
+ ),
111
+
112
+ # CEN Report (CR)
113
+ Pubid::Components::TypedStage.new(
114
+ code: :pubcr,
115
+ stage_code: :published,
116
+ type_code: :cr,
117
+ abbr: ["CR"],
118
+ name: "CEN Report",
119
+ harmonized_stages: %w[60.00 60.60],
120
+ ),
121
+
122
+ # European Prestandard (ENV)
123
+ Pubid::Components::TypedStage.new(
124
+ code: :pubenv,
125
+ stage_code: :published,
126
+ type_code: :env,
127
+ abbr: ["ENV"],
128
+ name: "European Prestandard",
129
+ harmonized_stages: %w[60.00 60.60],
130
+ ),
131
+ ].freeze
132
+
133
+ # Default typed stage for when no match is found
134
+ DEFAULT_TYPED_STAGE = Pubid::Components::TypedStage.new(
135
+ code: :puben,
136
+ stage_code: :published,
137
+ type_code: :en,
138
+ abbr: ["EN"],
139
+ name: "European Norm",
140
+ harmonized_stages: %w[60.00 60.60],
141
+ ).freeze
14
142
 
15
143
  def self.parse(identifier)
144
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
145
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
146
+ end
147
+
16
148
  CenCenelec::Identifier.parse(identifier)
17
149
  end
150
+
151
+ # Auto-discover all identifier types from the Identifiers namespace
152
+ # @return [Array<Class>] identifier classes that define a self.type Hash
153
+ def self.identifier_types
154
+ @identifier_types ||= Identifiers.constants
155
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
156
+ .select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
157
+ .select { |c| c.type.is_a?(Hash) }
158
+ end
159
+
160
+ # Build typed stage index from the module's TYPED_STAGES_REGISTRY
161
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
162
+ def self.all_typed_stages
163
+ TYPED_STAGES_REGISTRY
164
+ end
165
+
166
+ # Lookup: type code -> identifier class
167
+ # @param code [String, Symbol] the type key to find
168
+ # @return [Class, nil] the matching identifier class
169
+ def self.locate_type(code)
170
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
171
+ end
172
+
173
+ # Lookup: abbreviation -> typed stage
174
+ # @param abbr [String, Symbol] the abbreviation to find
175
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
176
+ def self.locate_stage(abbr)
177
+ abbr_str = abbr.to_s.upcase
178
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
179
+ end
18
180
  end
19
181
  end
20
182
 
21
183
  Pubid::Registry.register(:cen_cenelec, Pubid::CenCenelec)
184
+ Pubid::Registry.register(:cen, Pubid::CenCenelec)
185
+
186
+ # Per-flavor format registry: inherits global formats, overrides :human
187
+ # Register on both root hierarchies: SingleIdentifier and Identifiers::Base
188
+ cen_renderer = Pubid::CenCenelec::Renderer
189
+ Pubid::CenCenelec::SingleIdentifier.format_registry = Pubid::FormatRegistry.new(parent: Pubid::Identifier.format_registry)
190
+ Pubid::CenCenelec::SingleIdentifier.format_registry.register(:human, renderer: cen_renderer)
191
+ Pubid::CenCenelec::Identifiers::Base.format_registry = Pubid::FormatRegistry.new(parent: Pubid::Identifier.format_registry)
192
+ Pubid::CenCenelec::Identifiers::Base.format_registry.register(:human, renderer: cen_renderer)
@@ -7,6 +7,10 @@ module Pubid
7
7
  module Components
8
8
  # Code component for CIE identifiers
9
9
  # Handles number-part-iteration with style awareness
10
+ #
11
+ # Stays independent of Pubid::Components::Code because CIE tracks
12
+ # +style+ ("legacy" / "current") and +part_separator+ to round-trip
13
+ # slash vs dash notation, plus an +iteration+ sub-field.
10
14
  class Code < Lutaml::Model::Serializable
11
15
  attribute :number, :string # "013", "170", "198"
12
16
  attribute :part, :string # "1", "2", "3"
@@ -66,6 +70,10 @@ module Pubid
66
70
  new(number: code_str, style: style)
67
71
  end
68
72
  end
73
+
74
+ def render(context: nil)
75
+ to_s
76
+ end
69
77
  end
70
78
  end
71
79
  end
@@ -2,70 +2,23 @@
2
2
 
3
3
  module Pubid
4
4
  module Cie
5
- # Base Identifier class for CIE
6
- # Provides parse() entry point
7
- class Identifier < Lutaml::Model::Serializable
5
+ # Base Identifier class for CIE.
6
+ #
7
+ # Inherits the shared Pubid::Identifier contract (format_registry, render,
8
+ # to_urn, exclude, hash, eql?) while allowing CIE-specific attributes
9
+ # such as +style+ ("legacy" vs "current" date separator).
10
+ class Identifier < ::Pubid::Identifier
8
11
  attribute :style, :string # "legacy" or "current"
9
12
 
10
- # Parse CIE identifier string
11
13
  def self.parse(input)
14
+ if input.length > Pubid::MAX_INPUT_LENGTH
15
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
16
+ end
17
+
12
18
  parsed = Parser.parse(input)
13
19
  builder = Builder.new
14
20
  builder.build(parsed, original_string: input)
15
21
  end
16
-
17
- # Factory that builds a CIE identifier from a hash of primitives.
18
- # Dispatch on `:type` to a SingleIdentifier subclass; default is
19
- # {Identifiers::Standard}.
20
- TYPE_KEY_TO_KLASS = {
21
- standard: "Standard",
22
- conference: "Conference",
23
- bundle: "Bundle",
24
- joint_published: "JointPublished",
25
- dual_published: "DualPublished",
26
- identical: "Identical",
27
- tutorial_bundle: "TutorialBundle",
28
- }.freeze
29
-
30
- def self.create(type: nil, **opts)
31
- klass = resolve_create_class(type)
32
- klass.new(**coerce_create_attrs(opts, klass: klass))
33
- end
34
-
35
- def self.resolve_create_class(type)
36
- return Identifiers::Standard if type.nil?
37
-
38
- klass_name = TYPE_KEY_TO_KLASS[type.to_sym]
39
- raise ArgumentError, "Unknown CIE type: #{type.inspect}" unless klass_name
40
-
41
- Identifiers.const_get(klass_name)
42
- end
43
-
44
- def self.coerce_create_attrs(opts, klass:)
45
- attrs = {}
46
- attrs[:year] = opts[:year].to_s if opts[:year]
47
- attrs[:date_separator] = opts[:date_separator].to_s if opts[:date_separator]
48
-
49
- if (v = opts[:code] || opts[:number])
50
- attrs[:code] = Pubid::Cie::Components::Code.new(
51
- number: v.to_s,
52
- part: opts[:part]&.to_s,
53
- iteration: opts[:iteration]&.to_s,
54
- style: opts[:style]&.to_s,
55
- part_separator: opts[:part_separator]&.to_s,
56
- )
57
- end
58
-
59
- # Standard-only attributes
60
- if klass.attributes.key?(:s_prefix) && opts.key?(:s_prefix)
61
- attrs[:s_prefix] = opts[:s_prefix]
62
- end
63
- if klass.attributes.key?(:stage) && opts[:stage]
64
- attrs[:stage] = opts[:stage].to_s
65
- end
66
- attrs
67
- end
68
- private_class_method :resolve_create_class, :coerce_create_attrs
69
22
  end
70
23
  end
71
24
  end
@@ -18,10 +18,10 @@ module Pubid
18
18
  # - Identical (identical to ISO publications)
19
19
  # - TutorialBundle (tutorial bundles)
20
20
  class SingleIdentifier < Identifier
21
- # CIE uses a fixed publisher string
22
- def publisher
23
- "CIE"
24
- end
21
+ # Stored as a plain string (always "CIE") so it round-trips through
22
+ # to_hash/from_hash. Was a `def publisher` method, which made lutaml
23
+ # serialize a String against the Components::Publisher attribute and raise.
24
+ attribute :publisher, :string, default: -> { "CIE" }
25
25
 
26
26
  attribute :year, :string
27
27
  attribute :date_separator, :string # "dash" or "colon"
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Cie
5
+ # Parses CIE URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits:
8
+ # urn:cie:cie:{code}:{year}:sep.colon
9
+ #
10
+ # The trailing `sep.colon` token records the code/year separator used
11
+ # in the human-readable form (`:`). The leading `cie` after the
12
+ # namespace is the lowercase publisher.
13
+ #
14
+ # Examples:
15
+ # - urn:cie:cie:015:2018:sep.colon → CIE 015:2018
16
+ class UrnParser < Pubid::UrnParser::Base
17
+ def parse_urn(urn)
18
+ body = strip_namespace(urn)
19
+ parts = split_parts(body).reject { |p| p.start_with?("sep.") }
20
+
21
+ _publisher, code, year = parts
22
+ text = "CIE #{code}"
23
+ text += ":#{year}" if year
24
+ flavor_parse(text)
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/pubid/cie.rb CHANGED
@@ -11,16 +11,62 @@ module Pubid
11
11
  autoload :Identifier, "#{__dir__}/cie/identifier"
12
12
  autoload :Identifiers, "#{__dir__}/cie/identifiers"
13
13
  autoload :Parser, "#{__dir__}/cie/parser"
14
- autoload :Scheme, "#{__dir__}/cie/scheme"
15
14
  autoload :SingleIdentifier, "#{__dir__}/cie/single_identifier"
16
15
  autoload :SupplementIdentifier, "#{__dir__}/cie/supplement_identifier"
17
16
  autoload :UrnGenerator, "#{__dir__}/cie/urn_generator"
17
+ autoload :UrnParser, "#{__dir__}/cie/urn_parser"
18
18
 
19
19
  # Main entry point for CIE identifiers
20
20
  # Delegates to Identifier.parse
21
21
  def self.parse(input)
22
+ if input.length > Pubid::MAX_INPUT_LENGTH
23
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
24
+ end
25
+
22
26
  Identifier.parse(input)
23
27
  end
28
+
29
+ # Auto-discover all identifier types from the Identifiers namespace.
30
+ # CIE identifier classes extend Lutaml::Model::Serializable via
31
+ # SingleIdentifier / SupplementIdentifier, without a self.type Hash.
32
+ # We discover by checking for subclasses of those base types.
33
+ # @return [Array<Class>] identifier classes
34
+ def self.identifier_types
35
+ @identifier_types ||= Identifiers.constants
36
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
37
+ .select { |c| c.is_a?(Class) && (c < SingleIdentifier || c < SupplementIdentifier) }
38
+ end
39
+
40
+ # Build typed stage index from identifier types.
41
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
42
+ def self.all_typed_stages
43
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
44
+ if klass.const_defined?(:TYPED_STAGES)
45
+ klass.const_get(:TYPED_STAGES)
46
+ else
47
+ []
48
+ end
49
+ end
50
+ end
51
+
52
+ # Lookup: class name -> identifier class
53
+ # Since CIE lacks self.type, locate by class name suffix
54
+ # @param code [String, Symbol] the type key to find
55
+ # @return [Class, nil] the matching identifier class
56
+ def self.locate_type(code)
57
+ identifier_types.find do |t|
58
+ t.name.split("::").last.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, "") == code.to_s.downcase ||
59
+ t.name.split("::").last.downcase == code.to_s.downcase
60
+ end
61
+ end
62
+
63
+ # Lookup: abbreviation -> typed stage
64
+ # @param abbr [String, Symbol] the abbreviation to find
65
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
66
+ def self.locate_stage(abbr)
67
+ abbr_str = abbr.to_s.upcase
68
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
69
+ end
24
70
  end
25
71
  end
26
72
 
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Pubid
6
+ module Components
7
+ # Adoption component — captures the metadata when one identifier adopts
8
+ # another. Originally surfaced as BSI's AdoptedInternationalStandard /
9
+ # AdoptedEuropeanNorm and CEN-CENELEC's AdoptedEuropeanNorm; the same
10
+ # shape applies to CSA adoptions and IEEE Adopted-Standard relationships.
11
+ #
12
+ # Shape (union across BSI, CEN-CENELEC, CSA, IEEE):
13
+ # - base: the adopted document (polymorphic Identifier).
14
+ # - adopter_publisher: the publisher doing the adopting (BS, EN,
15
+ # CAN/, CSA, IEEE).
16
+ # - edition: edition of the adoption (BSI-only).
17
+ # - date: adoption date (replaces ad-hoc year attrs).
18
+ # - translation_lang: translation language code (BSI-only).
19
+ # - translation_upper: upper-case translation marker (BSI-only).
20
+ # - translation_suffix_type: "version" or "Translation" (BSI-only).
21
+ # - reaffirmation_year: "(R2004)" reaffirmation notation (BSI, CSA).
22
+ # - expert_commentary: true when the adoption ships with commentary
23
+ # (BSI-only).
24
+ # - expert_commentary_topic: topic of the commentary (BSI-only).
25
+ # - publisher_prefix: CSA-specific dash-vs-space prefix.
26
+ #
27
+ # Render delegates to the base identifier; the adopter's renderer decides
28
+ # the prefix and any suffix notation (translation, reaffirmation,
29
+ # commentary) by calling adoption.render(context:).
30
+ class Adoption < Lutaml::Model::Serializable
31
+ attribute :base, ::Pubid::Identifier, polymorphic: true
32
+ attribute :adopter_publisher, ::Pubid::Components::Publisher
33
+ attribute :edition, :string
34
+ attribute :date, ::Pubid::Components::Date
35
+ attribute :translation_lang, :string
36
+ attribute :translation_upper, :string
37
+ attribute :translation_suffix_type, :string
38
+ attribute :reaffirmation_year, :string
39
+ attribute :expert_commentary, :boolean
40
+ attribute :expert_commentary_topic, :string
41
+ attribute :publisher_prefix, :string
42
+
43
+ IDENTITY_FIELDS = %i[
44
+ base adopter_publisher edition date translation_lang translation_upper
45
+ translation_suffix_type reaffirmation_year expert_commentary
46
+ expert_commentary_topic publisher_prefix
47
+ ].freeze
48
+
49
+ def present?
50
+ IDENTITY_FIELDS.any? { |f| present_value?(public_send(f)) }
51
+ end
52
+
53
+ def render(context: nil)
54
+ return "" unless base
55
+
56
+ body = base.to_s
57
+ body += translation_suffix if translation_lang
58
+ body += reaffirmation_suffix if reaffirmation_year
59
+ body += commentary_suffix if expert_commentary
60
+ body
61
+ end
62
+
63
+ def to_s(**opts)
64
+ render(context: opts[:context])
65
+ end
66
+
67
+ def ==(other)
68
+ return false unless other.is_a?(self.class)
69
+
70
+ IDENTITY_FIELDS.all? { |f| public_send(f) == other.public_send(f) }
71
+ end
72
+
73
+ alias eql? ==
74
+
75
+ def hash
76
+ @hash ||= [self.class, *IDENTITY_FIELDS.map { |f| public_send(f) }].hash
77
+ end
78
+
79
+ private
80
+
81
+ def present_value?(value)
82
+ return false if value.nil?
83
+ return value if [true, false].include?(value)
84
+
85
+ value.is_a?(String) ? !value.empty? : !value.nil?
86
+ end
87
+
88
+ def translation_suffix
89
+ type = translation_suffix_type || "Translation"
90
+ lang = translation_lang&.upcase
91
+ " #{lang}#{type}"
92
+ end
93
+
94
+ def reaffirmation_suffix
95
+ " (R#{reaffirmation_year})"
96
+ end
97
+
98
+ def commentary_suffix
99
+ topic = expert_commentary_topic
100
+ topic ? " (Commentary: #{topic})" : " (Commentary)"
101
+ end
102
+ end
103
+ end
104
+ end
@@ -2,32 +2,46 @@
2
2
 
3
3
  module Pubid
4
4
  module Components
5
+ # Document code/number component.
6
+ #
7
+ # Holds the structured fields that recur across flavors: the main +value+
8
+ # (always present), plus optional +prefix+ (series/type designator),
9
+ # +part+, +subpart+, and free-form +parts+. Subclasses own their
10
+ # composition rules — flavor-specific separators and orderings live in
11
+ # the subclass #to_s / #render override.
5
12
  class Code < Lutaml::Model::Serializable
6
13
  attribute :value, :string
14
+ attribute :prefix, :string
15
+ attribute :part, :string
16
+ attribute :subpart, :string
17
+ attribute :parts, :string, collection: true
7
18
 
8
19
  def to_s
9
20
  value.to_s
10
21
  end
11
22
 
23
+ # Format-aware render seam. Default returns the bare value; subclasses
24
+ # override to compose flavor-specific shapes (e.g. ISO joins parts
25
+ # with "-", NIST joins subpart with ".").
12
26
  def render(context: nil)
13
27
  value.to_s
14
28
  end
15
29
 
16
- # Returns hash code for code component
17
- # @return [Integer] hash code
18
- # @note Memoized for performance
19
30
  def hash
20
- @hash ||= value.hash
31
+ [value, prefix, part, subpart, parts].hash
21
32
  end
22
33
 
23
- # Checks equality with another code component
24
- # @param other [Object] object to compare with
25
- # @return [Boolean] true if equal
34
+ # rubocop:disable Metrics/AbcSize
26
35
  def eql?(other)
27
36
  return false unless other.is_a?(self.class)
28
37
 
29
- value == other.value
38
+ value == other.value &&
39
+ prefix == other.prefix &&
40
+ part == other.part &&
41
+ subpart == other.subpart &&
42
+ parts == other.parts
30
43
  end
44
+ # rubocop:enable Metrics/AbcSize
31
45
  end
32
46
  end
33
47
  end
@@ -5,40 +5,47 @@ require "lutaml/model"
5
5
  module Pubid
6
6
  module Components
7
7
  # Publication date component
8
+ #
9
+ # Human render: "YYYY" or "YYYY-MM" or "YYYY-MM-DD".
10
+ # URN render: year only (RFC 5141-bis URN spec).
8
11
  class Date < Lutaml::Model::Serializable
9
12
  attribute :year, :string
10
13
  attribute :month, :string
11
14
  attribute :day, :string
12
15
 
13
- # Render date with optional context for flavor-specific formatting
14
- #
15
- # @param _context [RenderingContext] rendering context
16
- # (for future extensibility)
17
- # @param _include_month [Boolean] include month in output
18
- # (for future extensibility)
19
- # @return [String] rendered date string
16
+ # True when the year is set to a non-empty value.
17
+ def present?
18
+ !year.nil? && !year.to_s.empty?
19
+ end
20
+
20
21
  def render(context: nil)
21
- to_s
22
+ return nil unless present?
23
+ return year.to_s if context&.urn?
24
+ return year.to_s unless month
25
+
26
+ result = "#{year}-#{pad2(month)}"
27
+ result += "-#{pad2(day)}" if day
28
+ result
22
29
  end
23
30
 
24
31
  def to_s(_context: nil, _include_month: false)
25
32
  return year.to_s unless month
26
33
 
27
- result = "#{year}-#{month}"
28
- result += "-#{day}" if day
34
+ result = "#{year}-#{pad2(month)}"
35
+ result += "-#{pad2(day)}" if day
29
36
  result
30
37
  end
31
38
 
32
- # Returns hash code for date component
33
- # @return [Integer] hash code
34
- # @note Memoized for performance
39
+ private
40
+
41
+ def pad2(value)
42
+ value.to_s.rjust(2, "0")
43
+ end
44
+
35
45
  def hash
36
46
  @hash ||= [year, month, day].compact.map(&:hash).hash
37
47
  end
38
48
 
39
- # Checks equality with another date component
40
- # @param other [Object] object to compare with
41
- # @return [Boolean] true if equal
42
49
  def eql?(other)
43
50
  return false unless other.is_a?(self.class)
44
51
 
@@ -3,27 +3,30 @@
3
3
  module Pubid
4
4
  module Components
5
5
  # Edition component (typically a year and number)
6
+ #
7
+ # Human render: "ED#{number}".
8
+ # URN render: "ed-#{number}" per RFC 5141-bis.
6
9
  class Edition < Lutaml::Model::Serializable
7
10
  attribute :year, :string
8
- attribute :number, Lutaml::Model::Type::Value # Accept any value type
9
- attribute :original_text, :string # Store the exact parsed edition text
11
+ attribute :number, Lutaml::Model::Type::Value
12
+ attribute :original_text, :string
10
13
 
11
14
  def to_s
12
- # Always use canonical format for rendering
13
15
  number_value = number.is_a?(Components::Code) ? number.value : number
14
16
  number_value ? "ED#{number_value}" : nil
15
17
  end
16
18
 
17
- # V1 API compatibility - tests expect .value on edition itself
18
19
  def value
19
20
  number.is_a?(Components::Code) ? number.value : number
20
21
  end
21
22
 
22
23
  def render(context: nil)
23
- to_s
24
+ number_value = number.is_a?(Components::Code) ? number.value : number
25
+ return nil unless number_value
26
+
27
+ context&.urn? ? "ed-#{number_value}" : "ED#{number_value}"
24
28
  end
25
29
 
26
- # Method to get the original parsed format if needed
27
30
  def original_format
28
31
  original_text
29
32
  end