Class: RelatonDoi::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/relaton_doi/parser.rb

Constant Summary collapse

COUNTRIES =
%w[USA].freeze
TYPES =
{
  "book-chapter" => "inbook",
  "book-part" => "inbook",
  "book-section" => "inbook",
  "book-series" => "book",
  "book-set" => "book",
  "book-track" => "inbook",
  "component" => "misc",
  "database" => "dataset",
  "dissertation" => "thesis",
  "edited-book" => "book",
  "grant" => "misc",
  "journal-article" => "article",
  "journal-issue" => "article",
  "journal-volume" => "journal",
  "monograph" => "book",
  "other" => "misc",
  "peer-review" => "article",
  "posted-content" => "dataset",
  "proceedings-article" => "inproceedings",
  "proceedings-series" => "proceedings",
  "reference-book" => "book",
  "reference-entry" => "inbook",
  "report-component" => "techreport",
  "report-series" => "techreport",
  "report" => "techreport",
}.freeze
REALATION_TYPES =
{
  "is-cited-by" => "isCitedIn",
  "belongs-to" => "related",
  "is-child-of" => "includedIn",
  "is-expression-of" => "expressionOf",
  "has-expression" => "hasExpression",
  "is-manifestation-of" => "manifestationOf",
  "is-manuscript-of" => "draftOf",
  "has-manuscript" => "hasDraft",
  "is-preprint-of" => "draftOf",
  "has-preprint" => "hasDraft",
  "is-replaced-by" => "obsoletedBy",
  "replaces" => "obsoletes",
  "is-translation-of" => "translatedFrom",
  "has-translation" => "hasTranslation",
  "is-version-of" => "editionOf",
  "has-version" => "hasEdition",
  "is-based-on" => "updates",
  "is-basis-for" => "updatedBy",
  "is-comment-on" => "commentaryOf",
  "has-comment" => "hasCommentary",
  "is-continued-by" => "hasSuccessor",
  "continues" => "successorOf",
  "is-derived-from" => "derives",
  "has-derivation" => "derivedFrom",
  "is-documented-by" => "describedBy",
  "documents" => "describes",
  "is-part-of" => "partOf",
  "has-part" => "hasPart",
  "is-review-of" => "reviewOf",
  "has-review" => "hasReview",
  "references" => "cites",
  "is-referenced-by" => "isCitedIn",
  "requires" => "hasComplement",
  "is-required-by" => "complementOf",
  "is-supplement-to" => "complementOf",
  "is-supplemented-by" => "hasComplement",
}.freeze
ATTRS =
%i[type fetched title docid date link abstract contributor place
doctype relation extent series medium].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(src) ⇒ Parser

Initialize instance.

Parameters:

  • src (Hash)

    The source hash.



80
81
82
83
# File 'lib/relaton_doi/parser.rb', line 80

def initialize(src)
  @src = src
  @item = {}
end

Class Method Details

.parse(src) ⇒ RelatonBib::BibliographicItem, ...

Initialize instance and parse the source hash.

Parameters:

  • src (Hash)

    The source hash.

Returns:

  • (RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem, RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliographicItem)

    The bibitem.



94
95
96
# File 'lib/relaton_doi/parser.rb', line 94

def self.parse(src)
  new(src).parse
end

Instance Method Details

#author_investigatorsArray<RelatonBib::ContributionInfo>

Create authors investigators from the source hash.

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    The authors investigators.



325
326
327
328
329
330
# File 'lib/relaton_doi/parser.rb', line 325

def author_investigators
  RelatonBib.array(@src["project"]).reduce([]) do |memo, proj|
    memo + create_investigators(proj, "lead-investigator") +
      create_investigators(proj, "investigator")
  end
end

#authors_editors_translatorsArray<RelatonBib::ContributionInfo>

Create authors editors translators from the source hash.

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    The authors editors translators.



352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/relaton_doi/parser.rb', line 352

def authors_editors_translators
  %w[author editor translator].each_with_object([]) do |type, a|
    @src[type]&.each do |c|
      contrib = if c["family"]
                  create_person(c)
                else
                  RelatonBib::Organization.new(name: str_cleanup(c["name"]))
                end
      a << contributor(contrib, type)
    end
  end
