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
@@ -8,6 +8,31 @@ module Pubid
8
8
  attribute :typed_stage, ::Pubid::Components::TypedStage,
9
9
  default: -> { self.class.published_typed_stage }
10
10
 
11
+ # number/part/subpart are mapped HERE, not on Iec::Identifier, and the
12
+ # placement is the whole design.
13
+ #
14
+ # The four wrapper identifiers — FragmentIdentifier,
15
+ # ConsolidatedIdentifier, VapIdentifier and SheetIdentifier — inherit
16
+ # from Iec::Identifier DIRECTLY and override `number`/`part`/`subpart` as
17
+ # readers that delegate to what they wrap. A map on the shared parent
18
+ # would therefore serialize
19
+ # the delegated value twice: once at the wrapper's top level and again
20
+ # inside "base"/"identifiers". SingleIdentifier is the seam that excludes
21
+ # exactly those four while covering both classes that own a number of
22
+ # their own (Identifiers::Base and SupplementIdentifier).
23
+ #
24
+ # That is a structural exclusion, not a denylist of no-op converters that
25
+ # a later key can be forgotten from — which is how `month`/`day` came to
26
+ # leak (see DelegatedFieldSuppression).
27
+ #
28
+ # The values are plain strings, so no converter is needed: lutaml writes
29
+ # the scalar, and ::Pubid::Identifier#to_hash drops a nil.
30
+ key_value do
31
+ map "number", to: :number
32
+ map "part", to: :part
33
+ map "subpart", to: :subpart
34
+ end
35
+
11
36
  # Generate URN for this identifier
12
37
  #
13
38
  # @return [String] URN representation
@@ -28,16 +53,14 @@ module Pubid
28
53
  publisher.body
29
54
  end
30
55
 
31
- # Add type abbreviation if present
32
- if typed_stage && !typed_stage.abbreviation.empty?
33
- abbr = typed_stage.abbreviation
34
- # For copublishers or empty abbr, use space; otherwise use slash
35
- pub_string += if copublishers&.any? || abbr == ""
36
- (abbr == "" ? "" : " #{abbr}")
37
- else
38
- "/#{abbr}"
39
- end
40
- end
56
+ # IEC house style separates the publisher from the typed-stage
57
+ # abbreviation with a SPACE, for every type and whether or not there
58
+ # are copublishers: "IEC CD 60038", "IEC PNW 1000-1:2023". The slash
59
+ # stays the copublisher separator only. The slash input spelling
60
+ # ("IEC/CD 60038") is still accepted by the parser; only rendering
61
+ # normalises. See issue #360 item 2.
62
+ abbr = typed_stage&.abbreviation.to_s
63
+ pub_string += " #{abbr}" unless abbr.empty?
41
64
 
42
65
  pub_string
43
66
  end
@@ -48,7 +71,7 @@ module Pubid
48
71
  (part ? "-#{part}" : ""),
49
72
  (subpart ? "-#{subpart}" : ""),
50
73
  (stage_iteration ? ".#{stage_iteration}" : ""),
51
- (date ? ":#{date.year}" : ""),
74
+ (date ? ":#{date.render}" : ""),
52
75
  ].join
53
76
  end
54
77
 
@@ -4,7 +4,7 @@ module Pubid
4
4
  module Iec
5
5
  # Identifier that represents a supplement to a base identifier.
6
6
  class SupplementIdentifier < SingleIdentifier
7
- attribute :base_identifier, Identifier, polymorphic: true
7
+ attribute :base, Identifier, polymorphic: true
8
8
 
9
9
  # Serialize the supplemented document under "base". The supplement's own
10
10
  # number/date/stage come from the inherited common maps; route the nested
@@ -15,10 +15,10 @@ module Pubid
15
15
  end
16
16
 
17
17
  def base_to_kv(model, doc)
18
- base = model.base_identifier
18
+ base = model.base
19
19
  return unless base
20
20
 
21
- # `base_identifier` synthesises a base for a supplement that has none
21
+ # `base` synthesises a base for a supplement that has none
22
22
  # (e.g. a bare "+AMD1:2008" nested in a consolidation): a fake doc whose
23
23
  # number equals the supplement's own. It renders nothing and the getter
24
24
  # recreates it identically on load, so don't persist it. A standalone
