pubid 2.0.0.pre.alpha.8 → 2.0.0.pre.alpha.11

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 (672) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +33 -11
  3. data/conformance/pending.yaml +4 -0
  4. data/data/bipm/update_codes.yaml +9 -0
  5. data/data/iec/update_codes.yaml +3 -0
  6. data/data/ieee/update_codes.yaml +107 -1
  7. data/{archived-gems/pubid-nist → data/nist}/series.yaml +34 -0
  8. data/data/nist/update_codes.yaml +8 -0
  9. data/lib/pubid/adobe/builder.rb +52 -0
  10. data/lib/pubid/adobe/identifier.rb +47 -0
  11. data/lib/pubid/adobe/identifiers/publication.rb +31 -0
  12. data/lib/pubid/adobe/identifiers/tech_note.rb +32 -0
  13. data/lib/pubid/adobe/identifiers.rb +10 -0
  14. data/lib/pubid/adobe/parser.rb +136 -0
  15. data/lib/pubid/adobe/renderer.rb +39 -0
  16. data/lib/pubid/adobe/urn_generator.rb +42 -0
  17. data/lib/pubid/adobe/urn_parser.rb +69 -0
  18. data/lib/pubid/adobe.rb +61 -0
  19. data/lib/pubid/amca/builder.rb +4 -4
  20. data/lib/pubid/amca/identifier.rb +1 -3
  21. data/lib/pubid/amca/identifiers/base.rb +50 -33
  22. data/lib/pubid/amca/identifiers/interpretation.rb +18 -10
  23. data/lib/pubid/amca/identifiers/publication.rb +14 -10
  24. data/lib/pubid/amca/identifiers/standard.rb +3 -1
  25. data/lib/pubid/amca/identifiers.rb +0 -1
  26. data/lib/pubid/amca/parser.rb +1 -1
  27. data/lib/pubid/amca/renderer.rb +4 -4
  28. data/lib/pubid/amca/single_identifier.rb +1 -1
  29. data/lib/pubid/amca/urn_generator.rb +2 -2
  30. data/lib/pubid/amca.rb +5 -4
  31. data/lib/pubid/ansi/builder.rb +2 -2
  32. data/lib/pubid/ansi/identifier.rb +18 -0
  33. data/lib/pubid/ansi/parser.rb +1 -1
  34. data/lib/pubid/ansi/renderer.rb +2 -2
  35. data/lib/pubid/ansi.rb +5 -5
  36. data/lib/pubid/api/builder.rb +16 -2
  37. data/lib/pubid/api/identifier.rb +25 -4
  38. data/lib/pubid/api/identifiers/mpms.rb +10 -8
  39. data/lib/pubid/api/parser.rb +1 -1
  40. data/lib/pubid/api/renderer.rb +16 -7
  41. data/lib/pubid/api/single_identifier.rb +5 -12
  42. data/lib/pubid/api.rb +1 -0
  43. data/lib/pubid/ashrae/builder.rb +53 -32
  44. data/lib/pubid/ashrae/identifier.rb +3 -4
  45. data/lib/pubid/ashrae/identifiers/addenda_package.rb +7 -1
  46. data/lib/pubid/ashrae/identifiers/addendum.rb +9 -1
  47. data/lib/pubid/ashrae/identifiers/base.rb +94 -12
  48. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +8 -1
  49. data/lib/pubid/ashrae/identifiers/errata.rb +9 -0
  50. data/lib/pubid/ashrae/identifiers/guideline.rb +3 -0
  51. data/lib/pubid/ashrae/identifiers/interpretation.rb +16 -0
  52. data/lib/pubid/ashrae/identifiers/standard.rb +3 -0
  53. data/lib/pubid/ashrae/identifiers.rb +0 -1
  54. data/lib/pubid/ashrae/parser.rb +37 -17
  55. data/lib/pubid/ashrae/renderer.rb +20 -20
  56. data/lib/pubid/ashrae/single_identifier.rb +1 -1
  57. data/lib/pubid/ashrae/supplement_identifier.rb +21 -6
  58. data/lib/pubid/ashrae/urn_generator.rb +8 -2
  59. data/lib/pubid/ashrae.rb +10 -4
  60. data/lib/pubid/asme/builder.rb +11 -2
  61. data/lib/pubid/asme/identifier.rb +9 -0
  62. data/lib/pubid/asme/identifiers/standard.rb +86 -2
  63. data/lib/pubid/asme/parser.rb +1 -1
  64. data/lib/pubid/asme/renderer.rb +3 -3
  65. data/lib/pubid/asme/single_identifier.rb +8 -1
  66. data/lib/pubid/asme/urn_generator.rb +2 -2
  67. data/lib/pubid/asme.rb +1 -0
  68. data/lib/pubid/astm/builder.rb +10 -3
  69. data/lib/pubid/astm/identifier.rb +9 -0
  70. data/lib/pubid/astm/identifiers/adjunct.rb +16 -1
  71. data/lib/pubid/astm/identifiers/code_number.rb +81 -0
  72. data/lib/pubid/astm/identifiers/data_series.rb +2 -0
  73. data/lib/pubid/astm/identifiers/iso_dual_published.rb +16 -0
  74. data/lib/pubid/astm/identifiers/manual.rb +10 -0
  75. data/lib/pubid/astm/identifiers/monograph.rb +2 -0
  76. data/lib/pubid/astm/identifiers/research_report.rb +10 -0
  77. data/lib/pubid/astm/identifiers/standard.rb +10 -0
  78. data/lib/pubid/astm/identifiers/technical_report.rb +2 -0
  79. data/lib/pubid/astm/identifiers/work_in_progress.rb +2 -0
  80. data/lib/pubid/astm/identifiers.rb +1 -0
  81. data/lib/pubid/astm/parser.rb +1 -1
  82. data/lib/pubid/astm/renderer.rb +1 -1
  83. data/lib/pubid/astm/single_identifier.rb +31 -1
  84. data/lib/pubid/astm/urn_generator.rb +7 -5
  85. data/lib/pubid/astm.rb +1 -0
  86. data/lib/pubid/bipm/builder.rb +163 -0
  87. data/lib/pubid/bipm/identifier.rb +285 -0
  88. data/lib/pubid/bipm/identifiers/committee_document.rb +36 -0
  89. data/lib/pubid/bipm/identifiers/guide.rb +35 -0
  90. data/lib/pubid/bipm/identifiers/meeting.rb +53 -0
  91. data/lib/pubid/bipm/identifiers/mep.rb +33 -0
  92. data/lib/pubid/bipm/identifiers/metrologia_article.rb +48 -0
  93. data/lib/pubid/bipm/identifiers/si_brochure.rb +33 -0
  94. data/lib/pubid/bipm/identifiers.rb +15 -0
  95. data/lib/pubid/bipm/parser.rb +237 -0
  96. data/lib/pubid/bipm/renderer.rb +118 -0
  97. data/lib/pubid/bipm/urn_generator.rb +58 -0
  98. data/lib/pubid/bipm/urn_parser.rb +60 -0
  99. data/lib/pubid/bipm.rb +92 -0
  100. data/lib/pubid/bsi/builder.rb +62 -52
  101. data/lib/pubid/bsi/identifier.rb +0 -1
  102. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -2
  103. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
  104. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
  105. data/lib/pubid/bsi/identifiers/amendment.rb +4 -4
  106. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +0 -1
  107. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
  108. data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
  109. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +6 -0
  110. data/lib/pubid/bsi/identifiers/corrigendum.rb +4 -4
  111. data/lib/pubid/bsi/identifiers/expert_commentary.rb +5 -5
  112. data/lib/pubid/bsi/identifiers/handbook.rb +0 -2
  113. data/lib/pubid/bsi/identifiers/practice_guide.rb +0 -1
  114. data/lib/pubid/bsi/identifiers/set.rb +11 -0
  115. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
  116. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -2
  117. data/lib/pubid/bsi/identifiers/value_added_publication.rb +6 -6
  118. data/lib/pubid/bsi/parser.rb +1 -1
  119. data/lib/pubid/bsi/renderer.rb +71 -59
  120. data/lib/pubid/bsi/single_identifier.rb +64 -7
  121. data/lib/pubid/bsi/urn_generator.rb +11 -2
  122. data/lib/pubid/bsi.rb +7 -1
  123. data/lib/pubid/builder/base.rb +23 -11
  124. data/lib/pubid/bundled_identifier.rb +19 -9
  125. data/lib/pubid/calconnect/builder.rb +38 -0
  126. data/lib/pubid/calconnect/identifier.rb +121 -0
  127. data/lib/pubid/calconnect/identifiers/standard.rb +29 -0
  128. data/lib/pubid/calconnect/identifiers.rb +9 -0
  129. data/lib/pubid/calconnect/parser.rb +54 -0
  130. data/lib/pubid/calconnect/renderer.rb +36 -0
  131. data/lib/pubid/calconnect/urn_generator.rb +33 -0
  132. data/lib/pubid/calconnect/urn_parser.rb +34 -0
  133. data/lib/pubid/calconnect.rb +83 -0
  134. data/lib/pubid/ccsds/builder.rb +1 -1
  135. data/lib/pubid/ccsds/identifier.rb +10 -3
  136. data/lib/pubid/ccsds/identifiers/base.rb +4 -2
  137. data/lib/pubid/ccsds/identifiers/corrigendum.rb +4 -4
  138. data/lib/pubid/ccsds/parser.rb +1 -1
  139. data/lib/pubid/ccsds/single_identifier.rb +2 -2
  140. data/lib/pubid/ccsds/supplement_identifier.rb +6 -6
  141. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  142. data/lib/pubid/ccsds.rb +1 -0
  143. data/lib/pubid/cen_cenelec/builder.rb +131 -72
  144. data/lib/pubid/cen_cenelec/identifier.rb +115 -3
  145. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
  146. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
  147. data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
  148. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
  149. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
  150. data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
  151. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -14
  152. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
  153. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +60 -3
  154. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
  155. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
  156. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
  157. data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
  158. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
  159. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
  160. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
  161. data/lib/pubid/cen_cenelec/parser.rb +1 -1
  162. data/lib/pubid/cen_cenelec/renderer.rb +55 -60
  163. data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
  164. data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
  165. data/lib/pubid/cen_cenelec.rb +104 -82
  166. data/lib/pubid/cie/builder.rb +149 -24
  167. data/lib/pubid/cie/identifier.rb +13 -4
  168. data/lib/pubid/cie/identifiers/bundle.rb +35 -5
  169. data/lib/pubid/cie/identifiers/code_attributes.rb +52 -0
  170. data/lib/pubid/cie/identifiers/conference.rb +11 -6
  171. data/lib/pubid/cie/identifiers/corrigendum.rb +17 -23
  172. data/lib/pubid/cie/identifiers/dual_published.rb +6 -6
  173. data/lib/pubid/cie/identifiers/identical.rb +9 -9
  174. data/lib/pubid/cie/identifiers/joint_published.rb +10 -10
  175. data/lib/pubid/cie/identifiers/proceedings.rb +41 -0
  176. data/lib/pubid/cie/identifiers/standard.rb +43 -8
  177. data/lib/pubid/cie/identifiers/supplement.rb +27 -25
  178. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +7 -3
  179. data/lib/pubid/cie/identifiers.rb +2 -0
  180. data/lib/pubid/cie/parser.rb +55 -6
  181. data/lib/pubid/cie/single_identifier.rb +40 -1
  182. data/lib/pubid/cie/supplement_identifier.rb +29 -16
  183. data/lib/pubid/cie/urn_generator.rb +11 -8
  184. data/lib/pubid/cie.rb +7 -2
  185. data/lib/pubid/components/date.rb +21 -5
  186. data/lib/pubid/conformance/checks.rb +72 -0
  187. data/lib/pubid/conformance/corpus/case.rb +55 -0
  188. data/lib/pubid/conformance/corpus.rb +36 -0
  189. data/lib/pubid/conformance/generator.rb +212 -0
  190. data/lib/pubid/conformance/pending.rb +63 -0
  191. data/lib/pubid/conformance/runner.rb +153 -0
  192. data/lib/pubid/conformance.rb +55 -0
  193. data/lib/pubid/core.rb +2 -0
  194. data/lib/pubid/csa/builder.rb +48 -48
  195. data/lib/pubid/csa/composite_identifier.rb +18 -7
  196. data/lib/pubid/csa/identifier.rb +187 -80
  197. data/lib/pubid/csa/identifiers/bundled.rb +25 -9
  198. data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
  199. data/lib/pubid/csa/identifiers/cec.rb +44 -4
  200. data/lib/pubid/csa/identifiers/combined.rb +97 -69
  201. data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
  202. data/lib/pubid/csa/identifiers/package.rb +4 -4
  203. data/lib/pubid/csa/parser.rb +12 -8
  204. data/lib/pubid/csa/renderer.rb +13 -5
  205. data/lib/pubid/csa/single_identifier.rb +93 -4
  206. data/lib/pubid/csa/urn_generator.rb +9 -2
  207. data/lib/pubid/csa/wrapper_identifier.rb +43 -10
  208. data/lib/pubid/csa.rb +7 -1
  209. data/lib/pubid/doi/builder.rb +18 -0
  210. data/lib/pubid/doi/identifier.rb +49 -0
  211. data/lib/pubid/doi/identifiers/resource.rb +30 -0
  212. data/lib/pubid/doi/identifiers.rb +9 -0
  213. data/lib/pubid/doi/parser.rb +52 -0
  214. data/lib/pubid/doi/renderer.rb +13 -0
  215. data/lib/pubid/doi.rb +56 -0
  216. data/lib/pubid/easc/builder.rb +55 -0
  217. data/lib/pubid/easc/identifier.rb +59 -0
  218. data/lib/pubid/easc/identifiers/pmg.rb +20 -0
  219. data/lib/pubid/easc/identifiers/rmg.rb +19 -0
  220. data/lib/pubid/easc/identifiers.rb +10 -0
  221. data/lib/pubid/easc/parser.rb +88 -0
  222. data/lib/pubid/easc/renderer.rb +48 -0
  223. data/lib/pubid/easc/urn_generator.rb +46 -0
  224. data/lib/pubid/easc/urn_parser.rb +57 -0
  225. data/lib/pubid/easc.rb +53 -0
  226. data/lib/pubid/ecma/builder.rb +45 -0
  227. data/lib/pubid/ecma/identifier.rb +147 -0
  228. data/lib/pubid/ecma/identifiers/memento.rb +30 -0
  229. data/lib/pubid/ecma/identifiers/standard.rb +31 -0
  230. data/lib/pubid/ecma/identifiers/technical_report.rb +31 -0
  231. data/lib/pubid/ecma/identifiers.rb +11 -0
  232. data/lib/pubid/ecma/parser.rb +76 -0
  233. data/lib/pubid/ecma/renderer.rb +67 -0
  234. data/lib/pubid/ecma/urn_generator.rb +46 -0
  235. data/lib/pubid/ecma/urn_parser.rb +51 -0
  236. data/lib/pubid/ecma.rb +68 -0
  237. data/lib/pubid/errors.rb +80 -0
  238. data/lib/pubid/etsi/builder.rb +13 -4
  239. data/lib/pubid/etsi/identifier.rb +1 -3
  240. data/lib/pubid/etsi/identifiers/base.rb +43 -11
  241. data/lib/pubid/etsi/identifiers/etsi_standard.rb +207 -4
  242. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +45 -3
  243. data/lib/pubid/etsi/identifiers.rb +0 -1
  244. data/lib/pubid/etsi/parser.rb +9 -3
  245. data/lib/pubid/etsi/renderer.rb +8 -2
  246. data/lib/pubid/etsi.rb +6 -5
  247. data/lib/pubid/evs/builder.rb +26 -0
  248. data/lib/pubid/evs/identifier.rb +37 -0
  249. data/lib/pubid/evs/identifiers/national_adoption.rb +17 -0
  250. data/lib/pubid/evs/identifiers.rb +9 -0
  251. data/lib/pubid/evs/parser.rb +27 -0
  252. data/lib/pubid/evs/renderer.rb +30 -0
  253. data/lib/pubid/evs/urn_generator.rb +30 -0
  254. data/lib/pubid/evs/urn_parser.rb +80 -0
  255. data/lib/pubid/evs.rb +90 -0
  256. data/lib/pubid/export/exporter.rb +2 -1
  257. data/lib/pubid/export/flavor_exporter.rb +18 -3
  258. data/lib/pubid/export.rb +1 -0
  259. data/lib/pubid/format_detector.rb +1 -0
  260. data/lib/pubid/gb/builder.rb +45 -0
  261. data/lib/pubid/gb/identifier.rb +67 -0
  262. data/lib/pubid/gb/identifiers/standard.rb +34 -0
  263. data/lib/pubid/gb/identifiers.rb +9 -0
  264. data/lib/pubid/gb/parser.rb +63 -0
  265. data/lib/pubid/gb/renderer.rb +35 -0
  266. data/lib/pubid/gb.rb +88 -0
  267. data/lib/pubid/gost/builder.rb +185 -0
  268. data/lib/pubid/gost/identifier.rb +47 -0
  269. data/lib/pubid/gost/identifiers/foreign_reference.rb +25 -0
  270. data/lib/pubid/gost/identifiers/harmonized.rb +39 -0
  271. data/lib/pubid/gost/identifiers/identical_adoption.rb +39 -0
  272. data/lib/pubid/gost/identifiers/interstate_standard.rb +20 -0
  273. data/lib/pubid/gost/identifiers/national_standard.rb +19 -0
  274. data/lib/pubid/gost/identifiers.rb +13 -0
  275. data/lib/pubid/gost/parser.rb +105 -0
  276. data/lib/pubid/gost/renderer.rb +48 -0
  277. data/lib/pubid/gost/urn_generator.rb +46 -0
  278. data/lib/pubid/gost/urn_parser.rb +52 -0
  279. data/lib/pubid/gost.rb +50 -0
  280. data/lib/pubid/iala/builder.rb +22 -27
  281. data/lib/pubid/iala/identifier.rb +36 -8
  282. data/lib/pubid/iala/identifiers/advice.rb +1 -1
  283. data/lib/pubid/iala/identifiers/annex.rb +10 -10
  284. data/lib/pubid/iala/identifiers/general_assembly.rb +5 -2
  285. data/lib/pubid/iala/identifiers/guideline.rb +3 -1
  286. data/lib/pubid/iala/identifiers/letter.rb +1 -1
  287. data/lib/pubid/iala/identifiers/manual.rb +3 -1
  288. data/lib/pubid/iala/identifiers/model_course.rb +3 -1
  289. data/lib/pubid/iala/identifiers/recommendation.rb +3 -1
  290. data/lib/pubid/iala/identifiers/report.rb +1 -1
  291. data/lib/pubid/iala/identifiers/resolution.rb +1 -1
  292. data/lib/pubid/iala/identifiers/standard.rb +3 -1
  293. data/lib/pubid/iala/identifiers.rb +0 -1
  294. data/lib/pubid/iala/parser.rb +10 -2
  295. data/lib/pubid/iala/renderer.rb +1 -1
  296. data/lib/pubid/iala/urn_generator.rb +1 -1
  297. data/lib/pubid/iala/urn_parser.rb +24 -3
  298. data/lib/pubid/iala.rb +5 -4
  299. data/lib/pubid/iana/builder.rb +22 -0
  300. data/lib/pubid/iana/identifier.rb +140 -0
  301. data/lib/pubid/iana/identifiers/registry.rb +69 -0
  302. data/lib/pubid/iana/identifiers.rb +9 -0
  303. data/lib/pubid/iana/parser.rb +38 -0
  304. data/lib/pubid/iana/renderer.rb +32 -0
  305. data/lib/pubid/iana/urn_generator.rb +19 -0
  306. data/lib/pubid/iana/urn_parser.rb +24 -0
  307. data/lib/pubid/iana.rb +70 -0
  308. data/lib/pubid/identifier.rb +797 -26
  309. data/lib/pubid/identifier_metadata.rb +1 -0
  310. data/lib/pubid/idf/builder.rb +4 -4
  311. data/lib/pubid/idf/identifier.rb +18 -9
  312. data/lib/pubid/idf/parser.rb +3 -3
  313. data/lib/pubid/idf/renderer.rb +5 -5
  314. data/lib/pubid/idf/supplement_identifier.rb +3 -3
  315. data/lib/pubid/idf/urn_generator.rb +1 -1
  316. data/lib/pubid/idf.rb +7 -1
  317. data/lib/pubid/iec/builder.rb +49 -32
  318. data/lib/pubid/iec/components.rb +0 -1
  319. data/lib/pubid/iec/identifier.rb +112 -77
  320. data/lib/pubid/iec/identifiers/amendment.rb +6 -2
  321. data/lib/pubid/iec/identifiers/base.rb +2 -2
  322. data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
  323. data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
  324. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +6 -0
  325. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
  326. data/lib/pubid/iec/identifiers/fragment_identifier.rb +13 -15
  327. data/lib/pubid/iec/identifiers/guide.rb +0 -16
  328. data/lib/pubid/iec/identifiers/international_standard.rb +22 -6
  329. data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
  330. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
  331. data/lib/pubid/iec/identifiers/sheet_identifier.rb +12 -12
  332. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
  333. data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
  334. data/lib/pubid/iec/identifiers/technical_group.rb +30 -0
  335. data/lib/pubid/iec/identifiers/technical_report.rb +1 -18
  336. data/lib/pubid/iec/identifiers/technical_specification.rb +1 -18
  337. data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
  338. data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
  339. data/lib/pubid/iec/identifiers/vap_identifier.rb +12 -12
  340. data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
  341. data/lib/pubid/iec/identifiers/working_document.rb +24 -10
  342. data/lib/pubid/iec/identifiers.rb +1 -0
  343. data/lib/pubid/iec/parser.rb +53 -28
  344. data/lib/pubid/iec/renderer.rb +31 -18
  345. data/lib/pubid/iec/single_identifier.rb +34 -11
  346. data/lib/pubid/iec/supplement_identifier.rb +32 -19
  347. data/lib/pubid/iec/urn_generator.rb +227 -61
  348. data/lib/pubid/iec/urn_parser.rb +42 -4
  349. data/lib/pubid/iec.rb +2 -6
  350. data/lib/pubid/ieee/aiee/builder.rb +17 -3
  351. data/lib/pubid/ieee/aiee/identifier.rb +46 -62
  352. data/lib/pubid/ieee/aiee/parser.rb +1 -1
  353. data/lib/pubid/ieee/builder.rb +386 -69
  354. data/lib/pubid/ieee/compaction.rb +121 -0
  355. data/lib/pubid/ieee/components/draft.rb +47 -7
  356. data/lib/pubid/ieee/identifier.rb +1 -3
  357. data/lib/pubid/ieee/identifiers/adopted_standard.rb +62 -5
  358. data/lib/pubid/ieee/identifiers/amendment.rb +40 -0
  359. data/lib/pubid/ieee/identifiers/base.rb +148 -18
  360. data/lib/pubid/ieee/identifiers/code_number.rb +82 -0
  361. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +6 -2
  362. data/lib/pubid/ieee/identifiers/corrigendum.rb +17 -2
  363. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +24 -3
  364. data/lib/pubid/ieee/identifiers/dual_identifier.rb +3 -3
  365. data/lib/pubid/ieee/identifiers/dual_published.rb +58 -3
  366. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +102 -5
  367. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +25 -1
  368. data/lib/pubid/ieee/identifiers/joint_development.rb +64 -15
  369. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +58 -6
  370. data/lib/pubid/ieee/identifiers/nesc/base.rb +90 -19
  371. data/lib/pubid/ieee/identifiers/nesc/draft.rb +20 -5
  372. data/lib/pubid/ieee/identifiers/nesc/edition.rb +32 -0
  373. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +16 -5
  374. data/lib/pubid/ieee/identifiers/nesc/redline.rb +11 -2
  375. data/lib/pubid/ieee/identifiers/nesc/standard.rb +18 -3
  376. data/lib/pubid/ieee/identifiers/nesc.rb +1 -0
  377. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +3 -3
  378. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +14 -6
  379. data/lib/pubid/ieee/identifiers/redlined_standard.rb +4 -4
  380. data/lib/pubid/ieee/identifiers/si_standard.rb +4 -1
  381. data/lib/pubid/ieee/identifiers/standard.rb +4 -1
  382. data/lib/pubid/ieee/identifiers/supplement_identifier.rb +26 -7
  383. data/lib/pubid/ieee/identifiers.rb +2 -1
  384. data/lib/pubid/ieee/ire/builder.rb +7 -6
  385. data/lib/pubid/ieee/ire/identifier.rb +48 -33
  386. data/lib/pubid/ieee/ire/parser.rb +1 -1
  387. data/lib/pubid/ieee/nesc/builder.rb +33 -20
  388. data/lib/pubid/ieee/nesc/parser.rb +16 -15
  389. data/lib/pubid/ieee/parser.rb +462 -44
  390. data/lib/pubid/ieee/pre_parser.rb +1 -1
  391. data/lib/pubid/ieee/renderer.rb +158 -57
  392. data/lib/pubid/ieee/typed_stages.rb +12 -1
  393. data/lib/pubid/ieee/urn_generator.rb +35 -8
  394. data/lib/pubid/ieee.rb +63 -4
  395. data/lib/pubid/ieee_debug.rb +1 -0
  396. data/lib/pubid/ietf/builder.rb +78 -0
  397. data/lib/pubid/ietf/identifier.rb +5 -0
  398. data/lib/pubid/ietf/identifiers/base.rb +72 -0
  399. data/lib/pubid/ietf/identifiers/bcp.rb +36 -0
  400. data/lib/pubid/ietf/identifiers/fyi.rb +36 -0
  401. data/lib/pubid/ietf/identifiers/internet_draft.rb +45 -0
  402. data/lib/pubid/ietf/identifiers/rfc.rb +27 -0
  403. data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
  404. data/lib/pubid/ietf/identifiers/std.rb +36 -0
  405. data/lib/pubid/ietf/identifiers.rb +14 -0
  406. data/lib/pubid/ietf/parser.rb +61 -0
  407. data/lib/pubid/ietf/renderer.rb +64 -0
  408. data/lib/pubid/ietf/urn_generator.rb +37 -0
  409. data/lib/pubid/ietf/urn_parser.rb +43 -0
  410. data/lib/pubid/ietf.rb +86 -0
  411. data/lib/pubid/iho/identifier.rb +1 -3
  412. data/lib/pubid/iho/identifiers/base.rb +11 -10
  413. data/lib/pubid/iho/identifiers/bibliographic.rb +1 -1
  414. data/lib/pubid/iho/identifiers/circular_letter.rb +1 -1
  415. data/lib/pubid/iho/identifiers/miscellaneous.rb +1 -1
  416. data/lib/pubid/iho/identifiers/publication.rb +1 -1
  417. data/lib/pubid/iho/identifiers/standard.rb +1 -1
  418. data/lib/pubid/iho/identifiers.rb +0 -1
  419. data/lib/pubid/iho/parser.rb +1 -1
  420. data/lib/pubid/iho.rb +8 -7
  421. data/lib/pubid/isbn/builder.rb +44 -0
  422. data/lib/pubid/isbn/check_digit.rb +53 -0
  423. data/lib/pubid/isbn/identifier.rb +81 -0
  424. data/lib/pubid/isbn/identifiers/book.rb +30 -0
  425. data/lib/pubid/isbn/identifiers.rb +9 -0
  426. data/lib/pubid/isbn/parser.rb +45 -0
  427. data/lib/pubid/isbn/renderer.rb +16 -0
  428. data/lib/pubid/isbn.rb +53 -0
  429. data/lib/pubid/iso/builder.rb +9 -4
  430. data/lib/pubid/iso/bundled_identifier.rb +5 -3
  431. data/lib/pubid/iso/combined_identifier.rb +6 -4
  432. data/lib/pubid/iso/identifier.rb +29 -8
  433. data/lib/pubid/iso/identifiers/directives_supplement.rb +12 -12
  434. data/lib/pubid/iso/normalizer.rb +2 -2
  435. data/lib/pubid/iso/parser.rb +17 -13
  436. data/lib/pubid/iso/supplement_identifier.rb +19 -6
  437. data/lib/pubid/iso/urn_generator.rb +4 -1
  438. data/lib/pubid/iso/urn_parser.rb +1 -1
  439. data/lib/pubid/iso.rb +7 -1
  440. data/lib/pubid/itu/builder.rb +230 -29
  441. data/lib/pubid/itu/components/code.rb +48 -5
  442. data/lib/pubid/itu/components/designation.rb +35 -0
  443. data/lib/pubid/itu/components.rb +1 -0
  444. data/lib/pubid/itu/identifier.rb +1 -3
  445. data/lib/pubid/itu/identifiers/addendum.rb +15 -0
  446. data/lib/pubid/itu/identifiers/amendment.rb +7 -29
  447. data/lib/pubid/itu/identifiers/annex.rb +13 -2
  448. data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +87 -0
  449. data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +92 -0
  450. data/lib/pubid/itu/identifiers/base.rb +357 -25
  451. data/lib/pubid/itu/identifiers/combined_identifier.rb +99 -23
  452. data/lib/pubid/itu/identifiers/corrigendum.rb +16 -23
  453. data/lib/pubid/itu/identifiers/errata.rb +15 -0
  454. data/lib/pubid/itu/identifiers/handbook.rb +38 -0
  455. data/lib/pubid/itu/identifiers/question.rb +63 -0
  456. data/lib/pubid/itu/identifiers/recommendation.rb +3 -2
  457. data/lib/pubid/itu/identifiers/report.rb +39 -0
  458. data/lib/pubid/itu/identifiers/special_publication.rb +3 -1
  459. data/lib/pubid/itu/identifiers/standard_serialization.rb +58 -0
  460. data/lib/pubid/itu/identifiers/supplement.rb +119 -14
  461. data/lib/pubid/itu/identifiers.rb +10 -1
  462. data/lib/pubid/itu/model.rb +1 -1
  463. data/lib/pubid/itu/parser.rb +481 -27
  464. data/lib/pubid/itu/urn_generator.rb +36 -6
  465. data/lib/pubid/itu/urn_parser.rb +8 -0
  466. data/lib/pubid/itu.rb +12 -3
  467. data/lib/pubid/jcgm/builder.rb +24 -14
  468. data/lib/pubid/jcgm/identifier.rb +10 -0
  469. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -2
  470. data/lib/pubid/jcgm/identifiers/corrigendum.rb +34 -0
  471. data/lib/pubid/jcgm/identifiers/gum_guide.rb +3 -3
  472. data/lib/pubid/jcgm/identifiers/meeting.rb +47 -0
  473. data/lib/pubid/jcgm/identifiers.rb +2 -0
  474. data/lib/pubid/jcgm/parser.rb +74 -7
  475. data/lib/pubid/jcgm/renderer.rb +33 -12
  476. data/lib/pubid/jcgm/single_identifier.rb +84 -6
  477. data/lib/pubid/jcgm/supplement_identifier.rb +39 -4
  478. data/lib/pubid/jcgm/urn_generator.rb +21 -13
  479. data/lib/pubid/jcgm/urn_parser.rb +164 -10
  480. data/lib/pubid/jcgm.rb +10 -0
  481. data/lib/pubid/jis/identifier.rb +62 -3
  482. data/lib/pubid/jis/parser.rb +1 -1
  483. data/lib/pubid/jis.rb +1 -0
  484. data/lib/pubid/nist/builder.rb +29 -9
  485. data/lib/pubid/nist/caster.rb +7 -45
  486. data/lib/pubid/nist/circular_supplement_builder.rb +7 -5
  487. data/lib/pubid/nist/components/stage.rb +2 -2
  488. data/lib/pubid/nist/components/supplement.rb +5 -2
  489. data/lib/pubid/nist/configuration.rb +6 -2
  490. data/lib/pubid/nist/identifier.rb +1 -3
  491. data/lib/pubid/nist/identifiers/base.rb +133 -39
  492. data/lib/pubid/nist/identifiers/circular.rb +10 -3
  493. data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
  494. data/lib/pubid/nist/identifiers/commercial_standard.rb +1 -1
  495. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
  496. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +8 -2
  497. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -2
  498. data/lib/pubid/nist/identifiers/dated_document.rb +1 -1
  499. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +1 -1
  500. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +1 -1
  501. data/lib/pubid/nist/identifiers/handbook.rb +10 -3
  502. data/lib/pubid/nist/identifiers/internal_report.rb +13 -6
  503. data/lib/pubid/nist/identifiers/letter_circular.rb +1 -1
  504. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +15 -7
  505. data/lib/pubid/nist/identifiers/monograph.rb +15 -8
  506. data/lib/pubid/nist/identifiers/ncstar.rb +2 -2
  507. data/lib/pubid/nist/identifiers/nsrds.rb +1 -1
  508. data/lib/pubid/nist/identifiers/owmwp.rb +1 -1
  509. data/lib/pubid/nist/identifiers/report.rb +15 -7
  510. data/lib/pubid/nist/identifiers/special_publication.rb +10 -1
  511. data/lib/pubid/nist/identifiers/technical_note.rb +1 -1
  512. data/lib/pubid/nist/identifiers.rb +0 -1
  513. data/lib/pubid/nist/parser.rb +27 -4
  514. data/lib/pubid/nist/preprocessor.rb +15 -0
  515. data/lib/pubid/nist/router.rb +2 -2
  516. data/lib/pubid/nist/series/ir.rb +0 -3
  517. data/lib/pubid/nist/supplement_identifier.rb +24 -9
  518. data/lib/pubid/nist.rb +19 -13
  519. data/lib/pubid/oasis/builder.rb +79 -0
  520. data/lib/pubid/oasis/identifier.rb +160 -0
  521. data/lib/pubid/oasis/identifiers/standard.rb +29 -0
  522. data/lib/pubid/oasis/identifiers.rb +9 -0
  523. data/lib/pubid/oasis/parser.rb +34 -0
  524. data/lib/pubid/oasis/renderer.rb +29 -0
  525. data/lib/pubid/oasis/urn_generator.rb +25 -0
  526. data/lib/pubid/oasis/urn_parser.rb +22 -0
  527. data/lib/pubid/oasis.rb +80 -0
  528. data/lib/pubid/ogc/builder.rb +33 -0
  529. data/lib/pubid/ogc/identifier.rb +81 -0
  530. data/lib/pubid/ogc/identifiers/document.rb +26 -0
  531. data/lib/pubid/ogc/identifiers.rb +10 -0
  532. data/lib/pubid/ogc/parser.rb +40 -0
  533. data/lib/pubid/ogc/renderer.rb +33 -0
  534. data/lib/pubid/ogc/urn_generator.rb +14 -0
  535. data/lib/pubid/ogc/urn_parser.rb +22 -0
  536. data/lib/pubid/ogc.rb +72 -0
  537. data/lib/pubid/oiml/builder.rb +36 -8
  538. data/lib/pubid/oiml/identifier.rb +9 -1
  539. data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
  540. data/lib/pubid/oiml/identifiers/bulletin.rb +36 -0
  541. data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
  542. data/lib/pubid/oiml/identifiers/document.rb +2 -0
  543. data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
  544. data/lib/pubid/oiml/identifiers/guide.rb +2 -0
  545. data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
  546. data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
  547. data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
  548. data/lib/pubid/oiml/identifiers.rb +1 -0
  549. data/lib/pubid/oiml/parser.rb +12 -13
  550. data/lib/pubid/oiml/renderer.rb +13 -13
  551. data/lib/pubid/oiml/single_identifier.rb +41 -37
  552. data/lib/pubid/oiml/supplement_identifier.rb +36 -9
  553. data/lib/pubid/oiml/urn_parser.rb +23 -6
  554. data/lib/pubid/oiml.rb +10 -0
  555. data/lib/pubid/omg/builder.rb +20 -0
  556. data/lib/pubid/omg/identifier.rb +61 -0
  557. data/lib/pubid/omg/identifiers/specification.rb +32 -0
  558. data/lib/pubid/omg/identifiers.rb +9 -0
  559. data/lib/pubid/omg/parser.rb +93 -0
  560. data/lib/pubid/omg/renderer.rb +31 -0
  561. data/lib/pubid/omg.rb +52 -0
  562. data/lib/pubid/parser/grammar.rb +74 -0
  563. data/lib/pubid/parser.rb +2 -0
  564. data/lib/pubid/parsers/mr_string.rb +120 -7
  565. data/lib/pubid/plateau/builder.rb +8 -4
  566. data/lib/pubid/plateau/identifier.rb +1 -3
  567. data/lib/pubid/plateau/identifiers/base.rb +1 -6
  568. data/lib/pubid/plateau/identifiers/handbook.rb +1 -1
  569. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  570. data/lib/pubid/plateau/identifiers.rb +0 -1
  571. data/lib/pubid/plateau/parser.rb +16 -6
  572. data/lib/pubid/plateau/renderer.rb +1 -1
  573. data/lib/pubid/plateau/supplement_identifier.rb +11 -11
  574. data/lib/pubid/plateau.rb +14 -4
  575. data/lib/pubid/prefixes_support.rb +1 -0
  576. data/lib/pubid/renderers/annotator.rb +233 -0
  577. data/lib/pubid/renderers/base.rb +13 -0
  578. data/lib/pubid/renderers/directives_renderer.rb +3 -3
  579. data/lib/pubid/renderers/human_readable.rb +6 -4
  580. data/lib/pubid/renderers/mr_string.rb +54 -6
  581. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  582. data/lib/pubid/renderers.rb +1 -0
  583. data/lib/pubid/rendering/numbering.rb +25 -7
  584. data/lib/pubid/rendering/supplement.rb +4 -4
  585. data/lib/pubid/rendering.rb +1 -0
  586. data/lib/pubid/sae/builder.rb +1 -1
  587. data/lib/pubid/sae/identifier.rb +1 -3
  588. data/lib/pubid/sae/identifiers/base.rb +19 -9
  589. data/lib/pubid/sae/identifiers.rb +0 -1
  590. data/lib/pubid/sae/parser.rb +1 -1
  591. data/lib/pubid/sae.rb +4 -3
  592. data/lib/pubid/schema/declaration.rb +33 -0
  593. data/lib/pubid/schema/error.rb +14 -0
  594. data/lib/pubid/schema/identifier_type.rb +23 -0
  595. data/lib/pubid/schema/loader.rb +117 -0
  596. data/lib/pubid/schema/typed_stage.rb +24 -0
  597. data/lib/pubid/schema.rb +25 -0
  598. data/lib/pubid/tgpp/builder.rb +41 -0
  599. data/lib/pubid/tgpp/identifier.rb +107 -0
  600. data/lib/pubid/tgpp/identifiers/technical_report.rb +32 -0
  601. data/lib/pubid/tgpp/identifiers/technical_specification.rb +33 -0
  602. data/lib/pubid/tgpp/identifiers.rb +11 -0
  603. data/lib/pubid/tgpp/parser.rb +78 -0
  604. data/lib/pubid/tgpp/renderer.rb +52 -0
  605. data/lib/pubid/tgpp/urn_generator.rb +39 -0
  606. data/lib/pubid/tgpp/urn_parser.rb +30 -0
  607. data/lib/pubid/tgpp.rb +84 -0
  608. data/lib/pubid/type_resolver.rb +74 -0
  609. data/lib/pubid/un/builder.rb +42 -0
  610. data/lib/pubid/un/identifier.rb +40 -0
  611. data/lib/pubid/un/identifiers/document.rb +24 -0
  612. data/lib/pubid/un/identifiers.rb +9 -0
  613. data/lib/pubid/un/parser.rb +25 -0
  614. data/lib/pubid/un/renderer.rb +11 -0
  615. data/lib/pubid/un.rb +47 -0
  616. data/lib/pubid/urn_parser/errors.rb +8 -1
  617. data/lib/pubid/urn_parser.rb +1 -0
  618. data/lib/pubid/utils.rb +1 -0
  619. data/lib/pubid/version.rb +1 -1
  620. data/lib/pubid/w3c/builder.rb +55 -0
  621. data/lib/pubid/w3c/identifier.rb +130 -0
  622. data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +31 -0
  623. data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +31 -0
  624. data/lib/pubid/w3c/identifiers/draft_note.rb +31 -0
  625. data/lib/pubid/w3c/identifiers/note.rb +30 -0
  626. data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +31 -0
  627. data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +31 -0
  628. data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +31 -0
  629. data/lib/pubid/w3c/identifiers/recommendation.rb +31 -0
  630. data/lib/pubid/w3c/identifiers/standard.rb +12 -0
  631. data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +31 -0
  632. data/lib/pubid/w3c/identifiers/working_draft.rb +30 -0
  633. data/lib/pubid/w3c/identifiers.rb +25 -0
  634. data/lib/pubid/w3c/parser.rb +43 -0
  635. data/lib/pubid/w3c/renderer.rb +35 -0
  636. data/lib/pubid/w3c/urn_generator.rb +18 -0
  637. data/lib/pubid/w3c/urn_parser.rb +36 -0
  638. data/lib/pubid/w3c.rb +68 -0
  639. data/lib/pubid/xsf/builder.rb +17 -0
  640. data/lib/pubid/xsf/identifier.rb +66 -0
  641. data/lib/pubid/xsf/identifiers/xep.rb +31 -0
  642. data/lib/pubid/xsf/identifiers.rb +9 -0
  643. data/lib/pubid/xsf/parser.rb +38 -0
  644. data/lib/pubid/xsf/renderer.rb +23 -0
  645. data/lib/pubid/xsf/urn_generator.rb +13 -0
  646. data/lib/pubid/xsf/urn_parser.rb +18 -0
  647. data/lib/pubid/xsf.rb +82 -0
  648. data/lib/pubid.rb +424 -22
  649. data/lib/tasks/conformance.rake +34 -0
  650. data/lib/tasks/docs.rake +3 -3
  651. data/lib/tasks/schema.rake +88 -0
  652. data/schema/core/joint_prefixes.yaml +24 -0
  653. data/schema/iec.yaml +1017 -0
  654. data/schema/iso.yaml +1586 -0
  655. data/schema/schema.schema.yaml +96 -0
  656. metadata +241 -19
  657. data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
  658. data/archived-gems/pubid-iec/stages.yaml +0 -129
  659. data/archived-gems/pubid-iec/update_codes.yaml +0 -67
  660. data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
  661. data/archived-gems/pubid-iso/stages.yaml +0 -106
  662. data/archived-gems/pubid-iso/update_codes.yaml +0 -4
  663. data/archived-gems/pubid-itu/i18n.yaml +0 -13
  664. data/archived-gems/pubid-itu/series.yaml +0 -42
  665. data/archived-gems/pubid-nist/publishers.yaml +0 -6
  666. data/archived-gems/pubid-nist/update_codes.yaml +0 -93
  667. data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
  668. data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
  669. data/lib/pubid/cie/components/code.rb +0 -80
  670. data/lib/pubid/iala/identifiers/base.rb +0 -14
  671. data/lib/pubid/iec/components/code.rb +0 -36
  672. /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
