pubid 2.0.0.pre.alpha.9 → 2.0.0.pre.alpha.12

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 (461) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +33 -11
  3. data/conformance/pending.yaml +4 -0
  4. data/lib/pubid/adobe/identifier.rb +1 -3
  5. data/lib/pubid/adobe/parser.rb +10 -2
  6. data/lib/pubid/adobe.rb +1 -0
  7. data/lib/pubid/amca/builder.rb +2 -2
  8. data/lib/pubid/amca/identifiers/base.rb +49 -27
  9. data/lib/pubid/amca/identifiers/interpretation.rb +17 -9
  10. data/lib/pubid/amca/identifiers/publication.rb +13 -9
  11. data/lib/pubid/amca/identifiers/standard.rb +2 -0
  12. data/lib/pubid/amca/parser.rb +1 -1
  13. data/lib/pubid/amca/renderer.rb +4 -4
  14. data/lib/pubid/amca/urn_generator.rb +2 -2
  15. data/lib/pubid/amca.rb +2 -1
  16. data/lib/pubid/ansi/builder.rb +2 -2
  17. data/lib/pubid/ansi/identifier.rb +18 -0
  18. data/lib/pubid/ansi/parser.rb +1 -1
  19. data/lib/pubid/ansi/renderer.rb +2 -2
  20. data/lib/pubid/ansi.rb +5 -5
  21. data/lib/pubid/api/builder.rb +16 -2
  22. data/lib/pubid/api/identifier.rb +25 -4
  23. data/lib/pubid/api/identifiers/mpms.rb +10 -8
  24. data/lib/pubid/api/parser.rb +1 -1
  25. data/lib/pubid/api/renderer.rb +16 -7
  26. data/lib/pubid/api/single_identifier.rb +5 -12
  27. data/lib/pubid/api.rb +1 -0
  28. data/lib/pubid/ashrae/builder.rb +31 -10
  29. data/lib/pubid/ashrae/identifiers/addenda_package.rb +6 -0
  30. data/lib/pubid/ashrae/identifiers/addendum.rb +8 -0
  31. data/lib/pubid/ashrae/identifiers/base.rb +81 -5
  32. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +7 -0
  33. data/lib/pubid/ashrae/identifiers/errata.rb +9 -0
  34. data/lib/pubid/ashrae/identifiers/guideline.rb +3 -0
  35. data/lib/pubid/ashrae/identifiers/interpretation.rb +16 -0
  36. data/lib/pubid/ashrae/identifiers/standard.rb +3 -0
  37. data/lib/pubid/ashrae/parser.rb +23 -8
  38. data/lib/pubid/ashrae/renderer.rb +6 -6
  39. data/lib/pubid/ashrae/supplement_identifier.rb +17 -2
  40. data/lib/pubid/ashrae/urn_generator.rb +8 -2
  41. data/lib/pubid/ashrae.rb +7 -1
  42. data/lib/pubid/asme/builder.rb +11 -2
  43. data/lib/pubid/asme/identifier.rb +9 -0
  44. data/lib/pubid/asme/identifiers/standard.rb +86 -2
  45. data/lib/pubid/asme/parser.rb +1 -1
  46. data/lib/pubid/asme/renderer.rb +3 -3
  47. data/lib/pubid/asme/single_identifier.rb +8 -1
  48. data/lib/pubid/asme/urn_generator.rb +2 -2
  49. data/lib/pubid/asme.rb +1 -0
  50. data/lib/pubid/astm/builder.rb +10 -3
  51. data/lib/pubid/astm/identifier.rb +9 -0
  52. data/lib/pubid/astm/identifiers/adjunct.rb +16 -1
  53. data/lib/pubid/astm/identifiers/code_number.rb +81 -0
  54. data/lib/pubid/astm/identifiers/data_series.rb +2 -0
  55. data/lib/pubid/astm/identifiers/iso_dual_published.rb +16 -0
  56. data/lib/pubid/astm/identifiers/manual.rb +10 -0
  57. data/lib/pubid/astm/identifiers/monograph.rb +2 -0
  58. data/lib/pubid/astm/identifiers/research_report.rb +10 -0
  59. data/lib/pubid/astm/identifiers/standard.rb +10 -0
  60. data/lib/pubid/astm/identifiers/technical_report.rb +2 -0
  61. data/lib/pubid/astm/identifiers/work_in_progress.rb +2 -0
  62. data/lib/pubid/astm/identifiers.rb +1 -0
  63. data/lib/pubid/astm/parser.rb +1 -1
  64. data/lib/pubid/astm/renderer.rb +1 -1
  65. data/lib/pubid/astm/single_identifier.rb +31 -1
  66. data/lib/pubid/astm/urn_generator.rb +7 -5
  67. data/lib/pubid/astm.rb +1 -0
  68. data/lib/pubid/bipm/builder.rb +66 -10
  69. data/lib/pubid/bipm/identifier.rb +134 -9
  70. data/lib/pubid/bipm/identifiers/committee_document.rb +12 -0
  71. data/lib/pubid/bipm/identifiers/guide.rb +11 -0
  72. data/lib/pubid/bipm/identifiers/meeting.rb +12 -0
  73. data/lib/pubid/bipm/identifiers/mep.rb +12 -0
  74. data/lib/pubid/bipm/identifiers/metrologia_article.rb +24 -0
  75. data/lib/pubid/bipm/identifiers/si_brochure.rb +13 -0
  76. data/lib/pubid/bipm/parser.rb +65 -12
  77. data/lib/pubid/bipm/renderer.rb +8 -0
  78. data/lib/pubid/bipm/urn_parser.rb +11 -3
  79. data/lib/pubid/bipm.rb +7 -1
  80. data/lib/pubid/bsi/builder.rb +48 -38
  81. data/lib/pubid/bsi/components/date.rb +10 -4
  82. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +36 -7
  83. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +7 -6
  84. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +1 -2
  85. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +10 -0
  86. data/lib/pubid/bsi/identifiers/committee_document.rb +10 -1
  87. data/lib/pubid/bsi/identifiers/handbook.rb +1 -3
  88. data/lib/pubid/bsi/identifiers/practice_guide.rb +1 -2
  89. data/lib/pubid/bsi/identifiers/set.rb +11 -0
  90. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +10 -1
  91. data/lib/pubid/bsi/parser.rb +1 -1
  92. data/lib/pubid/bsi/renderer.rb +63 -51
  93. data/lib/pubid/bsi/single_identifier.rb +27 -9
  94. data/lib/pubid/bsi/urn_generator.rb +11 -2
  95. data/lib/pubid/bsi.rb +7 -1
  96. data/lib/pubid/builder/base.rb +18 -8
  97. data/lib/pubid/bundled_identifier.rb +16 -6
  98. data/lib/pubid/calconnect/identifier.rb +9 -5
  99. data/lib/pubid/calconnect/parser.rb +1 -1
  100. data/lib/pubid/calconnect.rb +7 -1
  101. data/lib/pubid/ccsds/identifier.rb +13 -2
  102. data/lib/pubid/ccsds/identifiers/base.rb +4 -2
  103. data/lib/pubid/ccsds/identifiers/corrigendum.rb +2 -2
  104. data/lib/pubid/ccsds/parser.rb +1 -1
  105. data/lib/pubid/ccsds/single_identifier.rb +16 -12
  106. data/lib/pubid/ccsds.rb +1 -0
  107. data/lib/pubid/cen_cenelec/builder.rb +101 -76
  108. data/lib/pubid/cen_cenelec/identifier.rb +115 -3
  109. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +27 -16
  110. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +46 -6
  111. data/lib/pubid/cen_cenelec/identifiers/base.rb +8 -9
  112. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +1 -1
  113. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +1 -1
  114. data/lib/pubid/cen_cenelec/identifiers/cenelec_harmonization_document.rb +1 -1
  115. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +29 -20
  116. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +47 -8
  117. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +27 -2
  118. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +1 -1
  119. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +15 -5
  120. data/lib/pubid/cen_cenelec/identifiers/guide.rb +1 -1
  121. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +1 -1
  122. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +1 -1
  123. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +1 -1
  124. data/lib/pubid/cen_cenelec/parser.rb +1 -1
  125. data/lib/pubid/cen_cenelec/renderer.rb +55 -60
  126. data/lib/pubid/cen_cenelec/single_identifier.rb +20 -2
  127. data/lib/pubid/cen_cenelec/urn_generator.rb +66 -44
  128. data/lib/pubid/cen_cenelec.rb +28 -10
  129. data/lib/pubid/cie/builder.rb +10 -0
  130. data/lib/pubid/cie/identifier.rb +6 -1
  131. data/lib/pubid/cie/identifiers/bundle.rb +4 -2
  132. data/lib/pubid/cie/identifiers/conference.rb +2 -2
  133. data/lib/pubid/cie/identifiers/corrigendum.rb +2 -2
  134. data/lib/pubid/cie/identifiers/dual_published.rb +2 -2
  135. data/lib/pubid/cie/identifiers/identical.rb +2 -2
  136. data/lib/pubid/cie/identifiers/joint_published.rb +2 -2
  137. data/lib/pubid/cie/identifiers/proceedings.rb +8 -6
  138. data/lib/pubid/cie/identifiers/standard.rb +22 -13
  139. data/lib/pubid/cie/identifiers/supplement.rb +2 -2
  140. data/lib/pubid/cie/identifiers/tutorial_bundle.rb +2 -2
  141. data/lib/pubid/cie/parser.rb +1 -1
  142. data/lib/pubid/cie.rb +7 -1
  143. data/lib/pubid/conformance/checks.rb +72 -0
  144. data/lib/pubid/conformance/corpus/case.rb +55 -0
  145. data/lib/pubid/conformance/corpus.rb +36 -0
  146. data/lib/pubid/conformance/generator.rb +212 -0
  147. data/lib/pubid/conformance/pending.rb +63 -0
  148. data/lib/pubid/conformance/runner.rb +153 -0
  149. data/lib/pubid/conformance.rb +55 -0
  150. data/lib/pubid/core.rb +2 -0
  151. data/lib/pubid/csa/builder.rb +47 -47
  152. data/lib/pubid/csa/composite_identifier.rb +14 -19
  153. data/lib/pubid/csa/identifier.rb +143 -81
  154. data/lib/pubid/csa/identifiers/bundled.rb +23 -13
  155. data/lib/pubid/csa/identifiers/canadian_adopted.rb +13 -13
  156. data/lib/pubid/csa/identifiers/cec.rb +44 -4
  157. data/lib/pubid/csa/identifiers/combined.rb +95 -73
  158. data/lib/pubid/csa/identifiers/csa_adopted.rb +4 -4
  159. data/lib/pubid/csa/identifiers/package.rb +2 -2
  160. data/lib/pubid/csa/parser.rb +6 -2
  161. data/lib/pubid/csa/renderer.rb +13 -5
  162. data/lib/pubid/csa/single_identifier.rb +93 -4
  163. data/lib/pubid/csa/urn_generator.rb +9 -2
  164. data/lib/pubid/csa/wrapper_identifier.rb +39 -23
  165. data/lib/pubid/csa.rb +7 -1
  166. data/lib/pubid/doi/identifier.rb +6 -3
  167. data/lib/pubid/doi/parser.rb +1 -1
  168. data/lib/pubid/doi.rb +1 -0
  169. data/lib/pubid/easc/identifier.rb +0 -2
  170. data/lib/pubid/easc/parser.rb +10 -2
  171. data/lib/pubid/easc.rb +1 -0
  172. data/lib/pubid/ecma/builder.rb +23 -9
  173. data/lib/pubid/ecma/identifier.rb +81 -10
  174. data/lib/pubid/ecma/parser.rb +39 -4
  175. data/lib/pubid/ecma/renderer.rb +29 -8
  176. data/lib/pubid/ecma/urn_generator.rb +34 -13
  177. data/lib/pubid/ecma/urn_parser.rb +30 -14
  178. data/lib/pubid/ecma.rb +1 -0
  179. data/lib/pubid/errors.rb +80 -0
  180. data/lib/pubid/etsi/builder.rb +6 -1
  181. data/lib/pubid/etsi/identifiers/base.rb +34 -20
  182. data/lib/pubid/etsi/identifiers/etsi_standard.rb +120 -41
  183. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +10 -0
  184. data/lib/pubid/etsi/parser.rb +1 -1
  185. data/lib/pubid/etsi.rb +1 -0
  186. data/lib/pubid/evs/builder.rb +26 -0
  187. data/lib/pubid/evs/identifier.rb +37 -0
  188. data/lib/pubid/evs/identifiers/national_adoption.rb +22 -0
  189. data/lib/pubid/evs/identifiers.rb +9 -0
  190. data/lib/pubid/evs/parser.rb +27 -0
  191. data/lib/pubid/evs/renderer.rb +30 -0
  192. data/lib/pubid/evs/urn_generator.rb +30 -0
  193. data/lib/pubid/evs/urn_parser.rb +80 -0
  194. data/lib/pubid/evs.rb +90 -0
  195. data/lib/pubid/export.rb +1 -0
  196. data/lib/pubid/format_detector.rb +1 -0
  197. data/lib/pubid/gb/builder.rb +14 -9
  198. data/lib/pubid/gb/identifier.rb +29 -7
  199. data/lib/pubid/gb/parser.rb +5 -1
  200. data/lib/pubid/gb/renderer.rb +4 -3
  201. data/lib/pubid/gb.rb +2 -0
  202. data/lib/pubid/gost/builder.rb +46 -9
  203. data/lib/pubid/gost/identifier.rb +0 -2
  204. data/lib/pubid/gost/identifiers/foreign_reference.rb +1 -1
  205. data/lib/pubid/gost/parser.rb +10 -2
  206. data/lib/pubid/gost.rb +1 -0
  207. data/lib/pubid/iala/identifier.rb +9 -6
  208. data/lib/pubid/iala/parser.rb +10 -2
  209. data/lib/pubid/iala/urn_parser.rb +6 -2
  210. data/lib/pubid/iala.rb +1 -0
  211. data/lib/pubid/iana/builder.rb +3 -1
  212. data/lib/pubid/iana/identifier.rb +74 -6
  213. data/lib/pubid/iana/identifiers/registry.rb +36 -0
  214. data/lib/pubid/iana/parser.rb +1 -1
  215. data/lib/pubid/iana/renderer.rb +3 -0
  216. data/lib/pubid/iana/urn_generator.rb +5 -1
  217. data/lib/pubid/iana.rb +1 -0
  218. data/lib/pubid/identifier.rb +605 -13
  219. data/lib/pubid/identifier_metadata.rb +1 -0
  220. data/lib/pubid/idf/builder.rb +3 -3
  221. data/lib/pubid/idf/identifier.rb +25 -9
  222. data/lib/pubid/idf/identifiers/amendment.rb +1 -1
  223. data/lib/pubid/idf/identifiers/corrigendum.rb +1 -1
  224. data/lib/pubid/idf/identifiers/international_standard.rb +1 -1
  225. data/lib/pubid/idf/identifiers/reviewed_method.rb +1 -1
  226. data/lib/pubid/idf/parser.rb +1 -1
  227. data/lib/pubid/idf/renderer.rb +4 -4
  228. data/lib/pubid/idf/single_identifier.rb +1 -1
  229. data/lib/pubid/idf/urn_generator.rb +1 -1
  230. data/lib/pubid/idf.rb +7 -1
  231. data/lib/pubid/iec/builder.rb +14 -7
  232. data/lib/pubid/iec/components.rb +0 -1
  233. data/lib/pubid/iec/identifier.rb +73 -83
  234. data/lib/pubid/iec/identifiers/amendment.rb +6 -2
  235. data/lib/pubid/iec/identifiers/component_specification.rb +0 -10
  236. data/lib/pubid/iec/identifiers/conformity_assessment.rb +0 -10
  237. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -2
  238. data/lib/pubid/iec/identifiers/fragment_identifier.rb +2 -4
  239. data/lib/pubid/iec/identifiers/guide.rb +0 -16
  240. data/lib/pubid/iec/identifiers/international_standard.rb +15 -2
  241. data/lib/pubid/iec/identifiers/operational_document.rb +0 -10
  242. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +0 -12
  243. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +0 -10
  244. data/lib/pubid/iec/identifiers/systems_reference_document.rb +0 -10
  245. data/lib/pubid/iec/identifiers/technical_report.rb +0 -17
  246. data/lib/pubid/iec/identifiers/technical_specification.rb +0 -17
  247. data/lib/pubid/iec/identifiers/technology_report.rb +0 -10
  248. data/lib/pubid/iec/identifiers/test_report_form.rb +0 -11
  249. data/lib/pubid/iec/identifiers/white_paper.rb +0 -10
  250. data/lib/pubid/iec/identifiers/working_document.rb +24 -10
  251. data/lib/pubid/iec/parser.rb +2 -18
  252. data/lib/pubid/iec/renderer.rb +13 -10
  253. data/lib/pubid/iec/single_identifier.rb +33 -10
  254. data/lib/pubid/iec/urn_generator.rb +227 -61
  255. data/lib/pubid/iec/urn_parser.rb +42 -4
  256. data/lib/pubid/iec.rb +1 -0
  257. data/lib/pubid/ieee/aiee/identifier.rb +2 -2
  258. data/lib/pubid/ieee/aiee/parser.rb +1 -1
  259. data/lib/pubid/ieee/builder.rb +87 -3
  260. data/lib/pubid/ieee/identifiers/adopted_standard.rb +32 -0
  261. data/lib/pubid/ieee/identifiers/base.rb +42 -5
  262. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +21 -0
  263. data/lib/pubid/ieee/identifiers/dual_published.rb +55 -0
  264. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +23 -0
  265. data/lib/pubid/ieee/identifiers/joint_development.rb +11 -7
  266. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +57 -5
  267. data/lib/pubid/ieee/identifiers/nesc/base.rb +2 -2
  268. data/lib/pubid/ieee/identifiers/nesc/draft.rb +2 -2
  269. data/lib/pubid/ieee/identifiers/nesc/handbook.rb +2 -2
  270. data/lib/pubid/ieee/identifiers/nesc/redline.rb +2 -2
  271. data/lib/pubid/ieee/identifiers/nesc/standard.rb +2 -2
  272. data/lib/pubid/ieee/identifiers/si_standard.rb +5 -2
  273. data/lib/pubid/ieee/ire/identifier.rb +2 -2
  274. data/lib/pubid/ieee/ire/parser.rb +20 -2
  275. data/lib/pubid/ieee/nesc/parser.rb +1 -1
  276. data/lib/pubid/ieee/parser.rb +208 -33
  277. data/lib/pubid/ieee/project_renderer.rb +46 -0
  278. data/lib/pubid/ieee/renderer.rb +11 -8
  279. data/lib/pubid/ieee/urn_generator.rb +32 -3
  280. data/lib/pubid/ieee.rb +9 -1
  281. data/lib/pubid/ieee_debug.rb +1 -0
  282. data/lib/pubid/ietf/builder.rb +24 -8
  283. data/lib/pubid/ietf/identifiers/base.rb +25 -28
  284. data/lib/pubid/ietf/identifiers/bcp.rb +11 -0
  285. data/lib/pubid/ietf/identifiers/fyi.rb +11 -0
  286. data/lib/pubid/ietf/identifiers/internet_draft.rb +18 -2
  287. data/lib/pubid/ietf/identifiers/rfc.rb +2 -0
  288. data/lib/pubid/ietf/identifiers/serialization.rb +51 -0
  289. data/lib/pubid/ietf/identifiers/std.rb +11 -0
  290. data/lib/pubid/ietf/identifiers.rb +1 -0
  291. data/lib/pubid/ietf/parser.rb +27 -9
  292. data/lib/pubid/ietf/renderer.rb +44 -6
  293. data/lib/pubid/ietf/urn_generator.rb +20 -6
  294. data/lib/pubid/ietf/urn_parser.rb +10 -2
  295. data/lib/pubid/ietf.rb +12 -2
  296. data/lib/pubid/iho/identifiers/base.rb +10 -3
  297. data/lib/pubid/iho/parser.rb +1 -1
  298. data/lib/pubid/iho.rb +1 -0
  299. data/lib/pubid/isbn/identifier.rb +25 -7
  300. data/lib/pubid/isbn/parser.rb +1 -1
  301. data/lib/pubid/isbn.rb +1 -0
  302. data/lib/pubid/iso/builder.rb +10 -11
  303. data/lib/pubid/iso/bundled_identifier.rb +5 -3
  304. data/lib/pubid/iso/combined_identifier.rb +5 -3
  305. data/lib/pubid/iso/components.rb +0 -1
  306. data/lib/pubid/iso/identifier.rb +23 -11
  307. data/lib/pubid/iso/identifiers/directives.rb +7 -4
  308. data/lib/pubid/iso/identifiers/directives_supplement.rb +4 -4
  309. data/lib/pubid/iso/identifiers/tc_document.rb +31 -46
  310. data/lib/pubid/iso/normalizer.rb +1 -1
  311. data/lib/pubid/iso/parser.rb +1 -1
  312. data/lib/pubid/iso/urn_generator.rb +10 -10
  313. data/lib/pubid/iso.rb +12 -5
  314. data/lib/pubid/itu/builder.rb +10 -0
  315. data/lib/pubid/itu/identifiers/addendum.rb +2 -2
  316. data/lib/pubid/itu/identifiers/amendment.rb +2 -2
  317. data/lib/pubid/itu/identifiers/base.rb +29 -5
  318. data/lib/pubid/itu/identifiers/contribution.rb +31 -0
  319. data/lib/pubid/itu/identifiers/corrigendum.rb +2 -2
  320. data/lib/pubid/itu/identifiers/errata.rb +2 -2
  321. data/lib/pubid/itu/identifiers/supplement.rb +2 -2
  322. data/lib/pubid/itu/identifiers.rb +1 -0
  323. data/lib/pubid/itu/parser.rb +20 -3
  324. data/lib/pubid/itu.rb +1 -0
  325. data/lib/pubid/jcgm/builder.rb +1 -1
  326. data/lib/pubid/jcgm/identifier.rb +10 -0
  327. data/lib/pubid/jcgm/identifiers/meeting.rb +1 -1
  328. data/lib/pubid/jcgm/parser.rb +10 -3
  329. data/lib/pubid/jcgm/renderer.rb +10 -3
  330. data/lib/pubid/jcgm/single_identifier.rb +24 -15
  331. data/lib/pubid/jcgm/urn_generator.rb +1 -1
  332. data/lib/pubid/jcgm/urn_parser.rb +156 -14
  333. data/lib/pubid/jcgm.rb +10 -0
  334. data/lib/pubid/jis/identifier.rb +10 -3
  335. data/lib/pubid/jis/parser.rb +1 -1
  336. data/lib/pubid/jis.rb +1 -0
  337. data/lib/pubid/nist/builder.rb +12 -12
  338. data/lib/pubid/nist/components/stage.rb +2 -2
  339. data/lib/pubid/nist/configuration.rb +6 -8
  340. data/lib/pubid/nist/identifiers/base.rb +22 -5
  341. data/lib/pubid/nist/identifiers/circular.rb +9 -2
  342. data/lib/pubid/nist/identifiers/circular_supplement.rb +14 -5
  343. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +1 -1
  344. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +7 -1
  345. data/lib/pubid/nist/identifiers/crpl_report.rb +12 -7
  346. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +2 -2
  347. data/lib/pubid/nist/identifiers/handbook.rb +9 -2
  348. data/lib/pubid/nist/identifiers/internal_report.rb +12 -5
  349. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +16 -8
  350. data/lib/pubid/nist/identifiers/monograph.rb +14 -7
  351. data/lib/pubid/nist/identifiers/report.rb +14 -6
  352. data/lib/pubid/nist/parser.rb +1 -1
  353. data/lib/pubid/nist/series/ir.rb +3 -7
  354. data/lib/pubid/nist/supplement_identifier.rb +16 -1
  355. data/lib/pubid/nist.rb +7 -1
  356. data/lib/pubid/oasis/builder.rb +12 -10
  357. data/lib/pubid/oasis/identifier.rb +89 -11
  358. data/lib/pubid/oasis/parser.rb +1 -1
  359. data/lib/pubid/oasis.rb +7 -1
  360. data/lib/pubid/ogc/identifier.rb +9 -5
  361. data/lib/pubid/ogc/parser.rb +1 -1
  362. data/lib/pubid/ogc.rb +1 -0
  363. data/lib/pubid/oiml/builder.rb +7 -3
  364. data/lib/pubid/oiml/identifiers/basic_publication.rb +2 -0
  365. data/lib/pubid/oiml/identifiers/bulletin.rb +40 -10
  366. data/lib/pubid/oiml/identifiers/code_number.rb +90 -0
  367. data/lib/pubid/oiml/identifiers/document.rb +2 -0
  368. data/lib/pubid/oiml/identifiers/expert_report.rb +2 -0
  369. data/lib/pubid/oiml/identifiers/guide.rb +2 -0
  370. data/lib/pubid/oiml/identifiers/recommendation.rb +2 -0
  371. data/lib/pubid/oiml/identifiers/seminar_report.rb +2 -0
  372. data/lib/pubid/oiml/identifiers/vocabulary.rb +2 -0
  373. data/lib/pubid/oiml/identifiers.rb +1 -0
  374. data/lib/pubid/oiml/parser.rb +8 -3
  375. data/lib/pubid/oiml/renderer.rb +3 -3
  376. data/lib/pubid/oiml/single_identifier.rb +26 -42
  377. data/lib/pubid/oiml/supplement_identifier.rb +27 -0
  378. data/lib/pubid/oiml/urn_generator.rb +4 -4
  379. data/lib/pubid/oiml.rb +7 -1
  380. data/lib/pubid/omg/builder.rb +1 -0
  381. data/lib/pubid/omg/identifier.rb +20 -3
  382. data/lib/pubid/omg/parser.rb +64 -11
  383. data/lib/pubid/omg/renderer.rb +13 -1
  384. data/lib/pubid/omg.rb +2 -1
  385. data/lib/pubid/parser/grammar.rb +74 -0
  386. data/lib/pubid/parser.rb +2 -0
  387. data/lib/pubid/parsers/mr_string.rb +19 -0
  388. data/lib/pubid/plateau/parser.rb +1 -1
  389. data/lib/pubid/plateau.rb +10 -0
  390. data/lib/pubid/prefixes_support.rb +1 -0
  391. data/lib/pubid/renderers/annotator.rb +233 -0
  392. data/lib/pubid/renderers/base.rb +13 -0
  393. data/lib/pubid/renderers/directives_renderer.rb +6 -4
  394. data/lib/pubid/renderers/human_readable.rb +3 -3
  395. data/lib/pubid/renderers/mr_string.rb +15 -9
  396. data/lib/pubid/renderers.rb +1 -0
  397. data/lib/pubid/rendering/numbering.rb +25 -7
  398. data/lib/pubid/rendering.rb +1 -0
  399. data/lib/pubid/sae/builder.rb +1 -1
  400. data/lib/pubid/sae/identifiers/base.rb +13 -3
  401. data/lib/pubid/sae/parser.rb +1 -1
  402. data/lib/pubid/sae/urn_generator.rb +1 -1
  403. data/lib/pubid/sae.rb +1 -0
  404. data/lib/pubid/schema/declaration.rb +33 -0
  405. data/lib/pubid/schema/error.rb +14 -0
  406. data/lib/pubid/schema/identifier_type.rb +23 -0
  407. data/lib/pubid/schema/loader.rb +117 -0
  408. data/lib/pubid/schema/typed_stage.rb +24 -0
  409. data/lib/pubid/schema.rb +25 -0
  410. data/lib/pubid/tgpp/builder.rb +1 -1
  411. data/lib/pubid/tgpp/identifier.rb +21 -5
  412. data/lib/pubid/tgpp/identifiers/technical_report.rb +2 -2
  413. data/lib/pubid/tgpp/identifiers/technical_specification.rb +2 -2
  414. data/lib/pubid/tgpp/parser.rb +22 -6
  415. data/lib/pubid/tgpp/renderer.rb +21 -5
  416. data/lib/pubid/tgpp/urn_generator.rb +27 -8
  417. data/lib/pubid/tgpp/urn_parser.rb +8 -6
  418. data/lib/pubid/tgpp.rb +7 -1
  419. data/lib/pubid/type_resolver.rb +16 -1
  420. data/lib/pubid/un/identifier.rb +6 -3
  421. data/lib/pubid/un/parser.rb +1 -1
  422. data/lib/pubid/un.rb +1 -0
  423. data/lib/pubid/urn_parser/errors.rb +8 -1
  424. data/lib/pubid/urn_parser.rb +1 -0
  425. data/lib/pubid/utils.rb +1 -0
  426. data/lib/pubid/version.rb +1 -1
  427. data/lib/pubid/w3c/builder.rb +5 -5
  428. data/lib/pubid/w3c/identifier.rb +38 -9
  429. data/lib/pubid/w3c/parser.rb +1 -1
  430. data/lib/pubid/w3c/renderer.rb +1 -1
  431. data/lib/pubid/w3c/urn_generator.rb +2 -2
  432. data/lib/pubid/w3c.rb +1 -0
  433. data/lib/pubid/xsf/identifier.rb +9 -5
  434. data/lib/pubid/xsf/parser.rb +17 -4
  435. data/lib/pubid/xsf.rb +7 -1
  436. data/lib/pubid.rb +399 -21
  437. data/lib/tasks/conformance.rake +34 -0
  438. data/lib/tasks/docs.rake +16 -14
  439. data/lib/tasks/schema.rake +88 -0
  440. data/schema/core/joint_prefixes.yaml +24 -0
  441. data/schema/iec.yaml +1017 -0
  442. data/schema/iso.yaml +1586 -0
  443. data/schema/schema.schema.yaml +96 -0
  444. metadata +40 -19
  445. data/archived-gems/pubid-ccsds/update_codes.yaml +0 -1
  446. data/archived-gems/pubid-iec/stages.yaml +0 -129
  447. data/archived-gems/pubid-iec/update_codes.yaml +0 -67
  448. data/archived-gems/pubid-ieee/update_codes.yaml +0 -104
  449. data/archived-gems/pubid-iso/stages.yaml +0 -106
  450. data/archived-gems/pubid-iso/update_codes.yaml +0 -4
  451. data/archived-gems/pubid-itu/i18n.yaml +0 -13
  452. data/archived-gems/pubid-itu/series.yaml +0 -42
  453. data/archived-gems/pubid-nist/publishers.yaml +0 -6
  454. data/archived-gems/pubid-nist/series.yaml +0 -121
  455. data/archived-gems/pubid-nist/update_codes.yaml +0 -93
  456. data/archived-gems/pubid-plateau/update_codes.yaml +0 -6
  457. data/lib/pubid/ccsds/identifiers/base_BASE_88929.rb +0 -70
  458. data/lib/pubid/cen_cenelec/supplement_identifier.rb +0 -48
  459. data/lib/pubid/iec/components/code.rb +0 -36
  460. data/lib/pubid/iso/components/code.rb +0 -24
  461. /data/{archived-gems/pubid-nist → data/nist}/stages.yaml +0 -0
