pubid 2.0.0.pre.alpha.2 → 2.0.0.pre.alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (458) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +25 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -39
  6. data/lib/pubid/amca/identifiers/base.rb +0 -26
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -17
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -13
  9. data/lib/pubid/amca/renderer.rb +82 -0
  10. data/lib/pubid/amca/single_identifier.rb +0 -23
  11. data/lib/pubid/amca/urn_parser.rb +28 -0
  12. data/lib/pubid/amca.rb +42 -1
  13. data/lib/pubid/ansi/builder.rb +5 -3
  14. data/lib/pubid/ansi/identifier.rb +1 -43
  15. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  16. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  17. data/lib/pubid/ansi/renderer.rb +53 -0
  18. data/lib/pubid/ansi/single_identifier.rb +2 -31
  19. data/lib/pubid/ansi/urn_generator.rb +3 -38
  20. data/lib/pubid/ansi/urn_parser.rb +23 -0
  21. data/lib/pubid/ansi.rb +38 -3
  22. data/lib/pubid/api/builder.rb +29 -74
  23. data/lib/pubid/api/identifier.rb +0 -51
  24. data/lib/pubid/api/identifiers/base.rb +0 -2
  25. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  26. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  27. data/lib/pubid/api/identifiers/mpms.rb +1 -17
  28. data/lib/pubid/api/identifiers/publication.rb +0 -2
  29. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  30. data/lib/pubid/api/identifiers/specification.rb +0 -2
  31. data/lib/pubid/api/identifiers/standard.rb +0 -2
  32. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  33. data/lib/pubid/api/identifiers/typeless_standard.rb +1 -14
  34. data/lib/pubid/api/identifiers.rb +18 -0
  35. data/lib/pubid/api/renderer.rb +89 -0
  36. data/lib/pubid/api/single_identifier.rb +1 -13
  37. data/lib/pubid/api/urn_generator.rb +0 -18
  38. data/lib/pubid/api/urn_parser.rb +35 -0
  39. data/lib/pubid/api.rb +51 -5
  40. data/lib/pubid/ashrae/builder.rb +3 -3
  41. data/lib/pubid/ashrae/identifier.rb +6 -39
  42. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  43. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  44. data/lib/pubid/ashrae/identifiers/base.rb +3 -0
  45. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  46. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  47. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  48. data/lib/pubid/ashrae/renderer.rb +117 -0
  49. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  50. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  51. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  52. data/lib/pubid/ashrae.rb +42 -1
  53. data/lib/pubid/asme/components/code.rb +10 -2
  54. data/lib/pubid/asme/identifier.rb +0 -46
  55. data/lib/pubid/asme/identifiers/base.rb +0 -60
  56. data/lib/pubid/asme/renderer.rb +66 -0
  57. data/lib/pubid/asme/urn_parser.rb +31 -0
  58. data/lib/pubid/asme.rb +42 -1
  59. data/lib/pubid/astm/components/code.rb +9 -0
  60. data/lib/pubid/{jis → astm}/components.rb +1 -1
  61. data/lib/pubid/astm/identifier.rb +0 -77
  62. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  63. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  64. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  65. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  66. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  67. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  68. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  69. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  70. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  71. data/lib/pubid/astm/identifiers.rb +18 -0
  72. data/lib/pubid/astm/renderer.rb +172 -0
  73. data/lib/pubid/astm/single_identifier.rb +0 -10
  74. data/lib/pubid/astm/urn_parser.rb +30 -0
  75. data/lib/pubid/astm.rb +39 -27
  76. data/lib/pubid/bsi/builder.rb +21 -12
  77. data/lib/pubid/bsi/identifier.rb +8 -62
  78. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  79. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  80. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  81. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  82. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  83. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  84. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  85. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  87. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  88. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  89. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  90. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  91. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  92. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  93. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  94. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  95. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  96. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  97. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  98. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  99. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  100. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  101. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  102. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  103. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  104. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  105. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  106. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  107. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  108. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  109. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  110. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  111. data/lib/pubid/bsi/identifiers.rb +0 -1
  112. data/lib/pubid/bsi/renderer.rb +1050 -0
  113. data/lib/pubid/bsi/single_identifier.rb +6 -70
  114. data/lib/pubid/bsi/urn_generator.rb +2 -3
  115. data/lib/pubid/bsi/urn_parser.rb +52 -0
  116. data/lib/pubid/bsi.rb +224 -1
  117. data/lib/pubid/builder/base.rb +57 -10
  118. data/lib/pubid/bundled_identifier.rb +0 -1
  119. data/lib/pubid/ccsds/builder.rb +4 -3
  120. data/lib/pubid/ccsds/identifier.rb +63 -66
  121. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  122. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  123. data/lib/pubid/ccsds/parser.rb +4 -2
  124. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  125. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  126. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  127. data/lib/pubid/ccsds.rb +39 -1
  128. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  129. data/lib/pubid/cen_cenelec/identifier.rb +7 -38
  130. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  131. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  132. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  133. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  135. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  136. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  137. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  139. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  140. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  141. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  143. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  145. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  146. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  147. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  148. data/lib/pubid/cen_cenelec.rb +168 -1
  149. data/lib/pubid/cie/components/code.rb +8 -0
  150. data/lib/pubid/cie/identifier.rb +6 -57
  151. data/lib/pubid/cie/urn_parser.rb +28 -0
  152. data/lib/pubid/cie.rb +43 -1
  153. data/lib/pubid/components/adoption.rb +104 -0
  154. data/lib/pubid/components/code.rb +22 -8
  155. data/lib/pubid/components/date.rb +23 -16
  156. data/lib/pubid/components/edition.rb +9 -6
  157. data/lib/pubid/components/iteration.rb +32 -0
  158. data/lib/pubid/components/language.rb +6 -4
  159. data/lib/pubid/components/locality.rb +10 -1
  160. data/lib/pubid/components/publisher.rb +9 -6
  161. data/lib/pubid/components/relationship.rb +151 -0
  162. data/lib/pubid/components/stage.rb +5 -14
  163. data/lib/pubid/components/supplement.rb +184 -0
  164. data/lib/pubid/components/type.rb +5 -15
  165. data/lib/pubid/components/typed_stage.rb +10 -11
  166. data/lib/pubid/components.rb +4 -1
  167. data/lib/pubid/core/update_codes.rb +28 -7
  168. data/lib/pubid/csa/identifier.rb +0 -59
  169. data/lib/pubid/csa/identifiers/base.rb +2 -122
  170. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  171. data/lib/pubid/csa/identifiers/series.rb +2 -102
  172. data/lib/pubid/csa/renderer.rb +292 -0
  173. data/lib/pubid/csa/urn_generator.rb +1 -1
  174. data/lib/pubid/csa/urn_parser.rb +33 -0
  175. data/lib/pubid/csa.rb +42 -1
  176. data/lib/pubid/etsi/components/code.rb +9 -2
  177. data/lib/pubid/etsi/identifier.rb +0 -43
  178. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  179. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  180. data/lib/pubid/etsi/renderer.rb +42 -0
  181. data/lib/pubid/etsi/urn_parser.rb +34 -0
  182. data/lib/pubid/etsi.rb +42 -1
  183. data/lib/pubid/export/exporter.rb +4 -46
  184. data/lib/pubid/export/flavor_exporter.rb +111 -278
  185. data/lib/pubid/export.rb +0 -6
  186. data/lib/pubid/identifier.rb +2 -17
  187. data/lib/pubid/identifier_facade.rb +114 -0
  188. data/lib/pubid/identifier_metadata.rb +1 -1
  189. data/lib/pubid/idf/builder.rb +3 -3
  190. data/lib/pubid/idf/identifier.rb +3 -66
  191. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  192. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  193. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  194. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  195. data/lib/pubid/idf/parser.rb +3 -2
  196. data/lib/pubid/idf/renderer.rb +84 -0
  197. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  198. data/lib/pubid/idf/urn_generator.rb +4 -39
  199. data/lib/pubid/idf/urn_parser.rb +25 -0
  200. data/lib/pubid/idf.rb +51 -1
  201. data/lib/pubid/iec/builder.rb +46 -64
  202. data/lib/pubid/iec/components/code.rb +8 -32
  203. data/lib/pubid/iec/components/publisher.rb +0 -1
  204. data/lib/pubid/iec/components.rb +14 -0
  205. data/lib/pubid/iec/identifier.rb +251 -213
  206. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  207. data/lib/pubid/iec/identifiers/base.rb +8 -32
  208. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  209. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  210. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -26
  211. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  212. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -22
  213. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  214. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  215. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  216. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  217. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  218. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -11
  219. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  220. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  222. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  223. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  224. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  225. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -19
  226. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  227. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  228. data/lib/pubid/iec/identifiers.rb +30 -0
  229. data/lib/pubid/iec/parser.rb +13 -12
  230. data/lib/pubid/iec/renderer.rb +254 -0
  231. data/lib/pubid/iec/single_identifier.rb +6 -12
  232. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  233. data/lib/pubid/iec/urn_generator.rb +3 -3
  234. data/lib/pubid/iec/urn_parser.rb +3 -3
  235. data/lib/pubid/iec.rb +40 -68
  236. data/lib/pubid/ieee/builder.rb +12 -12
  237. data/lib/pubid/ieee/components/code.rb +8 -0
  238. data/lib/pubid/ieee/components/draft.rb +14 -0
  239. data/lib/pubid/ieee/components/relationship.rb +5 -149
  240. data/lib/pubid/ieee/identifier.rb +6 -41
  241. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  242. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  243. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  245. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  246. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  247. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  248. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  249. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  250. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  251. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  252. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  253. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  254. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  255. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  256. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  257. data/lib/pubid/ieee/pre_parser.rb +301 -0
  258. data/lib/pubid/ieee/renderer.rb +307 -0
  259. data/lib/pubid/ieee/urn_parser.rb +34 -0
  260. data/lib/pubid/ieee.rb +62 -1
  261. data/lib/pubid/ieee_debug.rb +0 -1
  262. data/lib/pubid/iho/builder.rb +2 -2
  263. data/lib/pubid/iho/identifier.rb +8 -42
  264. data/lib/pubid/iho/identifiers/base.rb +49 -10
  265. data/lib/pubid/iho/parser.rb +3 -3
  266. data/lib/pubid/iho/renderer.rb +30 -0
  267. data/lib/pubid/iho/urn_generator.rb +2 -2
  268. data/lib/pubid/iho/urn_parser.rb +58 -0
  269. data/lib/pubid/iho.rb +50 -1
  270. data/lib/pubid/iso/builder.rb +55 -53
  271. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  272. data/lib/pubid/iso/components/code.rb +7 -19
  273. data/lib/pubid/iso/components/publisher.rb +10 -8
  274. data/lib/pubid/iso/components.rb +2 -4
  275. data/lib/pubid/iso/identifier.rb +218 -252
  276. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  277. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  278. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  279. data/lib/pubid/iso/identifiers/data.rb +0 -1
  280. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  281. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  282. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  283. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  284. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  285. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  286. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  287. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  288. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  289. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  290. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  291. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  292. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  293. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  294. data/lib/pubid/iso/identifiers.rb +0 -1
  295. data/lib/pubid/iso/normalizer.rb +89 -0
  296. data/lib/pubid/iso/parser.rb +22 -4
  297. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  298. data/lib/pubid/iso/urn_generator.rb +66 -182
  299. data/lib/pubid/iso/urn_parser.rb +12 -7
  300. data/lib/pubid/iso.rb +173 -2
  301. data/lib/pubid/itu/builder.rb +0 -12
  302. data/lib/pubid/itu/components/code.rb +8 -0
  303. data/lib/pubid/itu/components.rb +11 -0
  304. data/lib/pubid/itu/identifier.rb +6 -104
  305. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  306. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  307. data/lib/pubid/itu/identifiers/base.rb +0 -6
  308. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  309. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  310. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  311. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  312. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  313. data/lib/pubid/itu/urn_parser.rb +23 -0
  314. data/lib/pubid/itu.rb +42 -1
  315. data/lib/pubid/jcgm/builder.rb +16 -8
  316. data/lib/pubid/jcgm/identifier.rb +0 -43
  317. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  318. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  319. data/lib/pubid/jcgm/renderer.rb +68 -0
  320. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  321. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  322. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  323. data/lib/pubid/jcgm.rb +43 -2
  324. data/lib/pubid/jis/builder.rb +44 -52
  325. data/lib/pubid/jis/identifier.rb +132 -46
  326. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  327. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  328. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  329. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  330. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  331. data/lib/pubid/jis/identifiers.rb +1 -1
  332. data/lib/pubid/jis/parser.rb +31 -5
  333. data/lib/pubid/jis/renderer.rb +69 -0
  334. data/lib/pubid/jis/single_identifier.rb +6 -12
  335. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  336. data/lib/pubid/jis/urn_parser.rb +23 -0
  337. data/lib/pubid/jis.rb +42 -2
  338. data/lib/pubid/nist/builder.rb +63 -1871
  339. data/lib/pubid/nist/caster.rb +1272 -0
  340. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  341. data/lib/pubid/nist/components/code.rb +9 -20
  342. data/lib/pubid/nist/components/supplement.rb +2 -2
  343. data/lib/pubid/nist/components.rb +0 -1
  344. data/lib/pubid/nist/identifier.rb +11 -48
  345. data/lib/pubid/nist/identifiers/base.rb +110 -47
  346. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  347. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  348. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  349. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  350. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  351. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  352. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  353. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  354. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  355. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  356. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  357. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  358. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  359. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  360. data/lib/pubid/nist/identifiers/report.rb +4 -2
  361. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  362. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  363. data/lib/pubid/nist/identifiers.rb +1 -0
  364. data/lib/pubid/nist/parser.rb +62 -452
  365. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  366. data/lib/pubid/nist/preprocessor.rb +416 -0
  367. data/lib/pubid/nist/renderer.rb +43 -0
  368. data/lib/pubid/nist/router.rb +148 -0
  369. data/lib/pubid/nist/series/base.rb +58 -0
  370. data/lib/pubid/nist/series/crpl.rb +13 -0
  371. data/lib/pubid/nist/series/fips.rb +14 -0
  372. data/lib/pubid/nist/series/ir.rb +60 -0
  373. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  374. data/lib/pubid/nist/series/mono.rb +19 -0
  375. data/lib/pubid/nist/series/ncstar.rb +20 -0
  376. data/lib/pubid/nist/series.rb +49 -0
  377. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  378. data/lib/pubid/nist/urn_parser.rb +67 -0
  379. data/lib/pubid/nist.rb +82 -4
  380. data/lib/pubid/oiml/components/code.rb +10 -0
  381. data/lib/pubid/oiml/identifier.rb +0 -50
  382. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  383. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  384. data/lib/pubid/oiml/renderer.rb +161 -0
  385. data/lib/pubid/oiml/single_identifier.rb +6 -45
  386. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  387. data/lib/pubid/oiml/urn_generator.rb +0 -8
  388. data/lib/pubid/oiml/urn_parser.rb +22 -0
  389. data/lib/pubid/oiml.rb +42 -1
  390. data/lib/pubid/plateau/identifier.rb +7 -41
  391. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  392. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  393. data/lib/pubid/plateau/renderer.rb +51 -0
  394. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  395. data/lib/pubid/plateau/urn_parser.rb +43 -0
  396. data/lib/pubid/plateau.rb +43 -1
  397. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  398. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  399. data/lib/pubid/renderers/human_readable.rb +18 -7
  400. data/lib/pubid/rendering/context.rb +28 -19
  401. data/lib/pubid/rendering.rb +0 -3
  402. data/lib/pubid/sae/components/date.rb +8 -0
  403. data/lib/pubid/sae/components/type.rb +5 -1
  404. data/lib/pubid/sae/identifier.rb +0 -23
  405. data/lib/pubid/sae/identifiers/base.rb +2 -16
  406. data/lib/pubid/sae/renderer.rb +36 -0
  407. data/lib/pubid/sae/urn_generator.rb +2 -10
  408. data/lib/pubid/sae/urn_parser.rb +36 -0
  409. data/lib/pubid/sae.rb +42 -1
  410. data/lib/pubid/urn_generator/base.rb +12 -12
  411. data/lib/pubid/urn_parser/base.rb +81 -0
  412. data/lib/pubid/urn_parser/errors.rb +9 -0
  413. data/lib/pubid/urn_parser.rb +14 -0
  414. data/lib/pubid/version.rb +1 -1
  415. data/lib/pubid.rb +29 -7
  416. data/lib/tasks/website-data.json +1940 -1882
  417. metadata +75 -44
  418. data/lib/pubid/amca/scheme.rb +0 -16
  419. data/lib/pubid/ansi/scheme.rb +0 -15
  420. data/lib/pubid/api/scheme.rb +0 -66
  421. data/lib/pubid/ashrae/scheme.rb +0 -53
  422. data/lib/pubid/asme/scheme.rb +0 -37
  423. data/lib/pubid/astm/scheme.rb +0 -55
  424. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  425. data/lib/pubid/bsi/scheme.rb +0 -243
  426. data/lib/pubid/ccsds/scheme.rb +0 -57
  427. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  428. data/lib/pubid/cie/scheme.rb +0 -64
  429. data/lib/pubid/components/factory.rb +0 -50
  430. data/lib/pubid/csa/scheme.rb +0 -44
  431. data/lib/pubid/etsi/scheme.rb +0 -42
  432. data/lib/pubid/export/data_class_exporter.rb +0 -59
  433. data/lib/pubid/export/ieee_exporter.rb +0 -78
  434. data/lib/pubid/export/itu_exporter.rb +0 -66
  435. data/lib/pubid/export/nist_exporter.rb +0 -64
  436. data/lib/pubid/export/registry_exporter.rb +0 -90
  437. data/lib/pubid/export/scheme_exporter.rb +0 -70
  438. data/lib/pubid/identifier_registry.rb +0 -198
  439. data/lib/pubid/idf/scheme.rb +0 -61
  440. data/lib/pubid/iec/scheme.rb +0 -71
  441. data/lib/pubid/ieee/scheme.rb +0 -90
  442. data/lib/pubid/iho/scheme.rb +0 -29
  443. data/lib/pubid/iso/identifiers/base.rb +0 -115
  444. data/lib/pubid/iso/scheme.rb +0 -193
  445. data/lib/pubid/itu/scheme.rb +0 -174
  446. data/lib/pubid/jcgm/scheme.rb +0 -60
  447. data/lib/pubid/jis/components/code.rb +0 -59
  448. data/lib/pubid/jis/identifiers/base.rb +0 -72
  449. data/lib/pubid/jis/scheme.rb +0 -49
  450. data/lib/pubid/nist/components/publisher.rb +0 -24
  451. data/lib/pubid/nist/scheme.rb +0 -199
  452. data/lib/pubid/oiml/scheme.rb +0 -46
  453. data/lib/pubid/plateau/scheme.rb +0 -45
  454. data/lib/pubid/rendering/base.rb +0 -73
  455. data/lib/pubid/rendering/common.rb +0 -211
  456. data/lib/pubid/rendering/format.rb +0 -25
  457. data/lib/pubid/sae/scheme.rb +0 -47
  458. data/lib/pubid/scheme.rb +0 -219
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Iec
5
+ module Identifiers
6
+ autoload :Amendment, "#{__dir__}/identifiers/amendment"
7
+ autoload :Base, "#{__dir__}/identifiers/base"
8
+ autoload :ComponentSpecification, "#{__dir__}/identifiers/component_specification"
9
+ autoload :ConformityAssessment, "#{__dir__}/identifiers/conformity_assessment"
10
+ autoload :ConsolidatedIdentifier, "#{__dir__}/identifiers/consolidated_identifier"
11
+ autoload :Corrigendum, "#{__dir__}/identifiers/corrigendum"
12
+ autoload :FragmentIdentifier, "#{__dir__}/identifiers/fragment_identifier"
13
+ autoload :Guide, "#{__dir__}/identifiers/guide"
14
+ autoload :InternationalStandard, "#{__dir__}/identifiers/international_standard"
15
+ autoload :InterpretationSheet, "#{__dir__}/identifiers/interpretation_sheet"
16
+ autoload :OperationalDocument, "#{__dir__}/identifiers/operational_document"
17
+ autoload :PubliclyAvailableSpecification, "#{__dir__}/identifiers/publicly_available_specification"
18
+ autoload :SheetIdentifier, "#{__dir__}/identifiers/sheet_identifier"
19
+ autoload :SocietalTechnologyTrendReport, "#{__dir__}/identifiers/societal_technology_trend_report"
20
+ autoload :SystemsReferenceDocument, "#{__dir__}/identifiers/systems_reference_document"
21
+ autoload :TechnicalReport, "#{__dir__}/identifiers/technical_report"
22
+ autoload :TechnicalSpecification, "#{__dir__}/identifiers/technical_specification"
23
+ autoload :TechnologyReport, "#{__dir__}/identifiers/technology_report"
24
+ autoload :TestReportForm, "#{__dir__}/identifiers/test_report_form"
25
+ autoload :VapIdentifier, "#{__dir__}/identifiers/vap_identifier"
26
+ autoload :WhitePaper, "#{__dir__}/identifiers/white_paper"
27
+ autoload :WorkingDocument, "#{__dir__}/identifiers/working_document"
28
+ end
29
+ end
30
+ end
@@ -1,9 +1,5 @@
1
1
  require "parslet"
