relaton-bib 1.3.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,31 @@
1
1
  module RelatonBib
2
+ class BiblioNoteCollection
3
+ extend Forwardable
4
+
5
+ def_delegators :@array, :[], :first, :last, :empty?, :any?, :size,
6
+ :each, :map, :detect, :length
7
+
8
+ def initialize(notes)
9
+ @array = notes
10
+ end
11
+
12
+ # @param bibnote [RelatonBib::BiblioNote]
13
+ # @return [self]
14
+ def <<(bibnote)
15
+ @array << bibnote
16
+ self
17
+ end
18
+
19
+ # @param opts [Hash]
20
+ # @option opts [Nokogiri::XML::Builder] XML builder
21
+ # @option opts [String] :lang language
22
+ def to_xml(**opts)
23
+ bnc = @array.select { |bn| bn.language&.include? opts[:lang] }
24
+ bnc = @array unless bnc.any?
25
+ bnc.each { |bn| bn.to_xml opts[:builder] }
26
+ end
27
+ end
28
+
2
29
  class BiblioNote < FormattedString
3
30
  # @return [String, NilClass]
4
31
  attr_reader :type
@@ -6,7 +6,8 @@ module RelatonBib
6
6
  # Bibliographic date.
7
7
  class BibliographicDate
8
8
  TYPES = %w[published accessed created implemented obsoleted confirmed
9
- updated issued transmitted copied unchanged circulated adapted].freeze
9
+ updated issued transmitted copied unchanged circulated adapted
10
+ vote-started vote-ended].freeze
10
11
 
11
12
  # @return [String]
12
13
  attr_reader :type
@@ -45,7 +45,7 @@ module RelatonBib
45
45
  attr_reader :id, :type, :docnumber, :edition, :doctype
46
46
 
47
47
  # @!attribute [r] title
48
- # @return [Array<RelatonBib::TypedTitleString>]
48
+ # @return [RelatonBib::TypedTitleStringCollection]
49
49
 
50
50
  # @return [Array<RelatonBib::TypedUri>]
51
51
  attr_reader :link
@@ -59,10 +59,10 @@ module RelatonBib
59
59
  # @return [Array<RelatonBib::ContributionInfo>]
60
60
  attr_reader :contributor
61
61
 
62
- # @return [RelatonBib::BibliongraphicItem::Version, NilClass]
62
+ # @return [RelatonBib::BibliographicItem::Version, NilClass]
63
63
  attr_reader :version
64
64
 
65
- # @return [Array<RelatonBib::BiblioNote>]
65
+ # @return [RelatonBib::BiblioNoteCollection]
66
66
  attr_reader :biblionote
67
67
 
68
68
  # @return [Array<String>] language Iso639 code
@@ -126,7 +126,8 @@ module RelatonBib
126
126
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
127
127
 
128
128
  # @param id [String, NilClass]
129
- # @param title [Array<RelatonBib::TypedTitleString>]
129
+ # @param title [RelatonBib::TypedTitleStringCollection,
130
+ # Array<Hash, RelatonBib::TypedTitleString>]
130
131
  # @param formattedref [RelatonBib::FormattedRef, NilClass]
131
132
  # @param type [String, NilClass]
132
133
  # @param docid [Array<RelatonBib::DocumentIdentifier>]
@@ -136,7 +137,7 @@ module RelatonBib
136
137
  # @param docstatus [RelatonBib::DocumentStatus, NilClass]
137
138
  # @param edition [String, NilClass]
138
139
  # @param version [RelatonBib::BibliographicItem::Version, NilClass]
139
- # @param biblionote [Array<RelatonBib::BiblioNote>]
140
+ # @param biblionote [RelatonBib::BiblioNoteCollection]
140
141
  # @param series [Array<RelatonBib::Series>]
141
142
  # @param medium [RelatonBib::Medium, NilClas]
142
143
  # @param place [Array<String, RelatonBib::Place>]
@@ -193,9 +194,7 @@ module RelatonBib
193
194
  warn %{[relaton-bib] document type "#{args[:type]}" is invalid.}
194
195
  end
195
196
 
196
- @title = (args[:title] || []).map do |t|
197
- t.is_a?(Hash) ? TypedTitleString.new(t) : t
198
- end
197
+ @title = TypedTitleStringCollection.new(args[:title])
199
198
 
200
199
  @date = (args[:date] || []).map do |d|
201
200
  d.is_a?(Hash) ? BibliographicDate.new(d) : d
@@ -224,7 +223,7 @@ module RelatonBib
224
223
  @docnumber = args[:docnumber]
