pubid 2.0.0.pre.alpha.7 → 2.0.0.pre.alpha.9

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 (485) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +9 -50
  3. data/data/bipm/update_codes.yaml +9 -0
  4. data/data/iec/update_codes.yaml +3 -0
  5. data/data/ieee/update_codes.yaml +107 -1
  6. data/data/nist/series.yaml +155 -0
  7. data/data/nist/update_codes.yaml +8 -0
  8. data/lib/pubid/adobe/builder.rb +52 -0
  9. data/lib/pubid/adobe/identifier.rb +49 -0
  10. data/lib/pubid/adobe/identifiers/publication.rb +31 -0
  11. data/lib/pubid/adobe/identifiers/tech_note.rb +32 -0
  12. data/lib/pubid/adobe/identifiers.rb +10 -0
  13. data/lib/pubid/adobe/parser.rb +128 -0
  14. data/lib/pubid/adobe/renderer.rb +39 -0
  15. data/lib/pubid/adobe/urn_generator.rb +42 -0
  16. data/lib/pubid/adobe/urn_parser.rb +69 -0
  17. data/lib/pubid/adobe.rb +60 -0
  18. data/lib/pubid/amca/builder.rb +2 -2
  19. data/lib/pubid/amca/identifier.rb +1 -3
  20. data/lib/pubid/amca/identifiers/base.rb +1 -6
  21. data/lib/pubid/amca/identifiers/interpretation.rb +1 -1
  22. data/lib/pubid/amca/identifiers/publication.rb +1 -1
  23. data/lib/pubid/amca/identifiers/standard.rb +1 -1
  24. data/lib/pubid/amca/identifiers.rb +0 -1
  25. data/lib/pubid/amca/single_identifier.rb +1 -1
  26. data/lib/pubid/amca.rb +3 -3
  27. data/lib/pubid/ashrae/builder.rb +22 -22
  28. data/lib/pubid/ashrae/identifier.rb +3 -4
  29. data/lib/pubid/ashrae/identifiers/addenda_package.rb +1 -1
  30. data/lib/pubid/ashrae/identifiers/addendum.rb +1 -1
  31. data/lib/pubid/ashrae/identifiers/base.rb +14 -8
  32. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +1 -1
  33. data/lib/pubid/ashrae/identifiers.rb +0 -1
  34. data/lib/pubid/ashrae/parser.rb +14 -9
  35. data/lib/pubid/ashrae/renderer.rb +19 -19
  36. data/lib/pubid/ashrae/single_identifier.rb +1 -1
  37. data/lib/pubid/ashrae/supplement_identifier.rb +6 -6
  38. data/lib/pubid/ashrae.rb +3 -3
  39. data/lib/pubid/bipm/builder.rb +107 -0
  40. data/lib/pubid/bipm/identifier.rb +160 -0
  41. data/lib/pubid/bipm/identifiers/committee_document.rb +24 -0
  42. data/lib/pubid/bipm/identifiers/guide.rb +24 -0
  43. data/lib/pubid/bipm/identifiers/meeting.rb +41 -0
  44. data/lib/pubid/bipm/identifiers/mep.rb +21 -0
  45. data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
  46. data/lib/pubid/bipm/identifiers/si_brochure.rb +20 -0
  47. data/lib/pubid/bipm/identifiers.rb +15 -0
  48. data/lib/pubid/bipm/parser.rb +184 -0
  49. data/lib/pubid/bipm/renderer.rb +110 -0
  50. data/lib/pubid/bipm/urn_generator.rb +58 -0
  51. data/lib/pubid/bipm/urn_parser.rb +52 -0
  52. data/lib/pubid/bipm.rb +86 -0
  53. data/lib/pubid/bsi/builder.rb +14 -14
  54. data/lib/pubid/bsi/identifier.rb +0 -1
  55. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -2
  56. data/lib/pubid/bsi/identifiers/amendment.rb +4 -4
  57. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +6 -0
  58. data/lib/pubid/bsi/identifiers/corrigendum.rb +4 -4
  59. data/lib/pubid/bsi/identifiers/expert_commentary.rb +5 -5
  60. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -2
  61. data/lib/pubid/bsi/identifiers/value_added_publication.rb +6 -6
  62. data/lib/pubid/bsi/renderer.rb +8 -8
  63. data/lib/pubid/bsi/single_identifier.rb +48 -0
  64. data/lib/pubid/builder/base.rb +5 -3
  65. data/lib/pubid/bundled_identifier.rb +3 -3
  66. data/lib/pubid/calconnect/builder.rb +38 -0
  67. data/lib/pubid/calconnect/identifier.rb +117 -0
  68. data/lib/pubid/calconnect/identifiers/standard.rb +29 -0
  69. data/lib/pubid/calconnect/identifiers.rb +9 -0
  70. data/lib/pubid/calconnect/parser.rb +54 -0
  71. data/lib/pubid/calconnect/renderer.rb +36 -0
  72. data/lib/pubid/calconnect/urn_generator.rb +33 -0
  73. data/lib/pubid/calconnect/urn_parser.rb +34 -0
  74. data/lib/pubid/calconnect.rb +77 -0
  75. data/lib/pubid/ccsds/builder.rb +1 -1
  76. data/lib/pubid/ccsds/identifier.rb +1 -1
  77. data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
  78. data/lib/pubid/ccsds/supplement_identifier.rb +6 -6
  79. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  80. data/lib/pubid/cen_cenelec/builder.rb +46 -12
  81. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -2
  82. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +6 -0
  83. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -2
  84. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +60 -3
  85. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  86. data/lib/pubid/cen_cenelec/renderer.rb +5 -5
  87. data/lib/pubid/cen_cenelec/supplement_identifier.rb +5 -5
  88. data/lib/pubid/cen_cenelec/urn_generator.rb +1 -1
  89. data/lib/pubid/cen_cenelec.rb +76 -72
  90. data/lib/pubid/cie/builder.rb +139 -24
  91. data/lib/pubid/cie/identifier.rb +7 -3
  92. data/lib/pubid/cie/identifiers/bundle.rb +32 -4
  93. data/lib/pubid/cie/identifiers/code_attributes.rb +52 -0
  94. data/lib/pubid/cie/identifiers/conference.rb +9 -4
  95. data/lib/pubid/cie/identifiers/corrigendum.rb +17 -23
  96. data/lib/pubid/cie/identifiers/dual_published.rb +4 -4
  97. data/lib/pubid/cie/identifiers/identical.rb +7 -7
  98. data/lib/pubid/cie/identifiers/joint_published.rb +8 -8
  99. data/lib/pubid/cie/identifiers/proceedings.rb +39 -0
  100. data/lib/pubid/cie/identifiers/standard.rb +33 -7
  101. data/lib/pubid/cie/identifiers/supplement.rb +24 -22
  102. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +6 -2
  103. data/lib/pubid/cie/identifiers.rb +2 -0
  104. data/lib/pubid/cie/parser.rb +54 -5
  105. data/lib/pubid/cie/single_identifier.rb +40 -1
  106. data/lib/pubid/cie/supplement_identifier.rb +29 -16
  107. data/lib/pubid/cie/urn_generator.rb +11 -8
  108. data/lib/pubid/cie.rb +0 -1
  109. data/lib/pubid/components/date.rb +21 -5
  110. data/lib/pubid/csa/builder.rb +1 -1
  111. data/lib/pubid/csa/composite_identifier.rb +17 -1
  112. data/lib/pubid/csa/identifier.rb +48 -3
  113. data/lib/pubid/csa/identifiers/bundled.rb +6 -0
  114. data/lib/pubid/csa/identifiers/combined.rb +6 -0
  115. data/lib/pubid/csa/identifiers/package.rb +2 -2
  116. data/lib/pubid/csa/parser.rb +6 -6
  117. data/lib/pubid/csa/wrapper_identifier.rb +17 -0
  118. data/lib/pubid/doi/builder.rb +18 -0
  119. data/lib/pubid/doi/identifier.rb +46 -0
  120. data/lib/pubid/doi/identifiers/resource.rb +30 -0
  121. data/lib/pubid/doi/identifiers.rb +9 -0
  122. data/lib/pubid/doi/parser.rb +52 -0
  123. data/lib/pubid/doi/renderer.rb +13 -0
  124. data/lib/pubid/doi.rb +55 -0
  125. data/lib/pubid/easc/builder.rb +55 -0
  126. data/lib/pubid/easc/identifier.rb +61 -0
  127. data/lib/pubid/easc/identifiers/pmg.rb +20 -0
  128. data/lib/pubid/easc/identifiers/rmg.rb +19 -0
  129. data/lib/pubid/easc/identifiers.rb +10 -0
  130. data/lib/pubid/easc/parser.rb +80 -0
  131. data/lib/pubid/easc/renderer.rb +48 -0
  132. data/lib/pubid/easc/urn_generator.rb +46 -0
  133. data/lib/pubid/easc/urn_parser.rb +57 -0
  134. data/lib/pubid/easc.rb +52 -0
  135. data/lib/pubid/ecma/builder.rb +31 -0
  136. data/lib/pubid/ecma/identifier.rb +76 -0
  137. data/lib/pubid/ecma/identifiers/memento.rb +30 -0
  138. data/lib/pubid/ecma/identifiers/standard.rb +31 -0
  139. data/lib/pubid/ecma/identifiers/technical_report.rb +31 -0
  140. data/lib/pubid/ecma/identifiers.rb +11 -0
  141. data/lib/pubid/ecma/parser.rb +41 -0
  142. data/lib/pubid/ecma/renderer.rb +46 -0
  143. data/lib/pubid/ecma/urn_generator.rb +25 -0
  144. data/lib/pubid/ecma/urn_parser.rb +35 -0
  145. data/lib/pubid/ecma.rb +67 -0
  146. data/lib/pubid/etsi/builder.rb +7 -3
  147. data/lib/pubid/etsi/identifier.rb +1 -3
  148. data/lib/pubid/etsi/identifiers/base.rb +28 -10
  149. data/lib/pubid/etsi/identifiers/etsi_standard.rb +128 -4
  150. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +35 -3
  151. data/lib/pubid/etsi/identifiers.rb +0 -1
  152. data/lib/pubid/etsi/parser.rb +8 -2
  153. data/lib/pubid/etsi/renderer.rb +8 -2
  154. data/lib/pubid/etsi.rb +5 -5
  155. data/lib/pubid/export/exporter.rb +2 -1
  156. data/lib/pubid/export/flavor_exporter.rb +18 -3
  157. data/lib/pubid/gb/builder.rb +45 -0
  158. data/lib/pubid/gb/identifier.rb +64 -0
  159. data/lib/pubid/gb/identifiers/standard.rb +34 -0
  160. data/lib/pubid/gb/identifiers.rb +9 -0
  161. data/lib/pubid/gb/parser.rb +63 -0
  162. data/lib/pubid/gb/renderer.rb +35 -0
  163. data/lib/pubid/gb.rb +87 -0
  164. data/lib/pubid/gost/builder.rb +148 -0
  165. data/lib/pubid/gost/identifier.rb +49 -0
  166. data/lib/pubid/gost/identifiers/foreign_reference.rb +25 -0
  167. data/lib/pubid/gost/identifiers/harmonized.rb +39 -0
  168. data/lib/pubid/gost/identifiers/identical_adoption.rb +39 -0
  169. data/lib/pubid/gost/identifiers/interstate_standard.rb +20 -0
  170. data/lib/pubid/gost/identifiers/national_standard.rb +19 -0
  171. data/lib/pubid/gost/identifiers.rb +13 -0
  172. data/lib/pubid/gost/parser.rb +97 -0
  173. data/lib/pubid/gost/renderer.rb +48 -0
  174. data/lib/pubid/gost/urn_generator.rb +46 -0
  175. data/lib/pubid/gost/urn_parser.rb +52 -0
  176. data/lib/pubid/gost.rb +49 -0
  177. data/lib/pubid/iala/builder.rb +22 -27
  178. data/lib/pubid/iala/identifier.rb +27 -2
  179. data/lib/pubid/iala/identifiers/advice.rb +1 -1
  180. data/lib/pubid/iala/identifiers/annex.rb +14 -12
  181. data/lib/pubid/iala/identifiers/general_assembly.rb +5 -2
  182. data/lib/pubid/iala/identifiers/guideline.rb +3 -1
  183. data/lib/pubid/iala/identifiers/letter.rb +1 -1
  184. data/lib/pubid/iala/identifiers/manual.rb +3 -1
  185. data/lib/pubid/iala/identifiers/model_course.rb +3 -1
  186. data/lib/pubid/iala/identifiers/recommendation.rb +3 -1
  187. data/lib/pubid/iala/identifiers/report.rb +1 -1
  188. data/lib/pubid/iala/identifiers/resolution.rb +1 -1
  189. data/lib/pubid/iala/identifiers/standard.rb +3 -1
  190. data/lib/pubid/iala/identifiers.rb +0 -1
  191. data/lib/pubid/iala/renderer.rb +1 -1
  192. data/lib/pubid/iala/urn_generator.rb +1 -1
  193. data/lib/pubid/iala/urn_parser.rb +19 -2
  194. data/lib/pubid/iala.rb +4 -4
  195. data/lib/pubid/iana/builder.rb +20 -0
  196. data/lib/pubid/iana/identifier.rb +72 -0
  197. data/lib/pubid/iana/identifiers/registry.rb +33 -0
  198. data/lib/pubid/iana/identifiers.rb +9 -0
  199. data/lib/pubid/iana/parser.rb +38 -0
  200. data/lib/pubid/iana/renderer.rb +29 -0
  201. data/lib/pubid/iana/urn_generator.rb +15 -0
  202. data/lib/pubid/iana/urn_parser.rb +24 -0
  203. data/lib/pubid/iana.rb +69 -0
  204. data/lib/pubid/identifier.rb +210 -23
  205. data/lib/pubid/idf/builder.rb +1 -1
  206. data/lib/pubid/idf/parser.rb +2 -2
  207. data/lib/pubid/idf/renderer.rb +1 -1
  208. data/lib/pubid/idf/supplement_identifier.rb +3 -3
  209. data/lib/pubid/iec/builder.rb +35 -25
  210. data/lib/pubid/iec/identifier.rb +47 -2
  211. data/lib/pubid/iec/identifiers/base.rb +2 -2
  212. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +6 -0
  213. data/lib/pubid/iec/identifiers/fragment_identifier.rb +11 -11
  214. data/lib/pubid/iec/identifiers/international_standard.rb +8 -5
  215. data/lib/pubid/iec/identifiers/sheet_identifier.rb +12 -12
  216. data/lib/pubid/iec/identifiers/technical_group.rb +30 -0
  217. data/lib/pubid/iec/identifiers/technical_report.rb +1 -1
  218. data/lib/pubid/iec/identifiers/technical_specification.rb +1 -1
  219. data/lib/pubid/iec/identifiers/vap_identifier.rb +12 -12
  220. data/lib/pubid/iec/identifiers.rb +1 -0
  221. data/lib/pubid/iec/parser.rb +51 -10
  222. data/lib/pubid/iec/renderer.rb +18 -8
  223. data/lib/pubid/iec/single_identifier.rb +1 -1
  224. data/lib/pubid/iec/supplement_identifier.rb +32 -19
  225. data/lib/pubid/iec.rb +1 -6
  226. data/lib/pubid/ieee/aiee/builder.rb +17 -3
  227. data/lib/pubid/ieee/aiee/identifier.rb +45 -61
  228. data/lib/pubid/ieee/builder.rb +341 -68
  229. data/lib/pubid/ieee/compaction.rb +121 -0
  230. data/lib/pubid/ieee/components/draft.rb +47 -7
  231. data/lib/pubid/ieee/identifier.rb +1 -3
  232. data/lib/pubid/ieee/identifiers/adopted_standard.rb +30 -5
  233. data/lib/pubid/ieee/identifiers/amendment.rb +40 -0
  234. data/lib/pubid/ieee/identifiers/base.rb +106 -13
  235. data/lib/pubid/ieee/identifiers/code_number.rb +82 -0
  236. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +6 -2
  237. data/lib/pubid/ieee/identifiers/corrigendum.rb +17 -2
  238. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +3 -3
  239. data/lib/pubid/ieee/identifiers/dual_identifier.rb +3 -3
  240. data/lib/pubid/ieee/identifiers/dual_published.rb +3 -3
  241. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +102 -5
  242. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +2 -1
  243. data/lib/pubid/ieee/identifiers/joint_development.rb +56 -11
  244. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -1
  245. data/lib/pubid/ieee/identifiers/nesc/base.rb +90 -19
  246. data/lib/pubid/ieee/identifiers/nesc/draft.rb +20 -5
  247. data/lib/pubid/ieee/identifiers/nesc/edition.rb +32 -0
  248. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +16 -5
  249. data/lib/pubid/ieee/identifiers/nesc/redline.rb +11 -2
  250. data/lib/pubid/ieee/identifiers/nesc/standard.rb +18 -3
  251. data/lib/pubid/ieee/identifiers/nesc.rb +1 -0
  252. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +3 -3
  253. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +14 -6
  254. data/lib/pubid/ieee/identifiers/redlined_standard.rb +4 -4
  255. data/lib/pubid/ieee/identifiers/si_standard.rb +4 -1
  256. data/lib/pubid/ieee/identifiers/standard.rb +4 -1
  257. data/lib/pubid/ieee/identifiers/supplement_identifier.rb +26 -7
  258. data/lib/pubid/ieee/identifiers.rb +2 -1
  259. data/lib/pubid/ieee/ire/builder.rb +7 -6
  260. data/lib/pubid/ieee/ire/identifier.rb +48 -33
  261. data/lib/pubid/ieee/nesc/builder.rb +33 -20
  262. data/lib/pubid/ieee/nesc/parser.rb +15 -14
  263. data/lib/pubid/ieee/parser.rb +461 -43
  264. data/lib/pubid/ieee/pre_parser.rb +1 -1
  265. data/lib/pubid/ieee/renderer.rb +154 -57
  266. data/lib/pubid/ieee/typed_stages.rb +12 -1
  267. data/lib/pubid/ieee/urn_generator.rb +3 -5
  268. data/lib/pubid/ieee.rb +56 -3
  269. data/lib/pubid/ietf/builder.rb +62 -0
  270. data/lib/pubid/ietf/identifier.rb +5 -0
  271. data/lib/pubid/ietf/identifiers/base.rb +75 -0
  272. data/lib/pubid/ietf/identifiers/bcp.rb +25 -0
  273. data/lib/pubid/ietf/identifiers/fyi.rb +25 -0
  274. data/lib/pubid/ietf/identifiers/internet_draft.rb +29 -0
  275. data/lib/pubid/ietf/identifiers/rfc.rb +25 -0
  276. data/lib/pubid/ietf/identifiers/std.rb +25 -0
  277. data/lib/pubid/ietf/identifiers.rb +13 -0
  278. data/lib/pubid/ietf/parser.rb +43 -0
  279. data/lib/pubid/ietf/renderer.rb +26 -0
  280. data/lib/pubid/ietf/urn_generator.rb +23 -0
  281. data/lib/pubid/ietf/urn_parser.rb +35 -0
  282. data/lib/pubid/ietf.rb +76 -0
  283. data/lib/pubid/iho/identifier.rb +1 -3
  284. data/lib/pubid/iho/identifiers/base.rb +1 -7
  285. data/lib/pubid/iho/identifiers/bibliographic.rb +1 -1
  286. data/lib/pubid/iho/identifiers/circular_letter.rb +1 -1
  287. data/lib/pubid/iho/identifiers/miscellaneous.rb +1 -1
  288. data/lib/pubid/iho/identifiers/publication.rb +1 -1
  289. data/lib/pubid/iho/identifiers/standard.rb +1 -1
  290. data/lib/pubid/iho/identifiers.rb +0 -1
  291. data/lib/pubid/iho.rb +7 -7
  292. data/lib/pubid/isbn/builder.rb +44 -0
  293. data/lib/pubid/isbn/check_digit.rb +53 -0
  294. data/lib/pubid/isbn/identifier.rb +63 -0
  295. data/lib/pubid/isbn/identifiers/book.rb +30 -0
  296. data/lib/pubid/isbn/identifiers.rb +9 -0
  297. data/lib/pubid/isbn/parser.rb +45 -0
  298. data/lib/pubid/isbn/renderer.rb +16 -0
  299. data/lib/pubid/isbn.rb +52 -0
  300. data/lib/pubid/iso/builder.rb +9 -4
  301. data/lib/pubid/iso/combined_identifier.rb +2 -2
  302. data/lib/pubid/iso/identifier.rb +17 -1
  303. data/lib/pubid/iso/identifiers/directives_supplement.rb +8 -8
  304. data/lib/pubid/iso/normalizer.rb +2 -2
  305. data/lib/pubid/iso/parser.rb +16 -12
  306. data/lib/pubid/iso/supplement_identifier.rb +19 -6
  307. data/lib/pubid/iso/urn_generator.rb +4 -1
  308. data/lib/pubid/iso/urn_parser.rb +1 -1
  309. data/lib/pubid/itu/builder.rb +230 -29
  310. data/lib/pubid/itu/components/code.rb +48 -5
  311. data/lib/pubid/itu/components/designation.rb +35 -0
  312. data/lib/pubid/itu/components.rb +1 -0
  313. data/lib/pubid/itu/identifier.rb +1 -3
  314. data/lib/pubid/itu/identifiers/addendum.rb +15 -0
  315. data/lib/pubid/itu/identifiers/amendment.rb +6 -28
  316. data/lib/pubid/itu/identifiers/annex.rb +13 -2
  317. data/lib/pubid/itu/identifiers/annex_of_recommendation.rb +87 -0
  318. data/lib/pubid/itu/identifiers/appendix_of_recommendation.rb +92 -0
  319. data/lib/pubid/itu/identifiers/base.rb +341 -23
  320. data/lib/pubid/itu/identifiers/combined_identifier.rb +99 -23
  321. data/lib/pubid/itu/identifiers/corrigendum.rb +16 -23
  322. data/lib/pubid/itu/identifiers/errata.rb +15 -0
  323. data/lib/pubid/itu/identifiers/handbook.rb +38 -0
  324. data/lib/pubid/itu/identifiers/question.rb +63 -0
  325. data/lib/pubid/itu/identifiers/recommendation.rb +3 -2
  326. data/lib/pubid/itu/identifiers/report.rb +39 -0
  327. data/lib/pubid/itu/identifiers/special_publication.rb +3 -1
  328. data/lib/pubid/itu/identifiers/standard_serialization.rb +58 -0
  329. data/lib/pubid/itu/identifiers/supplement.rb +119 -14
  330. data/lib/pubid/itu/identifiers.rb +10 -1
  331. data/lib/pubid/itu/model.rb +1 -1
  332. data/lib/pubid/itu/parser.rb +480 -26
  333. data/lib/pubid/itu/urn_generator.rb +36 -6
  334. data/lib/pubid/itu/urn_parser.rb +8 -0
  335. data/lib/pubid/itu.rb +11 -3
  336. data/lib/pubid/jcgm/builder.rb +23 -13
  337. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -2
  338. data/lib/pubid/jcgm/identifiers/corrigendum.rb +34 -0
  339. data/lib/pubid/jcgm/identifiers/gum_guide.rb +3 -3
  340. data/lib/pubid/jcgm/identifiers/meeting.rb +47 -0
  341. data/lib/pubid/jcgm/identifiers.rb +2 -0
  342. data/lib/pubid/jcgm/parser.rb +66 -6
  343. data/lib/pubid/jcgm/renderer.rb +26 -12
  344. data/lib/pubid/jcgm/single_identifier.rb +74 -5
  345. data/lib/pubid/jcgm/supplement_identifier.rb +39 -4
  346. data/lib/pubid/jcgm/urn_generator.rb +21 -13
  347. data/lib/pubid/jcgm/urn_parser.rb +15 -3
  348. data/lib/pubid/jis/identifier.rb +52 -0
  349. data/lib/pubid/nist/builder.rb +29 -9
  350. data/lib/pubid/nist/caster.rb +7 -45
  351. data/lib/pubid/nist/circular_supplement_builder.rb +7 -5
  352. data/lib/pubid/nist/components/supplement.rb +5 -2
  353. data/lib/pubid/nist/configuration.rb +7 -1
  354. data/lib/pubid/nist/identifier.rb +1 -3
  355. data/lib/pubid/nist/identifiers/base.rb +121 -37
  356. data/lib/pubid/nist/identifiers/circular.rb +1 -1
  357. data/lib/pubid/nist/identifiers/commercial_standard.rb +1 -1
  358. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
  359. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +1 -1
  360. data/lib/pubid/nist/identifiers/crpl_report.rb +1 -1
  361. data/lib/pubid/nist/identifiers/dated_document.rb +1 -1
  362. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +1 -1
  363. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +1 -1
  364. data/lib/pubid/nist/identifiers/handbook.rb +1 -1
  365. data/lib/pubid/nist/identifiers/internal_report.rb +1 -1
  366. data/lib/pubid/nist/identifiers/letter_circular.rb +1 -1
  367. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +1 -1
  368. data/lib/pubid/nist/identifiers/monograph.rb +1 -1
  369. data/lib/pubid/nist/identifiers/ncstar.rb +2 -2
  370. data/lib/pubid/nist/identifiers/nsrds.rb +1 -1
  371. data/lib/pubid/nist/identifiers/owmwp.rb +1 -1
  372. data/lib/pubid/nist/identifiers/report.rb +1 -1
  373. data/lib/pubid/nist/identifiers/special_publication.rb +10 -1
  374. data/lib/pubid/nist/identifiers/technical_note.rb +1 -1
  375. data/lib/pubid/nist/identifiers.rb +0 -1
  376. data/lib/pubid/nist/parser.rb +29 -4
  377. data/lib/pubid/nist/preprocessor.rb +15 -0
  378. data/lib/pubid/nist/router.rb +3 -2
  379. data/lib/pubid/nist/series/ir.rb +0 -3
  380. data/lib/pubid/nist/supplement_identifier.rb +9 -9
  381. data/lib/pubid/nist.rb +13 -12
  382. data/lib/pubid/oasis/builder.rb +77 -0
  383. data/lib/pubid/oasis/identifier.rb +82 -0
  384. data/lib/pubid/oasis/identifiers/standard.rb +29 -0
  385. data/lib/pubid/oasis/identifiers.rb +9 -0
  386. data/lib/pubid/oasis/parser.rb +34 -0
  387. data/lib/pubid/oasis/renderer.rb +29 -0
  388. data/lib/pubid/oasis/urn_generator.rb +25 -0
  389. data/lib/pubid/oasis/urn_parser.rb +22 -0
  390. data/lib/pubid/oasis.rb +74 -0
  391. data/lib/pubid/ogc/builder.rb +33 -0
  392. data/lib/pubid/ogc/identifier.rb +77 -0
  393. data/lib/pubid/ogc/identifiers/document.rb +26 -0
  394. data/lib/pubid/ogc/identifiers.rb +10 -0
  395. data/lib/pubid/ogc/parser.rb +40 -0
  396. data/lib/pubid/ogc/renderer.rb +33 -0
  397. data/lib/pubid/ogc/urn_generator.rb +14 -0
  398. data/lib/pubid/ogc/urn_parser.rb +22 -0
  399. data/lib/pubid/ogc.rb +71 -0
  400. data/lib/pubid/oiml/builder.rb +31 -7
  401. data/lib/pubid/oiml/identifier.rb +9 -1
  402. data/lib/pubid/oiml/parser.rb +11 -12
  403. data/lib/pubid/oiml/renderer.rb +13 -13
  404. data/lib/pubid/oiml/single_identifier.rb +20 -0
  405. data/lib/pubid/oiml/supplement_identifier.rb +9 -9
  406. data/lib/pubid/oiml/urn_parser.rb +23 -6
  407. data/lib/pubid/oiml.rb +4 -0
  408. data/lib/pubid/omg/builder.rb +19 -0
  409. data/lib/pubid/omg/identifier.rb +44 -0
  410. data/lib/pubid/omg/identifiers/specification.rb +32 -0
  411. data/lib/pubid/omg/identifiers.rb +9 -0
  412. data/lib/pubid/omg/parser.rb +40 -0
  413. data/lib/pubid/omg/renderer.rb +19 -0
  414. data/lib/pubid/omg.rb +51 -0
  415. data/lib/pubid/parsers/mr_string.rb +101 -7
  416. data/lib/pubid/plateau/builder.rb +8 -4
  417. data/lib/pubid/plateau/identifier.rb +1 -3
  418. data/lib/pubid/plateau/identifiers/base.rb +1 -6
  419. data/lib/pubid/plateau/identifiers/handbook.rb +1 -1
  420. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  421. data/lib/pubid/plateau/identifiers.rb +0 -1
  422. data/lib/pubid/plateau/parser.rb +15 -5
  423. data/lib/pubid/plateau/renderer.rb +1 -1
  424. data/lib/pubid/plateau/supplement_identifier.rb +11 -11
  425. data/lib/pubid/plateau.rb +4 -4
  426. data/lib/pubid/renderers/human_readable.rb +3 -1
  427. data/lib/pubid/renderers/mr_string.rb +46 -4
  428. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  429. data/lib/pubid/rendering/supplement.rb +4 -4
  430. data/lib/pubid/sae/builder.rb +1 -1
  431. data/lib/pubid/sae/identifier.rb +1 -3
  432. data/lib/pubid/sae/identifiers/base.rb +10 -7
  433. data/lib/pubid/sae/identifiers.rb +0 -1
  434. data/lib/pubid/sae.rb +3 -3
  435. data/lib/pubid/tgpp/builder.rb +41 -0
  436. data/lib/pubid/tgpp/identifier.rb +91 -0
  437. data/lib/pubid/tgpp/identifiers/technical_report.rb +32 -0
  438. data/lib/pubid/tgpp/identifiers/technical_specification.rb +33 -0
  439. data/lib/pubid/tgpp/identifiers.rb +11 -0
  440. data/lib/pubid/tgpp/parser.rb +62 -0
  441. data/lib/pubid/tgpp/renderer.rb +36 -0
  442. data/lib/pubid/tgpp/urn_generator.rb +20 -0
  443. data/lib/pubid/tgpp/urn_parser.rb +28 -0
  444. data/lib/pubid/tgpp.rb +78 -0
  445. data/lib/pubid/type_resolver.rb +59 -0
  446. data/lib/pubid/un/builder.rb +42 -0
  447. data/lib/pubid/un/identifier.rb +37 -0
  448. data/lib/pubid/un/identifiers/document.rb +24 -0
  449. data/lib/pubid/un/identifiers.rb +9 -0
  450. data/lib/pubid/un/parser.rb +25 -0
  451. data/lib/pubid/un/renderer.rb +11 -0
  452. data/lib/pubid/un.rb +46 -0
  453. data/lib/pubid/version.rb +1 -1
  454. data/lib/pubid/w3c/builder.rb +55 -0
  455. data/lib/pubid/w3c/identifier.rb +101 -0
  456. data/lib/pubid/w3c/identifiers/candidate_recommendation.rb +31 -0
  457. data/lib/pubid/w3c/identifiers/candidate_recommendation_draft.rb +31 -0
  458. data/lib/pubid/w3c/identifiers/draft_note.rb +31 -0
  459. data/lib/pubid/w3c/identifiers/note.rb +30 -0
  460. data/lib/pubid/w3c/identifiers/obsolete_recommendation.rb +31 -0
  461. data/lib/pubid/w3c/identifiers/proposed_edited_recommendation.rb +31 -0
  462. data/lib/pubid/w3c/identifiers/proposed_recommendation.rb +31 -0
  463. data/lib/pubid/w3c/identifiers/recommendation.rb +31 -0
  464. data/lib/pubid/w3c/identifiers/standard.rb +12 -0
  465. data/lib/pubid/w3c/identifiers/superseded_recommendation.rb +31 -0
  466. data/lib/pubid/w3c/identifiers/working_draft.rb +30 -0
  467. data/lib/pubid/w3c/identifiers.rb +25 -0
  468. data/lib/pubid/w3c/parser.rb +43 -0
  469. data/lib/pubid/w3c/renderer.rb +35 -0
  470. data/lib/pubid/w3c/urn_generator.rb +18 -0
  471. data/lib/pubid/w3c/urn_parser.rb +36 -0
  472. data/lib/pubid/w3c.rb +67 -0
  473. data/lib/pubid/xsf/builder.rb +17 -0
  474. data/lib/pubid/xsf/identifier.rb +62 -0
  475. data/lib/pubid/xsf/identifiers/xep.rb +31 -0
  476. data/lib/pubid/xsf/identifiers.rb +9 -0
  477. data/lib/pubid/xsf/parser.rb +25 -0
  478. data/lib/pubid/xsf/renderer.rb +23 -0
  479. data/lib/pubid/xsf/urn_generator.rb +13 -0
  480. data/lib/pubid/xsf/urn_parser.rb +18 -0
  481. data/lib/pubid/xsf.rb +76 -0
  482. data/lib/pubid.rb +25 -1
  483. metadata +205 -4
  484. data/lib/pubid/cie/components/code.rb +0 -80
  485. data/lib/pubid/iala/identifiers/base.rb +0 -14
