pubid 2.0.0.pre.alpha.1 → 2.0.0.pre.alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. checksums.yaml +4 -4
  2. data/README.adoc +5 -1
  3. data/data/nist/update_codes.yaml +27 -0
  4. data/lib/pubid/amca/builder.rb +2 -2
  5. data/lib/pubid/amca/identifier.rb +7 -0
  6. data/lib/pubid/amca/identifiers/base.rb +0 -26
  7. data/lib/pubid/amca/identifiers/interpretation.rb +0 -17
  8. data/lib/pubid/amca/identifiers/publication.rb +0 -13
  9. data/lib/pubid/amca/renderer.rb +82 -0
  10. data/lib/pubid/amca/single_identifier.rb +0 -23
  11. data/lib/pubid/amca/urn_parser.rb +28 -0
  12. data/lib/pubid/amca.rb +42 -1
  13. data/lib/pubid/ansi/builder.rb +5 -3
  14. data/lib/pubid/ansi/identifier.rb +1 -1
  15. data/lib/pubid/ansi/identifiers/american_national_standard.rb +2 -1
  16. data/lib/pubid/ansi/identifiers/standard.rb +2 -3
  17. data/lib/pubid/ansi/renderer.rb +53 -0
  18. data/lib/pubid/ansi/single_identifier.rb +2 -31
  19. data/lib/pubid/ansi/urn_generator.rb +3 -38
  20. data/lib/pubid/ansi/urn_parser.rb +23 -0
  21. data/lib/pubid/ansi.rb +38 -3
  22. data/lib/pubid/api/builder.rb +29 -74
  23. data/lib/pubid/api/identifier.rb +0 -4
  24. data/lib/pubid/api/identifiers/base.rb +0 -2
  25. data/lib/pubid/api/identifiers/bulletin.rb +0 -2
  26. data/lib/pubid/api/identifiers/continuous_operations_standard.rb +0 -2
  27. data/lib/pubid/api/identifiers/mpms.rb +1 -17
  28. data/lib/pubid/api/identifiers/publication.rb +0 -2
  29. data/lib/pubid/api/identifiers/recommended_practice.rb +0 -2
  30. data/lib/pubid/api/identifiers/specification.rb +0 -2
  31. data/lib/pubid/api/identifiers/standard.rb +0 -2
  32. data/lib/pubid/api/identifiers/technical_report.rb +0 -2
  33. data/lib/pubid/api/identifiers/typeless_standard.rb +1 -14
  34. data/lib/pubid/api/identifiers.rb +18 -0
  35. data/lib/pubid/api/renderer.rb +89 -0
  36. data/lib/pubid/api/single_identifier.rb +1 -13
  37. data/lib/pubid/api/urn_generator.rb +0 -18
  38. data/lib/pubid/api/urn_parser.rb +35 -0
  39. data/lib/pubid/api.rb +51 -5
  40. data/lib/pubid/ashrae/builder.rb +3 -3
  41. data/lib/pubid/ashrae/identifier.rb +6 -0
  42. data/lib/pubid/ashrae/identifiers/addenda_package.rb +0 -10
  43. data/lib/pubid/ashrae/identifiers/addendum.rb +0 -19
  44. data/lib/pubid/ashrae/identifiers/base.rb +3 -0
  45. data/lib/pubid/ashrae/identifiers/combined_addenda.rb +0 -15
  46. data/lib/pubid/ashrae/identifiers/errata.rb +0 -10
  47. data/lib/pubid/ashrae/identifiers/interpretation.rb +0 -10
  48. data/lib/pubid/ashrae/renderer.rb +117 -0
  49. data/lib/pubid/ashrae/single_identifier.rb +0 -13
  50. data/lib/pubid/ashrae/urn_generator.rb +0 -8
  51. data/lib/pubid/ashrae/urn_parser.rb +27 -0
  52. data/lib/pubid/ashrae.rb +42 -1
  53. data/lib/pubid/asme/components/code.rb +10 -2
  54. data/lib/pubid/asme/identifiers/base.rb +0 -60
  55. data/lib/pubid/asme/renderer.rb +66 -0
  56. data/lib/pubid/asme/urn_parser.rb +31 -0
  57. data/lib/pubid/asme.rb +42 -1
  58. data/lib/pubid/astm/components/code.rb +9 -0
  59. data/lib/pubid/{jis → astm}/components.rb +1 -1
  60. data/lib/pubid/astm/identifiers/adjunct.rb +0 -8
  61. data/lib/pubid/astm/identifiers/data_series.rb +0 -14
  62. data/lib/pubid/astm/identifiers/iso_dual_published.rb +9 -34
  63. data/lib/pubid/astm/identifiers/manual.rb +0 -27
  64. data/lib/pubid/astm/identifiers/monograph.rb +0 -14
  65. data/lib/pubid/astm/identifiers/research_report.rb +0 -7
  66. data/lib/pubid/astm/identifiers/standard.rb +0 -39
  67. data/lib/pubid/astm/identifiers/technical_report.rb +0 -13
  68. data/lib/pubid/astm/identifiers/work_in_progress.rb +0 -11
  69. data/lib/pubid/astm/identifiers.rb +18 -0
  70. data/lib/pubid/astm/renderer.rb +172 -0
  71. data/lib/pubid/astm/single_identifier.rb +0 -10
  72. data/lib/pubid/astm/urn_parser.rb +30 -0
  73. data/lib/pubid/astm.rb +39 -27
  74. data/lib/pubid/bsi/builder.rb +21 -12
  75. data/lib/pubid/bsi/identifier.rb +8 -2
  76. data/lib/pubid/bsi/identifiers/addendum_document.rb +3 -33
  77. data/lib/pubid/bsi/identifiers/adopted_european_norm.rb +11 -47
  78. data/lib/pubid/bsi/identifiers/adopted_international_standard.rb +11 -38
  79. data/lib/pubid/bsi/identifiers/aerospace_standard.rb +3 -53
  80. data/lib/pubid/bsi/identifiers/amendment.rb +3 -19
  81. data/lib/pubid/bsi/identifiers/british_industrial_practice.rb +2 -4
  82. data/lib/pubid/bsi/identifiers/british_standard.rb +2 -1
  83. data/lib/pubid/bsi/identifiers/bundled_identifier.rb +3 -84
  84. data/lib/pubid/bsi/identifiers/committee_document.rb +1 -14
  85. data/lib/pubid/bsi/identifiers/consolidated_identifier.rb +3 -84
  86. data/lib/pubid/bsi/identifiers/corrigendum.rb +3 -7
  87. data/lib/pubid/bsi/identifiers/detailed_specification.rb +1 -34
  88. data/lib/pubid/bsi/identifiers/disc.rb +1 -27
  89. data/lib/pubid/bsi/identifiers/draft_document.rb +3 -44
  90. data/lib/pubid/bsi/identifiers/electronic_book.rb +3 -36
  91. data/lib/pubid/bsi/identifiers/expert_commentary.rb +3 -15
  92. data/lib/pubid/bsi/identifiers/explanatory_supplement.rb +1 -45
  93. data/lib/pubid/bsi/identifiers/flex.rb +1 -33
  94. data/lib/pubid/bsi/identifiers/handbook.rb +2 -13
  95. data/lib/pubid/bsi/identifiers/index.rb +1 -30
  96. data/lib/pubid/bsi/identifiers/method.rb +1 -39
  97. data/lib/pubid/bsi/identifiers/national_annex.rb +5 -27
  98. data/lib/pubid/bsi/identifiers/practice_guide.rb +2 -4
  99. data/lib/pubid/bsi/identifiers/publicly_available_specification.rb +3 -52
  100. data/lib/pubid/bsi/identifiers/published_document.rb +3 -52
  101. data/lib/pubid/bsi/identifiers/section.rb +1 -28
  102. data/lib/pubid/bsi/identifiers/set.rb +3 -17
  103. data/lib/pubid/bsi/identifiers/standalone_amendment.rb +1 -7
  104. data/lib/pubid/bsi/identifiers/supplement_document.rb +3 -21
  105. data/lib/pubid/bsi/identifiers/supplementary_index.rb +1 -44
  106. data/lib/pubid/bsi/identifiers/technical_specification.rb +3 -45
  107. data/lib/pubid/bsi/identifiers/test_method.rb +1 -30
  108. data/lib/pubid/bsi/identifiers/value_added_publication.rb +3 -14
  109. data/lib/pubid/bsi/identifiers.rb +0 -1
  110. data/lib/pubid/bsi/renderer.rb +1050 -0
  111. data/lib/pubid/bsi/single_identifier.rb +6 -70
  112. data/lib/pubid/bsi/urn_generator.rb +2 -3
  113. data/lib/pubid/bsi/urn_parser.rb +52 -0
  114. data/lib/pubid/bsi.rb +224 -1
  115. data/lib/pubid/builder/base.rb +57 -10
  116. data/lib/pubid/bundled_identifier.rb +0 -1
  117. data/lib/pubid/ccsds/builder.rb +4 -3
  118. data/lib/pubid/ccsds/identifier.rb +66 -1
  119. data/lib/pubid/ccsds/identifiers/base.rb +11 -50
  120. data/lib/pubid/ccsds/identifiers/corrigendum.rb +7 -6
  121. data/lib/pubid/ccsds/parser.rb +4 -2
  122. data/lib/pubid/ccsds/single_identifier.rb +4 -1
  123. data/lib/pubid/ccsds/supplement_identifier.rb +15 -11
  124. data/lib/pubid/ccsds/urn_generator.rb +3 -3
  125. data/lib/pubid/ccsds/urn_parser.rb +20 -0
  126. data/lib/pubid/ccsds.rb +39 -1
  127. data/lib/pubid/cen_cenelec/builder.rb +12 -14
  128. data/lib/pubid/cen_cenelec/identifier.rb +8 -2
  129. data/lib/pubid/cen_cenelec/identifiers/adopted_european_norm.rb +13 -4
  130. data/lib/pubid/cen_cenelec/identifiers/amendment.rb +2 -8
  131. data/lib/pubid/cen_cenelec/identifiers/base.rb +5 -41
  132. data/lib/pubid/cen_cenelec/identifiers/cen_report.rb +2 -1
  133. data/lib/pubid/cen_cenelec/identifiers/cen_workshop_agreement.rb +2 -1
  134. data/lib/pubid/cen_cenelec/identifiers/consolidated_identifier.rb +2 -25
  135. data/lib/pubid/cen_cenelec/identifiers/corrigendum.rb +2 -13
  136. data/lib/pubid/cen_cenelec/identifiers/european_norm.rb +2 -1
  137. data/lib/pubid/cen_cenelec/identifiers/european_prestandard.rb +4 -7
  138. data/lib/pubid/cen_cenelec/identifiers/european_specification.rb +2 -1
  139. data/lib/pubid/cen_cenelec/identifiers/fragment.rb +2 -2
  140. data/lib/pubid/cen_cenelec/identifiers/harmonization_document.rb +2 -1
  141. data/lib/pubid/cen_cenelec/identifiers/technical_report.rb +2 -1
  142. data/lib/pubid/cen_cenelec/identifiers/technical_specification.rb +2 -1
  143. data/lib/pubid/cen_cenelec/renderer.rb +261 -0
  144. data/lib/pubid/cen_cenelec/single_identifier.rb +11 -89
  145. data/lib/pubid/cen_cenelec/urn_generator.rb +6 -6
  146. data/lib/pubid/cen_cenelec/urn_parser.rb +28 -0
  147. data/lib/pubid/cen_cenelec.rb +168 -1
  148. data/lib/pubid/cie/components/code.rb +8 -0
  149. data/lib/pubid/cie/identifier.rb +6 -4
  150. data/lib/pubid/cie/urn_parser.rb +28 -0
  151. data/lib/pubid/cie.rb +43 -1
  152. data/lib/pubid/components/adoption.rb +104 -0
  153. data/lib/pubid/components/code.rb +22 -8
  154. data/lib/pubid/components/date.rb +23 -16
  155. data/lib/pubid/components/edition.rb +9 -6
  156. data/lib/pubid/components/iteration.rb +32 -0
  157. data/lib/pubid/components/language.rb +6 -4
  158. data/lib/pubid/components/locality.rb +10 -1
  159. data/lib/pubid/components/publisher.rb +9 -6
  160. data/lib/pubid/components/relationship.rb +151 -0
  161. data/lib/pubid/components/stage.rb +5 -14
  162. data/lib/pubid/components/supplement.rb +184 -0
  163. data/lib/pubid/components/type.rb +5 -15
  164. data/lib/pubid/components/typed_stage.rb +11 -8
  165. data/lib/pubid/components.rb +4 -0
  166. data/lib/pubid/core/update_codes.rb +28 -7
  167. data/lib/pubid/csa/identifier.rb +0 -3
  168. data/lib/pubid/csa/identifiers/base.rb +2 -122
  169. data/lib/pubid/csa/identifiers/cec.rb +2 -101
  170. data/lib/pubid/csa/identifiers/series.rb +2 -102
  171. data/lib/pubid/csa/renderer.rb +292 -0
  172. data/lib/pubid/csa/urn_generator.rb +1 -1
  173. data/lib/pubid/csa/urn_parser.rb +33 -0
  174. data/lib/pubid/csa.rb +42 -1
  175. data/lib/pubid/etsi/components/code.rb +9 -2
  176. data/lib/pubid/etsi/identifiers/base.rb +1 -4
  177. data/lib/pubid/etsi/identifiers/supplement_identifier.rb +2 -9
  178. data/lib/pubid/etsi/renderer.rb +42 -0
  179. data/lib/pubid/etsi/urn_parser.rb +34 -0
  180. data/lib/pubid/etsi.rb +42 -1
  181. data/lib/pubid/export/exporter.rb +4 -46
  182. data/lib/pubid/export/flavor_exporter.rb +111 -278
  183. data/lib/pubid/export.rb +0 -6
  184. data/lib/pubid/identifier.rb +10 -18
  185. data/lib/pubid/identifier_facade.rb +114 -0
  186. data/lib/pubid/identifier_metadata.rb +1 -1
  187. data/lib/pubid/idf/builder.rb +3 -3
  188. data/lib/pubid/idf/identifier.rb +3 -6
  189. data/lib/pubid/idf/identifiers/amendment.rb +2 -1
  190. data/lib/pubid/idf/identifiers/corrigendum.rb +2 -1
  191. data/lib/pubid/idf/identifiers/international_standard.rb +2 -1
  192. data/lib/pubid/idf/identifiers/reviewed_method.rb +2 -1
  193. data/lib/pubid/idf/parser.rb +3 -2
  194. data/lib/pubid/idf/renderer.rb +84 -0
  195. data/lib/pubid/idf/supplement_identifier.rb +2 -10
  196. data/lib/pubid/idf/urn_generator.rb +4 -39
  197. data/lib/pubid/idf/urn_parser.rb +25 -0
  198. data/lib/pubid/idf.rb +51 -1
  199. data/lib/pubid/iec/builder.rb +48 -65
  200. data/lib/pubid/iec/components/code.rb +9 -32
  201. data/lib/pubid/iec/components/publisher.rb +1 -1
  202. data/lib/pubid/iec/components.rb +14 -0
  203. data/lib/pubid/iec/identifier.rb +276 -3
  204. data/lib/pubid/iec/identifiers/amendment.rb +2 -3
  205. data/lib/pubid/iec/identifiers/base.rb +8 -28
  206. data/lib/pubid/iec/identifiers/component_specification.rb +3 -3
  207. data/lib/pubid/iec/identifiers/conformity_assessment.rb +1 -2
  208. data/lib/pubid/iec/identifiers/consolidated_identifier.rb +27 -30
  209. data/lib/pubid/iec/identifiers/corrigendum.rb +2 -3
  210. data/lib/pubid/iec/identifiers/fragment_identifier.rb +37 -26
  211. data/lib/pubid/iec/identifiers/guide.rb +0 -2
  212. data/lib/pubid/iec/identifiers/international_standard.rb +2 -3
  213. data/lib/pubid/iec/identifiers/interpretation_sheet.rb +2 -3
  214. data/lib/pubid/iec/identifiers/operational_document.rb +3 -3
  215. data/lib/pubid/iec/identifiers/publicly_available_specification.rb +2 -3
  216. data/lib/pubid/iec/identifiers/sheet_identifier.rb +21 -15
  217. data/lib/pubid/iec/identifiers/societal_technology_trend_report.rb +3 -3
  218. data/lib/pubid/iec/identifiers/systems_reference_document.rb +2 -3
  219. data/lib/pubid/iec/identifiers/technical_report.rb +2 -3
  220. data/lib/pubid/iec/identifiers/technical_specification.rb +2 -3
  221. data/lib/pubid/iec/identifiers/technology_report.rb +1 -2
  222. data/lib/pubid/iec/identifiers/test_report_form.rb +5 -34
  223. data/lib/pubid/iec/identifiers/vap_identifier.rb +26 -23
  224. data/lib/pubid/iec/identifiers/white_paper.rb +3 -3
  225. data/lib/pubid/iec/identifiers/working_document.rb +4 -48
  226. data/lib/pubid/iec/identifiers.rb +30 -0
  227. data/lib/pubid/iec/parser.rb +20 -14
  228. data/lib/pubid/iec/renderer.rb +254 -0
  229. data/lib/pubid/iec/single_identifier.rb +6 -12
  230. data/lib/pubid/iec/supplement_identifier.rb +58 -54
  231. data/lib/pubid/iec/urn_generator.rb +57 -171
  232. data/lib/pubid/iec/urn_parser.rb +53 -252
  233. data/lib/pubid/iec.rb +40 -68
  234. data/lib/pubid/ieee/builder.rb +12 -12
  235. data/lib/pubid/ieee/components/code.rb +8 -0
  236. data/lib/pubid/ieee/components/draft.rb +14 -0
  237. data/lib/pubid/ieee/components/relationship.rb +5 -149
  238. data/lib/pubid/ieee/identifier.rb +6 -0
  239. data/lib/pubid/ieee/identifiers/adopted_standard.rb +1 -6
  240. data/lib/pubid/ieee/identifiers/base.rb +101 -458
  241. data/lib/pubid/ieee/identifiers/conformance_identifier.rb +1 -7
  242. data/lib/pubid/ieee/identifiers/corrigendum.rb +1 -9
  243. data/lib/pubid/ieee/identifiers/csa_dual_published.rb +1 -7
  244. data/lib/pubid/ieee/identifiers/dual_identifier.rb +1 -1
  245. data/lib/pubid/ieee/identifiers/dual_published.rb +1 -1
  246. data/lib/pubid/ieee/identifiers/iec_ieee_copublished.rb +1 -6
  247. data/lib/pubid/ieee/identifiers/interpretation_identifier.rb +1 -7
  248. data/lib/pubid/ieee/identifiers/joint_development.rb +2 -0
  249. data/lib/pubid/ieee/identifiers/multi_numbered_identifier.rb +1 -15
  250. data/lib/pubid/ieee/identifiers/parenthetical_identifier.rb +1 -3
  251. data/lib/pubid/ieee/identifiers/project_draft_identifier.rb +15 -0
  252. data/lib/pubid/ieee/identifiers/redlined_standard.rb +1 -4
  253. data/lib/pubid/ieee/identifiers/si_standard.rb +1 -35
  254. data/lib/pubid/ieee/identifiers/standard.rb +1 -1
  255. data/lib/pubid/ieee/pre_parser.rb +301 -0
  256. data/lib/pubid/ieee/renderer.rb +307 -0
  257. data/lib/pubid/ieee/urn_parser.rb +34 -0
  258. data/lib/pubid/ieee.rb +62 -1
  259. data/lib/pubid/ieee_debug.rb +0 -1
  260. data/lib/pubid/iho/builder.rb +2 -2
  261. data/lib/pubid/iho/identifier.rb +8 -0
  262. data/lib/pubid/iho/identifiers/base.rb +49 -10
  263. data/lib/pubid/iho/identifiers/bibliographic.rb +0 -4
  264. data/lib/pubid/iho/identifiers/circular_letter.rb +0 -4
  265. data/lib/pubid/iho/identifiers/miscellaneous.rb +0 -4
  266. data/lib/pubid/iho/identifiers/publication.rb +0 -4
  267. data/lib/pubid/iho/identifiers/standard.rb +0 -4
  268. data/lib/pubid/iho/parser.rb +3 -3
  269. data/lib/pubid/iho/renderer.rb +30 -0
  270. data/lib/pubid/iho/urn_generator.rb +3 -3
  271. data/lib/pubid/iho/urn_parser.rb +58 -0
  272. data/lib/pubid/iho.rb +50 -1
  273. data/lib/pubid/iso/builder.rb +59 -53
  274. data/lib/pubid/iso/bundled_identifier.rb +51 -0
  275. data/lib/pubid/iso/components/code.rb +7 -19
  276. data/lib/pubid/iso/components/publisher.rb +10 -8
  277. data/lib/pubid/iso/components.rb +2 -4
  278. data/lib/pubid/iso/identifier.rb +233 -6
  279. data/lib/pubid/iso/identifiers/addendum.rb +9 -6
  280. data/lib/pubid/iso/identifiers/amendment.rb +8 -4
  281. data/lib/pubid/iso/identifiers/corrigendum.rb +4 -4
  282. data/lib/pubid/iso/identifiers/data.rb +0 -1
  283. data/lib/pubid/iso/identifiers/directives.rb +8 -2
  284. data/lib/pubid/iso/identifiers/directives_supplement.rb +43 -14
  285. data/lib/pubid/iso/identifiers/extract.rb +2 -2
  286. data/lib/pubid/iso/identifiers/guide.rb +0 -1
  287. data/lib/pubid/iso/identifiers/international_standard.rb +4 -4
  288. data/lib/pubid/iso/identifiers/international_standardized_profile.rb +4 -4
  289. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +10 -4
  290. data/lib/pubid/iso/identifiers/pas.rb +2 -2
  291. data/lib/pubid/iso/identifiers/recommendation.rb +2 -2
  292. data/lib/pubid/iso/identifiers/supplement.rb +11 -3
  293. data/lib/pubid/iso/identifiers/tc_document.rb +44 -15
  294. data/lib/pubid/iso/identifiers/technical_report.rb +4 -4
  295. data/lib/pubid/iso/identifiers/technical_specification.rb +2 -2
  296. data/lib/pubid/iso/identifiers/technology_trends_assessments.rb +2 -2
  297. data/lib/pubid/iso/identifiers.rb +0 -1
  298. data/lib/pubid/iso/normalizer.rb +89 -0
  299. data/lib/pubid/iso/parser.rb +26 -6
  300. data/lib/pubid/iso/single_identifier.rb +6 -3
  301. data/lib/pubid/iso/supplement_identifier.rb +15 -2
  302. data/lib/pubid/iso/urn_generator.rb +74 -176
  303. data/lib/pubid/iso/urn_parser.rb +28 -9
  304. data/lib/pubid/iso.rb +173 -2
  305. data/lib/pubid/itu/builder.rb +0 -12
  306. data/lib/pubid/itu/components/code.rb +8 -0
  307. data/lib/pubid/itu/components.rb +11 -0
  308. data/lib/pubid/itu/identifier.rb +6 -39
  309. data/lib/pubid/itu/identifiers/amendment.rb +0 -2
  310. data/lib/pubid/itu/identifiers/annex.rb +0 -2
  311. data/lib/pubid/itu/identifiers/base.rb +0 -6
  312. data/lib/pubid/itu/identifiers/combined_identifier.rb +0 -2
  313. data/lib/pubid/itu/identifiers/corrigendum.rb +0 -2
  314. data/lib/pubid/itu/identifiers/recommendation.rb +0 -2
  315. data/lib/pubid/itu/identifiers/special_publication.rb +0 -2
  316. data/lib/pubid/itu/identifiers/supplement.rb +0 -2
  317. data/lib/pubid/itu/urn_parser.rb +23 -0
  318. data/lib/pubid/itu.rb +42 -1
  319. data/lib/pubid/jcgm/builder.rb +16 -8
  320. data/lib/pubid/jcgm/identifiers/amendment.rb +2 -7
  321. data/lib/pubid/jcgm/identifiers/gum_guide.rb +2 -10
  322. data/lib/pubid/jcgm/renderer.rb +68 -0
  323. data/lib/pubid/jcgm/single_identifier.rb +1 -5
  324. data/lib/pubid/jcgm/urn_generator.rb +4 -6
  325. data/lib/pubid/jcgm/urn_parser.rb +23 -0
  326. data/lib/pubid/jcgm.rb +43 -2
  327. data/lib/pubid/jis/builder.rb +44 -52
  328. data/lib/pubid/jis/identifier.rb +132 -3
  329. data/lib/pubid/jis/identifiers/amendment.rb +1 -1
  330. data/lib/pubid/jis/identifiers/corrigendum.rb +16 -0
  331. data/lib/pubid/jis/identifiers/standard.rb +2 -1
  332. data/lib/pubid/jis/identifiers/technical_report.rb +2 -1
  333. data/lib/pubid/jis/identifiers/technical_specification.rb +2 -1
  334. data/lib/pubid/jis/identifiers.rb +1 -1
  335. data/lib/pubid/jis/parser.rb +31 -5
  336. data/lib/pubid/jis/renderer.rb +69 -0
  337. data/lib/pubid/jis/single_identifier.rb +6 -12
  338. data/lib/pubid/jis/supplement_identifier.rb +17 -14
  339. data/lib/pubid/jis/urn_parser.rb +23 -0
  340. data/lib/pubid/jis.rb +42 -2
  341. data/lib/pubid/nist/builder.rb +122 -1761
  342. data/lib/pubid/nist/caster.rb +1272 -0
  343. data/lib/pubid/nist/circular_supplement_builder.rb +291 -0
  344. data/lib/pubid/nist/components/code.rb +9 -20
  345. data/lib/pubid/nist/components/edition.rb +16 -0
  346. data/lib/pubid/nist/components/supplement.rb +88 -21
  347. data/lib/pubid/nist/components.rb +0 -1
  348. data/lib/pubid/nist/identifier.rb +25 -0
  349. data/lib/pubid/nist/identifiers/base.rb +206 -64
  350. data/lib/pubid/nist/identifiers/circular.rb +7 -2
  351. data/lib/pubid/nist/identifiers/circular_supplement.rb +3 -2
  352. data/lib/pubid/nist/identifiers/commercial_standard.rb +2 -1
  353. data/lib/pubid/nist/identifiers/commercial_standard_emergency.rb +6 -4
  354. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +10 -3
  355. data/lib/pubid/nist/identifiers/crpl_report.rb +8 -11
  356. data/lib/pubid/nist/identifiers/dated_document.rb +49 -0
  357. data/lib/pubid/nist/identifiers/federal_information_processing_standards.rb +17 -16
  358. data/lib/pubid/nist/identifiers/grant_contractor_report.rb +2 -1
  359. data/lib/pubid/nist/identifiers/handbook.rb +2 -1
  360. data/lib/pubid/nist/identifiers/internal_report.rb +2 -1
  361. data/lib/pubid/nist/identifiers/letter_circular.rb +2 -1
  362. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +5 -4
  363. data/lib/pubid/nist/identifiers/monograph.rb +7 -3
  364. data/lib/pubid/nist/identifiers/report.rb +4 -3
  365. data/lib/pubid/nist/identifiers/special_publication.rb +2 -1
  366. data/lib/pubid/nist/identifiers/technical_note.rb +3 -2
  367. data/lib/pubid/nist/identifiers.rb +1 -0
  368. data/lib/pubid/nist/parser.rb +67 -424
  369. data/lib/pubid/nist/parser_output_normalizer.rb +233 -0
  370. data/lib/pubid/nist/preprocessor.rb +416 -0
  371. data/lib/pubid/nist/renderer.rb +43 -0
  372. data/lib/pubid/nist/router.rb +148 -0
  373. data/lib/pubid/nist/series/base.rb +58 -0
  374. data/lib/pubid/nist/series/crpl.rb +13 -0
  375. data/lib/pubid/nist/series/fips.rb +14 -0
  376. data/lib/pubid/nist/series/ir.rb +60 -0
  377. data/lib/pubid/nist/series/letter_preserving.rb +15 -0
  378. data/lib/pubid/nist/series/mono.rb +19 -0
  379. data/lib/pubid/nist/series/ncstar.rb +20 -0
  380. data/lib/pubid/nist/series.rb +49 -0
  381. data/lib/pubid/nist/supplement_identifier.rb +11 -25
  382. data/lib/pubid/nist/urn_generator.rb +14 -8
  383. data/lib/pubid/nist/urn_parser.rb +67 -0
  384. data/lib/pubid/nist.rb +83 -4
  385. data/lib/pubid/oiml/components/code.rb +10 -0
  386. data/lib/pubid/oiml/identifiers/annex.rb +3 -45
  387. data/lib/pubid/oiml/identifiers/base.rb +2 -17
  388. data/lib/pubid/oiml/renderer.rb +161 -0
  389. data/lib/pubid/oiml/single_identifier.rb +6 -45
  390. data/lib/pubid/oiml/supplement_identifier.rb +4 -19
  391. data/lib/pubid/oiml/urn_generator.rb +0 -8
  392. data/lib/pubid/oiml/urn_parser.rb +22 -0
  393. data/lib/pubid/oiml.rb +42 -1
  394. data/lib/pubid/plateau/identifier.rb +23 -0
  395. data/lib/pubid/plateau/identifiers/handbook.rb +1 -3
  396. data/lib/pubid/plateau/identifiers/technical_report.rb +1 -1
  397. data/lib/pubid/plateau/renderer.rb +51 -0
  398. data/lib/pubid/plateau/supplement_identifier.rb +1 -1
  399. data/lib/pubid/plateau/urn_parser.rb +43 -0
  400. data/lib/pubid/plateau.rb +44 -1
  401. data/lib/pubid/renderers/base.rb +34 -0
  402. data/lib/pubid/renderers/directives_renderer.rb +27 -14
  403. data/lib/pubid/renderers/guide_renderer.rb +7 -1
  404. data/lib/pubid/renderers/human_readable.rb +31 -8
  405. data/lib/pubid/renderers/iwa_renderer.rb +5 -1
  406. data/lib/pubid/renderers/supplement_renderer.rb +4 -1
  407. data/lib/pubid/rendering/context.rb +33 -21
  408. data/lib/pubid/rendering.rb +0 -3
  409. data/lib/pubid/sae/components/date.rb +8 -0
  410. data/lib/pubid/sae/components/type.rb +5 -1
  411. data/lib/pubid/sae/identifiers/base.rb +2 -16
  412. data/lib/pubid/sae/renderer.rb +36 -0
  413. data/lib/pubid/sae/urn_generator.rb +2 -10
  414. data/lib/pubid/sae/urn_parser.rb +36 -0
  415. data/lib/pubid/sae.rb +42 -1
  416. data/lib/pubid/urn_generator/base.rb +12 -12
  417. data/lib/pubid/urn_parser/base.rb +81 -0
  418. data/lib/pubid/urn_parser/errors.rb +9 -0
  419. data/lib/pubid/urn_parser.rb +14 -0
  420. data/lib/pubid/version.rb +1 -1
  421. data/lib/pubid.rb +29 -7
  422. data/lib/tasks/website-data.json +1940 -1882
  423. metadata +77 -43
  424. data/lib/pubid/amca/scheme.rb +0 -16
  425. data/lib/pubid/ansi/scheme.rb +0 -15
  426. data/lib/pubid/api/scheme.rb +0 -66
  427. data/lib/pubid/ashrae/scheme.rb +0 -53
  428. data/lib/pubid/asme/scheme.rb +0 -37
  429. data/lib/pubid/astm/scheme.rb +0 -55
  430. data/lib/pubid/bsi/identifiers/base.rb +0 -11
  431. data/lib/pubid/bsi/scheme.rb +0 -243
  432. data/lib/pubid/ccsds/scheme.rb +0 -57
  433. data/lib/pubid/cen_cenelec/scheme.rb +0 -164
  434. data/lib/pubid/cie/scheme.rb +0 -64
  435. data/lib/pubid/csa/scheme.rb +0 -44
  436. data/lib/pubid/etsi/scheme.rb +0 -42
  437. data/lib/pubid/export/data_class_exporter.rb +0 -59
  438. data/lib/pubid/export/ieee_exporter.rb +0 -78
  439. data/lib/pubid/export/itu_exporter.rb +0 -66
  440. data/lib/pubid/export/nist_exporter.rb +0 -64
  441. data/lib/pubid/export/registry_exporter.rb +0 -90
  442. data/lib/pubid/export/scheme_exporter.rb +0 -70
  443. data/lib/pubid/identifier_registry.rb +0 -198
  444. data/lib/pubid/idf/scheme.rb +0 -61
  445. data/lib/pubid/iec/scheme.rb +0 -71
  446. data/lib/pubid/ieee/scheme.rb +0 -90
  447. data/lib/pubid/iho/scheme.rb +0 -29
  448. data/lib/pubid/iso/identifiers/base.rb +0 -115
  449. data/lib/pubid/iso/scheme.rb +0 -187
  450. data/lib/pubid/itu/scheme.rb +0 -174
  451. data/lib/pubid/jcgm/scheme.rb +0 -60
  452. data/lib/pubid/jis/components/code.rb +0 -59
  453. data/lib/pubid/jis/identifiers/base.rb +0 -72
  454. data/lib/pubid/jis/scheme.rb +0 -49
  455. data/lib/pubid/nist/components/publisher.rb +0 -24
  456. data/lib/pubid/nist/scheme.rb +0 -199
  457. data/lib/pubid/oiml/scheme.rb +0 -46
  458. data/lib/pubid/plateau/scheme.rb +0 -45
  459. data/lib/pubid/rendering/base.rb +0 -73
  460. data/lib/pubid/rendering/common.rb +0 -211
  461. data/lib/pubid/rendering/format.rb +0 -25
  462. data/lib/pubid/sae/scheme.rb +0 -47
  463. data/lib/pubid/scheme.rb +0 -207
