pubid 2.0.0 → 2.0.2

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 (214) hide show
  1. checksums.yaml +4 -4
  2. data/data/parg/adobe.json +1 -1
  3. data/data/parg/aiee.json +1 -1
  4. data/data/parg/amca.json +1 -1
  5. data/data/parg/ansi.json +1 -1
  6. data/data/parg/api.json +1 -1
  7. data/data/parg/ashrae.json +1 -1
  8. data/data/parg/asme.json +1 -1
  9. data/data/parg/astm.json +1 -1
  10. data/data/parg/bipm.json +1 -1
  11. data/data/parg/bsi.json +1 -1
  12. data/data/parg/calconnect.json +1 -1
  13. data/data/parg/ccsds.json +1 -1
  14. data/data/parg/cen_cenelec.json +1 -1
  15. data/data/parg/cie.json +1 -1
  16. data/data/parg/csa.json +1 -1
  17. data/data/parg/doi.json +1 -1
  18. data/data/parg/easc.json +1 -1
  19. data/data/parg/ecma.json +1 -1
  20. data/data/parg/etsi.json +1 -1
  21. data/data/parg/evs.json +1 -1
  22. data/data/parg/gb.json +1 -1
  23. data/data/parg/gost.json +1 -1
  24. data/data/parg/iala.json +1 -1
  25. data/data/parg/iana.json +1 -1
  26. data/data/parg/idf.json +1 -1
  27. data/data/parg/iec.json +1 -1
  28. data/data/parg/ieee.json +1 -29571
  29. data/data/parg/ietf.json +1 -1
  30. data/data/parg/iho.json +1 -0
  31. data/data/parg/ire.json +1 -1
  32. data/data/parg/isbn.json +1 -1
  33. data/data/parg/iso.json +1 -8510
  34. data/data/parg/itu.json +1 -1
  35. data/data/parg/jcgm.json +1 -1
  36. data/data/parg/jis.json +1 -1
  37. data/data/parg/nesc.json +1 -1
  38. data/data/parg/nist.json +1 -9588
  39. data/data/parg/oasis.json +1 -1
  40. data/data/parg/ogc.json +1 -1
  41. data/data/parg/oiml.json +1 -1
  42. data/data/parg/omg.json +1 -1
  43. data/data/parg/parg.json +1 -1
  44. data/data/parg/plateau.json +1 -1
  45. data/data/parg/sae.json +1 -1
  46. data/data/parg/tables/typed_stages.yaml +1 -0
  47. data/data/parg/tgpp.json +1 -1
  48. data/data/parg/un.json +1 -1
  49. data/data/parg/w3c.json +1 -1
  50. data/data/parg/xsf.json +1 -1
  51. data/lib/pubid/adobe/identifier.rb +1 -1
  52. data/lib/pubid/adobe/parser.rb +2 -113
  53. data/lib/pubid/amca/identifiers/base.rb +1 -1
  54. data/lib/pubid/amca/parser.rb +1 -145
  55. data/lib/pubid/ansi/identifier.rb +1 -1
  56. data/lib/pubid/ansi/parser.rb +1 -82
  57. data/lib/pubid/api/builder.rb +32 -1
  58. data/lib/pubid/api/identifier.rb +1 -1
  59. data/lib/pubid/api/parser.rb +1 -131
  60. data/lib/pubid/ashrae/identifiers/base.rb +1 -1
  61. data/lib/pubid/ashrae/parser.rb +3 -710
  62. data/lib/pubid/asme/builder.rb +6 -4
  63. data/lib/pubid/asme/identifier.rb +1 -2
  64. data/lib/pubid/asme/parser.rb +1 -328
  65. data/lib/pubid/astm/builder.rb +12 -3
  66. data/lib/pubid/astm/identifier.rb +1 -2
  67. data/lib/pubid/astm/parser.rb +1 -227
  68. data/lib/pubid/bipm/identifier.rb +8 -1
  69. data/lib/pubid/bipm/parser.rb +2 -224
  70. data/lib/pubid/bsi/builder.rb +2 -4
  71. data/lib/pubid/bsi/parser.rb +1 -666
  72. data/lib/pubid/bsi/single_identifier.rb +38 -1
  73. data/lib/pubid/calconnect/identifier.rb +1 -1
  74. data/lib/pubid/calconnect/parser.rb +2 -40
  75. data/lib/pubid/ccsds/identifier.rb +1 -1
  76. data/lib/pubid/ccsds/parser.rb +1 -66
  77. data/lib/pubid/cen_cenelec/identifier.rb +16 -1
  78. data/lib/pubid/cen_cenelec/parser.rb +3 -136
  79. data/lib/pubid/cie/identifier.rb +1 -1
  80. data/lib/pubid/cie/parser.rb +3 -378
  81. data/lib/pubid/conformance.rb +1 -1
  82. data/lib/pubid/csa/builder.rb +41 -18
  83. data/lib/pubid/csa/identifier.rb +12 -4
  84. data/lib/pubid/csa/identifiers/amendment.rb +28 -0
  85. data/lib/pubid/csa/identifiers.rb +1 -0
  86. data/lib/pubid/csa/parser.rb +16 -397
  87. data/lib/pubid/doi/identifier.rb +1 -1
  88. data/lib/pubid/doi/parser.rb +2 -37
  89. data/lib/pubid/easc/builder.rb +1 -1
  90. data/lib/pubid/easc/identifier.rb +1 -1
  91. data/lib/pubid/easc/parser.rb +2 -70
  92. data/lib/pubid/ecma/CLAUDE.md +8 -1
  93. data/lib/pubid/ecma/identifier.rb +13 -8
  94. data/lib/pubid/ecma/parser.rb +2 -54
  95. data/lib/pubid/ecma/renderer.rb +3 -7
  96. data/lib/pubid/errors.rb +18 -13
  97. data/lib/pubid/etsi/builder.rb +8 -5
  98. data/lib/pubid/etsi/identifiers/base.rb +1 -1
  99. data/lib/pubid/etsi/parser.rb +1 -132
  100. data/lib/pubid/evs/identifier.rb +7 -0
  101. data/lib/pubid/evs/parser.rb +1 -8
  102. data/lib/pubid/evs.rb +1 -1
  103. data/lib/pubid/gb/identifier.rb +7 -1
  104. data/lib/pubid/gb/parser.rb +2 -51
  105. data/lib/pubid/gost/identifier.rb +9 -1
  106. data/lib/pubid/gost/parser.rb +4 -81
  107. data/lib/pubid/iala/parser.rb +2 -121
  108. data/lib/pubid/iana/identifier.rb +1 -1
  109. data/lib/pubid/iana/parser.rb +2 -24
  110. data/lib/pubid/identifier.rb +78 -1
  111. data/lib/pubid/idf/builder.rb +42 -0
  112. data/lib/pubid/idf/identifier.rb +1 -1
  113. data/lib/pubid/idf/parser.rb +1 -137
  114. data/lib/pubid/idf.rb +1 -2
  115. data/lib/pubid/iec/builder.rb +158 -50
  116. data/lib/pubid/iec/identifier.rb +1 -1
  117. data/lib/pubid/iec/parser.rb +3 -430
  118. data/lib/pubid/ieee/aiee/identifier.rb +2 -1
  119. data/lib/pubid/ieee/aiee.rb +0 -1
  120. data/lib/pubid/ieee/builder.rb +2 -2
  121. data/lib/pubid/ieee/identifiers/base.rb +1 -1
  122. data/lib/pubid/ieee/ire/identifier.rb +2 -1
  123. data/lib/pubid/ieee/ire.rb +0 -1
  124. data/lib/pubid/ieee/nesc.rb +0 -1
  125. data/lib/pubid/ieee/parser.rb +1 -1257
  126. data/lib/pubid/ietf/identifiers/base.rb +17 -1
  127. data/lib/pubid/ietf/parser.rb +2 -47
  128. data/lib/pubid/ietf/renderer.rb +17 -2
  129. data/lib/pubid/iho/CLAUDE.md +89 -0
  130. data/lib/pubid/iho/builder.rb +4 -1
  131. data/lib/pubid/iho/identifiers/base.rb +28 -2
  132. data/lib/pubid/iho/renderer.rb +8 -0
  133. data/lib/pubid/iho/urn_generator.rb +11 -1
  134. data/lib/pubid/iho/urn_parser.rb +21 -11
  135. data/lib/pubid/iho.rb +0 -1
  136. data/lib/pubid/isbn/identifier.rb +1 -1
  137. data/lib/pubid/isbn/parser.rb +2 -31
  138. data/lib/pubid/iso/builder.rb +1 -1
  139. data/lib/pubid/iso/identifiers/directives.rb +6 -3
  140. data/lib/pubid/iso/identifiers/guide.rb +6 -3
  141. data/lib/pubid/iso/identifiers/international_standard.rb +3 -1
  142. data/lib/pubid/iso/identifiers/international_workshop_agreement.rb +6 -3
  143. data/lib/pubid/iso/normalizer.rb +1 -1
  144. data/lib/pubid/iso/parser.rb +1 -539
  145. data/lib/pubid/iso/supplement_identifier.rb +6 -3
  146. data/lib/pubid/iso/utilities.rb +4 -5
  147. data/lib/pubid/iso.rb +1 -19
  148. data/lib/pubid/itu/builder.rb +36 -20
  149. data/lib/pubid/itu/identifiers/base.rb +15 -2
  150. data/lib/pubid/itu/parser.rb +1 -775
  151. data/lib/pubid/jcgm/builder.rb +35 -0
  152. data/lib/pubid/jcgm/parser.rb +1 -151
  153. data/lib/pubid/jcgm.rb +1 -2
  154. data/lib/pubid/jis/builder.rb +18 -29
  155. data/lib/pubid/jis/identifier.rb +1 -1
  156. data/lib/pubid/jis/parser.rb +1 -128
  157. data/lib/pubid/nist/builder.rb +5 -1
  158. data/lib/pubid/nist/caster.rb +13 -3
  159. data/lib/pubid/nist/identifiers/base.rb +37 -2
  160. data/lib/pubid/nist/identifiers/circular.rb +2 -2
  161. data/lib/pubid/nist/identifiers/circular_supplement.rb +2 -2
  162. data/lib/pubid/nist/identifiers/commercial_standards_monthly.rb +2 -2
  163. data/lib/pubid/nist/identifiers/crpl_report.rb +2 -2
  164. data/lib/pubid/nist/identifiers/handbook.rb +2 -2
  165. data/lib/pubid/nist/identifiers/internal_report.rb +2 -2
  166. data/lib/pubid/nist/identifiers/miscellaneous_publication.rb +2 -2
  167. data/lib/pubid/nist/identifiers/monograph.rb +2 -2
  168. data/lib/pubid/nist/identifiers/report.rb +2 -2
  169. data/lib/pubid/nist/parser.rb +19 -775
  170. data/lib/pubid/nist/router.rb +4 -1
  171. data/lib/pubid/nist/supplement_identifier.rb +2 -2
  172. data/lib/pubid/oasis/identifier.rb +1 -1
  173. data/lib/pubid/oasis/parser.rb +2 -16
  174. data/lib/pubid/ogc/identifier.rb +1 -1
  175. data/lib/pubid/ogc/parser.rb +2 -26
  176. data/lib/pubid/oiml/identifiers/certification_system.rb +7 -0
  177. data/lib/pubid/oiml/identifiers/dual_published.rb +2 -2
  178. data/lib/pubid/oiml/parser.rb +1 -303
  179. data/lib/pubid/oiml.rb +1 -2
  180. data/lib/pubid/omg/identifier.rb +6 -1
  181. data/lib/pubid/omg/parser.rb +2 -76
  182. data/lib/pubid/parg/artifact.rb +22 -3
  183. data/lib/pubid/parg/model.rb +98 -0
  184. data/lib/pubid/parg.rb +1 -0
  185. data/lib/pubid/parser.rb +5 -4
  186. data/lib/pubid/parsers/mr_string.rb +1 -1
  187. data/lib/pubid/plateau/parser.rb +1 -66
  188. data/lib/pubid/plateau.rb +1 -2
  189. data/lib/pubid/renderers/directives_renderer.rb +1 -1
  190. data/lib/pubid/renderers/iwa_renderer.rb +1 -1
  191. data/lib/pubid/renderers/publisher_stripper.rb +82 -0
  192. data/lib/pubid/renderers/supplement_renderer.rb +1 -1
  193. data/lib/pubid/renderers.rb +1 -0
  194. data/lib/pubid/sae/identifiers/base.rb +1 -1
  195. data/lib/pubid/sae/parser.rb +1 -48
  196. data/lib/pubid/tgpp/identifier.rb +1 -1
  197. data/lib/pubid/tgpp/parser.rb +2 -59
  198. data/lib/pubid/un/identifier.rb +1 -1
  199. data/lib/pubid/un/parser.rb +1 -18
  200. data/lib/pubid/version.rb +1 -1
  201. data/lib/pubid/w3c/identifier.rb +1 -1
  202. data/lib/pubid/w3c/parser.rb +2 -27
  203. data/lib/pubid/xsf/identifier.rb +11 -7
  204. data/lib/pubid/xsf/parser.rb +3 -31
  205. data/lib/pubid/xsf/renderer.rb +2 -4
  206. data/lib/pubid.rb +8 -9
  207. metadata +15 -25
  208. data/lib/pubid/ieee/aiee/parser.rb +0 -130
  209. data/lib/pubid/ieee/ire/parser.rb +0 -109
  210. data/lib/pubid/ieee/nesc/parser.rb +0 -155
  211. data/lib/pubid/iho/parser.rb +0 -68
  212. data/lib/pubid/parser/common_parse_methods.rb +0 -13
  213. data/lib/pubid/parser/common_parse_rules.rb +0 -56
  214. data/lib/pubid/parser/grammar.rb +0 -96
