relaton-bib 2.0.0.pre.alpha.1 → 2.0.0

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/.rubocop.yml +1 -1
  4. data/CLAUDE.md +96 -0
  5. data/Gemfile +1 -0
  6. data/README.adoc +14 -2
  7. data/grammars/basicdoc.rng +75 -45
  8. data/grammars/biblio-standoc.rng +37 -56
  9. data/grammars/biblio.rng +68 -36
  10. data/grammars/versions.json +25 -25
  11. data/lib/relaton/bib/converter/asciibib/to_asciibib.rb +663 -0
  12. data/lib/relaton/bib/converter/asciibib.rb +13 -0
  13. data/lib/relaton/bib/converter/bibtex/from_bibtex.rb +245 -0
  14. data/lib/relaton/bib/converter/bibtex/to_bibtex.rb +341 -0
  15. data/lib/relaton/bib/converter/bibtex.rb +23 -0
  16. data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +383 -0
  17. data/lib/relaton/bib/converter/bibxml/from_rfcxml_referencegroup.rb +71 -0
  18. data/lib/relaton/bib/{renderer/rfc.rb → converter/bibxml/to_rfcxml.rb} +100 -92
  19. data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +52 -0
  20. data/lib/relaton/bib/converter/bibxml.rb +51 -0
  21. data/lib/relaton/bib/hash_parser_v1.rb +121 -78
  22. data/lib/relaton/bib/item_data.rb +83 -22
  23. data/lib/relaton/bib/model/abstract.rb +16 -0
  24. data/lib/relaton/bib/model/date.rb +6 -4
  25. data/lib/relaton/bib/model/depiction.rb +2 -0
  26. data/lib/relaton/bib/model/ext.rb +0 -3
  27. data/lib/relaton/bib/model/formattedref.rb +43 -0
  28. data/lib/relaton/bib/model/ics.rb +9 -0
  29. data/lib/relaton/bib/model/item.rb +12 -4
  30. data/lib/relaton/bib/model/item_base.rb +17 -9
  31. data/lib/relaton/bib/model/keyword.rb +3 -3
  32. data/lib/relaton/bib/model/logo.rb +2 -0
  33. data/lib/relaton/bib/model/organization_type.rb +1 -1
  34. data/lib/relaton/bib/model/relation.rb +2 -2
  35. data/lib/relaton/bib/model/series.rb +5 -3
  36. data/lib/relaton/bib/model/subdivision.rb +2 -0
  37. data/lib/relaton/bib/model/title.rb +38 -0
  38. data/lib/relaton/bib/model/type/string_date.rb +48 -0
  39. data/lib/relaton/bib/model/validity.rb +3 -3
  40. data/lib/relaton/bib/namespace_helper.rb +21 -0
  41. data/lib/relaton/bib/version.rb +1 -1
  42. data/lib/relaton/bib.rb +5 -82
  43. data/relaton-bib.gemspec +5 -2
  44. metadata +63 -29
  45. data/lib/relaton/bib/model/editorial_group.rb +0 -14
  46. data/lib/relaton/bib/model/technical_committee.rb +0 -14
  47. data/lib/relaton/bib/model/workgroup.rb +0 -20
  48. data/lib/relaton/bib/parser/rfc_address.rb +0 -60
  49. data/lib/relaton/bib/parser/rfc_contacts.rb +0 -35
  50. data/lib/relaton/bib/parser/rfc_docidentifier.rb +0 -70
  51. data/lib/relaton/bib/parser/rfc_organization.rb +0 -31
  52. data/lib/relaton/bib/parser/rfc_person.rb +0 -42
  53. data/lib/relaton/bib/parser/rfc_reference.rb +0 -143
  54. data/lib/relaton/bib/parser/rfc_referencegroup.rb +0 -45
  55. data/lib/relaton/bib/parser/rfc_shared.rb +0 -23
  56. data/lib/relaton/bib/renderer/bibtex_builder.rb +0 -348
  57. data/lib/relaton/bibtex_parser.rb +0 -243
  58. data/lib/relaton/bibxml_parser.rb +0 -419
  59. data/lib/relaton/deep_dup.rb +0 -30
  60. data/lib/relaton/hit.rb +0 -52
  61. data/lib/relaton/hit_collection.rb +0 -105
  62. data/lib/relaton/workers_pool.rb +0 -43
  63. data/lib/relaton/xml_parser.rb +0 -716
