pubid 2.0.0.pre.alpha.2 → 2.0.0.pre.alpha.4

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 (473) 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 +4 -55
  6. data/lib/pubid/amca/identifiers/base.rb +58 -47
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -21
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -17
  9. data/lib/pubid/amca/identifiers/standard.rb +0 -4
  10. data/lib/pubid/amca/renderer.rb +82 -0
  11. data/lib/pubid/amca/single_identifier.rb +0 -23
  12. data/lib/pubid/amca/urn_generator.rb +2 -1
  13. data/lib/pubid/amca/urn_parser.rb +28 -0
  14. data/lib/pubid/amca.rb +42 -1
  15. data/lib/pubid/ansi/builder.rb +5 -3
  16. data/lib/pubid/ansi/identifier.rb +1 -43
  17. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  18. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  19. data/lib/pubid/ansi/renderer.rb +53 -0
  20. data/lib/pubid/ansi/single_identifier.rb +2 -31
  21. data/lib/pubid/ansi/urn_generator.rb +3 -38
  22. data/lib/pubid/ansi/urn_parser.rb +23 -0
  23. data/lib/pubid/ansi.rb +38 -3
  24. data/lib/pubid/api/builder.rb +33 -74
  25. data/lib/pubid/api/identifier.rb +5 -52
  26. data/lib/pubid/api/identifiers/base.rb +2 -14
  27. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  28. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  29. data/lib/pubid/api/identifiers/mpms.rb +0 -20
  30. data/lib/pubid/api/identifiers/publication.rb +0 -2
  31. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  32. data/lib/pubid/api/identifiers/specification.rb +0 -2
  33. data/lib/pubid/api/identifiers/standard.rb +0 -2
  34. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  35. data/lib/pubid/api/identifiers/typeless_standard.rb +0 -16
  36. data/lib/pubid/api/identifiers.rb +18 -0
  37. data/lib/pubid/api/renderer.rb +89 -0
  38. data/lib/pubid/api/single_identifier.rb +5 -20
  39. data/lib/pubid/api/urn_generator.rb +0 -18
  40. data/lib/pubid/api/urn_parser.rb +35 -0
  41. data/lib/pubid/api.rb +51 -5
  42. data/lib/pubid/ashrae/builder.rb +3 -3
  43. data/lib/pubid/ashrae/identifier.rb +7 -55
  44. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  45. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  46. data/lib/pubid/ashrae/identifiers/base.rb +29 -15
  47. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  48. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  49. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  50. data/lib/pubid/ashrae/parser.rb +4 -0
  51. data/lib/pubid/ashrae/renderer.rb +117 -0
  52. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  53. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  54. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  55. data/lib/pubid/ashrae.rb +46 -1
  56. data/lib/pubid/asme/components/code.rb +10 -2
  57. data/lib/pubid/asme/identifier.rb +0 -46
  58. data/lib/pubid/asme/identifiers/base.rb +0 -60
  59. data/lib/pubid/asme/renderer.rb +66 -0
  60. data/lib/pubid/asme/single_identifier.rb +3 -1
  61. data/lib/pubid/asme/urn_parser.rb +31 -0
  62. data/lib/pubid/asme.rb +42 -1
  63. data/lib/pubid/astm/components/code.rb +9 -0
  64. data/lib/pubid/{jis → astm}/components.rb +1 -1
  65. data/lib/pubid/astm/identifier.rb +0 -77
  66. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  67. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  68. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  69. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  70. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  71. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  72. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  73. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  74. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  75. data/lib/pubid/astm/identifiers.rb +18 -0
  76. data/lib/pubid/astm/renderer.rb +172 -0
  77. data/lib/pubid/astm/single_identifier.rb +3 -11
  78. data/lib/pubid/astm/urn_parser.rb +30 -0
  79. data/lib/pubid/astm.rb +39 -27
  80. data/lib/pubid/bsi/builder.rb +21 -12
  81. data/lib/pubid/bsi/identifier.rb +5 -85
  82. data/lib/pubid/bsi/identifiers/addendum_document.rb +2 -36
  83. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +8 -48
  84. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +8 -39
  85. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +2 -55
  86. data/lib/pubid/bsi/identifiers/amendment.rb +2 -22
  87. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -6
  88. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  89. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -87
  90. data/lib/pubid/bsi/identifiers/committee_document.rb +0 -16
  91. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -87
  92. data/lib/pubid/bsi/identifiers/corrigendum.rb +2 -10
  93. data/lib/pubid/bsi/identifiers/detailed_specification.rb +0 -36
  94. data/lib/pubid/bsi/identifiers/disc.rb +0 -29
  95. data/lib/pubid/bsi/identifiers/draft_document.rb +2 -46
  96. data/lib/pubid/bsi/identifiers/electronic_book.rb +2 -38
  97. data/lib/pubid/bsi/identifiers/expert_commentary.rb +2 -18
  98. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +0 -47
  99. data/lib/pubid/bsi/identifiers/flex.rb +0 -35
  100. data/lib/pubid/bsi/identifiers/handbook.rb +1 -15
  101. data/lib/pubid/bsi/identifiers/index.rb +0 -32
  102. data/lib/pubid/bsi/identifiers/method.rb +0 -41
  103. data/lib/pubid/bsi/identifiers/national_annex.rb +4 -29
  104. data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -6
  105. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +2 -54
  106. data/lib/pubid/bsi/identifiers/published_document.rb +2 -54
  107. data/lib/pubid/bsi/identifiers/section.rb +0 -30
  108. data/lib/pubid/bsi/identifiers/set.rb +3 -20
  109. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +0 -9
  110. data/lib/pubid/bsi/identifiers/supplement_document.rb +2 -24
  111. data/lib/pubid/bsi/identifiers/supplementary_index.rb +0 -46
  112. data/lib/pubid/bsi/identifiers/technical_specification.rb +2 -47
  113. data/lib/pubid/bsi/identifiers/test_method.rb +0 -32
  114. data/lib/pubid/bsi/identifiers/value_added_publication.rb +2 -17
  115. data/lib/pubid/bsi/identifiers.rb +0 -1
  116. data/lib/pubid/bsi/renderer.rb +1050 -0
  117. data/lib/pubid/bsi/single_identifier.rb +33 -78
  118. data/lib/pubid/bsi/urn_generator.rb +2 -3
  119. data/lib/pubid/bsi/urn_parser.rb +52 -0
  120. data/lib/pubid/bsi.rb +232 -2
  121. data/lib/pubid/builder/base.rb +57 -10
  122. data/lib/pubid/bundled_identifier.rb +0 -1
  123. data/lib/pubid/ccsds/builder.rb +4 -3
  124. data/lib/pubid/ccsds/identifier.rb +53 -68
  125. data/lib/pubid/ccsds/identifiers/base.rb +11 -61
  126. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  127. data/lib/pubid/ccsds/parser.rb +4 -2
  128. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  129. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  130. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  131. data/lib/pubid/ccsds.rb +39 -1
  132. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  133. data/lib/pubid/cen_cenelec/identifier.rb +11 -40
  134. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +9 -4
  135. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +0 -10
  136. data/lib/pubid/cen_cenelec/identifiers/base.rb +2 -45
  137. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  138. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +0 -27
  140. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +0 -15
  141. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +2 -8
  143. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  144. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +0 -4
  145. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  146. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  147. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  148. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  149. data/lib/pubid/cen_cenelec/single_identifier.rb +9 -90
  150. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  151. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  152. data/lib/pubid/cen_cenelec.rb +172 -1
  153. data/lib/pubid/cie/components/code.rb +8 -0
  154. data/lib/pubid/cie/identifier.rb +10 -57
  155. data/lib/pubid/cie/single_identifier.rb +4 -4
  156. data/lib/pubid/cie/urn_parser.rb +28 -0
  157. data/lib/pubid/cie.rb +47 -1
  158. data/lib/pubid/components/adoption.rb +104 -0
  159. data/lib/pubid/components/code.rb +22 -8
  160. data/lib/pubid/components/date.rb +23 -16
  161. data/lib/pubid/components/edition.rb +9 -6
  162. data/lib/pubid/components/iteration.rb +32 -0
  163. data/lib/pubid/components/language.rb +6 -4
  164. data/lib/pubid/components/locality.rb +10 -1
  165. data/lib/pubid/components/publisher.rb +9 -6
  166. data/lib/pubid/components/relationship.rb +151 -0
  167. data/lib/pubid/components/stage.rb +5 -14
  168. data/lib/pubid/components/supplement.rb +184 -0
  169. data/lib/pubid/components/type.rb +5 -15
  170. data/lib/pubid/components/typed_stage.rb +10 -11
  171. data/lib/pubid/components.rb +4 -1
  172. data/lib/pubid/core/update_codes.rb +28 -7
  173. data/lib/pubid/csa/identifier.rb +9 -59
  174. data/lib/pubid/csa/identifiers/base.rb +0 -123
  175. data/lib/pubid/csa/identifiers/cec.rb +0 -103
  176. data/lib/pubid/csa/identifiers/series.rb +0 -104
  177. data/lib/pubid/csa/renderer.rb +292 -0
  178. data/lib/pubid/csa/single_identifier.rb +1 -1
  179. data/lib/pubid/csa/urn_generator.rb +1 -1
  180. data/lib/pubid/csa/urn_parser.rb +33 -0
  181. data/lib/pubid/csa.rb +46 -1
  182. data/lib/pubid/etsi/components/code.rb +10 -9
  183. data/lib/pubid/etsi/components/version.rb +0 -5
  184. data/lib/pubid/etsi/identifier.rb +4 -55
  185. data/lib/pubid/etsi/identifiers/base.rb +31 -27
  186. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +1 -11
  187. data/lib/pubid/etsi/renderer.rb +42 -0
  188. data/lib/pubid/etsi/urn_parser.rb +34 -0
  189. data/lib/pubid/etsi.rb +44 -1
  190. data/lib/pubid/export/exporter.rb +4 -46
  191. data/lib/pubid/export/flavor_exporter.rb +111 -278
  192. data/lib/pubid/export.rb +0 -6
  193. data/lib/pubid/identifier.rb +92 -18
  194. data/lib/pubid/identifier_metadata.rb +1 -1
  195. data/lib/pubid/idf/builder.rb +3 -3
  196. data/lib/pubid/idf/identifier.rb +7 -66
  197. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  198. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  199. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  200. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  201. data/lib/pubid/idf/parser.rb +3 -2
  202. data/lib/pubid/idf/renderer.rb +84 -0
  203. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  204. data/lib/pubid/idf/urn_generator.rb +4 -39
  205. data/lib/pubid/idf/urn_parser.rb +25 -0
  206. data/lib/pubid/idf.rb +55 -1
  207. data/lib/pubid/iec/builder.rb +46 -64
  208. data/lib/pubid/iec/components/code.rb +8 -32
  209. data/lib/pubid/iec/components/publisher.rb +0 -1
  210. data/lib/pubid/iec/components.rb +14 -0
  211. data/lib/pubid/iec/identifier.rb +251 -213
  212. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  213. data/lib/pubid/iec/identifiers/base.rb +5 -33
  214. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  215. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  216. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +23 -26
  217. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  218. data/lib/pubid/iec/identifiers/fragment_identifier.rb +35 -24
  219. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  220. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  221. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  222. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  223. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  224. data/lib/pubid/iec/identifiers/sheet_identifier.rb +17 -11
  225. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  226. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  227. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  228. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  229. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  230. data/lib/pubid/iec/identifiers/test_report_form.rb +3 -35
  231. data/lib/pubid/iec/identifiers/vap_identifier.rb +24 -21
  232. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  233. data/lib/pubid/iec/identifiers/working_document.rb +2 -50
  234. data/lib/pubid/iec/identifiers.rb +30 -0
  235. data/lib/pubid/iec/parser.rb +13 -12
  236. data/lib/pubid/iec/renderer.rb +254 -0
  237. data/lib/pubid/iec/single_identifier.rb +6 -12
  238. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  239. data/lib/pubid/iec/urn_generator.rb +3 -3
  240. data/lib/pubid/iec/urn_parser.rb +3 -3
  241. data/lib/pubid/iec.rb +43 -67
  242. data/lib/pubid/ieee/builder.rb +12 -12
  243. data/lib/pubid/ieee/components/code.rb +8 -0
  244. data/lib/pubid/ieee/components/draft.rb +14 -0
  245. data/lib/pubid/ieee/components/relationship.rb +5 -149
  246. data/lib/pubid/ieee/identifier.rb +5 -52
  247. data/lib/pubid/ieee/identifiers/adopted_standard.rb +0 -9
  248. data/lib/pubid/ieee/identifiers/base.rb +221 -556
  249. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +0 -10
  250. data/lib/pubid/ieee/identifiers/corrigendum.rb +0 -12
  251. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +0 -10
  252. data/lib/pubid/ieee/identifiers/dual_identifier.rb +0 -4
  253. data/lib/pubid/ieee/identifiers/dual_published.rb +0 -4
  254. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +0 -9
  255. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +0 -10
  256. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  257. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +0 -18
  258. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +0 -6
  259. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  260. data/lib/pubid/ieee/identifiers/redlined_standard.rb +0 -7
  261. data/lib/pubid/ieee/identifiers/si_standard.rb +0 -38
  262. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  263. data/lib/pubid/ieee/pre_parser.rb +301 -0
  264. data/lib/pubid/ieee/renderer.rb +307 -0
  265. data/lib/pubid/ieee/urn_parser.rb +34 -0
  266. data/lib/pubid/ieee.rb +66 -1
  267. data/lib/pubid/ieee_debug.rb +0 -1
  268. data/lib/pubid/iho/builder.rb +2 -2
  269. data/lib/pubid/iho/identifier.rb +7 -59
  270. data/lib/pubid/iho/identifiers/base.rb +64 -31
  271. data/lib/pubid/iho/parser.rb +3 -3
  272. data/lib/pubid/iho/renderer.rb +30 -0
  273. data/lib/pubid/iho/urn_generator.rb +2 -2
  274. data/lib/pubid/iho/urn_parser.rb +58 -0
  275. data/lib/pubid/iho.rb +52 -1
  276. data/lib/pubid/iso/builder.rb +55 -53
  277. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  278. data/lib/pubid/iso/components/code.rb +7 -19
  279. data/lib/pubid/iso/components/publisher.rb +10 -8
  280. data/lib/pubid/iso/components.rb +2 -4
  281. data/lib/pubid/iso/identifier.rb +219 -252
  282. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  283. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  284. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  285. data/lib/pubid/iso/identifiers/data.rb +0 -1
  286. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  287. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  288. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  289. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  290. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  291. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  292. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  293. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  294. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  295. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  296. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  297. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  298. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  299. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  300. data/lib/pubid/iso/identifiers.rb +0 -1
  301. data/lib/pubid/iso/normalizer.rb +89 -0
  302. data/lib/pubid/iso/parser.rb +22 -4
  303. data/lib/pubid/iso/single_identifier.rb +0 -4
  304. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  305. data/lib/pubid/iso/urn_generator.rb +66 -182
  306. data/lib/pubid/iso/urn_parser.rb +12 -7
  307. data/lib/pubid/iso.rb +177 -2
  308. data/lib/pubid/itu/builder.rb +0 -12
  309. data/lib/pubid/itu/components/code.rb +9 -7
  310. data/lib/pubid/itu/components/sector.rb +15 -4
  311. data/lib/pubid/itu/components/series.rb +0 -4
  312. data/lib/pubid/itu/components.rb +11 -0
  313. data/lib/pubid/itu/identifier.rb +4 -116
  314. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  315. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  316. data/lib/pubid/itu/identifiers/base.rb +124 -128
  317. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  318. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  319. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  320. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  321. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  322. data/lib/pubid/itu/urn_parser.rb +23 -0
  323. data/lib/pubid/itu.rb +44 -1
  324. data/lib/pubid/jcgm/builder.rb +16 -8
  325. data/lib/pubid/jcgm/identifier.rb +0 -43
  326. data/lib/pubid/jcgm/identifiers/amendment.rb +0 -9
  327. data/lib/pubid/jcgm/identifiers/gum_guide.rb +0 -12
  328. data/lib/pubid/jcgm/renderer.rb +68 -0
  329. data/lib/pubid/jcgm/single_identifier.rb +0 -8
  330. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  331. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  332. data/lib/pubid/jcgm.rb +43 -2
  333. data/lib/pubid/jis/builder.rb +44 -52
  334. data/lib/pubid/jis/identifier.rb +120 -46
  335. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  336. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  337. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  338. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  339. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  340. data/lib/pubid/jis/identifiers.rb +1 -1
  341. data/lib/pubid/jis/parser.rb +31 -5
  342. data/lib/pubid/jis/renderer.rb +69 -0
  343. data/lib/pubid/jis/single_identifier.rb +6 -12
  344. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  345. data/lib/pubid/jis/urn_parser.rb +23 -0
  346. data/lib/pubid/jis.rb +42 -2
  347. data/lib/pubid/nist/builder.rb +63 -1871
  348. data/lib/pubid/nist/caster.rb +1272 -0
  349. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  350. data/lib/pubid/nist/components/code.rb +9 -20
  351. data/lib/pubid/nist/components/supplement.rb +2 -2
  352. data/lib/pubid/nist/components.rb +0 -1
  353. data/lib/pubid/nist/identifier.rb +8 -60
  354. data/lib/pubid/nist/identifiers/base.rb +564 -492
  355. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  356. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -1
  357. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  358. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  359. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  360. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -8
  361. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  362. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +15 -24
  363. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  364. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  365. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  366. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  367. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  368. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  369. data/lib/pubid/nist/identifiers/report.rb +4 -2
  370. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  371. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  372. data/lib/pubid/nist/identifiers.rb +1 -0
  373. data/lib/pubid/nist/parser.rb +62 -452
  374. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  375. data/lib/pubid/nist/preprocessor.rb +428 -0
  376. data/lib/pubid/nist/renderer.rb +43 -0
  377. data/lib/pubid/nist/router.rb +148 -0
  378. data/lib/pubid/nist/series/base.rb +58 -0
  379. data/lib/pubid/nist/series/crpl.rb +13 -0
  380. data/lib/pubid/nist/series/fips.rb +14 -0
  381. data/lib/pubid/nist/series/ir.rb +60 -0
  382. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  383. data/lib/pubid/nist/series/mono.rb +19 -0
  384. data/lib/pubid/nist/series/ncstar.rb +20 -0
  385. data/lib/pubid/nist/series.rb +49 -0
  386. data/lib/pubid/nist/supplement_identifier.rb +3 -1
  387. data/lib/pubid/nist/urn_parser.rb +67 -0
  388. data/lib/pubid/nist.rb +86 -4
  389. data/lib/pubid/oiml/builder.rb +21 -3
  390. data/lib/pubid/oiml/components/code.rb +17 -0
  391. data/lib/pubid/oiml/identifier.rb +40 -46
  392. data/lib/pubid/oiml/identifiers/annex.rb +13 -46
  393. data/lib/pubid/oiml/identifiers/errata.rb +15 -0
  394. data/lib/pubid/oiml/identifiers.rb +1 -1
  395. data/lib/pubid/oiml/parser.rb +59 -12
  396. data/lib/pubid/oiml/renderer.rb +171 -0
  397. data/lib/pubid/oiml/single_identifier.rb +61 -42
  398. data/lib/pubid/oiml/supplement_identifier.rb +31 -17
  399. data/lib/pubid/oiml/urn_generator.rb +0 -8
  400. data/lib/pubid/oiml/urn_parser.rb +22 -0
  401. data/lib/pubid/oiml.rb +42 -1
  402. data/lib/pubid/plateau/identifier.rb +4 -55
  403. data/lib/pubid/plateau/identifiers/base.rb +45 -36
  404. data/lib/pubid/plateau/identifiers/handbook.rb +0 -6
  405. data/lib/pubid/plateau/identifiers/technical_report.rb +0 -4
  406. data/lib/pubid/plateau/renderer.rb +51 -0
  407. data/lib/pubid/plateau/supplement_identifier.rb +0 -4
  408. data/lib/pubid/plateau/urn_parser.rb +43 -0
  409. data/lib/pubid/plateau.rb +43 -1
  410. data/lib/pubid/renderers/directives_renderer.rb +22 -8
  411. data/lib/pubid/renderers/guide_renderer.rb +4 -2
  412. data/lib/pubid/renderers/human_readable.rb +18 -7
  413. data/lib/pubid/rendering/context.rb +28 -19
  414. data/lib/pubid/rendering.rb +0 -3
  415. data/lib/pubid/sae/components/date.rb +8 -0
  416. data/lib/pubid/sae/components/type.rb +5 -1
  417. data/lib/pubid/sae/identifier.rb +4 -35
  418. data/lib/pubid/sae/identifiers/base.rb +26 -31
  419. data/lib/pubid/sae/renderer.rb +36 -0
  420. data/lib/pubid/sae/urn_generator.rb +2 -10
  421. data/lib/pubid/sae/urn_parser.rb +36 -0
  422. data/lib/pubid/sae.rb +42 -1
  423. data/lib/pubid/urn_generator/base.rb +12 -12
  424. data/lib/pubid/urn_parser/base.rb +81 -0
  425. data/lib/pubid/urn_parser/errors.rb +9 -0
  426. data/lib/pubid/urn_parser.rb +14 -0
  427. data/lib/pubid/version.rb +1 -1
  428. data/lib/pubid.rb +45 -7
  429. data/lib/tasks/export.rake +6 -5
  430. data/lib/tasks/website-data.json +1940 -1882
  431. metadata +75 -45
  432. data/lib/pubid/amca/scheme.rb +0 -16
  433. data/lib/pubid/ansi/scheme.rb +0 -15
  434. data/lib/pubid/api/scheme.rb +0 -66
  435. data/lib/pubid/ashrae/scheme.rb +0 -53
  436. data/lib/pubid/asme/scheme.rb +0 -37
  437. data/lib/pubid/astm/scheme.rb +0 -55
  438. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  439. data/lib/pubid/bsi/scheme.rb +0 -243
  440. data/lib/pubid/ccsds/scheme.rb +0 -57
  441. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  442. data/lib/pubid/cie/scheme.rb +0 -64
  443. data/lib/pubid/components/factory.rb +0 -50
  444. data/lib/pubid/csa/scheme.rb +0 -44
  445. data/lib/pubid/etsi/scheme.rb +0 -42
  446. data/lib/pubid/export/data_class_exporter.rb +0 -59
  447. data/lib/pubid/export/ieee_exporter.rb +0 -78
  448. data/lib/pubid/export/itu_exporter.rb +0 -66
  449. data/lib/pubid/export/nist_exporter.rb +0 -64
  450. data/lib/pubid/export/registry_exporter.rb +0 -90
  451. data/lib/pubid/export/scheme_exporter.rb +0 -70
  452. data/lib/pubid/identifier_registry.rb +0 -198
  453. data/lib/pubid/idf/scheme.rb +0 -61
  454. data/lib/pubid/iec/scheme.rb +0 -71
  455. data/lib/pubid/ieee/scheme.rb +0 -90
  456. data/lib/pubid/iho/scheme.rb +0 -29
  457. data/lib/pubid/iso/identifiers/base.rb +0 -115
  458. data/lib/pubid/iso/scheme.rb +0 -193
  459. data/lib/pubid/itu/scheme.rb +0 -174
  460. data/lib/pubid/jcgm/scheme.rb +0 -60
  461. data/lib/pubid/jis/components/code.rb +0 -59
  462. data/lib/pubid/jis/identifiers/base.rb +0 -72
  463. data/lib/pubid/jis/scheme.rb +0 -49
  464. data/lib/pubid/nist/components/publisher.rb +0 -24
  465. data/lib/pubid/nist/scheme.rb +0 -199
  466. data/lib/pubid/oiml/identifiers/base.rb +0 -36
  467. data/lib/pubid/oiml/scheme.rb +0 -46
  468. data/lib/pubid/plateau/scheme.rb +0 -45
  469. data/lib/pubid/rendering/base.rb +0 -73
  470. data/lib/pubid/rendering/common.rb +0 -211
  471. data/lib/pubid/rendering/format.rb +0 -25
  472. data/lib/pubid/sae/scheme.rb +0 -47
  473. data/lib/pubid/scheme.rb +0 -219