@@ -34,7 +34,7 @@ module Pubid
34
34
  return unless value
35
35
 
36
36
  base = ::Pubid::Iec::Identifier.from_hash(value)
37
- model.base_identifier = base
37
+ model.base = base
38
38
 
39
39
  # A base of the exact SingleIdentifier class is the synthetic self-base
40
40
  # of a standalone supplement ("IEC/FDAM 60038-1"); a real attached base
@@ -55,18 +55,18 @@ module Pubid
55
55
  @supplement_number = @number
56
56
  end
57
57
 
58
- # Override base_identifier getter to ensure it's always created for standalone supplements
59
- def base_identifier
60
- @base_identifier || ensure_base_identifier
58
+ # Override base getter to ensure it's always created for standalone supplements
59
+ def base
60
+ @base || ensure_base
61
61
  end
62
62
 
63
63
  # Override number getter to trigger swap for standalone supplements
64
64
  def number
65
- # Guard against recursion in ensure_base_identifier
65
+ # Guard against recursion in ensure_base
66
66
  return @number if @ensuring_base
67
67
 
68
68
  # For standalone supplements, trigger base creation first
69
- ensure_base_identifier if @synthetic_base.nil? && publisher && part
69
+ ensure_base if @synthetic_base.nil? && publisher && part
70
70
 
71
71
  if @synthetic_base
72
72
  @supplement_number || @number
@@ -85,7 +85,7 @@ module Pubid
85
85
  end
86
86
  end
87
87
 
88
- # Delegate publisher and copublishers to base_identifier whenever there is
88
+ # Delegate publisher and copublishers to base whenever there is
89
89
  # a base (a supplement carries the publisher of the document it
90
90
  # supplements). Checking base first — rather than `@publisher || base` — is
91
91
  # required now that the publisher attribute has an IEC default, which would
@@ -93,20 +93,20 @@ module Pubid
93
93
  def publisher
94
94
  return @publisher if @ensuring_base
95
95
 
96
- base_identifier ? base_identifier.publisher : @publisher
96
+ base ? base.publisher : @publisher
97
97
  end
98
98
 
99
99
  def copublishers
100
100
  return @copublishers if @ensuring_base
101
101
 
102
- base_identifier ? base_identifier.copublishers : @copublishers
102
+ base ? base.copublishers : @copublishers
103
103
  end
104
104
 
105
- # Ensure we have a base_identifier for standalone supplements
105
+ # Ensure we have a base for standalone supplements
106
106
  # Creates a synthetic base identifier from supplement attributes if needed
107
- # Returns the base_identifier
108
- def ensure_base_identifier
109
- return @base_identifier if @base_identifier
107
+ # Returns the base
108
+ def ensure_base
109
+ return @base if @base
110
110
 
111
111
  # Guard flag to prevent recursion in number getter
112
112
  @ensuring_base = true
@@ -140,14 +140,14 @@ module Pubid
140
140
  stage_code: :undated,
141
141
  )
142
142
 
143
- @base_identifier = base
143
+ @base = base
144
144
 
145
145
  # Store the supplement number for getter override
146
- # The original number is the base number (moved to base_identifier)
146
+ # The original number is the base number (moved to base)
147
147
  # The original part is the supplement number (what we want to return)
148
148
  @supplement_number = supplement_number
149
149
 
150
- @base_identifier
150
+ @base
151
151
  ensure
152
152
  @ensuring_base = false
153
153
  end
@@ -160,6 +160,19 @@ module Pubid
160
160
  def to_s(**opts)
161
161
  render(format: :human, **opts)
162
162
  end
163
+
164
+ # MR supplement suffix: `/{type}.{number}.{year}` (e.g. "/amd.1.2016").
165
+ # The MrString renderer recurses into `base` and appends this so the
166
+ # full supplement chain round-trips losslessly (issue #142).
167
+ def mr_supplement_suffix
168
+ segments = []
169
+ segments << mr_type if mr_type
170
+ segments << number&.to_s if number
171
+ segments << date&.year&.to_s if date&.year
172
+ return nil if segments.empty?
173
+
174
+ segments.join(".")
175
+ end
163
176
  end
164
177
  end
165
178
  end
@@ -2,77 +2,243 @@
2
2
 
3
3
  module Pubid
4
4
  module Iec
