pubid 2.0.0.pre.alpha.2 → 2.0.0.pre.alpha.3

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 (458) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +25 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -39
  6. data/lib/pubid/amca/identifiers/base.rb +0 -26
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -17
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -13
  9. data/lib/pubid/amca/renderer.rb +82 -0
  10. data/lib/pubid/amca/single_identifier.rb +0 -23
  11. data/lib/pubid/amca/urn_parser.rb +28 -0
  12. data/lib/pubid/amca.rb +42 -1
  13. data/lib/pubid/ansi/builder.rb +5 -3
  14. data/lib/pubid/ansi/identifier.rb +1 -43
  15. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  16. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  17. data/lib/pubid/ansi/renderer.rb +53 -0
  18. data/lib/pubid/ansi/single_identifier.rb +2 -31
  19. data/lib/pubid/ansi/urn_generator.rb +3 -38
  20. data/lib/pubid/ansi/urn_parser.rb +23 -0
  21. data/lib/pubid/ansi.rb +38 -3
  22. data/lib/pubid/api/builder.rb +29 -74
  23. data/lib/pubid/api/identifier.rb +0 -51
  24. data/lib/pubid/api/identifiers/base.rb +0 -2
  25. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  26. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  27. data/lib/pubid/api/identifiers/mpms.rb +1 -17
  28. data/lib/pubid/api/identifiers/publication.rb +0 -2
  29. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  30. data/lib/pubid/api/identifiers/specification.rb +0 -2
  31. data/lib/pubid/api/identifiers/standard.rb +0 -2
  32. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  33. data/lib/pubid/api/identifiers/typeless_standard.rb +1 -14
  34. data/lib/pubid/api/identifiers.rb +18 -0
  35. data/lib/pubid/api/renderer.rb +89 -0
  36. data/lib/pubid/api/single_identifier.rb +1 -13
  37. data/lib/pubid/api/urn_generator.rb +0 -18
  38. data/lib/pubid/api/urn_parser.rb +35 -0
  39. data/lib/pubid/api.rb +51 -5
  40. data/lib/pubid/ashrae/builder.rb +3 -3
  41. data/lib/pubid/ashrae/identifier.rb +6 -39
  42. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  43. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  44. data/lib/pubid/ashrae/identifiers/base.rb +3 -0
  45. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  46. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  47. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  48. data/lib/pubid/ashrae/renderer.rb +117 -0
  49. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  50. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  51. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  52. data/lib/pubid/ashrae.rb +42 -1
  53. data/lib/pubid/asme/components/code.rb +10 -2
  54. data/lib/pubid/asme/identifier.rb +0 -46
  55. data/lib/pubid/asme/identifiers/base.rb +0 -60
  56. data/lib/pubid/asme/renderer.rb +66 -0
  57. data/lib/pubid/asme/urn_parser.rb +31 -0
  58. data/lib/pubid/asme.rb +42 -1
  59. data/lib/pubid/astm/components/code.rb +9 -0
  60. data/lib/pubid/{jis → astm}/components.rb +1 -1
  61. data/lib/pubid/astm/identifier.rb +0 -77
  62. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  63. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  64. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  65. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  66. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  67. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  68. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  69. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  70. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  71. data/lib/pubid/astm/identifiers.rb +18 -0
  72. data/lib/pubid/astm/renderer.rb +172 -0
  73. data/lib/pubid/astm/single_identifier.rb +0 -10
  74. data/lib/pubid/astm/urn_parser.rb +30 -0
  75. data/lib/pubid/astm.rb +39 -27
  76. data/lib/pubid/bsi/builder.rb +21 -12
  77. data/lib/pubid/bsi/identifier.rb +8 -62
  78. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  79. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  80. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  81. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  82. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  83. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  84. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  85. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  87. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  88. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  89. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  90. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  91. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  92. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  93. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  94. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  95. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  96. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  97. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  98. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  99. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  100. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  101. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  102. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  103. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  104. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  105. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  106. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  107. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  108. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  109. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  110. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  111. data/lib/pubid/bsi/identifiers.rb +0 -1
  112. data/lib/pubid/bsi/renderer.rb +1050 -0
  113. data/lib/pubid/bsi/single_identifier.rb +6 -70
  114. data/lib/pubid/bsi/urn_generator.rb +2 -3
  115. data/lib/pubid/bsi/urn_parser.rb +52 -0
  116. data/lib/pubid/bsi.rb +224 -1
  117. data/lib/pubid/builder/base.rb +57 -10
  118. data/lib/pubid/bundled_identifier.rb +0 -1
  119. data/lib/pubid/ccsds/builder.rb +4 -3
  120. data/lib/pubid/ccsds/identifier.rb +63 -66
  121. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  122. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  123. data/lib/pubid/ccsds/parser.rb +4 -2
  124. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  125. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  126. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  127. data/lib/pubid/ccsds.rb +39 -1
  128. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  129. data/lib/pubid/cen_cenelec/identifier.rb +7 -38
  130. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  131. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  132. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  133. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  135. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  136. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  137. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  139. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  140. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  141. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  143. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  145. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  146. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  147. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  148. data/lib/pubid/cen_cenelec.rb +168 -1
  149. data/lib/pubid/cie/components/code.rb +8 -0
  150. data/lib/pubid/cie/identifier.rb +6 -57
  151. data/lib/pubid/cie/urn_parser.rb +28 -0
  152. data/lib/pubid/cie.rb +43 -1
  153. data/lib/pubid/components/adoption.rb +104 -0
  154. data/lib/pubid/components/code.rb +22 -8
  155. data/lib/pubid/components/date.rb +23 -16
  156. data/lib/pubid/components/edition.rb +9 -6
  157. data/lib/pubid/components/iteration.rb +32 -0
  158. data/lib/pubid/components/language.rb +6 -4
  159. data/lib/pubid/components/locality.rb +10 -1
  160. data/lib/pubid/components/publisher.rb +9 -6
  161. data/lib/pubid/components/relationship.rb +151 -0
  162. data/lib/pubid/components/stage.rb +5 -14
  163. data/lib/pubid/components/supplement.rb +184 -0
  164. data/lib/pubid/components/type.rb +5 -15
  165. data/lib/pubid/components/typed_stage.rb +10 -11
  166. data/lib/pubid/components.rb +4 -1
  167. data/lib/pubid/core/update_codes.rb +28 -7
  168. data/lib/pubid/csa/identifier.rb +0 -59
  169. data/lib/pubid/csa/identifiers/base.rb +2 -122
  170. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  171. data/lib/pubid/csa/identifiers/series.rb +2 -102
  172. data/lib/pubid/csa/renderer.rb +292 -0
  173. data/lib/pubid/csa/urn_generator.rb +1 -1
  174. data/lib/pubid/csa/urn_parser.rb +33 -0
  175. data/lib/pubid/csa.rb +42 -1
  176. data/lib/pubid/etsi/components/code.rb +9 -2
  177. data/lib/pubid/etsi/identifier.rb +0 -43
  178. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  179. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  180. data/lib/pubid/etsi/renderer.rb +42 -0
  181. data/lib/pubid/etsi/urn_parser.rb +34 -0
  182. data/lib/pubid/etsi.rb +42 -1
  183. data/lib/pubid/export/exporter.rb +4 -46
  184. data/lib/pubid/export/flavor_exporter.rb +111 -278
  185. data/lib/pubid/export.rb +0 -6
  186. data/lib/pubid/identifier.rb +2 -17
  187. data/lib/pubid/identifier_facade.rb +114 -0
  188. data/lib/pubid/identifier_metadata.rb +1 -1
  189. data/lib/pubid/idf/builder.rb +3 -3
  190. data/lib/pubid/idf/identifier.rb +3 -66
  191. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  192. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  193. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  194. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  195. data/lib/pubid/idf/parser.rb +3 -2
  196. data/lib/pubid/idf/renderer.rb +84 -0
  197. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  198. data/lib/pubid/idf/urn_generator.rb +4 -39
  199. data/lib/pubid/idf/urn_parser.rb +25 -0
  200. data/lib/pubid/idf.rb +51 -1
  201. data/lib/pubid/iec/builder.rb +46 -64
  202. data/lib/pubid/iec/components/code.rb +8 -32
  203. data/lib/pubid/iec/components/publisher.rb +0 -1
  204. data/lib/pubid/iec/components.rb +14 -0
  205. data/lib/pubid/iec/identifier.rb +251 -213
  206. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  207. data/lib/pubid/iec/identifiers/base.rb +8 -32
  208. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  209. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  210. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -26
  211. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  212. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -22
  213. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  214. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  215. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  216. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  217. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  218. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -11
  219. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  220. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  222. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  223. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  224. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  225. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -19
  226. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  227. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  228. data/lib/pubid/iec/identifiers.rb +30 -0
  229. data/lib/pubid/iec/parser.rb +13 -12
  230. data/lib/pubid/iec/renderer.rb +254 -0
  231. data/lib/pubid/iec/single_identifier.rb +6 -12
  232. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  233. data/lib/pubid/iec/urn_generator.rb +3 -3
  234. data/lib/pubid/iec/urn_parser.rb +3 -3
  235. data/lib/pubid/iec.rb +40 -68
  236. data/lib/pubid/ieee/builder.rb +12 -12
  237. data/lib/pubid/ieee/components/code.rb +8 -0
  238. data/lib/pubid/ieee/components/draft.rb +14 -0
  239. data/lib/pubid/ieee/components/relationship.rb +5 -149
  240. data/lib/pubid/ieee/identifier.rb +6 -41
  241. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  242. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  243. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  245. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  246. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  247. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  248. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  249. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  250. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  251. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  252. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  253. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  254. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  255. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  256. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  257. data/lib/pubid/ieee/pre_parser.rb +301 -0
  258. data/lib/pubid/ieee/renderer.rb +307 -0
  259. data/lib/pubid/ieee/urn_parser.rb +34 -0
  260. data/lib/pubid/ieee.rb +62 -1
  261. data/lib/pubid/ieee_debug.rb +0 -1
  262. data/lib/pubid/iho/builder.rb +2 -2
  263. data/lib/pubid/iho/identifier.rb +8 -42
  264. data/lib/pubid/iho/identifiers/base.rb +49 -10
  265. data/lib/pubid/iho/parser.rb +3 -3
  266. data/lib/pubid/iho/renderer.rb +30 -0
  267. data/lib/pubid/iho/urn_generator.rb +2 -2
  268. data/lib/pubid/iho/urn_parser.rb +58 -0
  269. data/lib/pubid/iho.rb +50 -1
  270. data/lib/pubid/iso/builder.rb +55 -53
  271. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  272. data/lib/pubid/iso/components/code.rb +7 -19
  273. data/lib/pubid/iso/components/publisher.rb +10 -8
  274. data/lib/pubid/iso/components.rb +2 -4
  275. data/lib/pubid/iso/identifier.rb +218 -252
  276. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  277. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  278. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  279. data/lib/pubid/iso/identifiers/data.rb +0 -1
  280. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  281. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  282. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  283. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  284. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  285. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  286. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  287. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  288. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  289. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  290. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  291. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  292. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  293. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  294. data/lib/pubid/iso/identifiers.rb +0 -1
  295. data/lib/pubid/iso/normalizer.rb +89 -0
  296. data/lib/pubid/iso/parser.rb +22 -4
  297. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  298. data/lib/pubid/iso/urn_generator.rb +66 -182
  299. data/lib/pubid/iso/urn_parser.rb +12 -7
  300. data/lib/pubid/iso.rb +173 -2
  301. data/lib/pubid/itu/builder.rb +0 -12
  302. data/lib/pubid/itu/components/code.rb +8 -0
  303. data/lib/pubid/itu/components.rb +11 -0
  304. data/lib/pubid/itu/identifier.rb +6 -104
  305. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  306. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  307. data/lib/pubid/itu/identifiers/base.rb +0 -6
  308. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  309. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  310. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  311. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  312. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  313. data/lib/pubid/itu/urn_parser.rb +23 -0
  314. data/lib/pubid/itu.rb +42 -1
  315. data/lib/pubid/jcgm/builder.rb +16 -8
  316. data/lib/pubid/jcgm/identifier.rb +0 -43
  317. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  318. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  319. data/lib/pubid/jcgm/renderer.rb +68 -0
  320. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  321. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  322. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  323. data/lib/pubid/jcgm.rb +43 -2
  324. data/lib/pubid/jis/builder.rb +44 -52
  325. data/lib/pubid/jis/identifier.rb +132 -46
  326. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  327. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  328. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  329. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  330. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  331. data/lib/pubid/jis/identifiers.rb +1 -1
  332. data/lib/pubid/jis/parser.rb +31 -5
  333. data/lib/pubid/jis/renderer.rb +69 -0
  334. data/lib/pubid/jis/single_identifier.rb +6 -12
  335. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  336. data/lib/pubid/jis/urn_parser.rb +23 -0
  337. data/lib/pubid/jis.rb +42 -2
  338. data/lib/pubid/nist/builder.rb +63 -1871
  339. data/lib/pubid/nist/caster.rb +1272 -0
  340. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  341. data/lib/pubid/nist/components/code.rb +9 -20
  342. data/lib/pubid/nist/components/supplement.rb +2 -2
  343. data/lib/pubid/nist/components.rb +0 -1
  344. data/lib/pubid/nist/identifier.rb +11 -48
  345. data/lib/pubid/nist/identifiers/base.rb +110 -47
  346. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  347. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  348. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  349. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  350. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  351. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  352. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  353. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  354. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  355. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  356. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  357. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  358. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  359. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  360. data/lib/pubid/nist/identifiers/report.rb +4 -2
  361. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  362. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  363. data/lib/pubid/nist/identifiers.rb +1 -0
  364. data/lib/pubid/nist/parser.rb +62 -452
  365. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  366. data/lib/pubid/nist/preprocessor.rb +416 -0
  367. data/lib/pubid/nist/renderer.rb +43 -0
  368. data/lib/pubid/nist/router.rb +148 -0
  369. data/lib/pubid/nist/series/base.rb +58 -0
  370. data/lib/pubid/nist/series/crpl.rb +13 -0
  371. data/lib/pubid/nist/series/fips.rb +14 -0
  372. data/lib/pubid/nist/series/ir.rb +60 -0
  373. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  374. data/lib/pubid/nist/series/mono.rb +19 -0
  375. data/lib/pubid/nist/series/ncstar.rb +20 -0
  376. data/lib/pubid/nist/series.rb +49 -0
  377. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  378. data/lib/pubid/nist/urn_parser.rb +67 -0
  379. data/lib/pubid/nist.rb +82 -4
  380. data/lib/pubid/oiml/components/code.rb +10 -0
  381. data/lib/pubid/oiml/identifier.rb +0 -50
  382. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  383. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  384. data/lib/pubid/oiml/renderer.rb +161 -0
  385. data/lib/pubid/oiml/single_identifier.rb +6 -45
  386. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  387. data/lib/pubid/oiml/urn_generator.rb +0 -8
  388. data/lib/pubid/oiml/urn_parser.rb +22 -0
  389. data/lib/pubid/oiml.rb +42 -1
  390. data/lib/pubid/plateau/identifier.rb +7 -41
  391. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  392. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  393. data/lib/pubid/plateau/renderer.rb +51 -0
  394. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  395. data/lib/pubid/plateau/urn_parser.rb +43 -0
  396. data/lib/pubid/plateau.rb +43 -1
  397. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  398. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  399. data/lib/pubid/renderers/human_readable.rb +18 -7
  400. data/lib/pubid/rendering/context.rb +28 -19
  401. data/lib/pubid/rendering.rb +0 -3
  402. data/lib/pubid/sae/components/date.rb +8 -0
  403. data/lib/pubid/sae/components/type.rb +5 -1
  404. data/lib/pubid/sae/identifier.rb +0 -23
  405. data/lib/pubid/sae/identifiers/base.rb +2 -16
  406. data/lib/pubid/sae/renderer.rb +36 -0
  407. data/lib/pubid/sae/urn_generator.rb +2 -10
  408. data/lib/pubid/sae/urn_parser.rb +36 -0
  409. data/lib/pubid/sae.rb +42 -1
  410. data/lib/pubid/urn_generator/base.rb +12 -12
  411. data/lib/pubid/urn_parser/base.rb +81 -0
  412. data/lib/pubid/urn_parser/errors.rb +9 -0
  413. data/lib/pubid/urn_parser.rb +14 -0
  414. data/lib/pubid/version.rb +1 -1
  415. data/lib/pubid.rb +29 -7
  416. data/lib/tasks/website-data.json +1940 -1882
  417. metadata +75 -44
  418. data/lib/pubid/amca/scheme.rb +0 -16
  419. data/lib/pubid/ansi/scheme.rb +0 -15
  420. data/lib/pubid/api/scheme.rb +0 -66
  421. data/lib/pubid/ashrae/scheme.rb +0 -53
  422. data/lib/pubid/asme/scheme.rb +0 -37
  423. data/lib/pubid/astm/scheme.rb +0 -55
  424. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  425. data/lib/pubid/bsi/scheme.rb +0 -243
  426. data/lib/pubid/ccsds/scheme.rb +0 -57
  427. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  428. data/lib/pubid/cie/scheme.rb +0 -64
  429. data/lib/pubid/components/factory.rb +0 -50
  430. data/lib/pubid/csa/scheme.rb +0 -44
  431. data/lib/pubid/etsi/scheme.rb +0 -42
  432. data/lib/pubid/export/data_class_exporter.rb +0 -59
  433. data/lib/pubid/export/ieee_exporter.rb +0 -78
  434. data/lib/pubid/export/itu_exporter.rb +0 -66
  435. data/lib/pubid/export/nist_exporter.rb +0 -64
  436. data/lib/pubid/export/registry_exporter.rb +0 -90
  437. data/lib/pubid/export/scheme_exporter.rb +0 -70
  438. data/lib/pubid/identifier_registry.rb +0 -198
  439. data/lib/pubid/idf/scheme.rb +0 -61
  440. data/lib/pubid/iec/scheme.rb +0 -71
  441. data/lib/pubid/ieee/scheme.rb +0 -90
  442. data/lib/pubid/iho/scheme.rb +0 -29
  443. data/lib/pubid/iso/identifiers/base.rb +0 -115
  444. data/lib/pubid/iso/scheme.rb +0 -193
  445. data/lib/pubid/itu/scheme.rb +0 -174
  446. data/lib/pubid/jcgm/scheme.rb +0 -60
  447. data/lib/pubid/jis/components/code.rb +0 -59
  448. data/lib/pubid/jis/identifiers/base.rb +0 -72
  449. data/lib/pubid/jis/scheme.rb +0 -49
  450. data/lib/pubid/nist/components/publisher.rb +0 -24
  451. data/lib/pubid/nist/scheme.rb +0 -199
  452. data/lib/pubid/oiml/scheme.rb +0 -46
  453. data/lib/pubid/plateau/scheme.rb +0 -45
  454. data/lib/pubid/rendering/base.rb +0 -73
  455. data/lib/pubid/rendering/common.rb +0 -211
  456. data/lib/pubid/rendering/format.rb +0 -25
  457. data/lib/pubid/sae/scheme.rb +0 -47
  458. data/lib/pubid/scheme.rb +0 -219
