pubid 2.0.0.pre.alpha.2 → 2.0.0.pre.alpha.4

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 (473) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +25 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +4 -55
  6. data/lib/pubid/amca/identifiers/base.rb +58 -47
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -21
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -17
  9. data/lib/pubid/amca/identifiers/standard.rb +0 -4
  10. data/lib/pubid/amca/renderer.rb +82 -0
  11. data/lib/pubid/amca/single_identifier.rb +0 -23
  12. data/lib/pubid/amca/urn_generator.rb +2 -1
  13. data/lib/pubid/amca/urn_parser.rb +28 -0
  14. data/lib/pubid/amca.rb +42 -1
  15. data/lib/pubid/ansi/builder.rb +5 -3
  16. data/lib/pubid/ansi/identifier.rb +1 -43
  17. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  18. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  19. data/lib/pubid/ansi/renderer.rb +53 -0
  20. data/lib/pubid/ansi/single_identifier.rb +2 -31
  21. data/lib/pubid/ansi/urn_generator.rb +3 -38
  22. data/lib/pubid/ansi/urn_parser.rb +23 -0
  23. data/lib/pubid/ansi.rb +38 -3
  24. data/lib/pubid/api/builder.rb +33 -74
  25. data/lib/pubid/api/identifier.rb +5 -52
  26. data/lib/pubid/api/identifiers/base.rb +2 -14
  27. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  28. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  29. data/lib/pubid/api/identifiers/mpms.rb +0 -20
  30. data/lib/pubid/api/identifiers/publication.rb +0 -2
  31. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  32. data/lib/pubid/api/identifiers/specification.rb +0 -2
  33. data/lib/pubid/api/identifiers/standard.rb +0 -2
  34. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  35. data/lib/pubid/api/identifiers/typeless_standard.rb +0 -16
  36. data/lib/pubid/api/identifiers.rb +18 -0
  37. data/lib/pubid/api/renderer.rb +89 -0
  38. data/lib/pubid/api/single_identifier.rb +5 -20
  39. data/lib/pubid/api/urn_generator.rb +0 -18
  40. data/lib/pubid/api/urn_parser.rb +35 -0
  41. data/lib/pubid/api.rb +51 -5
  42. data/lib/pubid/ashrae/builder.rb +3 -3
  43. data/lib/pubid/ashrae/identifier.rb +7 -55
  44. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  45. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  46. data/lib/pubid/ashrae/identifiers/base.rb +29 -15
  47. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  48. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  49. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  50. data/lib/pubid/ashrae/parser.rb +4 -0
  51. data/lib/pubid/ashrae/renderer.rb +117 -0
  52. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  53. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  54. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  55. data/lib/pubid/ashrae.rb +46 -1
  56. data/lib/pubid/asme/components/code.rb +10 -2
  57. data/lib/pubid/asme/identifier.rb +0 -46
  58. data/lib/pubid/asme/identifiers/base.rb +0 -60
  59. data/lib/pubid/asme/renderer.rb +66 -0
  60. data/lib/pubid/asme/single_identifier.rb +3 -1
  61. data/lib/pubid/asme/urn_parser.rb +31 -0
  62. data/lib/pubid/asme.rb +42 -1
  63. data/lib/pubid/astm/components/code.rb +9 -0
  64. data/lib/pubid/{jis → astm}/components.rb +1 -1
  65. data/lib/pubid/astm/identifier.rb +0 -77
  66. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  67. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  68. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  69. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  70. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  71. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  72. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  73. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  74. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  75. data/lib/pubid/astm/identifiers.rb +18 -0
  76. data/lib/pubid/astm/renderer.rb +172 -0
  77. data/lib/pubid/astm/single_identifier.rb +3 -11
  78. data/lib/pubid/astm/urn_parser.rb +30 -0
  79. data/lib/pubid/astm.rb +39 -27
  80. data/lib/pubid/bsi/builder.rb +21 -12
  81. data/lib/pubid/bsi/identifier.rb +5 -85
  82. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -36
  83. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +8 -48
  84. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +8 -39
  85. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +2 -55
  86. data/lib/pubid/bsi/identifiers/amendment.rb +2 -22
  87. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -6
  88. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  89. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -87
  90. data/lib/pubid/bsi/identifiers/committee_document.rb +0 -16
  91. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -87
  92. data/lib/pubid/bsi/identifiers/corrigendum.rb +2 -10
  93. data/lib/pubid/bsi/identifiers/detailed_specification.rb +0 -36
  94. data/lib/pubid/bsi/identifiers/disc.rb +0 -29
  95. data/lib/pubid/bsi/identifiers/draft_document.rb +2 -46
  96. data/lib/pubid/bsi/identifiers/electronic_book.rb +2 -38
  97. data/lib/pubid/bsi/identifiers/expert_commentary.rb +2 -18
  98. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +0 -47
  99. data/lib/pubid/bsi/identifiers/flex.rb +0 -35
  100. data/lib/pubid/bsi/identifiers/handbook.rb +1 -15
  101. data/lib/pubid/bsi/identifiers/index.rb +0 -32
  102. data/lib/pubid/bsi/identifiers/method.rb +0 -41
  103. data/lib/pubid/bsi/identifiers/national_annex.rb +4 -29
  104. data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -6
  105. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +2 -54
  106. data/lib/pubid/bsi/identifiers/published_document.rb +2 -54
  107. data/lib/pubid/bsi/identifiers/section.rb +0 -30
  108. data/lib/pubid/bsi/identifiers/set.rb +3 -20
  109. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +0 -9
  110. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -24
  111. data/lib/pubid/bsi/identifiers/supplementary_index.rb +0 -46
  112. data/lib/pubid/bsi/identifiers/technical_specification.rb +2 -47
  113. data/lib/pubid/bsi/identifiers/test_method.rb +0 -32
  114. data/lib/pubid/bsi/identifiers/value_added_publication.rb +2 -17
  115. data/lib/pubid/bsi/identifiers.rb +0 -1
  116. data/lib/pubid/bsi/renderer.rb +1050 -0
  117. data/lib/pubid/bsi/single_identifier.rb +33 -78
  118. data/lib/pubid/bsi/urn_generator.rb +2 -3
  119. data/lib/pubid/bsi/urn_parser.rb +52 -0
  120. data/lib/pubid/bsi.rb +232 -2
  121. data/lib/pubid/builder/base.rb +57 -10
  122. data/lib/pubid/bundled_identifier.rb +0 -1
  123. data/lib/pubid/ccsds/builder.rb +4 -3
  124. data/lib/pubid/ccsds/identifier.rb +53 -68
  125. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  126. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  127. data/lib/pubid/ccsds/parser.rb +4 -2
  128. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  129. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  130. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  131. data/lib/pubid/ccsds.rb +39 -1
  132. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  133. data/lib/pubid/cen_cenelec/identifier.rb +11 -40
  134. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +9 -4
  135. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +0 -10
  136. data/lib/pubid/cen_cenelec/identifiers/base.rb +2 -45
  137. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +0 -27
  140. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +0 -15
  141. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +2 -8
  143. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +0 -4
  145. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  146. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  147. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  148. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  149. data/lib/pubid/cen_cenelec/single_identifier.rb +9 -90
  150. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  151. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  152. data/lib/pubid/cen_cenelec.rb +172 -1
  153. data/lib/pubid/cie/components/code.rb +8 -0
  154. data/lib/pubid/cie/identifier.rb +10 -57
  155. data/lib/pubid/cie/single_identifier.rb +4 -4
  156. data/lib/pubid/cie/urn_parser.rb +28 -0
  157. data/lib/pubid/cie.rb +47 -1
  158. data/lib/pubid/components/adoption.rb +104 -0
  159. data/lib/pubid/components/code.rb +22 -8
  160. data/lib/pubid/components/date.rb +23 -16
  161. data/lib/pubid/components/edition.rb +9 -6
  162. data/lib/pubid/components/iteration.rb +32 -0
  163. data/lib/pubid/components/language.rb +6 -4
  164. data/lib/pubid/components/locality.rb +10 -1
  165. data/lib/pubid/components/publisher.rb +9 -6
  166. data/lib/pubid/components/relationship.rb +151 -0
  167. data/lib/pubid/components/stage.rb +5 -14
  168. data/lib/pubid/components/supplement.rb +184 -0
  169. data/lib/pubid/components/type.rb +5 -15
  170. data/lib/pubid/components/typed_stage.rb +10 -11
  171. data/lib/pubid/components.rb +4 -1
  172. data/lib/pubid/core/update_codes.rb +28 -7
  173. data/lib/pubid/csa/identifier.rb +9 -59
  174. data/lib/pubid/csa/identifiers/base.rb +0 -123
  175. data/lib/pubid/csa/identifiers/cec.rb +0 -103
  176. data/lib/pubid/csa/identifiers/series.rb +0 -104
  177. data/lib/pubid/csa/renderer.rb +292 -0
  178. data/lib/pubid/csa/single_identifier.rb +1 -1
  179. data/lib/pubid/csa/urn_generator.rb +1 -1
  180. data/lib/pubid/csa/urn_parser.rb +33 -0
  181. data/lib/pubid/csa.rb +46 -1
  182. data/lib/pubid/etsi/components/code.rb +10 -9
  183. data/lib/pubid/etsi/components/version.rb +0 -5
  184. data/lib/pubid/etsi/identifier.rb +4 -55
  185. data/lib/pubid/etsi/identifiers/base.rb +31 -27
  186. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +1 -11
  187. data/lib/pubid/etsi/renderer.rb +42 -0
  188. data/lib/pubid/etsi/urn_parser.rb +34 -0
  189. data/lib/pubid/etsi.rb +44 -1
  190. data/lib/pubid/export/exporter.rb +4 -46
  191. data/lib/pubid/export/flavor_exporter.rb +111 -278
  192. data/lib/pubid/export.rb +0 -6
  193. data/lib/pubid/identifier.rb +92 -18
  194. data/lib/pubid/identifier_metadata.rb +1 -1
  195. data/lib/pubid/idf/builder.rb +3 -3
  196. data/lib/pubid/idf/identifier.rb +7 -66
  197. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  198. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  199. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  200. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  201. data/lib/pubid/idf/parser.rb +3 -2
  202. data/lib/pubid/idf/renderer.rb +84 -0
  203. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  204. data/lib/pubid/idf/urn_generator.rb +4 -39
  205. data/lib/pubid/idf/urn_parser.rb +25 -0
  206. data/lib/pubid/idf.rb +55 -1
  207. data/lib/pubid/iec/builder.rb +46 -64
  208. data/lib/pubid/iec/components/code.rb +8 -32
  209. data/lib/pubid/iec/components/publisher.rb +0 -1
  210. data/lib/pubid/iec/components.rb +14 -0
  211. data/lib/pubid/iec/identifier.rb +251 -213
  212. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  213. data/lib/pubid/iec/identifiers/base.rb +5 -33
  214. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  215. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  216. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +23 -26
  217. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  218. data/lib/pubid/iec/identifiers/fragment_identifier.rb +35 -24
  219. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  220. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  221. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  222. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  223. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  224. data/lib/pubid/iec/identifiers/sheet_identifier.rb +17 -11
  225. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  226. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  227. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  228. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  229. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  230. data/lib/pubid/iec/identifiers/test_report_form.rb +3 -35
  231. data/lib/pubid/iec/identifiers/vap_identifier.rb +24 -21
  232. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  233. data/lib/pubid/iec/identifiers/working_document.rb +2 -50
  234. data/lib/pubid/iec/identifiers.rb +30 -0
  235. data/lib/pubid/iec/parser.rb +13 -12
  236. data/lib/pubid/iec/renderer.rb +254 -0
  237. data/lib/pubid/iec/single_identifier.rb +6 -12
  238. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  239. data/lib/pubid/iec/urn_generator.rb +3 -3
  240. data/lib/pubid/iec/urn_parser.rb +3 -3
  241. data/lib/pubid/iec.rb +43 -67
  242. data/lib/pubid/ieee/builder.rb +12 -12
  243. data/lib/pubid/ieee/components/code.rb +8 -0
  244. data/lib/pubid/ieee/components/draft.rb +14 -0
  245. data/lib/pubid/ieee/components/relationship.rb +5 -149
  246. data/lib/pubid/ieee/identifier.rb +5 -52
  247. data/lib/pubid/ieee/identifiers/adopted_standard.rb +0 -9
  248. data/lib/pubid/ieee/identifiers/base.rb +221 -556
  249. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +0 -10
  250. data/lib/pubid/ieee/identifiers/corrigendum.rb +0 -12
  251. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +0 -10
  252. data/lib/pubid/ieee/identifiers/dual_identifier.rb +0 -4
  253. data/lib/pubid/ieee/identifiers/dual_published.rb +0 -4
  254. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +0 -9
  255. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +0 -10
  256. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  257. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +0 -18
  258. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +0 -6
  259. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  260. data/lib/pubid/ieee/identifiers/redlined_standard.rb +0 -7
  261. data/lib/pubid/ieee/identifiers/si_standard.rb +0 -38
  262. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  263. data/lib/pubid/ieee/pre_parser.rb +301 -0
  264. data/lib/pubid/ieee/renderer.rb +307 -0
  265. data/lib/pubid/ieee/urn_parser.rb +34 -0
  266. data/lib/pubid/ieee.rb +66 -1
  267. data/lib/pubid/ieee_debug.rb +0 -1
  268. data/lib/pubid/iho/builder.rb +2 -2
  269. data/lib/pubid/iho/identifier.rb +7 -59
  270. data/lib/pubid/iho/identifiers/base.rb +64 -31
  271. data/lib/pubid/iho/parser.rb +3 -3
  272. data/lib/pubid/iho/renderer.rb +30 -0
  273. data/lib/pubid/iho/urn_generator.rb +2 -2
  274. data/lib/pubid/iho/urn_parser.rb +58 -0
  275. data/lib/pubid/iho.rb +52 -1
  276. data/lib/pubid/iso/builder.rb +55 -53
  277. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  278. data/lib/pubid/iso/components/code.rb +7 -19
  279. data/lib/pubid/iso/components/publisher.rb +10 -8
  280. data/lib/pubid/iso/components.rb +2 -4
  281. data/lib/pubid/iso/identifier.rb +219 -252
  282. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  283. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  284. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  285. data/lib/pubid/iso/identifiers/data.rb +0 -1
  286. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  287. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  288. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  289. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  290. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  291. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  292. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  293. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  294. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  295. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  296. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  297. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  298. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  299. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  300. data/lib/pubid/iso/identifiers.rb +0 -1
  301. data/lib/pubid/iso/normalizer.rb +89 -0
  302. data/lib/pubid/iso/parser.rb +22 -4
  303. data/lib/pubid/iso/single_identifier.rb +0 -4
  304. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  305. data/lib/pubid/iso/urn_generator.rb +66 -182
  306. data/lib/pubid/iso/urn_parser.rb +12 -7
  307. data/lib/pubid/iso.rb +177 -2
  308. data/lib/pubid/itu/builder.rb +0 -12
  309. data/lib/pubid/itu/components/code.rb +9 -7
  310. data/lib/pubid/itu/components/sector.rb +15 -4
  311. data/lib/pubid/itu/components/series.rb +0 -4
  312. data/lib/pubid/itu/components.rb +11 -0
  313. data/lib/pubid/itu/identifier.rb +4 -116
  314. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  315. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  316. data/lib/pubid/itu/identifiers/base.rb +124 -128
  317. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  318. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  319. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  320. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  321. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  322. data/lib/pubid/itu/urn_parser.rb +23 -0
  323. data/lib/pubid/itu.rb +44 -1
  324. data/lib/pubid/jcgm/builder.rb +16 -8
  325. data/lib/pubid/jcgm/identifier.rb +0 -43
  326. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -9
  327. data/lib/pubid/jcgm/identifiers/gum_guide.rb +0 -12
  328. data/lib/pubid/jcgm/renderer.rb +68 -0
  329. data/lib/pubid/jcgm/single_identifier.rb +0 -8
  330. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  331. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  332. data/lib/pubid/jcgm.rb +43 -2
  333. data/lib/pubid/jis/builder.rb +44 -52
  334. data/lib/pubid/jis/identifier.rb +120 -46
  335. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  336. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  337. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  338. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  339. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  340. data/lib/pubid/jis/identifiers.rb +1 -1
  341. data/lib/pubid/jis/parser.rb +31 -5
  342. data/lib/pubid/jis/renderer.rb +69 -0
  343. data/lib/pubid/jis/single_identifier.rb +6 -12
  344. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  345. data/lib/pubid/jis/urn_parser.rb +23 -0
  346. data/lib/pubid/jis.rb +42 -2
  347. data/lib/pubid/nist/builder.rb +63 -1871
  348. data/lib/pubid/nist/caster.rb +1272 -0
  349. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  350. data/lib/pubid/nist/components/code.rb +9 -20
  351. data/lib/pubid/nist/components/supplement.rb +2 -2
  352. data/lib/pubid/nist/components.rb +0 -1
  353. data/lib/pubid/nist/identifier.rb +8 -60
  354. data/lib/pubid/nist/identifiers/base.rb +564 -492
  355. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  356. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  357. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  358. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  359. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  360. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  361. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  362. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  363. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  364. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  365. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  366. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  367. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  368. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  369. data/lib/pubid/nist/identifiers/report.rb +4 -2
  370. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  371. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  372. data/lib/pubid/nist/identifiers.rb +1 -0
  373. data/lib/pubid/nist/parser.rb +62 -452
  374. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  375. data/lib/pubid/nist/preprocessor.rb +428 -0
  376. data/lib/pubid/nist/renderer.rb +43 -0
  377. data/lib/pubid/nist/router.rb +148 -0
  378. data/lib/pubid/nist/series/base.rb +58 -0
  379. data/lib/pubid/nist/series/crpl.rb +13 -0
  380. data/lib/pubid/nist/series/fips.rb +14 -0
  381. data/lib/pubid/nist/series/ir.rb +60 -0
  382. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  383. data/lib/pubid/nist/series/mono.rb +19 -0
  384. data/lib/pubid/nist/series/ncstar.rb +20 -0
  385. data/lib/pubid/nist/series.rb +49 -0
  386. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  387. data/lib/pubid/nist/urn_parser.rb +67 -0
  388. data/lib/pubid/nist.rb +86 -4
  389. data/lib/pubid/oiml/builder.rb +21 -3
  390. data/lib/pubid/oiml/components/code.rb +17 -0
  391. data/lib/pubid/oiml/identifier.rb +40 -46
  392. data/lib/pubid/oiml/identifiers/annex.rb +13 -46
  393. data/lib/pubid/oiml/identifiers/errata.rb +15 -0
  394. data/lib/pubid/oiml/identifiers.rb +1 -1
  395. data/lib/pubid/oiml/parser.rb +59 -12
  396. data/lib/pubid/oiml/renderer.rb +171 -0
  397. data/lib/pubid/oiml/single_identifier.rb +61 -42
  398. data/lib/pubid/oiml/supplement_identifier.rb +31 -17
  399. data/lib/pubid/oiml/urn_generator.rb +0 -8
  400. data/lib/pubid/oiml/urn_parser.rb +22 -0
  401. data/lib/pubid/oiml.rb +42 -1
  402. data/lib/pubid/plateau/identifier.rb +4 -55
  403. data/lib/pubid/plateau/identifiers/base.rb +45 -36
  404. data/lib/pubid/plateau/identifiers/handbook.rb +0 -6
  405. data/lib/pubid/plateau/identifiers/technical_report.rb +0 -4
  406. data/lib/pubid/plateau/renderer.rb +51 -0
  407. data/lib/pubid/plateau/supplement_identifier.rb +0 -4
  408. data/lib/pubid/plateau/urn_parser.rb +43 -0
  409. data/lib/pubid/plateau.rb +43 -1
  410. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  411. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  412. data/lib/pubid/renderers/human_readable.rb +18 -7
  413. data/lib/pubid/rendering/context.rb +28 -19
  414. data/lib/pubid/rendering.rb +0 -3
  415. data/lib/pubid/sae/components/date.rb +8 -0
  416. data/lib/pubid/sae/components/type.rb +5 -1
  417. data/lib/pubid/sae/identifier.rb +4 -35
  418. data/lib/pubid/sae/identifiers/base.rb +26 -31
  419. data/lib/pubid/sae/renderer.rb +36 -0
  420. data/lib/pubid/sae/urn_generator.rb +2 -10
  421. data/lib/pubid/sae/urn_parser.rb +36 -0
  422. data/lib/pubid/sae.rb +42 -1
  423. data/lib/pubid/urn_generator/base.rb +12 -12
  424. data/lib/pubid/urn_parser/base.rb +81 -0
  425. data/lib/pubid/urn_parser/errors.rb +9 -0
  426. data/lib/pubid/urn_parser.rb +14 -0
  427. data/lib/pubid/version.rb +1 -1
  428. data/lib/pubid.rb +45 -7
  429. data/lib/tasks/export.rake +6 -5
  430. data/lib/tasks/website-data.json +1940 -1882
  431. metadata +75 -45
  432. data/lib/pubid/amca/scheme.rb +0 -16
  433. data/lib/pubid/ansi/scheme.rb +0 -15
  434. data/lib/pubid/api/scheme.rb +0 -66
  435. data/lib/pubid/ashrae/scheme.rb +0 -53
  436. data/lib/pubid/asme/scheme.rb +0 -37
  437. data/lib/pubid/astm/scheme.rb +0 -55
  438. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  439. data/lib/pubid/bsi/scheme.rb +0 -243
  440. data/lib/pubid/ccsds/scheme.rb +0 -57
  441. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  442. data/lib/pubid/cie/scheme.rb +0 -64
  443. data/lib/pubid/components/factory.rb +0 -50
  444. data/lib/pubid/csa/scheme.rb +0 -44
  445. data/lib/pubid/etsi/scheme.rb +0 -42
  446. data/lib/pubid/export/data_class_exporter.rb +0 -59
  447. data/lib/pubid/export/ieee_exporter.rb +0 -78
  448. data/lib/pubid/export/itu_exporter.rb +0 -66
  449. data/lib/pubid/export/nist_exporter.rb +0 -64
  450. data/lib/pubid/export/registry_exporter.rb +0 -90
  451. data/lib/pubid/export/scheme_exporter.rb +0 -70
  452. data/lib/pubid/identifier_registry.rb +0 -198
  453. data/lib/pubid/idf/scheme.rb +0 -61
  454. data/lib/pubid/iec/scheme.rb +0 -71
  455. data/lib/pubid/ieee/scheme.rb +0 -90
  456. data/lib/pubid/iho/scheme.rb +0 -29
  457. data/lib/pubid/iso/identifiers/base.rb +0 -115
  458. data/lib/pubid/iso/scheme.rb +0 -193
  459. data/lib/pubid/itu/scheme.rb +0 -174
  460. data/lib/pubid/jcgm/scheme.rb +0 -60
  461. data/lib/pubid/jis/components/code.rb +0 -59
  462. data/lib/pubid/jis/identifiers/base.rb +0 -72
  463. data/lib/pubid/jis/scheme.rb +0 -49
  464. data/lib/pubid/nist/components/publisher.rb +0 -24
  465. data/lib/pubid/nist/scheme.rb +0 -199
  466. data/lib/pubid/oiml/identifiers/base.rb +0 -36
  467. data/lib/pubid/oiml/scheme.rb +0 -46
  468. data/lib/pubid/plateau/scheme.rb +0 -45
  469. data/lib/pubid/rendering/base.rb +0 -73
  470. data/lib/pubid/rendering/common.rb +0 -211
  471. data/lib/pubid/rendering/format.rb +0 -25
  472. data/lib/pubid/sae/scheme.rb +0 -47
  473. data/lib/pubid/scheme.rb +0 -219
