relaton-bib 1.1.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) 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 +16 -0
  5. data/lib/relaton_bib.rb +15 -15
  6. data/lib/relaton_bib/bib_item_locality.rb +13 -1
  7. data/lib/relaton_bib/biblio_note.rb +11 -0
  8. data/lib/relaton_bib/biblio_version.rb +12 -0
  9. data/lib/relaton_bib/bibliographic_date.rb +13 -0
  10. data/lib/relaton_bib/bibliographic_item.rb +80 -24
  11. data/lib/relaton_bib/classification.rb +11 -0
  12. data/lib/relaton_bib/contribution_info.rb +27 -1
  13. data/lib/relaton_bib/contributor.rb +55 -1
  14. data/lib/relaton_bib/copyright_association.rb +14 -1
  15. data/lib/relaton_bib/document_identifier.rb +20 -4
  16. data/lib/relaton_bib/document_relation.rb +15 -5
  17. data/lib/relaton_bib/document_relation_collection.rb +12 -0
  18. data/lib/relaton_bib/document_status.rb +10 -0
  19. data/lib/relaton_bib/editorial_group.rb +9 -0
  20. data/lib/relaton_bib/formatted_ref.rb +7 -0
  21. data/lib/relaton_bib/formatted_string.rb +11 -0
  22. data/lib/relaton_bib/hash_converter.rb +55 -36
  23. data/lib/relaton_bib/ics.rb +11 -0
  24. data/lib/relaton_bib/localized_string.rb +23 -6
  25. data/lib/relaton_bib/medium.rb +11 -0
  26. data/lib/relaton_bib/organization.rb +27 -7
  27. data/lib/relaton_bib/person.rb +53 -7
  28. data/lib/relaton_bib/place.rb +13 -1
  29. data/lib/relaton_bib/series.rb +25 -4
  30. data/lib/relaton_bib/structured_identifier.rb +30 -0
  31. data/lib/relaton_bib/technical_committee.rb +11 -0
  32. data/lib/relaton_bib/typed_title_string.rb +13 -7
  33. data/lib/relaton_bib/typed_uri.rb +11 -0
  34. data/lib/relaton_bib/validity.rb +11 -0
  35. data/lib/relaton_bib/version.rb +1 -1
  36. data/lib/relaton_bib/workgroup.rb +10 -0
  37. data/lib/relaton_bib/xml_parser.rb +54 -39
  38. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7424cbb988868104ccd498b012e5dd247f60615619d20fe878a393cc6c885b92
4
- data.tar.gz: f24604096daa57ae965d39dc03426e34a588a7af6e7fd4012d37ba27fa8f5349
3
+ metadata.gz: 2d2e73e228a1e3d0b56ec177f3fa39a721dbd76ff99fd3f18e38c331672aca43
4
+ data.tar.gz: c9dab886bcffafd638735157419c904b88da2363048178fb8c458399d9a74909
5
5
  SHA512:
6
- metadata.gz: fc28cc344fd744c23c08b7b729880725f03c6cc893d8ccbb54e57c03f4cbb5e0dfd9b0cc9ba0453ae041b92ddcc1670490708acc89e55087f667b0234726d175
7
- data.tar.gz: e55f52ac794b3f50c3f80d23b565be2c509d51aa0d458799ca537dc4a53954bc6ba4469690cfbbc1f63ee4ae846d0820d0d1fd1ae2c5e30a93c57afcb0dc97bf
6
+ metadata.gz: 62292ca68783b8f5817807ca4b014ec0c782a81c3724ff7860562f7d4529cd3eac9e1f1dccddae7149d6bb56dbb114dd1bcd7393cbc797cb91b7beb02a3de953
7
+ data.tar.gz: ff58d4ed2c0bb448bca70e62e8a6d9252ffa02865bfcbbc31f0bf360e009f372e8bc292c59ee7c970f891e0ab496cf4e81df3241f967dbbde1968cebdccf8952
@@ -35,4 +35,5 @@ jobs:
35
35
  bundle install --jobs 4 --retry 3