end

#completename(person) ⇒ RelatonBib::LocalizedString

Create a complete name from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (RelatonBib::LocalizedString)

    The complete name.



571
572
573
574
575
# File 'lib/relaton_doi/parser.rb', line 571

def completename(person)
  return unless person["name"]

  RelatonBib::LocalizedString.new(person["name"], "en", "Latn")
end

#contribs_from_parent(contribs) ⇒ Array<RelatonBib::ContributionInfo>

Fetch authors and editors from parent if they are not present in the book part.

Parameters:

  • contribs (Array<RelatonBib::ContributionInfo>)

    present contributors

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    contributors with authors and editors from parent



372
373
374
375
376
377
378
379
380
# File 'lib/relaton_doi/parser.rb', line 372

def contribs_from_parent(contribs) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
  return [] unless %w[inbook inproceedings dataset].include?(parse_type) && @src["container-title"]

  has_authors = contribs.any? { |c| c.role&.any? { |r| r.type == "author" } }
  has_editors = contribs.any? { |c| c.role&.any? { |r| r.type == "editor" } }
  return [] if has_authors && has_editors

  create_authors_editors(has_authors, "author")
end

#contributor(entity, type, descriprion = nil) ⇒ RelatonBib::ContributionInfo

Create contributor from an entity and a role type.

Parameters:

  • entity (RelatonBib::Person, RelatonBib::Organization)

    The entity.

  • type (String)

    The role type.

Returns:

  • (RelatonBib::ContributionInfo)

    The contributor.



482
483
484
485
486
# File 'lib/relaton_doi/parser.rb', line 482

def contributor(entity, type, descriprion = nil)
  role = { type: type }
  role[:description] = [descriprion] if descriprion
  RelatonBib::ContributionInfo.new(entity: entity, role: [role])
end

#create_affiliation(person) ⇒ Array<RelatonBib::Affiliation>

Create person affiliations from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (Array<RelatonBib::Affiliation>)

    The affiliations.



510
511
512
513
514
515
# File 'lib/relaton_doi/parser.rb', line 510

def create_affiliation(person)
  (person["affiliation"] || []).map do |a|
    org = RelatonBib::Organization.new(name: a["name"])
    RelatonBib::Affiliation.new organization: org
  end
end

#create_authors_editors(has, type) ⇒ Array<RelatonBib::ContributionInfo>

Create authors and editors from parent item.

Parameters:

  • has (Boolean)

    true if authors or editors are present in the book part

  • type (String)

    “author” or “editor”

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    authors or editors



405
406
407
408
409
# File 'lib/relaton_doi/parser.rb', line 405

def create_authors_editors(has, type)
  return [] if has || !parent_item

  RelatonBib.array(parent_item[type]).map { |a| contributor(create_person(a), type) }
end

#create_bibitem(doi, bibitem) ⇒ RelatonBib::BibliographicItem, ...

Create a bibitem from the bibitem hash.

Parameters:

  • doi (String)

    The DOI.

  • bibitem (Hash)

    The bibitem hash.

Returns:

  • (RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem, RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliographicItem)

    The bibitem.



120
121
122
123
124
125
126
127
128
# File 'lib/relaton_doi/parser.rb', line 120

def create_bibitem(doi, bibitem) # rubocop:disable Metrics/CyclomaticComplexity
  case doi
  when /\/nist/ then RelatonNist::NistBibliographicItem.new(**bibitem)
  when /\/rfc\d+/ then RelatonIetf::IetfBibliographicItem.new(**bibitem)
  when /\/0026-1394\// then RelatonBipm::BipmBibliographicItem.new(**bibitem)
  when /\/ieee/ then RelatonIeee::IeeeBibliographicItem.new(**bibitem)
  else RelatonBib::BibliographicItem.new(**bibitem)
  end
end

#create_enabler(name) ⇒ RelatonBib::ContributionInfo

Create enabler contributor with type “enabler”.

Parameters:

  • name (String)

    <description>