@@ -23,19 +23,37 @@ module Pubid
23
23
  parts << "itu"
24
24
  end
25
25
 
26
+ # An ITU-R Report numbers independently of the Recommendation series,
27
+ # so "BT.2020-1" alone is ambiguous — the type has to reach the URN as
28
+ # well as `to_s` and the MR slug, or the two documents share an
29
+ # identifier on that surface.
30
+ parts << "report" if identifier.is_a?(Identifiers::Report)
31
+
26
32
  if identifier.series
27
33
  series = identifier.series.to_s
28
34
  if identifier.code
29
- code = identifier.code.to_s
30
- parts << "#{series}.#{code}"
35
+ # A series-code document joins with a dash, not a dot; rendering it
36
+ # "EMC.5" would be ambiguous with a hypothetical "ITU-T EMC.5" and
37
+ # would not parse back.
38
+ join = identifier.series_dash ? "-" : "."
39
+ parts << "#{series}#{join}#{identifier.code.compact_s}"
31
40
  else
32
41
  parts << series
33
42
  end
34
43
  elsif identifier.code
35
- code = identifier.code.to_s
44
+ code = identifier.code.compact_s
36
45
  parts << code
37
46
  end
38
47
 
48
+ # Identity-bearing markers that are not part of sector/series/code.
49
+ # Without them "ITU-T H.350 attachment", "ITU-T Q.120-Q.139" and
50
+ # "ITU-T E-100 series Suppl. 2" would each share a URN with the
51
+ # document they are distinct from — the same collision Code#compact_s
52
+ # exists to prevent for the code suffixes.
53
+ parts << "series" if identifier.series_word
54
+ parts << "attachment" if identifier.attachment
55
+ parts << "to-#{identifier.range_end}" if identifier.range_end
56
+
39
57
  if identifier.date