@@ -76,24 +76,12 @@ module Pubid
76
76
  if args[:draft_obj]
77
77
  self.draft_obj = args[:draft_obj]
78
78
  self.draft = args[:draft_obj].to_s
79
+ elsif args[:draft].is_a?(String)
80
+ self.draft_obj = Components::Draft.parse(args[:draft])
81
+ self.draft = draft_obj.to_s
79
82
  elsif args[:draft]
80
- # If draft is passed as string, try to create Draft object
81
- if args[:draft].is_a?(String)
82
- # Try to parse the string to extract version/revision
83
- if args[:draft] =~ /^D(\d+)(?:\.(\d+))?/
84
- version = $1
85
- revision = $2
86
- self.draft_obj = Components::Draft.new(version: version,
87
- revision: revision)
88
- else
89
- # Simple case - treat as version
90
- self.draft_obj = Components::Draft.new(version: args[:draft])
91
- end
92
- self.draft = draft_obj.to_s
93
- else
94
- self.draft_obj = args[:draft]
95
- self.draft = args[:draft].to_s
96
- end
83
+ self.draft_obj = args[:draft]
84
+ self.draft = args[:draft].to_s
97
85
  end
98
86
 
99
87
  # Set other attributes
@@ -122,328 +110,109 @@ module Pubid
122
110
  draft_obj.numeric_month