Returns:

  • (RelatonBib::ContributionInfo)

    The enabler contributor.



469
470
471
472
# File 'lib/relaton_doi/parser.rb', line 469

def create_enabler(name)
  org = RelatonBib::Organization.new name: name
  contributor(org, "enabler")
end

#create_investigators(project, type) ⇒ Array<RelatonBib::ContributionInfo>

Create investigators from the project.

Parameters:

  • project (Hash)

    The project hash.

  • type (String)

    The investigator type. “lead-investigator” or “investigator”.

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    The investigators.



340
341
342
343
344
345
# File 'lib/relaton_doi/parser.rb', line 340

def create_investigators(project, type)
  description = type.gsub("-", " ")
  RelatonBib.array(project[type]).map do |inv|
    contributor(create_person(inv), "author", description)
  end
end

#create_person(person) ⇒ RelatonBib::Person

Create a person from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (RelatonBib::Person)

    The person.



495
496
497
498
499
500
501
# File 'lib/relaton_doi/parser.rb', line 495

def create_person(person)
  RelatonBib::Person.new(
    name: create_person_name(person),
    affiliation: create_affiliation(person),
    identifier: person_id(person),
  )
end

#create_person_name(person) ⇒ RelatonBib::FullName

Create a person full name from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (RelatonBib::FullName)

    The full name.



524
525
526
527
528
529
530
531
# File 'lib/relaton_doi/parser.rb', line 524

def create_person_name(person)
  surname = titlecase(person["family"])
  sn = RelatonBib::LocalizedString.new(surname, "en", "Latn")
  RelatonBib::FullName.new(
    surname: sn, forename: forename(person), addition: nameaddition(person),
    completename: completename(person), prefix: nameprefix(person)
  )
end

#create_title(title, type = "main") ⇒ RelatonBib::TypedTitleString

Create a title from the title and type.

Parameters:

  • title (String)

    The title content.

  • type (String) (defaults to: "main")

    The title type. Defaults to “main”.

Returns:

  • (RelatonBib::TypedTitleString)

    The title.



204
205
206
207
# File 'lib/relaton_doi/parser.rb', line 204

def create_title(title, type = "main")
  cnt = str_cleanup title
  RelatonBib::TypedTitleString.new type: type, content: cnt, script: "Latn"
end

#date_type(type) ⇒ String

Join date parts into a string.

Parameters:

  • type (String)

    The date type.

Returns:

  • (String)

    The date string.



263
264
265
# File 'lib/relaton_doi/parser.rb', line 263

def date_type(type)
  @src[type]["date-parts"][0].map { |d| d.to_s.rjust(2, "0") }.join "-"
end

#fetch_locationString?

Fetch location from container.

Returns:

  • (String, nil)

    The location.



647
648
649
650
651
652
653
654
655
656
657
# File 'lib/relaton_doi/parser.rb', line 647

def fetch_location # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
  title = @item[:title].first&.title&.content
  qparts = [title, fetch_year, @src["publisher"]]
  query = CGI.escape qparts.compact.join("+").gsub(" ", "+")
  filter = "type:#{%w[book-chapter book-part book-section book-track].join(',type:')}"
  resp = Faraday.get "https://api.crossref.org/works?query=#{query}&filter=#{filter}"
  json = JSON.parse resp.body
  json["message"]["items"].detect do |i|
    i["publisher-location"] && i["container-title"].include?(title)
  end&.dig("publisher-location")
end

#fetch_yearString

Fetch year from the source hash.

Returns:

  • (String)

    The year.



717
718
719
720
# File 'lib/relaton_doi/parser.rb', line 717

def fetch_year
  d = @src["published"] || @src["approved"] || @src["created"]
  d["date-parts"][0][0]
end

#forename(person) ⇒ Array<RelatonBib::LocalizedString>

Create a forename from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (Array<RelatonBib::LocalizedString>)

    The forename.



584
585
586
587
588
589
# File 'lib/relaton_doi/parser.rb', line 584

def forename(person)
  return [] unless person["given"]

  fname = titlecase(person["given"])
  [RelatonBib::Forename.new(content: fname, language: "en", script: "Latn")]
