pubid 1.15.17 → 2.0.0.pre.alpha.1

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