36
36
  - name: Run specs
37
37
  run: |
38
+ unset JAVA_TOOL_OPTIONS
38
39
  bundle exec rake
@@ -5,6 +5,6 @@
5
5
  inherit_from:
6
6
  - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
7
7
  AllCops:
8
- TargetRubyVersion: 2.3
8
+ TargetRubyVersion: 2.4
9
9
  Rails:
10
- Enabled: true
10
+ Enabled: false
@@ -380,6 +380,22 @@ item.to_bibtex
380
380
  ...
381
381
  ----
382
382
 
383
+ === Exporting bibliographic item to AsciiBib
384
+
385
+ [source,ruby]
386
+ ----
387
+ item.to_asciibib
388
+ [%bibitem]
389
+ == {blank}
390
+ id:: ISOTC211
391
+ fetched:: 2020-08-19
392
+ title::
393
+ title.type:: title-main
394
+ title.conten:: Geographic information
395
+ title.format:: text/plain
396
+ ...
397
+ ----
398
+
383
399
  == Development
384
400
 
385
401
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -10,31 +10,31 @@ module RelatonBib
10
10
  class RequestError < StandardError; end
11
11
 
12
12
  class << self
13
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
14
-
15
- # @param date [String]
13
+ # @param date [String, Integer, Date]
16
14
  # @return [Date, NilClass]
17
- def parse_date(sdate)
18
- if sdate.is_a?(Date) then sdate
19
- elsif /(?<date>\w+\s\d{4})/ =~ sdate # February 2012
20
- Date.strptime(date, "%B %Y")
21
- elsif /(?<date>\w+\s\d{1,2},\s\d{4})/ =~ sdate # February 11, 2012
22
- Date.strptime(date, "%B %d, %Y")
23
- elsif /(?<date>\d{4}-\d{2}-\d{2})/ =~ sdate # 2012-02-11
24
- Date.parse(date)
25
- elsif /(?<date>\d{4}-\d{2})/ =~ sdate # 2012-02
15
+ def parse_date(date) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
16
+ return date if date.is_a?(Date)
17
+
18
+ sdate = date.to_s
19
+ case sdate
20
+ when /(?<date>\w+\s\d{4})/ # February 2012
21
+ Date.strptime($~[:date], "%B %Y")
22
+ when /(?<date>\w+\s\d{1,2},\s\d{4})/ # February 11, 2012
23
+ Date.strptime($~[:date], "%B %d, %Y")
24
+ when /(?<date>\d{4}-\d{2}-\d{2})/ # 2012-02-11
25
+ Date.parse($~[:date])
26
+ when /(?<date>\d{4}-\d{2})/ # 2012-02
26
27
  Date.strptime date, "%Y-%m"
27
- elsif /(?<date>\d{4})/ =~ sdate then Date.strptime date, "%Y" # 2012
28
+ when /(?<date>\d{4})/ then Date.strptime $~[:date], "%Y" # 2012
28
29
  end
29
30
  end
30
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
31
31
  end
32
32
 
33
33
  private
34
34
 
35
35
  # @param array [Array]
36
36
  # @return [Array<String>, String]
37
- def single_element_array(array)
37
+ def single_element_array(array) # rubocop:disable Metrics/CyclomaticComplexity
38
38
  if array.size > 1
39
39
  array.map { |e| e.is_a?(String) ? e : e.to_hash }
40
40
  else
@@ -17,7 +17,7 @@ module RelatonBib
17
17
  type_ptrn = %r{section|clause|part|paragraph|chapter|page|whole|table|
18
18
  annex|figure|note|list|example|volume|issue|time|
19
19
  locality:[a-zA-Z0-9_]+}x
20
- unless type =~ type_ptrn
20
+ unless type.match? type_ptrn
21
21
  warn "[relaton-bib] WARNING: invalid locality type: #{type}"
22
22
  end
23
23
 