end

#included_in_relationArray<RelatonBib::DocumentRelation>

Create included in relation.

Returns:

  • (Array<RelatonBib::DocumentRelation>)

    The relations.



698
699
700
701
702
703
704
705
706
707
708
709
710
# File 'lib/relaton_doi/parser.rb', line 698

def included_in_relation
  types = %w[
    book book-chapter book-part book-section book-track dataset journal-issue
    journal-value proceedings-article reference-entry report-component
  ]
  return [] unless @src["container-title"] && types.include?(@src["type"])

  @src["container-title"].map do |ct|
    contrib = create_authors_editors false, "editor"
    bib = RelatonBib::BibliographicItem.new(title: [content: ct], contributor: contrib)
    RelatonBib::DocumentRelation.new(type: "includedIn", bibitem: bib)
  end
end

#issn_type(type, id) ⇒ String

Create an ISSN type if it’s an ISSN ID.

Parameters:

  • type (String)

    identifier type

  • id (String)

    identifier

Returns:

  • (String)

    identifier type



232
233
234
235
236
237
# File 'lib/relaton_doi/parser.rb', line 232

def issn_type(type, id)
  return type unless type == "ISSN"

  t = @src["issn-type"]&.find { |it| it["value"] == id }&.dig("type")
  t ? "issn.#{t}" : type.downcase
end

#main_sub_titlesArray<Hash>

Parse main and subtitle from the source hash.

Returns:

  • (Array<Hash>)

    The titles.



178
179
180
181
182
183
# File 'lib/relaton_doi/parser.rb', line 178

def main_sub_titles
  title = @src["title"].map { |t| create_title t }
  RelatonBib.array(@src["subtitle"]).each { |t| title << create_title(t, "subtitle") }
  RelatonBib.array(@src["short-title"]).each { |t| title << create_title(t, "short") }
  title
end

#nameaddition(person) ⇒ Array<RelatonBib::LocalizedString>

Create an addition from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (Array<RelatonBib::LocalizedString>)

    The addition.



598
599
600
601
602
# File 'lib/relaton_doi/parser.rb', line 598

def nameaddition(person)
  return [] unless person["suffix"]

  [RelatonBib::LocalizedString.new(person["suffix"], "en", "Latn")]
end

#nameprefix(person) ⇒ Array<RelatonBib::LocalizedString>

Create a person name prefix from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (Array<RelatonBib::LocalizedString>)

    The name prefix.



558
559
560
561
562
# File 'lib/relaton_doi/parser.rb', line 558

def nameprefix(person)
  return [] unless person["prefix"]

  [RelatonBib::LocalizedString.new(person["prefix"], "en", "Latn")]
end

#org_aurhorizerArray<RelatonBib::ContributionInfo>

Parse authorizer contributor from the source hash.

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    The authorizer contributor.



441
442
443
444
445
446
447
# File 'lib/relaton_doi/parser.rb', line 441

def org_aurhorizer
  return [] unless @src["standards-body"]

  name, acronym = @src["standards-body"].values_at("name", "acronym")
  org = RelatonBib::Organization.new name: name, abbreviation: acronym
  [contributor(org, "authorizer")]
end

#org_enablerArray<RelatonBib::ContributionInfo>

Parse enabler contributor from the source hash.

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    The enabler contributor.



454
455
456
457
458
459
460
# File 'lib/relaton_doi/parser.rb', line 454

def org_enabler
  RelatonBib.array(@src["project"]).each_with_object([]) do |proj, memo|
    proj["funding"].each do |f|
      memo << create_enabler(f.dig("funder", "name"))
    end
  end + RelatonBib.array(@src["funder"]).map { |f| create_enabler f["name"] }
end

#org_publisherRelatonBib::Organization

Cerate an organization publisher from the source hash.

Returns:

  • (RelatonBib::Organization)

    The organization.



416
417
418
419
420
421
422
423
# File 'lib/relaton_doi/parser.rb', line 416