@@ -3,7 +3,10 @@ require_relative "../bib"
3
3
  module Relaton
4
4
  module Bib
5
5
  module HashParserV1
6
+ include Core::ArrayWrapper
7
+ include Core::DateParser
6
8
  extend self
9
+
7
10
  # @param args [Hash]
8
11
  # @return [Hash]
9
12
  def hash_to_bib(args) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
@@ -11,7 +14,9 @@ module Relaton
11
14
 
12
15
  ret = Marshal.load(Marshal.dump(symbolize(args))) # deep copy
13
16
  ret[:fetched] &&= ::Date.parse(ret[:fetched])
14
- ret[:schema_version] = ret.delete(:"schema-version") if ret[:"schema-version"]
17
+ ret.delete(:"schema-version")
18
+ ret.delete(:schema_version)
19
+ id_hash_to_bib ret
15
20
  title_hash_to_bib(ret)
16
21
  link_hash_to_bib(ret)
17
22
  language_hash_to_bib(ret)
@@ -24,6 +29,7 @@ module Relaton
24
29
  formattedref_hash_to_bib(ret)
25
30
  docstatus_hash_to_bib(ret)
26
31
  contributors_hash_to_bib(ret)
32
+ editorialgroup_hash_to_bib(ret)
27
33
  edition_hash_to_bib(ret)
28
34
  copyright_hash_to_bib(ret)
29
35
  relations_hash_to_bib(ret)
@@ -36,17 +42,22 @@ module Relaton
36
42
  classification_hash_to_bib(ret)
37
43
  validity_hash_to_bib(ret)
38
44
  keyword_hash_to_bib(ret)
39
- ret[:license] = Relaton.array(ret[:license])
45
+ ret[:license] = array(ret[:license])
40
46
  ext_hash_to_bib ret
41
47
  ret
42
48
  end
43
49
 
50
+ def id_hash_to_bib(ret)
51
+ return unless ret[:id]
52
+
53
+ ret[:id] = ret[:id].gsub(/\W+/, "")
54
+ end
55
+
44
56
  def ext_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize
45
57
  ret[:ext] ||= {}
46
58
  doctype_hash_to_bib ret
47
59
  ret[:ext][:subdoctype] = ret.delete(:subdoctype) if ret[:subdoctype]
48
60
  ret[:ext][:flavor] ||= flavor(ret)
49
- editorialgroup_hash_to_bib ret
50
61
  ics_hash_to_bib ret
51
62
  structuredidentifier_hash_to_bib ret
52
63
  ret[:ext] = Bib::Ext.new(**ret[:ext])
@@ -62,32 +73,32 @@ module Relaton
62
73
  end
63
74
 
64
75
  def keyword_hash_to_bib(ret)
65
- ret[:keyword] = Relaton.array(ret[:keyword]).map do |keyword|
66
- Bib::Keyword.new taxon: [localizedstring(keyword)]
76
+ ret[:keyword] = array(ret[:keyword]).map do |keyword|
77
+ Bib::Keyword.new vocab: localizedstring(keyword)
67
78
  end
68
79
  end
69
80
 
70
81
  def extent_hash_to_bib(ret)
71
82
  return unless ret[:extent]
72
83
 
73
- ret[:extent] = Relaton.array(ret[:extent]).map do |e|
84
+ ret[:extent] = array(ret[:extent]).map do |e|
74
85
  Relaton::Bib::Extent.new locality: locality(e[:locality]),