123
111
  end
124
112
 
125
- # Parse IEEE identifier string
113
+ # Parse IEEE identifier string.
114
+ #
115
+ # PreParser owns all regex/dispatch logic; this method is a thin
116
+ # orchestrator that consumes a PreParser::Result and routes to the
117
+ # correct builder.
126
118
  def self.parse(input)
127
- # Preprocessing: Convert comma-separated dual standards to "and" format
128
- # This must happen BEFORE the "and" check below
129
- # Pattern: "IEEE Std 960-1989, Std 1177-1989" -> "IEEE Std 960-1989 and IEEE Std 1177-1989"
130
- input = input.gsub(/(\d{4}),\s+Std\s/, '\1 and IEEE Std ')
131
-
132
- # Check for AIEE identifiers (but NOT those with parentheses which have relationships/adoptions)
133
- # AIEE has its own parser/builder for simple identifiers
134
- # AIEE inputs with parentheses are handled by IEEE parser for relationship/adoption parsing
135
- if input.start_with?("AIEE ") && !input.include?("(")
136
- return Aiee::Identifier.parse(input)
137
- end
138
-
139
- # Check for IEC/IEEE copublished patterns first (before other checks)
140
- if input.start_with?("IEC/IEEE ")
141
- return parse_single(input)
142
- end
143
-
144
- # Check for semicolon-separated dual identifiers (IEC-first patterns)
145
- # Pattern: "IEC 61523-3 First edition 2004-09; IEEE 1497"
146
- if input.include?("; ")
147
- parts = input.split("; ")
148
- if parts.length == 2
149
- # Try to parse both parts
150
- begin
151
- first = parse_single(parts[0].strip)
152
- second = parse_single(parts[1].strip)
153
-
154
- return Identifiers::DualPublished.new(
155
- first_identifier: first,
156
- second_identifier: second,
157
- )
158
- rescue Parslet::ParseFailed
159
- # If parsing fails, continue with normal flow
160
- end
161
- end
162
- end
163
-
164
- # PREPROCESS: Handle (R####) (Revision of...) pattern
165
- # Convert to single parenthetical: (Reaffirmed ####, Revision of...)
166
- # This allows parser to capture both in one parenthetical
167
- if input =~ /\(R(\d{4})\)\s*\(Revision of ([^)]+)\)/
168
- year = $1
169
- $2
170
- # Replace the two parentheticals with reaffirmed info extracted
171
- # Parse normally but capture year first
172
- input_modified = input.sub(
173
- /\(R(\d{4})\)\s*\(Revision of ([^)]+)\)/, "(Revision of \\2)"
174
- )
175
-
176
- # Parse the modified input
177
- result = parse_single(input_modified)
178
- # Add reaffirmed attribute
179
- if result.class.attributes.key?(:reaffirmed)
180
- result.reaffirmed = year
181
- end
182
- return result
183
- end
184
-
185
- # PREPROCESS: Handle (Reaffirmed ####) (Revision of...) pattern (full word format)
186
- # Pattern: "ANSI/IEEE Std 101-1987 (Reaffirmed 2010) (Revision of IEEE Std 101-1972)"
187
- if input =~ /\(Reaffirmed\s+(\d{4})\)\s*\(Revision of ([^)]+)\)/
188
- year = $1
189
- $2
190
- # Replace the two parentheticals
191
- input_modified = input.sub(
192
- /\(Reaffirmed\s+(\d{4})\)\s*\(Revision of ([^)]+)\)/, "(Revision of \\2)"
193
- )
194
-
195
- # Parse the modified input
196
- result = parse_single(input_modified)
197
- # Add reaffirmed attribute
198
- if result.class.attributes.key?(:reaffirmed)
199
- result.reaffirmed = year
200
- end
201
- return result
202
- end
203
-
204
- # NEW Session 174: Check for IRE dual published pattern
205
- # Pattern after preprocessing: "IEEE Std 218-1956 (R1980) (56 IRE 28.S2)"
206
- # First parenthetical: (Rxxx) reaffirmed
207
- # Second parenthetical: IRE identifier
208
- if /\(R\d{4}\)\s*\((\d+\s+IRE[^)]+)\)/.match?(input)
209
- main_part = input.split(" (R").first.strip # Get "IEEE Std 218-1956"
210
- reaffirmed_year = input.match(/\(R(\d{4})\)/)[1]
211
- ire_part = input.match(/\((\d+\s+IRE[^)]+)\)/)[1]
212
-
213
- begin
214
- # Parse main identifier
215
- ieee_id = parse_single(main_part)
216
- # Add reaffirmed year
217
- ieee_id.reaffirmed = reaffirmed_year if ieee_id.class.attributes.key?(:reaffirmed)
218
-
219
- # Parse IRE identifier
220
- ire_id = parse_single(ire_part)
221
-
222
- return Identifiers::DualPublished.new(
223
- first_identifier: ieee_id,
224
- second_identifier: ire_id,
225
- )
226
- rescue Parslet::ParseFailed
227
- # If parsing fails, fall through to regular processing
228
- end
229
- end
230
-
231
- # Check for space-separated dual identifiers (e.g., "IEC 62014-5 IEEE Std 1734-2011")
232
- # This must be checked before " and " pattern
233
- # Look for pattern where a second publisher appears after the first complete identifier
234
- # Publishers: IEEE, AIEE, ANSI, ASA, IEC, ISO, ASTM, NACE, NSF, ASHRAE, NCTA, AESC
235
- publishers = %w[IEEE AIEE ANSI ASA IEC ISO ASTM NACE NSF ASHRAE NCTA
236
- AESC]
237
-
238
- # Find all positions where publishers appear (but NOT inside parentheses)
239
- # Publishers inside parentheses are part of relationship clauses, not dual published patterns
240
- publisher_positions = []
241
- publishers.each do |pub|
242
- # Look for publisher at word boundaries (preceded by space or start of string)
243
- regex = /(?:^|\s)(#{Regexp.escape(pub)})(?:\s|\/)/
244
- input.scan(regex) do
245
- match_pos = Regexp.last_match.begin(1)
246
-
247
- # Check if this publisher is inside parentheses (relationship clause)
248
- # Count parens before this position
249
- before_match = input[0...match_pos]
250
- paren_count = before_match.count("(") - before_match.count(")")
251
-
252
- # Skip publishers inside parentheses - they're part of relationship clauses
253
- next if paren_count.positive?
254
-
255
- publisher_positions << { pos: match_pos, publisher: pub }
256
- end
257
- end
258
-
259
- # If we have 2 or more publishers at distinct positions (not co-publishers with /)
260
- if publisher_positions.length >= 2
261
- # Sort by position
262
- publisher_positions.sort_by! { |p| p[:pos] }
263
-
264
- # Check if they're not part of a co-published pattern (Publisher1/Publisher2)
265
- # by ensuring there's no slash between them
266
- first_pub = publisher_positions[0]
267
- second_pub = publisher_positions[1]
268
-
269
- # Get the substring between the two publishers
270
- between = input[first_pub[:pos]..(second_pub[:pos] - 1)]
271
-
272
- # If there's no slash and no " and ", this might be space-separated dual
273
- if !between.include?("/") && !between.include?(" and ")
274
- # Try to split at the second publisher position
275
- # Back up to find the space before the second publisher
276
- split_pos = second_pub[:pos]
277
- while split_pos.positive? && input[split_pos - 1] == " "
278
- split_pos -= 1
279
- end
280
-
281
- first_part = input[0...split_pos].strip
282
- second_part = input[split_pos..].strip
283
-
284
- # Try to parse both parts
285
- begin
286
- first = parse_single(first_part)
287
- second = parse_single(second_part)
288
-
289
- # Only treat as dual if both parse successfully
290
- return Identifiers::DualPublished.new(
291
- first_identifier: first,
292
- second_identifier: second,
293
- )
294
- rescue Parslet::ParseFailed
295
- # If parsing fails, continue with normal flow
296
- end
297
- end
298
- end
299
-
300
- # Check for dual published patterns with " and "
301
- if input.include?(" and ")
302
- # DON'T split if " and " is inside parentheses (likely a relationship clause)
303
- # Check if parentheses are balanced and " and " is inside them
304
- paren_count = 0
305
- and_outside_parens = false
306
- and_position = nil
307
-
308
- input.each_char.with_index do |char, i|
309
- paren_count += 1 if char == "("
310
- paren_count -= 1 if char == ")"
311
-
312
- # Check if " and " starts at this position and we're outside parens
313
- if paren_count.zero? && input[i..(i + 4)] == " and "
314
- and_outside_parens = true
315
- and_position = i
316
- break
317
- end
318
- end
319
-
320
- # Only split if " and " is outside parentheses
321
- if and_outside_parens && and_position
322
- # Split at the found position only (not at all " and " occurrences)
323
- first_part = input[0...and_position].strip
324
- second_part = input[(and_position + 5)..].strip
325
-
326
- # Parse each part separately
327
- first = parse_single(first_part)
328
- second = parse_single(second_part)
329
-
330
- return Identifiers::DualPublished.new(
331
- first_identifier: first,
332
- second_identifier: second,
333
- )
334
- end
335
- end
336
-
337
- # NEW Session 171: Check for dual published patterns with " & " (ampersand)
338
- if input.include?(" & ")
339
- # DON'T split if " & " is inside parentheses
340
- paren_count = 0
341
- ampersand_outside_parens = false
342
-
343
- input.each_char.with_index do |char, i|
344
- paren_count += 1 if char == "("
345
- paren_count -= 1 if char == ")"
346
-
347
- # Check if " & " starts at this position and we're outside parens
348
- if paren_count.zero? && input[i..(i + 2)] == " & "
349
- ampersand_outside_parens = true
350
- break
351
- end
352
- end
353
-
354
- # Only split if " & " is outside parentheses
355
- if ampersand_outside_parens
356
- parts = input.split(" & ")
357
- if parts.length == 2
358
- # Parse each part separately
359
- first = parse_single(parts[0].strip)
360
- second = parse_single(parts[1].strip)
361
-
362
- return Identifiers::DualPublished.new(
363
- first_identifier: first,
364
- second_identifier: second,
365
- )
366
- end
367
- end
368
- end
369
-
370
- # Special case: AIEE identifiers with ASA parenthetical references
371
- # Pattern: "AIEE No 18-1934 (ASA C55 1934)"
372
- if input.match?(/^AIEE\s+/) && input.include?("(") && input.include?("ASA")
373
- main_part = input.split("(").first.strip
374
- adoption_match = input.match(/\((ASA[^)]+)\)/)
375
-
376
- if adoption_match
377
- adoption_part = adoption_match.captures.first
378
- # Parse the main AIEE identifier
379
- begin
380
- aiee_id = parse_single(main_part)
381
- # Parse the ASA identifier
382
- asa_id = parse_single(adoption_part)
383
-
384
- return Identifiers::AdoptedStandard.new(
385
- ieee_identifier: aiee_id,
386
- adopted_identifier: asa_id,
387
- )
388
- rescue Parslet::ParseFailed
389
- # If parsing fails, fall through to regular processing
390
- end
391
- end
119
+ result = PreParser.preprocess(input)
120
+
121
+ case result.dispatch
122
+ when :aiee_simple
123
+ return Aiee::Identifier.parse(result.input)
124
+ when :iec_ieee_copublished
125
+ return parse_single(result.input)
126
+ when :dual_semicolon
127
+ return build_dual(result.parts)
128
+ when :dual_reaffirmed
129
+ return build_reaffirmed(result)
130
+ when :dual_ire
131
+ return build_dual_with_reaffirmed(result)
132
+ when :dual_space_separated
133
+ return build_dual(result.parts)
134
+ when :dual_and
135
+ return build_dual(result.parts)
136
+ when :dual_ampersand
137
+ return build_dual(result.parts)
138
+ when :aiee_asa_adoption
139
+ return build_aiee_asa_adoption(result.parts)
140
+ when :adopted
141
+ return build_adopted(result.parts)
142
+ else
143
+ parse_single(result.input)
392
144
  end