data/lib/pubid/cie.rb CHANGED
@@ -11,16 +11,58 @@ module Pubid
11
11
  autoload :Identifier, "#{__dir__}/cie/identifier"
12
12
  autoload :Identifiers, "#{__dir__}/cie/identifiers"
13
13
  autoload :Parser, "#{__dir__}/cie/parser"
14
- autoload :Scheme, "#{__dir__}/cie/scheme"
15
14
  autoload :SingleIdentifier, "#{__dir__}/cie/single_identifier"
16
15
  autoload :SupplementIdentifier, "#{__dir__}/cie/supplement_identifier"
17
16
  autoload :UrnGenerator, "#{__dir__}/cie/urn_generator"
17
+ autoload :UrnParser, "#{__dir__}/cie/urn_parser"
18
18
 
19
19
  # Main entry point for CIE identifiers
20
20
  # Delegates to Identifier.parse
21
21
  def self.parse(input)
22
22
  Identifier.parse(input)
23
23
  end
24
+
25
+ # Auto-discover all identifier types from the Identifiers namespace.
26
+ # CIE identifier classes extend Lutaml::Model::Serializable via
27
+ # SingleIdentifier / SupplementIdentifier, without a self.type Hash.
28
+ # We discover by checking for subclasses of those base types.
29
+ # @return [Array<Class>] identifier classes
30
+ def self.identifier_types
31
+ @identifier_types ||= Identifiers.constants
32
+ .filter_map { |c| begin; Identifiers.const_get(c); rescue NameError; nil; end }
33
+ .select { |c| c.is_a?(Class) && (c < SingleIdentifier || c < SupplementIdentifier) }
34
+ end
35
+
36
+ # Build typed stage index from identifier types.
37
+ # @return [Array<Pubid::Components::TypedStage>] all typed stages
38
+ def self.all_typed_stages
39
+ @all_typed_stages ||= identifier_types.flat_map do |klass|
40
+ if klass.const_defined?(:TYPED_STAGES)
41
+ klass.const_get(:TYPED_STAGES)
42
+ else
43
+ []
44
+ end
45
+ end
46
+ end
47
+
48
+ # Lookup: class name -> identifier class
49
+ # Since CIE lacks self.type, locate by class name suffix
50
+ # @param code [String, Symbol] the type key to find
51
+ # @return [Class, nil] the matching identifier class
52
+ def self.locate_type(code)
53
+ identifier_types.find do |t|
54
+ t.name.split("::").last.gsub(/([A-Z])/, '_\1').downcase.sub(/^_/, "") == code.to_s.downcase ||
55
+ t.name.split("::").last.downcase == code.to_s.downcase
56
+ end
57
+ end
58
+
59
+ # Lookup: abbreviation -> typed stage
60
+ # @param abbr [String, Symbol] the abbreviation to find
61
+ # @return [Pubid::Components::TypedStage, nil] the matching typed stage
62
+ def self.locate_stage(abbr)
63
+ abbr_str = abbr.to_s.upcase
64
+ all_typed_stages.find { |s| s.abbr.any? { |a| a.to_s.upcase == abbr_str } }
65
+ end
24
66
  end