@@ -6,7 +6,7 @@ module Pubid
6
6
  # Amendment Identifier
7
7
  # Contains a base identifier plus amendment parameters
8
8
  class Amendment < SingleIdentifier
9
- attribute :base_identifier, ::Pubid::Identifier, polymorphic: true
9
+ attribute :base, ::Pubid::Identifier, polymorphic: true
10
10
  attribute :amendment_number, :string
11
11
  attribute :amendment_year, :integer
12
12
  attribute :separator, :string, default: -> { "+" }
@@ -16,17 +16,17 @@ module Pubid
16
16
  attribute :amd_suffix_form, :boolean, default: -> { false }
17
17
 
18
18
  def publisher
19
- base_identifier&.publisher
19
+ base&.publisher
20
20
  end
21
21
 
22
22
  # Base document = the standard this amendment applies to, fully peeled.
23
23
  def base_document
24
- base_identifier&.base_document || self
24
+ base&.base_document || self
25
25
  end
26
26
 
27
27
  # Dropping the supplement layer yields the base standard.
28
28
  def drop_supplements
29
- base_identifier || self
29
+ base || self
30
30
  end
31
31
 
32
32
  # Uniform supplement interface (shared with Corrigendum) so callers need
@@ -68,6 +68,12 @@ module Pubid
68
68
  identifiers&.first&.base_document || self
