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
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Jcgm
5
+ # Human-readable renderer for JCGM identifiers.
6
+ #
7
+ # Produces strings like:
8
+ # "JCGM 100:2008"
9
+ # "JCGM 100:2008/Amd 1:2023"
10
+ # "JCGM GUM-6:2020"
11
+ #
12
+ # The renderer is registered as the `:human` format in the JCGM format
13
+ # registry and invoked via `render(format: :human)`.
14
+ class Renderer < ::Pubid::Renderers::Base
15
+ def render(context: nil, **opts)
16
+ id = @id
17
+
18
+ case id
19
+ when Identifiers::Amendment
20
+ render_amendment(id, context)
21
+ when Identifiers::GumGuide
22
+ render_gum_guide(id, context)
23
+ else
24
+ render_single(id)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def render_single(id)
31
+ parts = [id.publisher_portion]
32
+ parts << id.number_portion unless id.number_portion.empty?
33
+ result = parts.join(" ")
34
+ result += id.language_portion if id.languages&.any?
35
+ result
36
+ end
37
+
38
+ def render_amendment(id, context)
39
+ result = id.base_identifier.to_s if id.base_identifier
40
+ result += "/Amd"
41
+ result += " #{id.iteration.render(context:)}" if id.iteration
42
+ result += ":#{id.date}" if id.date
43
+ result
44
+ end
45
+
46
+ def render_gum_guide(id, context)
47
+ parts = []
48
+ parts << id.publisher.publisher if id.publisher
49
+ parts << "GUM-#{id.gum_number.render(context:)}" if id.gum_number
50
+
51
+ result = parts.join(" ")
52
+ result += ":#{id.date}" if id.date
53
+ result += gum_language_portion(id) if id.languages&.any?
54
+ result
55
+ end
56
+
57
+ def gum_language_portion(id)
58
+ return "" unless id.languages&.any?
59
+
60
+ codes = id.languages.map do |lang|
61
+ lang.original_code || lang.code
62
+ end
63
+
64
+ "(#{codes.join('/')})"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -37,11 +37,7 @@ module Pubid
37
37
  end
38
38
 
39
39
  def to_s
40
- parts = [publisher_portion]
41
- parts << number_portion unless number_portion.empty?
42
- result = parts.join(" ")
43
- result += language_portion
44
- result
40
+ render(format: :human)
45
41
  end
46
42
  end
47
43
  end
@@ -37,9 +37,8 @@ module Pubid
37
37
  parts << "-#{sp}"
38
38
  end
39
39
 
40
- if identifier.date
41
- year = identifier.date.year
42
- parts << year.to_s
40
+ if identifier.date&.is_a?(::Pubid::Components::Date) && identifier.date.present?
41
+ parts << identifier.date.render(context: URN_CONTEXT)
43
42
  elsif maybe(:year)
44
43
  parts << maybe(:year).to_s
45
44
  end
@@ -95,9 +94,8 @@ module Pubid
95
94
  parts << iter
96
95
  end
97
96
 
98
- if identifier.date
99
- year = identifier.date.year
100
- parts << year.to_s
97
+ if identifier.date&.is_a?(::Pubid::Components::Date) && identifier.date.present?
98
+ parts << identifier.date.render(context: URN_CONTEXT)
101
99
  end
102
100
  else
103
101
  parts << "unknown"
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Jcgm
5
+ # Parses JCGM URNs back into identifiers.
6
+ #
7
+ # UrnGenerator emits: `urn:jcgm:{number}:{year}`.
8
+ #
9
+ # Examples:
10
+ # - urn:jcgm:200:2012 → JCGM 200:2012
11
+ # - urn:jcgm:100:2008 → JCGM 100:2008
12
+ class UrnParser < Pubid::UrnParser::Base
13
+ def parse_urn(urn)
14
+ body = strip_namespace(urn)
15
+ parts = split_parts(body)
16
+ number, year = parts
17
+ text = "JCGM #{number}"
18
+ text += ":#{year}" if year
19
+ flavor_parse(text)
20
+ end
21
+ end
22
+ end
23
+ end
data/lib/pubid/jcgm.rb CHANGED
@@ -7,21 +7,62 @@ module Pubid
7
7
  autoload :Identifier, "#{__dir__}/jcgm/identifier"
8
8
  autoload :Identifiers, "#{__dir__}/jcgm/identifiers"