@@ -1,14 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "components/code"
4
- require_relative "components/date"
5
- require_relative "components/edition"
6
- require_relative "components/language"
7
- require_relative "components/locality"
8
- require_relative "components/publisher"
9
- require_relative "components/stage"
10
- require_relative "components/type"
11
-
12
3
  module Pubid
13
4
  class Identifier < Lutaml::Model::Serializable
14
5
  class << self
@@ -17,13 +8,103 @@ module Pubid
17
8
  end
18
9
 
19
10
  attr_writer :format_registry
11
+
12
+ # Polymorphic deserialization shared by every flavor base. lutaml's
13
+ # `key_value` polymorphic_map reads `_type` only to VALIDATE; it does not
14
+ # re-instantiate the concrete subclass. So a base-class `from_hash` would
15
+ # return a bare base object and drop subtype-specific attributes (e.g. a
16
+ # supplement's base_identifier). Route by `_type` to the concrete class
17
+ # named in `polymorphic_type_map`, then let its inherited from_hash (this
18
+ # method again, where klass == self) fall through to lutaml's real work.
19
+ #
20
+ # This generalizes the per-flavor `*_TYPE_MAP` dispatch that ISO, JIS,
21
+ # IEC, CCSDS and IHO each hand-rolled — one implementation, inherited by
22
+ # every flavor base.
23
+ def from_hash(data, options = {})
24
+ type = data && (data["_type"] || data[:_type])
25
+ klass = polymorphic_type_map[type]
26
+ return klass.from_hash(data, options) if klass && klass != self
27
+
28
+ super
29
+ end
30
+
31
+ # Map of polymorphic_name ("pubid:iso:corrigendum") => concrete class for
32
+ # the flavor this base belongs to. Built once by scanning the flavor's
33
+ # `Identifiers` namespace for Pubid::Identifier descendants and unioning
34
+ # the flavor's `identifier_types` registry (which may register classes
35
+ # living outside that namespace, e.g. ISO's BundledIdentifier). Memoized
36
+ # per class.
37
+ def polymorphic_type_map
38
+ @polymorphic_type_map ||=
39
+ identifier_registry_classes.each_with_object({}) do |klass, map|
40
+ poly = klass.polymorphic_name
41
+ map[poly] ||= klass if poly
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ # The flavor module namespacing this base, e.g. Pubid::Iso for
48
+ # Pubid::Iso::Identifier (and for the inherited Pubid::Iso::Identifiers::
49
+ # Corrigendum). Always the first two name components, so it is stable
50
+ # whether `self` is the base or a concrete subclass.
51
+ def flavor_module
52
+ @flavor_module ||= Object.const_get(name.split("::")[0, 2].join("::"))
53
+ end
54
+
55
+ def identifiers_namespace
56
+ @identifiers_namespace ||= flavor_module.const_get(:Identifiers)
57
+ end
58
+
59
+ def identifier_registry_classes
60
+ (scanned_identifier_classes +
61
+ registered_identifier_classes +
62
+ additional_identifier_classes).uniq
63
+ end
64
+
65
+ # Concrete identifier classes found directly in the flavor's `Identifiers`
66
+ # namespace. Empty for the abstract root (no flavor) or a flavor without
67
+ # that namespace. Only this namespace is scanned (never the flavor top
68
+ # level), to avoid force-autoloading unrelated flavor constants.
69
+ def scanned_identifier_classes
70
+ return [] unless flavor_identifiers_namespace?
71
+
72
+ identifiers_namespace.constants.filter_map do |const|
73
+ klass = identifiers_namespace.const_get(const)
74
+ klass if klass.is_a?(Class) && klass < ::Pubid::Identifier
75
+ rescue NameError
76
+ nil
77
+ end
78
+ end
79
+
80
+ # Classes the flavor explicitly registers via `identifier_types`, if any.
81
+ def registered_identifier_classes
82
+ return [] unless flavor_module.respond_to?(:identifier_types)
83
+
84
+ Array(flavor_module.identifier_types)
85
+ end
86
+
87
+ # Hook for identifier classes that carry a polymorphic `_type` but live
88
+ # OUTSIDE the flavor's `Identifiers` namespace (e.g. Pubid::Iso::
89
+ # BundledIdentifier, Pubid::Iec::SingleIdentifier). Flavors with such
90
+ # classes override this; the default is none. Replaces the hand-listing
91
+ # of these in the old static `*_TYPE_MAP`s.
92
+ def additional_identifier_classes
93
+ []
94
+ end
95
+
96
+ def flavor_identifiers_namespace?
97
+ flavor_module.const_defined?(:Identifiers)
98
+ rescue NameError
99
+ false
100
+ end
20
101
  end