69
69
  end
70
70
 
71
+ # The origin document. Members live in `identifiers` (not `base`), so
72
+ # walk the first member to its root.
73
+ def root
74
+ identifiers&.first&.root || self
75
+ end
76
+
71
77
  # Dropping the supplement layer yields the base standard alone.
72
78
  def drop_supplements
73
79
  identifiers&.first || self
@@ -6,23 +6,23 @@ module Pubid
6
6
  # Corrigendum Identifier
7
7
  # Contains a base identifier plus corrigendum parameters
8
8
  class Corrigendum < SingleIdentifier
9
- attribute :base_identifier, ::Pubid::Identifier, polymorphic: true
9
+ attribute :base, ::Pubid::Identifier, polymorphic: true
10
10
  attribute :corrigendum_number, :string
11
11
  attribute :corrigendum_year, :integer
12
12
  attribute :separator, :string, default: -> { "+" }
13
13
 
14
14
  def publisher
15
- base_identifier&.publisher
15
+ base&.publisher
16
16
  end
17
17
 
18
18
  # Base document = the standard this corrigendum applies to, fully peeled.
19
19
  def base_document
20
- base_identifier&.base_document || self
20
+ base&.base_document || self
21
21
  end
22
22
 
23
23
  # Dropping the supplement layer yields the base standard.