25
67
  end
26
68
 
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Pubid
6
+ module Components
7
+ # Adoption component — captures the metadata when one identifier adopts
8
+ # another. Originally surfaced as BSI's AdoptedInternationalStandard /
9
+ # AdoptedEuropeanNorm and CEN-CENELEC's AdoptedEuropeanNorm; the same
10
+ # shape applies to CSA adoptions and IEEE Adopted-Standard relationships.
11
+ #
12
+ # Shape (union across BSI, CEN-CENELEC, CSA, IEEE):
13
+ # - base: the adopted document (polymorphic Identifier).
14
+ # - adopter_publisher: the publisher doing the adopting (BS, EN,
15
+ # CAN/, CSA, IEEE).
16
+ # - edition: edition of the adoption (BSI-only).
17
+ # - date: adoption date (replaces ad-hoc year attrs).
18
+ # - translation_lang: translation language code (BSI-only).
19
+ # - translation_upper: upper-case translation marker (BSI-only).
20
+ # - translation_suffix_type: "version" or "Translation" (BSI-only).
21
+ # - reaffirmation_year: "(R2004)" reaffirmation notation (BSI, CSA).
22
+ # - expert_commentary: true when the adoption ships with commentary
23
+ # (BSI-only).
24
+ # - expert_commentary_topic: topic of the commentary (BSI-only).
25
+ # - publisher_prefix: CSA-specific dash-vs-space prefix.
26
+ #
27
+ # Render delegates to the base identifier; the adopter's renderer decides
28
+ # the prefix and any suffix notation (translation, reaffirmation,
29
+ # commentary) by calling adoption.render(context:).
30
+ class Adoption < Lutaml::Model::Serializable
31
+ attribute :base, ::Pubid::Identifier, polymorphic: true
32
+ attribute :adopter_publisher, ::Pubid::Components::Publisher
33
+ attribute :edition, :string
34
+ attribute :date, ::Pubid::Components::Date
35
+ attribute :translation_lang, :string
36
+ attribute :translation_upper, :string
37
+ attribute :translation_suffix_type, :string
38
+ attribute :reaffirmation_year, :string
39
+ attribute :expert_commentary, :boolean
40
+ attribute :expert_commentary_topic, :string
41
+ attribute :publisher_prefix, :string
42
+
43
+ IDENTITY_FIELDS = %i[
44
+ base adopter_publisher edition date translation_lang translation_upper
45
+ translation_suffix_type reaffirmation_year expert_commentary
46
+ expert_commentary_topic publisher_prefix
47
+ ].freeze
48
+
49
+ def present?
50
+ IDENTITY_FIELDS.any? { |f| present_value?(public_send(f)) }
51
+ end
52
+
53
+ def render(context: nil)
54
+ return "" unless base
55
+
56
+ body = base.to_s
57
+ body += translation_suffix if translation_lang
58
+ body += reaffirmation_suffix if reaffirmation_year
59
+ body += commentary_suffix if expert_commentary
60
+ body
61
+ end
62
+
63
+ def to_s(**opts)
64
+ render(context: opts[:context])
65
+ end
66
+
67
+ def ==(other)
68
+ return false unless other.is_a?(self.class)
69
+
70
+ IDENTITY_FIELDS.all? { |f| public_send(f) == other.public_send(f) }
71
+ end
72
+
73
+ alias eql? ==
74
+
75
+ def hash
76
+ @hash ||= [self.class, *IDENTITY_FIELDS.map { |f| public_send(f) }].hash
77
+ end
78
+
79
+ private
80
+
81
+ def present_value?(value)
82
+ return false if value.nil?
83
+ return value if [true, false].include?(value)
84
+
85
+ value.is_a?(String) ? !value.empty? : !value.nil?
86
+ end
87
+
88
+ def translation_suffix
89
+ type = translation_suffix_type || "Translation"
90
+ lang = translation_lang&.upcase
91
+ " #{lang}#{type}"
92
+ end
93
+
94
+ def reaffirmation_suffix
95
+ " (R#{reaffirmation_year})"
96
+ end
97
+
98
+ def commentary_suffix
99
+ topic = expert_commentary_topic
100
+ topic ? " (Commentary: #{topic})" : " (Commentary)"
101
+ end
102
+ end
103
+ end
104
+ end
@@ -2,32 +2,46 @@
2
2
 