145
+ rescue Parslet::ParseFailed
146
+ parse_single(input)
147
+ end
393
148
 
394
- # Check for adopted standards (parenthetical adoptions)
395
- # Only consider it an adoption if the parenthetical content looks like an identifier
396
- if input.include?("(") && input.include?(")") && !input.start_with?("IEC/IEEE ")
397
- # Extract the part before parentheses and the adoption part
398
- main_part = input.split("(").first.strip
399
- adoption_match = input.match(/\(([^)]+)\)/)
400
- adoption_part = adoption_match&.captures&.first
401
-
402
- # Check if adoption_part looks like an identifier (contains publisher or type keywords)
403
- # BUT exclude revision/amendment/supersedes notes
404
- # AND exclude Pattern 4 relationship types
405
- if main_part && adoption_part &&
406
- !adoption_part.match?(/^\s*(Revision|Revison|Amendment|Corrigendum|Corrigenda|incorporates|Incorporating|Incorporates|Adoption|Supplement|Draft Amendment|DRAFT Amendment|Draft Revision|Reaffirmation|Redesignation|redesignated as|Supersedes|Supercedes|Includes|Previously designated as|Notebooks|Standard Newspaper)/i) &&
407
- (adoption_part.match?(/\b(ANSI|ISO|IEC|IEEE|AIEE|IRE|ASA|ASTM|CSA|ASME|NACE|NSF|ASHRAE|NCTA|AESC)\s/) ||
408
- adoption_part.match?(/^\s*(ANSI|ISO|IEC|IEEE|AIEE|IRE|ASA|ASTM|CSA|ASME|NACE|NSF|ASHRAE|NCTA|AESC)\b/) ||
409
- adoption_part.match?(/\bStd\s+\d+/))
410
- # Parse the main IEEE identifier
411
- ieee_id = parse_single(main_part)
149
+ # ---- dispatch constructors (used by parse) ----
412
150
 