24
24
  def drop_supplements
25
- base_identifier || self
25
+ base || self
26
26
  end
27
27
 
28
28
  # Uniform supplement interface (shared with Amendment) so callers need
@@ -10,25 +10,25 @@ module Pubid
10
10
  # 2. "ExComm" (abbreviated form)
11
11
  # 3. "ExComm (Fire)" (with optional topic suffix)
12
12
  class ExpertCommentary < SingleIdentifier
13
- attribute :base_identifier, ::Pubid::Identifier, polymorphic: true
13
+ attribute :base, ::Pubid::Identifier, polymorphic: true
14
14
  attribute :format, :string # "full", "abbr", "abbr_with_topic"
15
15
  attribute :topic, :string # e.g., "Fire"
16
16
 
17
17
  def publisher
18
- base_identifier&.publisher
18
+ base&.publisher
19
19
  end
20
20
 
21
21
  def number
22
- base_identifier&.number
22
+ base&.number
23
23
  end
24
24
 
25
25
  def year
26
- base_identifier&.year
26
+ base&.year
27
27
  end
28
28
 
29
29
  # Base document = the commented standard, fully peeled.
30
30
  def base_document
31
- base_identifier&.base_document || self
31
+ base&.base_document || self
32
32
  end
33
33
  end
34
34
  end