@@ -77,14 +77,21 @@ module Pubid
77
77
  end
78
78
 
79
79
  def build_supplement(parsed_hash)
80
- # Determine supplement type
80
+ marker = parsed_hash[:trailing_marker].to_s if parsed_hash[:trailing_marker]
81
+
82
+ # Determine supplement type. The trailing word ("Amendment"/"Errata")
83
+ # selects the class; the concrete class then carries the word via
84
+ # #supplement_type, so only the `trailing` flag needs storing.
81
85
  supplement_class = if parsed_hash[:annex_letter] || parsed_hash[:annex_marker]
82
86
  Identifiers::Annex
87
+ elsif marker == "Errata"
88
+ Identifiers::Errata
83
89
  else
84
90
  Identifiers::Amendment
85
91
  end
86
92
 
87
93
  supplement = supplement_class.new
94
+ supplement.trailing = true if marker
88
95
 
89
96
  # Recursively parse base identifier
90
97
  if parsed_hash[:base_identifier]
@@ -103,6 +110,13 @@ module Pubid
103
110
  supplement.language = extract_language(parsed_hash[:language]) if parsed_hash[:language]
104
111
  supplement.letter = parsed_hash[:annex_letter].to_s if parsed_hash[:annex_letter]
105
112
 
113
+ # Annex with no year of its own but a dated base ("R 60:2017 Annexes"):
114
+ # the year belongs to the base and must render glued to it.
115
+ if supplement.is_a?(Identifiers::Annex) && !year_value &&
116
+ supplement.base_identifier&.date
117
+ supplement.year_on_base = true
118
+ end
119
+
106
120
  # Track if supplement itself was parsed with Edition format