2
2
  # frozen_string_literal: true
3
- require_relative "../parser/common_parse_rules"
4
- require_relative "../parser/common_parse_methods"
5
- require_relative "identifier"
6
- require_relative "supplement_identifier"
7
3
 
8
4
  module Pubid
9
5
  module Iec
@@ -14,10 +10,9 @@ module Pubid
14
10
  DASH_CHARS = ["-", "‑", "‐"].freeze
15
11
 
16
12
  # We need to sort by length to match longest first because that's how Parslet works
17
- TYPED_STAGES = Pubid::Iec::Scheme.typed_stages
18
- .map(&:abbr).flatten.sort_by(&:length).reverse
19
- TYPED_STAGES_SUPPLEMENTS = Pubid::Iec::Scheme.supplement_typed_stages
13
+ TYPED_STAGES = Pubid::Iec.all_typed_stages
20
14
  .map(&:abbr).flatten.sort_by(&:length).reverse
15
+ TYPED_STAGES_SUPPLEMENTS = TYPED_STAGES
21
16
 
22
17
  root :identifier
23
18
 
@@ -277,16 +272,22 @@ module Pubid
277
272
  # EXV = Example version
278
273
  # PAC = Package
279
274
  # PRV = Preview version
280
- rule(:vap_suffix) do
281
- space >> (
282
- str("CSV") |
275
+ # Internal helper (no `.as`): a single VAP code. The capture key stays
276
+ # :vap_suffix below; this rule just lets the suffix be one or more codes.
277
+ rule(:vap_code) do
278
+ str("CSV") |
283
279
  str("CMV") |
284
280
  str("RLV") |
285
281
  str("SER") |
286
282
  str("EXV") |
287
283
  str("PAC") |
288
284
  str("PRV")
289
- ).as(:vap_suffix)
285
+ end
286
+
287
+ # One or more VAP codes joined by "-", captured whole, e.g. "CSV" or
288
+ # "EXV-CMV"; the builder splits it into the VapIdentifier `vap` array.
289
+ rule(:vap_suffix) do
290
+ space >> (vap_code >> (str("-") >> vap_code).repeat).as(:vap_suffix)
290
291
  end