@@ -27,81 +27,113 @@ module Pubid
27
27
  raise(ArgumentError, "Unknown type code: #{typed_stage.type_code}")
28
28
  end
29
29
 
30
+ # Bound-hash layer fields: the base, the first supplement and the
31
+ # second supplement capture into disjoint key sets, so each
32
+ # wrapper's data can be peeled off the flat hash by name.
33
+ SUPP_KEYS = %i[supp_type_with_stage supp_number_with_part
34
+ supp_stage_iteration supp_date supp_undated_marker
35
+ supp_edition].freeze
36
+ SUPP2_KEYS = %i[supp2_type_with_stage supp2_number_with_part
37
+ supp2_stage_iteration supp2_date supp2_undated_marker
38
+ supp2_edition].freeze
39
+ FRAG_ABBRS = (Identifiers::FragmentIdentifier::TYPED_STAGES
40
+ .flat_map(&:abbr) + ["FRAGC"]).freeze
41
+ # third_part's /FRAGN notation wraps the OUTERMOST layer, so every
42
+ # early-return branch applies it and every inner base build strips
43
+ # it.
44
+ FRAG_NOTATION_KEYS = %i[fragment_type fragment_number].freeze
45
+
46
+ # third_part's /FRAGN notation (distinct from a FRAG typed stage)
47
+ # wraps the finished identifier.
48
+ def apply_fragment_notation(identifier, parsed_hash)
49
+ if parsed_hash[:fragment_type] && parsed_hash[:fragment_number]
50
+ return wrap_with_fragment(identifier,
51
+ parsed_hash[:fragment_number].to_s,
52
+ nil, Pubid::Iec.locate_stage("FRAG"))
53
+ end
54
+ identifier
55
+ end
56
+
30
57
  def build(parsed_hash)