5
- # Generates IEC URNs in the legacy positional format used as ground truth
6
- # by relaton-data-iec:
5
+ # Generates IEC URNs in the positional format used as ground truth by
6
+ # relaton-data-iec:
7
7
  #
8
- # urn:iec:std:{publisher}:{number}[-{part}]:{date}:{type}:{deliverable}:{language}[:{adjuncts}]
8
+ # urn:iec:std:{authority}:{number}[-{part}[-{subpart}]]
9
+ # :{date}:{stage-or-type}:{deliverable}:{language}{adjuncts}
9
10
  #
10
- # e.g. +urn:iec:std:iec:60050-102:2007:::+ (type after date; trailing empty
11
- # type/deliverable/language slots). This is a port of relaton-iec's
12
- # +Relaton::Iec.code_to_urn+ operating on +identifier.to_s+, which
13
- # round-trips faithfully. The all-parts series URN is the one exception: it
14
- # omits the language slot (8 fields), so it has a dedicated branch.
11
+ # e.g. +urn:iec:std:iec:60050-102:2007:::+. Absent trailing slots are
12
+ # emitted as empty fields. The all-parts series URN is the one exception:
13
+ # a bare series omits the language slot (8 fields).
14
+ #
15
+ # This used to be a port of relaton-iec's +code_to_urn+, which regex-scraped
16
+ # +identifier.to_s+. Three defects followed from reading the printed form:
17
+ # the stage was folded into the authority slot (+urn:iec:std:iec-np:...+),
18
+ # the edition was never emitted, and the regex was unanchored, so any type
19
+ # token outside its hard-coded list consumed the publisher instead
20
+ # (+IEC/DTS 62271-1+ became +urn:iec:std:dts:62271-1::::+, and every
21
+ # +IECEE TRF ...+ keyed +urn:iec:std:trf:...+). The generator now reads the
22
+ # identifier's own components. The slot ORDER is unchanged, because the
23
+ # published corpus uses it. See issue #360 item 4.
15
24
  class UrnGenerator < Pubid::UrnGenerator::Base
16
- # Deliverable markers occupying the positional deliverable slot.
17
- DELIVERABLES = /cmv|csv|exv|prv|rlv|ser/
25
+ URN_CONTEXT = Rendering::RenderingContext.urn.freeze
26
+ private_constant :URN_CONTEXT
27
+
28
+ # Type codes that occupy the type slot. `is` and `trf` render empty
29
+ # there, as they always have. `tec` and `wp` never appear in the corpus
30
+ # but the legacy grammar accepted them, so they stay recognised.
31
+ TYPE_SLOT_CODES = %w[tr ts pas srd guide tec wp].freeze
32
+
33
+ # Deliverable markers occupying the deliverable slot. "ser" reaches this
34
+ # list as a spelled-out VAP code ("IEC 60034:2026 SER"), which is not the
35
+ # same thing as the `all_parts` series form handled below.
36
+ DELIVERABLES = %w[cmv csv exv prv rlv ser].freeze
37
+
38
+ # Supplement classes that contribute an adjunct, and the token each one
39
+ # writes into it.
40
+ ADJUNCT_TOKENS = {
41
+ "Amendment" => "amd",
42
+ "Corrigendum" => "cor",
43
+ "InterpretationSheet" => "ish",
44
+ }.freeze
18
45
 
19
46
  def generate
20
- return series_urn if identifier.class.attributes.key?(:all_parts) && identifier.all_parts
47
+ doc = document
48
+ return nil if doc.nil?
21
49
 
22
- code_to_urn(identifier.to_s, urn_language)
50
+ num = number_segment(doc)
51
+ return nil if num.nil? || num.empty?
52
+
53
+ slots = ["urn", "iec", "std", authority(doc), num,
54
+ date_slot(doc), stage_or_type_slot(doc), deliverable_slot]
55
+ adjuncts = adjunct_slots(identifier)
56
+ language = language_slot
57
+ slots << language unless bare_series?(slots, adjuncts, language)
58
+
59
+ (slots + adjuncts).join(":").downcase
23
60
  end
24
61
 
25
62
  private
26
63
 