3
3
  module Pubid
4
4
  module Components
5
+ # Document code/number component.
6
+ #
7
+ # Holds the structured fields that recur across flavors: the main +value+
8
+ # (always present), plus optional +prefix+ (series/type designator),
9
+ # +part+, +subpart+, and free-form +parts+. Subclasses own their
10
+ # composition rules — flavor-specific separators and orderings live in
11
+ # the subclass #to_s / #render override.
5
12
  class Code < Lutaml::Model::Serializable
6
13
  attribute :value, :string
14
+ attribute :prefix, :string
15
+ attribute :part, :string
16
+ attribute :subpart, :string
17
+ attribute :parts, :string, collection: true
7
18
 
8
19
  def to_s
9
20
  value.to_s
10
21
  end
11
22
 
23
+ # Format-aware render seam. Default returns the bare value; subclasses
24
+ # override to compose flavor-specific shapes (e.g. ISO joins parts
25
+ # with "-", NIST joins subpart with ".").
12
26
  def render(context: nil)
13
27
  value.to_s
14
28
  end
15
29
 
16
- # Returns hash code for code component
17
- # @return [Integer] hash code
18
- # @note Memoized for performance
19
30
  def hash
20
- @hash ||= value.hash
31
+ [value, prefix, part, subpart, parts].hash
21
32
  end