@@ -35,18 +35,26 @@ module Pubid
35
35
  end
36
36
  end
37
37
 
38
+ # `number` is the relaton index key and is derived, not printed, so it has
39
+ # to be set here exactly as `Builder` sets it — a URN-reconstructed
40
+ # identifier must agree with a parsed one attribute for attribute.
38
41
  def build_metrologia(parts)
39
42
  Identifiers::MetrologiaArticle.new(
40
- volume: parts[1]&.to_i, issue: parts[2], article: parts[3],
43
+ number: presence(parts[1]), issue: parts[2], article: parts[3],
41
44
  )
42
45
  end
43
46
 
44
47
  def build_si_brochure(parts)
45
48
  Identifiers::SiBrochure.new(
46
- language: parts[1].to_s.upcase, edition: parts[2],
47
- version: parts[3], years: parts[4]
49
+ number: presence(parts[2]), language: parts[1].to_s.upcase,
50
+ edition: parts[2], version: parts[3], years: parts[4]
48
51
  )
49
52
  end
53
+
54
+ # A URN segment that was never filled in is an empty string, not nil.
55
+ def presence(segment)
56
+ segment unless segment.nil? || segment.empty?
57
+ end
50
58
  end
51
59
  end
52
60
  end
data/lib/pubid/bipm.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pubid"
3
4
  module Pubid