21
102
 
22
103
  attribute :_type, :string, polymorphic_class: true
23
104
  attribute :number, Components::Code
24
105
  attribute :part, Components::Code
25
106
  attribute :subpart, Components::Code
26
- attribute :stage_iteration, Components::Code
107
+ attribute :stage_iteration, Components::Iteration
27
108
  attribute :date, Components::Date
28
109
  attribute :edition, Components::Edition
29
110
  attribute :languages, Components::Language, collection: true
@@ -62,13 +143,6 @@ module Pubid
62
143
  "pubid:#{flavor}:#{type_kebab}"
63
144
  end
64
145
 
65
- klass_ref = self
66
- key_value do
67
- klass_ref.attributes.each_key do |name|
68
- map name.to_s, to: name.to_sym
69
- end
70
- end
71
-
72
146
  def root
73
147
  return base_identifier.root if base_identifier
74
148
 
@@ -165,7 +239,7 @@ module Pubid
165
239
  excluded_args << :date if excluded_args.delete(:year)
166
240
 
167
241
  attrs = self.class.attributes.each_with_object({}) do |(name, _), h|
168
- h[name] = excluded_args.include?(name) ? nil : send(name)
242
+ h[name] = excluded_args.include?(name) ? nil : public_send(name)
169
243
  end
