relaton-bib 1.2.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ubuntu.yml +1 -0
  3. data/.rubocop.yml +2 -2
  4. data/README.adoc +60 -18
  5. data/grammars/isodoc.rng +130 -21
  6. data/grammars/reqt.rng +2 -8
  7. data/lib/relaton_bib.rb +15 -15
  8. data/lib/relaton_bib/bib_item_locality.rb +13 -1
  9. data/lib/relaton_bib/biblio_note.rb +11 -0
  10. data/lib/relaton_bib/biblio_version.rb +12 -0
  11. data/lib/relaton_bib/bibliographic_date.rb +13 -0
  12. data/lib/relaton_bib/bibliographic_item.rb +93 -25
  13. data/lib/relaton_bib/classification.rb +11 -0
  14. data/lib/relaton_bib/contribution_info.rb +27 -1
  15. data/lib/relaton_bib/contributor.rb +55 -1
  16. data/lib/relaton_bib/copyright_association.rb +14 -1
  17. data/lib/relaton_bib/document_identifier.rb +49 -9
  18. data/lib/relaton_bib/document_relation.rb +14 -4
  19. data/lib/relaton_bib/document_relation_collection.rb +12 -0
  20. data/lib/relaton_bib/document_status.rb +10 -0
  21. data/lib/relaton_bib/editorial_group.rb +14 -0
  22. data/lib/relaton_bib/formatted_ref.rb +7 -0
  23. data/lib/relaton_bib/formatted_string.rb +11 -0
  24. data/lib/relaton_bib/hash_converter.rb +55 -36
  25. data/lib/relaton_bib/ics.rb +11 -0
  26. data/lib/relaton_bib/localized_string.rb +23 -6
  27. data/lib/relaton_bib/medium.rb +11 -0
  28. data/lib/relaton_bib/organization.rb +27 -7
  29. data/lib/relaton_bib/person.rb +54 -7
  30. data/lib/relaton_bib/place.rb +13 -1
  31. data/lib/relaton_bib/series.rb +25 -4
  32. data/lib/relaton_bib/structured_identifier.rb +30 -0
  33. data/lib/relaton_bib/technical_committee.rb +11 -0
  34. data/lib/relaton_bib/typed_title_string.rb +13 -7
  35. data/lib/relaton_bib/typed_uri.rb +11 -0
  36. data/lib/relaton_bib/validity.rb +11 -0
  37. data/lib/relaton_bib/version.rb +1 -1
  38. data/lib/relaton_bib/workgroup.rb +10 -0
  39. data/lib/relaton_bib/xml_parser.rb +54 -39
  40. metadata +5 -5
@@ -33,7 +33,7 @@ module RelatonBib
33
33
  o.is_a?(Hash) ? ContributionInfo.new(entity: Organization.new(o)) : o
34
34
  end
35
35
 
36
- @from = Date.strptime(from.to_s, "%Y") if from.to_s =~ /\d{4}/
36
+ @from = Date.strptime(from.to_s, "%Y") if from.to_s.match? /\d{4}/
37
37
  @to = Date.strptime(to.to_s, "%Y") unless to.to_s.empty?
38
38
  @scope = scope
39
39
  end
@@ -60,5 +60,18 @@ module RelatonBib
60
60
  hash["scope"] = scope if scope
61
61
  hash
62
62
  end
63
+
64
+ # @param prefix [String]
65
+ # @param count [Iteger] number of copyright elements
66
+ # @return [String]
67
+ def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
68
+ pref = prefix.empty? ? "copyright" : prefix + ".copyright"
69
+ out = count > 1 ? "#{pref}::\n" : ""
70
+ owner.each { |ow| out += ow.to_asciibib "#{pref}.owner", owner.size }
71
+ out += "#{pref}.from:: #{from.year}\n" if from
72
+ out += "#{pref}.to:: #{to.year}\n" if to
73
+ out += "#{pref}.scope:: #{scope}\n" if scope
74
+ out
75
+ end
63
76
  end
64
77
  end
@@ -5,34 +5,41 @@ module RelatonBib
5
5
  attr_reader :id
6
6
 
7
7
  # @return [String, NilClass]
8
- attr_reader :type
8
+ attr_reader :type, :scope
9
9
 
10
10
  # @param id [String]
11
11
  # @param type [String, NilClass]
12
- def initialize(id:, type: nil)
13
- @id = id
14
- @type = type
12
+ # @param scoope [String, NilClass]
13
+ def initialize(id:, type: nil, scope: nil)
14
+ @id = id
15
+ @type = type
16
+ @scope = scope
15
17
  end