40
58
  date = identifier.date
41
59
  if date&.year && date.month
@@ -57,8 +75,16 @@ module Pubid
57
75
 
58
76
  base = maybe(:base)
59
77
  if base
60
- base_gen = self.class.new(base)
61
- base_urn = base_gen.generate_base_urn
78
+ # An annex or appendix base holds its identity in its OWN base (its
79
+ # sector/series/code are nil), so generate_base_urn would emit
80
+ # "urn:itu:itu" for it — go through its own to_urn instead.
81
+ nested_wrapper = base.is_a?(Identifiers::AnnexOfRecommendation) ||
82
+ base.is_a?(Identifiers::AppendixOfRecommendation)
83
+ base_urn = if nested_wrapper
84
+ base.to_urn
85
+ else
86
+ self.class.new(base).generate_base_urn
87
+ end
62
88
 
63
89
  base_part = base_urn.sub(/^urn:itu:/, "")
64
90
  base_parts = base_part.split(":")
@@ -72,12 +98,16 @@ module Pubid
72
98
  if identifier.series
73
99
  series = identifier.series.to_s
74
100
  if identifier.code
75
- code = identifier.code.to_s
101
+ code = identifier.code.compact_s
76
102
  parts << "#{series}.#{code}"
77
103
  else
78
104
  parts << series