@@ -9,7 +9,7 @@ module Pubid
9
9
  # Forward: "BS 1000:Supplement No. 1:1972", "BS 1722-1 Supplement No. 1:1974"
10
10
  # Reverse: "Supplement No. 1 (1970) to BS 1831:1969"
11
11
  class SupplementDocument < SingleIdentifier
12
- attribute :base_identifier, ::Pubid::Identifier, polymorphic: true
12
+ attribute :base, ::Pubid::Identifier, polymorphic: true
13
13
  attribute :supplement_number, :string
14
14
  attribute :supplement_year, :integer
15
15
  attribute :supplement_type, :string, default: -> {
@@ -21,7 +21,7 @@ module Pubid
21
21
  } # Separator before Supplement (":" or " ")
22
22
 
23
23
  def publisher
24
- base_identifier&.publisher
24
+ base&.publisher
25
25
  end
26
26
  end
27
27
  end
@@ -12,24 +12,24 @@ module Pubid
12
12
  # PAS 96:2017 - TC
13
13
  # PP 7722:2006 BOOK
14
14
  class ValueAddedPublication < SingleIdentifier
15
- attribute :base_identifier, ::Pubid::Identifier, polymorphic: true
15
+ attribute :base, ::Pubid::Identifier, polymorphic: true
16
16
  attribute :format, :string, values: ["PDF", "TC", "BOOK"]