170
244
  self.class.new(attrs)
171
245
  end
@@ -102,7 +102,7 @@ module Pubid
102
102
  # Get the metadata for this class
103
103
  # @return [Metadata, nil]
104
104
  def metadata
105
- @metadata ||= if superclass.is_a?(Class) && superclass.respond_to?(:metadata)
105
+ @metadata ||= if superclass.is_a?(Class) && superclass.ancestors.include?(Pubid::IdentifierMetadata)
106
106
  superclass.metadata
107
107
  end
108
108
  end
@@ -13,8 +13,8 @@ module Pubid
13
13
  }.freeze
14
14
 
15
15
  def build(parsed_hash)
16
- typed_stage = Scheme.locate_typed_stage_by_abbr(parsed_hash[:type_with_stage])
17
- identifier = Scheme.locate_identifier_klass_by_type_code(typed_stage.type_code).new
16
+ typed_stage = Pubid::Idf.locate_stage(parsed_hash[:type_with_stage])
17
+ identifier = Pubid::Idf.locate_type(typed_stage.type_code).new
18
18
 
19
19
  if type_with_stage_fr = parsed_hash.delete(:type_with_stage_fr)
20
20
  parsed_hash[:type_with_stage] = type_with_stage_fr
@@ -48,7 +48,7 @@ module Pubid
48
48
  when :type_with_stage