4
5
  module Bipm
5
6
  extend Pubid::PrefixesSupport
@@ -27,8 +28,13 @@ module Pubid
27
28
  # @param identifier [String] the printed identifier
28
29
  # @return [Identifier] the parsed identifier
29
30
  def self.parse(identifier)
31
+ unless identifier.is_a?(String)
32
+ raise Pubid::Errors::InvalidInputError,
33
+ Pubid::INPUT_NOT_A_STRING_MESSAGE
34
+ end
35
+
30
36
  if identifier.length > Pubid::MAX_INPUT_LENGTH
31
- raise ArgumentError, Pubid::INPUT_TOO_LONG_MESSAGE
37
+ raise Pubid::Errors::InvalidInputError, Pubid::INPUT_TOO_LONG_MESSAGE
32
38
  end
33
39
 
34
40
  Identifier.parse(identifier)
@@ -164,7 +164,7 @@ module Pubid
164
164
 
165
165
  # Build attributes hash (conditional arguments must be handled separately)
166
166
  attrs = {
167
- number: Components::Code.new(value: number_val),
167
+ number: number_val,
168
168
  issue_number: issue_number,
169
169
  index_format: format,
170
170
  }
@@ -181,7 +181,7 @@ module Pubid
181
181
 
182
182
  # Build attributes hash