413
- # Parse comma-separated adopted identifiers
414
- adopted_parts = adoption_part.split(",").map(&:strip)
415
- adopted_ids = adopted_parts.map do |part|
416
- if part.strip.start_with?("IEC")
417
- # Use IEC parser for IEC adoptions
418
- # Preprocess to convert "Edition X.Y" to IEC format
419
- # Pattern: "IEC 60255-24 Edition 2.0 2013-04" → "IEC 60255-24:2013-04 ED2.0"
420
- iec_part = part.dup
421
- # Replace " Edition X.Y YYYY-MM" (or similar) with ":YYYY-MM EDX.Y"
422
- iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s+([0-9-]+)/,
423
- ':\2 ED\1')
424
- # Replace " Edition X.Y" at end (no date)
425
- iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s*$/, ' ED\1')
426
- Pubid::Iec.parse(iec_part)
427
- elsif part.strip.start_with?("ANSI")
428
- # Use ANSI parser for ANSI adoptions
429
- Pubid::Ansi.parse(part)
430
- else
431
- # Use IEEE parser for other adoptions
432
- parse_single(part)
433
- end
434
- end
151
+ def self.build_dual(parts)
152
+ first = parse_single(parts[0])
153
+ second = parse_single(parts[1])
154
+ Identifiers::DualPublished.new(
155
+ first_identifier: first,
156
+ second_identifier: second,
157
+ )
158
+ end
159
+ private_class_method :build_dual
435
160
 