9
9
  autoload :Parser, "#{__dir__}/jcgm/parser"
10
- autoload :Scheme, "#{__dir__}/jcgm/scheme"
10
+ autoload :Renderer, "#{__dir__}/jcgm/renderer"
11
11
  autoload :SingleIdentifier, "#{__dir__}/jcgm/single_identifier"
12
12
  autoload :SupplementIdentifier, "#{__dir__}/jcgm/supplement_identifier"
13
13
  autoload :UrnGenerator, "#{__dir__}/jcgm/urn_generator"
14
+ autoload :UrnParser, "#{__dir__}/jcgm/urn_parser"
14
15
 
15
16
  # Parse a JCGM identifier string
16
17
  # @param identifier [String] the identifier string to parse
17
18
  # @return [Identifier] the parsed identifier
18
19
  def self.parse(identifier)
19
20
  parser = Parser.new
20
- builder = Builder.new(Scheme)
21
+ builder = Builder.new
21
22
 
22
23
  parsed = parser.parse(identifier)
23
24
  builder.build(parsed)
24
25
  end
26
+
27
+ # Per-flavor format registry: inherits global formats, overrides :human
28
+ Identifier.format_registry = FormatRegistry.new(parent: Identifier.format_registry)
29
+ Identifier.format_registry.register(:human, renderer: Jcgm::Renderer)
30
+
31
+ # Auto-discover all identifier types from the Identifiers namespace
32
+ # @return [Array<Class>] identifier classes that define a self.type Hash
33
+ def self.identifier_types
34
+ @identifier_types ||= Identifiers.constants
35
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
36
+ .select { |c| c.is_a?(Class) && c.singleton_methods(false).include?(:type) }
37
+ .select { |c| c.type.is_a?(Hash) }
38
+ end
39
+
40
+ # Build typed stage index from identifier types
41
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
42
+ def self.all_typed_stages
43
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
44
+ if klass.const_defined?(:TYPED_STAGES)
45
+ klass.const_get(:TYPED_STAGES)
46
+ else
47
+ []
48
+ end
49
+ end
50
+ end
51
+
52
+ # Lookup: type code -> identifier class
53
+ # @param code [String, Symbol] the type key to find
54
+ # @return [Class, nil] the matching identifier class
55
+ def self.locate_type(code)
56
+ identifier_types.find { |t| t.type[:key].to_s == code.to_s }
57
+ end
58
+
59
+ # Lookup: abbreviation -> typed stage
60
+ # @param abbr [String, Symbol] the abbreviation to find
61
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
62
+ def self.locate_stage(abbr)
63
+ abbr_str = abbr.to_s.upcase
64
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
65
+ end
25
66
  end
26
67
 
27
68
  # Register this flavor with the Pubid registry
@@ -8,29 +8,37 @@ module Pubid
8
8
  end
9
9
 
10
10
  def build(data)
11
- # Handle supplement case first
12
- if data[:amendment]
13
- return build_amendment(data)
14
- elsif data[:explanation]
15
- return build_explanation(data)
16
- end
17
-
18
- # Build regular identifier
19
- build_single_identifier(data)
11
+ # Handle supplement case first; the SYMBOL clause (if any) attaches to
12
+ # the outermost identifier, be it the base or the supplement.
13
+ identifier = if data[:amendment]
14
+ build_amendment(data)
15
+ elsif data[:explanation]
16
+ build_explanation(data)
17
+ elsif data[:corrigendum]
18
+ build_corrigendum(data)
19
+ else
20
+ build_single_identifier(data)
21
+ end
22
+ attach_symbol(identifier, data)
20
23
  end
21
24
 
22
25
  private
23
26
 
24
- def build_single_identifier(data)
25
- # Build code component
26
- code = build_code(data)
27
+ # nil => no SYMBOL clause; "" => bare "SYMBOL" keyword; otherwise value.
28
+ def attach_symbol(identifier, data)
29
+ identifier.symbol = data[:symbol_value].to_s if data[:symbol_present]
30
+ identifier
31
+ end
27
32
 
28
- # Extract other attributes
33
+ def build_single_identifier(data)
29
34
  attrs = {
30
- code: code,
35
+ series: data[:series].to_s,
36
+ number: data[:number].to_s,
37
+ parts: extract_part_strings(data[:parts]),
31
38
  year: data[:year]&.to_i,
32
39
  language: data[:language]&.to_s,
33
- all_parts: data[:all_parts] ? true : false,
40
+ all_parts: (true if data[:all_parts]),
41
+ reaffirmed: (true if data[:reaffirmed]),
34
42
  }