75
86
  locality_stack: locality_stack(e[:locality_stack])
76
87
  end
77
88
  end
78
89
 
79
90
  def locality(locality)
80
- Relaton.array(locality).map { |l| Bib::Locality.new(**l) }
91
+ array(locality).map { |l| Bib::Locality.new(**l) }
81
92
  end
82
93
 
83
94
  def locality_stack(locality_stack)
84
- Relaton.array(locality_stack).map { |l| Bib::LocalityStack.new locality: locality(l[:locality]) }
95
+ array(locality_stack).map { |l| Bib::LocalityStack.new locality: locality(l[:locality]) }
85
96
  end
86
97
 
87
98
  def size_hash_to_bib(ret)
88
99
  return unless ret[:size]
89
100
 
90
- ret[:size] = Relaton.array(ret[:size])
101
+ ret[:size] = array(ret[:size])
91
102
  value = ret[:size]&.map do |val|
92
103
  val[:content] = val.delete(:value)
93
104
  Bib::Size::Value.new(**val)
@@ -98,7 +109,7 @@ module Relaton
98
109
  def title_hash_to_bib(ret)
99
110
  # return unless ret[:title]
100
111
 
101
- # ret[:title] = Relaton.array(ret[:title]).reduce(Bib::TitleCollection.new) do |m, t|
112
+ # ret[:title] = array(ret[:title]).reduce(Bib::TitleCollection.new) do |m, t|
102
113
  # m << (t.is_a?(Hash) ? Bib::Title.new(**t) : Bib::Title.new(content: t))
103
114
  # end
104
115
  ret[:title] &&= title_collection(ret[:title])
@@ -107,31 +118,33 @@ module Relaton
107
118
  def language_hash_to_bib(ret)
108
119
  return unless ret[:language]
109
120
 
110
- ret[:language] = Relaton.array(ret[:language])
121
+ ret[:language] = array(ret[:language])
111
122
  end
112
123
 
113
124
  def script_hash_to_bib(ret)
114
125
  return unless ret[:script]
115
126
 
116
- ret[:script] = Relaton.array(ret[:script])
127
+ ret[:script] = array(ret[:script])
117
128
  end
118
129
 
119
130
  def abstract_hash_to_bib(ret)
120
- ret[:abstract] &&= Relaton.array(ret[:abstract]).map do |a|
121
- localized_marked_up_string a
131
+ ret[:abstract] &&= array(ret[:abstract]).map do |a|
132
+ a = { content: a } if a.is_a?(String)
133
+ lang_scrip_array_to_string(a)
134
+ Bib::Abstract.new(**a)
122
135
  end
123
136
  end
124
137
 
125
138
  def link_hash_to_bib(ret)
126
139
  return unless ret[:link]
127
140
 
128
- ret[:source] = Relaton.array(ret[:link]).map do |l|
141
+ ret[:source] = array(ret[:link]).map do |l|
129
142
  Bib::Uri.new(**l)
130
143
  end
131
144
  end
132
145
 
133
146
  def place_hash_to_bib(ret)
134
- ret[:place] &&= Relaton.array(ret[:place]).map { |pl| create_place(pl) }
147
+ ret[:place] &&= array(ret[:place]).map { |pl| create_place(pl) }
135
148
  end
136
149
 
137
150
  def create_place(place)
@@ -145,7 +158,7 @@ module Relaton
145
158
  end
146
159
 
147
160
  def create_region(region)
148
- Relaton.array(region).map do |r|
161
+ array(region).map do |r|
149
162
  r[:content] ||= r.delete(:name)
150
163
  r[:iso] ||= r.delete(:code)
151
164
  Bib::Place::RegionType.new(**r)
@@ -155,11 +168,11 @@ module Relaton
155
168
  def accesslocation_hash_to_bib(ret)
156
169
  return unless ret[:accesslocation]
157
170
 