17
17
 
18
- # Delegate common attributes to base_identifier
18
+ # Delegate common attributes to base
19
19
  def publisher
20
- base_identifier&.publisher
20
+ base&.publisher
21
21
  end
22
22
 
23
23
  def number
24
- base_identifier&.number
24
+ base&.number
25
25
  end
26
26
 
27
27
  def year
28
- base_identifier&.year
28
+ base&.year
29
29
  end
30
30
 
31
31
  def date
32
- base_identifier&.date
32
+ base&.date
33
33
  end
34
34
  end
35
35
  end
@@ -160,13 +160,13 @@ module Pubid
160
160
  # ------------------------------------------------------------------
161
161
 
162
162
  def render_addendum_document(id, opts)
163
- result = id.base_identifier.to_s(**opts)
163
+ result = id.base.to_s(**opts)
164
164
 
165
- base_has_year = id.base_identifier.to_s =~ /:(\d{4})$/
165
+ base_has_year = id.base.to_s =~ /:(\d{4})$/
166
166
 
167
167
  sep = if id.separator == ":"
168
168
  ":"
169
- elsif base_has_year && id.base_identifier.to_s !~ /:\d{4}:/
169
+ elsif base_has_year && id.base.to_s !~ /:\d{4}:/
170
170
  " "
171
171
  else
172
172
  id.separator
@@ -289,7 +289,7 @@ module Pubid
289
289
  end
290
290
 
291
291
  def render_amendment(id)
292
- base = id.base_identifier ? id.base_identifier.to_s : ""
292
+ base = id.base ? id.base.to_s : ""
293
293
 
294
294
  if id.amd_suffix_form
295
295
  # Trailing " AMD5" / " AMD AA" suffix form
@@ -471,7 +471,7 @@ module Pubid
471
471
  end
472
472
 
473
473
  def render_corrigendum(id)
474
- result = id.base_identifier ? id.base_identifier.to_s : ""
474
+ result = id.base ? id.base.to_s : ""
475
475
  result += "#{id.separator}C"
476
476
  result += id.corrigendum_number.to_s if id.corrigendum_number
477
477
  result += ":#{id.corrigendum_year}" if id.corrigendum_year
@@ -589,7 +589,7 @@ module Pubid
589
589
  end
590
590
 
591
591
  def render_expert_commentary(id)
592
- base_str = id.base_identifier.to_s
592
+ base_str = id.base.to_s
593
593
  base_str = base_str.sub(/ (Expert Commentary|ExComm(\s*\(.*\))?)$/, "")
594
594
 
595
595
  case id.format
@@ -895,7 +895,7 @@ module Pubid
895
895
  end
896
896
 
897
897
  def render_supplement_document(id)
898
- base_str = id.base_identifier.to_s
898
+ base_str = id.base.to_s
899
899
 
900
900
  if id.reverse_format
901
901
  supplement_str = if id.supplement_type == "No."
@@ -998,7 +998,7 @@ module Pubid
998
998
  end
999
999
 
1000
1000
  def render_value_added_publication(id, opts)
1001
- base_str = id.base_identifier.to_s(**opts)
1001
+ base_str = id.base.to_s(**opts)
1002
1002
 
1003
1003
  case id.format
1004
1004
  when "TC"
@@ -75,6 +75,54 @@ module Pubid
75
75
  0
76
76
  end
77
77
  end
78
+
79
+ # Annex F series groupings per "Rules for the structure and drafting
80
+ # of UK standards" (BSI, 2017), F.1.3-F.1.5. Each maps a `prefix`
81
+ # token to the broader series category.
82
+ SERIES_CATEGORIES = {
83
+ # F.1.3 Automobile
84
+ "AU" => :automotive,
85
+ # F.1.4 Aerospace
86
+ "A" => :aerospace, "B" => :aerospace, "C" => :aerospace,
87
+ "F" => :aerospace, "G" => :aerospace, "HC" => :aerospace,
88
+ "L" => :aerospace, "S" => :aerospace, "SP" => :aerospace,
89
+ "X" => :aerospace, "M" => :aerospace, "TA" => :aerospace,
90
+ "2A" => :aerospace, "2B" => :aerospace, "2C" => :aerospace,
91
+ "2F" => :aerospace, "2G" => :aerospace, "2HC" => :aerospace,
92
+ "2HR" => :aerospace, "2L" => :aerospace, "2M" => :aerospace,
93
+ "2S" => :aerospace, "2SP" => :aerospace, "2TA" => :aerospace,
94
+ "2X" => :aerospace, "3A" => :aerospace, "3B" => :aerospace,
95
+ "3F" => :aerospace, "3G" => :aerospace, "3HR" => :aerospace,
96
+ "3J" => :aerospace, "3L" => :aerospace, "3S" => :aerospace,
97
+ "3TA" => :aerospace, "4F" => :aerospace, "4L" => :aerospace,
98
+ "4S" => :aerospace, "5S" => :aerospace, "7S" => :aerospace,
99
+ # F.1.5 Marine
100
+ "MA" => :marine, "PL" => :marine, "QC" => :marine,
101
+ }.freeze
102
+
103
+ # Series accessor — semantically named alias for `prefix` per
104
+ # issue #252. Returns the prefix token (e.g., "AU", "MA", "2A").
105
+ def series
106
+ prefix
107
+ end
108
+
109
+ # Series category — one of :automotive, :aerospace, :marine, or nil
110
+ # when the identifier doesn't carry a recognized Annex F prefix.
111
+ def series_category
112
+ SERIES_CATEGORIES[prefix.to_s] if prefix
113
+ end
114
+
115
+ def automotive?
116
+ series_category == :automotive
117
+ end
118
+
119
+ def aerospace?
120
+ series_category == :aerospace
121
+ end
122
+
123
+ def marine?
124
+ series_category == :marine
125
+ end
78
126
  end
79
127
 
80
128
  # Backward-compatible alias: BSI's base class is Pubid::Bsi::Identifier.
@@ -125,9 +125,11 @@ module Pubid
125
125
 
126
126
  def parse_date(value)