31
58
  all_parts = parsed_hash.delete(:all_parts)
32
59
 
33
- # Handle sheet_supplement_identifier pattern:
34
- # {base: {...}, sheet_number: ..., sheet_year: ..., type_with_stage: "COR", number_with_part: "1", date: "1995"}
35
- # This is a Corrigendum/Amendment wrapping a SheetIdentifier
36
- if parsed_hash[:base] && (parsed_hash[:sheet_number] || parsed_hash[:sheet_year]) && parsed_hash[:type_with_stage]
37
- # Extract sheet info first
38
- sheet_number = parsed_hash.delete(:sheet_number)
39
- sheet_year = parsed_hash.delete(:sheet_year)
40
-
41
- # Build the base identifier (IEC 60695-2-1 with /1:1994 -> SheetIdentifier)
42
- base_parsed = parsed_hash[:base].dup
43
- base_parsed[:sheet_number] = sheet_number
44
- base_parsed[:sheet_year] = sheet_year if sheet_year
45
- sheet_id = wrap_with_sheet(build(base_parsed), sheet_number,
46
- sheet_year)
47
-
48
- # Now build the supplement on top of the sheet
49
- # We need to preserve the supplement data and create a wrapper
50
- supplement_type = parsed_hash.delete(:type_with_stage)
51
- supplement_number = parsed_hash.delete(:number_with_part)
52
- supplement_date = parsed_hash.delete(:date)
53
- supplement_edition = parsed_hash.delete(:edition)
54
-
55
- # Locate the supplement identifier class
56
- typed_stage = locate_typed_stage(supplement_type)
57
- identifier_class = Pubid::Iec.locate_type(typed_stage.type_code) ||
58
- raise(ArgumentError, "Unknown type code: #{typed_stage.type_code}")
59
-
60
- # Create the supplement identifier
61
- supplement = identifier_class.new
62
- supp_attrs = identifier_class.attributes
63
- if supp_attrs.key?(:number)
64
- supplement.number = supplement_number.to_s
65
- end
66
- if supplement_date && supp_attrs.key?(:date)
67
- supplement.date = cast(:date, supplement_date)
68
- end
69
- if supplement_edition && supp_attrs.key?(:edition)
70
- supplement.edition = cast(:edition, supplement_edition)
71
- end
72
- supplement.typed_stage = typed_stage
60
+ # Second supplement layer (/AMD1:2018/COR1:2019): build the
61
+ # first-supplement form, then wrap the second supplement around
62
+ # it.
63
+ if parsed_hash[:supp2_type_with_stage]
64
+ supp2 = supplement_fields(parsed_hash, SUPP2_KEYS)
65
+ inner = build(parsed_hash.reject { |key, _| SUPP2_KEYS.include?(key) })
66
+ return apply_fragment_notation(wrap_supplement_layer(inner, supp2),
67
+ parsed_hash)
68
+ end
73
69
 