225
224
  @edition = args[:edition]
226
225
  @version = args[:version]
227
- @biblionote = args.fetch :biblionote, []
226
+ @biblionote = args.fetch :biblionote, BiblioNoteCollection.new([])
228
227
  @language = args.fetch :language, []
229
228
  @script = args.fetch :script, []
230
229
  @status = args[:docstatus]
@@ -262,12 +261,15 @@ module RelatonBib
262
261
  # @return [RelatonBib::FormattedString, Array<RelatonBib::FormattedString>]
263
262
  def abstract(lang: nil)
264
263
  if lang
265
- @abstract.detect { |a| a.language.include? lang }
264
+ @abstract.detect { |a| a.language&.include? lang }
266
265
  else
267
266
  @abstract
268
267
  end
269
268
  end
270
269
 
270
+ # @param id [RelatonBib::DocumentIdentifier]
271
+ # @param attribute [boolean, nil]
272
+ # @return [String]
271
273
  def makeid(id, attribute)
272
274
  return nil if attribute && !@id_attribute
273
275
 
@@ -282,8 +284,12 @@ module RelatonBib
282
284
  idstr.strip
283
285
  end
284
286
 
287
+ # @param identifier [RelatonBib::DocumentIdentifier]
288
+ # @param options [Hash]
289
+ # @option options [boolean, nil] :no_year
290
+ # @option options [boolean, nil] :all_parts
285
291
  # @return [String]
286
- def shortref(identifier, **opts) # rubocop:disable Metrics/CyclomaticComplexity
292
+ def shortref(identifier, **opts) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/PerceivedComplexity
287
293
  pubdate = date.select { |d| d.type == "published" }
288
294
  year = if opts[:no_year] || pubdate.empty? then ""
289
295
  else ":" + pubdate&.first&.on&.year.to_s
@@ -293,14 +299,18 @@ module RelatonBib
293
299
  "#{makeid(identifier, false)}#{year}"
294
300
  end
295
301
 
296
- # @param builder [Nokogiri::XML::Builder, NillClass] (nil)
297
- # @return [String]
298
- def to_xml(builder = nil, **opts, &block)
299
- if builder
300
- render_xml builder, **opts, &block
302
+ # @param opts [Hash]
303
+ # @option opts [Nokogiri::XML::Builder] :builder XML builder
304
+ # @option opts [Boolean] :bibdata
305
+ # @option opts [Symbol, NilClass] :date_format (:short), :full
306
+ # @option opts [String, Symbol] :lang language
307
+ # @return [String] XML
308
+ def to_xml(**opts, &block)
309
+ if opts[:builder]
310
+ render_xml **opts, &block
301
311
  else
302
312
  Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
303
- render_xml xml, **opts, &block
313
+ render_xml builder: xml, **opts, &block
304
314
  end.doc.root.to_xml
305
315
  end
306
316
  end
@@ -344,7 +354,9 @@ module RelatonBib
344
354
  hash["keyword"] = single_element_array(keyword) if keyword&.any?
345
355
  hash["license"] = single_element_array(license) if license&.any?
346
356
  hash["doctype"] = doctype if doctype
347
- hash["editorialgroup"] = editorialgroup.to_hash if editorialgroup
357
+ if editorialgroup&.presence?
358
+ hash["editorialgroup"] = editorialgroup.to_hash
359
+ end
348
360
  hash["ics"] = single_element_array ics if ics.any?
349
361
  if structuredidentifier&.presence?
350
362
  hash["structuredidentifier"] = structuredidentifier.to_hash
@@ -378,12 +390,10 @@ module RelatonBib
378
390
  bibtex.to_s
379
391
  end
380
392
 
381
- # @param lang [String] language code Iso639
382
- # @return [Array<RelatonIsoBib::TypedTitleString>]
393
+ # @param lang [String, nil] language code Iso639
394
+ # @return [RelatonIsoBib::TypedTitleStringCollection]
383
395
  def title(lang: nil)
384
- if lang then @title.select { |t| t.title.language&.include? lang }
385
- else @title
386
- end
396
+ @title.lang lang
387
397
  end
388
398
 
389
399
  # @param type [Symbol] type of url, can be :src/:obp/:rss
@@ -406,12 +416,12 @@ module RelatonBib
406
416
  end
407
417
 
408
418
  # remove title part components and abstract
409
- def to_all_parts # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
419
+ def to_all_parts # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength,Metrics/PerceivedComplexity
410
420
  me = deep_clone
411
421
  me.disable_id_attribute