@@ -39,6 +39,18 @@ module RelatonBib
39
39
  hash["reference_to"] = reference_to if reference_to
40
40
  hash
41
41
  end
42
+
43
+ # @param prefix [String]
44
+ # @param count [Integeg] number of localities
45
+ # @return [String]
46
+ def to_asciibib(prefix = "", count = 1)
47
+ pref = prefix.empty? ? prefix : prefix + "."
48
+ out = count > 1 ? "#{prefix}::\n" : ""
49
+ out += "#{pref}type:: #{type}\n"
50
+ out += "#{pref}reference_from:: #{reference_from}\n"
51
+ out += "#{pref}reference_to:: #{reference_to}\n" if reference_to
52
+ out
53
+ end
42
54
  end
43
55
 
44
56
  class Locality < BibItemLocality
@@ -29,5 +29,16 @@ module RelatonBib
29
29
  hash["type"] = type
30
30
  hash
31
31
  end
32
+
33
+ # @param prefix [String]
34
+ # @param count [Integer] number of notes
35
+ # @return [String]
36
+ def to_asciibib(prefix = "", count = 1)
37
+ pref = prefix.empty? ? prefix : prefix + "."
38
+ out = count > 1 ? "#{pref}biblionote::\n" : ""
39
+ out + "#{pref}biblionote.type:: #{type}\n" if type
40
+ out += super "#{pref}biblionote"
41
+ out
42
+ end
32
43
  end
33
44
  end
@@ -32,6 +32,18 @@ module RelatonBib
32
32
  hash["draft"] = single_element_array(draft) if draft&.any?
33
33
  hash
34
34
  end
35
+
36
+ # @param prefix [String]
37
+ # @return [String]
38
+ def to_asciibib(prefix = "")
39
+ pref = prefix.empty? ? prefix : prefix + "."
40
+ out = ""
41
+ if revision_date
42
+ out += "#{pref}version.revision_date:: #{revision_date}\n"
43
+ end
44
+ draft&.each { |d| out += "#{pref}version.draft:: #{d}\n" }
45
+ out
46
+ end
35
47
  end
36
48
  end
37
49
  end
@@ -60,6 +60,19 @@ module RelatonBib
60
60
  hash
61
61
  end
62
62
 
63
+ # @param prefix [String]
64
+ # @param count [Integer] number of dates
65
+ # @return [String]
66
+ def to_asciibib(prefix = "", count = 1)
67
+ pref = prefix.empty? ? prefix : prefix + "."
68
+ out = count > 1 ? "#{pref}date::\n" : ""
69
+ out += "#{pref}date.type:: #{type}\n"
70
+ out += "#{pref}date.on:: #{on}\n" if on
71
+ out += "#{pref}date.from:: #{from}\n" if from
72
+ out += "#{pref}date.to:: #{to}\n" if to
73
+ out
74
+ end
75
+
63
76
  private
64
77
 
65
78
  # Formats date
@@ -237,13 +237,18 @@ module RelatonBib
237
237
  end
238
238
  @series = args.fetch :series, []
239
239
  @medium = args[:medium]
240
- @place = args.fetch(:place, []).map { |pl| pl.is_a?(String) ? Place.new(name: pl) : pl }
240
+ @place = args.fetch(:place, []).map do |pl|
241
+ pl.is_a?(String) ? Place.new(name: pl) : pl
242
+ end
241
243
  @extent = args[:extent] || []
242
244
  @accesslocation = args.fetch :accesslocation, []
243
245
  @classification = args.fetch :classification, []
244
246
  @validity = args[:validity]
245
- @fetched = args.fetch :fetched, nil # , Date.today # we should pass the fetched arg from scrappers
246
- @keyword = (args[:keyword] || []).map { |kw| LocalizedString.new(kw) }
247
+ # we should pass the fetched arg from scrappers
248
+ @fetched = args.fetch :fetched, nil
249
+ @keyword = (args[:keyword] || []).map do |kw|
250
+ LocalizedString.new(kw)
251
+ end
247
252
  @license = args.fetch :license, []
