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

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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/README.adoc +183 -154
  4. data/bin/console +1 -1
  5. data/grammars/basicdoc.rng +1516 -645
  6. data/grammars/biblio-standoc.rng +100 -20
  7. data/grammars/biblio.rng +959 -356
  8. data/grammars/versions.json +10 -10
  9. data/lib/relaton/bib/hash_parser_v1.rb +711 -0
  10. data/lib/relaton/bib/item_data.rb +168 -0
  11. data/lib/relaton/bib/model/address.rb +22 -0
  12. data/lib/relaton/bib/model/affiliation.rb +16 -0
  13. data/lib/relaton/bib/model/bibdata.rb +24 -0
  14. data/lib/relaton/bib/model/bibitem.rb +23 -0
  15. data/lib/relaton/bib/model/contact.rb +18 -0
  16. data/lib/relaton/bib/model/contribution_info.rb +16 -0
  17. data/lib/relaton/bib/model/contributor.rb +71 -0
  18. data/lib/relaton/bib/model/copyright.rb +27 -0
  19. data/lib/relaton/bib/model/date.rb +29 -0
  20. data/lib/relaton/bib/model/depiction.rb +14 -0
  21. data/lib/relaton/bib/model/docidentifier.rb +33 -0
  22. data/lib/relaton/bib/model/doctype.rb +14 -0
  23. data/lib/relaton/bib/model/edition.rb +14 -0
  24. data/lib/relaton/bib/model/editorial_group.rb +14 -0
  25. data/lib/relaton/bib/model/ext.rb +29 -0
  26. data/lib/relaton/bib/model/extent.rb +16 -0
  27. data/lib/relaton/bib/model/full_name_type.rb +64 -0
  28. data/lib/relaton/bib/model/fullname.rb +11 -0
  29. data/lib/relaton/bib/model/ics.rb +14 -0
  30. data/lib/relaton/bib/model/image.rb +28 -0
  31. data/lib/relaton/bib/model/item.rb +129 -0
  32. data/lib/relaton/bib/model/item_base.rb +19 -0
  33. data/lib/relaton/bib/model/keyword.rb +30 -0
  34. data/lib/relaton/bib/model/locality.rb +18 -0
  35. data/lib/relaton/bib/model/locality_stack.rb +14 -0
  36. data/lib/relaton/bib/model/localized_string.rb +57 -0
  37. data/lib/relaton/bib/model/localized_string_attrs.rb +24 -0
  38. data/lib/relaton/bib/model/logo.rb +12 -0
  39. data/lib/relaton/bib/model/medium.rb +22 -0
  40. data/lib/relaton/bib/model/note.rb +16 -0
  41. data/lib/relaton/bib/model/organization.rb +13 -0
  42. data/lib/relaton/bib/model/organization_type.rb +42 -0
  43. data/lib/relaton/bib/model/person.rb +36 -0
  44. data/lib/relaton/bib/model/phone.rb +14 -0
  45. data/lib/relaton/bib/model/place.rb +33 -0
  46. data/lib/relaton/bib/model/price.rb +14 -0
  47. data/lib/relaton/bib/model/relation.rb +43 -0
  48. data/lib/relaton/bib/model/series.rb +32 -0
  49. data/lib/relaton/bib/model/size.rb +23 -0
  50. data/lib/relaton/bib/model/source_locality_stack.rb +14 -0
  51. data/lib/relaton/bib/model/status.rb +27 -0
  52. data/lib/relaton/bib/model/structured_identifier.rb +48 -0
  53. data/lib/relaton/bib/model/subdivision.rb +14 -0
  54. data/lib/relaton/bib/model/technical_committee.rb +14 -0
  55. data/lib/relaton/bib/model/title.rb +18 -0
  56. data/lib/relaton/bib/model/uri.rb +18 -0
  57. data/lib/relaton/bib/model/validity.rb +16 -0
  58. data/lib/relaton/bib/model/version.rb +14 -0
  59. data/lib/relaton/bib/model/workgroup.rb +20 -0
  60. data/lib/relaton/bib/parser/rfc_address.rb +60 -0
  61. data/lib/relaton/bib/parser/rfc_contacts.rb +35 -0
  62. data/lib/relaton/bib/parser/rfc_docidentifier.rb +70 -0
  63. data/lib/relaton/bib/parser/rfc_organization.rb +31 -0
  64. data/lib/relaton/bib/parser/rfc_person.rb +42 -0
  65. data/lib/relaton/bib/parser/rfc_reference.rb +143 -0
  66. data/lib/relaton/bib/parser/rfc_referencegroup.rb +45 -0
  67. data/lib/relaton/bib/parser/rfc_shared.rb +23 -0
  68. data/lib/relaton/bib/renderer/bibtex_builder.rb +348 -0
  69. data/lib/relaton/bib/renderer/rfc.rb +297 -0
  70. data/lib/relaton/bib/util.rb +18 -0
  71. data/lib/relaton/bib/version.rb +5 -0
  72. data/lib/{relaton_bib.rb → relaton/bib.rb} +47 -36
  73. data/lib/{relaton_bib → relaton}/bibtex_parser.rb +24 -27
  74. data/lib/{relaton_bib → relaton}/bibxml_parser.rb +43 -46
  75. data/lib/{relaton_bib → relaton}/hit.rb +3 -3
  76. data/lib/{relaton_bib → relaton}/hit_collection.rb +2 -2
  77. data/lib/{relaton_bib → relaton}/workers_pool.rb +1 -1
  78. data/lib/{relaton_bib → relaton}/xml_parser.rb +49 -51
  79. data/relaton-bib.gemspec +8 -8
  80. metadata +95 -74
  81. data/lib/relaton_bib/bib_item_locality.rb +0 -175
  82. data/lib/relaton_bib/biblio_note.rb +0 -72
  83. data/lib/relaton_bib/biblio_version.rb +0 -46
  84. data/lib/relaton_bib/bibliographic_date.rb +0 -119
  85. data/lib/relaton_bib/bibliographic_item.rb +0 -668
  86. data/lib/relaton_bib/bibliographic_size.rb +0 -103
  87. data/lib/relaton_bib/classification.rb +0 -40
  88. data/lib/relaton_bib/config.rb +0 -16
  89. data/lib/relaton_bib/contribution_info.rb +0 -117
  90. data/lib/relaton_bib/contributor.rb +0 -277
  91. data/lib/relaton_bib/copyright_association.rb +0 -79
  92. data/lib/relaton_bib/document_identifier.rb +0 -118
  93. data/lib/relaton_bib/document_relation.rb +0 -95
  94. data/lib/relaton_bib/document_relation_collection.rb +0 -57
  95. data/lib/relaton_bib/document_status.rb +0 -92
  96. data/lib/relaton_bib/document_type.rb +0 -52
  97. data/lib/relaton_bib/edition.rb +0 -55
  98. data/lib/relaton_bib/editorial_group.rb +0 -41
  99. data/lib/relaton_bib/extent.rb +0 -39
  100. data/lib/relaton_bib/forename.rb +0 -65
  101. data/lib/relaton_bib/formatted_ref.rb +0 -17
  102. data/lib/relaton_bib/formatted_string.rb +0 -133
  103. data/lib/relaton_bib/full_name.rb +0 -108
  104. data/lib/relaton_bib/hash_converter.rb +0 -568
  105. data/lib/relaton_bib/ics.rb +0 -42
  106. data/lib/relaton_bib/image.rb +0 -95
  107. data/lib/relaton_bib/localized_string.rb +0 -149
  108. data/lib/relaton_bib/medium.rb +0 -76
  109. data/lib/relaton_bib/organization.rb +0 -165
  110. data/lib/relaton_bib/person.rb +0 -129
  111. data/lib/relaton_bib/place.rb +0 -203
  112. data/lib/relaton_bib/renderer/bibtex_builder.rb +0 -312
  113. data/lib/relaton_bib/renderer/bibxml.rb +0 -296
  114. data/lib/relaton_bib/series.rb +0 -119
  115. data/lib/relaton_bib/structured_identifier.rb +0 -173
  116. data/lib/relaton_bib/technical_committee.rb +0 -34
  117. data/lib/relaton_bib/typed_title_string.rb +0 -191
  118. data/lib/relaton_bib/typed_uri.rb +0 -57
  119. data/lib/relaton_bib/util.rb +0 -16
  120. data/lib/relaton_bib/validity.rb +0 -52
  121. data/lib/relaton_bib/version.rb +0 -3
  122. data/lib/relaton_bib/workgroup.rb +0 -58
  123. /data/lib/{relaton_bib → relaton}/deep_dup.rb +0 -0