158
- ret[:accesslocation] = Relaton.array(ret[:accesslocation])
171
+ ret[:accesslocation] = array(ret[:accesslocation])
159
172
  end
160
173
 
161
174
  def dates_hash_to_bib(ret)
162
- ret[:date] &&= Relaton.array(ret[:date]).map do |d|
175
+ ret[:date] &&= array(ret[:date]).map do |d|
163
176
  # `at` is synonym of `on`, which is reserved word in YAML
164
177
  d[:at] = d.delete(:value) if d[:value]
165
178
  Bib::Date.new(**d)
@@ -169,7 +182,7 @@ module Relaton
169
182
  def docid_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize
170
183
  return unless ret[:docid]
171
184
 
172
- ret[:docidentifier] = Relaton.array(ret[:docid]).map do |id|
185
+ ret[:docidentifier] = array(ret[:docid]).map do |id|
173
186
  id[:type] ||= id[:id].match(/^\w+(?=\s)/)&.to_s
174
187
  id[:content] = id[:id]
175
188
  create_docid(**id)
@@ -183,14 +196,14 @@ module Relaton
183
196
  def version_hash_to_bib(ret)
184
197
  return unless ret[:version]
185
198
 
186
- ret[:version] = Relaton.array(ret[:version]).map do |v|
187
- v[:revision_date] &&= ::Date.parse(v[:revision_date])
199
+ ret[:version] = array(ret[:version]).map do |v|
200
+ v[:revision_date] &&= parse_date(v[:revision_date], str: false)
188
201
  Bib::Version.new(**v)
189
202
  end
190
203
  end
191
204
 
192
205
  def biblionote_hash_to_bib(ret)
193
- ret[:note] = Relaton.array(ret.delete(:biblionote)).map do |n|
206
+ ret[:note] = array(ret.delete(:biblionote)).map do |n|
194
207
  n.is_a?(String) ? Bib::Note.new(content: n) : Bib::Note.new(**n)
195
208
  end
196
209
  end
@@ -219,10 +232,10 @@ module Relaton
219
232
  end
220
233
 
221
234
  def contributors_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity
222
- ret[:contributor] &&= Relaton.array(ret[:contributor]).map do |c|
223
- roles = Relaton.array(c[:role]).map do |r|
235
+ ret[:contributor] &&= array(ret[:contributor]).map do |c|
236
+ roles = array(c[:role]).map do |r|
224
237
  if r.is_a? Hash
225
- desc = Relaton.array(r[:description]).map { |d| localized_marked_up_string d }
238
+ desc = array(r[:description]).map { |d| localized_marked_up_string d }
226
239
  Bib::Contributor::Role.new(type: r[:type], description: desc)
227
240
  else
228
241
  Bib::Contributor::Role.new(type: r)
@@ -256,20 +269,22 @@ module Relaton
256
269
  org[:phone] = phone_hash_to_bib(org[:contact])
257
270
  org[:email] = email_hash_to_bib(org[:contact])
258
271
  org[:uri] = uri_hash_to_bib(org[:contact] || org)
259
- org[:logo] = Bib::Logo.new image: Bib::Image.new(**org[:logo][:image]) if org[:logo]
272
+ org[:logo] = array(org[:logo]).map do |l|
273
+ Bib::Logo.new(image: Bib::Image.new(**l[:image]))
274
+ end
260
275
  org[:name] = typed_localized_string(org[:name])
261
276
  org[:abbreviation] &&= localizedstring(org[:abbreviation])
262
277
  org
263
278
  end
264
279
 
265
280
  def create_org_identifier(identifier)
266
- Relaton.array(identifier).map do |id|
281
+ array(identifier).map do |id|
267
282
  Bib::Organization::Identifier.new(type: id[:type], content: id[:id])
268
283
  end
269
284
  end
270
285
 
271
286
  def create_org_subdivision(subdivision)