def org_publisher
  pbr = @src["institution"]&.detect do |i|
    @src["publisher"].include?(i["name"]) ||
      i["name"].include?(@src["publisher"])
  end
  a = pbr["acronym"]&.first if pbr
  RelatonBib::Organization.new name: str_cleanup(@src["publisher"]), abbreviation: a
end

#parent_itemHash?

Fetch parent item from Crossref.

Returns:

  • (Hash, nil)

    parent item



387
388
389
390
391
392
393
394
395
# File 'lib/relaton_doi/parser.rb', line 387

def parent_item # rubocop:disable Metrics/AbcSize
  @parent_item ||= begin
    query = [@src["container-title"][0], fetch_year].compact.join "+"
    filter = "type:#{%w[book book-set edited-book monograph reference-book].join ',type:'}"
    resp = Faraday.get "https://api.crossref.org/works?query=#{query}&filter=#{filter}"
    json = JSON.parse resp.body
    json["message"]["items"].detect { |i| i["title"].include? @src["container-title"][0] }
  end
end

#parseRelatonBib::BibliographicItem, ...

Parse the source hash.

Returns:

  • (RelatonBib::BibliographicItem, RelatonIetf::IetfBibliographicItem, RelatonBipm::BipmBibliographicItem, RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliographicItem)

    The bibitem.



105
106
107
108
# File 'lib/relaton_doi/parser.rb', line 105

def parse
  ATTRS.each { |m| @item[m] = send "parse_#{m}" }
  create_bibitem @src["DOI"], @item
end

#parse_abstractArray<RelatonBib::FormattedString>

Parse abstract from the source hash.

Returns:

  • (Array<RelatonBib::FormattedString>)

    The abstract.



296
297
298
299
300
301
302
303
304
# File 'lib/relaton_doi/parser.rb', line 296

def parse_abstract
  return [] unless @src["abstract"]

  content = @src["abstract"]
  abstract = RelatonBib::FormattedString.new(
    content: content, language: "en", script: "Latn", format: "text/html",
  )
  [abstract]
end

#parse_contributorArray<RelatonBib::ContributionInfo>

Parse contributors from the source hash.

Returns:

  • (Array<RelatonBib::ContributionInfo>)

    The contributors.



311
312
313
314
315
316
317
318
# File 'lib/relaton_doi/parser.rb', line 311

def parse_contributor
  contribs = author_investigators
  contribs += authors_editors_translators
  contribs += contribs_from_parent(contribs)
  contribs << contributor(org_publisher, "publisher")
  contribs += org_aurhorizer
  contribs + org_enabler
end

#parse_dateArray<RelatonBib::BibliographicDate>

Parce dates from the source hash.

Returns:

  • (Array<RelatonBib::BibliographicDate>)

    The dates.



244
245
246
247
248
249
250
251
252
253
254
# File 'lib/relaton_doi/parser.rb', line 244

def parse_date # rubocop:disable Metrics/CyclomaticComplexity
  dates = %w[issued published approved].each_with_object([]) do |type, obj|
    next unless @src.dig(type, "date-parts")&.first&.compact&.any?

    obj << RelatonBib::BibliographicDate.new(type: type, on: date_type(type))
  end
  if dates.none?
    dates << RelatonBib::BibliographicDate.new(type: "created", on: date_type("created"))
  end
  dates
end

#parse_docidArray<RelatonBib::DocumentIdentifier>

Parse a docid from the source hash.

Returns:

  • (Array<RelatonBib::DocumentIdentifier>)

    The docid.



214
215
216
217
218
219
220
221
222
# File 'lib/relaton_doi/parser.rb', line 214

def parse_docid
  %w[DOI ISBN ISSN].each_with_object([]) do |type, obj|
    prm = type == "DOI"
    RelatonBib.array(@src[type]).each do |id|
      t = issn_type(type, id)
      obj << RelatonBib::DocumentIdentifier.new(type: t, id: id, primary: prm)
    end
  end
end

#parse_doctypeString

Parse the document type

Returns:

  • (String)

    The document type.



144
145
146
# File 'lib/relaton_doi/parser.rb', line 144

def parse_doctype
  RelatonBib::DocumentType.new type: @src["type"]
end