16
18
 
17
19
  # in docid manipulations, assume ISO as the default: id-part:year
18
20
  def remove_part
19
21
  case @type
20
22
  when "Chinese Standard" then @id.sub!(/\.\d+/, "")
21
- else
22
- @id.sub!(/-\d+/, "")
23
+ when "ISO", "IEC" then @id.sub!(/-[^:]+/, "")
24
+ when "URN" then remove_urn_part
23
25
  end
24
26
  end
25
27
 
26
28
  def remove_date
27
29
  case @type
28
30
  when "Chinese Standard" then @id.sub!(/-[12]\d\d\d/, "")
29
- else
30
- @id.sub!(/:[12]\d\d\d/, "")
31
+ when "ISO", "IEC" then @id.sub!(/:[12]\d\d\d/, "")
32
+ when "URN"
33
+ @id.sub!(/^(urn:iec:std:[^:]+:[^:]+:)[^:]*/, '\1')
31
34
  end
32
35
  end
33
36
 
34
37
  def all_parts
35
- @id += " (all parts)"
38
+ if type == "URN"
39
+ @id.sub!(%r{^(urn:iec:std(?::[^:]*){4}).*}, '\1:ser')
40
+ else
41
+ @id += " (all parts)"
42
+ end
36
43
  end
37
44
 
38
45
  #
@@ -43,13 +50,46 @@ module RelatonBib
43
50
  def to_xml(builder)
44
51
  element = builder.docidentifier id
45
52
  element[:type] = type if type
53
+ element[:scope] = scope if scope
46
54
  end
47
55
 
48
56
  # @return [Hash]
49
57
  def to_hash
50
58
  hash = { "id" => id }
51
59
  hash["type"] = type if type
60
+ hash["scope"] = scope if scope
52
61
  hash
53
62
  end
63
+
64
+ # @param prefix [String]
65
+ # @param count [Integer] number of docids
66
+ # @return [String]
67
+ def to_asciibib(prefix = "", count = 1)
68
+ pref = prefix.empty? ? prefix : prefix + "."
69
+ out = count > 1 ? "#{pref}docid::\n" : ""
70
+ out += "#{pref}docid.type:: #{type}\n" if type
71
+ out += "#{pref}docid.scope:: #{scope}\n" if scope
72
+ out += "#{pref}docid.id:: #{id}\n"
73
+ out
74
+ end
75
+
76
+ private
77
+
78
+ def remove_urn_part # rubocop:disable Metrics/MethodLength
79
+ @id.sub!(%r{^
80
+ (urn:iso:std:[^:]+ # ISO prefix and originator
81
+ (?::(?:data|guide|isp|iwa|pas|r|tr|ts|tta)) # type
82
+ ?:\d+) # docnumber
83
+ (?::-[^:]+)? # partnumber
84
+ (?::(draft|cancelled|stage-[^:]+))? # status
85
+ (?::ed-\d+)?(?::v[^:]+)? # edition and version
86
+ (?::\w{2}(?:,\w{2})*)? # langauge
87
+ }x, '\1') # remove partnumber, status, version, and language
88
+ @id.sub!(%r{^
89
+ (urn:iec:std:[^:]+ # IEC prefix and originator
90
+ :\d+) # docnumber
91
+ (?:-[^:]+)? # partnumber
92
+ }x, '\1') # remove partnumber
93
+ end
54
94
  end
55
95
  end
@@ -48,11 +48,11 @@ module RelatonBib
48
48
  unless self.class::TYPES.include? type
49
49
  warn "[relaton-bib] WARNING: invalid relation type: #{type}"
50
50
  end
51
- @type = type
52
- @description = description
53
- @locality = locality
51
+ @type = type
52
+ @description = description
53
+ @locality = locality
54
54
  @source_locality = source_locality
55
- @bibitem = bibitem
55
+ @bibitem = bibitem
56
56
  end
57
57
 
58
58
  # rubocop:disable Metrics/AbcSize
@@ -80,5 +80,15 @@ module RelatonBib
80
80
  end
81
81
  hash
82
82
  end
83
+
84
+ # @param prefix [String]
85
+ # @return [String]
86
+ def to_asciibib(prefix = "")
87
+ pref = prefix.empty? ? prefix : prefix + "."
88
+ out = "#{prefix}.type:: #{type}\n"
89
+ out += description.to_asciibib "#{pref}desctiption" if description
90
+ out += bibitem.to_asciibib "#{pref}bibitem" if bibitem
91
+ out
92
+ end
83
93
  end