272
- Relaton.array(subdivision).map do |sub|
287
+ array(subdivision).map do |sub|
273
288
  if sub.is_a? String
274
289
  orgname = Bib::TypedLocalizedString.new(content: sub)
275
290
  Bib::Subdivision.new(name: [orgname])
@@ -281,7 +296,7 @@ module Relaton
281
296
  end
282
297
 
283
298
  def typed_localized_string(typed_strs)
284
- Relaton.array(typed_strs).map do |args|
299
+ array(typed_strs).map do |args|
285
300
  if args.is_a? String
286
301
  Bib::TypedLocalizedString.new(content: args)
287
302
  elsif args.is_a? Hash
@@ -291,7 +306,7 @@ module Relaton
291
306
  end
292
307
 
293
308
  # def create_org_name(name)
294
- # Relaton.array(name).map do |nm|
309
+ # array(name).map do |nm|
295
310
  # if nm.is_a?(Hash)
296
311
  # Bib::Organization::Name.new(**nm)
297
312
  # else
@@ -303,7 +318,7 @@ module Relaton
303
318
  def create_person(person)
304
319
  Bib::Person.new(
305
320
  name: fullname_hash_to_bib(person),
306
- credential: Relaton.array(person[:credential]),
321
+ credential: array(person[:credential]),
307
322
  affiliation: affiliation_hash_to_bib(person),
308
323
  address: address_hash_to_bib(person[:contact]),
309
324
  phone: phone_hash_to_bib(person[:contact]),
@@ -320,8 +335,8 @@ module Relaton
320
335
  abbreviation: localizedstring(n[:abbreviation]),
321
336
  forename: fname,
322
337
  formatted_initials: localizedstring(n.dig(:given, :formatted_initials)),
323
- addition: Relaton.array(n[:addition])&.map { |f| localizedstring(f) },
324
- prefix: Relaton.array(n[:prefix])&.map { |f| localizedstring(f) },
338
+ addition: array(n[:addition])&.map { |f| localizedstring(f) },
339
+ prefix: array(n[:prefix])&.map { |f| localizedstring(f) },
325
340
  surname: localizedstring(n[:surname]),
326
341
  completename: localizedstring(n[:completename]),
327
342
  )
@@ -330,7 +345,7 @@ module Relaton
330
345
  def given_hash_to_bib(given)
331
346
  return unless given
332
347
 
333
- Relaton.array(given[:forename])&.map { |f| forename_hash_to_bib(f) }
348
+ array(given[:forename])&.map { |f| forename_hash_to_bib(f) }
334
349
  end
335
350
 
336
351
  def forename_hash_to_bib(fname)
@@ -343,7 +358,7 @@ module Relaton
343
358
  end
344
359
 
345
360
  def person_identifiers_hash_to_bib(person)
346
- Relaton.array(person[:identifier])&.map do |a|
361
+ array(person[:identifier])&.map do |a|
347
362
  Bib::Person::Identifier.new(type: a[:type], content: a[:id])
348
363
  end
349
364
  end
@@ -351,8 +366,8 @@ module Relaton
351
366
  def affiliation_hash_to_bib(person) # rubocop:disable Metrics/AbcSize
352
367
  return [] unless person[:affiliation]
353
368
 
354
- Relaton.array(person[:affiliation]).map do |a|
355
- a[:description] = Relaton.array(a[:description]).map do |d|
369
+ array(person[:affiliation]).map do |a|
370
+ a[:description] = array(a[:description]).map do |d|
356
371
  localized_marked_up_string d
357
372
  end