107
121
  if parsed_hash[:edition_format]
108
122
  supplement.parsed_format = "long"
@@ -119,8 +133,8 @@ module Pubid
119
133
 
120
134
  identifier = identifier_class.new
121
135
 
122
- # Handle code (number-part-subpart) specially
123
- if parsed_hash[:number] || parsed_hash[:part] || parsed_hash[:subpart]
136
+ # Handle code (number-part-subpart-suffix) specially
137
+ if parsed_hash[:number] || parsed_hash[:part] || parsed_hash[:subpart] || parsed_hash[:code_suffix]
124
138
  code_attrs = {}
125
139
  if parsed_hash[:number]
126
140
  code_attrs[:number] =
@@ -131,6 +145,10 @@ module Pubid
131
145
  code_attrs[:subpart] =
132
146
  parsed_hash[:subpart].to_s
133
147
  end
148
+ if parsed_hash[:code_suffix]
149
+ code_attrs[:suffix] = parsed_hash[:code_suffix].to_s
150
+ code_attrs[:space_suffix] = true if parsed_hash.key?(:space_suffix)
151
+ end
134
152
  identifier.code = Components::Code.new(**code_attrs)
135
153
  end
136
154
 
@@ -3,17 +3,34 @@
3
3
  module Pubid
4
4
  module Oiml