84
94
  end
@@ -30,5 +30,17 @@ module RelatonBib
30
30
  def replaces
31
31
  DocRelationCollection.new(@array.select { |r| r.type == "replace" })
32
32
  end
33
+
34
+ # @param prefix [String]
35
+ # @return [String]
36
+ def to_asciibib(prefix = "")
37
+ pref = prefix.empty? ? "relation" : prefix + ".relation"
38
+ out = ""
39
+ @array.each do |r|
40
+ out += size > 1 ? "#{pref}::\n" : ""
41
+ out += r.to_asciibib pref
42
+ end
43
+ out
44
+ end
33
45
  end
34
46
  end
@@ -41,6 +41,16 @@ module RelatonBib
41
41
  hash
42
42
  end
43
43
 
44
+ # @param prefix [String]
45
+ # @return [String]
46
+ def to_asciibib(prefix = "")
47
+ pref = prefix.empty? ? prefix : prefix + "."
48
+ out = "#{pref}docstatus.stage:: #{stage.value}\n"
49
+ out += "#{pref}docstatus.substage:: #{substage.value}\n" if substage
50
+ out += "#{pref}docstatus.iteration:: #{iteration}\n" if iteration
51
+ out
52
+ end
53
+
44
54
  private
45
55
 
46
56
  # @param stg [RelatonBib::DocumentStatus::Stage, Hash, String, NilClass]
@@ -23,5 +23,19 @@ module RelatonBib
23
23
  def to_hash
24
24
  single_element_array technical_committee
25
25
  end
26
+
27
+ # @param prefix [String]
28
+ # @return [String]
29
+ def to_asciibib(prefix = "")
30
+ pref = prefix.empty? ? "editorialgroup" : prefix + ".editorialgroup"
31
+ technical_committee.map do |tc|
32
+ tc.to_asciibib pref, technical_committee.size
33
+ end.join
34
+ end
35
+
36
+ # @return [true]
37
+ def presence?
38
+ true
39
+ end
26
40
  end
27
41
  end
@@ -6,5 +6,12 @@ module RelatonBib
6
6
  def to_xml(builder)
7
7
  builder.formattedref { super }
8
8
  end
9
+
10
+ # @param prefix [String]
11
+ # @return [String]
12
+ def to_asciibib(prefix = "")
13
+ pref = prefix.empty? ? "formattedref" : prefix + ".formattedref"
14
+ super pref
15
+ end
9
16
  end
10
17
  end
@@ -40,5 +40,16 @@ module RelatonBib
40
40
  hash["format"] = format
41
41
  hash
42
42
  end
43
+
44
+ # @param prefix [String]
45
+ # @param count [Integer] number of elements
46
+ # @return [String]
47
+ def to_asciibib(prefix = "", count = 1)
48
+ pref = prefix.empty? ? prefix : prefix + "."
49
+ # out = count > 1 ? "#{prefix}::\n" : ""
50
+ out = super
51
+ out += "#{pref}format:: #{format}\n" if format
52
+ out
53
+ end
43
54
  end
44
55
  end
@@ -4,7 +4,7 @@ module RelatonBib
4
4
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
5
5
 
6
6
  # @param args [Hash]
7
- # @param neated [TrueClas, FalseClass] default true
7
+ # @param neated [TrueClas, FalseClass] default false
8
8
  # @return [Hash]
9
9
  def hash_to_bib(args, nested = false)
10
10
  return nil unless args.is_a?(Hash)
@@ -62,8 +62,6 @@ module RelatonBib
62
62
  if t.is_a?(Hash) then m << t
63
63
  else
64
64
  m + TypedTitleString.from_string(t)
65
- # { content: t, language: "en", script: "Latn", format: "text/plain",
66
- # type: "main" }
67
65
  end
68
66
  end
69
67
  end
@@ -127,7 +125,8 @@ module RelatonBib
127
125
  ret[:docid] = array(ret[:docid])
128
126
  ret[:docid]&.each_with_index do |id, i|
129
127
  type = id[:type] || id[:id].match(/^\w+/)&.to_s
130
- ret[:docid][i] = DocumentIdentifier.new(id: id[:id], type: type)
128
+ ret[:docid][i] = DocumentIdentifier.new(id: id[:id], type: type,
129
+ scope: id[:scope])
131
130
  end
132
131
  end
133
132
 
@@ -140,31 +139,33 @@ module RelatonBib
140
139
  )
141
140
  end
142
141
 
143
- def biblionote_hash_to_bib(ret)
142
+ def biblionote_hash_to_bib(ret) # rubocop:disable Metrics/MethodLength
144
143
  return unless ret[:biblionote]