127
127
  value = value.to_s
128
- if value.match?(/^\d{4}(-\d{2})?$/)
129
- year, month = value.split("-")
130
- Pubid::Components::Date.new(year: year, month: month || nil)
128
+ if value.match?(/^\d{4}(-\d{2}){0,2}$/)
129
+ year, month, day = value.split("-")
130
+ Pubid::Components::Date.new(year: year,
131
+ month: month || nil,
132
+ day: day || nil)
131
133
  elsif value.is_a?(Integer) || (value.is_a?(String) && value.match?(/^\d{4}$/))
132
134
  Pubid::Components::Date.new(year: value)
133
135
  else
@@ -52,10 +52,10 @@ stage_format_long: nil, with_date: nil)
52
52
 
53
53
  supplements.each do |supplement|
54
54
  # ISO DirectivesSupplement always uses " + " (space before)
55
- # CEN-style supplements (AC, A) without base_identifier use "+" (no space before)
56
- # Other ISO supplements with base_identifier use " + " (space before)
55
+ # CEN-style supplements (AC, A) without base use "+" (no space before)
56
+ # Other ISO supplements with base use " + " (space before)
57
57
  if supplement.class.name&.include?("DirectivesSupplement") ||
58
- (supplement.class.attributes.key?(:base_identifier) && !supplement.base_identifier.nil?)
58
+ (supplement.class.attributes.key?(:base) && !supplement.base.nil?)
59
59
  result += " + #{supplement.to_s(lang: lang, lang_single: lang_single,
60
60
  with_edition: with_edition, format: format, stage_format_long: stage_format_long, with_date: with_date)}"