5
5
  module Components
6
+ # Code component for OIML identifiers.
7
+ #
8
+ # Stays independent of Pubid::Components::Code because OIML uses
9
+ # +number+ as the primary field (shared Code uses +value+). The
10
+ # shape is otherwise compatible; a future rename of +number+ →
11
+ # +value+ would let this become a subclass.
6
12
  class Code < Lutaml::Model::Serializable
7
13
  attribute :number, :string
8
14
  attribute :part, :string
9
15
  attribute :subpart, :string
16
+ # Free-form trailing suffix glued to the code, e.g. "sup", "A",
17
+ # "erratum", "GUM 1", "ISO3930". Preserved verbatim for round-trip.
18
+ attribute :suffix, :string
19
+ # When true the suffix is space-separated ("D 1 Brochure") rather than
20
+ # the default dash ("R 60-sup").
21
+ attribute :space_suffix, :boolean, default: false
10
22
 
11
23
  def to_s
12
24
  result = number.to_s
13
25
  result += "-#{part}" if part
14
26
  result += "-#{subpart}" if subpart
27
+ result += "#{space_suffix ? ' ' : '-'}#{suffix}" if suffix
15
28
  result
16
29
  end
30
+
31
+ def render(context: nil)
32
+ to_s
33
+ end
17
34
  end
