pubid 1.15.19 → 2.0.0.pre.alpha.2

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 (604) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.adoc +2041 -53
  4. data/archived-gems/pubid-ccsds/update_codes.yaml +1 -0
  5. data/archived-gems/pubid-iec/stages.yaml +129 -0
  6. data/archived-gems/pubid-iec/update_codes.yaml +67 -0
  7. data/archived-gems/pubid-ieee/update_codes.yaml +104 -0
  8. data/archived-gems/pubid-iso/stages.yaml +106 -0
  9. data/archived-gems/pubid-iso/update_codes.yaml +4 -0
  10. data/archived-gems/pubid-itu/i18n.yaml +13 -0
  11. data/archived-gems/pubid-itu/series.yaml +42 -0
  12. data/archived-gems/pubid-nist/publishers.yaml +6 -0
  13. data/archived-gems/pubid-nist/series.yaml +121 -0
  14. data/archived-gems/pubid-nist/stages.yaml +16 -0
  15. data/archived-gems/pubid-nist/update_codes.yaml +93 -0
  16. data/archived-gems/pubid-plateau/update_codes.yaml +6 -0
  17. data/data/ccsds/update_codes.yaml +1 -0
  18. data/data/iec/update_codes.yaml +67 -0
  19. data/data/ieee/update_codes.yaml +104 -0
  20. data/data/iso/update_codes.yaml +21 -0
  21. data/data/nist/update_codes.yaml +89 -0
  22. data/data/plateau/update_codes.yaml +6 -0
  23. data/lib/pubid/amca/builder.rb +176 -0
  24. data/lib/pubid/amca/identifier.rb +57 -0
  25. data/lib/pubid/amca/identifiers/base.rb +64 -0
  26. data/lib/pubid/amca/identifiers/interpretation.rb +51 -0
  27. data/lib/pubid/amca/identifiers/publication.rb +47 -0
  28. data/lib/pubid/amca/identifiers/standard.rb +22 -0
  29. data/lib/pubid/amca/identifiers.rb +12 -0
  30. data/lib/pubid/amca/parser.rb +153 -0
  31. data/lib/pubid/amca/scheme.rb +16 -0
  32. data/lib/pubid/amca/single_identifier.rb +33 -0
  33. data/lib/pubid/amca/urn_generator.rb +50 -0
  34. data/lib/pubid/amca.rb +26 -0
  35. data/lib/pubid/ansi/builder.rb +52 -0
  36. data/lib/pubid/ansi/identifier.rb +55 -0
  37. data/lib/pubid/ansi/identifiers/american_national_standard.rb +12 -0
  38. data/lib/pubid/ansi/identifiers/standard.rb +16 -0
  39. data/lib/pubid/ansi/identifiers.rb +11 -0
  40. data/lib/pubid/ansi/parser.rb +91 -0
  41. data/lib/pubid/ansi/scheme.rb +15 -0
  42. data/lib/pubid/ansi/single_identifier.rb +45 -0
  43. data/lib/pubid/ansi/urn_generator.rb +76 -0
  44. data/lib/pubid/ansi.rb +27 -0
  45. data/lib/pubid/api/builder.rb +85 -0
  46. data/lib/pubid/api/components/code.rb +9 -0
  47. data/lib/pubid/api/identifier.rb +68 -0
  48. data/lib/pubid/api/identifiers/base.rb +24 -0
  49. data/lib/pubid/api/identifiers/bulletin.rb +15 -0
  50. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +15 -0
  51. data/lib/pubid/api/identifiers/mpms.rb +44 -0
  52. data/lib/pubid/api/identifiers/publication.rb +15 -0
  53. data/lib/pubid/api/identifiers/recommended_practice.rb +15 -0
  54. data/lib/pubid/api/identifiers/specification.rb +15 -0
  55. data/lib/pubid/api/identifiers/standard.rb +15 -0
  56. data/lib/pubid/api/identifiers/technical_report.rb +15 -0
  57. data/lib/pubid/api/identifiers/typeless_standard.rb +27 -0
  58. data/lib/pubid/api/parser.rb +140 -0
  59. data/lib/pubid/api/scheme.rb +66 -0
  60. data/lib/pubid/api/single_identifier.rb +46 -0
  61. data/lib/pubid/api/urn_generator.rb +41 -0
  62. data/lib/pubid/api.rb +17 -0
  63. data/lib/pubid/ashrae/builder.rb +498 -0
  64. data/lib/pubid/ashrae/identifier.rb +57 -0
  65. data/lib/pubid/ashrae/identifiers/addenda_package.rb +46 -0
  66. data/lib/pubid/ashrae/identifiers/addendum.rb +55 -0
  67. data/lib/pubid/ashrae/identifiers/base.rb +23 -0
  68. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +51 -0
  69. data/lib/pubid/ashrae/identifiers/errata.rb +40 -0
  70. data/lib/pubid/ashrae/identifiers/guideline.rb +38 -0
  71. data/lib/pubid/ashrae/identifiers/interpretation.rb +39 -0
  72. data/lib/pubid/ashrae/identifiers/standard.rb +38 -0
  73. data/lib/pubid/ashrae/identifiers.rb +16 -0
  74. data/lib/pubid/ashrae/parser.rb +724 -0
  75. data/lib/pubid/ashrae/scheme.rb +53 -0
  76. data/lib/pubid/ashrae/single_identifier.rb +23 -0
  77. data/lib/pubid/ashrae/supplement_identifier.rb +23 -0
  78. data/lib/pubid/ashrae/urn_generator.rb +59 -0
  79. data/lib/pubid/ashrae.rb +21 -0
  80. data/lib/pubid/asme/builder.rb +153 -0
  81. data/lib/pubid/asme/components/code.rb +18 -0
  82. data/lib/pubid/asme/identifier.rb +61 -0
  83. data/lib/pubid/asme/identifiers/base.rb +70 -0
  84. data/lib/pubid/asme/identifiers/standard.rb +12 -0
  85. data/lib/pubid/asme/identifiers.rb +10 -0
  86. data/lib/pubid/asme/parser.rb +308 -0
  87. data/lib/pubid/asme/scheme.rb +37 -0
  88. data/lib/pubid/asme/single_identifier.rb +29 -0
  89. data/lib/pubid/asme/urn_generator.rb +133 -0
  90. data/lib/pubid/asme.rb +21 -0
  91. data/lib/pubid/astm/builder.rb +159 -0
  92. data/lib/pubid/astm/components/code.rb +33 -0
  93. data/lib/pubid/astm/identifier.rb +92 -0
  94. data/lib/pubid/astm/identifiers/adjunct.rb +21 -0
  95. data/lib/pubid/astm/identifiers/base.rb +13 -0
  96. data/lib/pubid/astm/identifiers/data_series.rb +25 -0
  97. data/lib/pubid/astm/identifiers/iso_dual_published.rb +74 -0
  98. data/lib/pubid/astm/identifiers/manual.rb +40 -0
  99. data/lib/pubid/astm/identifiers/monograph.rb +25 -0
  100. data/lib/pubid/astm/identifiers/research_report.rb +18 -0
  101. data/lib/pubid/astm/identifiers/standard.rb +52 -0
  102. data/lib/pubid/astm/identifiers/technical_report.rb +23 -0
  103. data/lib/pubid/astm/identifiers/work_in_progress.rb +21 -0
  104. data/lib/pubid/astm/parser.rb +244 -0
  105. data/lib/pubid/astm/scheme.rb +55 -0
  106. data/lib/pubid/astm/single_identifier.rb +25 -0
  107. data/lib/pubid/astm/urn_generator.rb +99 -0
  108. data/lib/pubid/astm.rb +38 -0
  109. data/lib/pubid/bsi/builder.rb +1483 -0
  110. data/lib/pubid/bsi/components/code.rb +11 -0
  111. data/lib/pubid/bsi/components/date.rb +11 -0
  112. data/lib/pubid/bsi/components/publisher.rb +11 -0
  113. data/lib/pubid/bsi/components/type.rb +11 -0
  114. data/lib/pubid/bsi/identifier.rb +87 -0
  115. data/lib/pubid/bsi/identifiers/addendum_document.rb +64 -0
  116. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +95 -0
  117. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +82 -0
  118. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +118 -0
  119. data/lib/pubid/bsi/identifiers/amendment.rb +40 -0
  120. data/lib/pubid/bsi/identifiers/base.rb +11 -0
  121. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +27 -0
  122. data/lib/pubid/bsi/identifiers/british_standard.rb +33 -0
  123. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +114 -0
  124. data/lib/pubid/bsi/identifiers/committee_document.rb +51 -0
  125. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +152 -0
  126. data/lib/pubid/bsi/identifiers/corrigendum.rb +28 -0
  127. data/lib/pubid/bsi/identifiers/detailed_specification.rb +69 -0
  128. data/lib/pubid/bsi/identifiers/disc.rb +56 -0
  129. data/lib/pubid/bsi/identifiers/draft_document.rb +71 -0
  130. data/lib/pubid/bsi/identifiers/electronic_book.rb +52 -0
  131. data/lib/pubid/bsi/identifiers/expert_commentary.rb +47 -0
  132. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +82 -0
  133. data/lib/pubid/bsi/identifiers/flex.rb +61 -0
  134. data/lib/pubid/bsi/identifiers/handbook.rb +39 -0
  135. data/lib/pubid/bsi/identifiers/index.rb +62 -0
  136. data/lib/pubid/bsi/identifiers/method.rb +76 -0
  137. data/lib/pubid/bsi/identifiers/national_annex.rb +73 -0
  138. data/lib/pubid/bsi/identifiers/practice_guide.rb +27 -0
  139. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +79 -0
  140. data/lib/pubid/bsi/identifiers/published_document.rb +79 -0
  141. data/lib/pubid/bsi/identifiers/section.rb +62 -0
  142. data/lib/pubid/bsi/identifiers/set.rb +46 -0
  143. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +40 -0
  144. data/lib/pubid/bsi/identifiers/supplement_document.rb +51 -0
  145. data/lib/pubid/bsi/identifiers/supplementary_index.rb +81 -0
  146. data/lib/pubid/bsi/identifiers/technical_specification.rb +79 -0
  147. data/lib/pubid/bsi/identifiers/test_method.rb +67 -0
  148. data/lib/pubid/bsi/identifiers/value_added_publication.rb +52 -0
  149. data/lib/pubid/bsi/identifiers.rb +52 -0
  150. data/lib/pubid/bsi/model.rb +196 -0
  151. data/lib/pubid/bsi/parser.rb +659 -0
  152. data/lib/pubid/bsi/scheme.rb +243 -0
  153. data/lib/pubid/bsi/single_identifier.rb +129 -0
  154. data/lib/pubid/bsi/urn_generator.rb +84 -0
  155. data/lib/pubid/bsi.rb +32 -0
  156. data/lib/pubid/builder/base.rb +138 -0
  157. data/lib/pubid/bundled_identifier.rb +126 -0
  158. data/lib/pubid/ccsds/builder.rb +56 -0
  159. data/lib/pubid/ccsds/identifier.rb +84 -0
  160. data/lib/pubid/ccsds/identifiers/base.rb +89 -0
  161. data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +70 -0
  162. data/lib/pubid/ccsds/identifiers/corrigendum.rb +39 -0
  163. data/lib/pubid/ccsds/identifiers.rb +10 -0
  164. data/lib/pubid/ccsds/parser.rb +71 -0
  165. data/lib/pubid/ccsds/scheme.rb +57 -0
  166. data/lib/pubid/ccsds/single_identifier.rb +77 -0
  167. data/lib/pubid/ccsds/supplement_identifier.rb +33 -0
  168. data/lib/pubid/ccsds/urn_generator.rb +115 -0
  169. data/lib/pubid/ccsds.rb +21 -0
  170. data/lib/pubid/cen_cenelec/builder.rb +330 -0
  171. data/lib/pubid/cen_cenelec/identifier.rb +52 -0
  172. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +40 -0
  173. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +29 -0
  174. data/lib/pubid/cen_cenelec/identifiers/base.rb +75 -0
  175. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +28 -0
  176. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +27 -0
  177. data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +28 -0
  178. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +61 -0
  179. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +35 -0
  180. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +41 -0
  181. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +37 -0
  182. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +28 -0
  183. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +22 -0
  184. data/lib/pubid/cen_cenelec/identifiers/guide.rb +27 -0
  185. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +27 -0
  186. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +27 -0
  187. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +35 -0
  188. data/lib/pubid/cen_cenelec/identifiers.rb +32 -0
  189. data/lib/pubid/cen_cenelec/parser.rb +144 -0
  190. data/lib/pubid/cen_cenelec/scheme.rb +164 -0
  191. data/lib/pubid/cen_cenelec/single_identifier.rb +130 -0
  192. data/lib/pubid/cen_cenelec/supplement_identifier.rb +48 -0
  193. data/lib/pubid/cen_cenelec/urn_generator.rb +129 -0
  194. data/lib/pubid/cen_cenelec.rb +21 -0
  195. data/lib/pubid/cie/builder.rb +399 -0
  196. data/lib/pubid/cie/components/code.rb +72 -0
  197. data/lib/pubid/cie/components/language.rb +58 -0
  198. data/lib/pubid/cie/identifier.rb +71 -0
  199. data/lib/pubid/cie/identifiers/bundle.rb +20 -0
  200. data/lib/pubid/cie/identifiers/conference.rb +32 -0
  201. data/lib/pubid/cie/identifiers/corrigendum.rb +40 -0
  202. data/lib/pubid/cie/identifiers/dual_published.rb +41 -0
  203. data/lib/pubid/cie/identifiers/identical.rb +64 -0
  204. data/lib/pubid/cie/identifiers/joint_published.rb +52 -0
  205. data/lib/pubid/cie/identifiers/standard.rb +58 -0
  206. data/lib/pubid/cie/identifiers/supplement.rb +45 -0
  207. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +20 -0
  208. data/lib/pubid/cie/identifiers.rb +17 -0
  209. data/lib/pubid/cie/parser.rb +347 -0
  210. data/lib/pubid/cie/scheme.rb +64 -0
  211. data/lib/pubid/cie/single_identifier.rb +30 -0
  212. data/lib/pubid/cie/supplement_identifier.rb +26 -0
  213. data/lib/pubid/cie/urn_generator.rb +123 -0
  214. data/lib/pubid/cie.rb +28 -0
  215. data/lib/pubid/components/code.rb +33 -0
  216. data/lib/pubid/components/date.rb +49 -0
  217. data/lib/pubid/components/edition.rb +32 -0
  218. data/lib/pubid/components/factory.rb +50 -0
  219. data/lib/pubid/components/language.rb +37 -0
  220. data/lib/pubid/components/locality.rb +10 -0
  221. data/lib/pubid/components/publisher.rb +36 -0
  222. data/lib/pubid/components/stage.rb +54 -0
  223. data/lib/pubid/components/type.rb +58 -0
  224. data/lib/pubid/components/typed_stage.rb +59 -0
  225. data/lib/pubid/components.rb +16 -0
  226. data/lib/pubid/core/pattern_doc_generator.rb +272 -0
  227. data/lib/pubid/core/update_codes.rb +77 -0
  228. data/lib/pubid/core.rb +8 -0
  229. data/lib/pubid/csa/builder.rb +671 -0
  230. data/lib/pubid/csa/components/code.rb +9 -0
  231. data/lib/pubid/csa/components.rb +9 -0
  232. data/lib/pubid/csa/composite_identifier.rb +27 -0
  233. data/lib/pubid/csa/identifier.rb +513 -0
  234. data/lib/pubid/csa/identifiers/base.rb +133 -0
  235. data/lib/pubid/csa/identifiers/bundled.rb +125 -0
  236. data/lib/pubid/csa/identifiers/canadian_adopted.rb +82 -0
  237. data/lib/pubid/csa/identifiers/cec.rb +129 -0
  238. data/lib/pubid/csa/identifiers/combined.rb +130 -0
  239. data/lib/pubid/csa/identifiers/csa_adopted.rb +78 -0
  240. data/lib/pubid/csa/identifiers/package.rb +65 -0
  241. data/lib/pubid/csa/identifiers/series.rb +127 -0
  242. data/lib/pubid/csa/identifiers/standard.rb +10 -0
  243. data/lib/pubid/csa/identifiers.rb +17 -0
  244. data/lib/pubid/csa/parser.rb +445 -0
  245. data/lib/pubid/csa/scheme.rb +44 -0
  246. data/lib/pubid/csa/single_identifier.rb +30 -0
  247. data/lib/pubid/csa/urn_generator.rb +80 -0
  248. data/lib/pubid/csa/wrapper_identifier.rb +31 -0
  249. data/lib/pubid/csa.rb +25 -0
  250. data/lib/pubid/etsi/builder.rb +133 -0
  251. data/lib/pubid/etsi/components/code.rb +42 -0
  252. data/lib/pubid/etsi/components/version.rb +37 -0
  253. data/lib/pubid/etsi/components.rb +10 -0
  254. data/lib/pubid/etsi/identifier.rb +57 -0
  255. data/lib/pubid/etsi/identifiers/amendment.rb +15 -0
  256. data/lib/pubid/etsi/identifiers/base.rb +38 -0
  257. data/lib/pubid/etsi/identifiers/corrigendum.rb +15 -0
  258. data/lib/pubid/etsi/identifiers/etsi_standard.rb +19 -0
  259. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +91 -0
  260. data/lib/pubid/etsi/identifiers.rb +14 -0
  261. data/lib/pubid/etsi/parser.rb +133 -0
  262. data/lib/pubid/etsi/scheme.rb +42 -0
  263. data/lib/pubid/etsi/urn_generator.rb +76 -0
  264. data/lib/pubid/etsi.rb +21 -0
  265. data/lib/pubid/export/auditor.rb +89 -0
  266. data/lib/pubid/export/data_class_exporter.rb +59 -0
  267. data/lib/pubid/export/exporter.rb +74 -0
  268. data/lib/pubid/export/flavor_exporter.rb +402 -0
  269. data/lib/pubid/export/ieee_exporter.rb +78 -0
  270. data/lib/pubid/export/itu_exporter.rb +66 -0
  271. data/lib/pubid/export/nist_exporter.rb +64 -0
  272. data/lib/pubid/export/registry_exporter.rb +90 -0
  273. data/lib/pubid/export/result.rb +97 -0
  274. data/lib/pubid/export/scheme_exporter.rb +70 -0
  275. data/lib/pubid/export.rb +18 -0
  276. data/lib/pubid/format_detector.rb +16 -0
  277. data/lib/pubid/format_registry.rb +42 -0
  278. data/lib/pubid/identifier.rb +242 -0
  279. data/lib/pubid/identifier_metadata.rb +148 -0
  280. data/lib/pubid/identifier_registry.rb +198 -0
  281. data/lib/pubid/idf/builder.rb +82 -0
  282. data/lib/pubid/idf/identifier.rb +129 -0
  283. data/lib/pubid/idf/identifiers/amendment.rb +27 -0
  284. data/lib/pubid/idf/identifiers/corrigendum.rb +27 -0
  285. data/lib/pubid/idf/identifiers/international_standard.rb +123 -0
  286. data/lib/pubid/idf/identifiers/reviewed_method.rb +100 -0
  287. data/lib/pubid/idf/identifiers.rb +13 -0
  288. data/lib/pubid/idf/parser.rb +143 -0
  289. data/lib/pubid/idf/scheme.rb +61 -0
  290. data/lib/pubid/idf/single_identifier.rb +19 -0
  291. data/lib/pubid/idf/supplement_identifier.rb +43 -0
  292. data/lib/pubid/idf/urn_generator.rb +84 -0
  293. data/lib/pubid/idf.rb +25 -0
  294. data/lib/pubid/iec/builder.rb +458 -0
  295. data/lib/pubid/iec/components/code.rb +60 -0
  296. data/lib/pubid/iec/components/consolidated_amendment.rb +59 -0
  297. data/lib/pubid/iec/components/publisher.rb +36 -0
  298. data/lib/pubid/iec/components/sheet.rb +32 -0
  299. data/lib/pubid/iec/components/trf_info.rb +38 -0
  300. data/lib/pubid/iec/components/vap_suffix.rb +41 -0
  301. data/lib/pubid/iec/identifier.rb +256 -0
  302. data/lib/pubid/iec/identifiers/amendment.rb +94 -0
  303. data/lib/pubid/iec/identifiers/base.rb +82 -0
  304. data/lib/pubid/iec/identifiers/component_specification.rb +39 -0
  305. data/lib/pubid/iec/identifiers/conformity_assessment.rb +39 -0
  306. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +82 -0
  307. data/lib/pubid/iec/identifiers/corrigendum.rb +94 -0
  308. data/lib/pubid/iec/identifiers/fragment_identifier.rb +137 -0
  309. data/lib/pubid/iec/identifiers/guide.rb +104 -0
  310. data/lib/pubid/iec/identifiers/international_standard.rb +147 -0
  311. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +104 -0
  312. data/lib/pubid/iec/identifiers/operational_document.rb +39 -0
  313. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +101 -0
  314. data/lib/pubid/iec/identifiers/sheet_identifier.rb +62 -0
  315. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +40 -0
  316. data/lib/pubid/iec/identifiers/systems_reference_document.rb +40 -0
  317. data/lib/pubid/iec/identifiers/technical_report.rb +132 -0
  318. data/lib/pubid/iec/identifiers/technical_specification.rb +132 -0
  319. data/lib/pubid/iec/identifiers/technology_report.rb +39 -0
  320. data/lib/pubid/iec/identifiers/test_report_form.rb +78 -0
  321. data/lib/pubid/iec/identifiers/vap_identifier.rb +73 -0
  322. data/lib/pubid/iec/identifiers/white_paper.rb +39 -0
  323. data/lib/pubid/iec/identifiers/working_document.rb +96 -0
  324. data/lib/pubid/iec/parser.rb +417 -0
  325. data/lib/pubid/iec/rendering_style.rb +113 -0
  326. data/lib/pubid/iec/scheme.rb +71 -0
  327. data/lib/pubid/iec/single_identifier.rb +80 -0
  328. data/lib/pubid/iec/supplement_identifier.rb +161 -0
  329. data/lib/pubid/iec/urn_generator.rb +79 -0
  330. data/lib/pubid/iec/urn_parser.rb +90 -0
  331. data/lib/pubid/iec.rb +85 -0
  332. data/lib/pubid/ieee/aiee/builder.rb +71 -0
  333. data/lib/pubid/ieee/aiee/identifier.rb +105 -0
  334. data/lib/pubid/ieee/aiee/parser.rb +130 -0
  335. data/lib/pubid/ieee/aiee.rb +11 -0
  336. data/lib/pubid/ieee/builder.rb +1237 -0
  337. data/lib/pubid/ieee/components/code.rb +102 -0
  338. data/lib/pubid/ieee/components/draft.rb +93 -0
  339. data/lib/pubid/ieee/components/relationship.rb +157 -0
  340. data/lib/pubid/ieee/components/typed_stage.rb +100 -0
  341. data/lib/pubid/ieee/identifier.rb +54 -0
  342. data/lib/pubid/ieee/identifiers/adopted_standard.rb +33 -0
  343. data/lib/pubid/ieee/identifiers/base.rb +591 -0
  344. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +35 -0
  345. data/lib/pubid/ieee/identifiers/corrigendum.rb +37 -0
  346. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +51 -0
  347. data/lib/pubid/ieee/identifiers/dual_identifier.rb +18 -0
  348. data/lib/pubid/ieee/identifiers/dual_published.rb +28 -0
  349. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +27 -0
  350. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +34 -0
  351. data/lib/pubid/ieee/identifiers/joint_development.rb +172 -0
  352. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +51 -0
  353. data/lib/pubid/ieee/identifiers/nesc/base.rb +56 -0
  354. data/lib/pubid/ieee/identifiers/nesc/draft.rb +28 -0
  355. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +32 -0
  356. data/lib/pubid/ieee/identifiers/nesc/redline.rb +26 -0
  357. data/lib/pubid/ieee/identifiers/nesc/standard.rb +26 -0
  358. data/lib/pubid/ieee/identifiers/nesc.rb +15 -0
  359. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +20 -0
  360. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +26 -0
  361. data/lib/pubid/ieee/identifiers/redlined_standard.rb +33 -0
  362. data/lib/pubid/ieee/identifiers/si_standard.rb +73 -0
  363. data/lib/pubid/ieee/identifiers/standard.rb +41 -0
  364. data/lib/pubid/ieee/identifiers/supplement_identifier.rb +23 -0
  365. data/lib/pubid/ieee/identifiers.rb +33 -0
  366. data/lib/pubid/ieee/ire/builder.rb +61 -0
  367. data/lib/pubid/ieee/ire/identifier.rb +58 -0
  368. data/lib/pubid/ieee/ire/parser.rb +91 -0
  369. data/lib/pubid/ieee/ire.rb +11 -0
  370. data/lib/pubid/ieee/nesc/builder.rb +101 -0
  371. data/lib/pubid/ieee/nesc/parser.rb +154 -0
  372. data/lib/pubid/ieee/nesc.rb +10 -0
  373. data/lib/pubid/ieee/parser.rb +1226 -0
  374. data/lib/pubid/ieee/scheme.rb +90 -0
  375. data/lib/pubid/ieee/typed_stages.rb +172 -0
  376. data/lib/pubid/ieee/urn_generator.rb +188 -0
  377. data/lib/pubid/ieee.rb +32 -0
  378. data/lib/pubid/ieee_debug.rb +31 -0
  379. data/lib/pubid/iho/builder.rb +37 -0
  380. data/lib/pubid/iho/identifier.rb +61 -0
  381. data/lib/pubid/iho/identifiers/base.rb +41 -0
  382. data/lib/pubid/iho/identifiers/bibliographic.rb +16 -0
  383. data/lib/pubid/iho/identifiers/circular_letter.rb +15 -0
  384. data/lib/pubid/iho/identifiers/miscellaneous.rb +16 -0
  385. data/lib/pubid/iho/identifiers/publication.rb +15 -0
  386. data/lib/pubid/iho/identifiers/standard.rb +15 -0
  387. data/lib/pubid/iho/identifiers.rb +14 -0
  388. data/lib/pubid/iho/parser.rb +68 -0
  389. data/lib/pubid/iho/scheme.rb +29 -0
  390. data/lib/pubid/iho/urn_generator.rb +29 -0
  391. data/lib/pubid/iho.rb +21 -0
  392. data/lib/pubid/iso/builder.rb +309 -0
  393. data/lib/pubid/iso/bundled_identifier.rb +85 -0
  394. data/lib/pubid/iso/combined_identifier.rb +22 -0
  395. data/lib/pubid/iso/components/code.rb +36 -0
  396. data/lib/pubid/iso/components/publisher.rb +60 -0
  397. data/lib/pubid/iso/components.rb +12 -0
  398. data/lib/pubid/iso/format_resolver.rb +45 -0
  399. data/lib/pubid/iso/identifier.rb +330 -0
  400. data/lib/pubid/iso/identifiers/addendum.rb +104 -0
  401. data/lib/pubid/iso/identifiers/amendment.rb +128 -0
  402. data/lib/pubid/iso/identifiers/base.rb +115 -0
  403. data/lib/pubid/iso/identifiers/corrigendum.rb +108 -0
  404. data/lib/pubid/iso/identifiers/data.rb +76 -0
  405. data/lib/pubid/iso/identifiers/directives.rb +59 -0
  406. data/lib/pubid/iso/identifiers/directives_supplement.rb +119 -0
  407. data/lib/pubid/iso/identifiers/extract.rb +30 -0
  408. data/lib/pubid/iso/identifiers/guide.rb +100 -0
  409. data/lib/pubid/iso/identifiers/international_standard.rb +168 -0
  410. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +94 -0
  411. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +89 -0
  412. data/lib/pubid/iso/identifiers/pas.rb +93 -0
  413. data/lib/pubid/iso/identifiers/recommendation.rb +45 -0
  414. data/lib/pubid/iso/identifiers/supplement.rb +87 -0
  415. data/lib/pubid/iso/identifiers/tc_document.rb +108 -0
  416. data/lib/pubid/iso/identifiers/technical_report.rb +103 -0
  417. data/lib/pubid/iso/identifiers/technical_specification.rb +102 -0
  418. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +95 -0
  419. data/lib/pubid/iso/identifiers.rb +33 -0
  420. data/lib/pubid/iso/parser.rb +512 -0
  421. data/lib/pubid/iso/rendering_style.rb +120 -0
  422. data/lib/pubid/iso/scheme.rb +193 -0
  423. data/lib/pubid/iso/single_identifier.rb +64 -0
  424. data/lib/pubid/iso/supplement_identifier.rb +27 -0
  425. data/lib/pubid/iso/urn_generator.rb +426 -0
  426. data/lib/pubid/iso/urn_parser.rb +437 -0
  427. data/lib/pubid/iso/utilities.rb +86 -0
  428. data/lib/pubid/iso.rb +50 -0
  429. data/lib/pubid/itu/builder.rb +171 -0
  430. data/lib/pubid/itu/components/code.rb +39 -0
  431. data/lib/pubid/itu/components/sector.rb +35 -0
  432. data/lib/pubid/itu/components/series.rb +29 -0
  433. data/lib/pubid/itu/i18n.rb +9 -0
  434. data/lib/pubid/itu/i18n.yaml +30 -0
  435. data/lib/pubid/itu/identifier.rb +118 -0
  436. data/lib/pubid/itu/identifiers/amendment.rb +43 -0
  437. data/lib/pubid/itu/identifiers/annex.rb +74 -0
  438. data/lib/pubid/itu/identifiers/base.rb +154 -0
  439. data/lib/pubid/itu/identifiers/combined_identifier.rb +47 -0
  440. data/lib/pubid/itu/identifiers/corrigendum.rb +44 -0
  441. data/lib/pubid/itu/identifiers/recommendation.rb +16 -0
  442. data/lib/pubid/itu/identifiers/special_publication.rb +31 -0
  443. data/lib/pubid/itu/identifiers/supplement.rb +46 -0
  444. data/lib/pubid/itu/identifiers.rb +16 -0
  445. data/lib/pubid/itu/model.rb +111 -0
  446. data/lib/pubid/itu/parser.rb +225 -0
  447. data/lib/pubid/itu/scheme.rb +174 -0
  448. data/lib/pubid/itu/urn_generator.rb +105 -0
  449. data/lib/pubid/itu.rb +22 -0
  450. data/lib/pubid/jcgm/builder.rb +88 -0
  451. data/lib/pubid/jcgm/components/publisher.rb +20 -0
  452. data/lib/pubid/jcgm/components.rb +9 -0
  453. data/lib/pubid/jcgm/identifier.rb +54 -0
  454. data/lib/pubid/jcgm/identifiers/amendment.rb +35 -0
  455. data/lib/pubid/jcgm/identifiers/guide.rb +21 -0
  456. data/lib/pubid/jcgm/identifiers/gum_guide.rb +51 -0
  457. data/lib/pubid/jcgm/identifiers.rb +11 -0
  458. data/lib/pubid/jcgm/parser.rb +84 -0
  459. data/lib/pubid/jcgm/scheme.rb +60 -0
  460. data/lib/pubid/jcgm/single_identifier.rb +48 -0
  461. data/lib/pubid/jcgm/supplement_identifier.rb +16 -0
  462. data/lib/pubid/jcgm/urn_generator.rb +110 -0
  463. data/lib/pubid/jcgm.rb +31 -0
  464. data/lib/pubid/jis/builder.rb +124 -0
  465. data/lib/pubid/jis/components/code.rb +59 -0
  466. data/lib/pubid/jis/components.rb +9 -0
  467. data/lib/pubid/jis/identifier.rb +61 -0
  468. data/lib/pubid/jis/identifiers/amendment.rb +16 -0
  469. data/lib/pubid/jis/identifiers/base.rb +72 -0
  470. data/lib/pubid/jis/identifiers/explanation.rb +22 -0
  471. data/lib/pubid/jis/identifiers/japanese_industrial_standard.rb +16 -0
  472. data/lib/pubid/jis/identifiers/standard.rb +27 -0
  473. data/lib/pubid/jis/identifiers/technical_report.rb +31 -0
  474. data/lib/pubid/jis/identifiers/technical_specification.rb +31 -0
  475. data/lib/pubid/jis/identifiers.rb +17 -0
  476. data/lib/pubid/jis/parser.rb +109 -0
  477. data/lib/pubid/jis/scheme.rb +49 -0
  478. data/lib/pubid/jis/single_identifier.rb +37 -0
  479. data/lib/pubid/jis/supplement_identifier.rb +47 -0
  480. data/lib/pubid/jis/urn_generator.rb +25 -0
  481. data/lib/pubid/jis.rb +23 -0
  482. data/lib/pubid/lutaml/no_store_registration.rb +30 -0
  483. data/lib/pubid/nist/builder.rb +2269 -0
  484. data/lib/pubid/nist/components/code.rb +38 -0
  485. data/lib/pubid/nist/components/edition.rb +134 -0
  486. data/lib/pubid/nist/components/issue_number.rb +28 -0
  487. data/lib/pubid/nist/components/part.rb +77 -0
  488. data/lib/pubid/nist/components/publisher.rb +24 -0
  489. data/lib/pubid/nist/components/stage.rb +53 -0
  490. data/lib/pubid/nist/components/supplement.rb +188 -0
  491. data/lib/pubid/nist/components/translation.rb +42 -0
  492. data/lib/pubid/nist/components/update.rb +103 -0
  493. data/lib/pubid/nist/components/version.rb +35 -0
  494. data/lib/pubid/nist/components/volume.rb +32 -0
  495. data/lib/pubid/nist/components.rb +19 -0
  496. data/lib/pubid/nist/configuration.rb +77 -0
  497. data/lib/pubid/nist/identifier.rb +62 -0
  498. data/lib/pubid/nist/identifiers/base.rb +578 -0
  499. data/lib/pubid/nist/identifiers/circular.rb +68 -0
  500. data/lib/pubid/nist/identifiers/circular_supplement.rb +50 -0
  501. data/lib/pubid/nist/identifiers/commercial_standard.rb +41 -0
  502. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +56 -0
  503. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +56 -0
  504. data/lib/pubid/nist/identifiers/crpl_report.rb +132 -0
  505. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +104 -0
  506. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +35 -0
  507. data/lib/pubid/nist/identifiers/handbook.rb +50 -0
  508. data/lib/pubid/nist/identifiers/internal_report.rb +56 -0
  509. data/lib/pubid/nist/identifiers/letter_circular.rb +45 -0
  510. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +65 -0
  511. data/lib/pubid/nist/identifiers/monograph.rb +69 -0
  512. data/lib/pubid/nist/identifiers/ncstar.rb +41 -0
  513. data/lib/pubid/nist/identifiers/nsrds.rb +41 -0
  514. data/lib/pubid/nist/identifiers/owmwp.rb +35 -0
  515. data/lib/pubid/nist/identifiers/report.rb +67 -0
  516. data/lib/pubid/nist/identifiers/special_publication.rb +36 -0
  517. data/lib/pubid/nist/identifiers/technical_note.rb +90 -0
  518. data/lib/pubid/nist/identifiers.rb +33 -0
  519. data/lib/pubid/nist/parser.rb +1117 -0
  520. data/lib/pubid/nist/scheme.rb +199 -0
  521. data/lib/pubid/nist/supplement_identifier.rb +67 -0
  522. data/lib/pubid/nist/urn_generator.rb +133 -0
  523. data/lib/pubid/nist.rb +37 -0
  524. data/lib/pubid/oiml/builder.rb +189 -0
  525. data/lib/pubid/oiml/components/code.rb +20 -0
  526. data/lib/pubid/oiml/components.rb +9 -0
  527. data/lib/pubid/oiml/identifier.rb +61 -0
  528. data/lib/pubid/oiml/identifiers/amendment.rb +13 -0
  529. data/lib/pubid/oiml/identifiers/annex.rb +62 -0
  530. data/lib/pubid/oiml/identifiers/base.rb +36 -0
  531. data/lib/pubid/oiml/identifiers/basic_publication.rb +13 -0
  532. data/lib/pubid/oiml/identifiers/document.rb +13 -0
  533. data/lib/pubid/oiml/identifiers/expert_report.rb +13 -0
  534. data/lib/pubid/oiml/identifiers/guide.rb +13 -0
  535. data/lib/pubid/oiml/identifiers/recommendation.rb +13 -0
  536. data/lib/pubid/oiml/identifiers/seminar_report.rb +13 -0
  537. data/lib/pubid/oiml/identifiers/vocabulary.rb +13 -0
  538. data/lib/pubid/oiml/identifiers.rb +18 -0
  539. data/lib/pubid/oiml/parser.rb +173 -0
  540. data/lib/pubid/oiml/scheme.rb +46 -0
  541. data/lib/pubid/oiml/single_identifier.rb +90 -0
  542. data/lib/pubid/oiml/supplement_identifier.rb +43 -0
  543. data/lib/pubid/oiml/urn_generator.rb +64 -0
  544. data/lib/pubid/oiml.rb +26 -0
  545. data/lib/pubid/parser/common_parse_methods.rb +13 -0
  546. data/lib/pubid/parser/common_parse_rules.rb +56 -0
  547. data/lib/pubid/parser.rb +8 -0
  548. data/lib/pubid/parsers/base.rb +11 -0
  549. data/lib/pubid/parsers/mr_string.rb +93 -0
  550. data/lib/pubid/plateau/builder.rb +50 -0
  551. data/lib/pubid/plateau/identifier.rb +57 -0
  552. data/lib/pubid/plateau/identifiers/annex.rb +16 -0
  553. data/lib/pubid/plateau/identifiers/base.rb +51 -0
  554. data/lib/pubid/plateau/identifiers/handbook.rb +34 -0
  555. data/lib/pubid/plateau/identifiers/technical_report.rb +20 -0
  556. data/lib/pubid/plateau/identifiers.rb +12 -0
  557. data/lib/pubid/plateau/parser.rb +63 -0
  558. data/lib/pubid/plateau/scheme.rb +45 -0
  559. data/lib/pubid/plateau/supplement_identifier.rb +72 -0
  560. data/lib/pubid/plateau/urn_generator.rb +29 -0
  561. data/lib/pubid/plateau.rb +26 -0
  562. data/lib/pubid/renderers/base.rb +53 -0
  563. data/lib/pubid/renderers/directives_renderer.rb +61 -0
  564. data/lib/pubid/renderers/guide_renderer.rb +24 -0
  565. data/lib/pubid/renderers/human_readable.rb +70 -0
  566. data/lib/pubid/renderers/iwa_renderer.rb +20 -0
  567. data/lib/pubid/renderers/mr_string.rb +16 -0
  568. data/lib/pubid/renderers/supplement_renderer.rb +36 -0
  569. data/lib/pubid/renderers/urn.rb +11 -0
  570. data/lib/pubid/renderers.rb +14 -0
  571. data/lib/pubid/rendering/base.rb +73 -0
  572. data/lib/pubid/rendering/common.rb +211 -0
  573. data/lib/pubid/rendering/context.rb +159 -0
  574. data/lib/pubid/rendering/date.rb +27 -0
  575. data/lib/pubid/rendering/format.rb +25 -0
  576. data/lib/pubid/rendering/language.rb +21 -0
  577. data/lib/pubid/rendering/numbering.rb +24 -0
  578. data/lib/pubid/rendering/publisher.rb +25 -0
  579. data/lib/pubid/rendering/stage.rb +38 -0
  580. data/lib/pubid/rendering/supplement.rb +46 -0
  581. data/lib/pubid/rendering.rb +16 -0
  582. data/lib/pubid/sae/builder.rb +32 -0
  583. data/lib/pubid/sae/components/code.rb +9 -0
  584. data/lib/pubid/sae/components/date.rb +19 -0
  585. data/lib/pubid/sae/components/type.rb +19 -0
  586. data/lib/pubid/sae/components.rb +11 -0
  587. data/lib/pubid/sae/identifier.rb +37 -0
  588. data/lib/pubid/sae/identifiers/base.rb +42 -0
  589. data/lib/pubid/sae/identifiers.rb +9 -0
  590. data/lib/pubid/sae/parser.rb +55 -0
  591. data/lib/pubid/sae/scheme.rb +47 -0
  592. data/lib/pubid/sae/urn_generator.rb +38 -0
  593. data/lib/pubid/sae.rb +19 -0
  594. data/lib/pubid/scheme.rb +219 -0
  595. data/lib/pubid/urn_generator/base.rb +110 -0
  596. data/lib/pubid/utils/string_normalizer.rb +196 -0
  597. data/lib/pubid/utils.rb +7 -0
  598. data/lib/pubid/version.rb +3 -1
  599. data/lib/pubid.rb +137 -13
  600. data/lib/tasks/docs.rake +37 -0
  601. data/lib/tasks/export.rake +38 -0
  602. data/lib/tasks/website-data.json +7488 -0
  603. metadata +616 -171
  604. data/lib/pubid/registry.rb +0 -30