27
- # Hyphen-joined language codes (e.g. "en-fr"), or nil when unset.
28
- def urn_language
29
- return nil unless identifier.class.attributes.key?(:languages)
30
-
31
- langs = identifier.languages
32
- return nil unless langs&.any?
33
-
34
- langs.map(&:code).join("-")
35
- end
36
-
37
- # The all-parts series URN drops the language slot and carries no part or
38
- # date: urn:iec:std:iec:80000:::ser.
39
- def series_urn
40
- code = identifier.to_s.sub(/\s*\(all parts\)\s*\z/, "")
41
- m = code.downcase.match(/(?<head>\S+)\s+(?<pnum>[\d-]+)/)
42
- head = m[:head].split("/").join("-")
43
- ["urn", "iec", "std", head, m[:pnum], "", "", "ser"].join(":")
44
- end
45
-
46
- # Port of Relaton::Iec.code_to_urn.
47
- def code_to_urn(code, lang = nil)
48
- rest = code.downcase.sub(%r{
49
- (?<head>[^\s]+)\s
50
- (?<type>is|ts|tr|pas|srd|guide|tec|wp)?(?(<type>)\s)
51
- (?<pnum>[\d-]+)\s?
52
- (?<_dd>:)?(?(<_dd>)(?<date>[\d-]+)\s?)
53
- }x, "")
54
- m = $~
55
- return unless m && m[:head] && m[:pnum]
56
-
57
- deliv = DELIVERABLES.match(code.downcase).to_s
58
- urn = ["urn", "iec", "std", m[:head].split("/").join("-"), m[:pnum],
59
- m[:date], m[:type], deliv, lang]
60
- (urn + adjunct_to_urn(rest)).join(":")
61
- end
62
-
63
- # Port of Relaton::Iec.ajunct_to_urn — recursively emits amd/cor/ish
64
- # adjuncts, prefixing "plus" for the "+" (consolidated) relation.
65
- def adjunct_to_urn(rest)
66
- r = rest.sub(%r{
67
- (?<pl>\+|/)(?(<pl>)(?<adjunct>(?:amd|cor|ish))(?<adjnum>\d+)\s?)
68
- (?<_d2>:)?(?(<_d2>)(?<adjdt>[\d-]+)\s?)
69
- }x, "")
70
- m = $~ || {}
71
- return [] unless m[:adjunct]
72
-
73
- plus = "plus" if m[:pl] == "+"
74
- urn = [plus, m[:adjunct], m[:adjnum], m[:adjdt]]
75
- urn + adjunct_to_urn(r)
64
+ # The document the URN names: the origin standard, with every amendment,
65
+ # corrigendum, consolidation, VAP and fragment layer peeled off. Those
66
+ # layers are what the adjunct and deliverable slots record.
67
+ #
68
+ # A CISPR test report form carries no number of its own — the document it
69
+ # reports on sits in `cispr_identifier`, and that is what the URN has
70
+ # always named.
71
+ def document
72
+ doc = identifier.respond_to?(:root) ? identifier.root : identifier
73
+ return doc if doc.nil? || number_segment(doc)
74
+
75
+ maybe_of(doc, :cispr_identifier) || doc
76
+ end
77
+
78
+ # A publisher body may carry a space ("IEC CA", "IECQ CS", "IECQ OD").
79
+ # The published corpus records only the last token for those
80
+ # (+urn:iec:std:ca:01:2017:::+), which is what the old whitespace-
81
+ # splitting regex produced. Keeping that spelling is what keeps those
82
+ # rows byte-identical; correcting it to "iec-ca" would need a data
83
+ # migration first.
84
+ def authority(doc)
85
+ publishers = [doc.publisher] + Array(doc.copublishers)
86
+ publishers.compact.map { |p| p.body.to_s.split(/\s+/).last.to_s }
87
+ .reject(&:empty?).join("-")
88
+ end
89
+
90
+ def number_segment(doc)
91
+ return nil unless doc.respond_to?(:number) && doc.number
92
+
93
+ segment = [doc.number, maybe_of(doc, :part), maybe_of(doc, :subpart)]
94
+ .compact.map(&:to_s).reject(&:empty?).join("-")
95
+ return nil if segment.empty?
96
+
97
+ # A few document numbers are multi-word ("DIR 1 IEC SUP"). A URN
98
+ # carries no spaces, so they become hyphens.
99
+ segment.gsub(/\s+/, "-")
100
+ end
101
+
102
+ # `Components::Date#render` under a URN context deliberately drops the
103
+ # month, which is the ISO convention. IEC keeps the precision it was
104
+ # given ("IEC CA 01:2025-10" keys ...:2025-10:...), so this reads the
105
+ # printed form.
106
+ def date_slot(doc)
107
+ maybe_of(doc, :date).to_s
108
+ end
109
+
110
+ # The stage slot and the type slot are the same slot, and a draft of a
111
+ # typed document has both. Both are kept, type first
112
+ # ("ts-stage-50.00"), because the harmonized codes are shared across
113
+ # types: dropping the type would make a draft TS, a draft TR and a draft
114
+ # International Standard collide, and `parse_urn` would resolve every one
115
+ # of them to an International Standard.
116
+ def stage_or_type_slot(doc)
117
+ type = type_token(doc)
118
+ stage = stage_token(doc)
119
+
120
+ return type if stage.nil?
121
+
122
+ [type, stage].reject { |t| t.nil? || t.empty? }.join("-")
123
+ end
124
+
125
+ def type_token(doc)
126
+ ts = maybe_of(doc, :typed_stage)
127
+ code = ts&.type_code.to_s.downcase
128
+ TYPE_SLOT_CODES.include?(code) ? code : ""
129
+ end
130
+
131
+ # nil when the document is published (or carries no stage at all), so the
132
+ # slot keeps holding the bare type token for every published row.
133
+ def stage_token(doc)
134
+ stage = maybe_of(doc, :typed_stage)&.to_stage || maybe_of(doc, :stage)
135
+ harmonized = stage&.harmonized_stages&.first.to_s
136
+ return nil if harmonized.empty?
137
+ return nil if published_stage?(stage)
138
+
139
+ "stage-#{harmonized}"
140
+ end
141
+
142
+ def published_stage?(stage)
143
+ stage.stage_code.to_s == "published"
144
+ end
145
+
146
+ # A deliverable code owns the slot; the edition takes it only when there
147
+ # is none.
148
+ def deliverable_slot
149
+ return "ser" if maybe_of(identifier, :all_parts)
150
+
151
+ vap = vap_codes
152
+ return vap unless vap.empty?
153
+
154
+ edition = maybe_of(identifier, :edition)
155
+ return "" unless edition&.number
156
+
157
+ edition.render(context: URN_CONTEXT).to_s
158
+ end
159
+
160
+ # A deliverable sits on the VAP layer, which is not always the outermost
161
+ # one: "IEC 60079-10-1:2020 CMV/COR1:2021" is a corrigendum wrapping the
162
+ # CMV, so the codes have to be looked for down the chain.
163
+ def vap_codes
164
+ codes = find_down(:vap)
165
+ return "" unless codes
166
+
167
+ Array(codes).map { |c| c.to_s.downcase }
168
+ .select { |c| DELIVERABLES.include?(c) }.join("-")
169
+ end
170
+
171
+ # First non-empty value of `attribute` from the outermost identifier
172
+ # inwards.
173
+ def find_down(attribute)
174
+ id = identifier
175
+ while id
176
+ value = maybe_of(id, attribute)
177
+ return value unless value.nil? ||
178
+ (value.respond_to?(:empty?) && value.empty?)
179
+
180
+ id = maybe_of(id, :base) ||
181
+ Array(maybe_of(id, :identifiers)).first
182
+ end
183
+ nil
184
+ end
185
+
186
+ def language_slot
187
+ langs = maybe_of(identifier, :languages)
188
+ return "" unless langs&.any?
189
+
190
+ langs.map { |l| l.code.to_s }.join("-")
191
+ end
192
+
193
+ # A bare, undated, stage- and language-less all-parts series drops the
194
+ # trailing empty language slot, matching the canonical relaton-data-iec
195
+ # form urn:iec:std:iec:80000:::ser. A dated series, or one carrying a
196
+ # stage, keeps the slot.
197
+ def bare_series?(slots, adjuncts, language)
198
+ slots.last == "ser" && slots[5, 2].all? { |s| s.to_s.empty? } &&
199
+ adjuncts.empty? && language.empty?
200
+ end
201
+
202
+ # Walks the identifier tree for the amendment / corrigendum /
203
+ # interpretation-sheet layers, innermost first. A member of a
204
+ # consolidated identifier carries the "plus" relation marker, which the
205
+ # printed form spells "+".
206
+ def adjunct_slots(id)
207
+ return [] if id.nil?
208
+
209
+ case id.class.name.split("::").last
210
+ when "ConsolidatedIdentifier"
211
+ members = Array(id.identifiers)
212
+ adjunct_slots(members.first) +
213
+ members.drop(1).flat_map { |m| adjunct_fields(m, plus: true) }
214
+ when *ADJUNCT_TOKENS.keys
215
+ adjunct_slots(id.base) + adjunct_fields(id, plus: false)
216
+ else
217
+ adjunct_slots(id.respond_to?(:base) ? id.base : nil)
218
+ end
219
+ end
220
+
221
+ def adjunct_fields(id, plus:)
222
+ token = ADJUNCT_TOKENS[id.class.name.split("::").last]
223
+ return adjunct_slots(id.respond_to?(:base) ? id.base : nil) unless token
224
+
225
+ [plus ? "plus" : "", token, id.number.to_s,
226
+ maybe_of(id, :date)&.render(context: URN_CONTEXT).to_s]
227
+ end
228
+
229
+ # Not every IEC class declares every attribute, and a wrapper may not
230
+ # declare one its base does. The `respond_to?` guard covers the missing
231
+ # attribute; the rescue covers an attribute that exists but nil-chases
232
+ # while resolving — `SupplementIdentifier#number` runs `ensure_base` and
233
+ # reads through a base that may not be built yet. It is deliberately
234
+ # narrow: a broader rescue would swallow a real bug into a silently
235
+ # empty URN slot instead of failing loudly.
236
+ def maybe_of(id, attribute)
237
+ return nil unless id.respond_to?(attribute)
238
+
239
+ id.public_send(attribute)
240
+ rescue NoMethodError
241
+ nil
76
242
  end