18
35
  end
19
36
  end
@@ -3,59 +3,53 @@
3
3
  module Pubid
4
4
  module Oiml
5
5
  class Identifier < Pubid::Identifier
6
- def to_urn
7
- UrnGenerator.new(self).generate
8
- end
9
-
10
- # Factory mirroring pubid 1.x's `Pubid::Oiml::Identifier.create` API.
11
- # Default subclass is {Identifiers::Recommendation}.
12
- TYPE_KEY_TO_KLASS = {
13
- recommendation: "Recommendation",
14
- document: "Document",
15
- guide: "Guide",
16
- vocabulary: "Vocabulary",
17
- basic_publication: "BasicPublication",
18
- expert_report: "ExpertReport",
19
- seminar_report: "SeminarReport",
20
- annex: "Annex",
6
+ # Maps each concrete identifier's polymorphic_name => class name, so
7
+ # key_value (de)serialization can re-instantiate the correct subclass
8
+ # from the `_type` discriminator. Kept in sync with the Identifiers
9
+ # namespace by a spec assertion (see spec/pubid/oiml/to_hash_spec.rb).
10
+ OIML_TYPE_MAP = {
11
+ "pubid:oiml:recommendation" => "Pubid::Oiml::Identifiers::Recommendation",
12
+ "pubid:oiml:basic-publication" => "Pubid::Oiml::Identifiers::BasicPublication",
13
+ "pubid:oiml:document" => "Pubid::Oiml::Identifiers::Document",
14
+ "pubid:oiml:guide" => "Pubid::Oiml::Identifiers::Guide",
15
+ "pubid:oiml:vocabulary" => "Pubid::Oiml::Identifiers::Vocabulary",
16
+ "pubid:oiml:expert-report" => "Pubid::Oiml::Identifiers::ExpertReport",
17
+ "pubid:oiml:seminar-report" => "Pubid::Oiml::Identifiers::SeminarReport",
18
+ "pubid:oiml:amendment" => "Pubid::Oiml::Identifiers::Amendment",
19
+ "pubid:oiml:errata" => "Pubid::Oiml::Identifiers::Errata",
20
+ "pubid:oiml:annex" => "Pubid::Oiml::Identifiers::Annex",
21
21
  }.freeze
22
22
 
23
- def self.create(type: nil, **opts)
24
- klass = resolve_create_class(type)
25
- klass.new(**coerce_create_attrs(opts))
26
- end
27
-
28
- def self.resolve_create_class(type)
29
- return Identifiers::Recommendation if type.nil?
30
-
31
- klass_name = TYPE_KEY_TO_KLASS[type.to_sym]
32
- raise ArgumentError, "Unknown OIML type: #{type.inspect}" unless klass_name
33
-
34
- Identifiers.const_get(klass_name)
23
+ # The base Pubid::Identifier no longer auto-maps attributes, so OIML must
24
+ # declare its own key_value mapping. SingleIdentifier and
25
+ # SupplementIdentifier (siblings) add their disjoint attribute deltas on
26
+ # top of this shared block. `type` is deliberately NOT mapped: OIML's
27
+ # `type` is a String-returning method (e.g. "R"), incompatible with the
28
+ # inherited Components::Type attribute — and the `_type` discriminator
29
+ # already pins the concrete subclass (and thus the type letter).
30
+ key_value do
31
+ map "_type", to: :_type, polymorphic_map: OIML_TYPE_MAP
32
+ map "language", to: :language
33
+ map "parsed_format", to: :parsed_format
35
34
  end
36
35
 
37
- def self.coerce_create_attrs(opts)
38
- attrs = { publisher: (opts[:publisher] || "OIML").to_s }
39
-
40
- if opts[:code].is_a?(Pubid::Oiml::Components::Code)
41
- attrs[:code] = opts[:code]
42
- elsif opts[:code] || opts[:number]
43
- attrs[:code] = Pubid::Oiml::Components::Code.new(
44
- number: (opts[:number] || opts[:code])&.to_s,
45
- part: opts[:part]&.to_s,
46
- subpart: opts[:subpart]&.to_s,
47
- )
36
+ # lutaml's polymorphic_map only validates `_type` on deserialization; it
37
+ # does not re-instantiate the concrete subclass. Route by `_type` so
38
+ # `Pubid::Oiml::Identifier.from_hash(h)` returns the right class (and its
39
+ # nested base_identifier), mirroring Pubid::Iso::Identifier.from_hash.
40
+ def self.from_hash(data, options = {})
41
+ type = data["_type"] || data[:_type]
42
+ klass_name = OIML_TYPE_MAP[type]
43
+ if klass_name
44
+ klass = Object.const_get(klass_name)
45
+ return klass.from_hash(data, options) unless klass == self
48
46
  end
47
+ super
48
+ end
49
49
 
50
- if (v = opts[:year])
51
- attrs[:date] = Pubid::Components::Date.new(year: v.to_s)
52
- end
53
- %i[stage iteration language edition].each do |k|
54
- attrs[k] = opts[k].to_s unless opts[k].nil?
55
- end
56
- attrs
50
+ def to_urn
51
+ UrnGenerator.new(self).generate
57
52
  end
58
- private_class_method :resolve_create_class, :coerce_create_attrs
59
53
  end
60
54
  end
61
55
  end
@@ -4,57 +4,24 @@ module Pubid
4
4
  module Oiml
5
5
  module Identifiers
6
6
  class Annex < SupplementIdentifier
7
- attribute :letter, :string # For "Annex A", "Annex B", etc.
7
+ attribute :letter, :string # For "Annex A", "Annex B", "Annex B-C"
8
+ # True when the publication year is glued to the base ("OIML R 60:2017
9
+ # Annexes") rather than the marker ("OIML R 60 Annexes:2017"); drives
10
+ # exact round-trip in the renderer.
11
+ attribute :year_on_base, :boolean, default: false
12
+
13
+ key_value do
14
+ map "letter", to: :letter
15
+ map "year_on_base", to: :year_on_base
16
+ end
8
17
 
9
18
  def supplement_type
10
19
  letter ? "Annex #{letter}" : "Annexes"
11
20
  end
12
21
 
13
- def to_s(format: nil)
14
- # Determine base format from its parsed_format
15
- base_format = if base_identifier.class.attributes.key?(:parsed_format) && base_identifier.parsed_format == "long"
16
- :long
17
- else
18
- :short
19
- end
20
-
21
- # Use format parameter or annex's own parsed_format
22
- annex_format = if format
23
- format
24
- elsif self.class.attributes.key?(:parsed_format) && parsed_format == "long"
25
- :long
26
- else
27
- :short
28
- end
29
-
30
- # Annexes have different pattern than amendments
31
- base_str = base_identifier.to_s(format: base_format)
32
- result = base_str.sub(/:.*/, "").sub(/\s+Edition\s+\d{4}/, "").sub(
33
- /\(.*\)/, ""
34
- ).strip
35
- if letter
36
- # Specific annex: "OIML R 60 Annex A Edition 2013 (E)"
37
- result += " Annex #{letter}"
38
-
39
- result += " Edition #{year}" if year
40
-
41
- # Supplements ALWAYS use space before language
42
-
43
- else
44
- # General annexes: "OIML R 60 Annexes Edition 2021 (E)" or "OIML R 60 Annexes:2021 (E)"
45
- result += " Annexes"
46
-
47
- if year
48
- result += annex_format == :long ? " Edition #{year}" : ":#{year}"
49
- elsif base_identifier.date
50
- result += annex_format == :long ? " Edition #{base_identifier.date.year}" : ":#{base_identifier.date.year}"
51
- end
52
-
53
- # Supplements ALWAYS use space before language
54
-
55
- end
56
- result += " (#{language})" if language
57
- result
22
+ def to_s(format: nil, **opts)
23
+ @requested_format = format
24
+ render(format: :human, **opts)
58
25
  end
59
26
  end
60
27
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Oiml
5
+ module Identifiers
6
+ # Errata supplement, used by the trailing-word shorthand
7
+ # "OIML R 126:2015 Errata" (the publication year lives on the base).
8
+ class Errata < SupplementIdentifier
9
+ def supplement_type
10
+ "Errata"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -5,9 +5,9 @@ module Pubid
5
5
  module Identifiers
6
6
  autoload :Amendment, "#{__dir__}/identifiers/amendment"
7
7
  autoload :Annex, "#{__dir__}/identifiers/annex"
8
- autoload :Base, "#{__dir__}/identifiers/base"
9
8
  autoload :BasicPublication, "#{__dir__}/identifiers/basic_publication"
10
9
  autoload :Document, "#{__dir__}/identifiers/document"
10
+ autoload :Errata, "#{__dir__}/identifiers/errata"
11
11
  autoload :ExpertReport, "#{__dir__}/identifiers/expert_report"
12
12
  autoload :Guide, "#{__dir__}/identifiers/guide"
13
13
  autoload :Recommendation, "#{__dir__}/identifiers/recommendation"
@@ -18,7 +18,8 @@ module Pubid
18
18
 
19
19
  # Main identifier pattern - check supplements first
20
20
  rule(:identifier) do
21
- amendment_identifier | amendment_short | annex_letter_identifier | annex_identifier | base_identifier
21
+ amendment_identifier | amendment_short | annex_letter_identifier |
22
+ annex_identifier | trailing_supplement_identifier | base_identifier
22
23
  end
23
24
 
24
25
  # Publisher - always "OIML"
@@ -30,14 +31,33 @@ module Pubid
30
31
  # Number with optional part and subpart
31
32
  rule(:number_only) { digits.as(:number) }
32
33
 
33
- rule(:part_number) { dash >> digits.as(:part) }
34
+ # Part number, optionally a slashed multi-part continuation captured
35
+ # verbatim, e.g. "1/-2" in "OIML R 46-1/-2:2012".
36
+ rule(:part_number) do
37
+ dash >> (digits >> (slash >> dash >> digits).repeat).as(:part)
38
+ end
34
39
 
35
40
  rule(:subpart_number) { dash >> digits.as(:subpart) }
36
41
 
42
+ # Free-form named/lettered code suffix glued after the numeric part:
43
+ # -GUM 1, -special, -sup, -erratum, -A, -ISO3930, -Amend, -Amended_2012
44
+ # plus the space-separated "Brochure" label. "GUM <n>" is tried first so
45
+ # its trailing number isn't lost to the bare-word alternative. The
46
+ # trailing `(_?digits)*` captures joint codes ("ISO3930") and the
47
+ # "Amended_2012" amendment label (the hand-off treats these as part
48
+ # suffixes, preserved verbatim for round-trip).
49
+ rule(:named_suffix) do
50
+ (dash >> (
51
+ (str("GUM") >> space >> digits) |
52
+ (match("[A-Za-z]").repeat(1) >> (str("_").maybe >> digits).repeat)
53
+ ).as(:code_suffix)) |
54
+ (space >> str("Brochure").as(:code_suffix) >> str("").as(:space_suffix))
55
+ end
56
+
37
57
  rule(:full_number) do
38
- (number_only >> part_number >> subpart_number) |
39
- (number_only >> part_number) |
40
- number_only
58
+ (number_only >> part_number >> subpart_number >> named_suffix.maybe) |
59
+ (number_only >> part_number >> named_suffix.maybe) |
60
+ (number_only >> named_suffix.maybe)
41
61
  end
42
62
 
43
63
  # Edition number - ordinal numbers
@@ -82,8 +102,18 @@ module Pubid
82
102
  end
83
103
 
84
104
  # Language codes
105
+ #
106
+ # relaton-data-oiml encodes the publication language with its own code
107
+ # set (lib/oiml_fetcher.rb DOCID_LANG_CODE): single uppercase letters
108
+ # E F D R S C A U X, plus two-letter PO/PT/PE/SR. The two-letter OIML
109
+ # codes must be tried before the single-letter rule so e.g. "PE" isn't
110
+ # left with a dangling "E".
85
111
  rule(:lang_single) do
86
- match("[EFRX]") # Single letter: E, F, R, X
112
+ match("[EFRXDSCAU]")
113
+ end
114
+
115
+ rule(:lang_multi_oiml) do
116
+ str("PO") | str("PT") | str("PE") | str("SR")
87
117
  end
88
118
 
89
119
  rule(:lang_multi) do
@@ -93,8 +123,9 @@ module Pubid
93
123
  rule(:language_code) do
94
124
  (
95
125
  (lang_single >> slash >> lang_single) | # E/F
96
- lang_single | # E, F
97
- lang_multi # en, fr
126
+ lang_multi_oiml | # PO, PT, PE, SR
127
+ lang_single | # E, F, D, R, S, C, A, U, X
128
+ lang_multi # en, fr
98
129
  ).as(:language)
99
130
  end
100
131
 
@@ -131,21 +162,37 @@ module Pubid
131
162
  language_portion.maybe.as(:language)
132
163
  end
133
164
 
134
- # Annex identifier - "BASE Annexes Edition YYYY" or "BASE Annexes:YYYY"
165
+ # Trailing supplement word - "BASE Amendment" / "BASE Errata" where the
166
+ # publication year stays on the base (e.g. "OIML R 138:2009 Amendment").
167
+ # amendment_short is tried first; it only matches when a year follows the
168
+ # word, so the no-year trailing form falls through to here.
169
+ rule(:trailing_supplement_identifier) do
170
+ base_without_language.as(:base_identifier) >>
171
+ space >> (str("Amendment") | str("Errata")).as(:trailing_marker) >>
172
+ language_portion.maybe.as(:language)
173
+ end
174
+
175
+ # Annex identifier - "BASE Annexes Edition YYYY" / "BASE Annexes:YYYY" /
176
+ # "BASE:YYYY Annexes" (year on the base, no annex year).
135
177
  rule(:annex_identifier) do
136
178
  base_without_language.as(:base_identifier) >>
137
179
  space >> str("Annexes").as(:annex_marker) >>
138
180
  (
139
181
  (space >> edition_text >> space >> year_digits.as(:year)).as(:edition_format) |
140
182
  (colon >> year_digits.as(:year))
141
- ) >>
183
+ ).maybe >>
142
184
  language_portion.maybe.as(:language)