412
422
  me.relation << DocumentRelation.new(type: "instance", bibitem: self)
413
423
  me.language.each do |l|
414
- me.title.delete_if { |t| t.type == "title-part" }
424
+ me.title.delete_title_part!
415
425
  ttl = me.title.select do |t|
416
426
  t.type != "main" && t.title.language&.include?(l)
417
427
  end
@@ -449,7 +459,7 @@ module RelatonBib
449
459
 
450
460
  # If revision_date exists then returns it else returns published date or nil
451
461
  # @return [String, NilClass]
452
- def revdate # rubocop:disable Metrics/CyclomaticComplexity
462
+ def revdate # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
453
463
  @revdate ||= if version&.revision_date
454
464
  version.revision_date
455
465
  else
@@ -526,7 +536,7 @@ module RelatonBib
526
536
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
527
537
 
528
538
  # @param [BibTeX::Entry]
529
- def bibtex_author(item) # rubocop:disable Metrics/CyclomaticComplexity
539
+ def bibtex_author(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
530
540
  authors = contributor.select do |c|
531
541
  c.entity.is_a?(Person) && c.role.map(&:type).include?("author")
532
542
  end.map &:entity
@@ -560,7 +570,7 @@ module RelatonBib
560
570
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
561
571
 
562
572
  # @param [BibTeX::Entry]
563
- def bibtex_note(item) # rubocop:disable Metrics/CyclomaticComplexity
573
+ def bibtex_note(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize
564
574
  biblionote.each do |n|
565
575
  case n.type
566
576
  when "annote" then item.annote = n.content
@@ -656,32 +666,40 @@ module RelatonBib
656
666
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
657
667
  # rubocop:disable Style/NestedParenthesizedCalls, Metrics/BlockLength
658
668
 
659
- # @param builder [Nokogiri::XML::Builder]
660
- # @return [String]
661
- def render_xml(builder, **opts)
669
+ # @param opts [Hash]
670
+ # @option opts [Nokogiri::XML::Builder] :builder XML builder
671
+ # @option opts [Boolean] bibdata
672
+ # @option opts [Symbol, NilClass] :date_format (:short), :full
673
+ # @option opts [String] :lang language
674
+ def render_xml(**opts)
662
675
  root = opts[:bibdata] ? :bibdata : :bibitem
663
- xml = builder.send(root) do
676
+ xml = opts[:builder].send(root) do |builder|
664
677
  builder.fetched fetched if fetched
665
- title.each { |t| builder.title { t.to_xml builder } }
678
+ title.to_xml **opts
666
679
  formattedref&.to_xml builder
667
680
  link.each { |s| s.to_xml builder }
668
- docidentifier.each { |di| di.to_xml builder }
681
+ docidentifier.each { |di| di.to_xml **opts }
669
682
  builder.docnumber docnumber if docnumber
670
683
  date.each { |d| d.to_xml builder, **opts }
671
684
  contributor.each do |c|
672
685
  builder.contributor do
673
- c.role.each { |r| r.to_xml builder }
674
- c.to_xml builder
686
+ c.role.each { |r| r.to_xml **opts }
687
+ c.to_xml **opts
675
688
  end
676
689
  end
677
690
  builder.edition edition if edition
678
691
  version&.to_xml builder
679
- biblionote.each { |n| n.to_xml builder }
692
+ biblionote.to_xml **opts
693
+ opts[:note]&.each do |n|
694
+ builder.note(n[:text], format: "text/plain", type: n[:type])
695
+ end
680
696
  language.each { |l| builder.language l }
681
697
  script.each { |s| builder.script s }
682
- abstract.each { |a| builder.abstract { a.to_xml(builder) } }
698
+ abstr = abstract.select { |ab| ab.language&.include? opts[:lang] }
699
+ abstr = abstract unless abstr.any?
700
+ abstr.each { |a| builder.abstract { a.to_xml(builder) } }
683
701
  status&.to_xml builder
684
- copyright&.each { |c| c.to_xml builder }
702
+ copyright&.each { |c| c.to_xml **opts }
685
703
  relation.each { |r| r.to_xml builder, **opts }
686
704
  series.each { |s| s.to_xml builder }
687
705
  medium&.to_xml builder
@@ -690,7 +708,9 @@ module RelatonBib
690
708
  accesslocation.each { |al| builder.accesslocation al }
691
709
  license.each { |l| builder.license l }
692
710
  classification.each { |cls| cls.to_xml builder }
693
- keyword.each { |kw| builder.keyword { kw.to_xml(builder) } }
711
+ kwrd = keyword.select { |kw| kw.language&.include? opts[:lang] }
712
+ kwrd = keyword unless kwrd.any?
713
+ kwrd.each { |kw| builder.keyword { kw.to_xml(builder) } }
694
714
  validity&.to_xml builder
695
715
  if block_given? then yield builder
696
716
  elsif opts[:bibdata] && (doctype || editorialgroup || ics&.any? ||
@@ -6,7 +6,7 @@ module RelatonBib
6
6
  class << self
7
7
  # @param bibtex [String]
8
8
  # @return [Hash{String=>RelatonBib::BibliographicItem}]
9
- def from_bibtex(bibtex)
9
+ def from_bibtex(bibtex) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
10
10
  BibTeX.parse(bibtex).reduce({}) do |h, bt|
11
11
  h[bt.key] = BibliographicItem.new(
12
12
  id: bt.key,
@@ -35,7 +35,7 @@ module RelatonBib
35
35
 
36
36
  # @param bibtex [BibTeX::Entry]
37
37
  # @return [Array<RelatonBib::DocumentIdentifier>]
38
- def fetch_docid(bibtex)
38
+ def fetch_docid(bibtex) # rubocop:disable Metrics/AbcSize
39
39
  docid = []
40
40
  docid << DocumentIdentifier.new(id: bibtex.isbn.to_s, type: "isbn") if bibtex["isbn"]
41
41
  docid << DocumentIdentifier.new(id: bibtex.lccn.to_s, type: "lccn") if bibtex["lccn"]
@@ -67,17 +67,17 @@ module RelatonBib
67
67
  end
68
68
 
69
69
  # @param bibtex [BibTeX::Entry]
70
- # @return [Array<Hash>]
70
+ # @return [RelatonBib::TypedTitleStringCollection]
71
71
  def fetch_title(bibtex)
72
72
  title = []
73
73
  title << { type: "main", content: bibtex.title.to_s } if bibtex["title"]
74
74
  title << { type: "main", content: bibtex.subtitle.to_s } if bibtex["subtitle"]
75
- title
75
+ TypedTitleStringCollection.new title
76
76
  end
77
77
 
78
78
  # @param bibtex [BibTeX::Entry]
79
79
  # @return [Array<Hash>]
80
- def fetch_contributor(bibtex)
80
+ def fetch_contributor(bibtex) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength
81
81
  contributor = []
82
82
  fetch_person(bibtex["author"]).each do |entity|
83
83
  contributor << { entity: entity, role: [{ type: "author" }] }
@@ -94,7 +94,7 @@ module RelatonBib
94
94
  if bibtex["institution"]
95
95
  contributor << {
96
96
  entity: { name: bibtex.institution.to_s },
97
- role: [{ type: "distributor", description: ["sponsor"] }]
97
+ role: [{ type: "distributor", description: ["sponsor"] }],
98
98
  }
99
99
  end
100
100
 
@@ -145,11 +145,11 @@ module RelatonBib
145
145
  end
146
146
 
147
147
  # @param bibtex [BibTeX::Entry]
148
- # @return [Array<RelatonBib::BiblioNote>]
148
+ # @return [RelatonBib::BiblioNoteCollection]
149
149
  def fetch_note(bibtex)
150
150
  bibtex.select do |k, _v|
151
151
  %i[annote howpublished comment note content].include? k
152
- end.reduce([]) do |mem, note|
152
+ end.reduce(BiblioNoteCollection.new([])) do |mem, note|
153
153
  type = case note[0]
154
154
  when :note then nil
155
155
  when :content then "tableOfContents"
@@ -164,13 +164,14 @@ module RelatonBib
164
164
  def fetch_relation(bibtex)
165
165
  return [] unless bibtex["booktitle"]
166
166
 
167
- title = TypedTitleString.new(type: "main", content: bibtex.booktitle.to_s)
168
- [{ type: "partOf", bibitem: BibliographicItem.new(title: [title]) }]
167
+ ttl = TypedTitleString.new(type: "main", content: bibtex.booktitle.to_s)
168
+ title = TypedTitleStringCollection.new [ttl]
169
+ [{ type: "partOf", bibitem: BibliographicItem.new(title: title) }]
169
170
  end
170
171
 
171
172
  # @param bibtex [BibTeX::Entry]
172
173
  # @return [Array<RelatonBib::BibItemLocality>]
173
- def fetch_extent(bibtex)
174
+ def fetch_extent(bibtex) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
174
175
  bibtex.select do |k, _v|
175
176
  %i[chapter pages volume].include? k
176
177
  end.reduce([]) do |mem, loc|
@@ -188,13 +189,13 @@ module RelatonBib
188
189
 
189
190
  # @param bibtex [BibTeX::Entry]
190
191
  # @return [Array<RelatonBib::Series>]
191
- def fetch_series(bibtex)
192
+ def fetch_series(bibtex) # rubocop:disable Metrics/MethodLength
192
193
  series = []
193
194
  if bibtex["journal"]
194
195
  series << Series.new(
195
196
  type: "journal",
196
197
  title: TypedTitleString.new(content: bibtex.journal.to_s),
197
- number: bibtex["number"]&.to_s,
198
+ number: bibtex["number"]&.to_s
198
199
  )
199
200
  end
200
201
 
@@ -207,7 +208,7 @@ module RelatonBib
207
208
 
208
209
  # @param bibtex [BibTeX::Entry]
209
210
  # @return [Array<RelatonBib::TypedUri>]
210
- def fetch_link(bibtex)
211
+ def fetch_link(bibtex) # rubocop:disable Metrics/AbcSize
211
212
  link = []
212
213
  link << TypedUri.new(type: "src", content: bibtex.url.to_s) if bibtex["url"]
213
214
  link << TypedUri.new(type: "doi", content: bibtex.doi.to_s) if bibtex["doi"]
@@ -242,4 +243,4 @@ module RelatonBib
242
243
  end
243
244
  end
244
245
  end
245
- end
246
+ end
@@ -31,11 +31,15 @@ module RelatonBib
31
31
  end
32
32
  end
33
33
 
34
- # @param builder [Nokogiri::XML::Builder]
35
- def to_xml(builder)
36
- builder.role(type: type) do
37
- description.each do |d|
38
- builder.description { |desc| d.to_xml(desc) }
34
+ # @param opts [Hash]
35
+ # @option opts [Nokogiri::XML::Builder] :builder XML builder
36
+ # @option opts [String] :lang language
37
+ def to_xml(**opts) # rubocop:disable Metrics/AbcSize
38
+ opts[:builder].role(type: type) do |builder|
39
+ desc = description.select { |d| d.language&.include? opts[:lang] }
40
+ desc = description unless desc.any?
41
+ desc.each do |d|
42
+ builder.description { |b| d.to_xml(b) }
39
43
  end
40
44
  end
41
45
  end
@@ -83,9 +87,11 @@ module RelatonBib
83
87
  @role = role.map { |r| ContributorRole.new(**r) }
84
88
  end
85
89
 
86
- # @param builder [Nokogiri::XML::Builder]
87
- def to_xml(builder)
88
- entity.to_xml builder
90
+ # @param opts [Hash]
91
+ # @option opts [Nokogiri::XML::Builder] :builder XML builder
92
+ # @option opts [String, Symbol] :lang language
93
+ def to_xml(**opts)
94
+ entity.to_xml **opts
89
95
  end
90
96
 
91
97
  # @return [Hash]
@@ -129,12 +129,16 @@ module RelatonBib
129
129
  @description = description
130
130
  end
131
131
 
132
- # @params builder [Nokogiri::XML::Builder]
133
- def to_xml(builder)
134
- builder.affiliation do
132
+ # @param opts [Hash]
133
+ # @option opts [Nokogiri::XML::Builder] :builder XML builder
134
+ # @option opts [String] :lang language
135
+ def to_xml(**opts) # rubocop:disable Metrics/AbcSize
136
+ opts[:builder].affiliation do |builder|
135
137
  builder.name { name.to_xml builder } if name
136
- description.each { |d| builder.description { d.to_xml builder } }
137
- organization.to_xml builder
138
+ desc = description.select { |d| d.language&.include? opts[:lang] }
139
+ desc = description unless desc.any?
140
+ desc.each { |d| builder.description { d.to_xml builder } }
141
+ organization.to_xml **opts
138
142
  end
139
143
  end
140
144
 
@@ -151,7 +155,7 @@ module RelatonBib
151
155
  # @param prefix [String]
152
156
  # @param count [Integer]
153
157
  # @return [String]
154
- def to_asciibib(prefix = "", count = 1)
158
+ def to_asciibib(prefix = "", count = 1) # rubocop:disable Metrics/AbcSize
155
159
  pref = prefix.empty? ? prefix : prefix + "."
156
160
  out = count > 1 ? "#{pref}affiliation::\n" : ""
157
161
  out += name.to_asciibib "#{pref}affiliation.name" if name