49
49
  iteration = value.to_s.match(/(\d+)$/)
50
50
  value = value.to_s.sub(iteration.to_s, "")
51
- typed_stage = Scheme.locate_typed_stage_by_abbr(value || "")
51
+ typed_stage = Pubid::Idf.locate_stage(value || "")
52
52
  {
53
53
  stage: typed_stage.to_stage,
54
54
  type: typed_stage.to_type,
@@ -7,11 +7,8 @@ module Pubid
7
7
  class Identifier < ::Pubid::Identifier
8
8
  attribute :typed_stage, Components::TypedStage
9
9
 
10
- def to_s(lang: :en, lang_single: false, with_edition: false)
11
- [
12
- publisher_portion(lang: lang),
13
- number_portion(lang_single: lang_single),
14
- ].join
10
+ def to_s(**opts)
11
+ render(format: :human, **opts)
15
12
  end
16
13
 
17
14
  def publisher_portion(lang: :en)
@@ -31,7 +28,7 @@ module Pubid
31
28
  (subpart ? "-#{subpart.value}" : ""),
32
29
 
33
30
  # Stage iteration is optional
34
- (stage_iteration ? ".#{stage_iteration.value}" : ""),
31
+ (stage_iteration ? ".#{stage_iteration.number}" : ""),
35
32
 
36
33
  # Date is optional
37
34
  (date ? ":#{date.year}" : ""),
@@ -56,6 +53,10 @@ module Pubid
56
53
  end
57
54
 
58
55
  def self.parse(string)
56
+ if string.length > Pubid::MAX_INPUT_LENGTH
57
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
58
+ end
59
+
59
60
  parsed = Pubid::Idf::Parser.new.parse(string)
60
61
  if parsed.nil? || parsed.empty?
61
62
  raise Pubid::Idf::Parser::ParseError,
@@ -64,66 +65,6 @@ module Pubid
64
65
 
65
66
  Pubid::Idf::Builder.new.build(parsed)
66
67
  end
67
-
68
- # Factory mirroring pubid 1.x's `Pubid::Idf::Identifier.create` API.
69
- # Default subclass is {Identifiers::InternationalStandard}.
70
- #
71
- # IDF's renderer requires `typed_stage` to be set (calls
72
- # `.abbreviation` without a nil check); factory auto-resolves the
73
- # "published" TypedStage for the chosen subclass.
74
- TYPE_KEY_TO_KLASS = {
75
- is: "InternationalStandard",
76
- reviewed_method: "ReviewedMethod",
77
- }.freeze
78
-
79
- def self.create(type: nil, stage: nil, **opts)
80
- klass = resolve_create_class(type)
81
- attrs = coerce_create_attrs(opts)
82
- ts = resolve_create_typed_stage(klass, stage)
83
- attrs[:typed_stage] = ts if ts
84
- klass.new(**attrs)
85
- end
86
-
87
- def self.resolve_create_class(type)
88
- return Identifiers::InternationalStandard if type.nil?
89
-
90
- klass_name = TYPE_KEY_TO_KLASS[type.to_sym]
91
- raise ArgumentError, "Unknown IDF type: #{type.inspect}" unless klass_name
92
-
93
- Identifiers.const_get(klass_name)
94
- end
95
-
96
- def self.resolve_create_typed_stage(klass, stage)
97
- return nil unless klass.const_defined?(:TYPED_STAGES)
98
-
99
- if stage
100
- klass.const_get(:TYPED_STAGES).find do |ts|
101
- ts.abbr.include?(stage.to_s)
102
- end
103
- else
104
- klass.const_get(:TYPED_STAGES).find do |ts|
105
- ts.stage_code&.to_sym == :published
106
- end
107
- end
108
- end
109
-
110
- def self.coerce_create_attrs(opts)
111
- attrs = {
112
- publisher: Pubid::Components::Publisher.new(
113
- body: (opts[:publisher] || "IDF").to_s,
114
- ),
115
- }
116
- if (v = opts[:number])
117
- attrs[:number] = Pubid::Components::Code.new(value: v.to_s)
118
- end
119
- if (v = opts[:year])
120
- attrs[:date] = Pubid::Components::Date.new(year: v.to_s)
121
- end
122
- attrs
123
- end
124
- private_class_method :resolve_create_class,
125
- :resolve_create_typed_stage,
126
- :coerce_create_attrs
127
68
  end
128
69
  end
129
70
  end
@@ -19,7 +19,8 @@ module Pubid
19
19
  ].freeze