183
183
  attrs = {
184
- number: Components::Code.new(value: number_val),
184
+ number: number_val,
185
185
  }
186
186
  attrs[:date] = Components::Date.new(year: year_val) if year_val
187
187
 
@@ -206,9 +206,9 @@ module Pubid
206
206
 
207
207
  # Build attributes hash
208
208
  attrs = {
209
- number: Components::Code.new(value: number_val),
209
+ number: number_val,
210
210
  }
211
- attrs[:part] = Components::Code.new(value: part_val) if part_val
211
+ attrs[:part] = part_val if part_val
212
212
  attrs[:date] = Components::Date.new(year: year_val) if year_val
213
213
 
214
214
  Identifiers::ExplanatorySupplement.new(attrs)
@@ -248,13 +248,13 @@ module Pubid
248
248
 
249
249
  # Build attributes hash
250
250
  attrs = {
251
- number: Components::Code.new(value: number_val),
251
+ number: number_val,
252
252
  method_code: method_code,
253
253
  method_to: method_to,
254
254
  method_and: method_and,
255
255
  is_plural: is_plural,
256
256
  }
257
- attrs[:part] = Components::Code.new(value: part_val) if part_val
257
+ attrs[:part] = part_val if part_val
258
258
  attrs[:date] = Components::Date.new(year: year_val) if year_val