291
292
 
292
293
  # Database suffix: " DB"
@@ -358,7 +359,7 @@ module Pubid
358
359
  end
359
360
 
360
361
  rule(:iso_identifier) do
361
- Iso::Parser.new.identifier
362
+ Pubid::Iso.joint_grammar_atom(:identifier)
362
363
  end
363
364
 
364
365
  rule(:supplement_type_with_stage) do
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Iec
5
+ # Human-readable renderer for IEC identifiers.
6
+ #
7
+ # Components are accessed only through `component.render(context:)`.
8
+ #
9
+ # Produces strings like:
10
+ # "IEC 60038:2009"
11
+ # "IEC/CD 60038"
12
+ # "IEC 60038:2009/AMD1:2011"
13
+ # "IEC/FDAM 60038-1"
14
+ # "IEC 60529:1989+AMD1:1999 CSV"
15
+ #
16
+ # The renderer is registered as the `:human` format in the IEC format
17
+ # registry and invoked via `render(format: :human)`.
18
+ #
19
+ # For simple (non-wrapper) identifiers, the renderer delegates to the
20
+ # identifier's own `publisher_portion` / `number_portion` helpers so that
21
+ # per-type overrides (e.g. TR, TS, Guide) continue to work without
22
+ # duplication. Wrapper types (Consolidated, VAP, Sheet, Fragment,
23
+ # Supplement, WorkingDocument, TestReportForm) have rendering logic
24
+ # here because their structure differs fundamentally.
25
+ class Renderer < ::Pubid::Renderers::Base
26
+ def render(context: nil, **opts)
27
+ id = @id
28
+
29
+ case id
30
+ when Identifiers::ConsolidatedIdentifier
31
+ render_consolidated(id, opts, context)
32
+ when Identifiers::VapIdentifier
33
+ render_vap(id, opts, context)
34
+ when Identifiers::SheetIdentifier
35
+ render_sheet(id, opts, context)
36
+ when Identifiers::FragmentIdentifier
37
+ render_fragment(id, opts, context)
38
+ when Identifiers::WorkingDocument
39
+ render_working_document(id, context)
40
+ when Identifiers::TestReportForm
41
+ render_test_report_form(id, context)
42
+ when SupplementIdentifier
43
+ render_supplement(id, opts, context)
44
+ else
45
+ render_single(id, opts, context)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def render_single(id, opts, context)
52
+ parts = []
53
+ parts << id.publisher_portion
54
+ parts << id.number_portion
55
+
56
+ if id.is_a?(Identifiers::Base)
57
+ parts << " #{id.edition.render(context:)}" if id.edition&.number
58
+ elsif opts[:with_edition] && id.edition&.number
59
+ parts << " #{id.edition.render(context:)}"
60
+ end
61
+
62
+ # VAP codes live on VapIdentifier (rendered in render_vap), not Base.
63
+
64
+ if id.is_a?(Identifiers::Base) && id.database
65
+ parts << " DB"
66
+ end
67
+
68
+ parts << " (all parts)" if id.all_parts
69
+
70
+ result = parts.compact.join
71
+
72
+ result << id.language_portion(lang_single: opts[:lang_single]) if id.languages&.any?
73
+
74
+ result
75
+ end
76
+
77
+ def render_supplement(id, opts, context)
78
+ id.ensure_base_identifier
79
+
80
+ if id.synthetic_base?
81
+ render_supplement_standalone(id, context)
82
+ elsif id.base_identifier
83
+ render_supplement_attached(id, opts, context)
84
+ else
85
+ render_single(id, opts, context)
86
+ end
87
+ end
88
+
89
+ def render_supplement_standalone(id, context)
90
+ parts = []
91
+
92
+ if id.publisher
93
+ parts << id.publisher.render(context:)
94
+ if id.copublishers&.any?
95
+ parts << "/#{id.copublishers.map { |c| c.render(context:) }.join('/')}"
96
+ end
97
+ end
98
+
99
+ abbr = id.typed_stage.abbr.first
100
+ number_str = id.base_identifier.number.to_s
101
+ number_str += "-#{id.number}" if id.number
102
+ number_str += "-#{id.subpart}" if id.subpart
103
+ parts << "#{abbr} #{number_str}"
104
+
105
+ result = parts.join("/")
106
+ result += ":#{id.date.render(context:)}" if id.date
107
+ result += " #{id.edition.render(context:)}" if id.edition&.number
108
+ result
109
+ end
110
+
111
+ def render_supplement_attached(id, opts, context)
112
+ parts = []
113
+ parts << id.base_identifier.to_s(**opts)
114
+
115
+ abbr = id.typed_stage.abbr.first.upcase
116
+ supp_part = "/#{abbr}#{id.number}"
117
+ supp_part += ":#{id.date.render(context:)}" if id.date
118
+ parts << supp_part
119
+
120
+ parts << " #{id.edition.render(context:)}" if id.edition&.number
121
+
122
+ parts.join
123
+ end
124
+
125
+ def render_consolidated(id, opts, _context)
126
+ id.identifiers.map.with_index do |sub_id, idx|
127
+ if idx.zero?
128
+ sub_id.to_s(**opts)
129
+ elsif sub_id.is_a?(Identifiers::Amendment)
130
+ render_consolidated_amendment(sub_id)
131
+ elsif sub_id.is_a?(Identifiers::Corrigendum)
132
+ render_consolidated_corrigendum(sub_id)
133
+ else
134
+ "+#{sub_id.to_s(**opts)}"
135
+ end
136
+ end.join
137
+ end
138
+
139
+ def render_consolidated_amendment(id)
140
+ if id.date&.present?
141
+ "+AMD#{id.number}:#{id.date.render}"
142
+ else
143
+ "+AMD#{id.number}"
144
+ end
145
+ end
146
+
147
+ def render_consolidated_corrigendum(id)
148
+ if id.date&.present?
149
+ "+COR#{id.number}:#{id.date.render}"
150
+ else
151
+ "+COR#{id.number}"
152
+ end
153
+ end
154
+
155
+ def render_vap(id, opts, context)
156
+ parts = []
157
+
158
+ parts << id.base_identifier.to_s(**opts.merge(with_edition: false))
159
+ parts << " #{id.vap.join('-')}" if id.vap&.any?
160
+ parts << " #{id.edition.render(context:)}" if id.edition&.number
161
+
162
+ parts.compact.join
163
+ end
164
+
165
+ def render_sheet(id, opts, context)
166
+ parts = []
167
+ parts << id.base_identifier.to_s(**opts)
168
+ parts << "/#{id.sheet_number}"
169
+ parts << ":#{id.year}" if id.year
170
+ parts.join
171
+ end
172
+
173
+ def render_fragment(id, opts, context)
174
+ parts = []
175
+ parts << id.base_identifier.to_s(**opts)
176
+
177
+ parts << if id.base_identifier.is_a?(Identifiers::Corrigendum)
178
+ "/FRAGC#{id.fragment_number}"
179
+ else
180
+ "/FRAG#{id.fragment_number}"
181
+ end
182
+
183
+ parts << " #{id.edition.render(context:)}" if id.edition&.number
184
+
185
+ parts.join
186
+ end
187
+
188
+ def render_working_document(id, context)
189
+ if id.wp_stage
190
+ parts = []
191
+ if id.publisher
192
+ parts << id.publisher.render(context:)
193
+ if id.copublishers&.any?
194
+ parts << "/#{id.copublishers.map { |c| c.render(context:) }.join('/')}"
195
+ end
196
+ parts << "/"
197
+ end
198
+ parts << id.wp_stage
199
+ if id.wp_type && !id.wp_type.strip.empty?
200
+ parts << " #{id.wp_type.strip}"
201
+ end
202
+
203
+ if id.number
204
+ num_str = id.number.to_s
205
+ num_str += "-#{id.part}" if id.part && id.part.to_s != ""
206
+ num_str += "-#{id.subpart}" if id.subpart && id.subpart.to_s != ""
207
+ parts << " #{num_str}"
208
+ end
209
+
210
+ parts << " #{id.edition.render(context:)}" if id.edition&.number
211
+ return parts.join
212
+ end
213
+
214
+ parts = []
215
+ parts << id.technical_committee if id.technical_committee
216
+
217
+ if id.wd_number
218
+ num_part = id.wd_number.to_s
219
+ num_part += "(#{id.wd_language})" if id.wd_language
220
+ parts << num_part
221
+ end
222
+
223
+ parts << id.wd_stage if id.wd_stage
224
+
225
+ parts.join("/")
226
+ end
227
+
228
+ def render_test_report_form(id, context)
229
+ parts = []
230
+ parts << id.publisher_portion
231
+
232
+ if id.cispr_identifier
233
+ cispr_parts = []
234
+ cispr_parts << id.cispr_identifier.publisher.render(context:)
235
+
236
+ num_str = id.cispr_identifier.number.to_s
237
+ num_str += "-#{id.cispr_identifier.part}" if id.cispr_identifier.part && id.cispr_identifier.part.to_s != ""
238
+ cispr_parts << num_str
239
+
240
+ cispr_str = cispr_parts.join(" ")
241
+ cispr_str += ":#{id.date.render(context:)}" if id.date
242
+
243
+ parts << " #{cispr_str}"
244
+ else
245
+ parts << id.number_portion
246
+ end
247
+
248
+ parts << id.trf_info.to_s if id.trf_info && !id.trf_info.empty?
249
+
250
+ parts.compact.join
251
+ end
252
+ end
253
+ end
254
+ end
@@ -1,25 +1,19 @@
1
- require_relative "identifier"
2
1
  # frozen_string_literal: true