22
33
 
23
- # Checks equality with another code component
24
- # @param other [Object] object to compare with
25
- # @return [Boolean] true if equal
34
+ # rubocop:disable Metrics/AbcSize
26
35
  def eql?(other)
27
36
  return false unless other.is_a?(self.class)
28
37
 
29
- value == other.value
38
+ value == other.value &&
39
+ prefix == other.prefix &&
40
+ part == other.part &&
41
+ subpart == other.subpart &&
42
+ parts == other.parts
30
43
  end
44
+ # rubocop:enable Metrics/AbcSize
31
45
  end
32
46
  end
33
47
  end
@@ -5,40 +5,47 @@ require "lutaml/model"
5
5
  module Pubid
6
6
  module Components
7
7
  # Publication date component
8
+ #
9
+ # Human render: "YYYY" or "YYYY-MM" or "YYYY-MM-DD".
10
+ # URN render: year only (RFC 5141-bis URN spec).
8
11
  class Date < Lutaml::Model::Serializable
9
12
  attribute :year, :string
10
13
  attribute :month, :string
11
14
  attribute :day, :string
12
15
 
13
- # Render date with optional context for flavor-specific formatting
14
- #
15
- # @param _context [RenderingContext] rendering context
16
- # (for future extensibility)
17
- # @param _include_month [Boolean] include month in output
18
- # (for future extensibility)
19
- # @return [String] rendered date string
16
+ # True when the year is set to a non-empty value.
17
+ def present?
18
+ !year.nil? && !year.to_s.empty?
19
+ end
20
+
20
21
  def render(context: nil)