259
259
 
260
260
  Identifiers::Method.new(attrs)
@@ -280,7 +280,7 @@ module Pubid
280
280
 
281
281
  # Build attributes hash
282
282
  attrs = {
283
- number: Components::Code.new(value: number_val),
283
+ number: number_val,
284
284
  test_series: test_series,
285
285
  test_id: test_id,
286
286
  }
@@ -313,7 +313,7 @@ module Pubid
313
313
 
314
314
  # Build attributes hash (conditional arguments must be handled separately)
315
315
  attrs = {
316
- number: Components::Code.new(value: number_val),
316
+ number: number_val,
317
317
  section_id: section_id,
318
318
  section_format: format,
319
319
  }
@@ -343,7 +343,7 @@ module Pubid
343
343
 
344
344
  # Build attributes hash
345
345
  attrs = {
346
- number: Components::Code.new(value: number_val),
346
+ number: number_val,
347
347
  }
348
348
  attrs[:spec_code] = Components::Code.new(value: spec_code) if spec_code
349
349
  if publisher_val
@@ -373,9 +373,9 @@ module Pubid
373
373
 
374
374
  # Build attributes hash
375
375
  attrs = {
376
- number: Components::Code.new(value: number_val),
376
+ number: number_val,
377
377
  }
378
- attrs[:part] = Components::Code.new(value: part_val) if part_val
378
+ attrs[:part] = part_val if part_val
379
379
  attrs[:publisher] = Components::Publisher.new(body: "DISC")