20
20
 
21
21
  def self.type
22
- { key: :amd, title: "Amendment", short: "AMD" }
22
+ { key: :amd,
23
+ web: :amendment, title: "Amendment", short: "AMD" }
23
24
  end
24
25
  end
25
26
  end
@@ -19,7 +19,8 @@ module Pubid
19
19
  ].freeze
20
20
 
21
21
  def self.type
22
- { key: :cor, title: "Corrigendum", short: "COR" }
22
+ { key: :cor,
23
+ web: :corrigendum, title: "Corrigendum", short: "COR" }
23
24
  end
24
25
  end
25
26
  end
@@ -115,7 +115,8 @@ module Pubid
115
115
  ].freeze
116
116
 
117
117
  def self.type
118
- { key: :is, title: "International Standard", short: nil }
118
+ { key: :is,
119
+ web: :international_standard, title: "International Standard", short: nil }
119
120
  end
120
121
  end
121
122
  end
@@ -92,7 +92,8 @@ module Pubid
92
92
  ].freeze
93
93
 
94
94
  def self.type
95
- { key: :rm, title: "Reviewed Method", short: "RM" }
95
+ { key: :rm,
96
+ web: :reviewed_method, title: "Reviewed Method", short: "RM" }
96
97
  end
97
98
  end