@@ -0,0 +1,437 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Iso
5
+ # Parses RFC 5141-bis compliant URNs into ISO identifiers
6
+ #
7
+ # URN format: urn:iso:std:{publisher}:{type}:{number}[-{part}]:{year}:{supplements}
8
+ #
9
+ # Examples:
10
+ # - urn:iso:std:iso:9001:2019
11
+ # - urn:iso:std:iso:tr:9001:2019
12
+ # - urn:iso:std:iso:9001:2019:stage-40.00
13
+ # - urn:iso:std:iso:9001:2019:amd:1:2020
14
+ # - urn:iso:std:iso-iec:27001:2013
15
+ class UrnParser
16
+ # Reverse mappings from URN format to PubID components
17
+ TYPED_STAGE_REVERSE_MAP = {
18
+ "WD" => :wd,
19
+ "WDS" => :wds,
20
+ "CD" => :cd,
21
+ "CDV" => :cdv,
22
+ "DIS" => :dis,
23
+ "FDIS" => :fdis,
24
+ "PDAM" => :pdam,
25
+ "DAM" => :dam,
26
+ "FDAM" => :fdamd,
27
+ "DCOR" => :dcor,
28
+ "FDCOR" => :fdcor,
29
+ "CDTS" => :cdts,
30
+ "DTS" => :dts,
31
+ "FDTS" => :fdts,
32
+ }.freeze
33
+
34
+ SUPPLEMENT_TYPE_MAP = {
35
+ "amd" => :amd,
36
+ "cor" => :cor,
37
+ "sup" => :sup,
38
+ "add" => :add,
39
+ }.freeze
40
+
41
+ TYPE_CODE_REVERSE_MAP = {
42
+ "tr" => :tr,
43
+ "ts" => :ts,
44
+ "pas" => :pas,
45
+ "guide" => :guide,
46
+ "dir" => :dir,
47
+ "dir-sup" => :dir_sup,
48
+ "iwa-sup" => :iwa_sup,
49
+ "isp" => :isp,
50
+ "iwa" => :iwa,
51
+ "r" => :r,
52
+ "data" => :data,
53
+ }.freeze
54
+
55
+ # Parse ISO URN string
56
+ # @param urn [String] URN string to parse
57
+ # @return [Identifier] parsed identifier
58
+ def self.parse(urn)
59
+ new.parse_urn(urn)
60
+ end
61
+
62
+ # Parse URN string into identifier
63
+ # @param urn [String] URN string
64
+ # @return [Identifier] parsed identifier
65
+ def parse_urn(urn)
66
+ # Remove urn:iso:std: prefix
67
+ unless urn.start_with?("urn:iso:std:")
68
+ raise ArgumentError,
69
+ "Invalid ISO URN: #{urn}"
70
+ end
71
+
72
+ parts = urn.sub("urn:iso:std:", "").split(":")
73
+
74
+ # Series suffix: a trailing "ser" marks an all-parts identifier. Strip
75
+ # it before component parsing so it is not misread as a language or
76
+ # supplement token (which previously rendered as "(SER)").
77
+ all_parts = false
78
+ if parts.last == "ser"
79
+ parts.pop
80
+ all_parts = true
81
+ end
82
+
83
+ # Parse publisher(s) - first part
84
+ publishers = parse_publisher(parts.shift)
85
+
86
+ # Parse type - optional (defaults to IS)
87
+ type_code = nil
88
+ type_code = parse_type(parts.first) if parts.first && TYPE_CODE_REVERSE_MAP.key?(parts.first.downcase)
89
+ parts.shift if type_code
90
+
91
+ # Parse number
92
+ number_part = parts.shift
93
+ number, part, subpart = parse_number_part(number_part)
94
+
95
+ # Parse year if present (4-digit year)
96
+ year = nil
97
+ if parts.first&.match(/^\d{4}$/)
98
+ year = parts.shift
99
+ end
100
+
101
+ # Handle URN-style part notation (:-22, :-5-1-1, etc.)
102
+ # These can come before or after year/edition in URN format
103
+ # Note: The parts are split by ':', so :-22 becomes two parts: "10164" and "-22"
104
+ if parts.first&.start_with?("-")
105
+ part_str = parts.shift
106
+ # Re-parse the number part with the URN-style part
107
+ number, part, subpart = parse_number_part("#{number}#{part_str}")
108
+ end
109
+
110
+ # Parse year if present (4-digit year) - may come after part
111
+ if year.nil? && parts.first&.match(/^\d{4}$/)
112
+ year = parts.shift
113
+ end
114
+
115
+ # Parse edition if present (ed-N format) - comes after year in URN
116
+ edition = nil
117
+ if parts.first&.start_with?("ed-")
118
+ edition = parts.shift.sub("ed-", "").to_i
119
+ end
120
+
121
+ # Parse language if present (2-letter codes like "en" or comma-separated)
122
+ languages = nil
123
+ if parts.first && !parts.first.match(/^\d+$/) &&
124
+ !parts.first.match?(/^(amd|cor|sup|add|v\d+|stage-|ed-)/i) &&
125
+ !TYPED_STAGE_REVERSE_MAP.key?(parts.first.upcase) &&
126
+ !parts.first.match?(/^[A-Z]+\.\d+$/i)
127
+ languages = parse_languages(parts.shift)
128
+ end
129
+
130
+ # Check for stage (stage-XX.XX or typed stage like WD, CD, etc.)
131
+ # IMPORTANT: This must come AFTER edition/part/language parsing but BEFORE supplements parsing
132
+ stage_code = nil
133
+ stage_iteration = nil
134
+ harmonized_stage_code = nil # Track full harmonized code for lookup
135
+ stage_from_abbr = nil # Track stage code from typed abbreviation
136
+ if parts.first&.start_with?("stage-")
137
+ stage_str = parts.shift
138
+ stage_code, stage_iteration = parse_stage_code(stage_str)
139
+ # Set harmonized_stage_code AFTER parse_stage_code has stripped .vX suffix
140
+ harmonized_stage_code = stage_str.sub("stage-", "").sub(/\.v\d+$/i,
141
+ "")
142
+ elsif TYPED_STAGE_REVERSE_MAP.key?(parts.first&.upcase) ||
143
+ (parts.first&.match?(/^[A-Za-z]+\.\d+$/) &&
144
+ TYPED_STAGE_REVERSE_MAP.key?(parts.first.upcase.split(".").first))
145
+ stage_abbr = parts.shift.upcase
146
+ # Check for iteration (WD.2 format)
147
+ if stage_abbr.include?(".")
148
+ abbr_part, iteration_part = stage_abbr.split(".")
149
+ stage_code = TYPED_STAGE_REVERSE_MAP[abbr_part]
150
+ stage_from_abbr = stage_code
151
+ stage_iteration = iteration_part.to_i
152
+ else
153
+ stage_code = TYPED_STAGE_REVERSE_MAP[stage_abbr]
154
+ stage_from_abbr = stage_code
155
+ end
156
+ end
157
+
158
+ # Check for supplements (amd, cor, sup, add)
159
+ supplements = []
160
+ while parts.any?
161
+ supp_type = nil
162
+ supp_number = nil
163
+ supp_year = nil
164
+ supp_stage = nil
165
+
166
+ # Check for supplement stage
167
+ if parts.first&.start_with?("stage-")
168
+ supp_stage_data = parts.shift
169
+ supp_stage, = parse_stage_code(supp_stage_data)
170
+ elsif TYPED_STAGE_REVERSE_MAP.key?(parts.first&.upcase)
171
+ supp_stage_abbr = parts.shift.upcase
172
+ supp_stage = TYPED_STAGE_REVERSE_MAP[supp_stage_abbr]
173
+ end
174
+
175
+ # Check for supplement type (amd, cor, sup, add)
176
+ if SUPPLEMENT_TYPE_MAP.key?(parts.first&.downcase)
177
+ supp_type = SUPPLEMENT_TYPE_MAP[parts.shift.downcase]
178
+ end
179
+
180
+ # Check for year or supplement number
181
+ if parts.first&.match(/^\d+$/)
182
+ if parts.first&.match(/^\d{4}$/)
183
+ # 4 digits = year
184
+ supp_year = parts.shift
185
+ else
186
+ # 1-3 digits = supplement number
187
+ supp_number = parts.shift.to_i
188
+ end
189
+ end
190
+
191
+ # Check for version (v1, v2, etc.) after year or number
192
+ if parts.first&.start_with?("v")
193
+ version_str = parts.shift
194
+ supp_number = version_str.sub("v", "").to_i
195
+ # Handle version with iteration (v1.2)
196
+ if supp_number.to_s.include?(".")
197
+ supp_number, = supp_number.to_s.split(".")
198
+ supp_number = supp_number.to_i
199
+ end
200
+ end
201
+
202
+ # Next part might be year if not already set
203
+ if supp_year.nil? && parts.first&.match(/^\d{4}$/)
204
+ supp_year = parts.shift
205
+ end
206
+
207
+ # Check for language after supplement
208
+ supp_languages = nil
209
+ if parts.first && !parts.first.match(/^\d+$/) && !parts.first.match?(/^(amd|cor|sup|add|v\d+|stage-)/i)
210
+ supp_languages = parse_languages(parts.shift)
211
+ end
212
+
213
+ supplements << {
214
+ type: supp_type,
215
+ number: supp_number,
216
+ year: supp_year,
217
+ stage: supp_stage,
218
+ languages: supp_languages,
219
+ }
220
+ end
221
+
222
+ # Build the identifier hash
223
+ build_identifier(publishers, number, part, subpart, type_code, stage_code, stage_iteration,
224
+ harmonized_stage_code, stage_from_abbr, year, edition, languages, supplements,
225
+ all_parts)
226
+ end
227
+
228
+ private
229
+
230
+ # Helper to find IS-type TypedStage by harmonized stage code
231
+ # Used when URN doesn't specify a type code (defaults to IS)
232
+ # Prefers the most specific (non-published) stage
233
+ def scheme_is_typed_stage_by_harmonized(harmonized_code)
234
+ candidates = Pubid::Iso::Scheme.instance.all_typed_stages.select do |ts|
235
+ ts.type_code.to_s == "is" && ts.harmonized_stages&.include?(harmonized_code)
236
+ end
237
+
238
+ return nil if candidates.empty?
239
+
240
+ # Prefer non-published stages (stage_code != "published")
241
+ # This ensures PRF is preferred over published IS for 60.00
242
+ non_published = candidates.reject do |ts|
243
+ ts.stage_code.to_s == "published"
244
+ end
245
+ candidates = non_published unless non_published.empty?
246
+
247
+ # Among remaining candidates, prefer the stage with MORE harmonized codes (more general)
248
+ # WD covers 6 codes, WDS covers only 2 — WD should be preferred for shared codes
249
+ candidates.max_by { |ts| ts.harmonized_stages&.length || 0 }
250
+ end
251
+
252
+ # Parse publisher component (iso, iso-iec, etc.)
253
+ def parse_publisher(publisher_str)
254
+ publisher_str.split("-").map(&:upcase)
255
+ end
256
+
257
+ # Parse type component
258
+ def parse_type(type_str)
259
+ TYPE_CODE_REVERSE_MAP[type_str.downcase]
260
+ end
261
+
262
+ # Parse number component (number, part, subpart)
263
+ # URN format uses :- prefix for parts: 10164:-22 or 10164:-5-1-1
264
+ def parse_number_part(number_str)
265
+ return [nil, nil, nil] unless number_str
266
+
267
+ # Check for URN-style part notation (:-22)
268
+ if number_str.match?(/^\w+:-/)
269
+ # Split by :- to get number and parts
270
+ main_and_parts = number_str.split(":-")
271
+ number = main_and_parts[0]
272
+
273
+ # The rest are parts/subparts separated by -
274
+ parts = main_and_parts[1..].join("-").split("-") if main_and_parts.length > 1
275
+ part = parts[0] if parts && parts[0]
276
+ # Join all remaining elements for subpart (e.g., "1-1" from ["5", "1", "1"])
277
+ subpart = parts[1..].join("-") if parts && parts.length > 1
278
+ [number, part, subpart]
279
+ elsif number_str.include?("-")
280
+ parts = number_str.split("-")
281
+ number = parts[0]
282
+ part = parts[1] if parts[1]
283
+ subpart = parts[2..].join("-") if parts && parts.length > 2
284
+ [number, part, subpart]
285
+ else
286
+ [number_str, nil, nil]
287
+ end
288
+ end
289
+
290
+ # Parse stage code (stage-XX.XX format)
291
+ # URN format may include iteration suffix: stage-30.00.v2
292
+ # Returns: [harmonized_stage_code_symbol, iteration_number]
293
+ # Note: The first value is the harmonized stage code (e.g., "30.00"), not a stage_code symbol
294
+ def parse_stage_code(stage_str)
295
+ stage_code = stage_str.sub("stage-", "")
296
+
297
+ # Check for iteration suffix (.v2, .v3, etc.)
298
+ if stage_code =~ /\.v(\d+)$/i
299
+ iteration = Regexp.last_match(1).to_i
300
+ stage_code = stage_code.sub(/\.v\d+$/i, "")
301
+ [stage_code.to_sym, iteration]
302
+ else
303
+ # Return harmonized stage code as symbol, no iteration
304
+ [stage_code.to_sym, nil]
305
+ end
306
+ end
307
+
308
+ # Parse language component
309
+ def parse_languages(lang_str)
310
+ lang_str.split(",").map(&:upcase)
311
+ end
312
+
313
+ # Build identifier from parsed components
314
+ def build_identifier(publishers, number, part, subpart, type_code, stage_code, stage_iteration,
315
+ harmonized_stage_code, stage_from_abbr, year, edition, languages, supplements,
316
+ all_parts = false)
317
+ # Start with base document hash
318
+ base_hash = {
319
+ publisher: publishers.first,
320
+ copublishers: publishers[1..]&.map { |c| { copublisher: c } },
321
+ }
322
+
323
+ # Build number_with_part (expected by Builder)
324
+ if part || subpart
325
+ number_with_part = number
326
+ number_with_part += "-#{part}" if part
327
+ number_with_part += "-#{subpart}" if subpart
328
+ base_hash[:number_with_part] = number_with_part
329
+ else
330
+ base_hash[:number] = number
331
+ end
332
+
333
+ base_hash[:year] = year if year
334
+ base_hash[:edition] = edition if edition
335
+
336
+ # Add type_with_stage if type_code is present
337
+ if type_code && type_code != :is
338
+ base_hash[:type_with_stage] = type_code.to_s.upcase
339
+ end
340
+
341
+ # Add stage if present
342
+ if stage_code
343
+ typed_stage = nil
344
+
345
+ if stage_from_abbr
346
+ # Stage came from a typed abbreviation (e.g., WDS, DIS, CD)
347
+ # Look up by abbreviation directly for exact match
348
+ # The stage_from_abbr is the value from TYPED_STAGE_REVERSE_MAP
349
+ # We need to find the reverse to get the original abbreviation
350
+ abbr_str = TYPED_STAGE_REVERSE_MAP.key(stage_from_abbr)
351
+ typed_stage = Scheme.locate_typed_stage_by_abbr(abbr_str) if abbr_str
352
+ # If no exact match, fall back to stage_code lookup
353
+ typed_stage ||= Scheme.locate_typed_stage_by_stage_code(stage_from_abbr)
354
+ else
355
+ # Stage came from a harmonized code (e.g., stage-20.20)
356
+ # Look up by harmonized stage code
357
+ # When no type_code is specified (default IS), look for IS type first
358
+ if !type_code || type_code == :is
359
+ typed_stage = scheme_is_typed_stage_by_harmonized(stage_code.to_s)
360
+ end
361
+
362
+ # Fall back to any typed stage if IS not found or type_code is specified
363
+ typed_stage ||= Scheme.locate_typed_stage_by_harmonized_code(stage_code.to_s)
364
+
365
+ # Special handling for stage "40.00": prefer DIS over FCD when parsing from URN
366
+ # This is because FCD is a legacy stage that maps to DIS in URN format
367
+ if stage_code.to_s == "40.00" && typed_stage && typed_stage.stage_code.to_s == "fcd"
368
+ dis_stage = Scheme.instance.all_typed_stages.detect do |ts|
369
+ ts.stage_code.to_s == "dis" && ts.harmonized_stages&.include?("40.00")
370
+ end
371
+ typed_stage = dis_stage if dis_stage
372
+ end
373
+ end
374
+
375
+ if typed_stage
376
+ base_hash[:type_with_stage] =
377
+ typed_stage.abbr.is_a?(Array) ? typed_stage.abbr.first : typed_stage.abbr
378
+ else
379
+ # Fallback: use raw harmonized stage code (shouldn't happen if data is correct)
380
+ base_hash[:stage] = harmonized_stage_code || stage_code.to_s
381
+ end
382
+
383
+ # Add stage iteration if present
384
+ base_hash[:stage_iteration] = stage_iteration.to_s if stage_iteration
385
+ end
386
+
387
+ # Add languages if present
388
+ if languages
389
+ base_hash[:languages] = languages.join("/")
390
+ end
391
+
392
+ # Build supplements recursively (forward order: first supplement wraps base,
393
+ # second wraps first, etc. -- matching URN left-to-right semantics)
394
+ supplements.each do |supp|
395
+ supp_hash = {}
396
+
397
+ if supp[:stage]
398
+ typed_stage = Scheme.locate_typed_stage_by_stage_code(supp[:stage])
399
+ supp_hash[:type_with_stage] = if
400
+ typed_stage
401
+ typed_stage.abbr.is_a?(Array) ? typed_stage.abbr.first : typed_stage.abbr
402
+ else
403
+ supp[:stage].to_s.upcase
404
+ end
405
+ end
406
+
407
+ supp_hash[:type_with_stage] ||= supp[:type].to_s.upcase if supp[:type]
408
+
409
+ if supp[:number]
410
+ supp_hash[:number] = supp[:number].to_s
411
+ end
412
+
413
+ if supp[:year]
414
+ supp_hash[:year] = supp[:year].to_s
415
+ end
416
+
417
+ if supp[:languages]
418
+ supp_hash[:languages] = supp[:languages].join("/")
419
+ end
420
+
421
+ # Wrap current identifier with supplement
422
+ base_hash = {
423
+ base_identifier: base_hash,
424
+ **supp_hash,
425
+ }
426
+ end
427
+
428
+ # all_parts belongs on the outermost identifier (after any supplement wrapping)
429
+ base_hash[:all_parts] = true if all_parts
430
+
431
+ # Build the final identifier
432
+ builder = Pubid::Iso::Builder.new(Pubid::Iso::Scheme.new)
433
+ builder.build(base_hash)
434
+ end
435
+ end
436
+ end
437
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "parslet"
4
+
5
+ module Pubid
6
+ module Iso
7
+ # Utility methods for ISO identifiers
8
+ module Utilities
9
+ module_function
10
+
11
+ # Parse identifier from document title
12
+ #
13
+ # This method attempts to extract an ISO identifier from a document title
14
+ # by progressively removing trailing words until a valid identifier is found.
15
+ #
16
+ # @param title [String] Document title
17
+ # @return [Identifier, nil] Parsed identifier, or nil if not found
18
+ #
19
+ # @example Extract identifier from title
20
+ # parse_from_title("ISO 9001:2015 Quality management systems")
21
+ # => #<Pubid::Iso::Identifiers::InternationalStandard>
22
+ def parse_from_title(title)
23
+ return nil if title.nil? || title.empty?
24
+
25
+ # Try to extract from the title by looking for common patterns
26
+ # Pattern 1: Title starts with identifier (e.g., "ISO 9001:2015 - Quality...")
27
+ if match = title.match(/^([A-Z]{2,4}(?:\/[A-Z]{2,4})?\s+\d+(?:-\d+)?(?::\d{4})?(?:\/[A-Z]+\s+\d+(?::\d{4})?)?)/i)
28
+ candidate = match[1]
29
+ begin
30
+ return Pubid::Iso.parse(candidate)
31
+ rescue Parslet::ParseFailed
32
+ # Continue to next method
33
+ end
34
+ end
35
+
36
+ # Pattern 2: Look for identifier within title (e.g., "Document on ISO 9001 requirements")
37
+ # Common ISO identifier pattern: ISO/IEC 1234-1:2015
38
+ identifier_pattern = /
39
+ \b
40
+ (?:ISO|IEC)
41
+ (?:\/[A-Z]{2,4})? # Optional copublisher
42
+ \s+
43
+ \d+(?:-\d+)? # Number and optional part
44
+ (?::\d{4})? # Optional year
45
+ (?:\/[A-Z]+\s+\d+(?::\d{4})?)? # Optional supplement
46
+ \b
47
+ /ix
48
+
49
+ # Scan for matches and try each one
50
+ matches = title.to_enum(:scan, identifier_pattern).map do
51
+ Regexp.last_match
52
+ end
53
+ matches.each do |m|
54
+ return Pubid::Iso.parse(m[0].strip)
55
+ rescue Parslet::ParseFailed
56
+ # Try next match
57
+ end
58
+
59
+ # Pattern 3: Split title into words and try progressively shorter suffixes
60
+ words = title.split(/\s+/)
61
+ (2..[words.length, 8].min).each do |count|
62
+ candidate = words[-count..].join(" ")
63
+ begin
64
+ return Pubid::Iso.parse(candidate)
65
+ rescue Parslet::ParseFailed
66
+ # Try with fewer words
67
+ end
68
+ end
69
+
70
+ # Pattern 4: Try removing trailing descriptive text
71
+ # Common patterns: " — Title", " - Title", ": Title"
72
+ title.split(/[\s—:-]+/).reverse.each do |part|
73
+ next if part.nil? || part.length < 5 # Skip very short parts
74
+
75
+ begin
76
+ return Pubid::Iso.parse(part.strip)
77
+ rescue Parslet::ParseFailed
78
+ # Try next part
79
+ end
80
+ end
81
+
82
+ nil
83
+ end
84
+ end
85
+ end
86
+ end
data/lib/pubid/iso.rb ADDED
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Pubid
6
+ module Iso
7
+ autoload :Builder, "#{__dir__}/iso/builder"
8
+ autoload :BundledIdentifier, "#{__dir__}/iso/bundled_identifier"
9
+ autoload :CombinedIdentifier, "#{__dir__}/iso/combined_identifier"
10
+ autoload :Components, "#{__dir__}/iso/components"
11
+ autoload :FormatResolver, "#{__dir__}/iso/format_resolver"
12
+ autoload :Identifier, "#{__dir__}/iso/identifier"
13
+ autoload :Identifiers, "#{__dir__}/iso/identifiers"
14
+ autoload :Parser, "#{__dir__}/iso/parser"
15
+ autoload :RenderingStyle, "#{__dir__}/iso/rendering_style"
16
+ autoload :Scheme, "#{__dir__}/iso/scheme"
17
+ autoload :SingleIdentifier, "#{__dir__}/iso/single_identifier"
18
+ autoload :SupplementIdentifier, "#{__dir__}/iso/supplement_identifier"
19
+ autoload :UrnGenerator, "#{__dir__}/iso/urn_generator"
20
+ autoload :UrnParser, "#{__dir__}/iso/urn_parser"
21
+ autoload :Utilities, "#{__dir__}/iso/utilities"
22
+
23
+ # Parse an ISO identifier string
24
+ # @param identifier [String] the identifier string to parse
25
+ # @param format [Symbol] :auto, :human, :mr_string, or :urn
26
+ # @return [Identifier] the parsed identifier
27
+ def self.parse(identifier, format: :auto)
28
+ format = Pubid::FormatDetector.detect(identifier) if format == :auto
29
+
30
+ case format
31
+ when :urn
32
+ UrnParser.parse(identifier)
33
+ when :mr_string
34
+ Pubid::Parsers::MrString.parse(identifier)
35
+ else
36
+ Scheme.parse(identifier)
37
+ end
38
+ end
39
+
40
+ # Parse an ISO URN string
41
+ # @param urn [String] the URN string to parse
42
+ # @return [Identifier] the parsed identifier
43
+ # @raise [Errors::ParseError] if URN is invalid
44
+ def self.parse_urn(urn)
45
+ UrnParser.parse(urn)
46
+ end
47
+ end
48
+ end
49
+
50
+ Pubid::Registry.register(:iso, Pubid::Iso)