143
185
  end
144
186
 
145
- # Annex with letter - "BASE Annex A Edition YYYY"
187
+ # Annex letter or letter range, e.g. "A" or "B-C".
188
+ rule(:annex_letter_value) do
189
+ (match("[A-Z]") >> (dash >> match("[A-Z]")).maybe).as(:annex_letter)
190
+ end
191
+
192
+ # Annex with letter - "BASE Annex A Edition YYYY" / "BASE:YYYY Annex B-C"
146
193
  rule(:annex_letter_identifier) do
147
194
  base_without_language.as(:base_identifier) >>
148
- space >> str("Annex") >> space >> match("[A-Z]").as(:annex_letter) >>
195
+ space >> str("Annex") >> space >> annex_letter_value >>
149
196
  ((space >> edition_text >> space >> year_digits.as(:year)) | (colon >> year_digits.as(:year))).maybe >>
150
197
  language_portion.maybe.as(:language)
151
198
  end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Oiml
5
+ # Human-readable renderer for OIML identifiers.
6
+ #
7
+ # Produces strings like:
8
+ # "OIML R 60:2000"
9
+ # "OIML R 60 Edition 2013"
10
+ # "OIML R 60 Annex A Edition 2013 (E)"
11
+ # "OIML R 60 Annexes:2021 (E)"
12
+ #
13
+ # The renderer is registered as the `:human` format in the OIML format
14
+ # registry and invoked via `render(format: :human)`.
15
+ class Renderer < ::Pubid::Renderers::Base
16
+ def render(context: nil, **opts)
17
+ id = @id
18
+ @context = context
19
+
20
+ case id
21
+ when Identifiers::Annex
22
+ render_annex(id)
23
+ when SupplementIdentifier
24
+ render_supplement(id)
25
+ when SingleIdentifier
26
+ render_single(id)
27
+ else
28
+ id.to_s
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def effective_format(id)
35
+ id.requested_format ||
36
+ (id.parsed_format == "long" ? :long : :short)
37
+ end
38
+
39
+ # Strip a trailing language group "(...)" from a rendered base string so
40
+ # the supplement can re-attach its own language at the end.
41
+ def strip_language(str)
42
+ str.sub(/\s*\([^)]+\)\s*$/, "").strip
43
+ end
44
+
45
+ def render_single(id)
46
+ format = effective_format(id)
47
+
48
+ result = "#{id.publisher} #{id.type_string} #{id.code}"
49
+
50
+ using_edition_format = false
51
+
52
+ if id.edition && id.date
53
+ result += " #{id.edition} Edition #{id.date.render(context: @context)}"
54
+ using_edition_format = true
55
+ elsif id.edition
56
+ result += " #{id.edition}"
57
+ using_edition_format = true
58
+ elsif id.date
59
+ if format == :long
60
+ result += " Edition #{id.date.render(context: @context)}"
61
+ using_edition_format = true
62
+ else
63
+ result += ":#{id.date.render(context: @context)}"
64
+ end
65
+ end
66
+
67
+ if id.stage || id.iteration
68
+ result += " "
69
+ result += id.iteration.to_s if id.iteration
70
+ result += id.stage.to_s if id.stage
71
+ end
72
+
73
+ if id.language
74
+ result += if using_edition_format || id.parsed_format == "short_with_space"
75
+ " (#{id.language})"
76
+ else
77
+ "(#{id.language})"
78
+ end
79
+ end
80
+
81
+ result
82
+ end
83
+
84
+ def render_supplement(id)
85
+ format = effective_format(id)
86
+
87
+ # Trailing-word shorthand: "BASE Amendment" / "BASE Errata" with the
88
+ # publication year kept on the base identifier. The word comes from the
89
+ # concrete supplement class.
90
+ if id.trailing
91
+ base_str = strip_language(id.base_identifier.to_s)
92
+ result = "#{base_str} #{id.supplement_type}"
93
+ result += " (#{id.language})" if id.language
94
+ return result
95
+ end
96
+
97
+ base_format = if format && format != :short
98
+ format
99
+ elsif id.base_identifier.class.attributes.key?(:parsed_format) && id.base_identifier.parsed_format == "long"
100
+ :long
101
+ else
102
+ :short
103
+ end
104
+
105
+ base_str = if id.base_identifier.is_a?(SingleIdentifier)
106
+ id.base_identifier.to_s(format: base_format)
107
+ else
108
+ id.base_identifier.to_s
109
+ end
110
+ base_str = strip_language(base_str)
111
+
112
+ result = "#{id.supplement_type} (#{id.year}) to #{base_str}"
113
+ result += " (#{id.language})" if id.language
114
+
115
+ result
116
+ end
117
+
118
+ def render_annex(id)
119
+ format = effective_format(id)
120
+
121
+ # "BASE:YYYY Annex(es)" — the year is glued to the base, the marker
122
+ # carries none. Keep the base date instead of stripping it.
123
+ if id.year_on_base
124
+ base_str = strip_language(id.base_identifier.to_s)
125
+ marker = id.letter ? "Annex #{id.letter}" : "Annexes"
126
+ result = "#{base_str} #{marker}"
127
+ result += " (#{id.language})" if id.language
128
+ return result
129
+ end
130
+
131
+ base_format = if id.base_identifier.class.attributes.key?(:parsed_format) && id.base_identifier.parsed_format == "long"
132
+ :long
133
+ else
134
+ :short
135
+ end
136
+
137
+ annex_format = if format
138
+ format
139
+ elsif id.class.attributes.key?(:parsed_format) && id.parsed_format == "long"
140
+ :long
141
+ else
142
+ :short
143
+ end
144
+
145
+ base_str = if id.base_identifier.is_a?(SingleIdentifier)
146
+ id.base_identifier.to_s(format: base_format)
147
+ else
148
+ id.base_identifier.to_s
149
+ end
150
+ result = base_str.sub(/:.*/, "").sub(/\s+Edition\s+\d{4}/, "").sub(
151
+ /\(.*\)/, ""
152
+ ).strip
153
+
154
+ if id.letter
155
+ result += " Annex #{id.letter}"
156
+ result += " Edition #{id.year}" if id.year
157
+ else
158
+ result += " Annexes"
159
+ if id.year
160
+ result += annex_format == :long ? " Edition #{id.year}" : ":#{id.year}"
161
+ elsif id.base_identifier.date
162
+ result += annex_format == :long ? " Edition #{id.base_identifier.date.render(context: @context)}" : ":#{id.base_identifier.date.render(context: @context)}"
163
+ end
164
+ end
165
+
166
+ result += " (#{id.language})" if id.language
167
+ result
168
+ end
169
+ end
170
+ end
171
+ end