145
144
 
146
145
  ret[:biblionote] = array(ret[:biblionote])
147
146
  (ret[:biblionote])&.each_with_index do |n, i|
148
147
  ret[:biblionote][i] = if n.is_a?(String)
149
- BiblioNote.new content: n
150
- else
151
- BiblioNote.new(
152
- content: n[:content], type: n[:type], language: n[:language],
153
- script: n[:script], format: n[:format]
154
- )
155
- end
148
+ BiblioNote.new content: n
149
+ else
150
+ BiblioNote.new(
151
+ content: n[:content], type: n[:type],
152
+ language: n[:language], script: n[:script],
153
+ format: n[:format]
154
+ )
155
+ end
156
156
  end
157
157
  end
158
158
 
159
159
  def formattedref_hash_to_bib(ret)
160
- ret[:formattedref] && ret[:formattedref] = formattedref(ret[:formattedref])
160
+ ret[:formattedref] &&
161
+ ret[:formattedref] = formattedref(ret[:formattedref])
161
162
  end
162
163
 
163
164
  def docstatus_hash_to_bib(ret)
164
165
  ret[:docstatus] && ret[:docstatus] = DocumentStatus.new(
165
166
  stage: stage(ret[:docstatus][:stage]),
166
167
  substage: stage(ret[:docstatus][:substage]),
167
- iteration: ret[:docstatus][:iteration],
168
+ iteration: ret[:docstatus][:iteration]
168
169
  )
169
170
  end
170
171
 
@@ -177,7 +178,7 @@ module RelatonBib
177
178
  DocumentStatus::Stage.new(**args)
178
179
  end
179
180
 
180
- def contributors_hash_to_bib(ret)
181
+ def contributors_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
181
182
  return unless ret[:contributor]
182
183
 
183
184
  ret[:contributor] = array(ret[:contributor])
@@ -216,11 +217,11 @@ module RelatonBib
216
217
  name: fullname_hash_to_bib(person),
217
218
  affiliation: affiliation_hash_to_bib(person),
218
219
  contact: contacts_hash_to_bib(person),
219
- identifier: person_identifiers_hash_to_bib(person),
220
+ identifier: person_identifiers_hash_to_bib(person)
220
221
  )
221
222
  end
222
223
 
223
- def fullname_hash_to_bib(person)
224
+ def fullname_hash_to_bib(person) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
224
225
  n = person[:name]
225
226
  FullName.new(
226
227
  forename: array(n[:forename])&.map { |f| localname(f, person) },
@@ -228,7 +229,7 @@ module RelatonBib
228
229
  addition: array(n[:addition])&.map { |f| localname(f, person) },
229
230
  prefix: array(n[:prefix])&.map { |f| localname(f, person) },
230
231
  surname: localname(n[:surname], person),
231
- completename: localname(n[:completename], person),
232
+ completename: localname(n[:completename], person)
232
233
  )
233
234
  end
234
235
 
@@ -238,7 +239,7 @@ module RelatonBib
238
239
  end
239
240
  end
240
241
 
241
- def affiliation_hash_to_bib(person)
242
+ def affiliation_hash_to_bib(person) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
242
243
  return [] unless person[:affiliation]
243
244
 
244
245
  array(person[:affiliation]).map do |a|
@@ -252,12 +253,12 @@ module RelatonBib
252
253
  end
253
254
  Affiliation.new(
254
255
  organization: Organization.new(org_hash_to_bib(a[:organization])),
255
- description: a[:description],
256
+ description: a[:description]
256
257
  )
257
258
  end
258
259
  end
259
260
 
260
- def contacts_hash_to_bib(person)
261
+ def contacts_hash_to_bib(person) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
261
262
  return [] unless person[:contact]
262
263
 
263
264
  array(person[:contact]).map do |a|
@@ -315,42 +316,48 @@ module RelatonBib
315
316
 
316
317
  # @param rel [Hash] relation
317
318
  # @return [RelatonBib::LocalityStack]
318
- def relation_locality_hash_to_bib(rel)
319
+ def relation_locality_hash_to_bib(rel) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
319
320
  rel[:locality] = array(rel[:locality])&.map do |bl|
320
321
  ls = if bl[:locality_stack]
321
322
  array(bl[:locality_stack]).map do |l|
322
323
  Locality.new(l[:type], l[:reference_from], l[:reference_to])
323
324
  end
324
325
  else