79
105
  end
80
106
  end
107
+ # A base-less supplement's whole identity is sector + series, so the
108
+ # series-group word belongs in the URN too — without it
109
+ # "ITU-T E-100 series Suppl. 2" and "ITU-T E-100 Suppl. 2" collide.
110
+ parts << "series" if identifier.series_word
81
111
  end
82
112
 
83
113
  supplement_notation = maybe(:supplement_notation)
@@ -16,6 +16,14 @@ module Pubid
16
16
  body = strip_namespace(urn)
17
17
  parts = split_parts(body)
18
18
  sector, code = parts
19
+
20
+ # UrnGenerator emits a "report" segment between the sector and the code
21
+ # for an ITU-R Report, which numbers independently of the
22
+ # Recommendation series (urn:itu:r:report:BT.2020-1).
23
+ if parts[1] == "report"
24
+ return flavor_parse("Report ITU-#{sector.upcase} #{parts[2]}")
25
+ end
26
+
19
27
  flavor_parse("ITU-#{sector.upcase} #{code}")
20
28
  end
21
29
  end
data/lib/pubid/itu.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  require "lutaml/model"
4
5
 
5
6
  module Pubid
@@ -7,11 +8,19 @@ module Pubid
7
8
  extend Pubid::PrefixesSupport