21
- to_s
22
+ return nil unless present?
23
+ return year.to_s if context&.urn?
24
+ return year.to_s unless month
25
+
26
+ result = "#{year}-#{pad2(month)}"
27
+ result += "-#{pad2(day)}" if day
28
+ result
22
29
  end
23
30
 
24
31
  def to_s(_context: nil, _include_month: false)
25
32
  return year.to_s unless month
26
33
 
27
- result = "#{year}-#{month}"
28
- result += "-#{day}" if day
34
+ result = "#{year}-#{pad2(month)}"
35
+ result += "-#{pad2(day)}" if day
29
36
  result
30
37
  end
31
38
 
32
- # Returns hash code for date component
33
- # @return [Integer] hash code
34
- # @note Memoized for performance
39
+ private
40
+
41
+ def pad2(value)
42
+ value.to_s.rjust(2, "0")
43
+ end
44
+
35
45
  def hash
36
46
  @hash ||= [year, month, day].compact.map(&:hash).hash
37
47
  end
38
48
 
39
- # Checks equality with another date component
40
- # @param other [Object] object to compare with
41
- # @return [Boolean] true if equal
42
49
  def eql?(other)
43
50
  return false unless other.is_a?(self.class)
44
51
 
@@ -3,27 +3,30 @@
3
3
  module Pubid