436
- return Identifiers::AdoptedStandard.new(
437
- ieee_identifier: ieee_id,
438
- adopted_identifiers: adopted_ids,
439
- )
161
+ def self.build_reaffirmed(result)
162
+ parsed = parse_single(result.input)
163
+ parsed.reaffirmed = result.metadata[:reaffirmed] if parsed.class.attributes.key?(:reaffirmed)
164
+ parsed
165
+ end
166
+ private_class_method :build_reaffirmed
167
+
168
+ def self.build_dual_with_reaffirmed(result)
169
+ ieee_id = parse_single(result.parts[0])
170
+ ieee_id.reaffirmed = result.metadata[:reaffirmed] if ieee_id.class.attributes.key?(:reaffirmed)
171
+ ire_id = parse_single(result.parts[1])
172
+ Identifiers::DualPublished.new(
173
+ first_identifier: ieee_id,
174
+ second_identifier: ire_id,
175
+ )
176
+ end
177
+ private_class_method :build_dual_with_reaffirmed
178
+
179
+ def self.build_aiee_asa_adoption(parts)
180
+ aiee_id = parse_single(parts[0])
181
+ asa_id = parse_single(parts[1])
182
+ Identifiers::AdoptedStandard.new(
183
+ ieee_identifier: aiee_id,
184
+ adopted_identifier: asa_id,
185
+ )
186
+ end
187
+ private_class_method :build_aiee_asa_adoption
188
+
189
+ def self.build_adopted(parts)
190
+ ieee_id = parse_single(parts[0])
191
+ adopted_parts = parts[1].split(",").map(&:strip)
192
+ adopted_ids = adopted_parts.map do |part|
193
+ if part.start_with?("IEC")
194
+ Pubid::Iec.parse(normalize_iec_adoption(part))
195
+ elsif part.start_with?("ANSI")
196
+ Pubid::Ansi.parse(part)
197
+ else
198
+ parse_single(part)
440
199
  end