8
9
 
9
10
  # Sole ITU publisher token (see the parser's `itu_prefix` rule).
11
+ #
12
+ # The leading "Report" of an ITU-R Report's canonical form
13
+ # ("Report ITU-R BT.2020-1") is deliberately NOT listed: prefix routing
14
+ # claims every reference beginning with the token, and "Report" is a
15
+ # generic English word that other SDOs' references start with — the
16
+ # mixin's documented exclusion for ambiguous tokens. Report references
17
+ # route by their "ITU" token in the infix spelling
18
+ # ("ITU-R Report BT.2020-1"), and `Pubid::Itu.parse` accepts both.
10
19
  PREFIXES = ["ITU"].freeze
11
20
 
12
21
  autoload :Builder, "#{__dir__}/itu/builder"
13
22
  autoload :Components, "#{__dir__}/itu/components"
14
- autoload :Identifier, "#{__dir__}/itu/identifier"
23
+ autoload :Identifier, "#{__dir__}/itu/identifiers/base"
15
24
  autoload :Identifiers, "#{__dir__}/itu/identifiers"
16
25
  autoload :Parser, "#{__dir__}/itu/parser"
17
26
  autoload :UrnGenerator, "#{__dir__}/itu/urn_generator"
@@ -32,9 +41,9 @@ module Pubid
32
41
  @identifier_types ||= Identifiers.constants