77
243
  end
78
244
  end
@@ -31,16 +31,24 @@ module Pubid
31
31
  # @return [Identifier] parsed identifier
32
32
  def parse_urn(urn)
33
33
  unless urn.start_with?("urn:iec:std:")
34
- raise Errors::ParseError, "Invalid IEC URN: #{urn}"
34
+ raise Pubid::UrnParser::Errors::ParseError, "Invalid IEC URN: #{urn}"
35
35
  end
36
36
 
37
37
  code, lang, all_parts = urn_to_code(urn)
38
- raise Errors::ParseError, "Invalid IEC URN: #{urn}" unless code
38
+ unless code
39
+ raise Pubid::UrnParser::Errors::ParseError,
40
+ "Invalid IEC URN: #{urn}"
41
+ end
39
42
 
40
43
  id = Pubid::Iec::Identifier.parse(code)
41
44
  id.all_parts = true if all_parts && id.class.attributes.key?(:all_parts)
45
+ # The language slot joins codes with a hyphen ("en-fr"). Building one
46
+ # Language from the whole field gave a single bogus language that
47
+ # rendered as "(en-fr)".
42
48
  if lang && !lang.empty? && id.class.attributes.key?(:languages)
43
- id.languages = [::Pubid::Components::Language.new(code: lang)]
49
+ id.languages = lang.split("-").map do |code|
50
+ ::Pubid::Components::Language.new(code: code)
51
+ end
44
52
  end