380
380
  attrs[:date] = Components::Date.new(year: year_val) if year_val
381
381
 
@@ -432,9 +432,9 @@ module Pubid
432
432
  # Build attributes hash
433
433
  attrs = {
434
434
  prefix: prefix_val,
435
- number: Components::Code.new(value: number_val),
435
+ number: number_val,
436
436
  }
437
- attrs[:part] = Components::Code.new(value: part_val) if part_val
437
+ attrs[:part] = part_val if part_val
438
438
  attrs[:iteration] = iteration_val if iteration_val
439
439
  attrs[:edition] = final_edition if final_edition
440
440
  attrs[:publisher] = Components::Publisher.new(body: "BS")
@@ -456,20 +456,20 @@ module Pubid
456
456
  # Build base identifier
457
457
  base_id = SingleIdentifier.new(
458
458
  publisher: Components::Publisher.new(body: "BS"),
459
- number: Components::Code.new(value: base_number),
459
+ number: base_number,
460
460
  )
461
461
 
462
462
  # Build identifiers for each part
463
463
  id1 = SingleIdentifier.new(
464
464
  publisher: Components::Publisher.new(body: "BS"),
465
- number: Components::Code.new(value: base_number),
466
- part: Components::Code.new(value: part1),
465
+ number: base_number,
466
+ part: part1,
467
467
  )
468
468
 
469
469
  id2 = SingleIdentifier.new(
470
470
  publisher: Components::Publisher.new(body: "BS"),
471
- number: Components::Code.new(value: base_number),
472
- part: Components::Code.new(value: part2),
471
+ number: base_number,
472
+ part: part2,
473
473
  )
474
474
 
475
475
  Identifiers::BundledIdentifier.new(
@@ -636,7 +636,7 @@ module Pubid
636
636
  publisher: Components::Publisher.new(body: publisher_val),
637
637
  )
638
638
  id.prefix = prefix_val if prefix_val && !prefix_val.empty?
639
- id.number = Components::Code.new(value: number_val) if number_val
639
+ id.number = number_val if number_val
640
640
 
641
641
  id.explicit_prefix = has_explicit_publisher || has_explicit_prefix
642
642
  id.explicit_publisher = has_explicit_publisher
@@ -646,11 +646,11 @@ module Pubid
646
646
  parts_array = parts_val[:parts]
647
647
  if parts_array.any?
648
648
  part_str = parts_array.first[:part].to_s
649
- id.part = Components::Code.new(value: part_str)
649
+ id.part = part_str
650
650
  end
651
651
  # Handle space-separated part (direct part attribute)
652
652
  elsif space_separated_part_val
653
- id.part = Components::Code.new(value: space_separated_part_val.to_s)
653
+ id.part = space_separated_part_val.to_s
654
654
  # Mark this part as space-separated for rendering
655
655
  id.space_separated_part = true
656
656
  end
@@ -790,8 +790,10 @@ module Pubid
790
790
  corrigendum = !amd_data[:corrigendum].nil?
791
791
  parenthesized = !data[:parenthesized_amd].nil?
792
792
 
793
+ # NOTE `amd_data[:amendment_number]` above is a PARSE-TREE key and keeps
794
+ # its name; only the attribute moved to `number`.
793
795
  attrs = {
794
- amendment_number: Components::Code.new(value: amendment_number),
796
+ number: Components::Code.new(value: amendment_number),
795
797
  corrigendum: corrigendum,
796
798
  parenthesized: parenthesized,
797
799
  }
@@ -809,8 +811,10 @@ module Pubid
809
811
  # Could also use a more sophisticated algorithm for year conversion
810
812
  full_year = year_val ? "20#{year_val}" : nil
811
813
 
814
+ # NOTE `data[:document_number]` above is a PARSE-TREE key and keeps its
815
+ # name; only the attribute moved to `number`.
812
816
  attrs = {
813
- document_number: document_number,
817
+ number: Components::Code.new(value: document_number),
814
818
  }
815
819
  attrs[:date] = Components::Date.new(year: full_year.to_i) if full_year
816
820
 
@@ -969,7 +973,7 @@ module Pubid
969
973
  value&.to_s
970
974
 
971
975
  when :number
972
- Components::Code.new(value: value.to_s)
976
+ value.to_s
973
977
 
974
978
  when :parts
975
979
  # Extract parts - handle both formats:
@@ -983,26 +987,25 @@ module Pubid
983
987
  # Check if subpart is already separated (new format from part_with_subpart rule)
984
988
  if first_part.key?(:subpart)
985
989
  {
986
- part: Components::Code.new(value: part_str),
987
- subpart: Components::Code.new(value: first_part[:subpart].to_s),
990
+ part: part_str,
991
+ subpart: first_part[:subpart].to_s,
988
992
  }
989
993
  else
990
994
  # Old format - split on dash to get part and subpart
991
995
  part_components = part_str.split("-")
992
- result = { part: Components::Code.new(value: part_components.first) }
996
+ result = { part: part_components.first }
993
997
  if part_components.length > 1
994
- result[:subpart] =
995
- Components::Code.new(value: part_components[1])
998
+ result[:subpart] = part_components[1]
996
999
  end
997
1000
  result
998
1001
  end
999
1002
  end
1000
1003
 
1001
1004
  when :part
1002
- Components::Code.new(value: value[:part].to_s) if value.is_a?(Hash)
1005
+ value[:part].to_s if value.is_a?(Hash)
1003
1006
 
1004
1007
  when :subpart
1005
- Components::Code.new(value: value.to_s)
1008
+ value.to_s
1006
1009
 
1007
1010
  when :year, :date
1008
1011
  # Only create date if value is present
@@ -1323,8 +1326,15 @@ module Pubid
1323
1326
 
1324
1327
  adopted_id = nil
1325
1328
 
