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,201 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
require "net/http"
|
|
3
|
+
require "openssl"
|
|
4
|
+
require "zlib"
|
|
5
|
+
|
|
6
|
+
module Relaton
|
|
7
|
+
module Index
|
|
8
|
+
#
|
|
9
|
+
# Reads a flavor's machine index from its GitHub Pages site (relaton#189).
|
|
10
|
+
#
|
|
11
|
+
# `index/manifest.json` gives the lookup rule, and a query reads only the
|
|
12
|
+
# one `index/shard-NNNNN.json` its document family lives in, in place of the
|
|
13
|
+
# whole `index-vN.zip`. The shard key is `crc32(id.root.number.to_s) %
|
|
14
|
+
# shards`, the expression the relaton-cli producer (`MachineIndex`) writes
|
|
15
|
+
# and `Type#candidates_by_number` narrows on. See
|
|
16
|
+
# `docs/data-repository-format.adoc`, "The machine index on the Pages site".
|
|
17
|
+
#
|
|
18
|
+
# Everything is held in memory for TTL seconds and never written to the
|
|
19
|
+
# storage. A shard 404 is a definitive "not found" (empty buckets are not
|
|
20
|
+
# published). A transport failure raises `Relaton::RequestError`, which
|
|
21
|
+
# `Relaton::Db#net_retry` retries; a machine index this client cannot read
|
|
22
|
+
# raises `Relaton::Index::Error`. Neither falls back to the monolith: the
|
|
23
|
+
# whole index is read only when the manifest publishes no shards, or when
|
|
24
|
+
# the query has no root number to key on.
|
|
25
|
+
#
|
|
26
|
+
class ShardSource
|
|
27
|
+
TTL = 24 * 60 * 60
|
|
28
|
+
VERSION = 2
|
|
29
|
+
KEY = "root-number".freeze
|
|
30
|
+
ALGORITHM = "crc32".freeze
|
|
31
|
+
|
|
32
|
+
NET_ERRORS = [
|
|
33
|
+
SocketError, Timeout::Error, IOError, SystemCallError, OpenSSL::SSL::SSLError,
|
|
34
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError,
|
|
35
|
+
Zlib::Error # a truncated gzip body, which Net::HTTP inflates
|
|
36
|
+
|
|
37
|
+
].freeze
|
|
38
|
+
|
|
39
|
+
attr_reader :pages_url
|
|
40
|
+
|
|
41
|
+
#
|
|
42
|
+
# @param [String] dir flavor directory name, used in log messages
|
|
43
|
+
# @param [String] pages_url base URL of the Pages site, with a trailing `/`
|
|
44
|
+
# @param [Class] pubid_class the flavor's pubid identifier class
|
|
45
|
+
#
|
|
46
|
+
def initialize(dir, pages_url, pubid_class)
|
|
47
|
+
@pages_url = pages_url.end_with?("/") ? pages_url : "#{pages_url}/"
|
|
48
|
+
# Only the deserialization helpers are used: this FileIO reads and
|
|
49
|
+
# writes no file.
|
|
50
|
+
@file_io = FileIO.new(dir, nil, nil, nil, pubid_class)
|
|
51
|
+
@mutex = Mutex.new
|
|
52
|
+
@state = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# Rows of the shard that holds the document family of `id`.
|
|
57
|
+
#
|
|
58
|
+
# @param [Pubid::Identifier] id parsed query
|
|
59
|
+
#
|
|
60
|
+
# @return [Array<Hash>] `{ id:, file: }` rows, empty when not found
|
|
61
|
+
#
|
|
62
|
+
def rows(id)
|
|
63
|
+
number = id.root.number.to_s
|
|
64
|
+
state = current_state
|
|
65
|
+
shards = manifest(state)["shards"]
|
|
66
|
+
return load_whole_index(state) if shards.zero? || number.empty?
|
|
67
|
+
|
|
68
|
+
n = Zlib.crc32(number) % shards
|
|
69
|
+
once(state, n) { fetch_shard(n) }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# Every row, from the monolith the manifest names (`<index>.zip` on the
|
|
74
|
+
# Pages site). Needed by a String query and a block-only search.
|
|
75
|
+
#
|
|
76
|
+
# @return [Array<Hash>] `{ id:, file: }` rows, sorted by root number
|
|
77
|
+
#
|
|
78
|
+
def whole_index
|
|
79
|
+
load_whole_index current_state
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
|
|
84
|
+
# One generation of cached data. It is replaced as a whole when it
|
|
85
|
+
# expires, so a fetch that finishes late stores into its own generation
|
|
86
|
+
# and never mixes an old shard with a new manifest.
|
|
87
|
+
def new_state
|
|
88
|
+
{ created: Time.now, data: {}, locks: {} }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def current_state
|
|
92
|
+
@mutex.synchronize do
|
|
93
|
+
@state = new_state if @state.nil? || Time.now - @state[:created] > TTL
|
|
94
|
+
@state
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Runs the block once for each key in a generation. The network call is
|
|
99
|
+
# made under a lock for that key only, so lookups of other shards (from
|
|
100
|
+
# the `Relaton::Db` workers pool) do not wait for it. A raise stores
|
|
101
|
+
# nothing, so the next call tries again.
|
|
102
|
+
def once(state, key)
|
|
103
|
+
lock = @mutex.synchronize { state[:locks][key] ||= Mutex.new }
|
|
104
|
+
lock.synchronize do
|
|
105
|
+
data = state[:data]
|
|
106
|
+
return @mutex.synchronize { data[key] } if @mutex.synchronize { data.key?(key) }
|
|
107
|
+
|
|
108
|
+
value = yield
|
|
109
|
+
@mutex.synchronize { data[key] = value }
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def manifest(state)
|
|
114
|
+
once(state, :manifest) do
|
|
115
|
+
body = get("index/manifest.json")
|
|
116
|
+
raise Error, "no machine index manifest at `#{url('index/manifest.json')}`" unless body
|
|
117
|
+
|
|
118
|
+
check_manifest parse_json(body, "index/manifest.json")
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def check_manifest(data)
|
|
123
|
+
unless data.is_a?(Hash) && data["version"] == VERSION &&
|
|
124
|
+
data["key"] == KEY && data["algorithm"] == ALGORITHM &&
|
|
125
|
+
data["shards"].is_a?(Integer) && !data["shards"].negative? &&
|
|
126
|
+
data["index"].is_a?(String) && !data["index"].empty?
|
|
127
|
+
raise Error, "unsupported machine index manifest at " \
|
|
128
|
+
"`#{url('index/manifest.json')}`: #{data.inspect}"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
data
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def fetch_shard(num)
|
|
135
|
+
path = format("index/shard-%05d.json", num)
|
|
136
|
+
body = get(path)
|
|
137
|
+
return [] unless body
|
|
138
|
+
|
|
139
|
+
data = parse_json(body, path)
|
|
140
|
+
raise Error, "shard `#{url(path)}` is not an array" unless data.is_a?(Array)
|
|
141
|
+
|
|
142
|
+
data.map { |r| { id: deserialize(r["id"], path), file: r["file"] } }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def load_whole_index(state)
|
|
146
|
+
path = "#{manifest(state)['index']}.zip"
|
|
147
|
+
once(state, :whole_index) do
|
|
148
|
+
body = get(path)
|
|
149
|
+
raise Error, "no whole index at `#{url(path)}`" unless body
|
|
150
|
+
|
|
151
|
+
yaml = unzip(body)
|
|
152
|
+
raise Error, "empty archive at `#{url(path)}`" unless yaml
|
|
153
|
+
|
|
154
|
+
index = YAML.safe_load(yaml, permitted_classes: [Symbol])
|
|
155
|
+
raise Error, "wrong structure of `#{url(path)}`" unless @file_io.check_basic_format(index)
|
|
156
|
+
|
|
157
|
+
@file_io.deserialize_pubid(index)
|
|
158
|
+
rescue FileIO::InvalidIndexError, Psych::SyntaxError, Zip::Error, Zlib::Error => e
|
|
159
|
+
raise Error, "cannot read `#{url(path)}`: #{e.message}"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def unzip(body)
|
|
164
|
+
yaml = nil
|
|
165
|
+
# `open_buffer` does not return the block's value.
|
|
166
|
+
Zip::File.open_buffer(body) { |zip| yaml = zip.entries.first&.get_input_stream&.read }
|
|
167
|
+
yaml
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def deserialize(raw, path)
|
|
171
|
+
@file_io.deserialize_id(raw)
|
|
172
|
+
rescue FileIO::InvalidIndexError => e
|
|
173
|
+
raise Error, "cannot read shard `#{url(path)}`: #{e.message}"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def parse_json(body, path)
|
|
177
|
+
JSON.parse(body)
|
|
178
|
+
rescue JSON::ParserError => e
|
|
179
|
+
raise Error, "cannot parse `#{url(path)}`: #{e.message}"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def url(path)
|
|
183
|
+
"#{@pages_url}#{path}"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
#
|
|
187
|
+
# @return [String, nil] the body, or nil for a 404
|
|
188
|
+
#
|
|
189
|
+
def get(path)
|
|
190
|
+
resp = Net::HTTP.get_response(URI.parse(url(path)))
|
|
191
|
+
case resp.code
|
|
192
|
+
when "200" then resp.body
|
|
193
|
+
when "404" then nil
|
|
194
|
+
else raise Relaton::RequestError, "Could not access #{url(path)}: HTTP #{resp.code}"
|
|
195
|
+
end
|
|
196
|
+
rescue *NET_ERRORS => e
|
|
197
|
+
raise Relaton::RequestError, "Could not access #{url(path)}: #{e.message}"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Index
|
|
3
|
+
#
|
|
4
|
+
# Relaton::Index::Type is a class for indexing Relaton files.
|
|
5
|
+
#
|
|
6
|
+
class Type
|
|
7
|
+
#
|
|
8
|
+
# Initialize a new Relaton::Index::Type object
|
|
9
|
+
#
|
|
10
|
+
# @param [String, Symbol] type type of index (ISO, IEC, etc.)
|
|
11
|
+
# @param [String, nil] url external URL to index, used to fetch index for searching files
|
|
12
|
+
# @param [String, nil] file output file name
|
|
13
|
+
# @param [Array<Symbol>] id_keys keys of identifier to be used for sorting index
|
|
14
|
+
# format of index file is checked if id_keys all is provided at least in one of the IDs
|
|
15
|
+
# @param [Pubid::Identifier, nil] pubid class for deserialization
|
|
16
|
+
# @param [String, nil] pages_url base URL of the Pages site that serves
|
|
17
|
+
# the machine index. With it the type reads the index from there, in
|
|
18
|
+
# memory (see ShardSource), and a parsed query fetches one shard only.
|
|
19
|
+
#
|
|
20
|
+
def initialize(type, url = nil, file = nil, id_keys = nil, pubid_class = nil, # rubocop:disable Metrics/ParameterLists
|
|
21
|
+
pages_url: nil)
|
|
22
|
+
@file = file
|
|
23
|
+
@dir = type.to_s.downcase
|
|
24
|
+
@pubid_class = pubid_class
|
|
25
|
+
@pages_url = pages_url
|
|
26
|
+
filename = file || Index.config.filename
|
|
27
|
+
@file_io = FileIO.new @dir, url, filename, id_keys, pubid_class
|
|
28
|
+
@source = new_source
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# With a Pages source the whole index is not kept here: the source holds
|
|
32
|
+
# it, and drops it when its 24 h expire.
|
|
33
|
+
def index
|
|
34
|
+
return @source.whole_index if @source
|
|
35
|
+
|
|
36
|
+
@index ||= @file_io.read
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Check if index is actual. If url or file is given, check if it is equal to
|
|
41
|
+
# index url or file.
|
|
42
|
+
#
|
|
43
|
+
# @param [Hash] **args arguments
|
|
44
|
+
# @option args [String, nil] :url external URL to index, used to fetch index for searching files
|
|
45
|
+
# @option args [String, nil] :file output file name
|
|
46
|
+
# @option args [String, nil] :pages_url base URL of the Pages site
|
|
47
|
+
#
|
|
48
|
+
# @return [Boolean] true if index is actual, false otherwise
|
|
49
|
+
#
|
|
50
|
+
def actual?(**args)
|
|
51
|
+
(!args.key?(:url) || args[:url] == @file_io.url) &&
|
|
52
|
+
(!args.key?(:file) || args[:file] == @file) &&
|
|
53
|
+
(!args.key?(:pages_url) || args[:pages_url] == @pages_url)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Add or update index item
|
|
58
|
+
#
|
|
59
|
+
# @param [Pubid::Identifier] id document ID
|
|
60
|
+
# @param [String] file file name of the document
|
|
61
|
+
#
|
|
62
|
+
# @return [void]
|
|
63
|
+
#
|
|
64
|
+
def add_or_update(id, file)
|
|
65
|
+
key = id.to_s
|
|
66
|
+
item = id_lookup[key]
|
|
67
|
+
if item
|
|
68
|
+
item[:file] = file
|
|
69
|
+
else
|
|
70
|
+
new_item = { id: id, file: file }
|
|
71
|
+
index << new_item
|
|
72
|
+
id_lookup[key] = new_item
|
|
73
|
+
@file_io.sorted = false
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
#
|
|
78
|
+
# Search index for a given ID.
|
|
79
|
+
#
|
|
80
|
+
# Without a block, two identifiers are matched with pubid's asymmetric
|
|
81
|
+
# subset match `id === item[:id]` (`Pubid::SubsetMatch`): the query is the
|
|
82
|
+
# reference, and a component it leaves nil or empty matches any value, so
|
|
83
|
+
# `OGC 12-128` answers with `12-128r19`. That is what a search by
|
|
84
|
+
# reference means. A caller that needs **exact** equality passes
|
|
85
|
+
# `exact: true`, which selects the rows with `item[:id] == id`. A nil
|
|
86
|
+
# component is a wildcard for `===`, not "the document has none": over
|
|
87
|
+
# the fixture indexes the subset match accepts 260 CCSDS pairs (the `-S`
|
|
88
|
+
# suffix) and 20,513 IETF pairs (a draft slug matches each of its
|
|
89
|
+
# versions) that `==` rejects. `Relaton::Ccsds` and `Relaton::Ietf` are
|
|
90
|
+
# the two callers that pass it.
|
|
91
|
+
#
|
|
92
|
+
# A String query keeps the substring match it always had, unless it is
|
|
93
|
+
# `exact:`.
|
|
94
|
+
#
|
|
95
|
+
# @param [String, Pubid::Identifier] id ID to search for
|
|
96
|
+
# @param [Boolean] exact match with `==` instead of the subset match
|
|
97
|
+
#
|
|
98
|
+
# @return [Array<Hash>] search results
|
|
99
|
+
#
|
|
100
|
+
def search(id = nil, exact: false, &block)
|
|
101
|
+
raise ArgumentError, "search takes exact: or a block, not both" if exact && block
|
|
102
|
+
|
|
103
|
+
items = search_candidates(id)
|
|
104
|
+
return items.select(&block) if block
|
|
105
|
+
return items.select { |i| i[:id] == id } if exact
|
|
106
|
+
|
|
107
|
+
items.select { |i| match_item(i, id) }
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# Save index to storage
|
|
112
|
+
#
|
|
113
|
+
# @return [void]
|
|
114
|
+
#
|
|
115
|
+
def save
|
|
116
|
+
@file_io.save(@index || [])
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
#
|
|
120
|
+
# Remove index file from storage and clear index
|
|
121
|
+
#
|
|
122
|
+
# @return [void]
|
|
123
|
+
#
|
|
124
|
+
def remove_file
|
|
125
|
+
# A Pages source has no file: its FileIO would resolve the default
|
|
126
|
+
# filename against the working directory.
|
|
127
|
+
@file_io.remove unless @source
|
|
128
|
+
@source = new_source
|
|
129
|
+
@index = nil
|
|
130
|
+
@id_lookup = nil
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
# Remove all index items
|
|
135
|
+
#
|
|
136
|
+
# @return [void]
|
|
137
|
+
#
|
|
138
|
+
def remove_all
|
|
139
|
+
@index = []
|
|
140
|
+
@id_lookup = nil
|
|
141
|
+
@file_io.sorted = true
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
private
|
|
145
|
+
|
|
146
|
+
def id_lookup
|
|
147
|
+
@id_lookup ||= index.each_with_object({}) do |item, h|
|
|
148
|
+
h[item[:id].to_s] = item
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def new_source
|
|
153
|
+
ShardSource.new(@dir, @pages_url, @pubid_class) if @pages_url
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def search_candidates(id)
|
|
157
|
+
# A parsed query reads only its own shard. `@index`, once loaded, is
|
|
158
|
+
# never refreshed, so the shards stay the fresher answer.
|
|
159
|
+
return @source.rows(id) if @source && id && !id.is_a?(String)
|
|
160
|
+
|
|
161
|
+
# index needs to be created to check if sorted
|
|
162
|
+
idx = index
|
|
163
|
+
if @file_io.sorted && id && !id.is_a?(String)
|
|
164
|
+
candidates_by_number(id)
|
|
165
|
+
else
|
|
166
|
+
idx
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Narrowing key: the base *document's* number as a string. `#root` walks a
|
|
171
|
+
# supplement/amendment/corrigendum's `.base` chain to the origin (and
|
|
172
|
+
# returns self for a base document), so a document and all its wrappers
|
|
173
|
+
# share one key and cluster together. `.to_s` because the key is compared
|
|
174
|
+
# as a string (a pubid number Component is not `<`/`>`-comparable), and
|
|
175
|
+
# FileIO sorts the index by this exact same key so bsearch stays valid.
|
|
176
|
+
def candidates_by_number(id)
|
|
177
|
+
target = id.root.number.to_s
|
|
178
|
+
left = bsearch_left(target)
|
|
179
|
+
return [] unless left
|
|
180
|
+
|
|
181
|
+
right = bsearch_right(target)
|
|
182
|
+
index[left...right]
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def bsearch_left(target)
|
|
186
|
+
index.bsearch_index do |item|
|
|
187
|
+
item[:id].root.number.to_s >= target
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def bsearch_right(target)
|
|
192
|
+
index.bsearch_index do |item|
|
|
193
|
+
item[:id].root.number.to_s > target
|
|
194
|
+
end || index.size
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# The query is the reference, so two identifiers take the subset match.
|
|
198
|
+
# See #search for the exact-equality escape hatch.
|
|
199
|
+
def match_item(item, id)
|
|
200
|
+
if item[:id].is_a?(String)
|
|
201
|
+
item[:id].include?(id.is_a?(String) ? id : id.to_s)
|
|
202
|
+
elsif id.is_a?(String)
|
|
203
|
+
item[:id].to_s.include?(id)
|
|
204
|
+
else
|
|
205
|
+
id === item[:id]
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Index
|
|
3
|
+
module Util
|
|
4
|
+
extend self
|
|
5
|
+
|
|
6
|
+
PROGNAME = "relaton-index".freeze
|
|
7
|
+
|
|
8
|
+
def method_missing(method_name, msg = nil, prog = nil, **opts, &block)
|
|
9
|
+
prog ||= self::PROGNAME
|
|
10
|
+
Relaton.logger_pool.send method_name, msg, prog, **opts, &block
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
14
|
+
Relaton.logger_pool.respond_to?(method_name) || super
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
require "zip"
|
|
5
|
+
require "relaton/logger"
|
|
6
|
+
|
|
7
|
+
require_relative "version"
|
|
8
|
+
require_relative "core/request_error"
|
|
9
|
+
require_relative "index/file_storage"
|
|
10
|
+
require_relative "index/config"
|
|
11
|
+
require_relative "index/util"
|
|
12
|
+
require_relative "index/pool"
|
|
13
|
+
require_relative "index/type"
|
|
14
|
+
require_relative "index/file_io"
|
|
15
|
+
require_relative "index/shard_source"
|
|
16
|
+
|
|
17
|
+
module Relaton
|
|
18
|
+
module Index
|
|
19
|
+
class Error < StandardError; end
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
#
|
|
23
|
+
# Proxy for Pool#type
|
|
24
|
+
#
|
|
25
|
+
def find_or_create(type, **args)
|
|
26
|
+
pool.type(type, **args)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def close(type)
|
|
30
|
+
pool.remove type
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#
|
|
34
|
+
# Create new index pool object or return existing
|
|
35
|
+
#
|
|
36
|
+
# @return [Relaton::Index::Pool] index pool
|
|
37
|
+
#
|
|
38
|
+
def pool
|
|
39
|
+
@pool ||= Pool.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# Create new config object or return existing
|
|
44
|
+
#
|
|
45
|
+
# @return [Relaton::Index::Config] config object
|
|
46
|
+
#
|
|
47
|
+
def config
|
|
48
|
+
@config ||= Config.new
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# Configure Relaton::Index
|
|
53
|
+
#
|
|
54
|
+
# @return [void]
|
|
55
|
+
#
|
|
56
|
+
def configure
|
|
57
|
+
yield config
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Isbn
|
|
3
|
+
class Isbn
|
|
4
|
+
#
|
|
5
|
+
# Create ISBN object.
|
|
6
|
+
#
|
|
7
|
+
# @param [String] isbn ISBN 13 number
|
|
8
|
+
#
|
|
9
|
+
def initialize(isbn)
|
|
10
|
+
@isbn = isbn&.delete("-")&.sub(/^ISBN[\s:]/i, "")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def parse
|
|
14
|
+
convert_to13
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def check?
|
|
18
|
+
case @isbn
|
|
19
|
+
when /^\d{9}[\dX]$/i then check10?
|
|
20
|
+
when /^\d{13}$/ then check13?
|
|
21
|
+
else false
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def check10?
|
|
26
|
+
@isbn[9] == calc_check_digit10
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def check13?
|
|
30
|
+
@isbn[12] == calc_check_digit13
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def calc_check_digit10
|
|
34
|
+
sum = 0
|
|
35
|
+
@isbn[..-2].chars.each_with_index do |c, i|
|
|
36
|
+
sum += c.to_i * (10 - i)
|
|
37
|
+
end
|
|
38
|
+
chk = (11 - sum % 11) % 11
|
|
39
|
+
chk == 10 ? "X" : chk.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def calc_check_digit13
|
|
43
|
+
sum = 0
|
|
44
|
+
@isbn[..-2].chars.each_with_index do |c, i|
|
|
45
|
+
sum += c.to_i * (i.even? ? 1 : 3)
|
|
46
|
+
end
|
|
47
|
+
((10 - sum % 10) % 10).to_s
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def convert_to13
|
|
51
|
+
return unless check?
|
|
52
|
+
|
|
53
|
+
return @isbn if @isbn.size == 13
|
|
54
|
+
|
|
55
|
+
@isbn = "978#{@isbn}"
|
|
56
|
+
@isbn[12] = calc_check_digit13
|
|
57
|
+
@isbn
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Isbn
|
|
3
|
+
#
|
|
4
|
+
# Search ISBN in Openlibrary.
|
|
5
|
+
#
|
|
6
|
+
module OpenLibrary
|
|
7
|
+
extend self
|
|
8
|
+
|
|
9
|
+
ENDPOINT = "http://openlibrary.org/api/volumes/brief/isbn/".freeze
|
|
10
|
+
|
|
11
|
+
def get(ref, _date = nil, _opts = {}) # rubocop:disable Metrics/MethodLength
|
|
12
|
+
Util.info "Fetching from OpenLibrary ...", key: ref
|
|
13
|
+
|
|
14
|
+
isbn = Isbn.new(ref).parse
|
|
15
|
+
unless isbn
|
|
16
|
+
Util.info "Incorrect ISBN.", key: ref
|
|
17
|
+
return
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
resp = request_api isbn
|
|
21
|
+
unless resp
|
|
22
|
+
Util.info "Not found.", key: ref
|
|
23
|
+
return
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
bib = Parser.parse resp
|
|
27
|
+
Util.info "Found: `#{bib.docidentifier.first.content}`", key: ref
|
|
28
|
+
bib
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def request_api(isbn)
|
|
32
|
+
uri = URI "#{ENDPOINT}#{isbn}.json"
|
|
33
|
+
response = Net::HTTP.get_response uri
|
|
34
|
+
return unless response.is_a? Net::HTTPSuccess
|
|
35
|
+
|
|
36
|
+
data = JSON.parse response.body
|
|
37
|
+
return unless data["records"]&.any?
|
|
38
|
+
|
|
39
|
+
data["records"].first.last
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Isbn
|
|
3
|
+
#
|
|
4
|
+
# OpenLibrary document parser.
|
|
5
|
+
#
|
|
6
|
+
class Parser
|
|
7
|
+
ATTRS = %i[fetched title docidentifier source contributor date place ext].freeze
|
|
8
|
+
|
|
9
|
+
def initialize(doc)
|
|
10
|
+
@doc = doc
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.parse(doc)
|
|
14
|
+
new(doc).parse
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def parse
|
|
18
|
+
args = ATTRS.each_with_object({}) { |a, h| h[a] = send(a) }
|
|
19
|
+
Bib::ItemData.new(**args)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def fetched = Date.today.to_s
|
|
25
|
+
|
|
26
|
+
def title
|
|
27
|
+
t = [Bib::Title.new(content: @doc["data"]["title"], type: "main")]
|
|
28
|
+
if @doc["data"]["subtitle"]
|
|
29
|
+
t << Bib::Title.new(content: @doc["data"]["subtitle"], type: "subtitle")
|
|
30
|
+
end
|
|
31
|
+
t
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def docidentifier
|
|
35
|
+
isbn = @doc["details"]["bib_key"].split(":").last
|
|
36
|
+
[Bib::Docidentifier.new(content: isbn, type: "ISBN", primary: true)]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def source
|
|
40
|
+
[Bib::Uri.new(content: @doc["recordURL"], type: "src")]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def contributor
|
|
44
|
+
create_authors + creaate_publishers
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def create_authors
|
|
48
|
+
@doc["data"]["authors"].map do |a|
|
|
49
|
+
name = Bib::FullName.new(
|
|
50
|
+
completename: Bib::LocalizedString.new(content: a["name"]),
|
|
51
|
+
)
|
|
52
|
+
person = Bib::Person.new(
|
|
53
|
+
name: name,
|
|
54
|
+
uri: a["url"] ? [Bib::Uri.new(content: a["url"])] : [],
|
|
55
|
+
)
|
|
56
|
+
Bib::Contributor.new(
|
|
57
|
+
person: person,
|
|
58
|
+
role: [Bib::Contributor::Role.new(type: "author")],
|
|
59
|
+
)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def creaate_publishers
|
|
64
|
+
@doc["data"]["publishers"].map do |p|
|
|
65
|
+
org = Bib::Organization.new(
|
|
66
|
+
name: [Bib::TypedLocalizedString.new(content: p["name"])],
|
|
67
|
+
)
|
|
68
|
+
Bib::Contributor.new(
|
|
69
|
+
organization: org,
|
|
70
|
+
role: [Bib::Contributor::Role.new(type: "publisher")],
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def date
|
|
76
|
+
@doc["publishDates"].map { Bib::Date.new type: "published", at: _1 }
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def place
|
|
80
|
+
@doc["data"]["publish_places"]&.map { Bib::Place.new city: _1["name"] }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def ext
|
|
84
|
+
Bib::Ext.new(flavor: "isbn")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|