45
53
  id
46
54
  end
@@ -57,7 +65,8 @@ module Pubid
57
65
  all_parts = false
58
66
 
59
67
  code = head.gsub("-", "/")
60
- code += " #{type}" unless type.nil? || type.empty?
68
+ type_code = type_slot_to_code(type)
69
+ code += " #{type_code}" unless type_code.empty?
61
70
  code += " #{num}"
62
71
  code += ":#{date}" unless date.nil? || date.empty?
63
72
  code += adjunct_to_code(fields[9..])
@@ -67,6 +76,8 @@ module Pubid
67
76
  # part or date, so to_s renders "IEC NNNN (all parts)").
68
77
  if deliv&.casecmp("SER")&.zero?
69
78
  all_parts = true
79
+ elsif (edition = edition_slot_to_code(deliv))
80
+ code += " #{edition}"
70
81
  elsif deliv && !deliv.empty?
71
82
  code += " #{deliv}"
72
83
  end
@@ -74,6 +85,33 @@ module Pubid
74
85
  [code, lang&.downcase, all_parts]
75
86
  end
76
87
 
88
+ # The type slot holds either the legacy type token ("TS"), a stage
89
+ # ("STAGE-10.20"), or both ("TS-STAGE-50.00"). A stage is written back as
90
+ # the abbreviation the grammar accepts, resolved from the registry by
91
+ # type code and harmonized code — so the round trip is exact in both
92
+ # directions. See issue #360 item 4.
93
+ def type_slot_to_code(type)
94
+ return "" if type.nil? || type.empty?
95
+
96
+ match = /\A(?:([A-Z]+)-)?STAGE-([\d.]+)\z/.match(type)
97
+ return type unless match
98
+
99
+ type_code = (match[1] || "IS").downcase
100
+ stage = Pubid::Iec.all_typed_stages.find do |s|
101
+ s.type_code.to_s == type_code &&
102
+ s.harmonized_stages&.first.to_s == match[2]
103
+ end
104
+ return "" unless stage
105
+
106
+ stage.abbr.first.to_s
107
+ end
108
+
109
+ # "ED-7" in the deliverable slot is an edition, not a deliverable code.
110
+ def edition_slot_to_code(deliv)
111
+ match = /\AED-(.+)\z/.match(deliv.to_s)
112
+ match && "ED#{match[1]}"
113
+ end
114
+
77
115
  # Port of Relaton::Iec.ajanct_to_code — recursively rebuilds amd/cor/ish