325
- [Locality.new(bl[:type], bl[:reference_from], bl[:reference_to])]
326
+ l = Locality.new(bl[:type], bl[:reference_from],
327
+ bl[:reference_to])
328
+ [l]
326
329
  end
327
330
  LocalityStack.new ls
328
331
  end
329
332
  end
330
333
 
331
334
  # @param rel [Hash] relation
332
- def relation_source_locality_hash_to_bib(rel)
335
+ def relation_source_locality_hash_to_bib(rel) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
333
336
  rel[:source_locality] = array(rel[:source_locality])&.map do |sl|
334
337
  sls = if sl[:source_locality_stack]
335
338
  array(sl[:source_locality_stack]).map do |l|
336
- SourceLocality.new(l[:type], l[:reference_from], l[:reference_to])
339
+ SourceLocality.new(l[:type], l[:reference_from],
340
+ l[:reference_to])
337
341
  end
338
342
  else
339
- [SourceLocality.new(sl[:type], sl[:reference_from], sl[:reference_to])]
343
+ l = SourceLocality.new(sl[:type], sl[:reference_from],
344
+ sl[:reference_to])
345
+ [l]
340
346
  end
341
347
  SourceLocalityStack.new sls
342
348
  end
343
349
  end
344
350
 
345
351
  # @param ret [Hash]
346
- def series_hash_to_bib(ret)
352
+ def series_hash_to_bib(ret) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
347
353
  ret[:series] = array(ret[:series])&.map do |s|
348
354
  s[:formattedref] && s[:formattedref] = formattedref(s[:formattedref])
349
355
  if s[:title]
350
356
  s[:title] = { content: s[:title] } unless s[:title].is_a?(Hash)
351
357
  s[:title] = typed_title_strig(s[:title])
352
358
  end
353
- s[:abbreviation] && s[:abbreviation] = localizedstring(s[:abbreviation])
359
+ s[:abbreviation] &&
360
+ s[:abbreviation] = localizedstring(s[:abbreviation])
354
361
  Series.new(s)
355
362
  end
356
363
  end
@@ -375,18 +382,29 @@ module RelatonBib
375
382
  end
376
383
  end
377
384
 
378
- # rubocop:disable Metrics/AbcSize
379
-
380
385
  # @param ret [Hash]
381
386
  def validity_hash_to_bib(ret)
382
387
  return unless ret[:validity]
383
388
 
384
- ret[:validity][:begins] && b = Time.parse(ret[:validity][:begins].to_s)
385
- ret[:validity][:ends] && e = Time.parse(ret[:validity][:ends].to_s)
386
- ret[:validity][:revision] && r = Time.parse(ret[:validity][:revision].to_s)
389
+ b = parse_validity_time(ret[:validity], :begins)
390
+ e = parse_validity_time(ret[:validity], :ends)
391
+ r = parse_validity_time(ret[:validity], :revision)
387
392
  ret[:validity] = Validity.new(begins: b, ends: e, revision: r)
388
393
  end
389
- # rubocop:enable Metrics/AbcSize
394
+
395
+ def parse_validity_time(val, period)
396
+ t = val[period]&.to_s
397
+ return unless t
398
+
399
+ p = period == :ends ? -1 : 1
400
+ case t
401
+ when /^\d{4}$/
402
+ Date.new(t.to_i, p, p).to_time
403
+ when /^(?<year>\d{4})-(?<month>\d{1,2})$/
404
+ Date.new($~[:year].to_i, $~[:month].to_i, p).to_time
405
+ else Time.parse t
406
+ end
407
+ end
390
408
 
391
409
  # @param ret [Hash]
392
410
  def editorialgroup_hash_to_bib(ret)
@@ -443,7 +461,7 @@ module RelatonBib
443
461
  # @param name [Hash, String, NilClass]
444
462
  # @param person [Hash]
445
463
  # @return [RelatonBib::LocalizedString]
446
- def localname(name, person)
464
+ def localname(name, person) # rubocop:disable Metrics/CyclomaticComplexity
447
465
  return nil if name.nil?
448
466
 
449
467
  lang = name[:language] if name.is_a?(Hash)
@@ -458,7 +476,8 @@ module RelatonBib
458
476
  # @return [RelatonBib::LocalizedString]
459
477
  def localizedstring(lst)
460
478
  if lst.is_a?(Hash)
461
- RelatonBib::LocalizedString.new(lst[:content], lst[:language], lst[:script])
479
+ RelatonBib::LocalizedString.new(lst[:content], lst[:language],
480
+ lst[:script])
462
481
  else
463
482
  RelatonBib::LocalizedString.new(lst)
464
483
  end