74
- # Wrap the sheet with the supplement
75
- return wrap_with_supplement(sheet_id, supplement)
70
+ # Sheet + supplement (…/1:1994/COR1): the sheet wraps the base,
71
+ # the supplement wraps the sheet. build re-enters the sheet
72
+ # branch for the base.
73
+ if parsed_hash[:sheet_number] && parsed_hash[:supp_type_with_stage]
74
+ supp = supplement_fields(parsed_hash, SUPP_KEYS)
75
+ base_hash = parsed_hash.reject { |key, _| SUPP_KEYS.include?(key) }
76
+ sheet_id = build(base_hash)
77
+ return apply_fragment_notation(wrap_supplement_layer(sheet_id, supp),
78
+ parsed_hash)
76
79
  end
77
80
 
78
- # Handle sheet_identifier pattern: {base: {...}, sheet_number: ..., sheet_year: ...}
79
- if parsed_hash[:base] && (parsed_hash[:sheet_number] || parsed_hash[:sheet_year])
80
- # Build the base identifier first
81
- base_id = build(parsed_hash[:base])
82
- # Wrap with SheetIdentifier
81
+ # Sheet notation (…/1:1994 or …/1): the remaining fields are the
82
+ # sheet's base identifier.
83
+ if parsed_hash[:sheet_number]
83
84
  sheet_number = parsed_hash.delete(:sheet_number)