3
- require_relative "../components/typed_stage"
4
- require_relative "urn_generator"
5
2
 
6
3
  module Pubid
7
4
  module Iec
8
5
  class SingleIdentifier < Identifier
9
- attribute :typed_stage, Components::TypedStage
6
+ # Default to the class's published typed_stage so an omitted "stage" key
7
+ # reconstructs the published state on from_hash.
8
+ attribute :typed_stage, ::Pubid::Components::TypedStage,
9
+ default: -> { self.class.published_typed_stage }
10
10
 
11
11
  # Generate URN for this identifier
12
12
  #
13
13
  # @return [String] URN representation
14
14
 
15
- def to_s(lang: :en, lang_single: false, with_edition: false)
16
- [].tap do |parts|
17
- parts << publisher_portion(lang: lang)
18
- parts << number_portion(lang_single: lang_single)
19
- parts << edition_portion(lang: lang) if with_edition
20
- end.compact.join(" ").tap do |s|
21
- s << language_portion(lang_single: lang_single) if languages&.any?
22
- end
15
+ def to_s(**opts)
16
+ render(format: :human, **opts)
23
17
  end
24
18
 
25
19
  def publisher_portion(lang: :en)
@@ -1,5 +1,3 @@
1
- require_relative "identifier"
2
- require_relative "single_identifier"
3
1
  # frozen_string_literal: true
