relaton 2.2.0.pre.alpha.1 → 3.0.0.pre.alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/{docs/README.adoc → README.adoc} +165 -38
- data/bin/console +0 -1
- data/lib/relaton/3gpp/bibdata.rb +9 -0
- data/lib/relaton/3gpp/bibitem.rb +9 -0
- data/lib/relaton/3gpp/bibliography.rb +123 -0
- data/lib/relaton/3gpp/data_fetcher.rb +303 -0
- data/lib/relaton/3gpp/docidentifier.rb +114 -0
- data/lib/relaton/3gpp/doctype.rb +9 -0
- data/lib/relaton/3gpp/ext.rb +31 -0
- data/lib/relaton/3gpp/item.rb +18 -0
- data/lib/relaton/3gpp/item_data.rb +15 -0
- data/lib/relaton/3gpp/parser.rb +400 -0
- data/lib/relaton/3gpp/processor.rb +71 -0
- data/lib/relaton/3gpp/release.rb +34 -0
- data/lib/relaton/3gpp/util.rb +8 -0
- data/lib/relaton/3gpp.rb +29 -0
- data/lib/relaton/adobe/bibdata.rb +8 -0
- data/lib/relaton/adobe/bibitem.rb +8 -0
- data/lib/relaton/adobe/bibliography.rb +92 -0
- data/lib/relaton/adobe/docidentifier.rb +49 -0
- data/lib/relaton/adobe/doctype.rb +14 -0
- data/lib/relaton/adobe/ext.rb +32 -0
- data/lib/relaton/adobe/item.rb +15 -0
- data/lib/relaton/adobe/item_base.rb +18 -0
- data/lib/relaton/adobe/item_data.rb +6 -0
- data/lib/relaton/adobe/processor.rb +45 -0
- data/lib/relaton/adobe/util.rb +8 -0
- data/lib/relaton/adobe.rb +37 -0
- data/lib/relaton/bib/converter/asciibib/to_asciibib.rb +663 -0
- data/lib/relaton/bib/converter/asciibib.rb +13 -0
- data/lib/relaton/bib/converter/bibtex/from_bibtex.rb +245 -0
- data/lib/relaton/bib/converter/bibtex/to_bibtex.rb +341 -0
- data/lib/relaton/bib/converter/bibtex.rb +23 -0
- data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +386 -0
- data/lib/relaton/bib/converter/bibxml/from_rfcxml_referencegroup.rb +71 -0
- data/lib/relaton/bib/converter/bibxml/to_rfcxml.rb +308 -0
- data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +52 -0
- data/lib/relaton/bib/converter/bibxml.rb +51 -0
- data/lib/relaton/bib/hash_parser_v1.rb +767 -0
- data/lib/relaton/bib/item_data.rb +229 -0
- data/lib/relaton/bib/model/abstract.rb +16 -0
- data/lib/relaton/bib/model/address.rb +22 -0
- data/lib/relaton/bib/model/affiliation.rb +16 -0
- data/lib/relaton/bib/model/bibdata.rb +11 -0
- data/lib/relaton/bib/model/bibdata_shared.rb +12 -0
- data/lib/relaton/bib/model/bibitem.rb +11 -0
- data/lib/relaton/bib/model/bibitem_shared.rb +12 -0
- data/lib/relaton/bib/model/contact.rb +18 -0
- data/lib/relaton/bib/model/contribution_info.rb +15 -0
- data/lib/relaton/bib/model/contributor.rb +29 -0
- data/lib/relaton/bib/model/copyright.rb +27 -0
- data/lib/relaton/bib/model/date.rb +31 -0
- data/lib/relaton/bib/model/depiction.rb +16 -0
- data/lib/relaton/bib/model/docidentifier.rb +49 -0
- data/lib/relaton/bib/model/doctype.rb +14 -0
- data/lib/relaton/bib/model/edition.rb +14 -0
- data/lib/relaton/bib/model/ext.rb +39 -0
- data/lib/relaton/bib/model/extent.rb +16 -0
- data/lib/relaton/bib/model/formattedref.rb +43 -0
- data/lib/relaton/bib/model/full_name_type.rb +64 -0
- data/lib/relaton/bib/model/fullname.rb +11 -0
- data/lib/relaton/bib/model/ics.rb +49 -0
- data/lib/relaton/bib/model/image.rb +28 -0
- data/lib/relaton/bib/model/item.rb +96 -0
- data/lib/relaton/bib/model/item_base.rb +20 -0
- data/lib/relaton/bib/model/item_shared.rb +88 -0
- data/lib/relaton/bib/model/keyword.rb +30 -0
- data/lib/relaton/bib/model/locality.rb +18 -0
- data/lib/relaton/bib/model/locality_stack.rb +14 -0
- data/lib/relaton/bib/model/localized_string.rb +48 -0
- data/lib/relaton/bib/model/localized_string_attrs.rb +24 -0
- data/lib/relaton/bib/model/logo.rb +14 -0
- data/lib/relaton/bib/model/medium.rb +22 -0
- data/lib/relaton/bib/model/note.rb +16 -0
- data/lib/relaton/bib/model/organization.rb +13 -0
- data/lib/relaton/bib/model/organization_type.rb +42 -0
- data/lib/relaton/bib/model/person.rb +36 -0
- data/lib/relaton/bib/model/phone.rb +14 -0
- data/lib/relaton/bib/model/place.rb +33 -0
- data/lib/relaton/bib/model/price.rb +14 -0
- data/lib/relaton/bib/model/relation.rb +43 -0
- data/lib/relaton/bib/model/series.rb +34 -0
- data/lib/relaton/bib/model/size.rb +23 -0
- data/lib/relaton/bib/model/source_locality_stack.rb +14 -0
- data/lib/relaton/bib/model/status.rb +27 -0
- data/lib/relaton/bib/model/structured_identifier.rb +49 -0
- data/lib/relaton/bib/model/subdivision.rb +16 -0
- data/lib/relaton/bib/model/title.rb +56 -0
- data/lib/relaton/bib/model/type/plain_date.rb +16 -0
- data/lib/relaton/bib/model/type/string_date.rb +48 -0
- data/lib/relaton/bib/model/uri.rb +18 -0
- data/lib/relaton/bib/model/validity.rb +16 -0
- data/lib/relaton/bib/model/version.rb +43 -0
- data/lib/relaton/bib/namespace_helper.rb +21 -0
- data/lib/relaton/bib/sanitizer.rb +264 -0
- data/lib/relaton/bib/util.rb +18 -0
- data/lib/relaton/bib/versions.json +35 -0
- data/lib/relaton/bib.rb +46 -0
- data/lib/relaton/bipm/bibliography.rb +231 -0
- data/lib/relaton/bipm/converter/asciibib.rb +64 -0
- data/lib/relaton/bipm/data_fetcher.rb +81 -0
- data/lib/relaton/bipm/data_outcomes_parser.rb +656 -0
- data/lib/relaton/bipm/id_parser.rb +278 -0
- data/lib/relaton/bipm/item_data.rb +47 -0
- data/lib/relaton/bipm/model/bibdata.rb +9 -0
- data/lib/relaton/bipm/model/bibitem.rb +9 -0
- data/lib/relaton/bipm/model/comment_period.rb +13 -0
- data/lib/relaton/bipm/model/doctype.rb +12 -0
- data/lib/relaton/bipm/model/ext.rb +38 -0
- data/lib/relaton/bipm/model/item.rb +11 -0
- data/lib/relaton/bipm/model/structured_identifier.rb +36 -0
- data/lib/relaton/bipm/processor.rb +69 -0
- data/lib/relaton/bipm/rawdata_bipm_metrologia/affiliations.rb +111 -0
- data/lib/relaton/bipm/rawdata_bipm_metrologia/fetcher.rb +172 -0
- data/lib/relaton/bipm/rawdata_bipm_metrologia/niso_jats_parser.rb +353 -0
- data/lib/relaton/bipm/si_brochure_parser.rb +188 -0
- data/lib/relaton/bipm/util.rb +8 -0
- data/lib/relaton/bipm.rb +38 -0
- data/lib/relaton/bsi/bibliography.rb +196 -0
- data/lib/relaton/bsi/hit.rb +28 -0
- data/lib/relaton/bsi/hit_collection.rb +113 -0
- data/lib/relaton/bsi/item_data.rb +13 -0
- data/lib/relaton/bsi/model/bibdata.rb +8 -0
- data/lib/relaton/bsi/model/bibitem.rb +8 -0
- data/lib/relaton/bsi/model/docidentifier.rb +107 -0
- data/lib/relaton/bsi/model/doctype.rb +14 -0
- data/lib/relaton/bsi/model/ext.rb +17 -0
- data/lib/relaton/bsi/model/item.rb +17 -0
- data/lib/relaton/bsi/model/item_base.rb +22 -0
- data/lib/relaton/bsi/model/relation.rb +9 -0
- data/lib/relaton/bsi/processor.rb +43 -0
- data/lib/relaton/bsi/schema.json +24882 -0
- data/lib/relaton/bsi/scraper.rb +288 -0
- data/lib/relaton/bsi/util.rb +8 -0
- data/lib/relaton/bsi.rb +25 -0
- data/lib/relaton/calconnect/bibliography.rb +93 -0
- data/lib/relaton/calconnect/data_fetcher.rb +174 -0
- data/lib/relaton/calconnect/docidentifier.rb +80 -0
- data/lib/relaton/calconnect/hit.rb +14 -0
- data/lib/relaton/calconnect/hit_collection.rb +92 -0
- data/lib/relaton/calconnect/item_data.rb +12 -0
- data/lib/relaton/calconnect/model/bibdata.rb +8 -0
- data/lib/relaton/calconnect/model/bibitem.rb +8 -0
- data/lib/relaton/calconnect/model/doctype.rb +11 -0
- data/lib/relaton/calconnect/model/ext.rb +11 -0
- data/lib/relaton/calconnect/model/item.rb +20 -0
- data/lib/relaton/calconnect/processor.rb +72 -0
- data/lib/relaton/calconnect/scraper.rb +87 -0
- data/lib/relaton/calconnect/util.rb +8 -0
- data/lib/relaton/calconnect.rb +36 -0
- data/lib/relaton/ccsds/bibliography.rb +63 -0
- data/lib/relaton/ccsds/data/fetcher.rb +252 -0
- data/lib/relaton/ccsds/data/iso_references.rb +30 -0
- data/lib/relaton/ccsds/data/parser.rb +194 -0
- data/lib/relaton/ccsds/hit.rb +24 -0
- data/lib/relaton/ccsds/hit_collection.rb +47 -0
- data/lib/relaton/ccsds/item_data.rb +9 -0
- data/lib/relaton/ccsds/model/bibdata.rb +8 -0
- data/lib/relaton/ccsds/model/bibitem.rb +8 -0
- data/lib/relaton/ccsds/model/docidentifier.rb +121 -0
- data/lib/relaton/ccsds/model/doctype.rb +9 -0
- data/lib/relaton/ccsds/model/ext.rb +19 -0
- data/lib/relaton/ccsds/model/item.rb +15 -0
- data/lib/relaton/ccsds/processor.rb +68 -0
- data/lib/relaton/ccsds/util.rb +10 -0
- data/lib/relaton/ccsds.rb +33 -0
- data/lib/relaton/cen/bibliography.rb +149 -0
- data/lib/relaton/cen/committees.yaml +66 -0
- data/lib/relaton/cen/hit.rb +31 -0
- data/lib/relaton/cen/hit_collection.rb +116 -0
- data/lib/relaton/cen/item_data.rb +7 -0
- data/lib/relaton/cen/model/bibdata.rb +8 -0
- data/lib/relaton/cen/model/bibitem.rb +8 -0
- data/lib/relaton/cen/model/docidentifier.rb +100 -0
- data/lib/relaton/cen/model/ext.rb +11 -0
- data/lib/relaton/cen/model/item.rb +14 -0
- data/lib/relaton/cen/model/structured_identifier.rb +9 -0
- data/lib/relaton/cen/processor.rb +45 -0
- data/lib/relaton/cen/scraper.rb +218 -0
- data/lib/relaton/cen/util.rb +8 -0
- data/lib/relaton/cen.rb +30 -0
- data/lib/relaton/cie/bibdata.rb +8 -0
- data/lib/relaton/cie/bibitem.rb +8 -0
- data/lib/relaton/cie/bibliography.rb +31 -0
- data/lib/relaton/cie/data_fetcher.rb +540 -0
- data/lib/relaton/cie/ext.rb +7 -0
- data/lib/relaton/cie/item.rb +11 -0
- data/lib/relaton/cie/item_data.rb +6 -0
- data/lib/relaton/cie/processor.rb +68 -0
- data/lib/relaton/cie/scrapper.rb +52 -0
- data/lib/relaton/cie/util.rb +8 -0
- data/lib/relaton/cie.rb +29 -0
- data/lib/relaton/core/array_wrapper.rb +20 -0
- data/lib/relaton/core/data_fetcher.rb +244 -0
- data/lib/relaton/core/date_parser.rb +42 -0
- data/lib/relaton/core/governor.rb +320 -0
- data/lib/relaton/core/hash_keys_sybolizer.rb +19 -0
- data/lib/relaton/core/hit.rb +49 -0
- data/lib/relaton/core/hit_collection.rb +118 -0
- data/lib/relaton/core/pacer.rb +134 -0
- data/lib/relaton/core/processor.rb +67 -0
- data/lib/relaton/core/request_error.rb +14 -0
- data/lib/relaton/core/workers_pool.rb +45 -0
- data/lib/relaton/core.rb +12 -0
- data/lib/relaton/db/registry.rb +44 -4
- data/lib/relaton/db.rb +0 -1
- data/lib/relaton/doi/crossref.rb +89 -0
- data/lib/relaton/doi/parser.rb +921 -0
- data/lib/relaton/doi/processor.rb +65 -0
- data/lib/relaton/doi/util.rb +8 -0
- data/lib/relaton/doi.rb +20 -0
- data/lib/relaton/easc/bibdata.rb +8 -0
- data/lib/relaton/easc/bibitem.rb +8 -0
- data/lib/relaton/easc/bibliography.rb +95 -0
- data/lib/relaton/easc/docidentifier.rb +100 -0
- data/lib/relaton/easc/doctype.rb +14 -0
- data/lib/relaton/easc/ext.rb +44 -0
- data/lib/relaton/easc/item.rb +13 -0
- data/lib/relaton/easc/item_base.rb +18 -0
- data/lib/relaton/easc/item_data.rb +6 -0
- data/lib/relaton/easc/processor.rb +46 -0
- data/lib/relaton/easc/util.rb +8 -0
- data/lib/relaton/easc.rb +35 -0
- data/lib/relaton/ecma/bibdata.rb +8 -0
- data/lib/relaton/ecma/bibitem.rb +8 -0
- data/lib/relaton/ecma/bibliography.rb +149 -0
- data/lib/relaton/ecma/data_fetcher.rb +162 -0
- data/lib/relaton/ecma/data_parser.rb +49 -0
- data/lib/relaton/ecma/docidentifier.rb +124 -0
- data/lib/relaton/ecma/edition_parser.rb +80 -0
- data/lib/relaton/ecma/ext.rb +7 -0
- data/lib/relaton/ecma/item.rb +13 -0
- data/lib/relaton/ecma/item_data.rb +6 -0
- data/lib/relaton/ecma/memento_parser.rb +60 -0
- data/lib/relaton/ecma/page_fetcher.rb +39 -0
- data/lib/relaton/ecma/parser_common.rb +33 -0
- data/lib/relaton/ecma/processor.rb +69 -0
- data/lib/relaton/ecma/standard_parser.rb +134 -0
- data/lib/relaton/ecma/util.rb +8 -0
- data/lib/relaton/ecma.rb +33 -0
- data/lib/relaton/etsi/bibdata.rb +10 -0
- data/lib/relaton/etsi/bibitem.rb +10 -0
- data/lib/relaton/etsi/bibliography.rb +111 -0
- data/lib/relaton/etsi/data_fetcher.rb +167 -0
- data/lib/relaton/etsi/data_parser.rb +208 -0
- data/lib/relaton/etsi/doctype.rb +30 -0
- data/lib/relaton/etsi/ext.rb +31 -0
- data/lib/relaton/etsi/item.rb +15 -0
- data/lib/relaton/etsi/item_data.rb +6 -0
- data/lib/relaton/etsi/processor.rb +71 -0
- data/lib/relaton/etsi/pubid.rb +37 -0
- data/lib/relaton/etsi/status.rb +13 -0
- data/lib/relaton/etsi/util.rb +8 -0
- data/lib/relaton/etsi.rb +26 -0
- data/lib/relaton/gb/bibdata.rb +8 -0
- data/lib/relaton/gb/bibitem.rb +8 -0
- data/lib/relaton/gb/bibliography.rb +171 -0
- data/lib/relaton/gb/ccs.rb +14 -0
- data/lib/relaton/gb/committee.rb +13 -0
- data/lib/relaton/gb/docidentifier.rb +72 -0
- data/lib/relaton/gb/doctype.rb +9 -0
- data/lib/relaton/gb/ext.rb +36 -0
- data/lib/relaton/gb/gb_scraper.rb +61 -0
- data/lib/relaton/gb/gb_type.rb +20 -0
- data/lib/relaton/gb/hit.rb +48 -0
- data/lib/relaton/gb/hit_collection.rb +19 -0
- data/lib/relaton/gb/item.rb +13 -0
- data/lib/relaton/gb/item_data.rb +6 -0
- data/lib/relaton/gb/processor.rb +49 -0
- data/lib/relaton/gb/project_number.rb +38 -0
- data/lib/relaton/gb/scraper.rb +221 -0
- data/lib/relaton/gb/sec_scraper.rb +92 -0
- data/lib/relaton/gb/stage_name.rb +13 -0
- data/lib/relaton/gb/structured_identifier.rb +26 -0
- data/lib/relaton/gb/t_scraper.rb +126 -0
- data/lib/relaton/gb/util.rb +8 -0
- data/lib/relaton/gb/yaml/prefixes.yaml +200 -0
- data/lib/relaton/gb.rb +33 -0
- data/lib/relaton/gost/bibdata.rb +8 -0
- data/lib/relaton/gost/bibitem.rb +8 -0
- data/lib/relaton/gost/bibliography.rb +107 -0
- data/lib/relaton/gost/docidentifier.rb +80 -0
- data/lib/relaton/gost/doctype.rb +16 -0
- data/lib/relaton/gost/ext.rb +46 -0
- data/lib/relaton/gost/item.rb +15 -0
- data/lib/relaton/gost/item_base.rb +18 -0
- data/lib/relaton/gost/item_data.rb +6 -0
- data/lib/relaton/gost/processor.rb +49 -0
- data/lib/relaton/gost/util.rb +8 -0
- data/lib/relaton/gost.rb +36 -0
- data/lib/relaton/iala/bibdata.rb +8 -0
- data/lib/relaton/iala/bibitem.rb +8 -0
- data/lib/relaton/iala/bibliography.rb +146 -0
- data/lib/relaton/iala/docidentifier.rb +89 -0
- data/lib/relaton/iala/doctype.rb +18 -0
- data/lib/relaton/iala/ext.rb +32 -0
- data/lib/relaton/iala/item.rb +21 -0
- data/lib/relaton/iala/item_base.rb +18 -0
- data/lib/relaton/iala/item_data.rb +6 -0
- data/lib/relaton/iala/processor.rb +43 -0
- data/lib/relaton/iala/relation.rb +7 -0
- data/lib/relaton/iala/util.rb +8 -0
- data/lib/relaton/iala.rb +35 -0
- data/lib/relaton/iana/bibdata.rb +8 -0
- data/lib/relaton/iana/bibitem.rb +8 -0
- data/lib/relaton/iana/bibliography.rb +100 -0
- data/lib/relaton/iana/data_fetcher.rb +101 -0
- data/lib/relaton/iana/item.rb +7 -0
- data/lib/relaton/iana/item_data.rb +6 -0
- data/lib/relaton/iana/parser.rb +146 -0
- data/lib/relaton/iana/processor.rb +70 -0
- data/lib/relaton/iana/util.rb +8 -0
- data/lib/relaton/iana.rb +40 -0
- data/lib/relaton/iec/bibliography.rb +283 -0
- data/lib/relaton/iec/data_fetcher.rb +222 -0
- data/lib/relaton/iec/data_parser.rb +391 -0
- data/lib/relaton/iec/hit.rb +26 -0
- data/lib/relaton/iec/hit_collection.rb +138 -0
- data/lib/relaton/iec/item_data.rb +7 -0
- data/lib/relaton/iec/model/bibdata.rb +8 -0
- data/lib/relaton/iec/model/bibitem.rb +8 -0
- data/lib/relaton/iec/model/docidentifier.rb +135 -0
- data/lib/relaton/iec/model/doctype.rb +12 -0
- data/lib/relaton/iec/model/ext.rb +53 -0
- data/lib/relaton/iec/model/item.rb +20 -0
- data/lib/relaton/iec/model/item_base.rb +12 -0
- data/lib/relaton/iec/model/relation.rb +7 -0
- data/lib/relaton/iec/model/stage_name.rb +13 -0
- data/lib/relaton/iec/processor.rb +74 -0
- data/lib/relaton/iec/statuses.yml +199 -0
- data/lib/relaton/iec/util.rb +8 -0
- data/lib/relaton/iec.rb +98 -0
- data/lib/relaton/ieee/balloting_group.rb +13 -0
- data/lib/relaton/ieee/bibdata.rb +8 -0
- data/lib/relaton/ieee/bibitem.rb +8 -0
- data/lib/relaton/ieee/bibliography.rb +73 -0
- data/lib/relaton/ieee/converter/bibxml/from_rfcxml.rb +10 -0
- data/lib/relaton/ieee/converter/bibxml/from_rfcxml_referencegroup.rb +10 -0
- data/lib/relaton/ieee/converter/bibxml.rb +20 -0
- data/lib/relaton/ieee/data_fetcher.rb +771 -0
- data/lib/relaton/ieee/doctype.rb +9 -0
- data/lib/relaton/ieee/editorial_group.rb +19 -0
- data/lib/relaton/ieee/ext.rb +36 -0
- data/lib/relaton/ieee/idams_parser.rb +330 -0
- data/lib/relaton/ieee/item.rb +11 -0
- data/lib/relaton/ieee/item_data.rb +7 -0
- data/lib/relaton/ieee/processor.rb +71 -0
- data/lib/relaton/ieee/rawbib_id_parser.rb +753 -0
- data/lib/relaton/ieee/util.rb +8 -0
- data/lib/relaton/ieee.rb +30 -0
- data/lib/relaton/ietf/bibdata.rb +8 -0
- data/lib/relaton/ietf/bibitem.rb +8 -0
- data/lib/relaton/ietf/bibliography.rb +35 -0
- data/lib/relaton/ietf/bibxml_parser.rb +232 -0
- data/lib/relaton/ietf/data_fetcher.rb +561 -0
- data/lib/relaton/ietf/doctype.rb +9 -0
- data/lib/relaton/ietf/ext.rb +63 -0
- data/lib/relaton/ietf/item.rb +16 -0
- data/lib/relaton/ietf/item_base.rb +18 -0
- data/lib/relaton/ietf/item_data.rb +6 -0
- data/lib/relaton/ietf/processing_instructions.rb +79 -0
- data/lib/relaton/ietf/processor.rb +72 -0
- data/lib/relaton/ietf/relation.rb +9 -0
- data/lib/relaton/ietf/rfc/abstract.rb +19 -0
- data/lib/relaton/ietf/rfc/author.rb +21 -0
- data/lib/relaton/ietf/rfc/entry.rb +446 -0
- data/lib/relaton/ietf/rfc/entry_date.rb +21 -0
- data/lib/relaton/ietf/rfc/format.rb +19 -0
- data/lib/relaton/ietf/rfc/index.rb +46 -0
- data/lib/relaton/ietf/rfc/is_also.rb +21 -0
- data/lib/relaton/ietf/rfc/keywords.rb +19 -0
- data/lib/relaton/ietf/rfc/rfc_index_namespace.rb +11 -0
- data/lib/relaton/ietf/scraper.rb +101 -0
- data/lib/relaton/ietf/util.rb +8 -0
- data/lib/relaton/ietf/wg_name_resolver.rb +42 -0
- data/lib/relaton/ietf.rb +30 -0
- data/lib/relaton/iho/bibdata.rb +8 -0
- data/lib/relaton/iho/bibitem.rb +8 -0
- data/lib/relaton/iho/bibliography.rb +114 -0
- data/lib/relaton/iho/comment_period.rb +13 -0
- data/lib/relaton/iho/docidentifier.rb +31 -0
- data/lib/relaton/iho/doctype.rb +10 -0
- data/lib/relaton/iho/ext.rb +20 -0
- data/lib/relaton/iho/hash_parser_v1.rb +144 -0
- data/lib/relaton/iho/item.rb +20 -0
- data/lib/relaton/iho/item_base.rb +18 -0
- data/lib/relaton/iho/item_data.rb +6 -0
- data/lib/relaton/iho/processor.rb +54 -0
- data/lib/relaton/iho/relation.rb +9 -0
- data/lib/relaton/iho/structured_identifier.rb +20 -0
- data/lib/relaton/iho/util.rb +8 -0
- data/lib/relaton/iho.rb +27 -0
- data/lib/relaton/index/config.rb +52 -0
- data/lib/relaton/index/file_io.rb +305 -0
- data/lib/relaton/index/file_storage.rb +66 -0
- data/lib/relaton/index/pool.rb +46 -0
- data/lib/relaton/index/shard_source.rb +201 -0
- data/lib/relaton/index/type.rb +210 -0
- data/lib/relaton/index/util.rb +18 -0
- data/lib/relaton/index.rb +61 -0
- data/lib/relaton/isbn/isbn.rb +61 -0
- data/lib/relaton/isbn/open_library.rb +43 -0
- data/lib/relaton/isbn/parser.rb +88 -0
- data/lib/relaton/isbn/processor.rb +48 -0
- data/lib/relaton/isbn/util.rb +8 -0
- data/lib/relaton/isbn.rb +19 -0
- data/lib/relaton/iso/bibliography.rb +412 -0
- data/lib/relaton/iso/data_fetcher.rb +338 -0
- data/lib/relaton/iso/data_parser.rb +458 -0
- data/lib/relaton/iso/hash_parser_v1.rb +177 -0
- data/lib/relaton/iso/hit.rb +57 -0
- data/lib/relaton/iso/hit_collection.rb +196 -0
- data/lib/relaton/iso/item_data.rb +50 -0
- data/lib/relaton/iso/model/bibdata.rb +10 -0
- data/lib/relaton/iso/model/bibitem.rb +8 -0
- data/lib/relaton/iso/model/contributor.rb +6 -0
- data/lib/relaton/iso/model/contributor_info.rb +9 -0
- data/lib/relaton/iso/model/docidentifier.rb +146 -0
- data/lib/relaton/iso/model/doctype.rb +13 -0
- data/lib/relaton/iso/model/ext.rb +35 -0
- data/lib/relaton/iso/model/item.rb +17 -0
- data/lib/relaton/iso/model/item_base.rb +22 -0
- data/lib/relaton/iso/model/organization.rb +9 -0
- data/lib/relaton/iso/model/project_number.rb +22 -0
- data/lib/relaton/iso/model/relation.rb +9 -0
- data/lib/relaton/iso/model/stagename.rb +14 -0
- data/lib/relaton/iso/model/structured_identifier.rb +31 -0
- data/lib/relaton/iso/processor.rb +85 -0
- data/lib/relaton/iso/scraper.rb +635 -0
- data/lib/relaton/iso/type/pubid.rb +50 -0
- data/lib/relaton/iso/util.rb +8 -0
- data/lib/relaton/iso.rb +30 -0
- data/lib/relaton/itu/bibliography.rb +95 -0
- data/lib/relaton/itu/data_crawler_r.rb +664 -0
- data/lib/relaton/itu/data_fetcher.rb +550 -0
- data/lib/relaton/itu/data_merge_r.rb +149 -0
- data/lib/relaton/itu/data_parser_r.rb +214 -0
- data/lib/relaton/itu/data_parser_t.rb +228 -0
- data/lib/relaton/itu/family_cache.rb +177 -0
- data/lib/relaton/itu/governor.rb +56 -0
- data/lib/relaton/itu/hit.rb +28 -0
- data/lib/relaton/itu/hit_collection.rb +299 -0
- data/lib/relaton/itu/item_data.rb +6 -0
- data/lib/relaton/itu/model/approval_stage.rb +13 -0
- data/lib/relaton/itu/model/bibdata.rb +8 -0
- data/lib/relaton/itu/model/bibitem.rb +8 -0
- data/lib/relaton/itu/model/docidentifier.rb +75 -0
- data/lib/relaton/itu/model/doctype.rb +13 -0
- data/lib/relaton/itu/model/ext.rb +47 -0
- data/lib/relaton/itu/model/item.rb +13 -0
- data/lib/relaton/itu/model/meeting.rb +13 -0
- data/lib/relaton/itu/model/meeting_date.rb +15 -0
- data/lib/relaton/itu/model/question.rb +13 -0
- data/lib/relaton/itu/model/recommendation_status.rb +11 -0
- data/lib/relaton/itu/model/structured_identifier.rb +38 -0
- data/lib/relaton/itu/processor.rb +72 -0
- data/lib/relaton/itu/pubid.rb +199 -0
- data/lib/relaton/itu/radio_regulations_parser.rb +70 -0
- data/lib/relaton/itu/recommendation_fields.rb +334 -0
- data/lib/relaton/itu/recommendation_parser.rb +30 -0
- data/lib/relaton/itu/scraper.rb +203 -0
- data/lib/relaton/itu/util.rb +8 -0
- data/lib/relaton/itu.rb +34 -0
- data/lib/relaton/jcgm/bibdata.rb +8 -0
- data/lib/relaton/jcgm/bibitem.rb +8 -0
- data/lib/relaton/jcgm/bibliography.rb +97 -0
- data/lib/relaton/jcgm/data_fetcher.rb +81 -0
- data/lib/relaton/jcgm/docidentifier.rb +102 -0
- data/lib/relaton/jcgm/doctype.rb +12 -0
- data/lib/relaton/jcgm/ext.rb +23 -0
- data/lib/relaton/jcgm/item.rb +20 -0
- data/lib/relaton/jcgm/item_base.rb +18 -0
- data/lib/relaton/jcgm/item_data.rb +6 -0
- data/lib/relaton/jcgm/meetings_parser.rb +175 -0
- data/lib/relaton/jcgm/processor.rb +71 -0
- data/lib/relaton/jcgm/relation.rb +9 -0
- data/lib/relaton/jcgm/structured_identifier.rb +40 -0
- data/lib/relaton/jcgm/util.rb +8 -0
- data/lib/relaton/jcgm.rb +24 -0
- data/lib/relaton/jis/bibdata.rb +8 -0
- data/lib/relaton/jis/bibitem.rb +8 -0
- data/lib/relaton/jis/bibliography.rb +73 -0
- data/lib/relaton/jis/data_fetcher.rb +183 -0
- data/lib/relaton/jis/docidentifier.rb +120 -0
- data/lib/relaton/jis/doctype.rb +9 -0
- data/lib/relaton/jis/ext.rb +13 -0
- data/lib/relaton/jis/hit.rb +88 -0
- data/lib/relaton/jis/hit_collection.rb +128 -0
- data/lib/relaton/jis/item.rb +22 -0
- data/lib/relaton/jis/item_base.rb +26 -0
- data/lib/relaton/jis/item_data.rb +8 -0
- data/lib/relaton/jis/processor.rb +55 -0
- data/lib/relaton/jis/relation.rb +11 -0
- data/lib/relaton/jis/scraper.rb +232 -0
- data/lib/relaton/jis/structured_identifier.rb +13 -0
- data/lib/relaton/jis/util.rb +8 -0
- data/lib/relaton/jis.rb +32 -0
- data/lib/relaton/logger/channels/gh_issue.rb +143 -0
- data/lib/relaton/logger/config.rb +34 -0
- data/lib/relaton/logger/formatter_json.rb +8 -0
- data/lib/relaton/logger/formatter_string.rb +12 -0
- data/lib/relaton/logger/log.rb +64 -0
- data/lib/relaton/logger/log_device.rb +27 -0
- data/lib/relaton/logger/pool.rb +24 -0
- data/lib/relaton/logger.rb +18 -0
- data/lib/relaton/nist/bibdata.rb +8 -0
- data/lib/relaton/nist/bibitem.rb +8 -0
- data/lib/relaton/nist/bibliography.rb +191 -0
- data/lib/relaton/nist/comment_period.rb +15 -0
- data/lib/relaton/nist/data_fetcher.rb +134 -0
- data/lib/relaton/nist/date.rb +7 -0
- data/lib/relaton/nist/docidentifier.rb +165 -0
- data/lib/relaton/nist/doctype.rb +7 -0
- data/lib/relaton/nist/ext.rb +16 -0
- data/lib/relaton/nist/hit.rb +18 -0
- data/lib/relaton/nist/hit_collection.rb +362 -0
- data/lib/relaton/nist/item.rb +19 -0
- data/lib/relaton/nist/item_base.rb +16 -0
- data/lib/relaton/nist/item_data.rb +6 -0
- data/lib/relaton/nist/mods_parser.rb +302 -0
- data/lib/relaton/nist/processor.rb +69 -0
- data/lib/relaton/nist/pubs_export.rb +69 -0
- data/lib/relaton/nist/relation.rb +10 -0
- data/lib/relaton/nist/scraper.rb +293 -0
- data/lib/relaton/nist/series.yaml +49 -0
- data/lib/relaton/nist/util.rb +8 -0
- data/lib/relaton/nist.rb +34 -0
- data/lib/relaton/oasis/bibdata.rb +8 -0
- data/lib/relaton/oasis/bibitem.rb +8 -0
- data/lib/relaton/oasis/bibliography.rb +201 -0
- data/lib/relaton/oasis/browser_agent.rb +71 -0
- data/lib/relaton/oasis/data_fetcher.rb +130 -0
- data/lib/relaton/oasis/data_parser.rb +305 -0
- data/lib/relaton/oasis/data_parser_utils.rb +330 -0
- data/lib/relaton/oasis/data_part_parser.rb +239 -0
- data/lib/relaton/oasis/docidentifier.rb +54 -0
- data/lib/relaton/oasis/doctype.rb +7 -0
- data/lib/relaton/oasis/ext.rb +19 -0
- data/lib/relaton/oasis/item.rb +14 -0
- data/lib/relaton/oasis/item_data.rb +6 -0
- data/lib/relaton/oasis/processor.rb +74 -0
- data/lib/relaton/oasis/util.rb +8 -0
- data/lib/relaton/oasis.rb +41 -0
- data/lib/relaton/ogc/bibdata.rb +8 -0
- data/lib/relaton/ogc/bibitem.rb +8 -0
- data/lib/relaton/ogc/bibliography.rb +64 -0
- data/lib/relaton/ogc/data_fetcher.rb +131 -0
- data/lib/relaton/ogc/docidentifier.rb +111 -0
- data/lib/relaton/ogc/doctype.rb +12 -0
- data/lib/relaton/ogc/ext.rb +15 -0
- data/lib/relaton/ogc/hit.rb +18 -0
- data/lib/relaton/ogc/hit_collection.rb +111 -0
- data/lib/relaton/ogc/item.rb +13 -0
- data/lib/relaton/ogc/item_data.rb +6 -0
- data/lib/relaton/ogc/processor.rb +59 -0
- data/lib/relaton/ogc/scraper.rb +225 -0
- data/lib/relaton/ogc/util.rb +8 -0
- data/lib/relaton/ogc.rb +30 -0
- data/lib/relaton/oiml/bibdata.rb +8 -0
- data/lib/relaton/oiml/bibitem.rb +8 -0
- data/lib/relaton/oiml/bibliography.rb +169 -0
- data/lib/relaton/oiml/docidentifier.rb +48 -0
- data/lib/relaton/oiml/doctype.rb +13 -0
- data/lib/relaton/oiml/ext.rb +42 -0
- data/lib/relaton/oiml/item.rb +20 -0
- data/lib/relaton/oiml/item_base.rb +18 -0
- data/lib/relaton/oiml/item_data.rb +6 -0
- data/lib/relaton/oiml/processor.rb +54 -0
- data/lib/relaton/oiml/relation.rb +9 -0
- data/lib/relaton/oiml/util.rb +8 -0
- data/lib/relaton/oiml.rb +24 -0
- data/lib/relaton/omg/bibdata.rb +8 -0
- data/lib/relaton/omg/bibitem.rb +8 -0
- data/lib/relaton/omg/bibliography.rb +31 -0
- data/lib/relaton/omg/docidentifier.rb +67 -0
- data/lib/relaton/omg/ext.rb +7 -0
- data/lib/relaton/omg/item.rb +9 -0
- data/lib/relaton/omg/item_data.rb +6 -0
- data/lib/relaton/omg/processor.rb +35 -0
- data/lib/relaton/omg/scraper.rb +186 -0
- data/lib/relaton/omg/util.rb +8 -0
- data/lib/relaton/omg.rb +25 -0
- data/lib/relaton/plateau/bibdata.rb +8 -0
- data/lib/relaton/plateau/bibitem.rb +8 -0
- data/lib/relaton/plateau/bibliography.rb +31 -0
- data/lib/relaton/plateau/data_fetcher.rb +176 -0
- data/lib/relaton/plateau/doctype.rb +7 -0
- data/lib/relaton/plateau/ext.rb +23 -0
- data/lib/relaton/plateau/handbook_parser.rb +102 -0
- data/lib/relaton/plateau/hit.rb +21 -0
- data/lib/relaton/plateau/hit_collection.rb +79 -0
- data/lib/relaton/plateau/item.rb +12 -0
- data/lib/relaton/plateau/item_data.rb +6 -0
- data/lib/relaton/plateau/parser.rb +101 -0
- data/lib/relaton/plateau/processor.rb +51 -0
- data/lib/relaton/plateau/technical_report_parser.rb +98 -0
- data/lib/relaton/plateau/util.rb +8 -0
- data/lib/relaton/plateau.rb +29 -0
- data/lib/relaton/sdo/config.rb +34 -0
- data/lib/relaton/sdo/fetcher.rb +52 -0
- data/lib/relaton/sdo/logo.rb +95 -0
- data/lib/relaton/sdo/name.rb +26 -0
- data/lib/relaton/sdo/organization.rb +71 -0
- data/lib/relaton/sdo/store.rb +49 -0
- data/lib/relaton/sdo.rb +29 -0
- data/lib/relaton/un/bibdata.rb +8 -0
- data/lib/relaton/un/bibitem.rb +8 -0
- data/lib/relaton/un/bibliography.rb +48 -0
- data/lib/relaton/un/doctype.rb +10 -0
- data/lib/relaton/un/ext.rb +30 -0
- data/lib/relaton/un/hit.rb +56 -0
- data/lib/relaton/un/hit_collection.rb +61 -0
- data/lib/relaton/un/item.rb +11 -0
- data/lib/relaton/un/item_data.rb +6 -0
- data/lib/relaton/un/parser.rb +108 -0
- data/lib/relaton/un/processor.rb +38 -0
- data/lib/relaton/un/session.rb +25 -0
- data/lib/relaton/un/token_generator.rb +105 -0
- data/lib/relaton/un/util.rb +8 -0
- data/lib/relaton/un/wasm/decoder.rb +434 -0
- data/lib/relaton/un/wasm/instance.rb +101 -0
- data/lib/relaton/un/wasm/interpreter.rb +613 -0
- data/lib/relaton/un/wasm/memory.rb +112 -0
- data/lib/relaton/un/wasm/module.rb +47 -0
- data/lib/relaton/un/wasm.rb +17 -0
- data/lib/relaton/un/wasm_v_bg.wasm +0 -0
- data/lib/relaton/un.rb +28 -0
- data/lib/relaton/version.rb +1 -1
- data/lib/relaton/w3c/bibdata.rb +8 -0
- data/lib/relaton/w3c/bibitem.rb +8 -0
- data/lib/relaton/w3c/bibliography.rb +174 -0
- data/lib/relaton/w3c/data_fetcher.rb +487 -0
- data/lib/relaton/w3c/data_parser.rb +379 -0
- data/lib/relaton/w3c/docidentifier.rb +48 -0
- data/lib/relaton/w3c/doctype.rb +7 -0
- data/lib/relaton/w3c/ext.rb +11 -0
- data/lib/relaton/w3c/governor.rb +32 -0
- data/lib/relaton/w3c/item.rb +15 -0
- data/lib/relaton/w3c/item_data.rb +6 -0
- data/lib/relaton/w3c/processor.rb +49 -0
- data/lib/relaton/w3c/pubid.rb +85 -0
- data/lib/relaton/w3c/safe_realize.rb +148 -0
- data/lib/relaton/w3c/util.rb +8 -0
- data/lib/relaton/w3c.rb +36 -0
- data/lib/relaton/xsf/bibdata.rb +8 -0
- data/lib/relaton/xsf/bibitem.rb +8 -0
- data/lib/relaton/xsf/bibliography.rb +84 -0
- data/lib/relaton/xsf/data_fetcher.rb +106 -0
- data/lib/relaton/xsf/docidentifier.rb +46 -0
- data/lib/relaton/xsf/hit.rb +17 -0
- data/lib/relaton/xsf/hit_collection.rb +52 -0
- data/lib/relaton/xsf/item.rb +13 -0
- data/lib/relaton/xsf/item_data.rb +6 -0
- data/lib/relaton/xsf/processor.rb +51 -0
- data/lib/relaton/xsf/util.rb +9 -0
- data/lib/relaton/xsf.rb +34 -0
- data/lib/relaton-core.rb +1 -0
- data/lib/relaton.rb +85 -0
- metadata +775 -161
- data/.github/workflows/rake.yml +0 -14
- data/.github/workflows/release.yml +0 -24
- data/.github/workflows/rubocop.yml +0 -48
- data/.gitignore +0 -12
- data/.rspec +0 -3
- data/CLAUDE.md +0 -78
- data/Gemfile +0 -29
- data/Rakefile +0 -6
- data/docs/CHANGELOG.adoc +0 -16
- data/docs/VERSIONING_POLICY.adoc +0 -38
- data/docs/navigation.adoc +0 -6
- data/lib/relaton/db/version.rb +0 -5
- data/relaton.gemspec +0 -72
- data/spec/relaton/config_spec.rb +0 -10
- data/spec/relaton/db_cache_spec.rb +0 -51
- data/spec/relaton/db_spec.rb +0 -567
- data/spec/relaton/registry_spec.rb +0 -178
- data/spec/relaton/util_spec.rb +0 -3
- data/spec/relaton_meta_spec.rb +0 -25
- data/spec/relaton_spec.rb +0 -800
- data/spec/spec_helper.rb +0 -45
- data/spec/support/gb_t_20223_2006.xml +0 -33
- data/spec/support/iso_111111119115_1.xml +0 -0
- data/spec/support/iso_19115_1.xml +0 -115
- data/spec/support/iso_19115_2.xml +0 -95
- data/spec/support/rfc_8341.xml +0 -46
- data/spec/vcr_cassetes/api_relaton_org.yml +0 -121
- data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +0 -140
- data/spec/vcr_cassetes/cc_dir_10005_2019.yml +0 -202
- data/spec/vcr_cassetes/cipm_meeting_43.yml +0 -1505
- data/spec/vcr_cassetes/gb_t_20223_2006.yml +0 -729
- data/spec/vcr_cassetes/iso_111111119115_1.yml +0 -12951
- data/spec/vcr_cassetes/iso_19115_1.yml +0 -17334
- data/spec/vcr_cassetes/iso_19115_1_2.yml +0 -322
- data/spec/vcr_cassetes/iso_19115_1_std.yml +0 -17334
- data/spec/vcr_cassetes/iso_19115_all_parts.yml +0 -185
- data/spec/vcr_cassetes/iso_19133_2005.yml +0 -144
- data/spec/vcr_cassetes/iso_combined_applied.yml +0 -318
- data/spec/vcr_cassetes/iso_combined_included.yml +0 -318
- data/spec/vcr_cassetes/ogc_19_025r1.yml +0 -374
- data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +0 -317
- data/spec/vcr_cassetes/rfc_8341.yml +0 -1278
|
@@ -0,0 +1,921 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Doi
|
|
3
|
+
class Parser
|
|
4
|
+
COUNTRIES = %w[USA].freeze
|
|
5
|
+
|
|
6
|
+
TYPES = {
|
|
7
|
+
"book-chapter" => "inbook",
|
|
8
|
+
"book-part" => "inbook",
|
|
9
|
+
"book-section" => "inbook",
|
|
10
|
+
"book-series" => "book",
|
|
11
|
+
"book-set" => "book",
|
|
12
|
+
"book-track" => "inbook",
|
|
13
|
+
"component" => "misc",
|
|
14
|
+
"database" => "dataset",
|
|
15
|
+
"dissertation" => "thesis",
|
|
16
|
+
"edited-book" => "book",
|
|
17
|
+
"grant" => "misc",
|
|
18
|
+
"journal-article" => "article",
|
|
19
|
+
"journal-issue" => "article",
|
|
20
|
+
"journal-volume" => "journal",
|
|
21
|
+
"monograph" => "book",
|
|
22
|
+
"other" => "misc",
|
|
23
|
+
"peer-review" => "article",
|
|
24
|
+
"posted-content" => "dataset",
|
|
25
|
+
"proceedings-article" => "inproceedings",
|
|
26
|
+
"proceedings-series" => "proceedings",
|
|
27
|
+
"reference-book" => "book",
|
|
28
|
+
"reference-entry" => "inbook",
|
|
29
|
+
"report-component" => "techreport",
|
|
30
|
+
"report-series" => "techreport",
|
|
31
|
+
"report" => "techreport",
|
|
32
|
+
}.freeze
|
|
33
|
+
|
|
34
|
+
REALATION_TYPES = {
|
|
35
|
+
"is-cited-by" => "isCitedIn",
|
|
36
|
+
"belongs-to" => "related",
|
|
37
|
+
"is-child-of" => "includedIn",
|
|
38
|
+
"is-expression-of" => "expressionOf",
|
|
39
|
+
"has-expression" => "hasExpression",
|
|
40
|
+
"is-manifestation-of" => "manifestationOf",
|
|
41
|
+
"is-manuscript-of" => "draftOf",
|
|
42
|
+
"has-manuscript" => "hasDraft",
|
|
43
|
+
"is-preprint-of" => "draftOf",
|
|
44
|
+
"has-preprint" => "hasDraft",
|
|
45
|
+
"is-replaced-by" => "obsoletedBy",
|
|
46
|
+
"replaces" => "obsoletes",
|
|
47
|
+
"is-translation-of" => "translatedFrom",
|
|
48
|
+
"has-translation" => "hasTranslation",
|
|
49
|
+
"is-version-of" => "editionOf",
|
|
50
|
+
"has-version" => "hasEdition",
|
|
51
|
+
"is-based-on" => "updates",
|
|
52
|
+
"is-basis-for" => "updatedBy",
|
|
53
|
+
"is-comment-on" => "commentaryOf",
|
|
54
|
+
"has-comment" => "hasCommentary",
|
|
55
|
+
"is-continued-by" => "hasSuccessor",
|
|
56
|
+
"continues" => "successorOf",
|
|
57
|
+
"is-derived-from" => "derives",
|
|
58
|
+
"has-derivation" => "derivedFrom",
|
|
59
|
+
"is-documented-by" => "describedBy",
|
|
60
|
+
"documents" => "describes",
|
|
61
|
+
"is-part-of" => "partOf",
|
|
62
|
+
"has-part" => "hasPart",
|
|
63
|
+
"is-review-of" => "reviewOf",
|
|
64
|
+
"has-review" => "hasReview",
|
|
65
|
+
"references" => "cites",
|
|
66
|
+
"is-referenced-by" => "isCitedIn",
|
|
67
|
+
"requires" => "hasComplement",
|
|
68
|
+
"is-required-by" => "complementOf",
|
|
69
|
+
"is-supplement-to" => "complementOf",
|
|
70
|
+
"is-supplemented-by" => "hasComplement",
|
|
71
|
+
}.freeze
|
|
72
|
+
|
|
73
|
+
ATTRS = %i[type fetched title docidentifier date source abstract contributor place
|
|
74
|
+
ext relation extent series medium].freeze
|
|
75
|
+
|
|
76
|
+
# Matches content that looks like markup. Same shape as the tag detector
|
|
77
|
+
# of `Relaton::Bib::Sanitizer`, so both agree on what to parse.
|
|
78
|
+
TAG_RE = %r{<[a-zA-Z/!?]}
|
|
79
|
+
|
|
80
|
+
CROSSREF_API_URL = "https://api.crossref.org/works?query=%{query}&filter=%{filter}".freeze
|
|
81
|
+
MAX_RETRIES = 3
|
|
82
|
+
RATE_LIMITED = "429".freeze
|
|
83
|
+
MAX_RETRY_DELAY = 60
|
|
84
|
+
|
|
85
|
+
#
|
|
86
|
+
# Initialize instance.
|
|
87
|
+
#
|
|
88
|
+
# @param [Hash] src The source hash.
|
|
89
|
+
#
|
|
90
|
+
def initialize(src)
|
|
91
|
+
@src = src
|
|
92
|
+
@item = {}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#
|
|
96
|
+
# Initialize instance and parse the source hash.
|
|
97
|
+
#
|
|
98
|
+
# @param [Hash] src The source hash.
|
|
99
|
+
#
|
|
100
|
+
# @return [Bib::ItemData] The bibitem.
|
|
101
|
+
#
|
|
102
|
+
def self.parse(src)
|
|
103
|
+
new(src).parse
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
#
|
|
107
|
+
# Parse the source hash.
|
|
108
|
+
#
|
|
109
|
+
# @return [Bib::ItemData] The bibitem.
|
|
110
|
+
#
|
|
111
|
+
def parse
|
|
112
|
+
ATTRS.each { |m| @item[m] = send "parse_#{m}" }
|
|
113
|
+
create_bibitem @src["DOI"], @item
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
#
|
|
117
|
+
# Create a bibitem from the bibitem hash.
|
|
118
|
+
#
|
|
119
|
+
# @param [String] doi The DOI.
|
|
120
|
+
# @param [Hash] bibitem The bibitem hash.
|
|
121
|
+
#
|
|
122
|
+
# @return [Bib::ItemData] The bibitem.
|
|
123
|
+
#
|
|
124
|
+
def create_bibitem(doi, bibitem) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
125
|
+
doctype_content = @src["type"]
|
|
126
|
+
case doi
|
|
127
|
+
when /\/nist/
|
|
128
|
+
bibitem[:ext] = Nist::Ext.new(doctype: Nist::Doctype.new(content: doctype_content))
|
|
129
|
+
Nist::ItemData.new(**bibitem)
|
|
130
|
+
when /\/rfc\d+/
|
|
131
|
+
bibitem[:ext] = Ietf::Ext.new(doctype: Ietf::Doctype.new(content: doctype_content))
|
|
132
|
+
Ietf::ItemData.new(**bibitem)
|
|
133
|
+
when /\/0026-1394\//
|
|
134
|
+
bibitem[:ext] = Bipm::Ext.new(doctype: Bipm::Doctype.new(content: doctype_content))
|
|
135
|
+
Bipm::ItemData.new(**bibitem)
|
|
136
|
+
when /\/ieee/
|
|
137
|
+
bibitem[:ext] = Ieee::Ext.new(doctype: Ieee::Doctype.new(content: doctype_content))
|
|
138
|
+
Ieee::ItemData.new(**bibitem)
|
|
139
|
+
else Bib::ItemData.new(**bibitem)
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# Parse the type.
|
|
145
|
+
#
|
|
146
|
+
# @return [String] The type.
|
|
147
|
+
#
|
|
148
|
+
def parse_type
|
|
149
|
+
TYPES[@src["type"]] || @src["type"]
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
#
|
|
153
|
+
# Parse the ext element with doctype.
|
|
154
|
+
#
|
|
155
|
+
# @return [Bib::Ext] The ext element.
|
|
156
|
+
#
|
|
157
|
+
def parse_ext
|
|
158
|
+
Bib::Ext.new doctype: Bib::Doctype.new(content: @src["type"])
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
#
|
|
162
|
+
# Parse the fetched date.
|
|
163
|
+
#
|
|
164
|
+
# @return [String] The fetched date.
|
|
165
|
+
#
|
|
166
|
+
def parse_fetched
|
|
167
|
+
Date.today.to_s
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
#
|
|
171
|
+
# Parse titles from the source hash.
|
|
172
|
+
#
|
|
173
|
+
# @return [Array<Bib::Title>] The titles.
|
|
174
|
+
#
|
|
175
|
+
def parse_title # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
176
|
+
if @src["title"].is_a?(Array) && @src["title"].any?
|
|
177
|
+
main_sub_titles
|
|
178
|
+
elsif @src["project"].is_a?(Array) && @src["project"].any?
|
|
179
|
+
project_titles
|
|
180
|
+
elsif @src["container-title"].is_a?(Array) && @src["container-title"].size > 1
|
|
181
|
+
@src["container-title"][0..-2].map { |t| create_title t }
|
|
182
|
+
else []
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
#
|
|
187
|
+
# Parse main and subtitle from the source hash.
|
|
188
|
+
#
|
|
189
|
+
# @return [Array<Bib::Title>] The titles.
|
|
190
|
+
#
|
|
191
|
+
def main_sub_titles
|
|
192
|
+
title = @src["title"].map { |t| create_title t }
|
|
193
|
+
Array(@src["subtitle"]).each { |t| title << create_title(t, "subtitle") }
|
|
194
|
+
Array(@src["short-title"]).each { |t| title << create_title(t, "short") }
|
|
195
|
+
title
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
#
|
|
199
|
+
# Fetch titles from the projects.
|
|
200
|
+
#
|
|
201
|
+
# @return [Array<Bib::Title>] The titles.
|
|
202
|
+
#
|
|
203
|
+
def project_titles
|
|
204
|
+
Array(@src["project"]).reduce([]) do |memo, proj|
|
|
205
|
+
memo + Array(proj["project-title"]).map { |t| create_title t["title"] }
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
#
|
|
210
|
+
# Create a title from the title and type.
|
|
211
|
+
#
|
|
212
|
+
# @param [String] title The title content.
|
|
213
|
+
# @param [String] type The title type. Defaults to "main".
|
|
214
|
+
#
|
|
215
|
+
# @return [Bib::Title] The title.
|
|
216
|
+
#
|
|
217
|
+
def create_title(title, type = "main")
|
|
218
|
+
cnt = str_cleanup normalize_markup(title)
|
|
219
|
+
Bib::Title.new type: type, content: cnt, script: "Latn"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
#
|
|
223
|
+
# Prepare raw Crossref markup for the relaton-bib sanitizer.
|
|
224
|
+
#
|
|
225
|
+
# Crossref returns JATS markup, and it sometimes encodes that markup as
|
|
226
|
+
# HTML entities, so decode them before the content reaches a model
|
|
227
|
+
# attribute. The markup also carries the `jats:` namespace prefix, and
|
|
228
|
+
# sometimes an `xlink:` prefix on an attribute, which Relaton never
|
|
229
|
+
# declares. Removing those prefixes is `Relaton::Bib::Sanitizer`'s job:
|
|
230
|
+
# every `Bib::Title` and `Bib::Abstract` runs the sanitizer on
|
|
231
|
+
# assignment, and it declares each undeclared prefix on a wrapper
|
|
232
|
+
# element so the markup parses and maps to the basicdoc set. An
|
|
233
|
+
# undeclared prefix that survives into the output makes
|
|
234
|
+
# relaton-render return nil, and isodoc then raises. See
|
|
235
|
+
# metanorma-pdfa#99.
|
|
236
|
+
#
|
|
237
|
+
# Upstream relaton-doi carries its own prefix removal, because the
|
|
238
|
+
# sanitizer fix is not in a released relaton-bib. Here both ship in one
|
|
239
|
+
# gem, so this method is the entity decode only.
|
|
240
|
+
#
|
|
241
|
+
# Decode only content that carries no markup of its own. Crossref
|
|
242
|
+
# escapes an ampersand and a literal angle bracket *inside* real
|
|
243
|
+
# markup, so an unconditional decode turns `<jats:p>Smith &
|
|
244
|
+
# Jones</jats:p>` into markup that no longer parses. The sanitizer
|
|
245
|
+
# would then give up on it and an unescapable string would reach the
|
|
246
|
+
# output -- the metanorma-pdfa#99 failure again, on the far more
|
|
247
|
+
# common input.
|
|
248
|
+
#
|
|
249
|
+
# @param [String, nil] str The raw Crossref content.
|
|
250
|
+
#
|
|
251
|
+
# @return [String, nil] The content, with the HTML entities decoded
|
|
252
|
+
# when it holds no markup.
|
|
253
|
+
#
|
|
254
|
+
def normalize_markup(str)
|
|
255
|
+
return str if str.nil? || str.match?(TAG_RE)
|
|
256
|
+
|
|
257
|
+
CGI.unescapeHTML(str)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
#
|
|
261
|
+
# Parse a docidentifier from the source hash.
|
|
262
|
+
#
|
|
263
|
+
# @return [Array<Bib::Docidentifier>] The docidentifier.
|
|
264
|
+
#
|
|
265
|
+
def parse_docidentifier
|
|
266
|
+
%w[DOI ISBN ISSN].each_with_object([]) do |type, obj|
|
|
267
|
+
prm = type == "DOI"
|
|
268
|
+
Array(@src[type]).each do |id|
|
|
269
|
+
t = issn_type(type, id)
|
|
270
|
+
obj << Bib::Docidentifier.new(type: t, content: id, primary: prm)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
#
|
|
276
|
+
# Create an ISSN type if it's an ISSN ID.
|
|
277
|
+
#
|
|
278
|
+
# @param [String] type identifier type
|
|
279
|
+
# @param [String] id identifier
|
|
280
|
+
#
|
|
281
|
+
# @return [String] identifier type
|
|
282
|
+
#
|
|
283
|
+
def issn_type(type, id)
|
|
284
|
+
return type unless type == "ISSN"
|
|
285
|
+
|
|
286
|
+
t = @src["issn-type"]&.find { |it| it["value"] == id }&.dig("type")
|
|
287
|
+
t ? "issn.#{t}" : type.downcase
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
#
|
|
291
|
+
# Parce dates from the source hash.
|
|
292
|
+
#
|
|
293
|
+
# @return [Array<Bib::Date>] The dates.
|
|
294
|
+
#
|
|
295
|
+
def parse_date # rubocop:disable Metrics/CyclomaticComplexity
|
|
296
|
+
dates = %w[issued published approved].each_with_object([]) do |type, obj|
|
|
297
|
+
next unless @src.dig(type, "date-parts")&.first&.compact&.any?
|
|
298
|
+
|
|
299
|
+
obj << Bib::Date.new(type: type, at: date_type(type))
|
|
300
|
+
end
|
|
301
|
+
if dates.none?
|
|
302
|
+
dates << Bib::Date.new(type: "created", at: date_type("created"))
|
|
303
|
+
end
|
|
304
|
+
dates
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
#
|
|
308
|
+
# Join date parts into a string.
|
|
309
|
+
#
|
|
310
|
+
# @param [String] type The date type.
|
|
311
|
+
#
|
|
312
|
+
# @return [String] The date string.
|
|
313
|
+
#
|
|
314
|
+
def date_type(type)
|
|
315
|
+
@src[type]["date-parts"][0].map { |d| d.to_s.rjust(2, "0") }.join "-"
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
#
|
|
319
|
+
# Parse source URIs from the source hash.
|
|
320
|
+
#
|
|
321
|
+
# @return [Array<Bib::Uri>] The source URIs.
|
|
322
|
+
#
|
|
323
|
+
def parse_source # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
|
|
324
|
+
disprefered_links = %w[similarity-checking text-mining]
|
|
325
|
+
links = []
|
|
326
|
+
if @src["URL"]
|
|
327
|
+
links << Bib::Uri.new(type: "DOI", content: @src["URL"])
|
|
328
|
+
end
|
|
329
|
+
[@src["link"], @src.dig("resource", "primary")].flatten.compact.each do |l|
|
|
330
|
+
next if disprefered_links.include? l["intended-application"]
|
|
331
|
+
|
|
332
|
+
type = case l["URL"]
|
|
333
|
+
when /\.pdf$/ then "pdf"
|
|
334
|
+
# when /\/rfc\d+$|iopscience\.iop\.org|ieeexplore\.ieee\.org/
|
|
335
|
+
else "src"
|
|
336
|
+
end
|
|
337
|
+
links << Bib::Uri.new(type: type, content: l["URL"]) # if type
|
|
338
|
+
end
|
|
339
|
+
links
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
#
|
|
343
|
+
# Parse abstract from the source hash.
|
|
344
|
+
#
|
|
345
|
+
# @return [Array<Bib::LocalizedMarkedUpString>] The abstract.
|
|
346
|
+
#
|
|
347
|
+
def parse_abstract
|
|
348
|
+
return [] unless @src["abstract"]
|
|
349
|
+
|
|
350
|
+
abstract = Bib::Abstract.new(
|
|
351
|
+
content: normalize_markup(@src["abstract"]),
|
|
352
|
+
language: "en",
|
|
353
|
+
script: "Latn",
|
|
354
|
+
)
|
|
355
|
+
[abstract]
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
#
|
|
359
|
+
# Parse contributors from the source hash.
|
|
360
|
+
#
|
|
361
|
+
# @return [Array<Bib::Contributor>] The contributors.
|
|
362
|
+
#
|
|
363
|
+
def parse_contributor
|
|
364
|
+
contribs = author_investigators
|
|
365
|
+
contribs += authors_editors_translators
|
|
366
|
+
contribs += contribs_from_parent(contribs)
|
|
367
|
+
contribs << contributor(org_publisher, "publisher")
|
|
368
|
+
contribs += org_aurhorizer
|
|
369
|
+
contribs + org_enabler
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
#
|
|
373
|
+
# Create authors investigators from the source hash.
|
|
374
|
+
#
|
|
375
|
+
# @return [Array<Bib::Contributor>] The authors investigators.
|
|
376
|
+
#
|
|
377
|
+
def author_investigators
|
|
378
|
+
Array(@src["project"]).reduce([]) do |memo, proj|
|
|
379
|
+
memo + create_investigators(proj, "lead-investigator") +
|
|
380
|
+
create_investigators(proj, "investigator")
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
#
|
|
385
|
+
# Create investigators from the project.
|
|
386
|
+
#
|
|
387
|
+
# @param [Hash] project The project hash.
|
|
388
|
+
# @param [String] type The investigator type. "lead-investigator" or "investigator".
|
|
389
|
+
#
|
|
390
|
+
# @return [Array<Bib::Contributor>] The investigators.
|
|
391
|
+
#
|
|
392
|
+
def create_investigators(project, type)
|
|
393
|
+
description = type.gsub("-", " ")
|
|
394
|
+
Array(project[type]).map do |inv|
|
|
395
|
+
contributor(create_person(inv), "author", description)
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
#
|
|
400
|
+
# Create authors editors translators from the source hash.
|
|
401
|
+
#
|
|
402
|
+
# @return [Array<Bib::Contributor>] The authors editors translators.
|
|
403
|
+
#
|
|
404
|
+
def authors_editors_translators
|
|
405
|
+
%w[author editor translator].each_with_object([]) do |type, a|
|
|
406
|
+
@src[type]&.each do |c|
|
|
407
|
+
contrib = if c["family"]
|
|
408
|
+
create_person(c)
|
|
409
|
+
else
|
|
410
|
+
create_org(str_cleanup(c["name"]))
|
|
411
|
+
end
|
|
412
|
+
a << contributor(contrib, type)
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
#
|
|
418
|
+
# Fetch authors and editors from parent if they are not present in the book part.
|
|
419
|
+
#
|
|
420
|
+
# @param [Array<Bib::Contributor>] contribs present contributors
|
|
421
|
+
#
|
|
422
|
+
# @return [Array<Bib::Contributor>] contributors with authors and editors from parent
|
|
423
|
+
#
|
|
424
|
+
def contribs_from_parent(contribs) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
425
|
+
return [] unless %w[inbook inproceedings dataset].include?(parse_type) && @src["container-title"]
|
|
426
|
+
|
|
427
|
+
has_authors = contribs.any? { |c| c.role&.any? { |r| r.type == "author" } }
|
|
428
|
+
has_editors = contribs.any? { |c| c.role&.any? { |r| r.type == "editor" } }
|
|
429
|
+
return [] if has_authors && has_editors
|
|
430
|
+
|
|
431
|
+
create_authors_editors(has_authors, "author")
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
#
|
|
435
|
+
# Fetch parent item from Crossref.
|
|
436
|
+
#
|
|
437
|
+
# @return [Hash, nil] parent item
|
|
438
|
+
#
|
|
439
|
+
def parent_item
|
|
440
|
+
@parent_item ||= begin
|
|
441
|
+
query = CGI.escape [@src["container-title"][0], fetch_year].compact.join("+")
|
|
442
|
+
filter = "type:#{%w[book book-set edited-book monograph reference-book].join ',type:'}"
|
|
443
|
+
items = fetch_crossref(query: query, filter: filter)
|
|
444
|
+
items&.detect { |i| i["title"].include? @src["container-title"][0] }
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
#
|
|
449
|
+
# Create authors and editors from parent item.
|
|
450
|
+
#
|
|
451
|
+
# @param [Boolean] has true if authors or editors are present in the book part
|
|
452
|
+
# @param [String] type "author" or "editor"
|
|
453
|
+
#
|
|
454
|
+
# @return [Array<Bib::Contributor>] authors or editors
|
|
455
|
+
#
|
|
456
|
+
def create_authors_editors(has, type)
|
|
457
|
+
return [] if has || !parent_item
|
|
458
|
+
|
|
459
|
+
Array(parent_item[type]).map { |a| contributor(create_person(a), type) }
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
#
|
|
463
|
+
# Cerate an organization publisher from the source hash.
|
|
464
|
+
#
|
|
465
|
+
# @return [Bib::Organization] The organization.
|
|
466
|
+
#
|
|
467
|
+
def org_publisher
|
|
468
|
+
pbr = @src["institution"]&.detect do |i|
|
|
469
|
+
@src["publisher"].include?(i["name"]) ||
|
|
470
|
+
i["name"].include?(@src["publisher"])
|
|
471
|
+
end
|
|
472
|
+
a = pbr["acronym"]&.first if pbr
|
|
473
|
+
create_org(str_cleanup(@src["publisher"]), a)
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
#
|
|
477
|
+
# Clean up trailing punctuation and whitespace from a string.
|
|
478
|
+
#
|
|
479
|
+
# @param [String] str The string to clean up.
|
|
480
|
+
#
|
|
481
|
+
# @return [String] The cleaned up string.
|
|
482
|
+
#
|
|
483
|
+
def str_cleanup(str)
|
|
484
|
+
str.strip.sub(/[,\/\s]+$/, "").sub(/\s:$/, "")
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
#
|
|
488
|
+
# Create an organization with properly typed name and abbreviation.
|
|
489
|
+
#
|
|
490
|
+
# @param [String] name The organization name.
|
|
491
|
+
# @param [String, nil] abbreviation The organization abbreviation.
|
|
492
|
+
#
|
|
493
|
+
# @return [Bib::Organization] The organization.
|
|
494
|
+
#
|
|
495
|
+
def create_org(name, abbreviation = nil)
|
|
496
|
+
n = [Bib::TypedLocalizedString.new(content: normalize_markup(name))]
|
|
497
|
+
a = if abbreviation
|
|
498
|
+
Bib::LocalizedString.new(content: normalize_markup(abbreviation))
|
|
499
|
+
end
|
|
500
|
+
Bib::Organization.new name: n, abbreviation: a
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
#
|
|
504
|
+
# Parse authorizer contributor from the source hash.
|
|
505
|
+
#
|
|
506
|
+
# @return [Array<Bib::Contributor>] The authorizer contributor.
|
|
507
|
+
#
|
|
508
|
+
def org_aurhorizer
|
|
509
|
+
return [] unless @src["standards-body"]
|
|
510
|
+
|
|
511
|
+
name, acronym = @src["standards-body"].values_at("name", "acronym")
|
|
512
|
+
[contributor(create_org(name, acronym), "authorizer")]
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
#
|
|
516
|
+
# Parse enabler contributor from the source hash.
|
|
517
|
+
#
|
|
518
|
+
# @return [Array<Bib::Contributor>] The enabler contributor.
|
|
519
|
+
#
|
|
520
|
+
def org_enabler
|
|
521
|
+
Array(@src["project"]).each_with_object([]) do |proj, memo|
|
|
522
|
+
proj["funding"].each do |f|
|
|
523
|
+
memo << create_enabler(f.dig("funder", "name"))
|
|
524
|
+
end
|
|
525
|
+
end + Array(@src["funder"]).map { |f| create_enabler f["name"] }
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
#
|
|
529
|
+
# Create enabler contributor with type "enabler".
|
|
530
|
+
#
|
|
531
|
+
# @param [String] name The funder name.
|
|
532
|
+
#
|
|
533
|
+
# @return [Bib::Contributor] The enabler contributor.
|
|
534
|
+
#
|
|
535
|
+
def create_enabler(name)
|
|
536
|
+
contributor(create_org(name), "enabler")
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
#
|
|
540
|
+
# Create contributor from an entity and a role type.
|
|
541
|
+
#
|
|
542
|
+
# @param [Bib::Person, Bib::Organization] entity The entity.
|
|
543
|
+
# @param [String] type The role type.
|
|
544
|
+
#
|
|
545
|
+
# @return [Bib::Contributor] The contributor.
|
|
546
|
+
#
|
|
547
|
+
def contributor(entity, type, descriprion = nil)
|
|
548
|
+
desc = descriprion ? [Bib::LocalizedMarkedUpString.new(content: descriprion)] : nil
|
|
549
|
+
role = [Bib::Contributor::Role.new(type: type, description: desc)]
|
|
550
|
+
if entity.is_a?(Bib::Person)
|
|
551
|
+
Bib::Contributor.new(role: role, person: entity)
|
|
552
|
+
else
|
|
553
|
+
Bib::Contributor.new(role: role, organization: entity)
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
#
|
|
558
|
+
# Create a person from a person hash.
|
|
559
|
+
#
|
|
560
|
+
# @param [Hash] person The person hash.
|
|
561
|
+
#
|
|
562
|
+
# @return [Bib::Person] The person.
|
|
563
|
+
#
|
|
564
|
+
def create_person(person)
|
|
565
|
+
Bib::Person.new(
|
|
566
|
+
name: create_person_name(person),
|
|
567
|
+
affiliation: create_affiliation(person),
|
|
568
|
+
identifier: person_id(person),
|
|
569
|
+
)
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
#
|
|
573
|
+
# Create person affiliations from a person hash.
|
|
574
|
+
#
|
|
575
|
+
# @param [Hash] person The person hash.
|
|
576
|
+
#
|
|
577
|
+
# @return [Array<Bib::Affiliation>] The affiliations.
|
|
578
|
+
#
|
|
579
|
+
def create_affiliation(person)
|
|
580
|
+
(person["affiliation"] || []).map do |a|
|
|
581
|
+
Bib::Affiliation.new organization: create_org(a["name"])
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
#
|
|
586
|
+
# Create a person full name from a person hash.
|
|
587
|
+
#
|
|
588
|
+
# @param [Hash] person The person hash.
|
|
589
|
+
#
|
|
590
|
+
# @return [Bib::FullName] The full name.
|
|
591
|
+
#
|
|
592
|
+
def create_person_name(person)
|
|
593
|
+
surname = titlecase(person["family"])
|
|
594
|
+
sn = Bib::LocalizedString.new(content: surname, language: "en", script: "Latn")
|
|
595
|
+
Bib::FullName.new(
|
|
596
|
+
surname: sn, forename: forename(person), addition: nameaddition(person),
|
|
597
|
+
completename: completename(person), prefix: nameprefix(person)
|
|
598
|
+
)
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
#
|
|
602
|
+
# Capitalize the first letter of each word in a string except for words that
|
|
603
|
+
# are 2 letters or less.
|
|
604
|
+
#
|
|
605
|
+
# @param [<Type>] str <description>
|
|
606
|
+
#
|
|
607
|
+
# @return [<Type>] <description>
|
|
608
|
+
#
|
|
609
|
+
def titlecase(str)
|
|
610
|
+
str.split.map do |s|
|
|
611
|
+
if s.size > 2 && s.upcase == s && !/\.&/.match?(s)
|
|
612
|
+
s.capitalize
|
|
613
|
+
else
|
|
614
|
+
s
|
|
615
|
+
end
|
|
616
|
+
end.join " "
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
#
|
|
620
|
+
# Create a person name prefix from a person hash.
|
|
621
|
+
#
|
|
622
|
+
# @param [Hash] person The person hash.
|
|
623
|
+
#
|
|
624
|
+
# @return [Array<Bib::LocalizedString>] The name prefix.
|
|
625
|
+
#
|
|
626
|
+
def nameprefix(person)
|
|
627
|
+
return [] unless person["prefix"]
|
|
628
|
+
|
|
629
|
+
[Bib::LocalizedString.new(content: person["prefix"], language: "en", script: "Latn")]
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
#
|
|
633
|
+
# Create a complete name from a person hash.
|
|
634
|
+
#
|
|
635
|
+
# @param [Hash] person The person hash.
|
|
636
|
+
#
|
|
637
|
+
# @return [Bib::LocalizedString] The complete name.
|
|
638
|
+
#
|
|
639
|
+
def completename(person)
|
|
640
|
+
return unless person["name"]
|
|
641
|
+
|
|
642
|
+
Bib::LocalizedString.new(content: person["name"], language: "en", script: "Latn")
|
|
643
|
+
end
|
|
644
|
+
|
|
645
|
+
#
|
|
646
|
+
# Create a forename from a person hash.
|
|
647
|
+
#
|
|
648
|
+
# @param [Hash] person The person hash.
|
|
649
|
+
#
|
|
650
|
+
# @return [Array<Bib::FullNameType::Forename>] The forename.
|
|
651
|
+
#
|
|
652
|
+
def forename(person)
|
|
653
|
+
return [] unless person["given"]
|
|
654
|
+
|
|
655
|
+
fname = titlecase(person["given"])
|
|
656
|
+
[Bib::FullNameType::Forename.new(content: fname, language: "en", script: "Latn")]
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
#
|
|
660
|
+
# Create an addition from a person hash.
|
|
661
|
+
#
|
|
662
|
+
# @param [Hash] person The person hash.
|
|
663
|
+
#
|
|
664
|
+
# @return [Array<Bib::LocalizedString>] The addition.
|
|
665
|
+
#
|
|
666
|
+
def nameaddition(person)
|
|
667
|
+
return [] unless person["suffix"]
|
|
668
|
+
|
|
669
|
+
[Bib::LocalizedString.new(content: person["suffix"], language: "en", script: "Latn")]
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
#
|
|
673
|
+
# Create a person identifier from a person hash.
|
|
674
|
+
#
|
|
675
|
+
# @param [Hash] person The person hash.
|
|
676
|
+
#
|
|
677
|
+
# @return [Array<Bib::Person::Identifier>] The person identifier.
|
|
678
|
+
#
|
|
679
|
+
def person_id(person)
|
|
680
|
+
return [] unless person["ORCID"]
|
|
681
|
+
|
|
682
|
+
[Bib::Person::Identifier.new(type: "orcid", content: person["ORCID"])]
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
#
|
|
686
|
+
# Parse a place from the source hash.
|
|
687
|
+
#
|
|
688
|
+
# @return [Array<Bib::Place>] The place.
|
|
689
|
+
#
|
|
690
|
+
def parse_place # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
|
691
|
+
pub_location = @src["publisher-location"] || fetch_location
|
|
692
|
+
return [] unless pub_location
|
|
693
|
+
|
|
694
|
+
pls1, pls2 = pub_location.split(", ")
|
|
695
|
+
pls1 = str_cleanup pls1
|
|
696
|
+
pls2 &&= str_cleanup pls2
|
|
697
|
+
if COUNTRIES.include? pls2
|
|
698
|
+
country = Bib::Place::RegionType.new(content: pls2)
|
|
699
|
+
[Bib::Place.new(city: pls1, country: [country])]
|
|
700
|
+
elsif pls2 && pls2 == pls2&.upcase
|
|
701
|
+
region = Bib::Place::RegionType.new(content: pls2)
|
|
702
|
+
[Bib::Place.new(city: pls1, region: [region])]
|
|
703
|
+
elsif pls1 == pls2 || pls2.nil? || pls2.empty?
|
|
704
|
+
[Bib::Place.new(city: pls1)]
|
|
705
|
+
else
|
|
706
|
+
[Bib::Place.new(city: pls1), Bib::Place.new(city: pls2)]
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
|
|
710
|
+
#
|
|
711
|
+
# Fetch location from container.
|
|
712
|
+
#
|
|
713
|
+
# @return [String, nil] The location.
|
|
714
|
+
#
|
|
715
|
+
def fetch_location
|
|
716
|
+
title = @item[:title].first&.content
|
|
717
|
+
qparts = [title, fetch_year, @src["publisher"]]
|
|
718
|
+
query = CGI.escape qparts.compact.join("+").gsub(" ", "+")
|
|
719
|
+
filter = "type:#{%w[book-chapter book-part book-section book-track].join(',type:')}"
|
|
720
|
+
items = fetch_crossref(query: query, filter: filter)
|
|
721
|
+
items&.detect do |i|
|
|
722
|
+
i["publisher-location"] && i["container-title"].include?(title)
|
|
723
|
+
end&.dig("publisher-location")
|
|
724
|
+
end
|
|
725
|
+
|
|
726
|
+
#
|
|
727
|
+
# Parse relations from the source hash.
|
|
728
|
+
#
|
|
729
|
+
# @return [Array<Bib::Relation>] The relations.
|
|
730
|
+
#
|
|
731
|
+
def parse_relation # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
732
|
+
rels = included_in_relation
|
|
733
|
+
@src["relation"].each_with_object(rels) do |(k, v), a|
|
|
734
|
+
type, desc = relation_type k
|
|
735
|
+
Array(v).each do |r|
|
|
736
|
+
rel_item = Crossref.get_by_id r["id"]
|
|
737
|
+
title = rel_item["title"].map { |t| create_title t }
|
|
738
|
+
docid = Bib::Docidentifier.new(content: r["id"], type: "DOI")
|
|
739
|
+
bib = create_bibitem r["id"], title: title, docidentifier: [docid]
|
|
740
|
+
a << Bib::Relation.new(type: type, description: desc, bibitem: bib)
|
|
741
|
+
end
|
|
742
|
+
end
|
|
743
|
+
end
|
|
744
|
+
|
|
745
|
+
#
|
|
746
|
+
# Transform crossref relation type to relaton relation type.
|
|
747
|
+
#
|
|
748
|
+
# @param [String] crtype The crossref relation type.
|
|
749
|
+
#
|
|
750
|
+
# @return [Array<String>] The relaton relation type and description.
|
|
751
|
+
#
|
|
752
|
+
def relation_type(crtype)
|
|
753
|
+
type = REALATION_TYPES[crtype] || begin
|
|
754
|
+
desc = Bib::LocalizedMarkedUpString.new(content: crtype)
|
|
755
|
+
"related"
|
|
756
|
+
end
|
|
757
|
+
[type, desc]
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
#
|
|
761
|
+
# Create included in relation.
|
|
762
|
+
#
|
|
763
|
+
# @return [Array<Bib::Relation>] The relations.
|
|
764
|
+
#
|
|
765
|
+
def included_in_relation
|
|
766
|
+
types = %w[
|
|
767
|
+
book book-chapter book-part book-section book-track dataset journal-issue
|
|
768
|
+
journal-value proceedings-article reference-entry report-component
|
|
769
|
+
]
|
|
770
|
+
return [] unless @src["container-title"] && types.include?(@src["type"])
|
|
771
|
+
|
|
772
|
+
@src["container-title"].map do |ct|
|
|
773
|
+
contrib = create_authors_editors false, "editor"
|
|
774
|
+
title = Bib::Title.new content: normalize_markup(ct)
|
|
775
|
+
bib = Bib::ItemBase.new(title: [title], contributor: contrib)
|
|
776
|
+
Bib::Relation.new(type: "includedIn", bibitem: bib)
|
|
777
|
+
end
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
#
|
|
781
|
+
# Fetch year from the source hash.
|
|
782
|
+
#
|
|
783
|
+
# @return [String] The year.
|
|
784
|
+
#
|
|
785
|
+
def fetch_year
|
|
786
|
+
d = @src["published"] || @src["approved"] || @src["created"]
|
|
787
|
+
d["date-parts"][0][0]
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
#
|
|
791
|
+
# Parse an extent from the source hash.
|
|
792
|
+
#
|
|
793
|
+
# @return [Array<Bib::Extent>] The extent.
|
|
794
|
+
#
|
|
795
|
+
def parse_extent # rubocop:disable Metrics/AbcSize
|
|
796
|
+
extent = []
|
|
797
|
+
extent << Bib::Locality.new(type: "volume", reference_from: @src["volume"]) if @src["volume"]
|
|
798
|
+
extent << Bib::Locality.new(type: "issue", reference_from: @src["issue"]) if @src["issue"]
|
|
799
|
+
if @src["page"]
|
|
800
|
+
from, to = @src["page"].split("-")
|
|
801
|
+
extent << Bib::Locality.new(type: "page", reference_from: from, reference_to: to)
|
|
802
|
+
end
|
|
803
|
+
extent.any? ? [Bib::Extent.new(locality: extent)] : []
|
|
804
|
+
end
|
|
805
|
+
|
|
806
|
+
#
|
|
807
|
+
# Parse a series from the source hash.
|
|
808
|
+
#
|
|
809
|
+
# @return [Array<Bib::Series>] The series.
|
|
810
|
+
#
|
|
811
|
+
def parse_series # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
812
|
+
types = %w[inbook incollection inproceedings]
|
|
813
|
+
return [] if !@src["container-title"] || types.include?(@item[:type]) || @src["type"] == "report-component"
|
|
814
|
+
|
|
815
|
+
con_ttl = if main_sub_titles.any? || project_titles.any?
|
|
816
|
+
@src["container-title"]
|
|
817
|
+
elsif @src["container-title"].size > 1
|
|
818
|
+
sct = @src["short-container-title"]&.last
|
|
819
|
+
abbrev = Bib::LocalizedString.new(content: sct) if sct
|
|
820
|
+
@src["container-title"][-1..-1]
|
|
821
|
+
else []
|
|
822
|
+
end
|
|
823
|
+
con_ttl.map do |ct|
|
|
824
|
+
title = Bib::Title.new content: normalize_markup(ct)
|
|
825
|
+
Bib::Series.new title: [title], abbreviation: abbrev
|
|
826
|
+
end
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
#
|
|
830
|
+
# Parse a medium from the source hash.
|
|
831
|
+
#
|
|
832
|
+
# @return [Bib::Medium, nil] The medium.
|
|
833
|
+
#
|
|
834
|
+
def parse_medium
|
|
835
|
+
genre = @src["degree"]&.first
|
|
836
|
+
return unless genre
|
|
837
|
+
|
|
838
|
+
Bib::Medium.new genre: genre
|
|
839
|
+
end
|
|
840
|
+
|
|
841
|
+
#
|
|
842
|
+
# Fetch data from Crossref API with retry logic.
|
|
843
|
+
#
|
|
844
|
+
# @param [String] query The query string.
|
|
845
|
+
# @param [String] filter The filter string.
|
|
846
|
+
#
|
|
847
|
+
# @return [Array<Hash>, nil] Items array from response or nil for 4xx responses
|
|
848
|
+
# other than 429.
|
|
849
|
+
#
|
|
850
|
+
# @raise [Relaton::RequestError] If request fails after retries, or if the
|
|
851
|
+
# rate limit does not clear.
|
|
852
|
+
#
|
|
853
|
+
def fetch_crossref(query:, filter:) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
854
|
+
url = format(CROSSREF_API_URL, query: query, filter: filter)
|
|
855
|
+
retries = 0
|
|
856
|
+
throttled = 0
|
|
857
|
+
begin
|
|
858
|
+
resp = Crossref.agent.get url
|
|
859
|
+
JSON.parse(resp.body).dig("message", "items")
|
|
860
|
+
rescue Mechanize::ResponseCodeError => e
|
|
861
|
+
# 429 must be handled before the 4xx nil return: a throttle is not
|
|
862
|
+
# "no such record". Returning nil here made a rate-limited lookup look
|
|
863
|
+
# like a missing document, so callers such as #parent_item silently
|
|
864
|
+
# produced an incomplete item instead of failing.
|
|
865
|
+
if e.response_code == RATE_LIMITED
|
|
866
|
+
throttled += 1
|
|
867
|
+
if throttled <= MAX_RETRIES
|
|
868
|
+
# Cap the backoff itself, not just the header value: escalating by
|
|
869
|
+
# attempt would otherwise let a single `Retry-After: 60` stall one
|
|
870
|
+
# lookup for 60+120+180s.
|
|
871
|
+
sleep [retry_delay(e) * throttled, MAX_RETRY_DELAY].min
|
|
872
|
+
retry
|
|
873
|
+
end
|
|
874
|
+
raise Relaton::RequestError,
|
|
875
|
+
"Crossref rate limit not cleared after #{MAX_RETRIES} retries: #{url}"
|
|
876
|
+
end
|
|
877
|
+
return nil if e.response_code.start_with?("4")
|
|
878
|
+
|
|
879
|
+
raise Relaton::RequestError, "Crossref request failed: #{e.response_code} #{e.page.body}"
|
|
880
|
+
rescue Net::HTTP::Persistent::Error, Net::HTTPError, Errno::ECONNREFUSED => e
|
|
881
|
+
retries += 1
|
|
882
|
+
retry if retries <= MAX_RETRIES
|
|
883
|
+
raise Relaton::RequestError, "Crossref network error after #{MAX_RETRIES} retries: #{e.message}"
|
|
884
|
+
rescue JSON::ParserError => e
|
|
885
|
+
raise Relaton::RequestError, "Crossref JSON parsing error: #{e.message}"
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
#
|
|
890
|
+
# Base seconds to wait before retrying a throttled Crossref request.
|
|
891
|
+
# Prefers Retry-After, falls back to Crossref's X-Rate-Limit-Interval
|
|
892
|
+
# (formatted "1s", hence the digit scan). An empty-bodied 429 carries
|
|
893
|
+
# neither header, so this never assumes one is present.
|
|
894
|
+
#
|
|
895
|
+
# @param [Mechanize::ResponseCodeError] err The rate-limit error.
|
|
896
|
+
#
|
|
897
|
+
# @return [Integer] Delay in seconds, at least 1 and at most MAX_RETRY_DELAY.
|
|
898
|
+
#
|
|
899
|
+
def retry_delay(err)
|
|
900
|
+
headers = err.page&.response || {}
|
|
901
|
+
secs = retry_after_seconds(headers["retry-after"]) ||
|
|
902
|
+
headers["x-rate-limit-interval"].to_s[/\d+/].to_i
|
|
903
|
+
secs.positive? ? [secs, MAX_RETRY_DELAY].min : 1
|
|
904
|
+
end
|
|
905
|
+
|
|
906
|
+
#
|
|
907
|
+
# Parse a Retry-After header value, which RFC 9110 allows to be either
|
|
908
|
+
# delta-seconds or an HTTP-date. Only the numeric form is usable as a
|
|
909
|
+
# delay: scanning digits out of a date would pick up the day-of-month,
|
|
910
|
+
# silently turning a long server-mandated backoff into a few seconds.
|
|
911
|
+
#
|
|
912
|
+
# @param [String, nil] value The raw header value.
|
|
913
|
+
#
|
|
914
|
+
# @return [Integer, nil] Seconds, or nil if absent or in the date form.
|
|
915
|
+
#
|
|
916
|
+
def retry_after_seconds(value)
|
|
917
|
+
value.to_s.strip.match?(/\A\d+\z/) ? value.to_i : nil
|
|
918
|
+
end
|
|
919
|
+
end
|
|
920
|
+
end
|
|
921
|
+
end
|