248
253
  @doctype = args[:doctype]
249
254
  @editorialgroup = args[:editorialgroup]
@@ -278,7 +283,7 @@ module RelatonBib
278
283
  end
279
284
 
280
285
  # @return [String]
281
- def shortref(identifier, **opts)
286
+ def shortref(identifier, **opts) # rubocop:disable Metrics/CyclomaticComplexity
282
287
  pubdate = date.select { |d| d.type == "published" }
283
288
  year = if opts[:no_year] || pubdate.empty? then ""
284
289
  else ":" + pubdate&.first&.on&.year.to_s
@@ -300,10 +305,8 @@ module RelatonBib
300
305
  end
301
306
  end
302
307
 
303
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
304
-
305
308
  # @return [Hash]
306
- def to_hash
309
+ def to_hash # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
307
310
  hash = {}
308
311
  hash["id"] = id if id
309
312
  hash["title"] = single_element_array(title) if title&.any?
@@ -312,7 +315,9 @@ module RelatonBib
312
315
  hash["docid"] = single_element_array(docidentifier) if docidentifier&.any?
313
316
  hash["docnumber"] = docnumber if docnumber
314
317
  hash["date"] = single_element_array(date) if date&.any?
315
- hash["contributor"] = single_element_array(contributor) if contributor&.any?
318
+ if contributor&.any?
319
+ hash["contributor"] = single_element_array(contributor)
320
+ end
316
321
  hash["edition"] = edition if edition
317
322
  hash["version"] = version.to_hash if version
318
323
  hash["revdate"] = revdate if revdate
@@ -328,8 +333,12 @@ module RelatonBib
328
333
  hash["medium"] = medium.to_hash if medium
329
334
  hash["place"] = single_element_array(place) if place&.any?
330
335
  hash["extent"] = single_element_array(extent) if extent&.any?
331
- hash["accesslocation"] = single_element_array(accesslocation) if accesslocation&.any?
332
- hash["classification"] = single_element_array(classification) if classification&.any?
336
+ if accesslocation&.any?
337
+ hash["accesslocation"] = single_element_array(accesslocation)
338
+ end
339
+ if classification&.any?
340
+ hash["classification"] = single_element_array(classification)
341
+ end
333
342
  hash["validity"] = validity.to_hash if validity
334
343
  hash["fetched"] = fetched.to_s if fetched
335
344
  hash["keyword"] = single_element_array(keyword) if keyword&.any?
@@ -342,11 +351,10 @@ module RelatonBib
342
351
  end
343
352
  hash
344
353
  end
345
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
346
354
 
347
355
  # @param bibtex [BibTeX::Bibliography, NilClass]
348
356
  # @return [String]
349
- def to_bibtex(bibtex = nil)
357
+ def to_bibtex(bibtex = nil) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
350
358
  item = BibTeX::Entry.new
351
359
  item.type = bibtex_type
352
360
  item.key = id
@@ -369,7 +377,6 @@ module RelatonBib
369
377
  bibtex << item
370
378
  bibtex.to_s
371
379
  end
372
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
373
380
 
374
381
  # @param lang [String] language code Iso639
375
382
  # @return [Array<RelatonIsoBib::TypedTitleString>]
@@ -391,7 +398,7 @@ module RelatonBib
391
398
 
392
399
  def deep_clone
393
400
  dump = Marshal.dump self
394
- Marshal.load dump
401
+ Marshal.load dump # rubocop:disable Security/MarshalLoad
395
402
  end
396
403
 
397
404
  def disable_id_attribute
@@ -399,17 +406,19 @@ module RelatonBib
399
406
  end
400
407
 
401
408
  # remove title part components and abstract
402
- def to_all_parts
409
+ def to_all_parts # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
403
410
  me = deep_clone
404
411
  me.disable_id_attribute
405
- me.relation << RelatonBib::DocumentRelation.new(
406
- type: "instance", bibitem: self,
407
- )
412
+ me.relation << DocumentRelation.new(type: "instance", bibitem: self)
408
413
  me.language.each do |l|
