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
@@ -2,8 +2,7 @@
2
2
 
3
3
  module Pubid
4
4
  module Sae
5
- # Base SAE Identifier. Canonical name Pubid::Sae::Identifier (Identifiers::Base
6
- # is a back-compat alias). SAE has a single identifier class that IS the
5
+ # Base SAE Identifier. Canonical name Pubid::Sae::Identifier. SAE has a single identifier class that IS the
7
6
  # document type, so this class is both the base and the only concrete type.
8
7
  # Handles all SAE document types (AMS, AIR, ARP, AS, MA).
9
8
  class Identifier < ::Pubid::Identifier
@@ -26,12 +25,16 @@ module Pubid
26
25
  def year
27
26
  date&.year
28
27
  end
29
- end
30
28
 
31
- module Identifiers
32
- # Backward-compatible alias: SAE's base class used to be
33
- # Pubid::Sae::Identifiers::Base. It is now Pubid::Sae::Identifier.
34
- Base = Pubid::Sae::Identifier
29
+ # SAE encodes the document class (AS, ARP, AMS, AIR, J, …) in `type.abbr`,
30
+ # not in `typed_stage.type_code`, so the generic mr_type returns nil.
31
+ # Losslessness requires the type letter to appear in MR — without it,
32
+ # `SAE J300` and `SAE AS300` would collide on `SAE.300.<year>`.
33
+ # Lowercased to match the all-lowercase MR convention (issue #142).
34
+ def mr_type
35
+ type&.abbr&.to_s&.downcase
36
+ end
35
37
  end
38
+
36
39
  end
37
40
  end
@@ -3,7 +3,6 @@
3
3
  module Pubid
4
4
  module Sae
5
5
  module Identifiers
6
- autoload :Base, "#{__dir__}/identifiers/base"
7
6
  end
8
7
  end
9
8
  end
data/lib/pubid/sae.rb CHANGED
@@ -10,7 +10,7 @@ module Pubid
10
10
 
11
11
  autoload :Builder, "#{__dir__}/sae/builder"
12
12
  autoload :Components, "#{__dir__}/sae/components"
13
- autoload :Identifier, "#{__dir__}/sae/identifier"
13
+ autoload :Identifier, "#{__dir__}/sae/identifiers/base"
14
14
  autoload :Identifiers, "#{__dir__}/sae/identifiers"
15
15
  autoload :Parser, "#{__dir__}/sae/parser"
16
16
  autoload :Renderer, "#{__dir__}/sae/renderer"
@@ -62,5 +62,5 @@ end
62
62
  Pubid::Registry.register(:sae, Pubid::Sae)
63
63
 
64
64
  # Per-flavor format registry: inherits global formats, overrides :human