441
- # If it doesn't look like an identifier, let the parser handle it as additional_parameters
442
200
  end
443
-
444
- # Fall back to single identifier parsing
445
- parse_single(input)
201
+ Identifiers::AdoptedStandard.new(
202
+ ieee_identifier: ieee_id,
203
+ adopted_identifiers: adopted_ids,
204
+ )
205
+ end
206
+ private_class_method :build_adopted
207
+
208
+ # "IEC 60255-24 Edition 2.0 2013-04" → "IEC 60255-24:2013-04 ED2.0"
209
+ def self.normalize_iec_adoption(part)
210
+ iec_part = part.dup
211
+ iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s+([0-9-]+)/, ':\2 ED\1')
212
+ iec_part.gsub!(/\s+Edition\s+([0-9.]+)\s*$/, ' ED\1')
213
+ iec_part
446
214
  end
215
+ private_class_method :normalize_iec_adoption
447
216
 
448
217
  # Parse a single IEEE identifier
449
218
  def self.parse_single(input)
@@ -457,133 +226,7 @@ module Pubid
457
226
  end
458
227
 
459
228
  def to_s
460
- parts = []
461
-
462
- # Publisher(s) - handle copublisher array properly
463
- if copublisher && !copublisher.empty?
464
- # Copublisher is an array, join all publishers with single slash
465
- parts << [publisher, *copublisher].join("/")
466
- else
467
- parts << publisher
468
- end
469
-
470
- # Draft status
471
- parts << draft_status if draft_status
472
-
473
- # Type - only render for IEEE/AIEE publishers, and only for non-projects
474
- # Must come BEFORE code
475
- should_render_type = publisher&.match?(/^(IEEE|AIEE)/)
476
-
477
- if should_render_type && !typed_stage&.project_status && type && !type.to_s.strip.empty? && type != "P"
478
- # Non-project with explicit type (Std, No, etc.)
479
- type_str = type.dup
480
- # Remove P prefix if somehow present
481
- type_str = type_str.sub(/^P/, "") if type_str.start_with?("P")
482
- parts << type_str unless type_str.strip.empty?
483
- end
484
-
485
- # Code - with P prefix for projects (concatenated, not separated)
486
- if code_obj
487
- result = code_obj.to_s
488
-
489
- # Prepend P if this is a project AND code doesn't already have P
490
- if typed_stage&.project_status && should_render_type && !result.start_with?("P")
491
- result = "P#{result}"
492
- end
493
-
494
- # Only attach year to code if there's no edition, no month, and no draft
495
- result += "-#{year}" if year && !draft_obj && !edition && !month
496
-
497
- # Append draft to code - with or without space based on original format
498
- if draft_obj
499
- result += space_before_draft ? " #{draft_obj}" : draft_obj.to_s
500
- end
501
-
502
- # Append interpretation notation (/INT)
503
- result += "/INT" if interpretation
504
-
505
- # Append conformance notation (/ConformanceNN-YYYY)
506
- if conf_number
507
- result += "/Conformance#{conf_number}"
508
- result += "-#{conf_year}" if conf_year
509
- end
510
-
511
- # Append ASHRAE joint publication (/ASHRAE Guideline NN-YYYY)
512
- if ashrae_number
513
- result += "/ASHRAE Guideline #{ashrae_number}"
514
- result += "-#{ashrae_year}" if ashrae_year
515
- end
516
-
517
- # Append IEEE cross-reference (/C62.22.1-1996)
518
- result += crossref if crossref
519
-
520
- parts << result
521
- elsif should_render_type && typed_stage&.project_status
522
- # No code but is a project - add standalone P
523
- parts << "P"
524
- end
525
-
526
- # Edition - with year if present (IEC style)
527
- if edition
528
- edition_str = "Edition #{edition}"
529
- if year
530
- edition_str += " #{year}"
531
- edition_str += "-#{edition_month}" if edition_month
532
- end
533
- parts << edition_str
534
- end
535
-
536
- # Build the main identifier (without month yet)
537
- result = parts.join(" ")
538
-
539
- # Month/Day - append directly to avoid extra space before comma
540
- if month
541
- # Format: ", Month Day, Year" or ", Month, Year"
542
- result += ", #{month}"
543
- result += " #{day}" if day
544
- if year && !edition
545
- # Add comma after month if year follows
546
- result += ", #{year}"
547
- end
548
- end
549
-
550
- # Add parenthetical content if present
551
- # Handle multiple parenthetical clauses (reaffirmed + relationships/revision)
552
- parentheticals = []
553
-
554
- reaff = reaffirmed
555
- if reaff && !reaff.to_s.strip.empty?
556
- parentheticals << "(R#{reaff})"
557
- end
558
-
559
- # Then add relationships/revision/amendment as second parenthetical
560
- if parenthetical_content
561
- parentheticals << "(#{parenthetical_content})"
562
- elsif relationships && !relationships.empty?
563
- # Render relationships (multiple separated by /)
564
- relationship_str = relationships.join(" / ")
565
- parentheticals << "(#{relationship_str})"
566
- elsif revision_of
567
- parentheticals << "(Revision of IEEE Std #{revision_of})"
568
- elsif amendment_to
569
- parentheticals << "(Amendment to IEEE Std #{amendment_to})"
570
- elsif adoption
571
- parentheticals << "(Adoption of #{adoption})"
572
- elsif note && !note.to_s.strip.empty?
573
- # Only add note if it doesn't duplicate other content
574
- parentheticals << "(#{note})"
575
- end
576
-
577
- # Append all parentheticals with space separation
578
- result += " #{parentheticals.join(' ')}" unless parentheticals.empty?
579
-
580
- # Book nickname - outside parentheses in square brackets
581
- result += " [#{nickname}]" if nickname && !nickname.to_s.strip.empty?
582
-
583
- # Redline suffix
584
- result += " - Redline" if redline
585
-
586
- result
229
+ render(format: :human)
587
230
  end