4
2
 
5
3
  module Pubid
@@ -8,6 +6,55 @@ module Pubid
8
6
  class SupplementIdentifier < SingleIdentifier
9
7
  attribute :base_identifier, Identifier, polymorphic: true
10
8
 
9
+ # Serialize the supplemented document under "base". The supplement's own
10
+ # number/date/stage come from the inherited common maps; route the nested
11
+ # base hash back through Identifier.from_hash so its concrete subclass (and
12
+ # any further nesting) is reconstructed.
13
+ key_value do
14
+ map "base", with: { to: :base_to_kv, from: :base_from_kv }
15
+ end
16
+
17
+ def base_to_kv(model, doc)
18
+ base = model.base_identifier
19
+ return unless base
20
+
21
+ # `base_identifier` synthesises a base for a supplement that has none
22
+ # (e.g. a bare "+AMD1:2008" nested in a consolidation): a fake doc whose
23
+ # number equals the supplement's own. It renders nothing and the getter
24
+ # recreates it identically on load, so don't persist it. A standalone
25
+ # supplement ("IEC/FDAM 60038-1") instead moves the real base number into
26
+ # the synthetic base (base.number != own number), which must be kept.
27
+ return if model.synthetic_base? && base.number.to_s == model.number.to_s
28
+
29
+ doc.add_child(Lutaml::KeyValue::DataModel::Element.new("base",
30
+ base.to_hash))
31
+ end
32
+
33
+ def base_from_kv(model, value)
34
+ return unless value
35
+
36
+ base = ::Pubid::Iec::Identifier.from_hash(value)
37
+ model.base_identifier = base
38
+
39
+ # A base of the exact SingleIdentifier class is the synthetic self-base
40
+ # of a standalone supplement ("IEC/FDAM 60038-1"); a real attached base
41
+ # is always a concrete type (InternationalStandard, etc.). Re-engage the
42
+ # synthetic-base state so the supplement renders in standalone form
43
+ # (publisher/TYPE base-number-supp-number) instead of attached form.
44
+ if base.instance_of?(::Pubid::Iec::SingleIdentifier)
45
+ model.mark_synthetic_standalone!
46
+ end
47
+ end
48
+
49
+ # Re-engage the standalone synthetic-base state on a deserialized
50
+ # supplement. At this point `number` already holds the supplement number
51
+ # (set from the "number" key before "base"), so preserve it as the
52
+ # supplement number and flag the synthetic base.
53
+ def mark_synthetic_standalone!
54
+ @synthetic_base = true
55
+ @supplement_number = @number
56
+ end
57
+
11
58
  # Override base_identifier getter to ensure it's always created for standalone supplements