#parse_extentArray<RelatonBib::Locality>

Parse an extent from the source hash.

Returns:

  • (Array<RelatonBib::Locality>)

    The extent.



727
728
729
730
731
732
733
734
735
736
# File 'lib/relaton_doi/parser.rb', line 727

def parse_extent # rubocop:disable Metrics/AbcSize
  extent = []
  extent << RelatonBib::Locality.new("volume", @src["volume"]) if @src["volume"]
  extent << RelatonBib::Locality.new("issue", @src["issue"]) if @src["issue"]
  if @src["page"]
    from, to = @src["page"].split("-")
    extent << RelatonBib::Locality.new("page", from, to)
  end
  extent.any? ? [RelatonBib::LocalityStack.new(extent)] : []
end

#parse_fetchedString

Parse the fetched date.

Returns:

  • (String)

    The fetched date.



153
154
155
# File 'lib/relaton_doi/parser.rb', line 153

def parse_fetched
  Date.today.to_s
end

Parse links from the source hash.

Returns:

  • (Array<RelatonBib::TypedUri>)

    The links.



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/relaton_doi/parser.rb', line 272

def parse_link # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
  disprefered_links = %w[similarity-checking text-mining]
  links = []
  if @src["URL"]
    links << RelatonBib::TypedUri.new(type: "DOI", content: @src["URL"])
  end
  [@src["link"], @src.dig("resource", "primary")].flatten.compact.each do |l|
    next if disprefered_links.include? l["intended-application"]

    type =  case l["URL"]
            when /\.pdf$/ then "pdf"
            # when /\/rfc\d+$|iopscience\.iop\.org|ieeexplore\.ieee\.org/
            else "src"
            end
    links << RelatonBib::TypedUri.new(type: type, content: l["URL"]) # if type
  end
  links
end

#parse_mediumRelatonBib::Mediub?

Parse a medium from the source hash.

Returns:

  • (RelatonBib::Mediub, nil)

    The medium.



766
767
768
769
770
771
# File 'lib/relaton_doi/parser.rb', line 766

def parse_medium
  genre = @src["degree"]&.first
  return unless genre

  RelatonBib::Medium.new genre: genre
end

#parse_placeArray<RelatonBib::Place>

Parse a place from the source hash.

Returns:

  • (Array<RelatonBib::Place>)

    The place.



622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
# File 'lib/relaton_doi/parser.rb', line 622

def parse_place # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
  pub_location = @src["publisher-location"] || fetch_location
  return [] unless pub_location

  pls1, pls2 = pub_location.split(", ")
  pls1 = str_cleanup pls1
  pls2 &&= str_cleanup pls2
  if COUNTRIES.include? pls2
    country = RelatonBib::Place::RegionType.new(name: pls2)
    [RelatonBib::Place.new(city: pls1, country: [country])]
  elsif pls2 && pls2 == pls2&.upcase
    region = RelatonBib::Place::RegionType.new(name: pls2)
    [RelatonBib::Place.new(city: pls1, region: [region])]
  elsif pls1 == pls2 || pls2.nil? || pls2.empty?
    [RelatonBib::Place.new(city: pls1)]
  else
    [RelatonBib::Place.new(city: pls1), RelatonBib::Place.new(city: pls2)]
  end
end

#parse_relationArray<RelatonBib::DocumentRelation>

Parse relations from the source hash.

Returns:

  • (Array<RelatonBib::DocumentRelation>)

    The relations.



664
665
666
667
668
669
670
671
672
673
674
675
676
# File 'lib/relaton_doi/parser.rb', line 664

def parse_relation # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  rels = included_in_relation
  @src["relation"].each_with_object(rels) do |(k, v), a|
    type, desc = relation_type k
    RelatonBib.array(v).each do |r|
      rel_item = Crossref.get_by_id r["id"]
      title = rel_item["title"].map { |t| create_title t }
      docid = RelatonBib::DocumentIdentifier.new(id: r["id"], type: "DOI")
      bib = create_bibitem r["id"], title: title, docid: [docid]
      a << RelatonBib::DocumentRelation.new(type: type, description: desc, bibitem: bib)
    end
  end