33
42
  .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
34
43
  .select { |c| c.is_a?(Class) && c < Pubid::Identifier }
35
- # Exclude the flavor base itself by identity (Identifiers::Base is now an
44
+ # Exclude the flavor base itself by identity (Identifier is now an
36
45
  # alias for Pubid::Itu::Identifier, so name-based matching misses it).
37
- .reject { |c| c == Identifiers::Base }
46
+ .reject { |c| c == Identifier }
38
47
  end
39
48
 
40
49
  # Build typed stage index from identifier types
@@ -4,8 +4,11 @@ module Pubid
4
4
  module Jcgm
5
5
  class Builder < Pubid::Builder::Base
6
6
  def locate_identifier_klass(parsed_hash)
7
- if parsed_hash[:base_identifier]
8
- return Jcgm.locate_type(:amendment)
7
+ if parsed_hash[:base]
8
+ type_with_stage = parsed_hash[:type_with_stage]
9
+ return Jcgm.locate_type(:amendment) unless type_with_stage
10
+
11
+ return Jcgm.locate_type(locate_typed_stage(type_with_stage).type_code)
9
12
  end
10
13
 
11
14
  if parsed_hash[:gum_number]
@@ -22,15 +25,26 @@ module Pubid
22
25
  end
23
26
 
24
27
  def build(parsed_hash)
25
- identifier = locate_identifier_klass(parsed_hash).new
28
+ klass = locate_identifier_klass(parsed_hash)
29
+
30
+ # GUM guides store their part number in the shared `number` attribute
31
+ # ("JCGM GUM-6" -> number "6"); the parser tags it :gum_number only to
32
+ # pick this class. Fold it back onto :number before assigning.
33
+ if parsed_hash[:gum_number] && klass == Identifiers::GumGuide
34
+ parsed_hash = parsed_hash.merge(number: parsed_hash[:gum_number])
35
+ parsed_hash.delete(:gum_number)
36
+ end
37
+
38
+ identifier = klass.new
26
39
  assign_attributes(identifier, parsed_hash)
27
40
 
41
+ # Bare guides/gum-guides carry no parsed stage; derive the (single,
42
+ # published) typed_stage from the concrete class so parse and from_hash
43
+ # agree. Avoids the ambiguous locate_stage("") lookup (Guide and
44
+ # GumGuide both register abbr: [""]).
28
45
  if identifier.class.attributes.key?(:typed_stage) && identifier.typed_stage.nil?
29
- default_typed_stage = Jcgm.locate_stage("") ||
30
- raise(ArgumentError, "Unknown type abbreviation: ''")
31
- identifier.typed_stage = default_typed_stage
32
- identifier.stage = default_typed_stage.to_stage if identifier.class.attributes.key?(:stage)
33
- identifier.type = default_typed_stage.to_type if identifier.class.attributes.key?(:type)
46
+ identifier.typed_stage = identifier.class.published_typed_stage ||
47
+ raise(ArgumentError, "No published typed_stage for #{identifier.class}")
34
48
  end
35
49
 
36
50
  identifier
@@ -50,14 +64,12 @@ module Pubid
50
64
 
51
65
  def cast(type, value)
52
66
  case type
53
- when :base_identifier
67
+ when :base
54
68
  build(value)
55
69
  when :publisher
56
70
  Jcgm::Components::Publisher.new(publisher: value.to_s)
57
71
  when :number
58
- Pubid::Components::Code.new(value: value.to_s)
59
- when :gum_number
60
- Pubid::Components::Code.new(value: value.to_s)
72
+ value.to_s
61
73
  when :date
62
74
  date_str = value.to_s
63
75
  if date_str.include?("-")
@@ -70,8 +82,6 @@ module Pubid
70
82
  else
71
83
  Pubid::Components::Date.new(year: date_str)
72
84
  end
73
- when :iteration
74
- Pubid::Components::Code.new(value: value.to_s)
75
85
  when :type_with_stage
76
86
  typed_stage = locate_typed_stage(value.to_s)