12
59
  def base_identifier
13
60
  @base_identifier || ensure_base_identifier
@@ -38,17 +85,21 @@ module Pubid
38
85
  end
39
86
  end
40
87
 
41
- # Delegate publisher and copublishers to base_identifier if not set
88
+ # Delegate publisher and copublishers to base_identifier whenever there is
89
+ # a base (a supplement carries the publisher of the document it
90
+ # supplements). Checking base first — rather than `@publisher || base` — is
91
+ # required now that the publisher attribute has an IEC default, which would
92
+ # otherwise mask the delegation.
42
93
  def publisher
43
94
  return @publisher if @ensuring_base
44
95
 
45
- @publisher || base_identifier&.publisher
96
+ base_identifier ? base_identifier.publisher : @publisher
46
97
  end
47
98
 
48
99
  def copublishers
49
100
  return @copublishers if @ensuring_base
50
101
 
51
- @copublishers || base_identifier&.copublishers
102
+ base_identifier ? base_identifier.copublishers : @copublishers
52
103
  end
53
104
 
54
105
  # Ensure we have a base_identifier for standalone supplements
@@ -83,7 +134,6 @@ module Pubid
83
134
 
84
135
  # Create typed_stage for the base - use "IS" (International Standard) type
85
136
  # not the supplement type