98
99
  end
@@ -9,9 +9,10 @@ module Pubid
9
9
  include ::Pubid::Parser::CommonParseMethods
10
10
 
11
11
  # We need to sort by length to match longest first because that's how Parslet works
12
- TYPED_STAGES = Pubid::Idf::Scheme.typed_stages
12
+ TYPED_STAGES = Pubid::Idf.all_typed_stages
13
13
  .map(&:abbr).flatten.sort_by(&:length).reverse
14
- TYPED_STAGES_SUPPLEMENTS = Pubid::Idf::Scheme.supplement_typed_stages
14
+ TYPED_STAGES_SUPPLEMENTS = Pubid::Idf.all_typed_stages
15
+ .select { |ts| %w[amd cor].include?(ts.type_code.to_s) }
15
16
  .map(&:abbr).flatten.sort_by(&:length).reverse
16
17
 
17
18
  root :identifier
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Idf
5
+ # Human-readable renderer for IDF identifiers.
6
+ #
7
+ # Produces strings like:
8
+ # "IDF 125:1988"
9
+ # "IDF/AMD 1:2023"
10
+ # "IDF 125:1988/AMD 1:2023"
11
+ #
12
+ # The renderer is registered as the `:human` format in the IDF format
13
+ # registry and invoked via `render(format: :human)`.
14
+ class Renderer < ::Pubid::Renderers::Base
15
+ def render(context: nil, **opts)
16
+ id = @id
17
+
18
+ case id
19
+ when SupplementIdentifier
20
+ render_supplement(id, opts, context)
21
+ else
22
+ render_single(id, opts, context)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def render_single(id, opts, context)
29
+ [
30
+ publisher_portion(id, context),
31
+ number_portion(id, opts, context),
32
+ ].join
33
+ end
34
+
35
+ def publisher_portion(id, context)
36
+ [
37
+ id.publisher.render(context:),
38
+ (id.typed_stage.abbreviation.empty? ? "" : "/#{id.typed_stage.abbreviation}"),
39
+ ].join
40
+ end
41
+
42
+ def number_portion(id, opts, context)
43
+ lang_single = opts[:lang_single] || false
44
+
45
+ [
46
+ (id.number ? " #{id.number.render(context:)}" : ""),
47
+ (id.part ? "-#{id.part.render(context:)}" : ""),
48
+ (id.subpart ? "-#{id.subpart.render(context:)}" : ""),
49
+ (id.stage_iteration ? ".#{id.stage_iteration.render(context:)}" : ""),
50
+ (id.date ? ":#{id.date.render(context:)}" : ""),
51
+ language_portion(id, lang_single: lang_single),
52
+ ].join
53
+ end
54
+
55
+ def language_portion(id, lang_single: false)
56
+ return "" unless id.languages&.any?
57
+
58
+ [
59
+ "(",
60
+ id.languages.map do |lang|
61
+ lang.to_s(lang_single: lang_single)
62
+ end.join(lang_single ? "/" : ","),
63
+ ")",
64
+ ].join
65
+ end
66
+
67
+ def render_supplement(id, opts, context)
68
+ lang = opts[:lang] || :en
69
+ lang_single = opts[:lang_single] || false
70
+ with_edition = opts[:with_edition] || false
71
+
72
+ [
73
+ id.base_identifier.to_s(lang: lang, lang_single: lang_single,
74
+ with_edition: with_edition),
75
+ "/",
76
+ id.typed_stage.abbreviation,
77
+ " ",
78
+ id.number.render(context:),
79
+ (id.date ? ":#{id.date.render(context:)}" : ""),
80
+ ].join
81
+ end
82
+ end
83
+ end
84
+ end
@@ -27,16 +27,8 @@ module Pubid
27
27
  # @param lang_single [Boolean] Use single-char language codes (default: false)
28
28
  # @param with_edition [Boolean] Include edition (default: false)
29
29
  # @return [String] String representation of supplement
30
- def to_s(lang: :en, lang_single: false, with_edition: false)
31
- [
32
- base_identifier.to_s(lang: lang, lang_single: lang_single,
33
- with_edition: with_edition),
34
- "/",
35
- typed_stage.abbreviation,
36
- " ",
37
- number.value,
38
- (date ? ":#{date.year}" : ""),
39
- ].join
30
+ def to_s(**opts)
31
+ render(format: :human, **opts)
40
32
  end
41
33
  end