61
61
  else
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Calconnect
5
+ # Builds a CalConnect identifier object from a Parslet parse tree. There is
6
+ # a single concrete type (Identifiers::Standard), so no type dispatch.
7
+ class Builder
8
+ def self.build(parsed_data)
9
+ new.build(parsed_data)
10
+ end
11
+
12
+ def build(data)
13
+ Identifiers::Standard.new(
14
+ series: data[:series]&.to_s,
15
+ number: data[:number].to_s,
16
+ date: build_date(data),
17
+ )
18
+ end
19
+
20
+ private
21
+
22
+ # Publication date as a Pubid::Components::Date, or nil for a partial
23
+ # reference that omits the trailing ":YYYY" (relaton matches such refs by
24
+ # excluding the date). Digits are kept as strings verbatim (already
25
+ # zero-padded in the source, e.g. "07"/"23"); month/day are nil for the
26
+ # common year-only form.
27
+ def build_date(data)
28
+ return nil if data[:year].nil?
29
+
30
+ ::Pubid::Components::Date.new(
31
+ year: data[:year].to_s,
32
+ month: data[:month]&.to_s,
33
+ day: data[:day]&.to_s,
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Calconnect
5
+ # Base class for every CalConnect identifier AND the flavor's parse entry
6
+ # point — mirrors Pubid::Jis::Identifier. Concrete identifiers under
7
+ # Pubid::Calconnect::Identifiers descend from this class, so a parsed
8
+ # CalConnect id is an instance of Pubid::Calconnect::Identifier and
9
+ # relaton-index can pass this class as `pubid_class` for from_hash/to_hash.
10
+ class Identifier < ::Pubid::Identifier
11
+ # `number` is a CalConnect-specific plain string (preserves leading zeros
12
+ # like "0514" and the sub-part separator, "0812-1"/"0707.1"), so it
13
+ # overrides the inherited Components::Code type. The publication date uses
14
+ # the shared Pubid::Components::Date (inherited attribute): `year` is
15
+ # always present, `month`/`day` only for the rare full-date form
16
+ # ("CC/WD 51017:2024-07-23").
17
+ attribute :series, :string # Optional series letter/token (A, WD, DIR, …)
18
+ attribute :number, :string
19
+ attribute :date, ::Pubid::Components::Date
20
+
21
+ # Polymorphic type map for lutaml::Model key_value (de)serialization,
22
+ # mapping the concrete class's polymorphic_name to its class name so a
23
+ # stored hash rebuilds the correct identifier type via from_hash.
24
+ CALCONNECT_TYPE_MAP = {
25
+ "pubid:calconnect:standard" => "Pubid::Calconnect::Identifiers::Standard",
26
+ }.freeze
27
+
28
+ # The date serializes FLAT as year/month/day string keys (nils omitted),
29
+ # mirroring lib/pubid/iso/identifier.rb — not as a nested "date" object —
30
+ # so the index row stays a shallow hash and round-trips exactly.
31
+ key_value do
32
+ map "_type", to: :_type, polymorphic_map: CALCONNECT_TYPE_MAP
33
+ map "series", to: :series
34
+ map "number", to: :number
35
+ map "year", with: { to: :year_to_kv, from: :year_from_kv }
36
+ map "month", with: { to: :month_to_kv, from: :month_from_kv }
37
+ map "day", with: { to: :day_to_kv, from: :day_from_kv }
38
+ end
39
+
40
+ # Publisher is always "CC". A plain constant (not a `publisher` method) so
41
+ # it doesn't shadow the inherited lutaml `publisher` attribute, which
42
+ # would otherwise fail serialization type validation.
43
+ PUBLISHER = "CC"
44
+
45
+ attr_reader :with_publisher
46
+
47
+ # Render the publication date, e.g. "2018" or "2024-07-23". Shared by the
48
+ # renderer and the URN generator so they always agree.
49
+ # Pubid::Components::Date#to_s yields the year alone, or the zero-padded
50
+ # "YYYY-MM-DD" when month/day are present.
51
+ def date_string
52
+ date&.to_s
53
+ end
54
+
55
+ # Basic string representation. Delegates to the human renderer. The
56
+ # printed CalConnect id carries the "CC" publisher token by default; pass
57
+ # with_publisher: false to drop it (and the series slash).
58
+ def to_s(**opts)
59
+ render(format: :human, **opts)
60
+ end
61
+
62
+ # Capture the with_publisher flag on EVERY render call (default true), so
63
+ # it can never leak across calls. The base `render` only forwards
64
+ # `:with_edition` to the renderer, so the flag is threaded via this
65
+ # per-call instance write (the renderer reads `id.with_publisher`).
66
+ def render(format: :human, with_publisher: true, **opts)
67
+ @with_publisher = with_publisher
68
+ super(format: format, **opts)
69
+ end
70
+
71
+ # --- date serialized flat as year/month/day (mirrors ISO) ---
72
+ def year_to_kv(model, doc)
73
+ emit_date_part(doc, "year", model.date&.year)
74
+ end
75
+
76
+ def month_to_kv(model, doc)
77
+ emit_date_part(doc, "month", model.date&.month)
78
+ end
79
+
80
+ def day_to_kv(model, doc)
81
+ emit_date_part(doc, "day", model.date&.day)
82
+ end
83
+
84
+ def year_from_kv(model, value) = date_for(model).year = value.to_s
85
+ def month_from_kv(model, value) = date_for(model).month = value.to_s
86
+ def day_from_kv(model, value) = date_for(model).day = value.to_s
87
+
88
+ def emit_date_part(doc, key, val)
89
+ return if val.nil? || val.to_s.empty?
90
+
91
+ doc.add_child(Lutaml::KeyValue::DataModel::Element.new(key, val.to_s))
92
+ end
93
+
94
+ def date_for(model)
95
+ model.date ||= ::Pubid::Components::Date.new
96
+ end
97
+
98
+ # from_hash is the shared polymorphic dispatch on Pubid::Identifier.
99
+ # CALCONNECT_TYPE_MAP remains as the key_value polymorphic_map.
100
+
101
+ # Parse a CalConnect identifier string into an identifier object.
102
+ # @param identifier [String] The CalConnect identifier string to parse
103
+ # @return [Identifier] The appropriate identifier object
104
+ # @raise [ArgumentError] If the input exceeds the maximum length
105
+ # @raise [RuntimeError] If parsing fails
106
+ def self.parse(identifier)
107
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
108
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
109
+ end
110
+
111
+ Builder.build(Parser.parse(identifier))
112
+ rescue Parslet::ParseFailed => e
113
+ raise "Failed to parse CalConnect '#{identifier}': #{e.message}"
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Calconnect
5
+ module Identifiers
6
+ # The sole CalConnect document type. Its polymorphic_name resolves
7
+ # automatically to "pubid:calconnect:standard".
8
+ class Standard < Identifier
9
+ TYPED_STAGES = [
10
+ Pubid::Components::TypedStage.new(
11
+ code: :pubcc,
12
+ stage_code: :published,
13
+ type_code: :cc,
14
+ abbr: ["CC"],
15
+ name: "CalConnect Standard",
16
+ harmonized_stages: [],
17
+ ),
18
+ ].freeze
19
+
20
+ def self.type
21
+ { key: :cc,
22
+ web: :standard,
23
+ title: "CalConnect Standard",
24
+ short: "CC" }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Calconnect
5
+ module Identifiers
6
+ autoload :Standard, "#{__dir__}/identifiers/standard"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+
5
+ module Pubid
6
+ module Calconnect
7
+ # Parslet grammar for CalConnect identifiers.
8
+ #
9
+ # Shape: CC[/<series>] <number>:<date>
10
+ # CC 18011:2018
11
+ # CC/DIR 10006:2019
12
+ # CC/Adv 0707.1:2007 (dot sub-part)
13
+ # CC/A 0812-1:2008 (dash sub-part)
14
+ # CC/WD 51017:2024-07-23 (full ISO date)
15
+ class Parser < Parslet::Parser
16
+ rule(:digit) { match["0-9"] }
17
+ rule(:digits) { digit.repeat(1) }
18
+
19
+ # Publisher token
20
+ rule(:publisher) { str("CC") }
21
+
22
+ # Series token — an open [A-Za-z]+ set (A, WD, R, S, CD, DIR, Adv, FDS, …)
23
+ rule(:series) { match["A-Za-z"].repeat(1).as(:series) }
24
+
25
+ # Number — digits, preserving leading zeros, with at most one dot- or
26
+ # dash-delimited sub-part ("0707.1", "0812-1"). Kept as a string.
27
+ rule(:number) do
28
+ (digits >> ((str(".") | str("-")) >> digits).maybe).as(:number)
29
+ end
30
+
31
+ # Date after the colon: a year, optionally a full "YYYY-MM-DD". The colon
32
+ # hard-delimits number from date, and month+day only appear together, so
33
+ # the split is unambiguous.
34
+ rule(:date) do
35
+ digits.as(:year) >>
36
+ (str("-") >> digits.as(:month) >> str("-") >> digits.as(:day)).maybe
37
+ end
38
+
39
+ rule(:identifier) do
40
+ publisher >>
41
+ (str("/") >> series).maybe >>
42
+ str(" ") >>
43
+ number >>
44
+ (str(":") >> date).maybe
45
+ end
46
+
47
+ rule(:root) { identifier }
48
+
49
+ def self.parse(input)
50
+ new.parse(input)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Calconnect
5
+ # Human-readable renderer for CalConnect identifiers.
6
+ #
7
+ # Produces the canonical printed form, e.g.:
8
+ # "CC 18011:2018"
9
+ # "CC/DIR 10006:2019"
10
+ # "CC/WD 51017:2024-07-23"
11
+ # "DIR 10006:2019" (only when with_publisher: false)
12
+ #
13
+ # Registered as the `:human` format in the CalConnect format registry and
14
+ # invoked via `render(format: :human)`.
15
+ class Renderer < ::Pubid::Renderers::Base
16
+ PUBLISHER = "CC"
17
+
18
+ def render(**_opts)
19
+ id = @id
20
+ prefix = if with_publisher?(id)
21
+ id.series ? "#{PUBLISHER}/#{id.series} " : "#{PUBLISHER} "
22
+ else
23
+ id.series ? "#{id.series} " : ""
24
+ end
25
+ date = id.date_string
26
+ "#{prefix}#{id.number}#{":#{date}" if date}"
27
+ end
28
+
29
+ private
30
+
31
+ def with_publisher?(id)
32
+ id.respond_to?(:with_publisher) && id.with_publisher != false
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Calconnect
5
+ # Emits CalConnect URNs of the form
6
+ # urn:calconnect[:<series>]:<number>:<date>
7
+ # e.g. "urn:calconnect:DIR:10006:2019", "urn:calconnect:18011:2018",
8
+ # "urn:calconnect:WD:51017:2024-07-23".
9
+ #
10
+ # The series keeps its printed case (JIS keeps its code case likewise) so a
11
+ # URN reconstructs the human form losslessly — mirror in urn_parser.rb.
12
+ #
13
+ # NOTE: a *partial* (date-less) reference has NO round-trippable URN form.
14
+ # Both `series` and `date` are optional, and UrnParser reads the trailing
15
+ # segments positionally, so a date-less URN like "urn:calconnect:11001"
16
+ # (or "urn:calconnect:DIR:10006") is ambiguous with a series-less dated URN
17
+ # and does not parse back. Partial refs are matched by pubid `#exclude`,
18
+ # not by URN, so this generator simply omits the missing segment rather
19
+ # than emitting an empty ":" — callers must not rely on URN round-trip for
20
+ # a partial id.
21
+ class UrnGenerator < Pubid::UrnGenerator::Base
22
+ def generate
23
+ # series and date_string are nil for a series-less or partial
24
+ # (date-less) id; compact drops them so no empty ":" segment appears.
25
+ parts = [
26
+ "urn", "calconnect",
27
+ identifier.series, identifier.number.to_s, identifier.date_string
28
+ ]
29
+ parts.compact.join(":")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Calconnect
5
+ # Parses CalConnect URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits: urn:calconnect[:<series>]:<number>:<date>
8
+ # urn:calconnect:18011:2018 → CC 18011:2018
9
+ # urn:calconnect:DIR:10006:2019 → CC/DIR 10006:2019
10
+ # urn:calconnect:WD:51017:2024-07-23 → CC/WD 51017:2024-07-23
11
+ #
12
+ # The date segment (year or full "YYYY-MM-DD") never contains a colon, so
13
+ # it is a single trailing part; the number precedes it, and an optional
14
+ # series precedes the number.
15
+ #
16
+ # This positional pop assumes a *dated* URN (the form UrnGenerator emits for
17
+ # a full id). A partial (date-less) reference has no round-trippable URN —
18
+ # see UrnGenerator — so this parser is only guaranteed for URNs produced
19
+ # from a full id; a date-less URN misaligns the pops and will not parse.
20
+ class UrnParser < Pubid::UrnParser::Base
21
+ def parse_urn(urn)
22
+ parts = split_parts(strip_namespace(urn))
23
+ date = parts.pop
24
+ number = parts.pop
25
+ series = parts.pop
26
+
27
+ text = +"CC"
28
+ text << "/#{series}" if series
29
+ text << " #{number}:#{date}"
30
+ flavor_parse(text)
31
+ end
32
+ end
33
+ end
34
+ end