588
231
  end
589
232
  end
@@ -21,13 +21,7 @@ module Pubid
21
21
  ].freeze
22
22
 
23
23
  def to_s
24
- return base_identifier.to_s unless base_identifier
25
-
26
- # Format: BASE/ConformanceNN-YEAR
27
- result = base_identifier.to_s
28
- result += "/Conformance#{conf_number}" if conf_number
29
- result += "-#{conf_year}" if conf_year
30
- result
24
+ render(format: :human)
31
25
  end
32
26
  end
33
27
  end
@@ -21,15 +21,7 @@ module Pubid
21
21
  ].freeze
22
22
 
23
23
  def to_s
24
- return super unless base_identifier
25
-
26
- # Format: BASE/Cor NUMBER-YEAR or BASE/Cor. NUMBER-YEAR
27
- result = base_identifier.to_s
28
- result += "/Cor"
29
- result += ". " if cor_number # Add period and space for formal format
30
- result += cor_number if cor_number
31
- result += "-#{cor_year}" if cor_year
32
- result
24
+ render(format: :human)
33
25
  end
34
26
  end
35
27
  end
@@ -33,13 +33,7 @@ module Pubid
33
33
  end
34
34
 
35
35
  def to_s
36
- # Format: IEEE_IDENTIFIER/CSA CSA_IDENTIFIER
37
- # The CSA identifier should render with "CSA" prefix
38
- csa_str = csa_identifier.to_s
39
- # Ensure CSA prefix is present
40
- csa_str = "CSA #{csa_str}" unless csa_str.start_with?("CSA", "CAN/")
41
-
42
- "#{ieee_identifier}/#{csa_str}"
36
+ render(format: :human)
43
37
  end
44
38
 
45
39
  def self.parse(string)
@@ -10,7 +10,7 @@ module Pubid
10
10
  attribute :second_identifier, Base, polymorphic: true
11
11
 
12
12
  def to_s
13
- "#{first_identifier} and #{second_identifier}"
13
+ render(format: :human)
14
14
  end
15
15
  end
16
16
  end
@@ -15,7 +15,7 @@ module Pubid
15
15
  attribute :second_identifier, Base, polymorphic: true
16
16
 
17
17
  def to_s
18
- "#{first_identifier} and #{second_identifier}"
18
+ render(format: :human)
19
19
  end
20
20
 
21
21
  def publisher
@@ -14,12 +14,7 @@ module Pubid
14
14
  attribute :date_info, :string # Date information like "(10/07)"
15
15
 
16
16
  def to_s
17
- result = "IEC/IEEE"
18
- result += " #{copublished_number}" if copublished_number
19
- result += draft_info if draft_info
20
- result += " IEC:#{iec_year}" if iec_year
21
- result += " #{date_info}" if date_info
22
- result
17
+ render(format: :human)
23
18
  end
24
19
  end
25
20
  end