42
34
  end
@@ -9,41 +9,6 @@ module Pubid
9
9
  identifier.type.abbr.to_s.downcase
10
10
  end
11
11
 
12
- def urn_number
13
- return nil unless identifier.number
14
-
15
- identifier.number.value.to_s
16
- end
17
-
18
- def urn_part
19
- return nil unless identifier.part
20
-
21
- "-#{identifier.part.value}"
22
- end
23
-
24
- def urn_subpart
25
- return nil unless identifier.subpart
26
-
27
- "-#{identifier.subpart.value}"
28
- end
29
-
30
- def urn_year
31
- if identifier.date&.year
32
- return identifier.date.year.to_s
33
- end
34
-
35
- identifier.year&.to_s
36
- end
37
-
38
- def urn_edition
39
- return nil unless identifier.edition
40
-
41
- num = identifier.edition.number
42
- return nil unless num
43
-
44
- "ed.#{num}"
45
- end
46
-
47
12
  def generate
48
13
  parts = ["urn", "idf"]
49
14
  parts << urn_number if urn_number
@@ -54,12 +19,12 @@ module Pubid
54
19
  parts << urn_type if urn_type
55
20
 
56
21
  if identifier.publisher
57
- parts[1] = identifier.publisher.body.to_s.downcase
22
+ parts[1] = identifier.publisher.render(context: URN_CONTEXT)
58
23
  end
59
24
 
60
25
  if identifier.copublishers&.any?
61
- copubs = identifier.copublishers.map(&:body)
62
- parts[1] = "#{parts[1]}-#{copubs.join('-').downcase}"
26
+ copubs = identifier.copublishers.map { |cp| cp.render(context: URN_CONTEXT) }
27
+ parts[1] = "#{parts[1]}-#{copubs.join('-')}"
63
28
  end
64
29
 
65
30
  if identifier.languages&.any?
@@ -73,7 +38,7 @@ module Pubid
73
38
  end
74
39
 
75
40
  if identifier.number
76
- parts << identifier.number.value.to_s
41
+ parts << identifier.number.render(context: URN_CONTEXT)
77
42
  end
78
43
  end
79
44
 
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Idf
5
+ # Parses IDF URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits: `urn:idf:{number}:{year}:` with a trailing empty
8
+ # field (a known quirk of the generator).
9
+ #
10
+ # Examples:
11
+ # - urn:idf:87:2019: → IDF 87:2019
12
+ # - urn:idf:100: → IDF 100
13
+ class UrnParser < Pubid::UrnParser::Base
14
+ def parse_urn(urn)
15
+ body = strip_namespace(urn)
16
+ parts = split_parts(body).reject(&:empty?)
17
+
18
+ number, year = parts
19
+ text = "IDF #{number}"
20
+ text += ":#{year}" if year
21
+ flavor_parse(text)
22
+ end
23
+ end
24
+ end
25
+ end
data/lib/pubid/idf.rb CHANGED
@@ -6,18 +6,72 @@ module Pubid
6
6
  autoload :Identifier, "#{__dir__}/idf/identifier"
7
7
  autoload :Identifiers, "#{__dir__}/idf/identifiers"
8
8
  autoload :Parser, "#{__dir__}/idf/parser"
9
- autoload :Scheme, "#{__dir__}/idf/scheme"
9
+ autoload :Renderer, "#{__dir__}/idf/renderer"
10
10
  autoload :SingleIdentifier, "#{__dir__}/idf/single_identifier"
11
11
  autoload :SupplementIdentifier, "#{__dir__}/idf/supplement_identifier"
12
12
  autoload :UrnGenerator, "#{__dir__}/idf/urn_generator"
13
+ autoload :UrnParser, "#{__dir__}/idf/urn_parser"
13
14
 
14
15
  def self.parse(identifier)
16
+ if identifier.length > Pubid::MAX_INPUT_LENGTH
17
+ raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
18
+ end
19
+
15
20
  parser = Parser.new
16
21
  builder = Builder.new
17
22
 
18
23
  parsed = parser.parse(identifier)
19
24
  builder.build(parsed)
20
25
  end
26
+
27
+ # Build an IDF identifier from a parse-tree hash (used by ISO joint-identifier
28
+ # parsing). This is the public seam: callers should never reach into
29
+ # `Idf::Builder` directly.
30
+ # @param hash [Hash] parse tree for the joint identifier
31
+ # @return [Pubid::Idf::Identifier]
32
+ def self.build_from_parse(hash)
33
+ Builder.new.build(hash)
34
+ end
35
+
36
+ # Per-flavor format registry: inherits global formats, overrides :human
37
+ Identifier.format_registry = FormatRegistry.new(parent: Identifier.format_registry)
38
+ Identifier.format_registry.register(:human, renderer: Idf::Renderer)
39
+
40
+ # Auto-discover all identifier types from the Identifiers namespace
41
+ # @return [Array<Class>] identifier classes that define a self.type Hash
42
+ def self.identifier_types
43
+ @identifier_types ||= Identifiers.constants
44
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
45
+ .select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
46
+ .select { |c| c.type.is_a?(Hash) }
47
+ end
48
+
49
+ # Build typed stage index from identifier types
50
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
51
+ def self.all_typed_stages
52
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
53
+ if klass.const_defined?(:TYPED_STAGES)
54
+ klass.const_get(:TYPED_STAGES)
55
+ else
56
+ []
57
+ end
58
+ end
59
+ end
60
+
61
+ # Lookup: type code -> identifier class
62
+ # @param code [String, Symbol] the type key to find
63
+ # @return [Class, nil] the matching identifier class
64
+ def self.locate_type(code)
65
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
66
+ end
67
+
68
+ # Lookup: abbreviation -> typed stage
69
+ # @param abbr [String, Symbol] the abbreviation to find
70
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
71
+ def self.locate_stage(abbr)
72
+ abbr_str = abbr.to_s.upcase
73
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
74
+ end
21
75
  end
22
76
  end
23
77