35
43
 
36
44
  # Determine identifier class from type
@@ -59,6 +67,7 @@ module Pubid
59
67
  base: base,
60
68
  number: amd_data[:amd_number].to_i,
61
69
  year: amd_data[:amd_year].to_i,
70
+ reaffirmed: (true if amd_data[:amd_reaffirmed]),
62
71
  )
63
72
  end
64
73
 
@@ -77,47 +86,30 @@ module Pubid
77
86
  )
78
87
  end
79
88
 
80
- def build_code(data)
81
- series = data[:series].to_s
82
- number_str = data[:number].to_s
83
- number = number_str.to_i
84
-
85
- # Extract parts with both integer values and original strings
86
- parts_result = extract_parts(data[:parts])
87
- parts = parts_result[:parts]
88
- part_strings = parts_result[:part_strings]
89
-
90
- Components::Code.new(
91
- series: series,
92
- number: number,
93
- parts: parts,
94
- number_string: number_str,
95
- part_strings: part_strings,
89
+ def build_corrigendum(data)
90
+ corr_data = data[:corrigendum]
91
+
92
+ # Build base document (without supplement)
93
+ base_data = data.except(:corrigendum)
94
+ base = build_single_identifier(base_data)
95
+
96
+ # Build corrigendum
97
+ Identifiers::Corrigendum.new(
98
+ base: base,
99
+ number: corr_data[:corr_number].to_i,
100
+ year: corr_data[:corr_year].to_i,
101
+ reaffirmed: (true if corr_data[:corr_reaffirmed]),
96
102
  )
97
103
  end
98
104
 
99
- def extract_parts(parts_data)
100
- parts = []
101
- part_strings = []
102
-
103
- return { parts: parts, part_strings: part_strings } unless parts_data
104
-
105
- # parts_data is an array of hashes with :part key
106
- if parts_data.is_a?(Array)
107
- parts_data.each do |part_hash|
108
- if part_hash[:part]
109
- part_str = part_hash[:part].to_s
110
- parts << part_str.to_i
111
- part_strings << part_str
112
- end
113
- end
114
- elsif parts_data.is_a?(Hash) && parts_data[:part]
115
- part_str = parts_data[:part].to_s
116
- parts << part_str.to_i
117
- part_strings << part_str
105
+ # parts_data is an array of `{ part: "1" }` hashes (or a single hash for
106
+ # a one-level part); return the part numbers as strings.
107
+ def extract_part_strings(parts_data)
108
+ case parts_data
109
+ when Array then parts_data.filter_map { |h| h[:part]&.to_s }
110
+ when Hash then [parts_data[:part]&.to_s].compact
111
+ else []
118
112
  end
119
-
120
- { parts: parts, part_strings: part_strings }
121
113
  end
122
114
  end
123
115
  end
@@ -2,60 +2,146 @@
2
2
 
3
3
  module Pubid
4
4
  module Jis
5
- module Identifier
5
+ # Base class for every JIS identifier AND the flavor's parse/create entry
6
+ # point — mirrors Pubid::Iso::Identifier. Concrete identifiers under
7
+ # Pubid::Jis::Identifiers descend from this class, so a parsed JIS id is an
8
+ # instance of Pubid::Jis::Identifier.
9
+ class Identifier < ::Pubid::Identifier
10
+ # JIS keeps its number flat at the top level (string, to preserve leading
11
+ # zeros like "0205"), with the division letter in `series` and any
12
+ # multi-level part numbers in `parts`. Supplements override `number` with
13
+ # their integer sequence number; the document number then lives on `base`.
14
+ attribute :number, :string
15
+ attribute :series, :string # Division letter A-Z
16
+ attribute :parts, :string, collection: true # Optional multi-level parts
17
+ attribute :year, :integer
18
+ attribute :language, :string # "E" or "J"
19
+ # Boolean flags carry no default, so they stay nil (and are omitted from
20
+ # the serialized hash) unless actually set true.
21
+ attribute :all_parts, :boolean
22
+ # Reaffirmation (再確認): a trailing "R" on the year marks an edition
23
+ # that was reaffirmed without revision (e.g. ":2019R").
24
+ attribute :reaffirmed, :boolean
25
+ # Graphical-symbol sub-reference (JIS Z 8210 etc.): the value after
26
+ # "SYMBOL". nil means no SYMBOL clause; an empty string means a bare
27
+ # "SYMBOL" keyword with no value.
28
+ attribute :symbol, :string
29
+
30
+ # Polymorphic type map for lutaml::Model key_value (de)serialization:
31
+ # maps each subclass's polymorphic_name to its class name so a stored
32
+ # hash rebuilds the correct identifier type via from_hash.
33
+ JIS_TYPE_MAP = {
34
+ "pubid:jis:japanese-industrial-standard" =>
35
+ "Pubid::Jis::Identifiers::JapaneseIndustrialStandard",
36
+ "pubid:jis:standard" => "Pubid::Jis::Identifiers::Standard",
37
+ "pubid:jis:technical-report" =>
38
+ "Pubid::Jis::Identifiers::TechnicalReport",
39
+ "pubid:jis:technical-specification" =>
40
+ "Pubid::Jis::Identifiers::TechnicalSpecification",
41
+ "pubid:jis:amendment" => "Pubid::Jis::Identifiers::Amendment",
42
+ "pubid:jis:corrigendum" => "Pubid::Jis::Identifiers::Corrigendum",
43
+ "pubid:jis:explanation" => "Pubid::Jis::Identifiers::Explanation",
44
+ }.freeze
45
+
46
+ key_value do
47
+ map "_type", to: :_type, polymorphic_map: JIS_TYPE_MAP
48
+ map "series", to: :series
49
+ map "number", to: :number
50
+ map "parts", to: :parts
51
+ map "year", to: :year
52
+ map "language", to: :language
53
+ map "all_parts", to: :all_parts
54
+ map "reaffirmed", to: :reaffirmed
55
+ # render_empty keeps a bare "SYMBOL" (empty-string value) in the hash so
56
+ # it round-trips distinctly from "no symbol" (nil).
57
+ map "symbol", to: :symbol, render_empty: true
58
+ end
59
+
60
+ # Publisher is always "JIS". A plain constant (not a `publisher` method)
61
+ # so it doesn't shadow the inherited lutaml `publisher` attribute, which
62
+ # would otherwise fail serialization type validation.
63
+ PUBLISHER = "JIS"
64
+
65
+ def all_parts?
66
+ all_parts == true
67
+ end
68
+
69
+ def reaffirmed?
70
+ reaffirmed == true
71
+ end
72
+
73
+ # Render a year with its reaffirmation marker, e.g. "2019R".
74
+ def year_with_reaffirmation
75
+ "#{year}#{'R' if reaffirmed?}"
76
+ end
77
+
78
+ # Render the trailing " SYMBOL[ <value>]" clause, or "" when absent.
79
+ def symbol_suffix
80
+ return "" if symbol.nil?
81
+
82
+ symbol.empty? ? " SYMBOL" : " SYMBOL #{symbol}"
83
+ end
84
+
85
+ # The rendered document code, e.g. "B 0205-1" (series, number, parts).
86
+ # A convenience for rendering; the underlying data is the flat
87
+ # series/number/parts attributes.
88
+ def code
89
+ result = "#{series} #{number}"
90
+ result += parts.map { |p| "-#{p}" }.join if parts&.any?
91
+ result
92
+ end
93
+
94
+ # Comparison with all_parts logic
95
+ # When either identifier has all_parts=true, compare only series and number
96
+ def ==(other)
97
+ return false unless other.is_a?(Identifier)
98
+
99
+ if all_parts? || other.all_parts?
100
+ # Compare only series and number, ignore year, parts, all_parts
101
+ return series == other.series && number == other.number
102
+ end
103
+
104
+ # Normal full comparison
105
+ series == other.series &&
106
+ number == other.number &&
107
+ (parts || []) == (other.parts || []) &&
108
+ year == other.year &&
109
+ language == other.language &&
110
+ all_parts? == other.all_parts? &&
111
+ reaffirmed? == other.reaffirmed? &&
112
+ symbol == other.symbol
113
+ end
114
+
115
+ # Basic string representation. Delegates to renderer.
116
+ def to_s(**opts)
117
+ render(format: :human, **opts)
118
+ end
119
+
120
+ # Dispatch deserialization to the concrete identifier class named by the
121
+ # stored `_type`, so `from_hash` rebuilds e.g. a Corrigendum rather than a
122
+ # bare Pubid::Jis::Identifier. lutaml resolves `_type` only for validation,
123
+ # not instantiation, so we route to the mapped subclass and let its own
124
+ # (inherited) from_hash do the actual work.
125
+ def self.from_hash(data, options = {})
126
+ type = data["_type"] || data[:_type]
127
+ klass_name = JIS_TYPE_MAP[type]
128
+ if klass_name
129
+ klass = Object.const_get(klass_name)
130
+ return klass.from_hash(data, options) unless klass == self
131
+ end
132
+ super
133
+ end
134
+
6
135
  # Parse a JIS identifier string into an identifier object
7
136
  # @param identifier [String] The JIS identifier string to parse
8
- # @return [Identifiers::Base] The appropriate identifier object
9
- # @raise [Parslet::ParseFailed] If parsing fails
137
+ # @return [Identifier] The appropriate identifier object
138
+ # @raise [RuntimeError] If parsing fails
10
139
  def self.parse(identifier)
11
140
  parsed = Parser.parse(identifier)
12
141
  Builder.build(parsed)
13
142
  rescue Parslet::ParseFailed => e
14
143
  raise "Failed to parse JIS identifier '#{identifier}': #{e.message}"
15
144
  end
16
-
17
- # Factory mirroring pubid 1.x's `Pubid::Jis::Identifier.create` API.
18
- #
19
- # JIS uses a different attribute schema from most flavors — `series`
20
- # (single letter A–Z), `number` (integer), `parts` (integer collection),
21
- # `year` (integer), `language`. Publisher is hardcoded "JIS" on the
22
- # instance and not a constructor kwarg; supplying `:publisher` is
23
- # silently ignored.
24
- #
25
- # Type dispatch: :jis → Standard, :tr → TechnicalReport,
26
- # :ts → TechnicalSpecification. Default → Standard.
27
- def self.create(type: nil, **opts)
28
- klass = if type
29
- safe_locate_klass(type) || Identifiers::Standard
30
- else
31
- Identifiers::Standard
32
- end
33
- klass.new(**coerce_create_attrs(opts))
34
- end
35
-
36
- # JIS Scheme raises ArgumentError on miss; wrap.
37
- def self.safe_locate_klass(type)
38
- Scheme.locate_identifier_klass_by_type_code(type)
39
- rescue ArgumentError
40
- nil
41
- end
42
-
43
- def self.coerce_create_attrs(opts)
44
- attrs = {}
45
- attrs[:series] = opts[:series].to_s if opts[:series]
46
- attrs[:number] = opts[:number].to_i if opts[:number]
47
- if opts[:parts]
48
- attrs[:parts] = Array(opts[:parts]).map(&:to_i)
49
- end
50
- attrs[:code] = opts[:code] if opts[:code]
51
- attrs[:year] = opts[:year].to_i if opts[:year]
52
- attrs[:language] = opts[:language].to_s if opts[:language]
53
- attrs[:all_parts] = opts[:all_parts] if opts.key?(:all_parts)
54
- # TODO(create-shim): :publisher silently ignored (JIS hardcodes
55
- # "JIS"); supplement subclasses not yet wired through.
56
- attrs
57
- end
58
- private_class_method :safe_locate_klass, :coerce_create_attrs
59
145
  end
60
146
  end
61
147
  end
@@ -8,7 +8,7 @@ module Pubid
8
8
  # Example: JIS A 0001:1999/AMD 1:2000
9
9
  class Amendment < SupplementIdentifier
10
10
  def supplement_notation
11
- "AMD #{number}:#{year}"
11
+ "AMD #{number}:#{year_with_reaffirmation}"
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Jis
5
+ module Identifiers
6
+ # Corrigendum identifier type
7
+ # Format: {base}/CORRIGENDUM {number}:{year}
8
+ # Example: JIS B 3700-11:1996/CORRIGENDUM 1:2002
9
+ class Corrigendum < SupplementIdentifier
10
+ def supplement_notation
11
+ "CORRIGENDUM #{number}:#{year_with_reaffirmation}"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -19,7 +19,8 @@ module Pubid
19
19
  ].freeze