86
- require_relative "../components/typed_stage"
87
137
  base.typed_stage = Pubid::Components::TypedStage.new(
88
138
  abbr: ["IS"],
89
139
  type_code: :is,
@@ -107,54 +157,8 @@ module Pubid
107
157
  @synthetic_base ||= false
108
158
  end
109
159
 
110
- def to_s(lang: :en, lang_single: false, with_edition: false)
111
- # Ensure we have a base_identifier for standalone supplements
112
- ensure_base_identifier
113
-
114
- # For standalone supplements (synthetic base), use standalone format
115
- # IEC/FDAM 60038-1, not IEC/IS 60038/FDAM1
116
- if synthetic_base?
117
- parts = []
118
-
119
- # Publisher portion
120
- if publisher
121
- parts << publisher.body
122
- parts << "/#{copublishers.map(&:body).join('/')}" if copublishers&.any?
123
- end
124
-
125
- # Supplement type and number with part (use base number)
126
- abbr = typed_stage.abbr.first
127
- number_str = base_identifier.number.to_s
128
- number_str += "-#{number}" if number # supplement number
129
- number_str += "-#{subpart}" if subpart
130
- parts << "#{abbr} #{number_str}"
131
-
132
- result = parts.join("/")
133
- result += ":#{date.year}" if date
134
- result += " #{edition}" if edition&.number
135
- result
136
- elsif base_identifier
137
- # Normal supplement with real base identifier
138
- # Format: "IEC 60050-102:2007/AMD1:2017"
139
- parts = []
140
- parts << base_identifier.to_s(lang: lang, lang_single: lang_single,
141
- with_edition: with_edition)
142
-
143
- # Supplement notation
144
- # Use uppercase abbreviation without space: /AMD1, /COR1
145
- abbr = typed_stage.abbr.first.upcase
146
- supp_part = "/#{abbr}#{number}"
147
- supp_part += ":#{date.year}" if date
148
- parts << supp_part
149
-
150
- # Add edition if present
151
- parts << " #{edition}" if edition&.number
152
-
153
- parts.join
154
- else
155
- # Fallback - shouldn't happen
156
- super
157
- end
160
+ def to_s(**opts)
161
+ render(format: :human, **opts)
158
162
  end
159
163
  end
160
164
  end
@@ -14,10 +14,10 @@ module Pubid
14
14
  # omits the language slot (8 fields), so it has a dedicated branch.
15
15
  class UrnGenerator < Pubid::UrnGenerator::Base
16
16
  # Deliverable markers occupying the positional deliverable slot.
17
- DELIVERABLES = /cmv|csv|exv|prv|rlv|ser/.freeze
17
+ DELIVERABLES = /cmv|csv|exv|prv|rlv|ser/
18
18
 
19
19
  def generate
20
- return series_urn if identifier.respond_to?(:all_parts) && identifier.all_parts
20
+ return series_urn if identifier.class.attributes.key?(:all_parts) && identifier.all_parts
21
21
 
22
22
  code_to_urn(identifier.to_s, urn_language)
23
23
  end
@@ -26,7 +26,7 @@ module Pubid
26
26
 
27
27
  # Hyphen-joined language codes (e.g. "en-fr"), or nil when unset.
28
28
  def urn_language
29
- return nil unless identifier.respond_to?(:languages)
29
+ return nil unless identifier.class.attributes.key?(:languages)
30
30
 
31
31
  langs = identifier.languages
32
32
  return nil unless langs&.any?
@@ -38,8 +38,8 @@ module Pubid
38
38
  raise Errors::ParseError, "Invalid IEC URN: #{urn}" unless code
39
39
 
40
40
  id = Pubid::Iec::Identifier.parse(code)
41
- id.all_parts = true if all_parts && id.respond_to?(:all_parts=)
42
- if lang && !lang.empty? && id.respond_to?(:languages=)
41
+ id.all_parts = true if all_parts && id.class.attributes.key?(:all_parts)
42
+ if lang && !lang.empty? && id.class.attributes.key?(:languages)
43
43
  id.languages = [::Pubid::Components::Language.new(code: lang)]
44
44
  end
45
45
  id
@@ -65,7 +65,7 @@ module Pubid
65
65
  # "ser" marks an all-parts series rather than a deliverable suffix; it
66
66
  # is signalled out-of-band (the code built from a series URN carries no
67
67
  # part or date, so to_s renders "IEC NNNN (all parts)").
68
- if deliv && deliv.casecmp("SER").zero?
68
+ if deliv&.casecmp("SER")&.zero?
69
69
  all_parts = true
70
70
  elsif deliv && !deliv.empty?
71
71
  code += " #{deliv}"