84
85
  sheet_year = parsed_hash.delete(:sheet_year)
85
- return wrap_with_sheet(base_id, sheet_number, sheet_year)
86
+ rest = parsed_hash.reject { |key, _| FRAG_NOTATION_KEYS.include?(key) }
87
+ return apply_fragment_notation(
88
+ wrap_with_sheet(build(rest), sheet_number, sheet_year),
89
+ parsed_hash,
90
+ )
91
+ end
92
+
93
+ # Standalone supplement (IEC/AMD 1:2017 — no base designation):
94
+ # the supplement's own fields are the primary ones.
95
+ if parsed_hash[:supp_type_with_stage] && !parsed_hash[:number_with_part] &&
96
+ !parsed_hash[:trf_org] && !parsed_hash[:technical_committee]
97
+ return build(standalone_supplement_hash(parsed_hash))
86
98
  end
87
99
 
88
100
  # Extract FRAG/FRAGC indicator if present
89
101
  frag_abbrs = Pubid::Iec::Identifiers::FragmentIdentifier::TYPED_STAGES
90
102
  .flat_map(&:abbr)
91
103
  is_fragment = frag_abbrs.include?(parsed_hash[:type_with_stage]) ||
92
- parsed_hash[:type_with_stage] == "FRAGC"
104
+ parsed_hash[:type_with_stage] == "FRAGC" ||
105
+ frag_abbrs.include?(parsed_hash[:supp_type_with_stage]) ||
106
+ parsed_hash[:supp_type_with_stage] == "FRAGC"
93
107
  fragment_typed_stage = nil