4
4
  module Components
5
5
  # Edition component (typically a year and number)
6
+ #
7
+ # Human render: "ED#{number}".
8
+ # URN render: "ed-#{number}" per RFC 5141-bis.
6
9
  class Edition < Lutaml::Model::Serializable
7
10
  attribute :year, :string
8
- attribute :number, Lutaml::Model::Type::Value # Accept any value type
9
- attribute :original_text, :string # Store the exact parsed edition text
11
+ attribute :number, Lutaml::Model::Type::Value
12
+ attribute :original_text, :string
10
13
 
11
14
  def to_s
12
- # Always use canonical format for rendering
13
15
  number_value = number.is_a?(Components::Code) ? number.value : number
14
16
  number_value ? "ED#{number_value}" : nil
15
17
  end
16
18
 
17
- # V1 API compatibility - tests expect .value on edition itself
18
19
  def value
19
20
  number.is_a?(Components::Code) ? number.value : number
20
21
  end
21
22
 
22
23
  def render(context: nil)
23
- to_s
24
+ number_value = number.is_a?(Components::Code) ? number.value : number
25
+ return nil unless number_value
26
+
27
+ context&.urn? ? "ed-#{number_value}" : "ED#{number_value}"
24
28
  end
25
29
 
26
- # Method to get the original parsed format if needed
27
30
  def original_format
28
31
  original_text
29
32
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pubid
4
+ module Components
5
+ # Stage iteration component — the numeric suffix on a stage (e.g., "WD.2").
6
+ #
7
+ # Renders as the bare number; the caller decides the separator (".")
8
+ # because URN, MR, and human formats position iteration differently
9
+ # relative to the stage abbreviation.
10
+ class Iteration < Lutaml::Model::Serializable
11
+ attribute :number, :string
12
+
13
+ def to_s
14
+ number.to_s
15
+ end
16
+
17
+ def render(context: nil)
18
+ number.to_s
19
+ end
20
+
21
+ def hash
22
+ @hash ||= number.hash
23
+ end
24
+
25
+ def eql?(other)
26
+ return false unless other.is_a?(self.class)
27
+
28
+ number == other.number
29
+ end
30
+ end
31
+ end
32
+ end
@@ -3,6 +3,9 @@
3
3
  module Pubid
4
4
  module Components
5
5
  # Language component (typically a language code)
6
+ #
7
+ # Human render: language code, optionally single-char.
8
+ # URN render: lowercase ISO 639-1 code (RFC 5141-bis).
6
9
  class Language < Lutaml::Model::Serializable
7
10
  CHAR_MAP = {
8
11
  "R" => "ru",
@@ -13,13 +16,10 @@ module Pubid
13
16
  "D" => "de",
14
17
  }.freeze
15
18
 
16
- # code is always an ISO 639-1 two-letter code
17
19
  attribute :code, :string, values: CHAR_MAP.values
18
- attribute :original_code, :string # Store the actual parsed format
20
+ attribute :original_code, :string
19
21
 
20
22
  def to_s(lang_single: false)
21
- # When multi-char format requested (lang_single: false) but original was
22
- # single-char, normalize to multi-char (for with_edition: true mode)
23
23
  if !lang_single && original_code&.length == 1
24
24
  code
25
25
  elsif original_code
@@ -30,6 +30,8 @@ module Pubid
30
30
  end
31
31
 
32
32
  def render(context: nil, **opts)
33
+ return code&.downcase if context&.urn?
34
+
33
35
  to_s(**opts)
34
36
  end
35
37
  end
@@ -2,9 +2,18 @@
2
2
 
3
3
  module Pubid
4
4
  module Components
5
- # Handles "all parts"
5
+ # Locality marker (e.g. "all parts")
6
+ #
7
+ # Renders the human-readable phrase "(all parts)" and a URN
8
+ # suffix that completes the locality segment.
6
9
  class Locality < Lutaml::Model::Serializable
7
10
  attribute :value, :string
11
+
12
+ def render(context: nil)
13
+ return "all" if context&.urn?
14
+
15
+ "(all parts)"
16
+ end
8
17
  end
9
18
  end
10
19
  end
@@ -5,6 +5,9 @@ require "lutaml/model"
5
5
  module Pubid
6
6
  module Components
7
7
  # Publisher ISO, IEC, etc.
8
+ #
9
+ # Human render: the publisher body (e.g. "ISO").
10
+ # URN render: lowercase body (e.g. "iso") per RFC 5141-bis.
8
11
  class Publisher < Lutaml::Model::Serializable
9
12
  attribute :body, :string
10
13
 
@@ -13,19 +16,19 @@ module Pubid
13
16
  end
14
17
 
15
18
  def render(context: nil)
19
+ return body&.downcase if context&.urn?
20
+
16
21
  body
17
22
  end
18
23
 
19
- # Returns hash code for publisher component
20
- # @return [Integer] hash code
21
- # @note Memoized for performance
24
+ def copublished?
25
+ false
26
+ end
27
+
22
28
  def hash
23
29
  @hash ||= body.hash
24
30
  end
25
31
 
26
- # Checks equality with another publisher component
27
- # @param other [Object] object to compare with
28
- # @return [Boolean] true if equal
29
32
  def eql?(other)
30
33
  return false unless other.is_a?(self.class)