1326
- # Check for EN ISO or EN IEC patterns (triple-level)
1327
- if adopted_str_clean.match?(/EN\s+(ISO\/IEC|IEC|ISO)/)
1329
+ # Check for EN ISO or EN IEC patterns (triple-level).
1330
+ # The test must be ANCHORED, because the repair below is: an unanchored
1331
+ # match accepts "CEN ISO/TS 12180-1:2007" (the "EN ISO" is inside
1332
+ # "CEN ISO"), but `sub(/^EN\s+/, "")` then changes nothing, so
1333
+ # adopted_id stayed nil and the whole parse returned nil for 49
1334
+ # "DD CEN ISO/..." identifiers in BSI's own pass fixtures. Anchored,
1335
+ # a "CEN ..." string falls through to the CEN branch below, which is
1336
+ # where it belongs.
1337
+ if adopted_str_clean.match?(/\AEN\s+(ISO\/IEC|IEC|ISO)/)
1328
1338
  # Parse the ISO/IEC part
1329
1339
  iso_iec_str = adopted_str_clean.sub(/^EN\s+/, "")
1330
1340
 
@@ -1336,11 +1346,11 @@ module Pubid
1336
1346
  adopted_id = Pubid::Iec.parse(iso_iec_str)
1337
1347
  end
1338
1348
 
1339
- # Wrap ISO/IEC identifier in EN adoption
1349
+ # Wrap ISO/IEC identifier in EN adoption (the publisher is the
1350
+ # "EN" default)
1340
1351
  if adopted_id
1341
1352
  adopted_id = Pubid::CenCenelec::Identifiers::AdoptedEuropeanNorm.new(
1342
- publisher: ["EN"],
1343
- adopted_identifier: adopted_id,
1353
+ adopted: adopted_id,
1344
1354
  )
1345
1355
  end
1346
1356
 
@@ -1373,7 +1383,7 @@ module Pubid
1373
1383
  identifier = if adopted_id.class.name.start_with?("Pubid::CenCenelec::")