94
108
  fragment_number = nil
95
109
  fragment_edition = nil
96
110
 
97
111
  if is_fragment
98
112
  # For FRAG typed stages, look up the fragment's own typed stage
99
- fragment_typed_stage = Pubid::Iec.locate_stage(parsed_hash[:type_with_stage])
113
+ fragment_typed_stage = Pubid::Iec.locate_stage(parsed_hash[:type_with_stage] ||
114
+ parsed_hash[:supp_type_with_stage])
100
115
 
101
116
  # FRAGC is a rendering notation, not a typed stage abbreviation;
102
117
  # fall back to the canonical "FRAG" typed stage
103
118
  fragment_typed_stage ||= Pubid::Iec.locate_stage("FRAG")
104
119
 
120
+ # For FRAG/FRAGC, we need to build the base Amendment/Corrigendum
121
+ # then wrap it with FragmentIdentifier
122
+ if parsed_hash[:supp_type_with_stage] &&
123
+ (parsed_hash[:number_with_part] || parsed_hash[:trf_org])
124
+ # FRAG riding the supplement layer: the base is the rest.
125
+ fragment_number = parsed_hash[:supp_number_with_part].to_s
126
+ fragment_edition = parsed_hash[:supp_edition]
127
+ base_id = build(parsed_hash.reject do |key, _|
128
+ SUPP_KEYS.include?(key) || FRAG_NOTATION_KEYS.include?(key)
129
+ end)
130
+ return apply_fragment_notation(
131
+ wrap_with_fragment(base_id, fragment_number,
132
+ fragment_edition, fragment_typed_stage),
133
+ parsed_hash,
134
+ )
135
+ end
136
+
105
137
  # For FRAG/FRAGC, we need to build the base Amendment/Corrigendum
106
138
  # then wrap it with FragmentIdentifier
107
139
  if parsed_hash[:number_with_part]
@@ -136,6 +168,18 @@ module Pubid
136
168
  parsed_hash[:cispr_identifier] = cispr_id
137
169
  end
138
170
 
171
+ # Supplement over a base designation (…/AMD1:2021): build the
172
+ # base from the remaining fields, then wrap.
173
+ if parsed_hash[:supp_type_with_stage]
174
+ supp = supplement_fields(parsed_hash, SUPP_KEYS)
175
+ base_hash = parsed_hash.reject do |key, _|
176
+ SUPP_KEYS.include?(key) || FRAG_NOTATION_KEYS.include?(key)
177
+ end
178
+ base = build(base_hash)
179
+ return apply_fragment_notation(wrap_supplement_layer(base, supp),
180
+ parsed_hash)
181
+ end
182
+
139
183
  # Extract and store wrapper data before building
140
184
  consolidated_supplements_data = parsed_hash.delete(:consolidated_supplements)
141
185
  vap_suffix_data = parsed_hash.delete(:vap_suffix)