20
20
 
21
21
  def self.type
22
- { key: :jis, title: "Japanese Industrial Standard", short: "JIS" }
22
+ { key: :jis,
23
+ web: :japanese_industrial_standard, title: "Japanese Industrial Standard", short: "JIS" }
23
24
  end
24
25
  end
25
26
  end
@@ -19,7 +19,8 @@ module Pubid
19
19
  ].freeze
20
20
 
21
21
  def self.type
22
- { key: :tr, title: "Technical Report", short: "TR" }
22
+ { key: :tr,
23
+ web: :technical_report, title: "Technical Report", short: "TR" }
23
24
  end
24
25
 
25
26
  def type_prefix
@@ -19,7 +19,8 @@ module Pubid
19
19
  ].freeze
20
20
 
21
21
  def self.type
22
- { key: :ts, title: "Technical Specification", short: "TS" }
22
+ { key: :ts,
23
+ web: :technical_specification, title: "Technical Specification", short: "TS" }
23
24
  end
24
25
 
25
26
  def type_prefix
@@ -4,7 +4,7 @@ module Pubid
4
4
  module Jis
5
5
  module Identifiers
6
6
  autoload :Amendment, "#{__dir__}/identifiers/amendment"
7
- autoload :Base, "#{__dir__}/identifiers/base"
7
+ autoload :Corrigendum, "#{__dir__}/identifiers/corrigendum"
8
8
  autoload :Explanation, "#{__dir__}/identifiers/explanation"