end

#parse_seriesArrey<RelatonBib::Series>

Parse a series from the source hash.

Returns:

  • (Arrey<RelatonBib::Series>)

    The series.



743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
# File 'lib/relaton_doi/parser.rb', line 743

def parse_series # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
  types = %w[inbook incollection inproceedings]
  return [] if !@src["container-title"] || types.include?(@item[:type]) || @src["type"] == "report-component"

  con_ttl = if main_sub_titles.any? || project_titles.any?
              @src["container-title"]
            elsif @src["container-title"].size > 1
              sct = @src["short-container-title"]&.last
              abbrev = RelatonBib::LocalizedString.new sct if sct
              @src["container-title"][-1..-1]
            else []
            end
  con_ttl.map do |ct|
    title = RelatonBib::TypedTitleString.new content: ct
    RelatonBib::Series.new title: title, abbreviation: abbrev
  end
end

#parse_titleArray<Hash>

Parse titles from the source hash.

Returns:

  • (Array<Hash>)

    The titles.



162
163
164
165
166
167
168
169
170
171
# File 'lib/relaton_doi/parser.rb', line 162

def parse_title # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
  if @src["title"].is_a?(Array) && @src["title"].any?
    main_sub_titles
  elsif @src["project"].is_a?(Array) && @src["project"].any?
    project_titles
  elsif @src["container-title"].is_a?(Array) && @src["container-title"].size > 1
    @src["container-title"][0..-2].map { |t| create_title t }
  else []
  end
end

#parse_typeString

Parse the type.

Returns:

  • (String)

    The type.



135
136
137
# File 'lib/relaton_doi/parser.rb', line 135

def parse_type
  TYPES[@src["type"]] || @src["type"]
end

#person_id(person) ⇒ Array<RelatonBib::PersonIdentifier>

Create a person identifier from a person hash.

Parameters:

  • person (Hash)

    The person hash.

Returns:

  • (Array<RelatonBib::PersonIdentifier>)

    The person identifier.



611
612
613
614
615
# File 'lib/relaton_doi/parser.rb', line 611

def person_id(person)
  return [] unless person["ORCID"]

  [RelatonBib::PersonIdentifier.new("orcid", person["ORCID"])]
end

#project_titlesArray<Hash>

Fetch titles from the projects.

Returns:

  • (Array<Hash>)

    The titles.



190
191
192
193
194
# File 'lib/relaton_doi/parser.rb', line 190

def project_titles
  RelatonBib.array(@src["project"]).reduce([]) do |memo, proj|
    memo + RelatonBib.array(proj["project-title"]).map { |t| create_title t["title"] }
  end
end

#relation_type(crtype) ⇒ Array<String>

Transform crossref relation type to relaton relation type.

Parameters:

  • crtype (String)

    The crossref relation type.

Returns:

  • (Array<String>)

    The relaton relation type and description.



685
686
687
688
689
690
691
# File 'lib/relaton_doi/parser.rb', line 685

def relation_type(crtype)
  type = REALATION_TYPES[crtype] || begin
    desc = RelatonBib::FormattedString.new(content: crtype)
    "related"
  end
  [type, desc]
end

#str_cleanup(str) ⇒ String

Clean up trailing punctuation and whitespace from a string.

Parameters:

  • str (String)

    The string to clean up.

Returns:

  • (String)

    The cleaned up string.



432
433
434
# File 'lib/relaton_doi/parser.rb', line 432

def str_cleanup(str)
  str.strip.sub(/[,\/\s]+$/, "").sub(/\s:$/, "")
end

#titlecase(str) ⇒ <Type>

Capitalize the first letter of each word in a string except for words that

are 2 letters or less.

Parameters:

  • str (<Type>)

    <description>

Returns:

  • (<Type>)

    <description>



541
542
543
544
545
546
547
548
549
# File 'lib/relaton_doi/parser.rb', line 541

def titlecase(str)
  str.split.map do |s|
    if s.size > 2 && s.upcase == s && !/\.&/.match?(s)
      s.capitalize
    else
      s
    end
  end.join " "
end