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,578 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Nist
5
+ module Identifiers
6
+ # Base NIST/NBS identifier class
7
+ # Each series type inherits from this and overrides series_code
8
+ class Base < Pubid::Identifier
9
+ # Default: no typed stages. Subclasses override as needed.
10
+ def self.typed_stages
11
+ []
12
+ end
13
+
14
+ # Generate URN for this identifier
15
+ #
16
+ # @return [String] URN representation
17
+
18
+ attribute :publisher, Components::Publisher
19
+ attribute :series, Components::Code # Set by Builder from parsed data
20
+ attribute :number, Components::Code
21
+
22
+ # V2 COMPONENTS (Lutaml::Model objects) - PROPER SEPARATION
23
+ attribute :edition, Components::Edition # Edition (type + id): e2, e2021, r5, -3
24
+ attribute :edition_component, Components::Edition # V2 edition component (alias)
25
+ attribute :volume, Components::Volume # Volume component (v6)
26
+ attribute :part, Components::Part # Part component (n1 or pt1)
27
+ attribute :stage, Components::Stage
28
+ attribute :version_component, Components::Version
29
+ attribute :update_component, Components::Update
30
+ attribute :translation_component, Components::Translation
31
+ attribute :issue_number, Components::IssueNumber
32
+ attribute :parsed_format, :string # :mr, :short, :long, :abbrev
33
+ attribute :publisher_was_parsed, :boolean, default: -> { false }
34
+
35
+ # LEGACY attributes (keep for backward compatibility during migration)
36
+ attribute :parts, Components::Code, collection: true
37
+ attribute :revision, :string
38
+ attribute :revision_year, :string # Year for revision (e.g., r6/1925, r1963, rJun1992)
39
+ attribute :revision_month, :string # Month for revision (e.g., rJun1992)
40
+ attribute :edition_year, :string # Legacy edition year for backward compatibility
41
+ attribute :version, :string
42
+ attribute :update, Components::Update
43
+ attribute :year, :integer
44
+ attribute :month, :integer
45
+
46
+ # Additional attributes for complex patterns
47
+ attribute :first_number, Components::Code
48
+ attribute :second_number, Components::Code
49
+ attribute :update_number, :string
50
+ attribute :update_year, :string
51
+ attribute :addendum, :string
52
+ attribute :addendum_number, :string
53
+ # Single source of truth for the supplement: a structured component with
54
+ # isolated parts (number / year / month / date-range / revision), so a
55
+ # supplement's year is queryable independently of its number. Presence
56
+ # (non-nil) means "is a supplement"; an all-empty component is a bare
57
+ # "sup" marker. Replaces the former flat :supplement string plus the
58
+ # separate date-range/has_revision fields.
59
+ attribute :supplement, Components::Supplement
60
+ attribute :errata, :string
61
+ attribute :index, :string
62
+ attribute :insert, :string
63
+ attribute :section, :string
64
+ attribute :appendix, :string
65
+ attribute :translation, :string
66
+ attribute :draft, :string
67
+ attribute :draft_number, :string # For -draft N → N pd rendering
68
+
69
+ # Default series_code — subclasses override to provide a normalized series name.
70
+ def series_code
71
+ nil
72
+ end
73
+
74
+ def initialize(**attributes)
75
+ super()
76
+
77
+ attrs = self.class.attributes
78
+ attributes.each do |key, value|
79
+ next if value.nil?
80
+
81
+ setter = :"#{key}="
82
+ public_send(setter, value) if attrs.key?(key)
83
+ end
84
+
85
+ # NOTE: Compound number building is handled by the Builder class
86
+ # Do NOT build compound numbers here - let the builder apply special patterns first
87
+ # See lib/pubid/nist/builder.rb lines 368-472 for compound number logic
88
+ end
89
+
90
+ # Attributes that are build artifacts or rendering aliases, not part
91
+ # of an identifier's logical identity. They diverge between equally-
92
+ # valid spellings of the same id (e.g. long "Rev. 1" vs short "r1"):
93
+ # - edition_component: redundant alias of :edition
94
+ # - first_number/second_number: decomposed parts of the canonical
95
+ # :number, retained from the parse for building
96
+ # - parsed_format: records the input format for round-trip rendering
97
+ EQUALITY_IGNORED_ATTRS = %i[
98
+ edition_component first_number second_number parsed_format
99
+ ].freeze
100
+
101
+ # Logical identity comparison: equal when every attribute except the
102
+ # build artifacts/aliases above matches. (Edition#== already ignores
103
+ # its rendering-only original_prefix.)
104
+ def ==(other)
105
+ return false unless other.instance_of?(self.class)
106
+
107
+ self.class.attributes.each_key.all? do |name|
108
+ EQUALITY_IGNORED_ATTRS.include?(name) || send(name) == other.send(name)
109
+ end
110
+ end
111
+
112
+ alias eql? ==
113
+
114
+ def hash
115
+ vals = self.class.attributes.each_key.reject do |name|
116
+ EQUALITY_IGNORED_ATTRS.include?(name)
117
+ end.map { |name| send(name) }
118
+ [self.class, *vals].hash
119
+ end
120
+
121
+ # Wildcard / partial-identifier match. Treats +self+ as a QUERY pattern
122
+ # and +candidate+ as a concrete document: every ID part SET on the query
123
+ # must equal the candidate's, while parts left unset (nil/empty) are
124
+ # wildcards that match any value. So a query carrying no edition and no
125
+ # supplement matches that document across ALL editions, years, and
126
+ # supplements — the basis for "select docs by ID parts".
127
+ #
128
+ # Asymmetric (unlike ==): "NBS CIRC 25".matches?("NBS CIRC 25sup1924")
129
+ # is true, but not the reverse. The candidate must be the same class or
130
+ # a subclass so series-level identity still holds.
131
+ def matches?(candidate)
132
+ return false unless candidate.is_a?(self.class)
133
+
134
+ self.class.attributes.each_key.all? do |name|
135
+ next true if EQUALITY_IGNORED_ATTRS.include?(name)
136
+
137
+ query_val = public_send(name)
138
+ next true if query_val.nil? ||
139
+ (query_val.respond_to?(:empty?) && query_val.empty?)
140
+
141
+ query_val == candidate.public_send(name)
142
+ end
143
+ end
144
+
145
+ # Return a copy with the named attributes nil'd. Overrides
146
+ # Pubid::Identifier#exclude because NIST's initialize is keyword-only
147
+ # (initialize(**attributes)) while the inherited exclude rebuilds via
148
+ # the positional self.class.new(attrs) form — passing a positional
149
+ # hash to a keyword-only initializer raises ArgumentError. Rebuild
150
+ # with the keyword splat instead.
151
+ def exclude(*args)
152
+ excluded_args = args.dup
153
+ excluded_args << :date if excluded_args.delete(:year)
154
+
155
+ attrs = self.class.attributes.each_with_object({}) do |(name, _), h|
156
+ h[name] = excluded_args.include?(name) ? nil : send(name)
157
+ end
158
+ self.class.new(**attrs)
159
+ end
160
+
161
+ # Short-form supplement fragment ("sup", "sup1924", "supJan1924",
162
+ # "suprev", " supJun1925-Jun1926"), rendered from the structured
163
+ # component. A present-but-empty component is the bare "sup" marker; a
164
+ # number-less date range gets the leading space the number would have
165
+ # supplied. Shared by base and the per-series to_short_style overrides.
166
+ def supplement_short
167
+ return "" unless supplement
168
+
169
+ prefix = (supplement.range? && !number) ? " " : ""
170
+ rendered = supplement.to_s(:short)
171
+ prefix + (rendered.empty? ? "sup" : rendered)
172
+ end
173
+
174
+ # Compute revision from edition component for backward compatibility
175
+ # @return [String, nil] revision string (e.g., "r5") or nil
176
+ def revision
177
+ return @revision if @revision
178
+
179
+ # Compute from edition component if available
180
+ if edition&.type && edition.id
181
+ "#{edition.type}#{edition.id}"
182
+ end
183
+ end
184
+
185
+ # Backward compatibility: translation method returns translation_component
186
+ # This allows tests to use parsed.translation.language instead of parsed.translation_component.language
187
+ def translation
188
+ translation_component
189
+ end
190
+
191
+ # Backward compatibility: language method returns translation_component
192
+ # This allows tests to use parsed.language instead of parsed.translation_component
193
+ def language
194
+ translation_component
195
+ end
196
+
197
+ # Generate identifier string in specified format
198
+ # @param format [:full, :long, :abbreviated, :short, :mr] output format
199
+ def to_s(format = nil)
200
+ # Handle both keyword argument (hash) and positional argument (symbol/string)
201
+ format = format[:format] if format.is_a?(Hash)
202
+
203
+ # Default to parsed_format if available (preserves input format on round-trip)
204
+ # Falls back to :short format for output (normalization)
205
+ # Explicit format parameter always overrides parsed_format
206
+ effective_format = format || parsed_format&.to_sym || :short
207
+ effective_format = effective_format.to_sym if effective_format.is_a?(String)
208
+ case effective_format
209
+ when :full, :long
210
+ to_full_style
211
+ when :abbreviated, :abbrev
212
+ to_abbreviated_style
213
+ when :short
214
+ to_short_style
215
+ when :mr
216
+ to_mr_style
217
+ else
218
+ to_short_style
219
+ end
220
+ end
221
+
222
+ # Returns weight based on amount of defined attributes
223
+ # Used for ranking identifiers by specificity for conflict resolution
224
+ # @return [Integer] weight score (higher = more specific)
225
+ def weight
226
+ self.class.attributes.keys.inject(0) do |sum, key|
227
+ val = public_send(key)
228
+ val && !val.to_s.empty? ? sum + 1 : sum
229
+ end
230
+ end
231
+
232
+ # Merge another document into this one
233
+ # Used for combining document data, preferring more specific values
234
+ # @param document [Base] another NIST document to merge
235
+ # @return [Base] self with merged attributes
236
+ def merge(document)
237
+ return self unless document.is_a?(Base)
238
+
239
+ attrs = self.class.attributes
240
+ attrs.each_key do |var_name|
241
+ next if var_name == :rendering_style
242
+ next if var_name == :parsed_format
243
+
244
+ current_val = public_send(var_name)
245
+ new_val = document.public_send(var_name)
246
+ next unless new_val
247
+
248
+ should_merge = case var_name
249
+ when :publisher, :series, :number
250
+ true
251
+ when :edition
252
+ current_val.nil? || edition_greater?(new_val,
253
+ current_val)
254
+ when :volume, :part, :version, :revision
255
+ current_val.nil? || (new_val.to_s.length > current_val.to_s.length)
256
+ when :supplement, :errata, :index, :insert, :section, :appendix, :translation
257
+ true
258
+ when :year, :month, :update, :draft
259
+ true
260
+ else
261
+ false
262
+ end
263
+
264
+ public_send(:"#{var_name}=", new_val) if should_merge
265
+ end
266
+
267
+ self
268
+ end
269
+
270
+ # Helper to compare edition values numerically
271
+ # @return [Boolean] true if edition1 is greater than edition2
272
+ def edition_greater?(edition1, edition2)
273
+ num1 = extract_edition_number(edition1)
274
+ num2 = extract_edition_number(edition2)
275
+ num1 && num2 && num1 > num2
276
+ end
277
+
278
+ # Extract numeric value from edition (r3 -> 3, r5 -> 5, e2 -> 2)
279
+ # @return [Integer, nil] the edition number or nil if not extractable
280
+ def extract_edition_number(edition)
281
+ # Handle both String and Edition component
282
+ edition_str = edition.to_s
283
+ # Match patterns like r3, r5, e2, etc.
284
+ match = edition_str.match(/^[er]?(\d+)$/)
285
+ match ? match[1].to_i : nil
286
+ end
287
+
288
+ private
289
+
290
+ def to_full_style
291
+ # "National Institute of Standards and Technology Special Publication 800-27, Revision A"
292
+ result = publisher_full_name
293
+ result += " #{series_full_name}" if series
294
+ result += " #{number.value}" if number
295
+ result += parts.map { |p| "-#{p}" }.join if parts&.any?
296
+
297
+ # Render volume and issue number in long form: "Vol. 6, No. 12"
298
+ if volume && issue_number
299
+ result += " Vol. #{volume}, #{issue_number.to_s(:long)}"
300
+ elsif volume
301
+ result += " Vol. #{volume}"
302
+ end
303
+
304
+ # NEW: Use edition component properly
305
+ result += " #{edition.to_s(:long)}" if edition
306
+
307
+ result += ", Revision #{revision.sub(/^r/, '')}" if revision
308
+
309
+ # V2: Use version_component
310
+ result += " #{version_component.to_s(:long)}" if version_component
311
+
312
+ # V2: Use update_component
313
+ result += " #{update_component.to_s(:long)}" if update_component
314
+
315
+ # V2: Use stage
316
+ result += " #{stage.to_s(:long)}" if stage
317
+
318
+ # V2: Use translation_component (already includes space)
319
+ result += translation_component.to_s(:long) if translation_component
320
+
321
+ result
322
+ end
323
+
324
+ def to_abbreviated_style
325
+ # "Natl. Inst. Stand. Technol. Spec. Publ. 800-57 Part 1, Revision 4"
326
+ result = publisher_abbreviated_name
327
+ result += " #{series_abbreviated_name}" if series
328
+ result += " #{number}" if number
329
+ result += " Part #{parts.first}" if parts&.any?
330
+
331
+ # NEW: Use edition component properly
332
+ result += " #{edition.to_s(:abbrev)}" if edition
333
+
334
+ result += ", Revision #{revision}" if revision
335
+
336
+ # V2: Use version_component
337
+ result += " #{version_component.to_s(:abbrev)}" if version_component
338
+
339
+ # V2: Use update_component
340
+ result += " #{update_component.to_s(:abbrev)}" if update_component
341
+
342
+ # V2: Use stage
343
+ result += " #{stage.to_s(:abbrev)}" if stage
344
+
345
+ # V2: Use translation_component
346
+ result += ", #{translation_component.to_s(:abbrev)}" if translation_component
347
+
348
+ result
349
+ end
350
+
351
+ def to_short_style
352
+ # "SP 800-187" or "NIST SP 800-187" - handle compound series properly
353
+ result = ""
354
+
355
+ # Determine effective publisher
356
+ # Only show publisher if it was explicitly parsed (either directly or from series prefix)
357
+ effective_publisher = if publisher && publisher_was_parsed
358
+ # Publisher was in input (either as separate field or extracted from "NBS CS" series)
359
+ publisher.to_s
360
+ else
361
+ # No publisher in input, don't show default
362
+ nil
363
+ end
364
+
365
+ # Determine effective series - PREFER series_code if subclass defines it
366
+ # This allows normalization (e.g., LCIRC → LC in LetterCircular)
367
+ effective_series = if series_code
368
+ series_code
369
+ elsif series
370
+ series.to_s
371
+ end
372
+
373
+ # Special handling for compound series that include publisher prefix
374
+ # If series starts with "NBS " (like "NBS CIRC"), use it as-is
375
+ if effective_series&.start_with?("NBS ")
376
+ result += effective_series
377
+ elsif effective_publisher && effective_series
378
+ result += "#{effective_publisher} #{effective_series}"
379
+ elsif effective_series && publisher_was_parsed
380
+ # Only add "NIST" prefix if publisher was explicitly in the input
381
+ result += "NIST #{effective_series}"
382
+ elsif effective_series
383
+ # No publisher in input, just show series without prefix
384
+ result += effective_series
385
+ end
386
+
387
+ result += " #{number}" if number
388
+ result += parts.map { |p| "-#{p}" }.join if parts&.any?
389
+
390
+ # NEW: Use Volume and Part components (v6n1 notation for CSM, pt1 for SP)
391
+ if volume.is_a?(Components::Volume) && part.is_a?(Components::Part)
392
+ # CSM series: v#n# notation
393
+ result += " #{volume}#{part}"
394
+ elsif part.is_a?(Components::Part)
395
+ # SP and other series: use Part.type to determine format
396
+ result += part.to_s
397
+ # Legacy: Render standalone volume (not part of v#n#)
398
+ elsif volume && !issue_number && !part
399
+ vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
400
+ result += vol_str
401
+ elsif volume && issue_number
402
+ # Render volume and issue number in short form: "v6n12"
403
+ vol_str = volume.is_a?(Components::Volume) ? volume.to_s : "v#{volume}"
404
+ result += "#{vol_str}n#{issue_number.number}"
405
+ end
406
+
407
+ # NEW: Use edition component properly (e2, e2021, r5, -3)
408
+ # NO space before edition when number present (per NIST spec)
409
+ # Only add space for bare edition (no number case) or if original_prefix has specific format
410
+ if edition
411
+ if edition.original_prefix && !edition.original_prefix.empty?
412
+ # original_prefix includes the full prefix (e.g., " Rev. " for verbose format)
413
+ result += edition.to_s
414
+ elsif number
415
+ # Number present, NO space: "800-53r5"
416
+ result += edition.to_s
417
+ else
418
+ # Bare edition, add space: " r5"
419
+ result += " #{edition}"
420
+ end
421
+ end
422
+
423
+ # V2: Use version_component if available, else use version string.
424
+ # Attach directly (no leading space) to match edition rendering
425
+ # (e.g. "800-53r5"), so version reads "800-45ver2" not
426
+ # "800-45 ver2".
427
+ if version_component
428
+ result += version_component.to_s(:short)
429
+ elsif version
430
+ result += "ver#{version}"
431
+ end
432
+
433
+ # Add supplement. NIST/NBS canonical short form is single-p "sup"
434
+ # with the suffix attached directly, no dash (relaton-data-nist
435
+ # uses "sup2", "sup1940", "supA"); date-range keeps its inner dash.
436
+ # Rendered from the structured component; a present-but-empty
437
+ # component is the bare "sup" marker.
438
+ result += supplement_short
439
+
440
+ # Add other attributes
441
+ result += errata.to_s if errata
442
+ result += "index" if index
443
+ result += "insert" if insert
444
+ result += "sec#{section}" if section
445
+ result += "app" if appendix
446
+
447
+ # Add addendum - render as " Add." suffix
448
+ if addendum || addendum_number
449
+ result += " Add."
450
+ end
451
+
452
+ # V2: Use update_component if available, else use update string
453
+ if update_component
454
+ result += update_component.to_s(:short)
455
+ elsif update
456
+ result += "-upd#{update}"
457
+ end
458
+
459
+ # Add draft - render as {N}pd if draft_number present
460
+ if draft_number
461
+ result += " #{draft_number}pd"
462
+ elsif draft&.to_s&.include?("draft") && !draft.to_s.include?("Draft)")
463
+ result += "-draft"
464
+ end
465
+
466
+ # V2: Add stage component (at end, before translation)
467
+ if stage
468
+ result += " #{stage.to_s(:short)}"
469
+ end
470
+
471
+ # V2: Use translation_component if available, else use translation string
472
+ # Note: translation_component.to_s already includes the space prefix
473
+ if translation_component
474
+ result += translation_component.to_s(:short)
475
+ elsif translation
476
+ result += " #{translation}"
477
+ end
478
+
479
+ result
480
+ end
481
+
482
+ def to_mr_style
483
+ # "NIST.SP.800-116r1.ipd" (machine-readable with dots)
484
+ result = (publisher || "NIST").to_s
485
+
486
+ # Determine effective series - PREFER series_code if subclass defines it
487
+ # This allows normalization (e.g., LCIRC → LC in LetterCircular)
488
+ effective_series = if series_code
489
+ series_code
490
+ elsif series
491
+ series.to_s
492
+ end
493
+
494
+ result += ".#{effective_series}" if effective_series
495
+ result += ".#{number}" if number
496
+ result += parts.map { |p| "-#{p}" }.join if parts&.any?
497
+
498
+ # Part component (pt1, v6n1, etc.)
499
+ result += part.to_s if part.is_a?(Components::Part)
500
+
501
+ # NEW: Use edition component - NO space before edition in MR format (per NIST spec)
502
+ if edition
503
+ # If edition has original_prefix set (e.g., verbose " Rev. "), use it as-is
504
+ # Otherwise, no space needed in MR format: ".800-53r5"
505
+ if edition.original_prefix && !edition.original_prefix.empty?
506
+ end
507
+ result += edition.to_s
508
+ end
509
+
510
+ # V2: Use version_component
511
+ result += version_component.to_s(:mr) if version_component
512
+
513
+ # V2: Use update_component
514
+ result += update_component.to_s(:mr) if update_component
515
+
516
+ # V2: Use stage
517
+ result += ".#{stage.to_s(:mr)}" if stage
518
+
519
+ # Add addendum - render as ".Add." suffix in MR format
520
+ if addendum || addendum_number
521
+ result += ".Add."
522
+ end
523
+
524
+ # V2: Use translation_component
525
+ result += translation_component.to_s(:mr) if translation_component
526
+
527
+ result
528
+ end
529
+
530
+ def series_full_name
531
+ {
532
+ "SP" => "Special Publication",
533
+ "FIPS" => "Federal Information Processing Standards",
534
+ "IR" => "Interagency Report",
535
+ "TN" => "Technical Note",
536
+ }[series] || series
537
+ end
538
+
539
+ def series_abbreviated_name
540
+ {
541
+ "SP" => "Spec. Publ.",
542
+ "FIPS" => "Fed. Inf. Proc. Stand.",
543
+ "IR" => "Interag. Rep.",
544
+ "TN" => "Tech. Note",
545
+ }[series&.to_s || series_code] || (series&.to_s || series_code)
546
+ end
547
+
548
+ def publisher_full_name
549
+ case publisher.to_s
550
+ when "NBS"
551
+ "National Bureau of Standards"
552
+ when "NIST"
553
+ "National Institute of Standards and Technology"
554
+ else
555
+ publisher.to_s
556
+ end
557
+ end
558
+
559
+ def publisher_abbreviated_name
560
+ case publisher.to_s
561
+ when "NBS"
562
+ "Natl. Bur. Stand."
563
+ when "NIST"
564
+ "Natl. Inst. Stand. Technol."
565
+ else
566
+ publisher.to_s
567
+ end
568
+ end
569
+
570
+ # Default publisher for series without explicit publisher
571
+ # Subclasses can override
572
+ def default_publisher
573
+ "NIST"
574
+ end
575
+ end
576
+ end
577
+ end
578
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Nist
5
+ module Identifiers
6
+ # NBS Circular Identifier
7
+ # Examples:
8
+ # - "NBS CIRC 13e2revJune1908" = Circular 13, edition 2, revised June 1908
9
+ # - "NBS CIRC 13" = Circular 13
10
+ class Circular < Base
11
+ TYPED_STAGES = [
12
+ Pubid::Components::TypedStage.new(
13
+ abbr: ["CIRC", "NBS CIRC"],
14
+ stage_code: "published",
15
+ type_code: "circ",
16
+ ),
17
+ ].freeze
18
+
19
+ class << self
20
+ def typed_stages
21
+ TYPED_STAGES
22
+ end
23
+
24
+ def type
25
+ { key: :circ, title: "NBS Circular", short: "CIRC" }
26
+ end
27
+ end
28
+
29
+ attribute :revised_date, :string # For revJune1908 notation
30
+
31
+ def default_publisher
32
+ "NBS"
33
+ end
34
+
35
+ def series_code
36
+ "CIRC"
37
+ end
38
+
39
+ # Convenience methods for tests that expect string values
40
+ def publisher
41
+ super&.to_s || default_publisher
42
+ end
43
+
44
+ def series
45
+ super&.to_s || series_code
46
+ end
47
+
48
+ # Override to_s for CIRC-specific edition+year rendering
49
+ # CIRC uses dot notation: "NBS CIRC 11e2.1915" instead of "NBS CIRC 11e2-1915"
50
+ def to_s(format = nil)
51
+ result = super
52
+
53
+ # For CIRC edition patterns with additional_text (year), render with dot notation
54
+ # "11e2-1915" format: edition.id="2", additional_text="1915" → render as "11e2.1915"
55
+ if edition && edition.type == "e" && edition.additional_text&.match?(/^\d{4}$/)
56
+ # Replace "11e1915" with "11e2.1915" format
57
+ # Pattern: number + "e" + year (where year was stored in edition.id)
58
+ # Need to reconstruct: number + "e" + edition.id + "." + additional_text
59
+ result = result.gsub(/e(\d{4})$/,
60
+ "e#{edition.id || '?'}.#{edition.additional_text}")
61
+ end
62
+
63
+ result
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Nist
5
+ module Identifiers
6
+ # NBS Circular Supplement Identifier
7
+ # Wraps a base Circular identifier with supplement information
8
+ #
9
+ # Examples:
10
+ # - "NBS CIRC 101e2supp" → CircularSupplement(base: Circular(101, e2))
11
+ # - "NBS CIRC 25supp-1924" → CircularSupplement(base: Circular(25), edition: 1924)
12
+ # - "NBS CIRC suppJun1925-Jun1926" → CircularSupplement(edition with date range)
13
+ class CircularSupplement < SupplementIdentifier
14
+ # NOTE: CircularSupplement uses same TYPED_STAGES as Circular
15
+ # It's a variant edition pattern, not a separate series type
16
+ TYPED_STAGES = [
17
+ Pubid::Components::TypedStage.new(
18
+ abbr: ["CIRC", "NBS CIRC"],
19
+ stage_code: "published",
20
+ type_code: "circ",
21
+ ),
22
+ ].freeze
23
+
24
+ class << self
25
+ def typed_stages
26
+ TYPED_STAGES
27
+ end
28
+
29
+ def type
30
+ { key: :circ_supp, title: "NBS Circular Supplement", short: "CIRC" }
31
+ end
32
+ end
33
+
34
+ attribute :supplement_date_range_start, :string # Jun1925
35
+ attribute :supplement_date_range_end, :string # Jun1926
36
+ attribute :implicit_supplement, :boolean # true for implicit supplements (e.g., "145r11/1925")
37
+
38
+ def to_s(format = :short)
39
+ # Handle date range supplements (no base identifier)
40
+ if supplement_date_range_start && supplement_date_range_end
41
+ return "NBS CIRC sup#{supplement_date_range_start}-#{supplement_date_range_end}"
42
+ end
43
+
44
+ # Use parent's rendering for base + supplement
45
+ super
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end