358
373
  Bib::Affiliation.new(
@@ -363,7 +378,7 @@ module Relaton
363
378
  end
364
379
 
365
380
  def address_hash_to_bib(contact)
366
- Relaton.array(contact).reduce([]) do |a, c|
381
+ array(contact).reduce([]) do |a, c|
367
382
  next a unless c[:address]
368
383
 
369
384
  a << create_address(c[:address])
@@ -371,7 +386,7 @@ module Relaton
371
386
  end
372
387
 
373
388
  def phone_hash_to_bib(contact)
374
- Relaton.array(contact).reduce([]) do |a, c|
389
+ array(contact).reduce([]) do |a, c|
375
390
  next a unless c[:phone]
376
391
 
377
392
  c[:type] ||= "work"
@@ -380,7 +395,7 @@ module Relaton
380
395
  end
381
396
 
382
397
  def email_hash_to_bib(contact)
383
- Relaton.array(contact).reduce([]) do |a, c|
398
+ array(contact).reduce([]) do |a, c|
384
399
  next a unless c[:email]
385
400
 
386
401
  a << c[:email]
@@ -388,7 +403,7 @@ module Relaton
388
403
  end
389
404
 
390
405
  def uri_hash_to_bib(contact)
391
- Relaton.array(contact).reduce([]) do |a, c|
406
+ array(contact).reduce([]) do |a, c|
392
407
  next a unless c[:uri] || c[:url]
393
408
 
394
409
  a << Bib::Uri.new(content: c[:uri] || c[:url])
@@ -415,7 +430,7 @@ module Relaton
415
430
 
416
431
  def create_address(adr)
417
432
  if adr.is_a?(Hash)
418
- adr[:street] = Relaton.array(adr[:street])
433
+ adr[:street] = array(adr[:street])
419
434
  Bib::Address.new(**adr)
420
435
  else
421
436
  Bib::Address.new(formatted_address: adr)
@@ -424,8 +439,8 @@ module Relaton
424
439
 
425
440
  # @param ret [Hash]
426
441
  def copyright_hash_to_bib(ret)
427
- ret[:copyright] &&= Relaton.array(ret[:copyright]).map do |c|
428
- c[:owner] = Relaton.array(c[:owner]).map do |o|
442
+ ret[:copyright] &&= array(ret[:copyright]).map do |c|
443
+ c[:owner] = array(c[:owner]).map do |o|
429
444
  create_contribution_info(o)
430
445
  end
431
446
  Bib::Copyright.new(**c)
@@ -444,7 +459,7 @@ module Relaton
444
459
  def relations_hash_to_bib(ret) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
445
460
  return unless ret[:relation]
446
461
 
447
- ret[:relation] &&= Relaton.array(ret[:relation]).map do |rel|
462
+ ret[:relation] &&= array(ret[:relation]).map do |rel|
448
463
  rel[:description] = LocalizedMarkedUpString.new(**rel[:description]) if rel[:description]
449
464
  relation_bibitem_hash_to_bib(rel)
450
465
  relation_locality_hash_to_bib(rel)
@@ -480,7 +495,7 @@ module Relaton
480
495
  def relation_locality_hash_to_bib(rel)
481
496
  return unless rel[:locality]&.any?
482
497
 
483
- rel[:locality] = Relaton.array(rel[:locality]).map do |bl|
498
+ rel[:locality] = array(rel[:locality]).map do |bl|
484
499
  Bib::Locality.new(**bl)
485
500
  end
486
501
  end
@@ -488,7 +503,7 @@ module Relaton
488
503
  def relation_locality_stack_hash_to_bib(rel)
489
504
  return unless rel[:locality_stack]&.any?
490
505
 
491
- rel[:locality_stack] = Relaton.array(rel[:locality_stack]).map do |ls|
506
+ rel[:locality_stack] = array(rel[:locality_stack]).map do |ls|
492
507
  Bib::LocalityStack.new locality: relation_locality_hash_to_bib(ls)
493
508
  end
494
509
  end
@@ -506,15 +521,15 @@ module Relaton
506
521
 
507
522
  # @param rel [Hash] relation
508
523
  def relation_source_locality_hash_to_bib(rel)
509
- rel[:source_locality] = Relaton.array(rel[:source_locality]).map do |loc|
524
+ rel[:source_locality] = array(rel[:source_locality]).map do |loc|
510
525
  Bib::Locality.new(**loc)
511
526
  end
512
527
  end
513
528
 
514
529
  def relaton_source_locality_stack_hash_to_bib(rel) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength
515
- sls = Relaton.array(rel[:source_locality_stack])
516
- Relaton.array(rel[:source_locality]).each do |loc|
517
- sls << Relaton.array(loc[:source_locality_stack]) if loc[:source_locality_stack]
530
+ sls = array(rel[:source_locality_stack])
531
+ array(rel[:source_locality]).each do |loc|
532
+ sls << array(loc[:source_locality_stack]) if loc[:source_locality_stack]
518
533
  end
519
534
 
520
535
  case rel[:source_locality]
@@ -529,13 +544,13 @@ module Relaton
529
544
 
530
545
  # @param ret [Hash]
531
546
  def series_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
532
- ret[:series] &&= Relaton.array(ret[:series]).map do |s|
547
+ ret[:series] &&= array(ret[:series]).map do |s|
533
548
  s[:formattedref] && s[:formattedref] = formattedref(s[:formattedref])
534
549
  s[:title] &&= title_collection(s[:title])
535
550
  s[:place] &&= create_place(s[:place])
536
551
  s[:abbreviation] &&= localizedstring(s[:abbreviation])
537
- s[:from] &&= ::Date.parse(s[:from])
538
- s[:to] &&= ::Date.parse(s[:to])
552
+ s[:from] &&= s[:from].to_s
553
+ s[:to] &&= s[:to].to_s
539
554
  Bib::Series.new(**s)
540
555
  end
541
556
  end
@@ -546,7 +561,7 @@ module Relaton
546
561
  # @return [Relaton::Bib::TitleCollection]
547
562
  #
548
563
  def title_collection(title)
549
- Relaton.array(title).map do |t|
564
+ array(title).map do |t|
550
565
  if t.is_a?(Hash)
551
566
  lang_scrip_array_to_string t
552
567
  Bib::Title.new(**t)
@@ -564,7 +579,7 @@ module Relaton
564
579
  # @param ret [Hash]
565
580
  def classification_hash_to_bib(ret)
566
581
  if ret[:classification]
567
- ret[:classification] = Relaton.array(ret[:classification]).map do |cls|
582
+ ret[:classification] = array(ret[:classification]).map do |cls|
568
583
  cls[:content] ||= cls.delete(:value)
569
584
  Docidentifier.new(**cls)
570
585
  end
@@ -588,29 +603,58 @@ module Relaton
588
603
  p = period == :ends ? -1 : 1
589
604
  case t
590
605
  when /^\d{4}$/
591
- ::Date.new(t.to_i, p, p).to_time
606
+ ::Date.new(t.to_i, p, p).to_datetime.to_time.utc
592
607
  when /^(?<year>\d{4})-(?<month>\d{1,2})$/
593
- ::Date.new($~[:year].to_i, $~[:month].to_i, p).to_time
594
- else ::Date.parse t
608
+ ::Date.new($~[:year].to_i, $~[:month].to_i, p).to_datetime.to_time.utc
609
+ else
610
+ # Default to UTC when no timezone is specified
611
+ t += " UTC" unless t.match?(/[+-]\d{2}:?\d{2}\s*$|Z\s*$/i)
612
+ ::Time.parse t
595
613
  end
596
614
  end
597
615
 
598
616
  # @param ret [Hash]
599
- def editorialgroup_hash_to_bib(ret)
600
- eg = ret.dig(:ext, :editorialgroup) || ret[:editorialgroup] # @todo remove ret[:editorialgroup] in the future
617
+ def editorialgroup_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
618
+ eg = ret.dig(:ext, :editorialgroup) || ret[:editorialgroup]
601
619
  return unless eg
602
620
 
603
- technical_committee = workgroup_hash_to_bib eg
604
- ret[:ext][:editorialgroup] = Bib::EditorialGroup.new technical_committee: technical_committee
605
- end
606
-
607
- def workgroup_hash_to_bib(wrkg)
608
- Relaton.array(wrkg).map { |wg| create_workgroup wg }
621
+ ret[:ext]&.delete(:editorialgroup)
622
+ ret.delete(:editorialgroup)
623
+ ret[:contributor] ||= []
624
+ array(eg).each do |wg|
625
+ wg[:content] ||= wg.delete(:name)
626
+ ret[:contributor] << Bib::Contributor.new(
627
+ role: [Bib::Contributor::Role.new(
628
+ type: "author",
629
+ description: [Bib::LocalizedMarkedUpString.new(content: "committee")],
630
+ )],
631
+ organization: Bib::Organization.new(
632
+ name: wg[:prefix] ? [Bib::TypedLocalizedString.new(content: wg[:prefix])] : [],
633
+ subdivision: [Bib::Subdivision.new(
634
+ type: "technical-committee",
635
+ subtype: wg[:type],
636
+ name: [Bib::TypedLocalizedString.new(content: wg[:content])],
637
+ identifier: eg_identifiers(wg),
638
+ )],
639
+ abbreviation: wg[:prefix] ? Bib::LocalizedString.new(content: wg[:prefix]) : nil,
640
+ ),
641
+ )
642
+ end
609
643
  end
610
644
 
611
- def create_workgroup(wrkg)
612
- wrkg[:content] ||= wrkg.delete(:name)
613
- Bib::WorkGroup.new(**wrkg)
645
+ def eg_identifiers(workgroup) # rubocop:disable Metrics/MethodLength
646
+ ids = []
647
+ if workgroup[:number]
648
+ ids << Bib::OrganizationType::Identifier.new(
649
+ content: workgroup[:number].to_s,
650
+ )
651
+ end
652
+ if workgroup[:identifier]
653
+ ids << Bib::OrganizationType::Identifier.new(
654
+ content: workgroup[:identifier],
655
+ )
656
+ end
657
+ ids
614
658
  end
615
659
 
616
660
  # @param ret [Hash]
@@ -618,7 +662,7 @@ module Relaton
618
662
  ics = ret.dig(:ext, :ics) || ret[:ics] # @todo remove ret[:ics] in the future
619
663
  return unless ics
620
664
 
621
- ret[:ext][:ics] = Relaton.array(ics).map { |item| Bib::ICS.new(**item) }
665
+ ret[:ext][:ics] = array(ics).map { |item| Bib::ICS.new(**item) }
622
666
  end
623
667
 
624
668
  # @param ret [Hash]
@@ -626,8 +670,8 @@ module Relaton
626
670
  struct_id = ret.dig(:ext, :structuredidentifier) || ret[:structuredidentifier] # @todo remove ret[:structuredidentifier] in the future
627
671
  return unless struct_id
628
672
 
629
- sids = Relaton.array(struct_id).map do |si|
630
- si[:agency] = Relaton.array si[:agency]
673
+ sids = array(struct_id).map do |si|
674
+ si[:agency] = array si[:agency]
631
675
  si[:klass] = si.delete(:class)
632
676
  Bib::StructuredIdentifier.new(**si)
633
677
  end
@@ -679,11 +723,10 @@ module Relaton
679
723
  # @return [Relaton::Bib::Formattedref]
680
724
  def formattedref(frf)
681
725
  if frf.is_a?(Hash)
682
- # Relaton::Bib::Formattedref.new(**frf)
683
- frf[:content]
726
+ lang_scrip_array_to_string(frf)
727
+ Relaton::Bib::Formattedref.new(**frf)
684
728
  else
685
- # Relaton::Bib::Formattedref.new(content: frf)
686
- frf
729
+ Relaton::Bib::Formattedref.new(content: frf)
687
730
  end
688
731
  end
689
732