77
87
  {
@@ -3,6 +3,16 @@
3
3
  module Pubid
4
4
  module Jcgm
5
5
  class Identifier < ::Pubid::Identifier
6
+ # `number`/`part`/`subpart` are declared here rather than inherited as a
7
+ # Components::Code: JCGM stores a bare string in `number` and uses neither
8
+ # of the other two. Declaring on this class is safe because its body lives
9
+ # in this one file and is never reopened, so every subclass body opens
10
+ # after it has run (lutaml deep-dups the parent attribute table at
11
+ # class-definition time).
12
+ attribute :number, :string
13
+ attribute :part, :string
14
+ attribute :subpart, :string
15
+
6
16
  def self.parse(string)
7
17
  Pubid::Jcgm.parse(string)
8
18
  end
@@ -4,8 +4,6 @@ module Pubid
4
4
  module Jcgm
5
5
  module Identifiers
6
6
  class Amendment < SupplementIdentifier
7
- attribute :type, Pubid::Components::Type, default: -> { self.class.type[:key] }
8
-
9
7
  TYPED_STAGES = [
10
8
  Pubid::Components::TypedStage.new(
11
9
  code: :pubamd,
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Jcgm
5
+ module Identifiers
6
+ # A JCGM corrigendum. Two surface forms are supported:
7
+ #
8
+ # "JCGM 200:2008 Corrigendum" — base guide + trailing " Corrigendum"
9
+ # word, no iteration number
10
+ # "JCGM 101:2008/Cor 1:2009" — base guide + slash-separated
11
+ # numbered corrigendum with date
12
+ #
13
+ # The first form is the JCGM-native convention. The second mirrors the
14
+ # ISO/IEC supplement syntax and is needed to round-trip identifiers like
15
+ # "JCGM 101:2008/Cor 1:2009" (corrigendum to GUM Supplement 1).
16
+ class Corrigendum < SupplementIdentifier
17
+ TYPED_STAGES = [
18
+ Pubid::Components::TypedStage.new(
19
+ code: :pubcorr,
20
+ stage_code: :published,
21
+ type_code: :corrigendum,
22
+ abbr: %w[Corrigendum Cor],
23
+ name: "Corrigendum",
24
+ harmonized_stages: %w[60.00 60.60],
25
+ ),
26
+ ].freeze
27
+
28
+ def self.type
29
+ { key: :corrigendum, title: "Corrigendum", short: "Corr" }
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -3,10 +3,10 @@
3
3
  module Pubid
4
4
  module Jcgm
5
5
  module Identifiers
6
+ # A GUM guide, e.g. "JCGM GUM-6:2020". The GUM-series part number ("6")
7
+ # lives in the inherited `number` attribute (serialized as `number: "6"`);
8
+ # `_type: pubid:jcgm:gum-guide` disambiguates it from a plain guide.
6
9
  class GumGuide < SingleIdentifier
7
- attribute :gum_number, Pubid::Components::Code
8
- attribute :type, Pubid::Components::Type, default: -> { self.class.type[:key] }
9
-
10
10
  TYPED_STAGES = [
11
11
  Pubid::Components::TypedStage.new(
12
12
  code: :pubgumguide,
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Jcgm
5
+ module Identifiers
6
+ # A JCGM committee/meeting record, e.g. "JCGM 17th Meeting (2012)".
7
+ #
8
+ # `number` (Components::Code) holds the meeting ordinal as a clean integer
9
+ # value ("17"); `date` (Components::Date, year-only) holds the year.
10
+ class Meeting < SingleIdentifier
11
+ TYPED_STAGES = [
12
+ Pubid::Components::TypedStage.new(
13
+ code: :pubmeeting,
14
+ stage_code: :published,
15
+ type_code: :jcgm_meeting,
16
+ abbr: ["Meeting"],
17
+ name: "Meeting",
18
+ harmonized_stages: %w[60.00 60.60],
19
+ ),
20
+ ].freeze
21
+
22
+ def self.type
23
+ { key: :jcgm_meeting, title: "Meeting" }
24
+ end
25
+
26
+ # Ordinal suffix as printed by the JCGM/BIPM data generator: a naive
27
+ # last-digit rule (1->st, 2->nd, 3->rd, else th) with NO 11/12/13 teens
28
+ # exception. The real records print "11st", "12nd", "13rd", so applying
29
+ # the standard-English teens exception would break round-trip.
30
+ def self.ordinal(number)
31
+ n = number.to_i
32
+ suffix = case n % 10
33
+ when 1 then "st"
34
+ when 2 then "nd"
35
+ when 3 then "rd"
36
+ else "th"
37
+ end
38
+ "#{n}#{suffix}"
39
+ end
40
+
41
+ def ordinal
42
+ self.class.ordinal(number)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -4,8 +4,10 @@ module Pubid
4
4
  module Jcgm
5
5
  module Identifiers
6
6
  autoload :Amendment, "#{__dir__}/identifiers/amendment"
7
+ autoload :Corrigendum, "#{__dir__}/identifiers/corrigendum"
7
8
  autoload :Guide, "#{__dir__}/identifiers/guide"
8
9
  autoload :GumGuide, "#{__dir__}/identifiers/gum_guide"
10
+ autoload :Meeting, "#{__dir__}/identifiers/meeting"
9
11
  end
10
12
  end
11
13
  end
@@ -4,24 +4,86 @@ require "parslet"
4
4
 
5
5
  module Pubid
6
6
  module Jcgm
7
- class Parser < Parslet::Parser
7
+ class Parser < ::Pubid::Parser::Grammar
8
8
  include ::Pubid::Parser::CommonParseRules
9
9
  include ::Pubid::Parser::CommonParseMethods
10
10
 
11
11
  root :identifier
12
12
 
13
13
  rule(:identifier) do
14
- amendment_identifier | base_identifier
14
+ meeting_identifier | amendment_identifier | corrigendum_identifier |
15
+ numbered_corrigendum_identifier | base | named_guide_identifier
15
16
  end
16
17
 
17
- rule(:base_identifier) do
18
- publisher >> space >> number_portion >> date_portion >> language_portion.maybe
18
+ # "JCGM 200:2008 Corrigendum" — a base guide plus a trailing
19
+ # " Corrigendum" word (no number). Must precede base: Parslet
20
+ # is an ordered PEG that commits to the first matching alternative, so if
21
+ # base ran first it would consume "JCGM 200:2008" and root
22
+ # would fail on the leftover " Corrigendum". Emits type_with_stage so the
23
+ # builder routes it to Corrigendum.
24
+ rule(:corrigendum_identifier) do
25
+ base.as(:base) >> space >>
26
+ str("Corrigendum").as(:type_with_stage)
27
+ end
28
+
29
+ # "JCGM 101:2008/Cor 1:2009" — a base guide plus a slash-separated
30
+ # numbered corrigendum (mirrors the ISO/IEC supplement form). The
31
+ # trailing :YYYY is optional so "JCGM 101:2008/Cor 1" also parses.
32
+ # Must precede base for the same PEG-commit reason as corrigendum_identifier.
33
+ rule(:numbered_corrigendum_identifier) do
34
+ base.as(:base) >>
35
+ str("/") >> str("Cor").as(:type_with_stage) >>
36
+ space >> digits.as(:number) >>
37
+ corrigendum_date.maybe
38
+ end
39
+
40
+ # Dateless "named" guides: "JCGM GUM", "JCGM VIM-3" (and future "VIM-N").
41
+ # Last in the alternation — only reached when base fully fails
42
+ # (these have no date, so number_portion/date_portion never match).
43
+ rule(:named_guide_identifier) do
44
+ publisher >> space >> named_number
45
+ end
46
+
47
+ rule(:named_number) do
48
+ (str("GUM") | (str("VIM") >> (str("-") >> digits).maybe)).as(:number)
49
+ end
50
+
51
+ # Committee/meeting record, e.g. "JCGM 17th Meeting (2012)". Diverges
52
+ # from base right after the digits (base wants ":", meeting
53
+ # wants the ordinal suffix), so ordered choice is unambiguous. Emits the
54
+ # same tokens as a guide plus type_with_stage "Meeting", so the generic
55
+ # builder path resolves it to Identifiers::Meeting (like "Amd").
56
+ #
57
+ # The trailing " (YYYY)" group is optional, so the partial reference
58
+ # "JCGM 11st Meeting" parses with `date` left nil. JCGM numbers its
59
+ # meetings in one sequence, so the ordinal alone names the event and the
60
+ # year is redundant detail. The whole group is `.maybe` (not the year
61
+ # inside it), so a dangling "(" or a truncated year still fails —
62
+ # the same shape as `date_portion.maybe` in `rule(:base)`.
63
+ rule(:meeting_identifier) do
64
+ publisher >> space >> digits.as(:number) >> ordinal_suffix >>
65
+ space >> str("Meeting").as(:type_with_stage) >>
66
+ (space >> str("(") >> year_digits.as(:date) >> str(")")).maybe
67
+ end
68
+
69
+ rule(:ordinal_suffix) do
70
+ str("st") | str("nd") | str("rd") | str("th")
71
+ end
72
+
73
+ # `date_portion` is optional so a partial reference that omits the
74
+ # trailing `:YYYY` date (e.g. "JCGM 100") parses with `date` left nil,
75
+ # letting relaton match a collection via `matches?(row, ignore: [:date])`.
76
+ # The whole sub-rule is `.maybe` (not the year inside it) so a dangling
77
+ # ":" still fails. Mirrors ETSI (lib/pubid/etsi/parser.rb).
78
+ rule(:base) do
79
+ publisher >> space >> number_portion >>
80
+ date_portion.maybe >> language_portion.maybe
19
81
  end
20
82
 
21
83
  rule(:amendment_identifier) do
22
- base_identifier.as(:base_identifier) >>
84
+ base.as(:base) >>
23
85
  str("/") >> amendment_type >>
24
- space >> amendment_number >>
86
+ space >> digits.as(:number) >>
25
87
  amendment_date.maybe
26
88
  end
27
89
 
@@ -73,12 +135,17 @@ module Pubid
73
135
  end
74
136
 
75
137
  rule(:amendment_number) do
76
- digits.as(:iteration)
138
+ digits.as(:number)
77
139
  end
78
140
 
79
141
  rule(:amendment_date) do
80
142
  str(":") >> (full_date | year_only)
81
143
  end
144
+
145
+ # Numbered corrigendum date: same shape as amendment_date.
146
+ rule(:corrigendum_date) do
147
+ str(":") >> (full_date | year_only)
148
+ end
82
149
  end
83
150
  end
84
151
  end
@@ -13,20 +13,41 @@ module Pubid
13
13
  # registry and invoked via `render(format: :human)`.
14
14
  class Renderer < ::Pubid::Renderers::Base
15
15
  def render(context: nil, **opts)
16
- id = @id
17
-
18
- case id
19
- when Identifiers::Amendment
20
- render_amendment(id, context)
21
- when Identifiers::GumGuide
22
- render_gum_guide(id, context)
23
- else
24
- render_single(id)
16
+ case @id
17
+ when Identifiers::Amendment then render_amendment(@id, context)
18
+ when Identifiers::Corrigendum then render_corrigendum(@id)
19
+ when Identifiers::GumGuide then render_gum_guide(@id, context)
20
+ when Identifiers::Meeting then render_meeting(@id)
21
+ else render_single(@id)
25
22
  end
26
23
  end
27
24
 
28
25
  private
29
26
 
27
+ def render_corrigendum(id)
28
+ # Two surface forms:
29
+ # "JCGM 200:2008 Corrigendum" — number absent (word form)
30
+ # "JCGM 101:2008/Cor 1:2009" — number present (numbered form)
31
+ return "#{id.base}/Cor #{id.number}#{corrigendum_date_suffix(id)}" if id.number
32
+
33
+ "#{id.base} Corrigendum"
34
+ end
35
+
36
+ def corrigendum_date_suffix(id)
37
+ id.date ? ":#{id.date}" : ""
38
+ end
39
+
40
+ # Two surface forms:
41
+ # "JCGM 17th Meeting (2012)" — date present (published records)
42
+ # "JCGM 17th Meeting" — date absent (partial reference)
43
+ # The ordinal alone names the meeting, so the dateless form is a valid
44
+ # identifier and must stay re-parseable (the parser makes the " (YYYY)"
45
+ # group optional to match).
46
+ def render_meeting(id)
47
+ base = "JCGM #{id.ordinal} Meeting"
48
+ id.date ? "#{base} (#{id.date.year})" : base
49
+ end
50
+
30
51
  def render_single(id)
31
52
  parts = [id.publisher_portion]
32
53
  parts << id.number_portion unless id.number_portion.empty?
@@ -36,9 +57,9 @@ module Pubid
36
57
  end
37
58
 
38
59
  def render_amendment(id, context)
39
- result = id.base_identifier.to_s if id.base_identifier
60
+ result = id.base.to_s if id.base
40
61
  result += "/Amd"
41
- result += " #{id.iteration.render(context:)}" if id.iteration
62
+ result += " #{id.number}" if id.number
42
63
  result += ":#{id.date}" if id.date
43
64
  result
44
65
  end
@@ -46,7 +67,7 @@ module Pubid
46
67
  def render_gum_guide(id, context)
47
68
  parts = []
48
69
  parts << id.publisher.publisher if id.publisher
49
- parts << "GUM-#{id.gum_number.render(context:)}" if id.gum_number
70
+ parts << "GUM-#{id.number}" if id.number
50
71
 
51
72
  result = parts.join(" ")
52
73
  result += ":#{id.date}" if id.date
@@ -3,17 +3,95 @@
3
3
  module Pubid
4
4
  module Jcgm
5
5
  class SingleIdentifier < Identifier
6
- attribute :publisher, Jcgm::Components::Publisher
7
- attribute :typed_stage, Pubid::Components::TypedStage
8
- attribute :number, Pubid::Components::Code
6
+ attribute :publisher, Jcgm::Components::Publisher,
7
+ default: -> { self.class.default_publisher }
8
+ attribute :typed_stage, Pubid::Components::TypedStage,
9
+ default: -> { self.class.published_typed_stage }
9
10
  attribute :date, Pubid::Components::Date
10
11
  attribute :languages, Pubid::Components::Language, collection: true
11
12
  attribute :stage, Pubid::Components::Stage
12
13
  attribute :type, Pubid::Components::Type
13
14
 
14
- # Generate URN for this identifier
15
+ # Compact serialization: only per-instance information is mapped. The
16
+ # publisher (always "JCGM") and the derived type / stage / typed_stage
17
+ # (fully determined by the class, i.e. `_type`) are intentionally NOT
18
+ # mapped — they are reconstructed from the class on load via the
19
+ # attribute defaults above. Components collapse to bare scalars:
20
+ # number is already a bare :string; date -> year/month/day scalars.
21
+ # Mirrors ISO (lib/pubid/iso/identifier.rb) and OIML.
22
+ key_value do
23
+ map "_type", to: :_type
24
+ map "number", with: { to: :number_to_kv, from: :number_from_kv }
25
+ map "year", with: { to: :year_to_kv, from: :year_from_kv }
26
+ map "month", with: { to: :month_to_kv, from: :month_from_kv }
27
+ map "day", with: { to: :day_to_kv, from: :day_from_kv }
28
+ map "languages", to: :languages
29
+ end
30
+
31
+ # The publisher implied when none is serialized — always JCGM.
32
+ def self.default_publisher
33
+ Jcgm::Components::Publisher.new(publisher: Jcgm::PREFIXES.first)
34
+ end
35
+
36
+ # The class's published typed_stage (canonical surface form). Each JCGM
37
+ # class registers exactly one, all :published; `_type` fixes the class,
38
+ # so an omitted typed_stage reconstructs deterministically on from_hash.
15
39
  #
16
- # @return [String] URN representation
40
+ # `original_abbr` is deliberately LEFT NIL. It records the spelling the
41
+ # input used and is not serialized, so it cannot survive a round trip —
42
+ # and this method is one of the two paths that fill `typed_stage`. The
43
+ # other is the parse path (`Builder#locate_typed_stage` ->
44
+ # `Jcgm.locate_stage`), which returns the registry entry untouched.
45
+ # Setting it here made the two disagree, so `from_hash(to_hash) != parse`
46
+ # for every type the grammar tags (Meeting, Corrigendum, Amendment) —
47
+ # and because `#matches?` is `exclude(...) == other.exclude(...)`, a
48
+ # relaton index lookup then silently matched nothing. Nothing in JCGM
49
+ # reads the field: the renderer hardcodes its surface words, the URN
50
+ # generator reads only `type_code`, and `TypedStage#abbreviation` chooses
51
+ # among long_abbr/short_abbr/abbr.first. Recording the *matched* token
52
+ # instead would not work either — "/Cor 1" would store "Cor" where
53
+ # from_hash rebuilds "Corrigendum".
54
+ def self.published_typed_stage
55
+ return nil unless const_defined?(:TYPED_STAGES)
56
+
57
+ ts = self::TYPED_STAGES.find { |t| t.stage_code.to_s == "published" }
58
+ # dup: locate_stage hands out the shared object from the frozen
59
+ # TYPED_STAGES array (the array is frozen, its elements are not), so a
60
+ # future in-place mutation would otherwise leak globally.
61
+ ts&.dup
62
+ end
63
+
64
+ # type and stage are derived from typed_stage, never stored — so the
65
+ # doctype (fixed by the class / _type) is not carried in the hash.
66
+ def type
67
+ typed_stage&.to_type
68
+ end
69
+
70
+ def stage
71
+ typed_stage&.to_stage
72
+ end
73
+
74
+ # --- number ---
75
+ def number_to_kv(model, doc) = emit_kv(doc, "number", model.number)
76
+ def number_from_kv(model, value) = model.number = value.to_s
77
+
78
+ # --- date flattened to top-level year/month/day scalars ---
79
+ def year_to_kv(model, doc) = emit_kv(doc, "year", model.date&.year)
80
+ def month_to_kv(model, doc) = emit_kv(doc, "month", model.date&.month)
81
+ def day_to_kv(model, doc) = emit_kv(doc, "day", model.date&.day)
82
+ def year_from_kv(model, value) = date_for(model).year = value.to_s
83
+ def month_from_kv(model, value) = date_for(model).month = value.to_s
84
+ def day_from_kv(model, value) = date_for(model).day = value.to_s
85
+
86
+ def emit_kv(doc, key, value)
87
+ return if value.nil? || value.to_s.empty?
88
+
89
+ doc.add_child(Lutaml::KeyValue::DataModel::Element.new(key, value.to_s))
90
+ end
91
+
92
+ def date_for(model)
93
+ model.date ||= Pubid::Components::Date.new
94
+ end
17
95
 
18
96
  def publisher_portion
19
97
  publisher.to_s
@@ -21,7 +99,7 @@ module Pubid
21
99
 
22
100
  def number_portion
23
101
  parts = []
24
- parts << number.value if number
102
+ parts << number if number
25
103
  parts << ":#{date.year}" if date
26
104
  parts.join
27
105
  end