409
414
  me.title.delete_if { |t| t.type == "title-part" }
410
- ttl = me.title.select { |t| t.type != "main" && t.title.language&.include?(l) }
415
+ ttl = me.title.select do |t|
416
+ t.type != "main" && t.title.language&.include?(l)
417
+ end
411
418
  tm_en = ttl.map { |t| t.title.content }.join " – "
412
- me.title.detect { |t| t.type == "main" && t.title.language&.include?(l) }&.title&.content = tm_en
419
+ me.title.detect do |t|
420
+ t.type == "main" && t.title.language&.include?(l)
421
+ end&.title&.content = tm_en
413
422
  end
414
423
  me.abstract = []
415
424
  me.docidentifier.each(&:remove_part)
@@ -440,7 +449,7 @@ module RelatonBib
440
449
 
441
450
  # If revision_date exists then returns it else returns published date or nil
442
451
  # @return [String, NilClass]
443
- def revdate
452
+ def revdate # rubocop:disable Metrics/CyclomaticComplexity
444
453
  @revdate ||= if version&.revision_date
445
454
  version.revision_date
446
455
  else
@@ -448,6 +457,53 @@ module RelatonBib
448
457
  end
449
458
  end
450
459
 
460
+ # @param prefix [String]
461
+ # @return [String]
462
+ def to_asciibib(prefix = "") # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
463
+ pref = prefix.empty? ? prefix : prefix + "."
464
+ out = prefix.empty? ? "[%bibitem]\n== {blank}\n" : ""
465
+ out += "#{pref}id:: #{id}\n" if id
466
+ out += "#{pref}fetched:: #{fetched}\n" if fetched
467
+ title.each { |t| out += t.to_asciibib(prefix, title.size) }
468
+ out += "#{pref}type:: #{type}\n" if type
469
+ docidentifier.each do |di|
470
+ out += di.to_asciibib prefix, docidentifier.size
471
+ end
472
+ out += "#{pref}docnumber:: #{docnumber}\n" if docnumber
473
+ out += "#{pref}edition:: #{edition}\n" if edition
474
+ language.each { |l| out += "#{pref}language:: #{l}\n" }
475
+ script.each { |s| out += "#{pref}script:: #{s}\n" }
476
+ out += version.to_asciibib prefix if version
477
+ biblionote&.each { |b| out += b.to_asciibib prefix, biblionote.size }
478
+ out += status.to_asciibib prefix if status
479
+ date.each { |d| out += d.to_asciibib prefix, date.size }
480
+ abstract.each do |a|
481
+ out += a.to_asciibib "#{pref}abstract", abstract.size
482
+ end
483
+ copyright.each { |c| out += c.to_asciibib prefix, copyright.size }
484
+ link.each { |l| out += l.to_asciibib prefix, link.size }
485
+ out += medium.to_asciibib prefix if medium
486
+ place.each { |pl| out += pl.to_asciibib prefix, place.size }
487
+ extent.each { |ex| out += ex.to_asciibib "#{pref}extent", extent.size }
488
+ accesslocation.each { |al| out += "#{pref}accesslocation:: #{al}\n" }
489
+ classification.each do |cl|
490
+ out += cl.to_asciibib prefix, classification.size
491
+ end
492
+ out += validity.to_asciibib prefix if validity
493
+ contributor.each do |c|
494
+ out += c.to_asciibib "contributor.*", contributor.size
495
+ end
496
+ out += relation.to_asciibib prefix if relation
497
+ series.each { |s| out += s.to_asciibib prefix, series.size }
498
+ out += "#{pref}doctype:: #{doctype}\n" if doctype
499
+ out += "#{pref}formattedref:: #{formattedref}\n" if formattedref
500
+ keyword.each { |kw| out += kw.to_asciibib "#{pref}keyword", keyword.size }
501
+ out += editorialgroup.to_asciibib prefix if editorialgroup
502
+ ics.each { |i| out += i.to_asciibib prefix, ics.size }
503
+ out += structuredidentifier.to_asciibib prefix if structuredidentifier
504
+ out
505
+ end
506
+
451
507
  private
