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,561 @@
|
|
|
1
|
+
require "etc"
|
|
2
|
+
require "parallel"
|
|
3
|
+
require "pubid"
|
|
4
|
+
require "pubid/ietf"
|
|
5
|
+
require "relaton/core"
|
|
6
|
+
require_relative "../ietf"
|
|
7
|
+
require_relative "bibxml_parser"
|
|
8
|
+
require_relative "rfc/index"
|
|
9
|
+
require_relative "rfc/entry"
|
|
10
|
+
require_relative "wg_name_resolver"
|
|
11
|
+
|
|
12
|
+
module Relaton
|
|
13
|
+
module Ietf
|
|
14
|
+
class DataFetcher < Core::DataFetcher
|
|
15
|
+
#
|
|
16
|
+
# Fetch documents
|
|
17
|
+
#
|
|
18
|
+
def fetch(source)
|
|
19
|
+
@source = source
|
|
20
|
+
case source
|
|
21
|
+
when "ietf-rfcsubseries" then fetch_ieft_rfcsubseries
|
|
22
|
+
when "ietf-internet-drafts" then fetch_ieft_internet_drafts
|
|
23
|
+
when "ietf-rfc-entries" then fetch_ieft_rfcs
|
|
24
|
+
end
|
|
25
|
+
index.save
|
|
26
|
+
report_unindexed
|
|
27
|
+
report_unparsed
|
|
28
|
+
report_collisions
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# The published index is the pubid-structured `index-v2` (relaton#109).
|
|
34
|
+
# `pubid_class:` is not decoration: `FileIO#save` serialises an id to its
|
|
35
|
+
# `_type:` hash only when it is an instance of the configured class, so
|
|
36
|
+
# without it — or without parsing the id below — this writes a v1-shaped
|
|
37
|
+
# file under a v2 name.
|
|
38
|
+
# `url: nil` is load-bearing, not decoration. Scraper opens the same
|
|
39
|
+
# `:IETF` pool key with a `url:`, and `Type#actual?` skips the URL check
|
|
40
|
+
# when the caller omits it (`!args.key?(:url)`) — so in a process where a
|
|
41
|
+
# lookup ran first, omitting it here would hand the crawl the
|
|
42
|
+
# remote-backed Type and `save` would write to `~/.relaton/ietf/` instead
|
|
43
|
+
# of `./`, publishing no index at all. Passing it explicitly forces a
|
|
44
|
+
# local-file Type.
|
|
45
|
+
def index
|
|
46
|
+
@index ||= Relaton::Index.find_or_create(
|
|
47
|
+
:IETF, url: nil, file: "#{INDEXFILE}.yaml",
|
|
48
|
+
pubid_class: ::Pubid::Ietf::Identifier
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
#
|
|
53
|
+
# Fetches ietf-rfcsubseries documents
|
|
54
|
+
#
|
|
55
|
+
def fetch_ieft_rfcsubseries
|
|
56
|
+
idx = Rfc::Index.from_xml(rfc_index)
|
|
57
|
+
# Keyed by the normalised doc-id, built once for the whole crawl:
|
|
58
|
+
# `Entry` looks constituents up by `Entry.squish(ref)`, and doing it
|
|
59
|
+
# per-entry over ~9,800 RFCs would rebuild this table 367 times.
|
|
60
|
+
rfc_map = (idx.rfc_entries || []).each_with_object({}) do |entry, h|
|
|
61
|
+
key = Rfc::Entry.squish(entry.doc_id)
|
|
62
|
+
if h.key?(key)
|
|
63
|
+
Util.warn "Duplicate RFC doc-id `#{entry.doc_id}` after normalisation " \
|
|
64
|
+
"(`#{key}`); the later entry wins for constituent lookup"
|
|
65
|
+
end
|
|
66
|
+
h[key] = entry
|
|
67
|
+
end
|
|
68
|
+
idx.subseries_entries.each do |entry|
|
|
69
|
+
save_doc entry.to_item(rfc_map, wg_names: wg_names)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
# Fetches ietf-internet-drafts documents.
|
|
75
|
+
#
|
|
76
|
+
# Each work unit (one series, or one singleton XML) is processed
|
|
77
|
+
# end-to-end in a worker process: parse → link relations → serialize →
|
|
78
|
+
# write. Workers return Marshal-friendly index entries; the parent
|
|
79
|
+
# collects them and updates `Relaton::Index` and the duplicate-check set
|
|
80
|
+
# serially. Set `RELATON_IETF_PARALLEL_WORKERS=0` to force serial
|
|
81
|
+
# execution (useful for tests and debugging).
|
|
82
|
+
#
|
|
83
|
+
def fetch_ieft_internet_drafts
|
|
84
|
+
series_groups, singleton_paths = group_draft_paths
|
|
85
|
+
# Workers fork from here, so `unique_output_file`'s reservation cannot
|
|
86
|
+
# see a peer's claim and `write_unique` must never overwrite. Set
|
|
87
|
+
# before the first fork, so the children inherit it.
|
|
88
|
+
@cross_process = true
|
|
89
|
+
|
|
90
|
+
series_results = parallelize(series_groups.to_a) do |(series, paths_info)|
|
|
91
|
+
process_series(series, paths_info)
|
|
92
|
+
end.flatten(1)
|
|
93
|
+
|
|
94
|
+
singleton_results = parallelize(singleton_paths) do |path|
|
|
95
|
+
process_singleton(path)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
entries, unparsed = (series_results + singleton_results).compact
|
|
99
|
+
.partition { |r| r[:unparsed].nil? }
|
|
100
|
+
# Tallied here, not in the worker: a counter incremented in a Parallel
|
|
101
|
+
# worker process is lost on the way back (see record_index_entry).
|
|
102
|
+
@unparsed = unparsed.map { |r| "#{r[:unparsed]} (#{r[:error]})" }
|
|
103
|
+
reconcile_output_files entries
|
|
104
|
+
entries.each { |r| record_index_entry(r) }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
#
|
|
108
|
+
# Run `block` once per item, in parallel worker processes when configured.
|
|
109
|
+
# `Parallel.map(items, in_processes: 0)` runs synchronously in the
|
|
110
|
+
# current process, which keeps tests deterministic and lets mocks work.
|
|
111
|
+
#
|
|
112
|
+
def parallelize(items, &block)
|
|
113
|
+
Parallel.map(items, in_processes: worker_count, &block)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def worker_count
|
|
117
|
+
ENV.fetch("RELATON_IETF_PARALLEL_WORKERS", Etc.nprocessors.to_s).to_i
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
#
|
|
121
|
+
# Filename-only scan: group versioned drafts by normalized series stem;
|
|
122
|
+
# everything else (non-versioned, non-`D.draft-`) goes to singletons.
|
|
123
|
+
# No XML parsing happens here — workers do that.
|
|
124
|
+
#
|
|
125
|
+
# @return [Array(Hash, Array<String>)]
|
|
126
|
+
# series_groups: { normalized_series => [{path, ver, ref}, ...] }
|
|
127
|
+
# singleton_paths: [path, ...]
|
|
128
|
+
#
|
|
129
|
+
def group_draft_paths
|
|
130
|
+
series_groups = {}
|
|
131
|
+
singleton_paths = []
|
|
132
|
+
Dir["bibxml-ids/*.xml"].each do |path|
|
|
133
|
+
file = File.basename(path, ".xml")
|
|
134
|
+
is_draft = file.include?("D.draft-")
|
|
135
|
+
ver = is_draft ? file[/(\d+)$/, 1] : nil
|
|
136
|
+
ref = file.sub(/^reference\.I-D\./, "").downcase
|
|
137
|
+
stem_match = is_draft && ver ? /^(draft-.+)-(\d{2})$/.match(ref) : nil
|
|
138
|
+
if stem_match
|
|
139
|
+
series = stem_match[1].gsub(/[.\s\/:-]+/, "-")
|
|
140
|
+
(series_groups[series] ||= []) << { path: path, ver: ver, ref: ref }
|
|
141
|
+
else
|
|
142
|
+
singleton_paths << path
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
[series_groups, singleton_paths]
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
#
|
|
149
|
+
# Worker: parse all files in a series, sort by version, append
|
|
150
|
+
# immediate-neighbor relations (skipped for bibxml), write each version
|
|
151
|
+
# and the un-versioned aggregator doc. Returns an array of index entries
|
|
152
|
+
# for the parent.
|
|
153
|
+
#
|
|
154
|
+
def process_series(series, paths_info)
|
|
155
|
+
parsed = paths_info.sort_by { |p| p[:ver].to_i }.map do |p|
|
|
156
|
+
bib, marker = parse_bibxml(p[:path])
|
|
157
|
+
next marker unless bib
|
|
158
|
+
|
|
159
|
+
bib.version = [Bib::Version.new(draft: p[:ver])]
|
|
160
|
+
p.merge(bib: bib, source: bib.source)
|
|
161
|
+
end
|
|
162
|
+
# A file that failed to parse must not reach `sorted`:
|
|
163
|
+
# link_neighbor_relations and build_unversioned_doc both dereference
|
|
164
|
+
# `entry[:bib]`, and a dropped version is better than a nil one.
|
|
165
|
+
sorted, skipped = parsed.partition { |e| e[:unparsed].nil? }
|
|
166
|
+
link_neighbor_relations(sorted) if @format != "bibxml"
|
|
167
|
+
|
|
168
|
+
results = sorted.map { |entry| serialize_and_write(entry[:bib]) }
|
|
169
|
+
results << serialize_and_write(build_unversioned_doc(series, sorted)) if @format != "bibxml"
|
|
170
|
+
results.compact + skipped
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
#
|
|
174
|
+
# Worker: parse + serialize + write a single non-grouped XML.
|
|
175
|
+
#
|
|
176
|
+
def process_singleton(path)
|
|
177
|
+
file = File.basename(path, ".xml")
|
|
178
|
+
is_draft = file.include?("D.draft-")
|
|
179
|
+
ver = is_draft ? file[/(\d+)$/, 1] : nil
|
|
180
|
+
bib, marker = parse_bibxml(path)
|
|
181
|
+
return marker unless bib
|
|
182
|
+
|
|
183
|
+
bib.version = [Bib::Version.new(draft: ver)] if ver
|
|
184
|
+
serialize_and_write(bib)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
#
|
|
188
|
+
# Read and parse one bibxml file, or nil if it cannot be parsed.
|
|
189
|
+
#
|
|
190
|
+
# Rescues `StandardError` rather than a narrow list on purpose: lutaml
|
|
191
|
+
# raises `InvalidFormatError` on bad bytes, but the converter also runs
|
|
192
|
+
# regexes over parsed text (`parse_surname_initials` and friends), and
|
|
193
|
+
# those raise `ArgumentError: invalid byte sequence` on anything that slips
|
|
194
|
+
# through. One unparseable file must cost one document, never the crawl —
|
|
195
|
+
# the drafts path runs under Parallel.map, which discards every result from
|
|
196
|
+
# the pass when a worker raises.
|
|
197
|
+
#
|
|
198
|
+
# @param path [String]
|
|
199
|
+
# @return [Relaton::Ietf::ItemData, nil]
|
|
200
|
+
#
|
|
201
|
+
# @param path [String]
|
|
202
|
+
# @return [Array(Relaton::Ietf::ItemData, nil), Array(nil, Hash)]
|
|
203
|
+
# the record, or nil plus a marker carrying why
|
|
204
|
+
def parse_bibxml(path)
|
|
205
|
+
bib = BibXMLParser.parse(read_bibxml(path))
|
|
206
|
+
bib ? [bib, nil] : [nil, unparsed_marker(path, "parser returned no record")]
|
|
207
|
+
rescue StandardError => e
|
|
208
|
+
[nil, unparsed_marker(path, "#{e.class}: #{e.message.to_s.lines.first.to_s.strip}")]
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Marshal-friendly stand-in for a record, carried back to the parent so the
|
|
212
|
+
# skip can be counted where a tally survives. The reason rides along rather
|
|
213
|
+
# than sitting in an ivar, which a later file would overwrite.
|
|
214
|
+
def unparsed_marker(path, error)
|
|
215
|
+
{ unparsed: path, error: error }
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
#
|
|
219
|
+
# Read a bibxml file as UTF-8, recovering Windows-1252 bytes.
|
|
220
|
+
#
|
|
221
|
+
# These files declare `encoding='UTF-8'` but some carry CP1252 — smart
|
|
222
|
+
# quotes and accented Latin letters. `File.read(encoding: "UTF-8")` only
|
|
223
|
+
# *tags* the string, so those reach lutaml as invalid UTF-8 and it raises.
|
|
224
|
+
#
|
|
225
|
+
# `scrub` with a block transcodes each invalid *run* as CP1252 while
|
|
226
|
+
# leaving valid UTF-8 untouched. Both halves matter:
|
|
227
|
+
#
|
|
228
|
+
# * Not plain `scrub`, which substitutes U+FFFD: `client’s` would become
|
|
229
|
+
# `client\uFFFDs` and `Muñoz` `Mu\uFFFDoz` — author surnames included.
|
|
230
|
+
# The damage is length-preserving, so a length check will not catch it.
|
|
231
|
+
# * Not a whole-file CP1252 re-decode, which mangles a file that is
|
|
232
|
+
# genuinely UTF-8 apart from one stray byte: `Muñoz café ’` would come
|
|
233
|
+
# back as `Muñoz café ’`, silently, since the result is valid UTF-8 and
|
|
234
|
+
# nothing raises. No such file exists in today's corpus (0 of the 125
|
|
235
|
+
# affected contain valid multi-byte UTF-8) but it grows daily, and
|
|
236
|
+
# "decodes losslessly as CP1252" is weak evidence of correctness —
|
|
237
|
+
# CP1252 maps 251 of 256 byte values.
|
|
238
|
+
#
|
|
239
|
+
# `undef: :replace` covers the five bytes CP1252 leaves undefined
|
|
240
|
+
# (0x81 0x8D 0x8F 0x90 0x9D), so this returns valid UTF-8 rather than
|
|
241
|
+
# raising and costing the whole file.
|
|
242
|
+
#
|
|
243
|
+
# @param path [String]
|
|
244
|
+
# @return [String] UTF-8, valid encoding
|
|
245
|
+
#
|
|
246
|
+
def read_bibxml(path)
|
|
247
|
+
utf8 = File.binread(path).force_encoding(Encoding::UTF_8)
|
|
248
|
+
return utf8 if utf8.valid_encoding?
|
|
249
|
+
|
|
250
|
+
utf8.scrub do |bad|
|
|
251
|
+
bad.force_encoding(Encoding::WINDOWS_1252)
|
|
252
|
+
.encode(Encoding::UTF_8, undef: :replace)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
#
|
|
257
|
+
# Append immediate-neighbor `updates` / `updatedBy` relations in memory.
|
|
258
|
+
# Single-version series get no relations (no neighbors).
|
|
259
|
+
#
|
|
260
|
+
def link_neighbor_relations(sorted)
|
|
261
|
+
sorted.each_with_index do |entry, i|
|
|
262
|
+
if i.positive?
|
|
263
|
+
prev = sorted[i - 1]
|
|
264
|
+
entry[:bib].relation << version_relation({ ref: prev[:ref], source: prev[:source] }, "updates")
|
|
265
|
+
end
|
|
266
|
+
if i < sorted.size - 1
|
|
267
|
+
nxt = sorted[i + 1]
|
|
268
|
+
entry[:bib].relation << version_relation({ ref: nxt[:ref], source: nxt[:source] }, "updatedBy")
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
#
|
|
274
|
+
# Build (but do not write) the un-versioned series aggregator doc with
|
|
275
|
+
# `includes` relations to every version. Uses the latest version's
|
|
276
|
+
# title/abstract from memory.
|
|
277
|
+
#
|
|
278
|
+
# The aggregator is *synthesised* — there is no upstream document for it,
|
|
279
|
+
# so `date`, `ext` (hence doctype) and `source` can only be inherited from
|
|
280
|
+
# its newest constituent, which `sorted` already holds in memory. Without
|
|
281
|
+
# that inheritance it publishes undated (and so unsorted on the Pages
|
|
282
|
+
# index, which sorts by date) and with no document type at all.
|
|
283
|
+
#
|
|
284
|
+
# @return [Relaton::Ietf::ItemData, nil]
|
|
285
|
+
#
|
|
286
|
+
def build_unversioned_doc(series, sorted)
|
|
287
|
+
if sorted.empty?
|
|
288
|
+
Util.warn "No versions found for #{series}"
|
|
289
|
+
return nil
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
last_v = sorted.last[:bib]
|
|
293
|
+
docid = Bib::Docidentifier.new(type: "Internet-Draft", content: series, primary: true)
|
|
294
|
+
rel = sorted.map { |e| version_relation({ ref: e[:ref], source: e[:source] }, "includes") }
|
|
295
|
+
ItemData.new(
|
|
296
|
+
title: last_v.title, abstract: last_v.abstract, formattedref: Bib::Formattedref.new(content: series),
|
|
297
|
+
docidentifier: [docid], relation: rel,
|
|
298
|
+
# dup'd, not shared: these are the newest version's own objects, and
|
|
299
|
+
# aliasing them would make any later edit to the aggregator mutate the
|
|
300
|
+
# `-NN` record too.
|
|
301
|
+
date: last_v.date&.dup, ext: last_v.ext&.dup, source: last_v.source&.dup
|
|
302
|
+
)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
#
|
|
306
|
+
# Create bibitem relation
|
|
307
|
+
#
|
|
308
|
+
# @param [Hash] ver version reference, { ref:, source: }
|
|
309
|
+
# @param [String] type relation type
|
|
310
|
+
#
|
|
311
|
+
# @return [Relaton::Ietf::Relation] relation
|
|
312
|
+
#
|
|
313
|
+
def version_relation(ver, type)
|
|
314
|
+
docid = Bib::Docidentifier.new(type: "Internet-Draft", content: ver[:ref], primary: true)
|
|
315
|
+
bibitem = ItemData.new(formattedref: Bib::Formattedref.new(content: ver[:ref]), docidentifier: [docid], source: ver[:source])
|
|
316
|
+
Relaton::Ietf::Relation.new(type: type, bibitem: bibitem)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
#
|
|
320
|
+
# Fetches ietf-rfc-entries documents
|
|
321
|
+
#
|
|
322
|
+
def fetch_ieft_rfcs
|
|
323
|
+
idx = Rfc::Index.from_xml(rfc_index)
|
|
324
|
+
idx.rfc_entries.each do |entry|
|
|
325
|
+
save_doc entry.to_item(nil, wg_names: wg_names)
|
|
326
|
+
rescue StandardError => e
|
|
327
|
+
Util.error "Error parsing #{entry.doc_id}: #{e.message}\n" \
|
|
328
|
+
"#{e.backtrace[0..5].join("\n")}"
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
#
|
|
333
|
+
# Get RFC index
|
|
334
|
+
#
|
|
335
|
+
# @return [Nokogiri::XML::Document] RFC index
|
|
336
|
+
#
|
|
337
|
+
def rfc_index
|
|
338
|
+
uri = URI "https://www.rfc-editor.org/rfc-index.xml"
|
|
339
|
+
Net::HTTP.get(uri)
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def wg_names
|
|
343
|
+
@wg_names ||= WgNameResolver.fetch
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
#
|
|
347
|
+
# Save document to file (sequential path: serialize, write, index).
|
|
348
|
+
# Used by the rfcsubseries / rfc-entries fetchers; the I-D fetcher splits
|
|
349
|
+
# this into worker-safe `serialize_and_write` plus parent-only
|
|
350
|
+
# `record_index_entry` so the index is touched only in the main process.
|
|
351
|
+
#
|
|
352
|
+
# @param [Relaton::Ietf::Rfc::Entry, nil] entry
|
|
353
|
+
# @param [Boolean] check_duplicate check for duplicate
|
|
354
|
+
#
|
|
355
|
+
def save_doc(entry, check_duplicate: true)
|
|
356
|
+
result = serialize_and_write(entry)
|
|
357
|
+
record_index_entry(result, check_duplicate: check_duplicate) if result
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
#
|
|
361
|
+
# Worker-safe: serialize, compute output filename, write to disk, return
|
|
362
|
+
# a Marshal-friendly hash with the docid+file pair the parent needs to
|
|
363
|
+
# update `Relaton::Index` and `@files`. Does NOT touch instance state
|
|
364
|
+
# that has to stay consistent across workers (`@files`, the index).
|
|
365
|
+
#
|
|
366
|
+
# @param [#to_yaml, #to_xml, #to_rfcxml, nil] entry
|
|
367
|
+
# @return [Hash, nil]
|
|
368
|
+
#
|
|
369
|
+
def serialize_and_write(entry) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
370
|
+
return nil unless entry
|
|
371
|
+
|
|
372
|
+
content = case @format
|
|
373
|
+
when "xml" then entry.to_xml(bibdata: true)
|
|
374
|
+
when "yaml" then entry.to_yaml
|
|
375
|
+
when "bibxml" then entry.to_rfcxml
|
|
376
|
+
else entry.send("to_#{@format}")
|
|
377
|
+
end
|
|
378
|
+
id = if entry.respond_to?(:docidentifier)
|
|
379
|
+
entry.docidentifier.detect { |i| i.type == "Internet-Draft" && i.primary }&.content
|
|
380
|
+
end
|
|
381
|
+
id ||= entry.docnumber || entry.formattedref.content
|
|
382
|
+
file = write_unique(id, content)
|
|
383
|
+
primary = entry.docidentifier.detect(&:primary) || entry.docidentifier.first
|
|
384
|
+
# `docid` is the id the file was written under and `plain_file` the name
|
|
385
|
+
# it would have taken uncontested; `reconcile_output_files` needs both.
|
|
386
|
+
# Neither is `index_id`: `id` falls back through docnumber and
|
|
387
|
+
# formattedref, so on the RFC path the two differ ("RFC0001" vs "RFC 1").
|
|
388
|
+
{ docnumber: entry.docnumber, docid: id, file: file,
|
|
389
|
+
plain_file: output_file(id), index_id: primary.content,
|
|
390
|
+
pubid: parse_pubid(primary.content) }
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
#
|
|
394
|
+
# Parse a record's primary docidentifier into the pubid the index stores.
|
|
395
|
+
#
|
|
396
|
+
# Deliberately here rather than in `record_index_entry`: this runs inside
|
|
397
|
+
# the `Parallel` workers, and a pubid identifier survives the Marshal round
|
|
398
|
+
# trip Parallel does on the return value. Parsing in the parent instead
|
|
399
|
+
# would put ~0.7 ms per record back on the serial path — some minutes over
|
|
400
|
+
# the 167k-draft crawl, all of it outside the parallelism this fetcher is
|
|
401
|
+
# built around.
|
|
402
|
+
#
|
|
403
|
+
# @param [String] content primary docidentifier content
|
|
404
|
+
# @return [Pubid::Ietf::Identifier, nil] nil when pubid rejects it
|
|
405
|
+
#
|
|
406
|
+
def parse_pubid(content)
|
|
407
|
+
::Pubid::Ietf::Identifier.parse content
|
|
408
|
+
rescue StandardError => e
|
|
409
|
+
# Full message: the tail is the part that says *what shape* pubid
|
|
410
|
+
# stopped accepting, which is the whole point of the warning.
|
|
411
|
+
Util.warn "Not indexing `#{content}`: #{e.message}"
|
|
412
|
+
nil
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
#
|
|
416
|
+
# Parent-only: dedupe-check `@files` and update `Relaton::Index`. Called
|
|
417
|
+
# serially after workers return so index updates are race-free.
|
|
418
|
+
#
|
|
419
|
+
def record_index_entry(result, check_duplicate: true)
|
|
420
|
+
if check_duplicate && @files.include?(result[:file])
|
|
421
|
+
Util.warn "File #{result[:file]} already exists. Document: #{result[:docnumber]}"
|
|
422
|
+
elsif check_duplicate
|
|
423
|
+
@files << result[:file]
|
|
424
|
+
end
|
|
425
|
+
# A record whose identifier pubid rejects is written but not indexed —
|
|
426
|
+
# never fatal. The index load is all-or-nothing (`deserialize_id` raises
|
|
427
|
+
# on the first bad id and `load_index` then rejects the *entire* index),
|
|
428
|
+
# so one malformed upstream record must cost one document, not every
|
|
429
|
+
# lookup. All 176,862 published ids parse today; this guards drift.
|
|
430
|
+
# Counted here, in the parent, because a worker's tally would be lost.
|
|
431
|
+
unless result[:pubid]
|
|
432
|
+
@unindexed = @unindexed.to_i + 1
|
|
433
|
+
return
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
index.add_or_update result[:pubid], result[:file]
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
#
|
|
440
|
+
# Settle, in the parent, which record keeps which filename.
|
|
441
|
+
#
|
|
442
|
+
# `output_file` is not injective, so distinct docids can want one path.
|
|
443
|
+
# `write_unique` refuses to clobber, but a forked worker cannot know
|
|
444
|
+
# WHICH of the clashing docids deserves the plain name — it only knows the
|
|
445
|
+
# path was taken. Left there, the winner would follow the race and the two
|
|
446
|
+
# filenames would swap between crawls, churning the data repo.
|
|
447
|
+
#
|
|
448
|
+
# So the parent decides once it can see every docid: within a group of
|
|
449
|
+
# records that wanted one path, the alphabetically first docid keeps it
|
|
450
|
+
# and the rest take their digest variant. Runs over EVERY group, not just
|
|
451
|
+
# clashing ones — a lone record that fell back to a digest path (a
|
|
452
|
+
# leftover file, any transient clash) must get its plain name back, or the
|
|
453
|
+
# published filename churns and the old file is orphaned.
|
|
454
|
+
#
|
|
455
|
+
# @param [Array<Hash>] results worker results, mutated in place so
|
|
456
|
+
# `record_index_entry` indexes the final path
|
|
457
|
+
#
|
|
458
|
+
def reconcile_output_files(results)
|
|
459
|
+
results.group_by { |r| r[:plain_file] }.each do |plain, group|
|
|
460
|
+
next if plain.nil? # hand-built results, and the bibxml format
|
|
461
|
+
|
|
462
|
+
targets = assign_output_files plain, group
|
|
463
|
+
record_collision targets
|
|
464
|
+
filled = Set.new
|
|
465
|
+
order(group, targets, plain).each do |result|
|
|
466
|
+
target = targets[result[:docid].to_s]
|
|
467
|
+
place_output_file result, target, filled.add?(target).nil?
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
# docid => the filename it should end up with. Sorting the *unique* docids
|
|
473
|
+
# leaves no tie to break, so the assignment cannot drift between crawls
|
|
474
|
+
# the way an unstable `sort_by` over the results would.
|
|
475
|
+
def assign_output_files(plain, group)
|
|
476
|
+
group.map { |r| r[:docid].to_s }.uniq.sort.each_with_index.to_h do |docid, i|
|
|
477
|
+
[docid, i.zero? ? plain : digest_output_file(docid)]
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
# Records already at their target first (they are no-ops), then the movers
|
|
482
|
+
# bound for a digest path, then the one bound for `plain`. That ordering is
|
|
483
|
+
# load-bearing: a loser may be sitting ON the plain path, and moving the
|
|
484
|
+
# winner there first would destroy it.
|
|
485
|
+
def order(group, targets, plain)
|
|
486
|
+
group.sort_by do |r|
|
|
487
|
+
target = targets[r[:docid].to_s]
|
|
488
|
+
[r[:file] == target ? 0 : 1, target == plain ? 1 : 0, r[:file].to_s]
|
|
489
|
+
end
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
#
|
|
493
|
+
# Move one record's file to the name the parent chose for it.
|
|
494
|
+
#
|
|
495
|
+
# `duplicate` means another result for the SAME docid already holds the
|
|
496
|
+
# target. Today that is one file and one warning, so drop the stray rather
|
|
497
|
+
# than publish the document twice under two names.
|
|
498
|
+
#
|
|
499
|
+
def place_output_file(result, target, duplicate)
|
|
500
|
+
file = result[:file]
|
|
501
|
+
return result[:file] = target if file.nil? || file == target
|
|
502
|
+
|
|
503
|
+
if duplicate
|
|
504
|
+
# The document is at the target whatever happens next, so the result
|
|
505
|
+
# follows it first. The stray may ALREADY be gone: two workers that
|
|
506
|
+
# both lost the race to the plain path land on one fallback name,
|
|
507
|
+
# because that name is keyed on the docid -- so the first of them
|
|
508
|
+
# renamed this very file onto the target. Leaving the result on its
|
|
509
|
+
# old name would put an index row on a path that no longer exists.
|
|
510
|
+
result[:file] = target
|
|
511
|
+
return unless File.exist?(file)
|
|
512
|
+
|
|
513
|
+
Util.warn "Duplicate document `#{result[:docid]}`: dropping #{file}, keeping #{target}"
|
|
514
|
+
return File.delete(file)
|
|
515
|
+
end
|
|
516
|
+
return unless File.exist?(file)
|
|
517
|
+
|
|
518
|
+
File.rename file, target
|
|
519
|
+
result[:file] = target
|
|
520
|
+
rescue SystemCallError => e
|
|
521
|
+
# A late failure must not throw away a multi-hour crawl. The record keeps
|
|
522
|
+
# the name it already has on disk.
|
|
523
|
+
Util.warn "Could not move #{file} to #{target}: #{e.message}"
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def record_collision(targets)
|
|
527
|
+
return if targets.size < 2
|
|
528
|
+
|
|
529
|
+
# targets.keys is already the uniqued, sorted docid list.
|
|
530
|
+
(@collisions ||= []) << targets.keys
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
# One line for a crawl that writes ~177k records, not one per collision.
|
|
534
|
+
def report_collisions
|
|
535
|
+
return if @collisions.nil? || @collisions.empty?
|
|
536
|
+
|
|
537
|
+
Util.warn "#{@collisions.size} filename collision(s): distinct docids sanitize to " \
|
|
538
|
+
"one filename and were given separate files. " \
|
|
539
|
+
"First: #{@collisions.first(5).map { |g| g.join(' <-> ') }.join('; ')}"
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
# Skips are per-record warnings in a crawl that writes ~177k of them, so
|
|
543
|
+
# restate the total where it can actually be noticed.
|
|
544
|
+
# One line for a crawl that reads ~167k files, not one per skip.
|
|
545
|
+
def report_unparsed
|
|
546
|
+
return if @unparsed.nil? || @unparsed.empty?
|
|
547
|
+
|
|
548
|
+
Util.warn "#{@unparsed.size} file(s) skipped: could not be parsed. " \
|
|
549
|
+
"First: #{@unparsed.first(5).join(', ')}"
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def report_unindexed
|
|
553
|
+
return unless @unindexed.to_i.positive?
|
|
554
|
+
|
|
555
|
+
Util.warn "#{@unindexed} document(s) written but not indexed: " \
|
|
556
|
+
"identifier not parseable by Pubid::Ietf"
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
require_relative "doctype"
|
|
2
|
+
require_relative "processing_instructions"
|
|
3
|
+
|
|
4
|
+
module Relaton
|
|
5
|
+
module Ietf
|
|
6
|
+
class Ext < Bib::Ext
|
|
7
|
+
attribute :doctype, Doctype
|
|
8
|
+
attribute :area, :string, collection: true, values: %W[
|
|
9
|
+
apt gen int ops rtg sec tsv Applications\sand\sReal-Time General
|
|
10
|
+
Internet Operations\sand\sManagement Routing Security Transport
|
|
11
|
+
]
|
|
12
|
+
attribute :stream, :string, values: %w[IAB IETF Independent IRTF Legacy Editorial]
|
|
13
|
+
attribute :ipr, :string
|
|
14
|
+
attribute :pi, ProcessingInstructions
|
|
15
|
+
attribute :consensus, :string
|
|
16
|
+
attribute :index_include, :string
|
|
17
|
+
attribute :ipr_extract, :string
|
|
18
|
+
attribute :sort_refs, :string
|
|
19
|
+
attribute :sym_refs, :string
|
|
20
|
+
attribute :toc_include, :string
|
|
21
|
+
attribute :toc_depth, :string
|
|
22
|
+
attribute :show_on_front_page, :string
|
|
23
|
+
|
|
24
|
+
xml do
|
|
25
|
+
map_element "area", to: :area
|
|
26
|
+
map_element "stream", to: :stream
|
|
27
|
+
map_element "ipr", to: :ipr
|
|
28
|
+
map_element "pi", to: :pi
|
|
29
|
+
map_element "consensus", to: :consensus
|
|
30
|
+
map_element "indexInclude", to: :index_include
|
|
31
|
+
map_element "iprExtract", to: :ipr_extract
|
|
32
|
+
map_element "sortRefs", to: :sort_refs
|
|
33
|
+
map_element "symRefs", to: :sym_refs
|
|
34
|
+
map_element "tocInclude", to: :toc_include
|
|
35
|
+
map_element "tocDepth", to: :toc_depth
|
|
36
|
+
map_element "showOnFrontPage", to: :show_on_front_page
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
key_value do
|
|
40
|
+
map_element "schema_version", to: :schema_version, render_default: true
|
|
41
|
+
map_element "doctype", to: :doctype
|
|
42
|
+
map_element "subdoctype", to: :subdoctype
|
|
43
|
+
map_element "flavor", to: :flavor
|
|
44
|
+
map_element "ics", to: :ics
|
|
45
|
+
map_element "structuredidentifier", to: :structuredidentifier
|
|
46
|
+
map_element "area", to: :area
|
|
47
|
+
map_element "stream", to: :stream
|
|
48
|
+
map_element "ipr", to: :ipr
|
|
49
|
+
map_element "pi", to: :pi
|
|
50
|
+
map_element "consensus", to: :consensus
|
|
51
|
+
map_element "index_include", to: :index_include
|
|
52
|
+
map_element "ipr_extract", to: :ipr_extract
|
|
53
|
+
map_element "sort_refs", to: :sort_refs
|
|
54
|
+
map_element "sym_refs", to: :sym_refs
|
|
55
|
+
map_element "toc_include", to: :toc_include
|
|
56
|
+
map_element "toc_depth", to: :toc_depth
|
|
57
|
+
map_element "show_on_front_page", to: :show_on_front_page
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def get_schema_version = Relaton.schema_versions["relaton-model-ietf"]
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require_relative "ext"
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Ietf
|
|
5
|
+
class Item < Bib::Item
|
|
6
|
+
model ItemData
|
|
7
|
+
|
|
8
|
+
attribute :ext, Ext
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
require_relative "relation"
|
|
14
|
+
|
|
15
|
+
Relaton::Ietf::Item.attribute :relation, Relaton::Ietf::Relation,
|
|
16
|
+
collection: true, initialize_empty: true
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Ietf
|
|
3
|
+
class ItemBase < Lutaml::Model::Serializable
|
|
4
|
+
include Bib::NamespaceHelper
|
|
5
|
+
|
|
6
|
+
attr_accessor :type
|
|
7
|
+
|
|
8
|
+
model ItemData
|
|
9
|
+
|
|
10
|
+
instance_exec(&Bib::ItemShared::ATTRIBUTES)
|
|
11
|
+
|
|
12
|
+
xml do
|
|
13
|
+
map_attribute "type", to: :type
|
|
14
|
+
instance_exec(&Bib::ItemShared::XML_BODY)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|