@@ -282,6 +326,70 @@ module Pubid
282
326
  )
283
327
  end
284
328
 
329
+ # Peels one supplement layer's supp_* / supp2_* fields off the
330
+ # flat bound hash.
331
+ def supplement_fields(parsed_hash, keys)
332
+ parsed_hash.slice(*keys).transform_keys { |key|
333
+ key.to_s.delete_prefix("supp").delete_prefix("2_").gsub(/\A_/, "").to_sym
334
+ }
335
+ end
336
+
337
+ # Wraps one supplement layer around its base: a FRAG/FRAGC layer
338
+ # is a FragmentIdentifier wrapper, anything else is an
339
+ # Amendment/Corrigendum built from the layer's fields.
340
+ def wrap_supplement_layer(base, supp)
341
+ abbr = supp[:type_with_stage].to_s
342
+ if FRAG_ABBRS.include?(abbr)
343
+ typed_stage = Pubid::Iec.locate_stage(abbr) ||
344
+ Pubid::Iec.locate_stage("FRAG")
345
+ return wrap_with_fragment(base, supp[:number_with_part].to_s,
346
+ supp[:edition], typed_stage)
347
+ end
348
+ wrap_with_supplement(base, build_supplement(supp))
349
+ end
350
+
351
+ # Materializes one supplement (Amendment/Corrigendum/…) from its
352
+ # layer's fields.
353
+ def build_supplement(fields)
354
+ typed_stage = locate_typed_stage(fields[:type_with_stage])
355
+ identifier_class = Pubid::Iec.locate_type(typed_stage.type_code) ||
356
+ raise(ArgumentError, "Unknown type code: #{typed_stage.type_code}")
357
+
358
+ supplement = identifier_class.new
359
+ supp_attrs = identifier_class.attributes
360
+ if supp_attrs.key?(:number) && fields[:number_with_part]
361
+ supplement.number = fields[:number_with_part].to_s
362
+ end
363
+ if supp_attrs.key?(:date)
364
+ if fields[:date]
365
+ supplement.date = parse_date(fields[:date])
366
+ elsif fields[:undated_marker]
367
+ supplement.date = Pubid::Components::Date.new(undated: true)
368
+ end
369
+ end
370
+ if supp_attrs.key?(:edition) && fields[:edition]
371
+ supplement.edition = Pubid::Components::Edition.new(number: fields[:edition].to_s)
372
+ end
373
+ supplement.typed_stage = typed_stage
374
+ supplement
375
+ end
376
+
377
+ # A standalone supplement (IEC/AMD 1:2017) has no base designation:
378
+ # its supp_* fields become the primary ones.
379
+ def standalone_supplement_hash(parsed_hash)
380
+ parsed_hash
381
+ .slice(:publisher, :copublishers, :type_with_stage_fr,
382
+ :languages, :fragment_type, :fragment_number, :all_parts)
383
+ .merge(
384
+ type_with_stage: parsed_hash[:supp_type_with_stage],
385
+ number_with_part: parsed_hash[:supp_number_with_part],
386
+ stage_iteration: parsed_hash[:supp_stage_iteration],
387
+ date: parsed_hash[:supp_date],
388
+ undated_marker: parsed_hash[:supp_undated_marker],
389
+ edition: parsed_hash[:supp_edition],
390
+ ).compact
391
+ end
392
+
285
393
  # Wrap base identifier with supplement (Amendment/Corrigendum)
286
394
  def wrap_with_supplement(base, supplement)
287
395
  supplement.base = base
@@ -323,7 +323,7 @@ module Pubid
323
323
 
324
324
  # Apply legacy update_codes normalization first, before any other preprocessing
325
325
  normalized = Core::UpdateCodes.apply(string, :iec)
326
- parsed = Pubid::Parg::Backend.parse(:iec, Pubid::Iec::Parser.normalize_input(normalized))
326
+ parsed = Pubid::Parg::Model.bound(:iec, Pubid::Iec::Parser.normalize_input(normalized))
327
327
  Pubid::Iec::Builder.new.build(parsed)
328
328
  end
329
329