78
116
  # adjuncts from (relation, type, number, date) quartets. A "PLUS"
79
117
  # relation token (the consolidated "+" marker) yields "+"; otherwise "/".
data/lib/pubid/iec.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Iec
5
6
  autoload :Components, "#{__dir__}/iec/components"
@@ -23,12 +24,7 @@ module Pubid
23
24
  autoload :Renderer, "#{__dir__}/iec/renderer"
24
25
 
25
26
  def self.parse(identifier_string)
26
- if identifier_string.length > Pubid::MAX_INPUT_LENGTH
27
- raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
28
- end
29
-
30
- parsed = Parser.new.parse(identifier_string)
31
- Builder.new.build(parsed)
27
+ Identifier.parse(identifier_string)
32
28
  end
33
29
 
34
30
  def self.parse_urn(urn)
@@ -23,7 +23,7 @@ module Pubid
23
23
  end
24
24
 
25
25
  # Extract code
26
- code_str = extract_value(parsed[:number])
26
+ code_str = extract_number(parsed[:number])
27
27
  if code_str
28
28
  attributes[:code] = Components::Code.parse(code_str)
29
29
  end
@@ -36,9 +36,11 @@ module Pubid
36
36
  month_str = extract_value(parsed[:month])
37
37
  attributes[:month] = month_str if month_str
38
38
 
39
- # Extract separator (for rendering distinction)
39
+ # Extract the long-form date separator ("," or ".") for rendering.
40
+ # Named `date_separator` on the identifier to avoid colliding with the
41
+ # CodeNumber code-part `separator`.
40
42
  separator_str = extract_value(parsed[:separator])
41
- attributes[:separator] = separator_str if separator_str
43
+ attributes[:date_separator] = separator_str if separator_str
42
44
 
43
45
  # Set original format based on parsed data
44
46
  attributes[:original_format] = if separator_str || month_str
@@ -53,6 +55,18 @@ module Pubid
53
55
 
54
56
  private
55
57
 
58
+ # Extract the number, flattening a "431 (105)" main-number/parenthetical
59
+ # subtree into a plain string. Without this, a Hash node leaks its raw
60
+ # Parslet inspect form (e.g. `{main_number: "431"@8, ...}`) into `to_s`.
61
+ def extract_number(value)
62
+ return extract_value(value) unless value.is_a?(Hash)
63
+
64
+ main = extract_value(value[:main_number])
65
+ paren = value[:parenthetical]
66
+ alt = paren.is_a?(Hash) ? extract_value(paren[:alt_number]) : nil
67
+ alt ? "#{main} (#{alt})" : main
68
+ end
69
+
56
70
  def extract_value(value)
57
71
  return nil if value.nil?
58
72
  return nil if value.is_a?(Array) && value.empty?