452
508
 
453
509
  # @return [String]
@@ -470,7 +526,7 @@ module RelatonBib
470
526
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
471
527
 
472
528
  # @param [BibTeX::Entry]
473
- def bibtex_author(item)
529
+ def bibtex_author(item) # rubocop:disable Metrics/CyclomaticComplexity
474
530
  authors = contributor.select do |c|
475
531
  c.entity.is_a?(Person) && c.role.map(&:type).include?("author")
476
532
  end.map &:entity
@@ -487,7 +543,7 @@ module RelatonBib
487
543
  end
488
544
 
489
545
  # @param [BibTeX::Entry]
490
- def bibtex_contributor(item)
546
+ def bibtex_contributor(item) # rubocop:disable Metrics/CyclomaticComplexity
491
547
  contributor.each do |c|
492
548
  rls = c.role.map(&:type)
493
549
  if rls.include?("publisher") then item.publisher = c.entity.name
@@ -504,7 +560,7 @@ module RelatonBib
504
560
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
505
561
 
506
562
  # @param [BibTeX::Entry]
507
- def bibtex_note(item)
563
+ def bibtex_note(item) # rubocop:disable Metrics/CyclomaticComplexity
508
564
  biblionote.each do |n|
509
565
  case n.type
510
566
  when "annote" then item.annote = n.content
@@ -25,5 +25,16 @@ module RelatonBib
25
25
  hash["type"] = type if type
26
26
  hash
27
27
  end
28
+
29
+ # @param prefix [String]
30
+ # @param count [Integer] number of classifications
31
+ # @return [String]
32
+ def to_asciibib(prefix = "", count = 1)
33
+ pref = prefix.empty? ? "classification" : prefix + ".classification"
34
+ out = count > 1 ? "#{pref}::\n" : ""
35
+ out += "#{pref}.type:: #{type}\n" if type
36
+ out += "#{pref}.value:: #{value}\n"
37
+ out
38
+ end
28
39
  end
29
40
  end
@@ -26,7 +26,9 @@ module RelatonBib
26
26
  end
27
27
 
28
28
  @type = args[:type]
29
- @description = args.fetch(:description, []).map { |d| FormattedString.new content: d, format: nil }
29
+ @description = args.fetch(:description, []).map do |d|
30
+ FormattedString.new content: d, format: nil
31
+ end
30
32
  end
31
33
 
32
34
  # @param builder [Nokogiri::XML::Builder]
@@ -48,6 +50,19 @@ module RelatonBib
48
50
  type
49
51
  end
50
52
  end
53
+
54
+ # @param prefix [String]
55
+ # @param count [Integer] number of contributors
56
+ # 2return [String]
57
+ def to_asciibib(prefix = "", count = 1)
58
+ pref = prefix.empty? ? prefix : prefix + "."
59
+ out = count > 1 ? "#{prefix}::\n" : ""
60
+ description.each do |d|
61
+ out += d.to_asciibib "#{pref}role.description", description.size
62
+ end
63
+ out += "#{pref}role.type:: #{type}\n" if type
64
+ out
65
+ end
51
66
  end
52
67
 
53
68
  # Contribution info.
@@ -79,5 +94,16 @@ module RelatonBib
79
94
  hash["role"] = single_element_array(role) if role&.any?
80
95
  hash
81
96
  end
97
+
98
+ # @param prefix [String]
99
+ # @param count [Integer] number of contributors
100
+ # @return [String]
101
+ def to_asciibib(prefix = "", count = 1)
102
+ pref = prefix.split(".").first
103
+ out = count > 1 ? "#{pref}::\n" : ""
104
+ out += entity.to_asciibib prefix
105
+ role.each { |r| out += r.to_asciibib pref, role.size }
106
+ out
107
+ end
82
108
  end
83
109
  end