31
34
 
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Pubid
6
+ module Components
7
+ # Relationship component — captures how one identifier relates to others.
8
+ #
9
+ # Originally modeled as IEEE's Components::Relationship; promoted to the
10
+ # shared namespace because the same relationship vocabulary applies to
11
+ # ISO, IEC, and other flavors that need to express "revises", "amends",
12
+ # "incorporates", "adopts", etc.
13
+ #
14
+ # Shape:
15
+ # - relationship_type: one of the VALID_TYPES constants below.
16
+ # - related_identifiers: array of identifier objects the relationship
17
+ # points at (e.g., the standards being revised).
18
+ # - intermediate_amendments: optional array of identifiers that amended
19
+ # the related identifier between its original publication and the
20
+ # current revision (renders as "... as amended by ...").
21
+ # - approved_amendments_flag: when true and no intermediate_amendments
22
+ # are listed, renders "... and its approved amendments".
23
+ class Relationship < Lutaml::Model::Serializable
24
+ REVISION_OF = "revision_of"
25
+ AMENDMENT_TO = "amendment_to"
26
+ CORRIGENDUM_TO = "corrigendum_to"
27
+ INCORPORATES = "incorporates"
28
+ INCORPORATING = "incorporating"
29
+ ADOPTION_OF = "adoption_of"
30
+ SUPPLEMENT_TO = "supplement_to"
31
+ DRAFT_AMENDMENT_TO = "draft_amendment_to"
32
+ DRAFT_REVISION_OF = "draft_revision_of"
33
+ REAFFIRMATION_OF = "reaffirmation_of"
34
+ REDESIGNATION_OF = "redesignation_of"
35
+ SUPERSEDES = "supersedes"
36
+ PREVIOUSLY_DESIGNATED_AS = "previously_designated_as"
37
+ INCLUDES = "includes"
38
+
39
+ VALID_TYPES = [
40
+ REVISION_OF,
41
+ AMENDMENT_TO,
42
+ CORRIGENDUM_TO,
43
+ INCORPORATES,
44
+ INCORPORATING,
45
+ ADOPTION_OF,
46
+ SUPPLEMENT_TO,
47
+ DRAFT_AMENDMENT_TO,
48
+ DRAFT_REVISION_OF,
49
+ REAFFIRMATION_OF,
50
+ REDESIGNATION_OF,
51
+ SUPERSEDES,
52
+ PREVIOUSLY_DESIGNATED_AS,
53
+ INCLUDES,
54
+ ].freeze
55
+
56
+ attribute :relationship_type, :string
57
+
58
+ attr_accessor :related_identifiers, :intermediate_amendments,
59
+ :approved_amendments_flag
60
+
61
+ PREFIXES = {
62
+ REVISION_OF => "Revision of",
63
+ AMENDMENT_TO => "Amendment to",
64
+ CORRIGENDUM_TO => "Corrigendum to",
65
+ INCORPORATES => "incorporates",
66
+ ADOPTION_OF => "Adoption of",
67
+ SUPPLEMENT_TO => "Supplement to",
68
+ DRAFT_AMENDMENT_TO => "Draft Amendment to",
69
+ DRAFT_REVISION_OF => "Draft Revision of",
70
+ REAFFIRMATION_OF => "Reaffirmation of",
71
+ REDESIGNATION_OF => "Redesignation of",
72
+ SUPERSEDES => "Supersedes",
73
+ PREVIOUSLY_DESIGNATED_AS => "Previously designated as",
74
+ INCLUDES => "Includes",
75
+ }.freeze
76
+
77
+ def initialize(**args)
78
+ @related_identifiers = args.delete(:related_identifiers)
79
+ @intermediate_amendments = args.delete(:intermediate_amendments)
80
+ @approved_amendments_flag = args.delete(:approved_amendments_flag)
81
+ super
82
+ normalize_incorporating!
83
+ validate_relationship_type if relationship_type
84
+ end
85
+
86
+ def normalize_incorporating!
87
+ return unless relationship_type == INCORPORATING
88
+
89
+ self.relationship_type = INCORPORATES
90
+ end
91
+
92
+ def validate_relationship_type
93
+ return if VALID_TYPES.include?(relationship_type)
94
+
95
+ raise ArgumentError,
96
+ "Invalid relationship type: #{relationship_type}. " \
97
+ "Valid types: #{VALID_TYPES.join(', ')}"
98
+ end
99
+
100
+ def to_s
101
+ return "" if related_identifiers.nil? || related_identifiers.empty?
102
+
103
+ prefix = format_relationship_prefix
104
+ ids = format_identifier_list(related_identifiers)
105
+ return "#{prefix} #{ids}" unless intermediate_clause?
106
+
107
+ "#{prefix} #{ids} #{intermediate_clause}"
108
+ end
109
+
110
+ def render(context: nil)
111
+ to_s
112
+ end
113
+
114
+ private
115
+
116
+ def intermediate_clause?
117
+ (intermediate_amendments && !intermediate_amendments.empty?) ||
118
+ approved_amendments_flag
119
+ end
120
+
121
+ def intermediate_clause
122
+ if intermediate_amendments && !intermediate_amendments.empty?
123
+ "as amended by #{format_identifier_list(intermediate_amendments)}"
124
+ else
125
+ "and its approved amendments"
126
+ end
127
+ end
128
+
129
+ def format_relationship_prefix
130
+ PREFIXES.fetch(relationship_type, relationship_type)
131
+ end
132
+
133
+ # Format a list of identifiers using proper English grammar:
134
+ # - Single: "IEEE Std X"
135
+ # - Two: "IEEE Std X and IEEE Std Y"
136
+ # - Three+: "IEEE Std X, IEEE Std Y, and IEEE Std Z" (Oxford comma)
137
+ def format_identifier_list(identifiers)
138
+ return "" if identifiers.nil? || identifiers.empty?
139
+
140
+ case identifiers.length
141
+ when 1
142
+ identifiers.first.to_s
143
+ when 2
144
+ "#{identifiers.first} and #{identifiers.last}"
145
+ else
146
+ "#{identifiers[0..-2].join(', ')}, and #{identifiers.last}"
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
@@ -1,23 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/model"
4
- require_relative "../rendering/context" if File.exist?(File.join(__dir__,
5
- "../../rendering/context.rb"))
6
4
 
7
5
  module Pubid
8
6
  module Components
9
7
  # Stage component (a set of defined stages)
8
+ #
9
+ # Human render: abbreviation with flavor-specific separator.
10
+ # URN render: stage abbreviation alone (no separator).
10
11
  class Stage < Lutaml::Model::Serializable
11
12
  attribute :name, :string
12
13
  attribute :stage_code, :string
13
14
  attribute :harmonized_stages, :string, collection: true
14
15
  attribute :abbr, :string
15
16
 
16
- # Render stage with optional context for flavor-specific separators
17
- #
18
- # @param context [RenderingContext] rendering context for flavor rules
19
- # @param has_copublisher [Boolean] whether identifier has copublisher
20
- # @return [String] rendered stage string
21
17
  def to_s(context: nil, has_copublisher: false)
22
18
  return "" unless abbr
23
19
 
@@ -25,25 +21,20 @@ module Pubid
25
21
  sep = context.stage_separator_for(has_copublisher:)
26
22
  sep == "" ? abbr : "#{sep}#{abbr}"
27
23
  else
28
- # Default behavior: space after copublisher, slash otherwise
29
24
  has_copublisher ? " #{abbr}" : "/#{abbr}"
30
25
  end
31
26
  end
32
27
 
33
28
  def render(context: nil)
29
+ return abbr.to_s if context&.urn?
30
+
34
31
  abbr.to_s
35
32
  end
36
33
 
37
- # Returns hash code for stage component
38
- # @return [Integer] hash code
39
- # @note Memoized for performance
40
34
  def hash
41
35
  @hash ||= [stage_code, abbr].compact.map(&:hash).hash
42
36
  end
43
37
 
44
- # Checks equality with another stage component
45
- # @param other [Object] object to compare with
46
- # @return [Boolean] true if equal
47
38
  def eql?(other)
48
39
  return false unless other.is_a?(self.class)
49
40