1374
1384
  Identifiers::AdoptedEuropeanNorm.new(
1375
1385
  publisher: Components::Publisher.new(body: bsi_prefix),
1376
- adopted_identifier: adopted_id,
1386
+ adopted: adopted_id,
1377
1387
  edition: final_edition&.to_s,
1378
1388
  translation_lang: data[:translation_lang]&.to_s,
1379
1389
  translation_upper: data[:translation_upper]&.to_s,
@@ -1386,7 +1396,7 @@ module Pubid
1386
1396
  # Otherwise it's ISO/IEC, use AdoptedInternationalStandard
1387
1397
  Identifiers::AdoptedInternationalStandard.new(
1388
1398
  publisher: Components::Publisher.new(body: bsi_prefix),
1389
- adopted_identifier: adopted_id,
1399
+ adopted: adopted_id,
1390
1400
  edition: final_edition&.to_s,
1391
1401
  translation_lang: data[:translation_lang]&.to_s,
1392
1402
  translation_upper: data[:translation_upper]&.to_s,
@@ -1,11 +1,17 @@
1
- # frozen_string_literal: true
1
+ # frozen_string: true
2
2
 
3
3
  module Pubid
4
4
  module Bsi
5
5
  module Components
6
- # Date component for BSI flavor
7
- class Date < Pubid::Components::Date
8
- end
6
+ # BSI has no date semantics of its own, so this is the shared
7
+ # component, not a subclass: an empty `class Date <
8
+ # Pubid::Components::Date` rejected the shared instances a nested
9
+ # cross-flavor adopted identifier carries (pubid#379 — the adoption
10
+ # wrappers delegate `date` to the foreign object), and made `==`
11
+ # compare the parsed instance against the deserialized one by class.
12
+ # Aliased so the builder's `Components::Date.new` call sites construct
13
+ # the shared class.
14
+ Date = ::Pubid::Components::Date
9
15
  end
10
16
  end
11
17
  end
@@ -7,7 +7,7 @@ module Pubid
7
7
  # Example: "BS EN 10077-1:2006" where EN 10077-1:2006 is a CEN identifier object
8
8
  # Example: "BS EN ISO 8601:2019" where EN ISO 8601:2019 is a CEN AdoptedEuropeanNorm wrapping ISO
9
9
  class AdoptedEuropeanNorm < BritishStandard
10
- attribute :adopted_identifier, ::Pubid::Identifier, polymorphic: true # CEN object
10
+ attribute :adopted, ::Pubid::Identifier, polymorphic: true # CEN object
11
11
  attribute :edition, :string
12
12
  attribute :translation_lang, :string
13
13
  attribute :translation_upper, :string
@@ -25,29 +25,58 @@ module Pubid
25
25
  nil
26
26
  end
27
27
 
28
+ # Walk to the adopted document for the relaton-index key.
29
+ #
30
+ # The `#number` delegation below is not enough on its own: a
31
+ # "DD ENV ISO 11079:1999" adopts a CenCenelec EuropeanPrestandard,
32
+ # which is ITSELF a wrapper around the ISO standard, so the delegation
33
+ # returned that wrapper's own (nil) number and the chain died one level
34
+ # short. `#root` recurses, so it reaches the ISO standard however many
35
+ # adoption layers sit in between.
36
+ def root
37
+ adopted ? adopted.root : self
38
+ end
39
+
28
40
  # Delegate common methods to adopted identifier
29
41
  def number
30
- adopted_identifier&.number
42
+ delegate_target&.number
31
43
  end
32
44
 
33
45
  def year
34
- adopted_identifier&.year if adopted_identifier&.methods&.include?(:year)
46
+ delegate_target&.year if delegate_target&.methods&.include?(:year)
35
47
  end
36
48
 
37
49
  def date
38
- adopted_identifier&.date if adopted_identifier&.methods&.include?(:date)
50
+ delegate_target&.date if delegate_target&.methods&.include?(:date)
39
51
  end
40
52
 
41
53
  def parts
42
- adopted_identifier&.parts if adopted_identifier&.methods&.include?(:parts)
54
+ delegate_target&.parts if delegate_target&.methods&.include?(:parts)
43
55
  end
44
56
 
45
57
  def part
46
- adopted_identifier&.part if adopted_identifier&.methods&.include?(:part)
58
+ delegate_target&.part if delegate_target&.methods&.include?(:part)
47
59
  end
48
60
 
49
61
  def subpart
50
- adopted_identifier&.subpart if adopted_identifier&.methods&.include?(:subpart)
62
+ adopted&.subpart if adopted&.methods&.include?(:subpart)
63
+ end
64
+
65
+ private
66
+
67
+ # The identifier that holds the number, part and date. For
68
+ # "BS EN ISO 8848:2021" the adopted document is a CEN adoption of an
69
+ # ISO standard, and the CEN adoption keeps no number of its own, so
70
+ # read through it to the ISO standard. The CEN class used to do this
71
+ # with delegating readers, which broke its serialization. `subpart`
72
+ # keeps reading the CEN object, as it did before.
73
+ def delegate_target
74
+ target = adopted
75
+ if target.is_a?(::Pubid::CenCenelec::Identifiers::AdoptedEuropeanNorm)
76
+ target.adopted
77
+ else
78
+ target
79
+ end
51
80
  end
52
81
  end
53
82
  end
@@ -7,7 +7,8 @@ module Pubid
7
7
  # Example: "BS ISO 8601:2019" where ISO 8601:2019 is an ISO identifier object
8
8
  # Example: "BS IEC 62600:2020" where IEC 62600:2020 is an IEC identifier object
9
9
  class AdoptedInternationalStandard < BritishStandard
10
- attribute :adopted_identifier, ::Pubid::Identifier, polymorphic: true # ISO/IEC object
10
+ # The adopted ISO/IEC identifier object
11
+ attribute :adopted, ::Pubid::Identifier, polymorphic: true
11
12
  attribute :edition, :string
12
13
  attribute :translation_lang, :string
13
14
  attribute :translation_upper, :string
@@ -27,23 +28,23 @@ module Pubid
27
28
 
28
29
  # Delegate common methods to adopted identifier
29
30
  def number
30
- adopted_identifier&.number
31
+ adopted&.number
31
32
  end
32
33
 
33
34
  def year
34
- adopted_identifier&.year if adopted_identifier&.methods&.include?(:year)
35
+ adopted&.year if adopted&.methods&.include?(:year)
35
36
  end
36
37
 
37
38
  def date
38
- adopted_identifier&.date if adopted_identifier&.methods&.include?(:date)
39
+ adopted&.date if adopted&.methods&.include?(:date)
39
40
  end
40
41
 
41
42
  def parts
42
- adopted_identifier&.parts if adopted_identifier&.methods&.include?(:parts)
43
+ adopted&.parts if adopted&.methods&.include?(:parts)
43
44
  end
44
45
 
45
46
  def part
46
- adopted_identifier&.part if adopted_identifier&.methods&.include?(:part)
47
+ adopted&.part if adopted&.methods&.include?(:part)
47
48
  end
48
49
  end
49
50
  end
@@ -6,8 +6,7 @@ module Pubid
6
6
  # British Industrial Practice (BIP)
7
7
  # Examples: "BIP 2225:2022", "BIP 0142:2014", "BIP 0009:2020"
8
8
  class BritishIndustrialPractice < SingleIdentifier
9
- attribute :number, Bsi::Components::Code
10
- attribute :date, Bsi::Components::Date
9
+
11
10
 
12
11
  def self.type
13
12
  {
@@ -24,6 +24,16 @@ module Pubid
24
24
  # Compare first identifier
25
25
  identifiers.first <=> other.identifiers.first
26
26
  end
27
+
28
+ # A bundle carries no number of its own — each member holds one — so
29
+ # `root.number`, the key relaton-index sorts and bsearches on, was "".
30
+ # Walk to the first member, the shape ConsolidatedIdentifier already
31
+ # uses. Members of one bundle are consecutive numbers of a single
32
+ # series, so the bundle files under the first, and `<=>` above orders
33
+ # bundles by that same member.
34
+ def root
35
+ identifiers&.first ? identifiers.first.root : self
36
+ end
27
37
  end
28
38
  end
29
39
  end
@@ -11,7 +11,16 @@ module Pubid
11
11
  # 21/30445138 DC
12
12
  # 24/30300822 DC
13
13
  class CommitteeDocument < SingleIdentifier
14
- attribute :document_number, :string # The 8-digit document number
14
+ # The 8-digit document number lives in the `number` inherited from
15
+ # SingleIdentifier (a Bsi::Components::Code). It used to be a separate
16
+ # `document_number` :string, which left `number` nil — so `root.number`,
17
+ # the key relaton-index sorts and bsearches on, was "".
18
+ #
19
+ # The duplicate is DELETED rather than mirrored into `number`: keeping
20
+ # both would emit the same digits twice in `to_hash`, and a derived
21
+ # `#number` method is not available here because `number` is a lutaml
22
+ # attribute, whose generated accessor such a method would collide with.
23
+ # Nothing is retyped — the inherited attribute is already a Code.
15
24
 
16
25
  # TYPED_STAGES for committee documents (draft by default)
17
26
  TYPED_STAGES = [
@@ -6,9 +6,7 @@ module Pubid
6
6
  # BSI Handbook
7
7
  # Examples: "Handbook 17:1963", "HB 10146:1998"
8
8
  class Handbook < SingleIdentifier
9
- attribute :number, Bsi::Components::Code
10
- attribute :part, Bsi::Components::Code
11
- attribute :date, Bsi::Components::Date
9
+
12
10
  attribute :original_abbr, :string # Preserve "Handbook" or "HB"
13
11
 
14
12
  def self.type
@@ -6,8 +6,7 @@ module Pubid
6
6
  # BSI Practice Guide (PP - Published Practice)
7
7
  # Examples: "PP 888:1982", "PP 7307:1986", "PP 7722:2006"
8
8
  class PracticeGuide < SingleIdentifier
9
- attribute :number, Bsi::Components::Code
10
- attribute :date, Bsi::Components::Date
9
+
11
10
 
12
11
  def self.type
13
12
  {
@@ -23,6 +23,17 @@ module Pubid
23
23
  # Compare first identifier
24
24
  identifiers.first <=> other.identifiers.first
25
25
  end
26
+
27
+ # As for BundledIdentifier: a set holds no number of its own, so walk
28
+ # to the first member for the relaton-index key.
29
+ #
30
+ # NOTE the members are frequently a FOREIGN flavor (BS ISO ... holds
31
+ # Pubid::Iso identifiers), which `to_hash` still rejects — see the
32
+ # hand-off bsi-set-cross-flavor-type. `#root` is unaffected by that:
33
+ # it only reads the object, never serializes it.
34
+ def root
35
+ identifiers&.first ? identifiers.first.root : self
36
+ end
26
37
  end
27
38
  end
28
39
  end
@@ -6,7 +6,16 @@ module Pubid
6
6
  # Standalone Amendment identifier (no base reference)
7
7
  # Examples: "AMD 11015", "(AMD 10971)", "AMD Corrigendum 14716"
8
8
  class StandaloneAmendment < SingleIdentifier
9
- attribute :amendment_number, Components::Code
9
+ # The amendment number lives in the `number` inherited from
10
+ # SingleIdentifier — already a Bsi::Components::Code, exactly what the
11
+ # deleted `amendment_number` was, so nothing is retyped. It used to sit
12
+ # under the private name, leaving `number` nil and `root.number` "".
13
+ #
14
+ # A standalone amendment is its OWN document (there is no base standard
15
+ # to walk to — that is what "standalone" means), so it needs a real
16
+ # number rather than a #root override. `Identifiers::Amendment`, the
17
+ # attached kind, keeps its own `amendment_number` and is untouched:
18
+ # there the ordinal is a supplement ordinal, not the document number.
10
19
  attribute :corrigendum, :boolean, default: false
11
20
  attribute :parenthesized, :boolean, default: false
12
21
 
@@ -4,7 +4,7 @@ require "parslet"
4
4
 
5
5
  module Pubid
6
6
  module Bsi
7
- class Parser < Parslet::Parser
7
+ class Parser < ::Pubid::Parser::Grammar
8
8
  # Case-insensitive string match (Parslet 2.0 has no built-in `stri`).
9
9
  # Each character becomes a two-case character class; other characters
10
10
  # (spaces, punctuation) match verbatim.