65
- Pubid::Sae::Identifiers::Base.format_registry = Pubid::FormatRegistry.new(parent: Pubid::Identifier.format_registry)
66
- Pubid::Sae::Identifiers::Base.format_registry.register(:human, renderer: Pubid::Sae::Renderer)
65
+ Pubid::Sae::Identifier.format_registry = Pubid::FormatRegistry.new(parent: Pubid::Identifier.format_registry)
66
+ Pubid::Sae::Identifier.format_registry.register(:human, renderer: Pubid::Sae::Renderer)
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ class Builder
6
+ def self.build(parsed_data)
7
+ new.build(parsed_data)
8
+ end
9
+
10
+ def build(data)
11
+ identifier_class(data[:type]).new(
12
+ number: data[:number].to_s,
13
+ suffix: data[:suffix]&.to_s,
14
+ parts: extract_part_strings(data[:parts]),
15
+ release: data[:release]&.to_s,
16
+ version: data[:version].to_s,
17
+ )
18
+ end
19
+
20
+ private
21
+
22
+ def identifier_class(type)
23
+ if type.to_s == "TR"
24
+ Identifiers::TechnicalReport
25
+ else
26
+ Identifiers::TechnicalSpecification
27
+ end
28
+ end
29
+
30
+ # parts_data is an array of `{ part: "1" }` hashes (or a single hash for a
31
+ # one-level part); return the part numbers as strings.
32
+ def extract_part_strings(parts_data)
33
+ case parts_data
34
+ when Array then parts_data.filter_map { |h| h[:part]&.to_s }
35
+ when Hash then [parts_data[:part]&.to_s].compact
36
+ else []
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ # Base class for every 3GPP identifier AND the flavor's parse entry point —
6
+ # mirrors Pubid::Jis::Identifier. Concrete identifiers under
7
+ # Pubid::Tgpp::Identifiers descend from this class, so a parsed 3GPP id is
8
+ # an instance of Pubid::Tgpp::Identifier.
9
+ class Identifier < ::Pubid::Identifier
10
+ # The dotted core (e.g. "23.207") kept as a string to preserve leading
11
+ # zeros. `number` overrides the base Components::Code attribute.
12
+ attribute :number, :string
13
+ # Optional letter suffix directly after the number: "U", "dcs", "ext"…
14
+ attribute :suffix, :string
15
+ # 1–2 hyphen parts (e.g. "26.171-1", "29.198-04-1"); strings preserve any
16
+ # zero-padding.
17
+ attribute :parts, :string, collection: true
18
+ # Raw release token, stored verbatim: "REL-4", "Ph1", "UMTS",
19
+ # "Release 2000".
20
+ attribute :release, :string
21
+ # Three-part version string, e.g. "2.0.0".
22
+ attribute :version, :string
23
+
24
+ # Polymorphic type map for lutaml::Model key_value (de)serialization.
25
+ # Keys are the `pubid:3gpp:…` names produced by polymorphic_name (below).
26
+ TGPP_TYPE_MAP = {
27
+ "pubid:3gpp:technical-report" =>
28
+ "Pubid::Tgpp::Identifiers::TechnicalReport",
29
+ "pubid:3gpp:technical-specification" =>
30
+ "Pubid::Tgpp::Identifiers::TechnicalSpecification",
31
+ }.freeze
32
+
33
+ key_value do
34
+ map "_type", to: :_type, polymorphic_map: TGPP_TYPE_MAP
35
+ map "number", to: :number
36
+ map "suffix", to: :suffix
37
+ map "parts", to: :parts
38
+ map "release", to: :release
39
+ map "version", to: :version
40
+ end
41
+
42
+ # Publisher token. A plain constant (not a `publisher` method) so it does
43
+ # not shadow the inherited lutaml `publisher` attribute.
44
+ PUBLISHER = "3GPP"
45
+
46
+ # The auto-derived polymorphic name would be "pubid:tgpp:…" (from the
47
+ # module constant). Force the "3gpp" segment so the `_type` tag matches
48
+ # the relaton flavor name and TGPP_TYPE_MAP.
49
+ def self.polymorphic_name
50
+ super&.sub(/\Apubid:tgpp:/, "pubid:3gpp:")
51
+ end
52
+
53
+ # Rendering flag: whether to prefix the string with "3GPP ". Transient
54
+ # (not serialized). #to_s sets it, renders, then resets it to false in an
55
+ # ensure block, so a subsequent bare #render defaults to no publisher and
56
+ # the flag never leaks past the to_s call that set it.
57
+ attr_reader :with_publisher
58
+
59
+ # The rendered document code, e.g. "29.198-04-1" (number+suffix+parts).
60
+ def code
61
+ result = "#{number}#{suffix}"
62
+ result += parts.map { |p| "-#{p}" }.join if parts&.any?
63
+ result
64
+ end
65
+
66
+ # Basic string representation. Delegates to the :human renderer. Default
67
+ # omits the "3GPP " publisher token (matches the relaton index id);
68
+ # `to_s(with_publisher: true)` emits the printed "3GPP TS …" form.
69
+ def to_s(with_publisher: false, **opts)
70
+ @with_publisher = with_publisher
71
+ render(format: :human, **opts)
72
+ ensure
73
+ @with_publisher = false
74
+ end
75
+
76
+ # Parse a 3GPP identifier string into an identifier object
77
+ # @param identifier [String] The 3GPP identifier string to parse
78
+ # @return [Identifier] The appropriate identifier object
79
+ def self.parse(identifier)
80
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
81
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
82
+ end
83
+
84
+ parsed = Parser.parse(identifier)
85
+ Builder.build(parsed)
86
+ rescue Parslet::ParseFailed => e
87
+ raise "Failed to parse 3GPP identifier '#{identifier}': #{e.message}"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ module Identifiers
6
+ # Technical Report identifier type.
7
+ # Format: [3GPP ]TR NN.NNN[suffix][-part…]:<release>/<version>
8
+ # Example: TR 00.01U:UMTS/3.0.0
9
+ class TechnicalReport < Pubid::Tgpp::Identifier
10
+ TYPED_STAGES = [
11
+ Pubid::Components::TypedStage.new(
12
+ code: :tr,
13
+ stage_code: :published,
14
+ type_code: :tr,
15
+ abbr: ["TR"],
16
+ name: "Technical Report",
17
+ harmonized_stages: [],
18
+ ),
19
+ ].freeze
20
+
21
+ def self.type
22
+ { key: :tr,
23
+ web: :technical_report, title: "Technical Report", short: "TR" }
24
+ end
25
+
26
+ def type_prefix
27
+ "TR"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ module Identifiers
6
+ # Technical Specification identifier type.
7
+ # Format: [3GPP ]TS NN.NNN[suffix][-part…]:<release>/<version>
8
+ # Example: TS 23.207:REL-4/2.0.0
9
+ class TechnicalSpecification < Pubid::Tgpp::Identifier
10
+ TYPED_STAGES = [
11
+ Pubid::Components::TypedStage.new(
12
+ code: :ts,
13
+ stage_code: :published,
14
+ type_code: :ts,
15
+ abbr: ["TS"],
16
+ name: "Technical Specification",
17
+ harmonized_stages: [],
18
+ ),
19
+ ].freeze
20
+
21
+ def self.type
22
+ { key: :ts,
23
+ web: :technical_specification,
24
+ title: "Technical Specification", short: "TS" }
25
+ end
26
+
27
+ def type_prefix
28
+ "TS"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ module Identifiers
6
+ autoload :TechnicalReport, "#{__dir__}/identifiers/technical_report"
7
+ autoload :TechnicalSpecification,
8
+ "#{__dir__}/identifiers/technical_specification"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+
5
+ module Pubid
6
+ module Tgpp
7
+ # Parslet grammar for 3GPP identifiers.
8
+ #
9
+ # Form: `[3GPP ]<TR|TS> <NN.NNN>[suffix][-part…]:<release>/<version>`
10
+ # TS 23.207:REL-4/2.0.0
11
+ # 3GPP TR 00.01U:UMTS/3.0.0
12
+ # TS 29.198-04-1:REL-5/5.0.0
13
+ # TS 02.68:Release 2000/9.0.0
14
+ class Parser < Parslet::Parser
15
+ rule(:digit) { match["0-9"] }
16
+ rule(:digits) { digit.repeat(1) }
17
+ rule(:space) { str(" ") }
18
+
19
+ # Optional leading publisher token.
20
+ rule(:publisher_prefix) { str("3GPP") >> space }
21
+
22
+ # Document type.
23
+ rule(:type) { (str("TR") | str("TS")).as(:type) }
24
+
25
+ # Dotted number core, kept as a string (preserves leading zeros).
26
+ rule(:number_core) { (digits >> str(".") >> digits).as(:number) }
27
+
28
+ # Letter suffix directly after the number ("U"/"dcs"/"ext"…). Generic so
29
+ # future controlled-vocabulary values keep round-tripping.
30
+ rule(:suffix) { match["A-Za-z"].repeat(1).as(:suffix) }
31
+
32
+ # Hyphen parts.
33
+ rule(:part) { str("-") >> digits.as(:part) }
34
+ rule(:parts) { part.repeat(0).as(:parts) }
35
+
36
+ # Release token, stored verbatim: everything up to the version separator.
37
+ # Excludes ":" (as well as "/") so the ":"-delimited URN scheme can always
38
+ # encode it — every real release ("REL-4", "Ph1", "UMTS", "Release 2000")
39
+ # is colon-free.
40
+ rule(:release) { match["^/:"].repeat(1).as(:release) }
41
+
42
+ # Three-part version, kept as a string.
43
+ rule(:version) do
44
+ (digits >> str(".") >> digits >> str(".") >> digits).as(:version)
45
+ end
46
+
47
+ rule(:identifier) do
48
+ publisher_prefix.maybe >>
49
+ type >> space >>
50
+ number_core >> suffix.maybe >> parts >>
51
+ (str(":") >> release).maybe >>
52
+ str("/") >> version
53
+ end
54
+
55
+ rule(:root) { identifier }
56
+
57
+ def self.parse(input)
58
+ new.parse(input)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ # Human-readable renderer for 3GPP identifiers.
6
+ #
7
+ # Produces strings like:
8
+ # "TS 23.207:REL-4/2.0.0" (default, no publisher)
9
+ # "3GPP TS 23.207:REL-4/2.0.0" (with_publisher: true)
10
+ # "TS 29.198-04-1:REL-5/5.0.0" (parts)
11
+ # "TR 00.01U:UMTS/3.0.0" (suffix)
12
+ class Renderer < ::Pubid::Renderers::Base
13
+ PUBLISHER = "3GPP"
14
+
15
+ def render(context: nil, **_opts)
16
+ id = @id
17
+ head = []
18
+ head << PUBLISHER if with_publisher?(id)
19
+ head << id.type_prefix
20
+ result = "#{head.join(' ')} #{id.code}"
21
+ # A handful of legacy records omit the release segment entirely
22
+ # (e.g. "TS 29.215/2.0.0").
23
+ result += ":#{id.release}" if id.release
24
+ "#{result}/#{id.version}"
25
+ end
26
+
27
+ private
28
+
29
+ # Default is no publisher token (the relaton index id form); the caller
30
+ # opts in via `to_s(with_publisher: true)`.
31
+ def with_publisher?(id)
32
+ id.with_publisher == true
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ # Emits `urn:3gpp:<type>:<code>:<release>:<version>`, e.g.
6
+ # `urn:3gpp:ts:23.207:REL-4:2.0.0`. `<code>` is number+suffix+parts.
7
+ class UrnGenerator < Pubid::UrnGenerator::Base
8
+ def generate
9
+ [
10
+ "urn",
11
+ "3gpp",
12
+ identifier.type_prefix.downcase,
13
+ identifier.code,
14
+ identifier.release,
15
+ identifier.version,
16
+ ].join(":")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Tgpp
5
+ # Parses 3GPP URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits `urn:3gpp:<type>:<code>:<release>:<version>`; the code,
8
+ # release and version chunks never contain ":", so a plain split recovers
9
+ # them. Example: urn:3gpp:ts:23.207:REL-4:2.0.0 → TS 23.207:REL-4/2.0.0
10
+ class UrnParser < Pubid::UrnParser::Base
11
+ # The module is Tgpp but the URN namespace is "3gpp".
12
+ def flavor_name
13
+ "3gpp"
14
+ end
15
+
16
+ def parse_urn(urn)
17
+ body = strip_namespace(urn)
18
+ type, code, release, version = split_parts(body)
19
+ # The rare no-release form (e.g. TS 29.215/2.0.0) serialises with an
20
+ # empty release chunk ("urn:3gpp:ts:29.215::2.0.0"); rebuild it without
21
+ # the release colon.
22
+ head = "#{type.upcase} #{code}"
23
+ head += ":#{release}" unless release.nil? || release.empty?
24
+ flavor_parse("#{head}/#{version}")
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/pubid/tgpp.rb ADDED
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ # 3GPP (3rd Generation Partnership Project) flavor.
5
+ #
6
+ # The Ruby constant is `Pubid::Tgpp` because a constant may not begin with a
7
+ # digit, but the external contract stays "3gpp": the registry key is "3gpp",
8
+ # the polymorphic `_type` is `pubid:3gpp:…`, and URNs use the `urn:3gpp:`
9
+ # namespace. Only the on-disk file names (lib/pubid/tgpp/…) follow the module.
10
+ module Tgpp
11
+ extend Pubid::PrefixesSupport
12
+
13
+ # Sole routing token. 3GPP references are printed as "3GPP TS 23.207:…";
14
+ # the bare document types (TR/TS) are ambiguous (JIS uses them too) and are
15
+ # excluded. The parser still accepts an optional leading "3GPP ".
16
+ PREFIXES = ["3GPP"].freeze
17
+
18
+ autoload :Builder, "#{__dir__}/tgpp/builder"
19
+ autoload :Identifier, "#{__dir__}/tgpp/identifier"
20
+ autoload :Identifiers, "#{__dir__}/tgpp/identifiers"
21
+ autoload :Parser, "#{__dir__}/tgpp/parser"
22
+ autoload :Renderer, "#{__dir__}/tgpp/renderer"
23
+ autoload :UrnGenerator, "#{__dir__}/tgpp/urn_generator"
24
+ autoload :UrnParser, "#{__dir__}/tgpp/urn_parser"
25
+
26
+ # Parse a 3GPP identifier string
27
+ def self.parse(identifier)
28
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
29
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
30
+ end
31
+
32
+ Identifier.parse(identifier)
33
+ end
34
+
35
+ # Per-flavor format registry: inherits global formats, overrides :human
36
+ Identifier.format_registry = FormatRegistry.new(parent: Identifier.format_registry)
37
+ Identifier.format_registry.register(:human, renderer: Tgpp::Renderer)
38
+
39
+ # Auto-discover all identifier types from the Identifiers namespace
40
+ # @return [Array<Class>] identifier classes that define a self.type Hash
41
+ def self.identifier_types
42
+ @identifier_types ||= Identifiers.constants
43
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
44
+ .select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
45
+ .select { |c| c.type.is_a?(Hash) }
46
+ end
47
+
48
+ # Build typed stage index from identifier types
49
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
50
+ def self.all_typed_stages
51
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
52
+ if klass.const_defined?(:TYPED_STAGES)
53
+ klass.const_get(:TYPED_STAGES)
54
+ else
55
+ []
56
+ end
57
+ end
58
+ end
59
+
60
+ # Lookup: type code -> identifier class
61
+ # @param code [String, Symbol] the type key to find
62
+ # @return [Class, nil] the matching identifier class
63
+ def self.locate_type(code)
64
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
65
+ end
66
+
67
+ # Lookup: abbreviation -> typed stage
68
+ # @param abbr [String, Symbol] the abbreviation to find
69
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
70
+ def self.locate_stage(abbr)
71
+ abbr_str = abbr.to_s.upcase
72
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
73
+ end
74
+ end
75
+ end
76
+
77
+ # Register 3GPP flavor with the registry (external key stays "3gpp").
78
+ Pubid::Registry.register(:"3gpp", Pubid::Tgpp)
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ # Resolves a polymorphic `_type` string (e.g. "pubid:iso:technical-report")
5
+ # to the concrete Ruby class that owns it.
6
+ #
7
+ # Each flavor's Identifier base owns a `polymorphic_type_map` for the types
8
+ # defined in its own namespace. A nested polymorphic attribute (e.g. a GOST
9
+ # Harmonized identifier's adopted ISO identifier) carries a `_type` from a
10
+ # different flavor, so the owning flavor's map misses. This service routes
11
+ # the lookup to the registered flavor whose name appears in the type's
12
+ # second segment ("pubid:<flavor>:…"), giving every from_hash caller a
13
+ # single cross-flavor dispatch path.
14
+ class TypeResolver
15
+ TYPE_PREFIX = "pubid:"
16
+ SEGMENT_SEPARATOR = ":"
17
+
18
+ class << self
19
+ # @param type [String, nil] Polymorphic _type, e.g. "pubid:iso:technical-report".
20
+ # @return [Class<Pubid::Identifier>, nil] The concrete class, or nil if
21
+ # the type is blank, malformed, or unknown to its flavor.
22
+ def resolve(type)
23
+ return nil unless type.is_a?(String)
24
+
25
+ flavor_name = flavor_segment(type)
26
+ return nil unless flavor_name
27
+
28
+ # Ensure the flavor module is loaded so its self-register call has
29
+ # run; without this, Registry may know of flavors that haven't yet
30
+ # populated their Identifier base's polymorphic_type_map.
31
+ ::Pubid.eager_load_flavors!
32
+
33
+ flavor = ::Pubid::Registry.get(flavor_name)
34
+ return nil unless flavor
35
+
36
+ identifier_base = flavor::Identifier
37
+ identifier_base.polymorphic_type_map[type]
38
+ rescue NameError
39
+ # Flavor module is registered but its Identifier base cannot be
40
+ # loaded (autoload failure). Treat as unresolvable.
41
+ nil
42
+ end
43
+
44
+ private
45
+
46
+ # The flavor name is the segment between the leading "pubid:" and the
47
+ # type-name, e.g. "iso" in "pubid:iso:technical-report".
48
+ def flavor_segment(type)
49
+ return nil unless type.start_with?(TYPE_PREFIX)
50
+
51
+ remainder = type[TYPE_PREFIX.length..]
52
+ flavor_end = remainder.index(SEGMENT_SEPARATOR)
53
+ return nil unless flavor_end
54
+
55
+ remainder[0, flavor_end]
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Un
5
+ class Builder
6
+ YEAR_REGEX = /\A\d{4}\z/.freeze
7
+
8
+ def self.build(parsed_data)
9
+ new.build(parsed_data)
10
+ end
11
+
12
+ def build(data)
13
+ tokens = extract_tokens(data)
14
+ raise "UN identifier has no tokens" if tokens.empty?
15
+
16
+ number = tokens.last
17
+ path = tokens[0...-1]
18
+ year_token = path.reverse.find { |t| t.match?(YEAR_REGEX) }
19
+
20
+ Identifiers::Document.new(
21
+ path: path,
22
+ number: number,
23
+ date: year_token ? ::Pubid::Components::Date.new(year: year_token) : nil,
24
+ )
25
+ end
26
+
27
+ private
28
+
29
+ def extract_tokens(data)
30
+ raw = data.is_a?(Hash) ? data[:token] : data
31
+ case raw
32
+ when Array
33
+ raw.map { |h| h.is_a?(Hash) ? h[:token].to_s : h.to_s }
34
+ when Hash
35
+ [raw[:token].to_s]
36
+ else
37
+ [raw.to_s]
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Un
5
+ class Identifier < ::Pubid::Identifier
6
+ attribute :path, :string, collection: true, default: []
7
+ attribute :number, :string
8
+
9
+ UN_TYPE_MAP = {
10
+ "pubid:un:document" => "Pubid::Un::Identifiers::Document",
11
+ }.freeze
12
+
13
+ key_value do
14
+ map "_type", to: :_type, polymorphic_map: UN_TYPE_MAP
15
+ map "path", to: :path
16
+ map "number", to: :number
17
+ end
18
+
19
+ PUBLISHER = "UN"
20
+
21
+ def to_s(**opts)
22
+ render(format: :human, **opts)
23
+ end
24
+
25
+ def self.parse(identifier)
26
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
27
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
28
+ end
29
+
30
+ parsed = Parser.parse(identifier)
31
+ Builder.build(parsed)
32
+ rescue Parslet::ParseFailed => e
33
+ raise "Failed to parse UN identifier '#{identifier}': #{e.message}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Un
5
+ module Identifiers
6
+ class Document < Identifier
7
+ TYPED_STAGES = [
8
+ Pubid::Components::TypedStage.new(
9
+ code: :pubun,
10
+ stage_code: :published,
11
+ type_code: :un,
12
+ abbr: ["UN"],
13
+ name: "UN Document",
14
+ harmonized_stages: %w[60.00 60.60],
15
+ ),
16
+ ].freeze
17
+
18
+ def self.type
19
+ { key: :un, web: :document, title: "UN Document", short: "UN" }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Un
5
+ module Identifiers
6
+ autoload :Document, "#{__dir__}/identifiers/document"
7
+ end
8
+ end
9
+ end