@@ -0,0 +1,711 @@
1
+ require_relative "../bib"
2
+
3
+ module Relaton
4
+ module Bib
5
+ module HashParserV1
6
+ extend self
7
+ # @param args [Hash]
8
+ # @return [Hash]
9
+ def hash_to_bib(args) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
10
+ return nil unless args.is_a?(Hash)
11
+
12
+ ret = Marshal.load(Marshal.dump(symbolize(args))) # deep copy
13
+ ret[:fetched] &&= ::Date.parse(ret[:fetched])
14
+ ret[:schema_version] = ret.delete(:"schema-version") if ret[:"schema-version"]
15
+ title_hash_to_bib(ret)
16
+ link_hash_to_bib(ret)
17
+ language_hash_to_bib(ret)
18
+ script_hash_to_bib(ret)
19
+ dates_hash_to_bib(ret)
20
+ docid_hash_to_bib(ret)
21
+ version_hash_to_bib(ret)
22
+ biblionote_hash_to_bib(ret)
23
+ abstract_hash_to_bib(ret)
24
+ formattedref_hash_to_bib(ret)
25
+ docstatus_hash_to_bib(ret)
26
+ contributors_hash_to_bib(ret)
27
+ edition_hash_to_bib(ret)
28
+ copyright_hash_to_bib(ret)
29
+ relations_hash_to_bib(ret)
30
+ series_hash_to_bib(ret)
31
+ medium_hash_to_bib(ret)
32
+ place_hash_to_bib(ret)
33
+ extent_hash_to_bib(ret)
34
+ size_hash_to_bib(ret)
35
+ accesslocation_hash_to_bib(ret)
36
+ classification_hash_to_bib(ret)
37
+ validity_hash_to_bib(ret)
38
+ keyword_hash_to_bib(ret)
39
+ ret[:license] = Relaton.array(ret[:license])
40
+ ext_hash_to_bib ret
41
+ ret
42
+ end
43
+
44
+ def ext_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize
45
+ ret[:ext] ||= {}
46
+ doctype_hash_to_bib ret
47
+ ret[:ext][:subdoctype] = ret.delete(:subdoctype) if ret[:subdoctype]
48
+ ret[:ext][:flavor] ||= flavor(ret)
49
+ editorialgroup_hash_to_bib ret
50
+ ics_hash_to_bib ret
51
+ structuredidentifier_hash_to_bib ret
52
+ ret[:ext] = Bib::Ext.new(**ret[:ext])
53
+ end
54
+
55
+ def flavor(ret)
56
+ return unless ret[:docid]
57
+
58
+ docid = ret[:docidentifier].find(&:primary)
59
+ return unless docid
60
+
61
+ docid.type.downcase
62
+ end
63
+
64
+ def keyword_hash_to_bib(ret)
65
+ ret[:keyword] = Relaton.array(ret[:keyword]).map do |keyword|
66
+ Bib::Keyword.new taxon: [localizedstring(keyword)]
67
+ end
68
+ end
69
+
70
+ def extent_hash_to_bib(ret)
71
+ return unless ret[:extent]
72
+
73
+ ret[:extent] = Relaton.array(ret[:extent]).map do |e|
74
+ Relaton::Bib::Extent.new locality: locality(e[:locality]),
75
+ locality_stack: locality_stack(e[:locality_stack])
76
+ end
77
+ end
78
+
79
+ def locality(locality)
80
+ Relaton.array(locality).map { |l| Bib::Locality.new(**l) }
81
+ end
82
+
83
+ def locality_stack(locality_stack)
84
+ Relaton.array(locality_stack).map { |l| Bib::LocalityStack.new locality: locality(l[:locality]) }
85
+ end
86
+
87
+ def size_hash_to_bib(ret)
88
+ return unless ret[:size]
89
+
90
+ ret[:size] = Relaton.array(ret[:size])
91
+ value = ret[:size]&.map do |val|
92
+ val[:content] = val.delete(:value)
93
+ Bib::Size::Value.new(**val)
94
+ end
95
+ ret[:size] = Bib::Size.new(value: value)
96
+ end
97
+
98
+ def title_hash_to_bib(ret)
99
+ # return unless ret[:title]
100
+
101
+ # ret[:title] = Relaton.array(ret[:title]).reduce(Bib::TitleCollection.new) do |m, t|
102
+ # m << (t.is_a?(Hash) ? Bib::Title.new(**t) : Bib::Title.new(content: t))
103
+ # end
104
+ ret[:title] &&= title_collection(ret[:title])
105
+ end
106
+
107
+ def language_hash_to_bib(ret)
108
+ return unless ret[:language]
109
+
110
+ ret[:language] = Relaton.array(ret[:language])
111
+ end
112
+
113
+ def script_hash_to_bib(ret)
114
+ return unless ret[:script]
115
+
116
+ ret[:script] = Relaton.array(ret[:script])
117
+ end
118
+
119
+ def abstract_hash_to_bib(ret)
120
+ ret[:abstract] &&= Relaton.array(ret[:abstract]).map do |a|
121
+ localized_marked_up_string a
122
+ end
123
+ end
124
+
125
+ def link_hash_to_bib(ret)
126
+ return unless ret[:link]
127
+
128
+ ret[:source] = Relaton.array(ret[:link]).map do |l|
129
+ Bib::Uri.new(**l)
130
+ end
131
+ end
132
+
133
+ def place_hash_to_bib(ret)
134
+ ret[:place] &&= Relaton.array(ret[:place]).map { |pl| create_place(pl) }
135
+ end
136
+
137
+ def create_place(place)
138
+ if place.is_a?(String)
139
+ Bib::Place.new(formatted_place: place)
140
+ else
141
+ place[:region] &&= create_region(place[:region])
142
+ place[:country] &&= create_region(place[:country])
143
+ Bib::Place.new(**place)
144
+ end
145
+ end
146
+
147
+ def create_region(region)
148
+ Relaton.array(region).map do |r|
149
+ r[:content] ||= r.delete(:name)
150
+ r[:iso] ||= r.delete(:code)
151
+ Bib::Place::RegionType.new(**r)
152
+ end
153
+ end
154
+
155
+ def accesslocation_hash_to_bib(ret)
156
+ return unless ret[:accesslocation]
157
+
158
+ ret[:accesslocation] = Relaton.array(ret[:accesslocation])
159
+ end
160
+
161
+ def dates_hash_to_bib(ret)
162
+ ret[:date] &&= Relaton.array(ret[:date]).map do |d|
163
+ # `at` is synonym of `on`, which is reserved word in YAML
164
+ d[:at] = d.delete(:value) if d[:value]
165
+ Bib::Date.new(**d)
166
+ end
167
+ end
168
+
169
+ def docid_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize
170
+ return unless ret[:docid]
171
+
172
+ ret[:docidentifier] = Relaton.array(ret[:docid]).map do |id|
173
+ id[:type] ||= id[:id].match(/^\w+(?=\s)/)&.to_s
174
+ id[:content] = id[:id]
175
+ create_docid(**id)
176
+ end
177
+ end
178
+
179
+ def create_docid(**args)
180
+ Bib::Docidentifier.new(**args)
181
+ end
182
+
183
+ def version_hash_to_bib(ret)
184
+ return unless ret[:version]
185
+
186
+ ret[:version] = Relaton.array(ret[:version]).map do |v|
187
+ v[:revision_date] &&= ::Date.parse(v[:revision_date])
188
+ Bib::Version.new(**v)
189
+ end
190
+ end
191
+
192
+ def biblionote_hash_to_bib(ret)
193
+ ret[:note] = Relaton.array(ret.delete(:biblionote)).map do |n|
194
+ n.is_a?(String) ? Bib::Note.new(content: n) : Bib::Note.new(**n)
195
+ end
196
+ end
197
+
198
+ def formattedref_hash_to_bib(ret)
199
+ ret[:formattedref] &&
200
+ ret[:formattedref] = formattedref(ret[:formattedref])
201
+ end
202
+
203
+ def docstatus_hash_to_bib(ret)
204
+ ret[:docstatus] && ret[:status]= Bib::Status.new(
205
+ stage: stage(ret[:docstatus][:stage]),
206
+ substage: stage(ret[:docstatus][:substage]),
207
+ iteration: ret[:docstatus][:iteration],
208
+ )
209
+ end
210
+
211
+ # @param stg [Hash]
212
+ # @return [Relaton::Bib::DocumentStatus::Stage]
213
+ def stage(stg)
214
+ return unless stg
215
+
216
+ args = stg.is_a?(String) ? { content: stg } : stg
217
+ args[:content] ||= args.delete(:value)
218
+ Bib::Status::Stage.new(**args)
219
+ end
220
+
221
+ 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|
224
+ if r.is_a? Hash
225
+ desc = Relaton.array(r[:description]).map { |d| localized_marked_up_string d }
226
+ Bib::Contributor::Role.new(type: r[:type], description: desc)
227
+ else
228
+ Bib::Contributor::Role.new(type: r)
229
+ end
230
+ end
231
+ c[:role] = roles
232
+ (c[:person] &&= create_person(c[:person])) ||
233
+ (c[:organization] &&= create_organization(c[:organization]))
234
+ Bib::Contributor.new(**c)
235
+ end
236
+ end
237
+
238
+ def edition_hash_to_bib(ret)
239
+ ret[:edition] &&= if ret[:edition].is_a?(Hash)
240
+ Bib::Edition.new(**ret[:edition])
241
+ else
242
+ Bib::Edition.new(content: ret[:edition])
243
+ end
244
+ end
245
+
246
+ def create_organization(org)
247
+ return nil if org.nil?
248
+
249
+ Bib::Organization.new(**org_hash_to_bib(org))
250
+ end
251
+
252
+ def org_hash_to_bib(org) # rubocop:disable Metrics/AbcSize
253
+ org[:identifier] = create_org_identifier(org[:identifier])
254
+ org[:subdivision] = create_org_subdivision(org[:subdivision])
255
+ org[:address] = address_hash_to_bib(org[:contact])
256
+ org[:phone] = phone_hash_to_bib(org[:contact])
257
+ org[:email] = email_hash_to_bib(org[:contact])
258
+ 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]
260
+ org[:name] = typed_localized_string(org[:name])
261
+ org[:abbreviation] &&= localizedstring(org[:abbreviation])
262
+ org
263
+ end
264
+
265
+ def create_org_identifier(identifier)
266
+ Relaton.array(identifier).map do |id|
267
+ Bib::Organization::Identifier.new(type: id[:type], content: id[:id])
268
+ end
269
+ end
270
+
271
+ def create_org_subdivision(subdivision)
272
+ Relaton.array(subdivision).map do |sub|
273
+ if sub.is_a? String
274
+ orgname = Bib::TypedLocalizedString.new(content: sub)
275
+ Bib::Subdivision.new(name: [orgname])
276
+ elsif sub.is_a?(Hash) && sub[:content]
277
+ sub[:name] = sub.delete(:content)
278
+ Bib::Subdivision.new(**org_hash_to_bib(sub))
279
+ end
280
+ end.compact
281
+ end
282
+
283
+ def typed_localized_string(typed_strs)
284
+ Relaton.array(typed_strs).map do |args|
285
+ if args.is_a? String
286
+ Bib::TypedLocalizedString.new(content: args)
287
+ elsif args.is_a? Hash
288
+ Bib::TypedLocalizedString.new(**args)
289
+ end
290
+ end
291
+ end
292
+
293
+ # def create_org_name(name)
294
+ # Relaton.array(name).map do |nm|
295
+ # if nm.is_a?(Hash)
296
+ # Bib::Organization::Name.new(**nm)
297
+ # else
298
+ # Bib::Organization::Name.new(content: nm)
299
+ # end
300
+ # end
301
+ # end
302
+
303
+ def create_person(person)
304
+ Bib::Person.new(
305
+ name: fullname_hash_to_bib(person),
306
+ credential: Relaton.array(person[:credential]),
307
+ affiliation: affiliation_hash_to_bib(person),
308
+ address: address_hash_to_bib(person[:contact]),
309
+ phone: phone_hash_to_bib(person[:contact]),
310
+ email: email_hash_to_bib(person[:contact]),
311
+ uri: uri_hash_to_bib(person[:contact]),
312
+ identifier: person_identifiers_hash_to_bib(person),
313
+ )
314
+ end
315
+
316
+ def fullname_hash_to_bib(person) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
317
+ n = person[:name]
318
+ fname = given_hash_to_bib n[:given] || n # `n` is for backward compatibility
319
+ Bib::FullName.new(
320
+ abbreviation: localizedstring(n[:abbreviation]),
321
+ forename: fname,
322
+ 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) },
325
+ surname: localizedstring(n[:surname]),
326
+ completename: localizedstring(n[:completename]),
327
+ )
328
+ end
329
+
330
+ def given_hash_to_bib(given)
331
+ return unless given
332
+
333
+ Relaton.array(given[:forename])&.map { |f| forename_hash_to_bib(f) }
334
+ end
335
+
336
+ def forename_hash_to_bib(fname)
337
+ case fname
338
+ when Hash
339
+ lang_scrip_array_to_string fname
340
+ FullNameType::Forename.new(**fname)
341
+ when String then FullNameType::Forename.new(content: fname)
342
+ end
343
+ end
344
+
345
+ def person_identifiers_hash_to_bib(person)
346
+ Relaton.array(person[:identifier])&.map do |a|
347
+ Bib::Person::Identifier.new(type: a[:type], content: a[:id])
348
+ end
349
+ end
350
+
351
+ def affiliation_hash_to_bib(person) # rubocop:disable Metrics/AbcSize
352
+ return [] unless person[:affiliation]
353
+
354
+ Relaton.array(person[:affiliation]).map do |a|
355
+ a[:description] = Relaton.array(a[:description]).map do |d|
356
+ localized_marked_up_string d
357
+ end
358
+ Bib::Affiliation.new(
359
+ organization: create_organization(a[:organization]),
360
+ description: a[:description], name: localizedstring(a[:name])
361
+ )
362
+ end
363
+ end
364
+
365
+ def address_hash_to_bib(contact)
366
+ Relaton.array(contact).reduce([]) do |a, c|
367
+ next a unless c[:address]
368
+
369
+ a << create_address(c[:address])
370
+ end
371
+ end
372
+
373
+ def phone_hash_to_bib(contact)
374
+ Relaton.array(contact).reduce([]) do |a, c|
375
+ next a unless c[:phone]
376
+
377
+ c[:type] ||= "work"
378
+ a << Bib::Phone.new(type: c[:type], content: c[:phone])
379
+ end
380
+ end
381
+
382
+ def email_hash_to_bib(contact)
383
+ Relaton.array(contact).reduce([]) do |a, c|
384
+ next a unless c[:email]
385
+
386
+ a << c[:email]
387
+ end
388
+ end
389
+
390
+ def uri_hash_to_bib(contact)
391
+ Relaton.array(contact).reduce([]) do |a, c|
392
+ next a unless c[:uri] || c[:url]
393
+
394
+ a << Bib::Uri.new(content: c[:uri] || c[:url])
395
+ end
396
+ end
397
+
398
+ # def contacts_hash_to_bib(entity) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity
399
+ # return [] unless entity[:contact]
400
+
401
+ # Relaton.array(entity[:contact]).map do |a|
402
+ # type, value = a.reject { |k, _| k == :type }.flatten
403
+ # case type
404
+ # when :street, :city, :state, :country, :postcode # it's for old version compatibility, should be removed in the future
405
+ # a[:street] = Relaton.array(a[:street])
406
+ # Bib::Address.new(**a)
407
+ # when :address then create_address(a[:address])
408
+ # when :phone, :email, :uri
409
+ # Bib::Contact.new(type: type.to_s, value: value, subtype: a[:type])
410
+ # else # it's for old version compatibility, should be removed in the future
411
+ # Bib::Contact.new(**a)
412
+ # end
413
+ # end
414
+ # end
415
+
416
+ def create_address(adr)
417
+ if adr.is_a?(Hash)
418
+ adr[:street] = Relaton.array(adr[:street])
419
+ Bib::Address.new(**adr)
420
+ else
421
+ Bib::Address.new(formatted_address: adr)
422
+ end
423
+ end
424
+
425
+ # @param ret [Hash]
426
+ 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|
429
+ create_contribution_info(o)
430
+ end
431
+ Bib::Copyright.new(**c)
432
+ end
433
+ end
434
+
435
+ def create_contribution_info(contrib)
436
+ if contrib[:name].is_a?(Hash) && (contrib[:name].keys & %i[prefix forename addition surname completename]).any?
437
+ Bib::ContributionInfo.new person: create_person(contrib)
438
+ else
439
+ Bib::ContributionInfo.new organization: create_organization(contrib)
440
+ end
441
+ end
442
+
443
+ # @param ret [Hash]
444
+ def relations_hash_to_bib(ret) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
445
+ return unless ret[:relation]
446
+
447
+ ret[:relation] &&= Relaton.array(ret[:relation]).map do |rel|
448
+ rel[:description] = LocalizedMarkedUpString.new(**rel[:description]) if rel[:description]
449
+ relation_bibitem_hash_to_bib(rel)
450
+ relation_locality_hash_to_bib(rel)
451
+ relation_locality_stack_hash_to_bib(rel)
452
+ relaton_source_locality_stack_hash_to_bib(rel)
453
+ relation_source_locality_hash_to_bib(rel)
454
+ create_relation rel
455
+ end
456
+ end
457
+
458
+ def create_relation(rel)
459
+ Bib::Relation.new(**rel)
460
+ end
461
+
462
+ # @param rel [Hash] relation
463
+ def relation_bibitem_hash_to_bib(rel)
464
+ if rel[:bibitem]
465
+ rel[:bibitem] = bib_item hash_to_bib(rel[:bibitem])
466
+ else
467
+ Util.warn "Bibitem missing: `#(rel)`"
468
+ rel[:bibitem] = nil
469
+ end
470
+ end
471
+
472
+ # @param item_hash [Hash]
473
+ # @return [Relaton::Bib::Item]
474
+ def bib_item(item_hash)
475
+ ItemData.new(**item_hash)
476
+ end
477
+
478
+ # @param rel [Hash] relation
479
+ # @return [Relaton::Bib::LocalityStack]
480
+ def relation_locality_hash_to_bib(rel)
481
+ return unless rel[:locality]&.any?
482
+
483
+ rel[:locality] = Relaton.array(rel[:locality]).map do |bl|
484
+ Bib::Locality.new(**bl)
485
+ end
486
+ end
487
+
488
+ def relation_locality_stack_hash_to_bib(rel)
489
+ return unless rel[:locality_stack]&.any?
490
+
491
+ rel[:locality_stack] = Relaton.array(rel[:locality_stack]).map do |ls|
492
+ Bib::LocalityStack.new locality: relation_locality_hash_to_bib(ls)
493
+ end
494
+ end
495
+
496
+ # def locality_locality_stack(lls)
497
+ # if lls[:locality_stack]
498
+ # RelatonBib.array(lls[:locality_stack]).map do |lc|
499
+ # l = lc[:locality] || lc
500
+ # Locality.new(l[:type], l[:reference_from], l[:reference_to])
501
+ # end
502
+ # else
503
+ # [Locality.new(lls[:type], lls[:reference_from], lls[:reference_to])]
504
+ # end
505
+ # end
506
+
507
+ # @param rel [Hash] relation
508
+ def relation_source_locality_hash_to_bib(rel)
509
+ rel[:source_locality] = Relaton.array(rel[:source_locality]).map do |loc|
510
+ Bib::Locality.new(**loc)
511
+ end
512
+ end
513
+
514
+ 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]
518
+ end
519
+
520
+ case rel[:source_locality]
521
+ when Hash then rel[:source_locality].delete(:source_locality_stack)
522
+ when Array then rel[:source_locality].delete_if { |loc| loc[:source_locality_stack] }
523
+ end
524
+
525
+ rel[:source_locality_stack] = sls.map do |loc|
526
+ SourceLocalityStack.new source_locality: relation_source_locality_hash_to_bib(source_locality: loc)
527
+ end
528
+ end
529
+
530
+ # @param ret [Hash]
531
+ def series_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
532
+ ret[:series] &&= Relaton.array(ret[:series]).map do |s|
533
+ s[:formattedref] && s[:formattedref] = formattedref(s[:formattedref])
534
+ s[:title] &&= title_collection(s[:title])
535
+ s[:place] &&= create_place(s[:place])
536
+ s[:abbreviation] &&= localizedstring(s[:abbreviation])
537
+ s[:from] &&= ::Date.parse(s[:from])
538
+ s[:to] &&= ::Date.parse(s[:to])
539
+ Bib::Series.new(**s)
540
+ end
541
+ end
542
+
543
+ #
544
+ # @param title [Hash, Strinbg, Array<Hash, String>]
545
+ #
546
+ # @return [Relaton::Bib::TitleCollection]
547
+ #
548
+ def title_collection(title)
549
+ Relaton.array(title).map do |t|
550
+ if t.is_a?(Hash)
551
+ lang_scrip_array_to_string t
552
+ Bib::Title.new(**t)
553
+ elsif t.is_a?(String)
554
+ Bib::Title.new(content: t)
555
+ end
556
+ end
557
+ end
558
+
559
+ # @param ret [Hash]
560
+ def medium_hash_to_bib(ret)
561
+ ret[:medium] = Bib::Medium.new(**ret[:medium]) if ret[:medium]
562
+ end
563
+
564
+ # @param ret [Hash]
565
+ def classification_hash_to_bib(ret)
566
+ if ret[:classification]
567
+ ret[:classification] = Relaton.array(ret[:classification]).map do |cls|
568
+ cls[:content] ||= cls.delete(:value)
569
+ Docidentifier.new(**cls)
570
+ end
571
+ end
572
+ end
573
+
574
+ # @param ret [Hash]
575
+ def validity_hash_to_bib(ret)
576
+ return unless ret[:validity]
577
+
578
+ b = parse_validity_time(ret[:validity], :begins)
579
+ e = parse_validity_time(ret[:validity], :ends)
580
+ r = parse_validity_time(ret[:validity], :revision)
581
+ ret[:validity] = Bib::Validity.new(begins: b, ends: e, revision: r)
582
+ end
583
+
584
+ def parse_validity_time(val, period)
585
+ t = val[period]&.to_s
586
+ return unless t
587
+
588
+ p = period == :ends ? -1 : 1
589
+ case t
590
+ when /^\d{4}$/
591
+ ::Date.new(t.to_i, p, p).to_time
592
+ 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
595
+ end
596
+ end
597
+
598
+ # @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
601
+ return unless eg
602
+
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 }
609
+ end
610
+
611
+ def create_workgroup(wrkg)
612
+ wrkg[:content] ||= wrkg.delete(:name)
613
+ Bib::WorkGroup.new(**wrkg)
614
+ end
615
+
616
+ # @param ret [Hash]
617
+ def ics_hash_to_bib(ret)
618
+ ics = ret.dig(:ext, :ics) || ret[:ics] # @todo remove ret[:ics] in the future
619
+ return unless ics
620
+
621
+ ret[:ext][:ics] = Relaton.array(ics).map { |item| Bib::ICS.new(**item) }
622
+ end
623
+
624
+ # @param ret [Hash]
625
+ def structuredidentifier_hash_to_bib(ret)
626
+ struct_id = ret.dig(:ext, :structuredidentifier) || ret[:structuredidentifier] # @todo remove ret[:structuredidentifier] in the future
627
+ return unless struct_id
628
+
629
+ sids = Relaton.array(struct_id).map do |si|
630
+ si[:agency] = Relaton.array si[:agency]
631
+ si[:klass] = si.delete(:class)
632
+ Bib::StructuredIdentifier.new(**si)
633
+ end
634
+ ret[:ext][:structuredidentifier] = sids
635
+ end
636
+
637
+ # @param ogj [Hash, Array, String]
638
+ # @return [Hash, Array, String]
639
+ def symbolize(obj)
640
+ case obj
641
+ when Hash
642
+ obj.reduce({}) do |memo, (k, v)|
643
+ memo[k.to_sym] = symbolize(v)
644
+ memo
645
+ end
646
+ when Array then obj.reduce([]) { |memo, v| memo << symbolize(v) }
647
+ else obj
648
+ end
649
+ end
650
+
651
+ # @param lst [Hash, Array<Relaton::Bib::LocalizedString>, String]
652
+ # @return [Relaton::Bib::LocalizedString]
653
+ def localizedstring(lst)
654
+ return unless lst
655
+
656
+ if lst.is_a?(Hash)
657
+ lang_scrip_array_to_string lst
658
+ Bib::LocalizedString.new(**lst)
659
+ else Bib::LocalizedString.new(content: lst)
660
+ end
661
+ end
662
+
663
+ def lang_scrip_array_to_string(lst)
664
+ lst[:language] = lst[:language][0] if lst[:language].is_a?(Array)
665
+ lst[:script] = lst[:script][0] if lst[:script].is_a?(Array)
666
+ end
667
+
668
+ def localized_marked_up_string(lst)
669
+ return unless lst
670
+
671
+ if lst.is_a?(Hash)
672
+ lang_scrip_array_to_string lst
673
+ LocalizedMarkedUpString.new(**lst)
674
+ else LocalizedMarkedUpString.new(content: lst)
675
+ end
676
+ end
677
+
678
+ # @param frf [Hash, String]
679
+ # @return [Relaton::Bib::Formattedref]
680
+ def formattedref(frf)
681
+ if frf.is_a?(Hash)
682
+ # Relaton::Bib::Formattedref.new(**frf)
683
+ frf[:content]
684
+ else
685
+ # Relaton::Bib::Formattedref.new(content: frf)
686
+ frf
687
+ end
688
+ end
689
+
690
+ def doctype_hash_to_bib(ret)
691
+ doctype = ret.dig(:ext, :doctype) || ret[:doctype] # @todo remove ret[:doctype] in the future
692
+ return unless doctype
693
+
694
+ ret[:ext][:doctype] = create_doctype(doctype_args(doctype))
695
+ end
696
+
697
+ def doctype_args(args)
698
+ if args.is_a?(String)
699
+ { content: args }
700
+ else
701
+ args[:content] = args.delete(:type)
702
+ args
703
+ end
704
+ end
705
+
706
+ def create_doctype(args)
707
+ Bib::Doctype.new(**args)
708
+ end
709
+ end
710
+ end
711
+ end