Class: Relaton::Doi::Parser
- Inherits:
-
Object
- Object
- Relaton::Doi::Parser
- 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 docidentifier date source abstract contributor place ext relation extent series medium].freeze
- CROSSREF_API_URL =
"https://api.crossref.org/works?query=%{query}&filter=%{filter}".freeze
- MAX_RETRIES =
3
Class Method Summary collapse
-
.parse(src) ⇒ Bib::ItemData
Initialize instance and parse the source hash.
Instance Method Summary collapse
-
#author_investigators ⇒ Array<Bib::Contributor>
Create authors investigators from the source hash.
-
#authors_editors_translators ⇒ Array<Bib::Contributor>
Create authors editors translators from the source hash.
-
#completename(person) ⇒ Bib::LocalizedString
Create a complete name from a person hash.
-
#contribs_from_parent(contribs) ⇒ Array<Bib::Contributor>
Fetch authors and editors from parent if they are not present in the book part.
-
#contributor(entity, type, descriprion = nil) ⇒ Bib::Contributor
Create contributor from an entity and a role type.
-
#create_affiliation(person) ⇒ Array<Bib::Affiliation>
Create person affiliations from a person hash.
-
#create_authors_editors(has, type) ⇒ Array<Bib::Contributor>
Create authors and editors from parent item.
-
#create_bibitem(doi, bibitem) ⇒ Bib::ItemData
Create a bibitem from the bibitem hash.
-
#create_enabler(name) ⇒ Bib::Contributor
Create enabler contributor with type “enabler”.
-
#create_investigators(project, type) ⇒ Array<Bib::Contributor>
Create investigators from the project.
-
#create_org(name, abbreviation = nil) ⇒ Bib::Organization
Create an organization with properly typed name and abbreviation.
-
#create_person(person) ⇒ Bib::Person
Create a person from a person hash.
-
#create_person_name(person) ⇒ Bib::FullName
Create a person full name from a person hash.
-
#create_title(title, type = "main") ⇒ Bib::Title
Create a title from the title and type.
-
#date_type(type) ⇒ String
Join date parts into a string.
-
#fetch_crossref(query:, filter:) ⇒ Array<Hash>?
Fetch data from Crossref API with retry logic.
-
#fetch_location ⇒ String?
Fetch location from container.
-
#fetch_year ⇒ String
Fetch year from the source hash.
-
#forename(person) ⇒ Array<Bib::FullNameType::Forename>
Create a forename from a person hash.
-
#included_in_relation ⇒ Array<Bib::Relation>
Create included in relation.
-
#initialize(src) ⇒ Parser
constructor
Initialize instance.
-
#issn_type(type, id) ⇒ String
Create an ISSN type if it’s an ISSN ID.
-
#main_sub_titles ⇒ Array<Bib::Title>
Parse main and subtitle from the source hash.
-
#nameaddition(person) ⇒ Array<Bib::LocalizedString>
Create an addition from a person hash.
-
#nameprefix(person) ⇒ Array<Bib::LocalizedString>
Create a person name prefix from a person hash.
-
#org_aurhorizer ⇒ Array<Bib::Contributor>
Parse authorizer contributor from the source hash.
-
#org_enabler ⇒ Array<Bib::Contributor>
Parse enabler contributor from the source hash.
-
#org_publisher ⇒ Bib::Organization
Cerate an organization publisher from the source hash.
-
#parent_item ⇒ Hash?
Fetch parent item from Crossref.
-
#parse ⇒ Bib::ItemData
Parse the source hash.
-
#parse_abstract ⇒ Array<Bib::LocalizedMarkedUpString>
Parse abstract from the source hash.
-
#parse_contributor ⇒ Array<Bib::Contributor>
Parse contributors from the source hash.
-
#parse_date ⇒ Array<Bib::Date>
Parce dates from the source hash.
-
#parse_docidentifier ⇒ Array<Bib::Docidentifier>
Parse a docidentifier from the source hash.
-
#parse_ext ⇒ Bib::Ext
Parse the ext element with doctype.
-
#parse_extent ⇒ Array<Bib::Extent>
Parse an extent from the source hash.
-
#parse_fetched ⇒ String
Parse the fetched date.
-
#parse_medium ⇒ Bib::Medium?
Parse a medium from the source hash.
-
#parse_place ⇒ Array<Bib::Place>
Parse a place from the source hash.
-
#parse_relation ⇒ Array<Bib::Relation>
Parse relations from the source hash.
-
#parse_series ⇒ Array<Bib::Series>
Parse a series from the source hash.
-
#parse_source ⇒ Array<Bib::Uri>
Parse source URIs from the source hash.
-
#parse_title ⇒ Array<Bib::Title>
Parse titles from the source hash.
-
#parse_type ⇒ String
Parse the type.
-
#person_id(person) ⇒ Array<Bib::Person::Identifier>
Create a person identifier from a person hash.
-
#project_titles ⇒ Array<Bib::Title>
Fetch titles from the projects.
-
#relation_type(crtype) ⇒ Array<String>
Transform crossref relation type to relaton relation type.
-
#str_cleanup(str) ⇒ String
Clean up trailing punctuation and whitespace from a string.
-
#titlecase(str) ⇒ <Type>
Capitalize the first letter of each word in a string except for words that are 2 letters or less.
Constructor Details
#initialize(src) ⇒ Parser
Initialize instance.
84 85 86 87 |
# File 'lib/relaton/doi/parser.rb', line 84 def initialize(src) @src = src @item = {} end |
Class Method Details
.parse(src) ⇒ Bib::ItemData
Initialize instance and parse the source hash.
96 97 98 |
# File 'lib/relaton/doi/parser.rb', line 96 def self.parse(src) new(src).parse end |
Instance Method Details
#author_investigators ⇒ Array<Bib::Contributor>
Create authors investigators from the source hash.
332 333 334 335 336 337 |
# File 'lib/relaton/doi/parser.rb', line 332 def Array(@src["project"]).reduce([]) do |memo, proj| memo + create_investigators(proj, "lead-investigator") + create_investigators(proj, "investigator") end end |
#authors_editors_translators ⇒ Array<Bib::Contributor>
Create authors editors translators from the source hash.
359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'lib/relaton/doi/parser.rb', line 359 def %w[author editor translator].each_with_object([]) do |type, a| @src[type]&.each do |c| contrib = if c["family"] create_person(c) else create_org(str_cleanup(c["name"])) end a << contributor(contrib, type) end end end |
#completename(person) ⇒ Bib::LocalizedString
Create a complete name from a person hash.
593 594 595 596 597 |
# File 'lib/relaton/doi/parser.rb', line 593 def completename(person) return unless person["name"] Bib::LocalizedString.new(content: person["name"], language: "en", script: "Latn") end |
#contribs_from_parent(contribs) ⇒ Array<Bib::Contributor>
Fetch authors and editors from parent if they are not present in the book part.
379 380 381 382 383 384 385 386 387 |
# File 'lib/relaton/doi/parser.rb', line 379 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"] = 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_editors (, "author") end |
#contributor(entity, type, descriprion = nil) ⇒ Bib::Contributor
Create contributor from an entity and a role type.
501 502 503 504 505 506 507 508 509 |
# File 'lib/relaton/doi/parser.rb', line 501 def contributor(entity, type, descriprion = nil) desc = descriprion ? [Bib::LocalizedMarkedUpString.new(content: descriprion)] : nil role = [Bib::Contributor::Role.new(type: type, description: desc)] if entity.is_a?(Bib::Person) Bib::Contributor.new(role: role, person: entity) else Bib::Contributor.new(role: role, organization: entity) end end |
#create_affiliation(person) ⇒ Array<Bib::Affiliation>
Create person affiliations from a person hash.
533 534 535 536 537 |
# File 'lib/relaton/doi/parser.rb', line 533 def create_affiliation(person) (person["affiliation"] || []).map do |a| Bib::Affiliation.new organization: create_org(a["name"]) end end |
#create_authors_editors(has, type) ⇒ Array<Bib::Contributor>
Create authors and editors from parent item.
411 412 413 414 415 |
# File 'lib/relaton/doi/parser.rb', line 411 def (has, type) return [] if has || !parent_item Array(parent_item[type]).map { |a| contributor(create_person(a), type) } end |
#create_bibitem(doi, bibitem) ⇒ Bib::ItemData
Create a bibitem from the bibitem hash.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/relaton/doi/parser.rb', line 118 def create_bibitem(doi, bibitem) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength doctype_content = @src["type"] case doi when /\/nist/ bibitem[:ext] = Nist::Ext.new(doctype: Nist::Doctype.new(content: doctype_content)) Nist::ItemData.new(**bibitem) when /\/rfc\d+/ bibitem[:ext] = Ietf::Ext.new(doctype: Ietf::Doctype.new(content: doctype_content)) Ietf::ItemData.new(**bibitem) when /\/0026-1394\// bibitem[:ext] = Bipm::Ext.new(doctype: Bipm::Doctype.new(content: doctype_content)) Bipm::ItemData.new(**bibitem) when /\/ieee/ bibitem[:ext] = Ieee::Ext.new(doctype: Ieee::Doctype.new(content: doctype_content)) Ieee::ItemData.new(**bibitem) else Bib::ItemData.new(**bibitem) end end |
#create_enabler(name) ⇒ Bib::Contributor
Create enabler contributor with type “enabler”.
489 490 491 |
# File 'lib/relaton/doi/parser.rb', line 489 def create_enabler(name) contributor(create_org(name), "enabler") end |
#create_investigators(project, type) ⇒ Array<Bib::Contributor>
Create investigators from the project.
347 348 349 350 351 352 |
# File 'lib/relaton/doi/parser.rb', line 347 def create_investigators(project, type) description = type.gsub("-", " ") Array(project[type]).map do |inv| contributor(create_person(inv), "author", description) end end |
#create_org(name, abbreviation = nil) ⇒ Bib::Organization
Create an organization with properly typed name and abbreviation.
450 451 452 453 454 |
# File 'lib/relaton/doi/parser.rb', line 450 def create_org(name, abbreviation = nil) n = [Bib::TypedLocalizedString.new(content: name)] a = abbreviation ? Bib::LocalizedString.new(content: abbreviation) : nil Bib::Organization.new name: n, abbreviation: a end |
#create_person(person) ⇒ Bib::Person
Create a person from a person hash.
518 519 520 521 522 523 524 |
# File 'lib/relaton/doi/parser.rb', line 518 def create_person(person) Bib::Person.new( name: create_person_name(person), affiliation: create_affiliation(person), identifier: person_id(person), ) end |
#create_person_name(person) ⇒ Bib::FullName
Create a person full name from a person hash.
546 547 548 549 550 551 552 553 |
# File 'lib/relaton/doi/parser.rb', line 546 def create_person_name(person) surname = titlecase(person["family"]) sn = Bib::LocalizedString.new(content: surname, language: "en", script: "Latn") Bib::FullName.new( surname: sn, forename: forename(person), addition: nameaddition(person), completename: completename(person), prefix: nameprefix(person) ) end |
#create_title(title, type = "main") ⇒ Bib::Title
Create a title from the title and type.
211 212 213 214 |
# File 'lib/relaton/doi/parser.rb', line 211 def create_title(title, type = "main") cnt = str_cleanup title Bib::Title.new type: type, content: cnt, script: "Latn" end |
#date_type(type) ⇒ String
Join date parts into a string.
270 271 272 |
# File 'lib/relaton/doi/parser.rb', line 270 def date_type(type) @src[type]["date-parts"][0].map { |d| d.to_s.rjust(2, "0") }.join "-" end |
#fetch_crossref(query:, filter:) ⇒ Array<Hash>?
Fetch data from Crossref API with retry logic.
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 |
# File 'lib/relaton/doi/parser.rb', line 804 def fetch_crossref(query:, filter:) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength url = format(CROSSREF_API_URL, query: query, filter: filter) retries = 0 begin resp = Crossref.agent.get url JSON.parse(resp.body).dig("message", "items") rescue Mechanize::ResponseCodeError => e return nil if e.response_code.start_with?("4") raise Relaton::RequestError, "Crossref request failed: #{e.response_code} #{e.page.body}" rescue Net::HTTP::Persistent::Error, Net::HTTPError, Errno::ECONNREFUSED => e retries += 1 retry if retries <= MAX_RETRIES raise Relaton::RequestError, "Crossref network error after #{MAX_RETRIES} retries: #{e.}" rescue JSON::ParserError => e raise Relaton::RequestError, "Crossref JSON parsing error: #{e.}" end end |
#fetch_location ⇒ String?
Fetch location from container.
669 670 671 672 673 674 675 676 677 678 |
# File 'lib/relaton/doi/parser.rb', line 669 def fetch_location title = @item[:title].first&.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:')}" items = fetch_crossref(query: query, filter: filter) items&.detect do |i| i["publisher-location"] && i["container-title"].include?(title) end&.dig("publisher-location") end |
#fetch_year ⇒ String
Fetch year from the source hash.
738 739 740 741 |
# File 'lib/relaton/doi/parser.rb', line 738 def fetch_year d = @src["published"] || @src["approved"] || @src["created"] d["date-parts"][0][0] end |
#forename(person) ⇒ Array<Bib::FullNameType::Forename>
Create a forename from a person hash.
606 607 608 609 610 611 |
# File 'lib/relaton/doi/parser.rb', line 606 def forename(person) return [] unless person["given"] fname = titlecase(person["given"]) [Bib::FullNameType::Forename.new(content: fname, language: "en", script: "Latn")] end |
#included_in_relation ⇒ Array<Bib::Relation>
Create included in relation.
719 720 721 722 723 724 725 726 727 728 729 730 731 |
# File 'lib/relaton/doi/parser.rb', line 719 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 = false, "editor" bib = Bib::ItemBase.new(title: [Bib::Title.new(content: ct)], contributor: contrib) Bib::Relation.new(type: "includedIn", bibitem: bib) end end |
#issn_type(type, id) ⇒ String
Create an ISSN type if it’s an ISSN ID.
239 240 241 242 243 244 |
# File 'lib/relaton/doi/parser.rb', line 239 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_titles ⇒ Array<Bib::Title>
Parse main and subtitle from the source hash.
185 186 187 188 189 190 |
# File 'lib/relaton/doi/parser.rb', line 185 def main_sub_titles title = @src["title"].map { |t| create_title t } Array(@src["subtitle"]).each { |t| title << create_title(t, "subtitle") } Array(@src["short-title"]).each { |t| title << create_title(t, "short") } title end |
#nameaddition(person) ⇒ Array<Bib::LocalizedString>
Create an addition from a person hash.
620 621 622 623 624 |
# File 'lib/relaton/doi/parser.rb', line 620 def nameaddition(person) return [] unless person["suffix"] [Bib::LocalizedString.new(content: person["suffix"], language: "en", script: "Latn")] end |
#nameprefix(person) ⇒ Array<Bib::LocalizedString>
Create a person name prefix from a person hash.
580 581 582 583 584 |
# File 'lib/relaton/doi/parser.rb', line 580 def nameprefix(person) return [] unless person["prefix"] [Bib::LocalizedString.new(content: person["prefix"], language: "en", script: "Latn")] end |
#org_aurhorizer ⇒ Array<Bib::Contributor>
Parse authorizer contributor from the source hash.
461 462 463 464 465 466 467 |
# File 'lib/relaton/doi/parser.rb', line 461 def org_aurhorizer return [] unless @src["standards-body"] name, acronym = @src["standards-body"].values_at("name", "acronym") org = create_org(name, acronym) [contributor(org, "authorizer")] end |
#org_enabler ⇒ Array<Bib::Contributor>
Parse enabler contributor from the source hash.
474 475 476 477 478 479 480 |
# File 'lib/relaton/doi/parser.rb', line 474 def org_enabler Array(@src["project"]).each_with_object([]) do |proj, memo| proj["funding"].each do |f| memo << create_enabler(f.dig("funder", "name")) end end + Array(@src["funder"]).map { |f| create_enabler f["name"] } end |
#org_publisher ⇒ Bib::Organization
Cerate an organization publisher from the source hash.
422 423 424 425 426 427 428 429 |
# File 'lib/relaton/doi/parser.rb', line 422 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 create_org(str_cleanup(@src["publisher"]), a) end |
#parent_item ⇒ Hash?
Fetch parent item from Crossref.
394 395 396 397 398 399 400 401 |
# File 'lib/relaton/doi/parser.rb', line 394 def parent_item @parent_item ||= begin query = CGI.escape [@src["container-title"][0], fetch_year].compact.join("+") filter = "type:#{%w[book book-set edited-book monograph reference-book].join ',type:'}" items = fetch_crossref(query: query, filter: filter) items&.detect { |i| i["title"].include? @src["container-title"][0] } end end |
#parse ⇒ Bib::ItemData
Parse the source hash.
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_abstract ⇒ Array<Bib::LocalizedMarkedUpString>
Parse abstract from the source hash.
303 304 305 306 307 308 309 310 311 |
# File 'lib/relaton/doi/parser.rb', line 303 def parse_abstract return [] unless @src["abstract"] content = @src["abstract"] abstract = Bib::Abstract.new( content: content, language: "en", script: "Latn", ) [abstract] end |
#parse_contributor ⇒ Array<Bib::Contributor>
Parse contributors from the source hash.
318 319 320 321 322 323 324 325 |
# File 'lib/relaton/doi/parser.rb', line 318 def parse_contributor contribs = contribs += contribs += contribs_from_parent(contribs) contribs << contributor(org_publisher, "publisher") contribs += org_aurhorizer contribs + org_enabler end |
#parse_date ⇒ Array<Bib::Date>
Parce dates from the source hash.
251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/relaton/doi/parser.rb', line 251 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 << Bib::Date.new(type: type, at: date_type(type)) end if dates.none? dates << Bib::Date.new(type: "created", at: date_type("created")) end dates end |
#parse_docidentifier ⇒ Array<Bib::Docidentifier>
Parse a docidentifier from the source hash.
221 222 223 224 225 226 227 228 229 |
# File 'lib/relaton/doi/parser.rb', line 221 def parse_docidentifier %w[DOI ISBN ISSN].each_with_object([]) do |type, obj| prm = type == "DOI" Array(@src[type]).each do |id| t = issn_type(type, id) obj << Bib::Docidentifier.new(type: t, content: id, primary: prm) end end end |
#parse_ext ⇒ Bib::Ext
Parse the ext element with doctype.
151 152 153 |
# File 'lib/relaton/doi/parser.rb', line 151 def parse_ext Bib::Ext.new doctype: Bib::Doctype.new(content: @src["type"]) end |
#parse_extent ⇒ Array<Bib::Extent>
Parse an extent from the source hash.
748 749 750 751 752 753 754 755 756 757 |
# File 'lib/relaton/doi/parser.rb', line 748 def parse_extent # rubocop:disable Metrics/AbcSize extent = [] extent << Bib::Locality.new(type: "volume", reference_from: @src["volume"]) if @src["volume"] extent << Bib::Locality.new(type: "issue", reference_from: @src["issue"]) if @src["issue"] if @src["page"] from, to = @src["page"].split("-") extent << Bib::Locality.new(type: "page", reference_from: from, reference_to: to) end extent.any? ? [Bib::Extent.new(locality: extent)] : [] end |
#parse_fetched ⇒ String
Parse the fetched date.
160 161 162 |
# File 'lib/relaton/doi/parser.rb', line 160 def parse_fetched Date.today.to_s end |
#parse_medium ⇒ Bib::Medium?
Parse a medium from the source hash.
787 788 789 790 791 792 |
# File 'lib/relaton/doi/parser.rb', line 787 def parse_medium genre = @src["degree"]&.first return unless genre Bib::Medium.new genre: genre end |
#parse_place ⇒ Array<Bib::Place>
Parse a place from the source hash.
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 |
# File 'lib/relaton/doi/parser.rb', line 644 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 = Bib::Place::RegionType.new(content: pls2) [Bib::Place.new(city: pls1, country: [country])] elsif pls2 && pls2 == pls2&.upcase region = Bib::Place::RegionType.new(content: pls2) [Bib::Place.new(city: pls1, region: [region])] elsif pls1 == pls2 || pls2.nil? || pls2.empty? [Bib::Place.new(city: pls1)] else [Bib::Place.new(city: pls1), Bib::Place.new(city: pls2)] end end |
#parse_relation ⇒ Array<Bib::Relation>
Parse relations from the source hash.
685 686 687 688 689 690 691 692 693 694 695 696 697 |
# File 'lib/relaton/doi/parser.rb', line 685 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 Array(v).each do |r| rel_item = Crossref.get_by_id r["id"] title = rel_item["title"].map { |t| create_title t } docid = Bib::Docidentifier.new(content: r["id"], type: "DOI") bib = create_bibitem r["id"], title: title, docidentifier: [docid] a << Bib::Relation.new(type: type, description: desc, bibitem: bib) end end end |
#parse_series ⇒ Array<Bib::Series>
Parse a series from the source hash.
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 |
# File 'lib/relaton/doi/parser.rb', line 764 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 = Bib::LocalizedString.new(content: sct) if sct @src["container-title"][-1..-1] else [] end con_ttl.map do |ct| title = Bib::Title.new content: ct Bib::Series.new title: [title], abbreviation: abbrev end end |
#parse_source ⇒ Array<Bib::Uri>
Parse source URIs from the source hash.
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/relaton/doi/parser.rb', line 279 def parse_source # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity disprefered_links = %w[similarity-checking text-mining] links = [] if @src["URL"] links << Bib::Uri.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 << Bib::Uri.new(type: type, content: l["URL"]) # if type end links end |
#parse_title ⇒ Array<Bib::Title>
Parse titles from the source hash.
169 170 171 172 173 174 175 176 177 178 |
# File 'lib/relaton/doi/parser.rb', line 169 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_type ⇒ String
Parse the type.
142 143 144 |
# File 'lib/relaton/doi/parser.rb', line 142 def parse_type TYPES[@src["type"]] || @src["type"] end |
#person_id(person) ⇒ Array<Bib::Person::Identifier>
Create a person identifier from a person hash.
633 634 635 636 637 |
# File 'lib/relaton/doi/parser.rb', line 633 def person_id(person) return [] unless person["ORCID"] [Bib::Person::Identifier.new(type: "orcid", content: person["ORCID"])] end |
#project_titles ⇒ Array<Bib::Title>
Fetch titles from the projects.
197 198 199 200 201 |
# File 'lib/relaton/doi/parser.rb', line 197 def project_titles Array(@src["project"]).reduce([]) do |memo, proj| memo + 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.
706 707 708 709 710 711 712 |
# File 'lib/relaton/doi/parser.rb', line 706 def relation_type(crtype) type = REALATION_TYPES[crtype] || begin desc = Bib::LocalizedMarkedUpString.new(content: crtype) "related" end [type, desc] end |
#str_cleanup(str) ⇒ String
Clean up trailing punctuation and whitespace from a string.
438 439 440 |
# File 'lib/relaton/doi/parser.rb', line 438 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.
563 564 565 566 567 568 569 570 571 |
# File 'lib/relaton/doi/parser.rb', line 563 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 |