9
9
  autoload :JapaneseIndustrialStandard,
10
10
  "#{__dir__}/identifiers/japanese_industrial_standard"
@@ -43,9 +43,12 @@ module Pubid
43
43
 
44
44
  rule(:parts) { part.repeat(0).as(:parts) }
45
45
 
46
+ # Reaffirmation marker (再確認): trailing "R" on a year
47
+ rule(:reaffirmed) { str("R").maybe.as(:reaffirmed) }
48
+
46
49
  # Year
47
50
  rule(:year) do
48
- colon >> digits.as(:year)
51
+ colon >> digits.as(:year) >> reaffirmed
49
52
  end
50
53
 
51
54
  # Language code
@@ -68,7 +71,8 @@ module Pubid
68
71
  space >>
69
72
  digits.as(:amd_number) >>
70
73
  colon >>
71
- digits.as(:amd_year)
74
+ digits.as(:amd_year) >>
75
+ str("R").maybe.as(:amd_reaffirmed)
72
76
  end
73
77
 
74
78
  # Explanation supplement
@@ -78,9 +82,30 @@ module Pubid
78
82
  (space >> digits.as(:expl_number)).maybe
79
83
  end
80
84
 
81
- # Supplements (AMD or EXPL, only one for JIS)
85
+ # Corrigendum supplement
86
+ rule(:corrigendum) do
87
+ str("/") >>
88
+ (str("CORRIGENDUM") | str("CORR")).as(:corr_type) >>
89
+ space >>
90
+ digits.as(:corr_number) >>
91
+ colon >>
92
+ digits.as(:corr_year) >>
93
+ str("R").maybe.as(:corr_reaffirmed)
94
+ end
95
+
96
+ # Supplements (AMD, EXPL or CORRIGENDUM, only one for JIS)
82
97
  rule(:supplement) do
83
- amendment.as(:amendment) | explanation.as(:explanation)
98
+ amendment.as(:amendment) | explanation.as(:explanation) |
99
+ corrigendum.as(:corrigendum)
100
+ end
101
+
102
+ # Graphical-symbol sub-reference (e.g. JIS Z 8210 safety signs):
103
+ # "SYMBOL <id>" where <id> runs to the end of the string and may be a
104
+ # number, an alphanumeric code or a free-text phrase. The keyword may
105
+ # also appear bare with no value.
106
+ rule(:symbol_clause) do
107
+ space >> str("SYMBOL").as(:symbol_present) >>
108
+ (space >> match["^\n"].repeat(1).as(:symbol_value)).maybe
84
109
  end
85
110
 
86
111
  # Main identifier
@@ -95,7 +120,8 @@ module Pubid
95
120
  year.maybe >>
96
121
  language.maybe >>
97
122
  all_parts.maybe >>
98
- supplement.maybe
123
+ supplement.maybe >>
124
+ symbol_clause.maybe
99
125
  end
100
126
 
101
127
  rule(:root) { identifier }