relaton 3.0.0.pre.alpha.1 → 3.0.0.pre.alpha.3
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/README.adoc +57 -1
- data/bin/console +0 -1
- data/lib/relaton/3gpp/bibliography.rb +82 -7
- data/lib/relaton/3gpp/data_fetcher.rb +51 -3
- data/lib/relaton/3gpp/docidentifier.rb +114 -0
- data/lib/relaton/3gpp/item.rb +6 -0
- data/lib/relaton/3gpp/parser.rb +1 -1
- data/lib/relaton/3gpp/processor.rb +4 -1
- data/lib/relaton/3gpp.rb +5 -1
- 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/model/address.rb +2 -2
- data/lib/relaton/bib/model/docidentifier.rb +24 -9
- data/lib/relaton/bib/model/localized_string.rb +1 -1
- data/lib/relaton/bib/model/structured_identifier.rb +10 -9
- data/lib/relaton/bib/sanitizer.rb +202 -6
- data/lib/relaton/bib.rb +0 -2
- data/lib/relaton/bipm/bibliography.rb +159 -10
- data/lib/relaton/bipm/data_fetcher.rb +26 -2
- data/lib/relaton/bipm/data_outcomes_parser.rb +3 -4
- data/lib/relaton/bipm/id_parser.rb +5 -4
- data/lib/relaton/bipm/model/structured_identifier.rb +21 -0
- data/lib/relaton/bipm/processor.rb +2 -2
- data/lib/relaton/bipm/rawdata_bipm_metrologia/fetcher.rb +2 -4
- data/lib/relaton/bipm/si_brochure_parser.rb +5 -3
- data/lib/relaton/bipm.rb +7 -1
- data/lib/relaton/bsi/bibliography.rb +115 -43
- data/lib/relaton/bsi/hit.rb +14 -0
- data/lib/relaton/bsi/hit_collection.rb +15 -16
- data/lib/relaton/bsi/model/docidentifier.rb +107 -1
- data/lib/relaton/bsi/processor.rb +1 -0
- data/lib/relaton/calconnect/bibliography.rb +12 -14
- data/lib/relaton/calconnect/data_fetcher.rb +77 -9
- data/lib/relaton/calconnect/docidentifier.rb +80 -0
- data/lib/relaton/calconnect/hit_collection.rb +65 -57
- data/lib/relaton/calconnect/model/item.rb +7 -0
- data/lib/relaton/calconnect/processor.rb +7 -1
- data/lib/relaton/calconnect.rb +11 -1
- data/lib/relaton/ccsds/data/fetcher.rb +17 -12
- data/lib/relaton/ccsds/data/parser.rb +1 -1
- data/lib/relaton/ccsds/hit_collection.rb +6 -1
- data/lib/relaton/ccsds/model/docidentifier.rb +121 -0
- data/lib/relaton/ccsds/model/item.rb +2 -0
- data/lib/relaton/cen/bibliography.rb +75 -47
- data/lib/relaton/cen/hit.rb +16 -1
- data/lib/relaton/cen/hit_collection.rb +59 -11
- data/lib/relaton/cen/model/docidentifier.rb +92 -1
- data/lib/relaton/cen/processor.rb +13 -8
- data/lib/relaton/cen/scraper.rb +13 -5
- data/lib/relaton/cen.rb +1 -0
- data/lib/relaton/cie/data_fetcher.rb +215 -30
- data/lib/relaton/cie/processor.rb +3 -1
- data/lib/relaton/cie/scrapper.rb +15 -2
- data/lib/relaton/cie.rb +2 -1
- data/lib/relaton/core/data_fetcher.rb +150 -3
- data/lib/relaton/core/governor.rb +320 -0
- data/lib/relaton/core/pacer.rb +134 -0
- data/lib/relaton/core/processor.rb +19 -0
- data/lib/relaton/core/request_error.rb +14 -0
- data/lib/relaton/core.rb +3 -0
- data/lib/relaton/db/registry.rb +41 -1
- data/lib/relaton/doi/crossref.rb +19 -2
- data/lib/relaton/doi/parser.rb +109 -15
- 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/bibliography.rb +93 -25
- data/lib/relaton/ecma/data_fetcher.rb +71 -12
- data/lib/relaton/ecma/docidentifier.rb +124 -0
- data/lib/relaton/ecma/item.rb +2 -0
- data/lib/relaton/ecma/memento_parser.rb +1 -1
- data/lib/relaton/ecma/page_fetcher.rb +15 -3
- data/lib/relaton/ecma/parser_common.rb +2 -2
- data/lib/relaton/ecma/processor.rb +4 -1
- data/lib/relaton/ecma/standard_parser.rb +2 -2
- data/lib/relaton/ecma.rb +10 -1
- data/lib/relaton/etsi/bibliography.rb +67 -2
- data/lib/relaton/etsi/data_fetcher.rb +43 -4
- data/lib/relaton/etsi/processor.rb +3 -1
- data/lib/relaton/etsi.rb +2 -1
- data/lib/relaton/gb/bibliography.rb +55 -29
- data/lib/relaton/gb/docidentifier.rb +58 -9
- data/lib/relaton/gb/processor.rb +3 -0
- data/lib/relaton/gb/scraper.rb +27 -10
- 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/bibliography.rb +67 -14
- data/lib/relaton/iana/data_fetcher.rb +35 -5
- data/lib/relaton/iana/processor.rb +3 -1
- data/lib/relaton/iana.rb +12 -1
- data/lib/relaton/iec/data_fetcher.rb +7 -1
- data/lib/relaton/iec/hit_collection.rb +1 -1
- data/lib/relaton/iec/model/docidentifier.rb +9 -5
- data/lib/relaton/iec/model/ext.rb +2 -2
- data/lib/relaton/iec/processor.rb +1 -0
- data/lib/relaton/ieee/bibliography.rb +25 -3
- data/lib/relaton/ieee/data_fetcher.rb +158 -17
- data/lib/relaton/ieee/idams_parser.rb +18 -11
- data/lib/relaton/ieee/processor.rb +4 -1
- data/lib/relaton/ieee/rawbib_id_parser.rb +291 -86
- data/lib/relaton/ieee.rb +2 -1
- data/lib/relaton/ietf/data_fetcher.rb +295 -12
- data/lib/relaton/ietf/processor.rb +7 -3
- data/lib/relaton/ietf/rfc/entry.rb +39 -3
- data/lib/relaton/ietf/scraper.rb +69 -36
- data/lib/relaton/ietf.rb +4 -1
- data/lib/relaton/iho/bibliography.rb +1 -1
- data/lib/relaton/iho/docidentifier.rb +1 -1
- data/lib/relaton/index/file_io.rb +11 -11
- data/lib/relaton/index/file_storage.rb +6 -1
- data/lib/relaton/index/pool.rb +6 -1
- data/lib/relaton/index/shard_source.rb +201 -0
- data/lib/relaton/index/type.rb +63 -12
- data/lib/relaton/index.rb +2 -1
- data/lib/relaton/iso/bibliography.rb +20 -15
- data/lib/relaton/iso/data_fetcher.rb +3 -3
- data/lib/relaton/iso/data_parser.rb +17 -3
- data/lib/relaton/iso/hit_collection.rb +27 -15
- data/lib/relaton/iso/item_data.rb +22 -0
- data/lib/relaton/iso/model/docidentifier.rb +24 -12
- data/lib/relaton/iso/processor.rb +1 -0
- data/lib/relaton/iso/scraper.rb +19 -3
- data/lib/relaton/itu/bibliography.rb +9 -4
- data/lib/relaton/itu/data_crawler_r.rb +664 -0
- data/lib/relaton/itu/data_fetcher.rb +496 -50
- data/lib/relaton/itu/data_merge_r.rb +149 -0
- data/lib/relaton/itu/data_parser_r.rb +163 -89
- 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 +9 -3
- data/lib/relaton/itu/hit_collection.rb +258 -86
- data/lib/relaton/itu/model/docidentifier.rb +67 -1
- data/lib/relaton/itu/model/structured_identifier.rb +19 -0
- data/lib/relaton/itu/processor.rb +10 -4
- data/lib/relaton/itu/pubid.rb +27 -5
- data/lib/relaton/itu/recommendation_fields.rb +334 -0
- data/lib/relaton/itu/recommendation_parser.rb +18 -149
- data/lib/relaton/itu/scraper.rb +13 -3
- data/lib/relaton/itu.rb +2 -1
- 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/bibliography.rb +8 -10
- data/lib/relaton/jis/data_fetcher.rb +21 -19
- data/lib/relaton/jis/docidentifier.rb +104 -5
- data/lib/relaton/jis/hit.rb +18 -23
- data/lib/relaton/jis/hit_collection.rb +19 -18
- data/lib/relaton/jis/processor.rb +1 -1
- data/lib/relaton/jis.rb +2 -3
- data/lib/relaton/logger/channels/gh_issue.rb +78 -13
- data/lib/relaton/nist/data_fetcher.rb +63 -13
- data/lib/relaton/nist/docidentifier.rb +165 -0
- data/lib/relaton/nist/item.rb +2 -0
- data/lib/relaton/nist/item_base.rb +16 -0
- data/lib/relaton/nist/mods_parser.rb +38 -12
- data/lib/relaton/nist/processor.rb +2 -1
- data/lib/relaton/nist/relation.rb +3 -0
- data/lib/relaton/nist/scraper.rb +6 -3
- data/lib/relaton/oasis/bibliography.rb +147 -6
- data/lib/relaton/oasis/data_fetcher.rb +41 -5
- data/lib/relaton/oasis/data_parser_utils.rb +37 -3
- data/lib/relaton/oasis/docidentifier.rb +54 -0
- data/lib/relaton/oasis/item.rb +3 -0
- data/lib/relaton/oasis/processor.rb +7 -1
- data/lib/relaton/oasis.rb +14 -1
- data/lib/relaton/ogc/data_fetcher.rb +23 -2
- data/lib/relaton/ogc/docidentifier.rb +105 -0
- data/lib/relaton/ogc/hit_collection.rb +78 -3
- data/lib/relaton/ogc/processor.rb +2 -1
- data/lib/relaton/ogc.rb +5 -1
- data/lib/relaton/oiml/bibliography.rb +90 -15
- data/lib/relaton/oiml/docidentifier.rb +18 -3
- data/lib/relaton/omg/docidentifier.rb +67 -0
- data/lib/relaton/omg/item.rb +1 -0
- data/lib/relaton/omg/processor.rb +1 -0
- data/lib/relaton/omg/scraper.rb +61 -16
- data/lib/relaton/omg.rb +1 -0
- data/lib/relaton/plateau/bibliography.rb +10 -3
- data/lib/relaton/plateau/data_fetcher.rb +25 -2
- data/lib/relaton/plateau/handbook_parser.rb +8 -1
- data/lib/relaton/plateau/hit.rb +10 -2
- data/lib/relaton/plateau/hit_collection.rb +31 -11
- data/lib/relaton/plateau/processor.rb +3 -1
- data/lib/relaton/plateau/technical_report_parser.rb +8 -1
- data/lib/relaton/plateau.rb +2 -1
- 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/version.rb +1 -1
- data/lib/relaton/w3c/bibliography.rb +132 -12
- data/lib/relaton/w3c/data_fetcher.rb +194 -16
- data/lib/relaton/w3c/data_parser.rb +3 -3
- data/lib/relaton/w3c/docidentifier.rb +48 -0
- data/lib/relaton/w3c/governor.rb +32 -0
- data/lib/relaton/w3c/item.rb +3 -0
- data/lib/relaton/w3c/pubid.rb +12 -0
- data/lib/relaton/w3c/safe_realize.rb +110 -21
- data/lib/relaton/w3c.rb +12 -1
- data/lib/relaton/xsf/bibliography.rb +61 -1
- data/lib/relaton/xsf/data_fetcher.rb +55 -5
- data/lib/relaton/xsf/docidentifier.rb +46 -0
- data/lib/relaton/xsf/hit_collection.rb +31 -3
- data/lib/relaton/xsf/item.rb +6 -0
- data/lib/relaton/xsf/processor.rb +1 -0
- data/lib/relaton/xsf.rb +5 -1
- data/lib/relaton.rb +42 -0
- metadata +135 -24
- data/lib/relaton/ieee/pub_id.rb +0 -161
- data/lib/relaton/index/id_number.rb +0 -30
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require "mechanize"
|
|
2
|
-
require_relative "id_parser"
|
|
3
2
|
|
|
4
3
|
module Relaton::Bipm
|
|
5
4
|
class Bibliography
|
|
@@ -46,11 +45,14 @@ module Relaton::Bipm
|
|
|
46
45
|
# @return [RelatonBipm::BipmBibliographicItem]
|
|
47
46
|
#
|
|
48
47
|
def get_bipm(reference) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
49
|
-
|
|
50
|
-
rows =
|
|
51
|
-
return
|
|
48
|
+
pubid = parse_ref reference
|
|
49
|
+
rows = search_index pubid, reference
|
|
50
|
+
return if rows.empty?
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
# Latest edition wins. Metrologia and SI Brochure rows carry no year,
|
|
53
|
+
# so they all score 0; the file path breaks that tie so a repeated
|
|
54
|
+
# lookup returns the same document (the index sort is not stable).
|
|
55
|
+
row = rows.max_by { |r| [r[:id].year.to_i, r[:file]] }
|
|
54
56
|
url = "#{GH_ENDPOINT}#{row[:file]}"
|
|
55
57
|
resp = Mechanize.new.get url
|
|
56
58
|
return unless resp.code == "200"
|
|
@@ -60,16 +62,163 @@ module Relaton::Bipm
|
|
|
60
62
|
item
|
|
61
63
|
end
|
|
62
64
|
|
|
65
|
+
# Look the reference up in the pubid `index-v2`, narrowing the candidate
|
|
66
|
+
# rows before the match runs. `Relaton::Index::Type#search` binary-searches
|
|
67
|
+
# only when given an identifier — the same call shape ISO, OIML and JCGM
|
|
68
|
+
# use. Both sides are now `Pubid::Bipm` objects, so the bespoke `Id`
|
|
69
|
+
# grammar takes no part in a query.
|
|
70
|
+
#
|
|
71
|
+
# Two escapes sit under the narrowing, each covering a case where the
|
|
72
|
+
# query's bsearch key cannot equal its row's:
|
|
73
|
+
#
|
|
74
|
+
# 1. A bare `SI Brochure` names no edition, so it keys to `""` while its
|
|
75
|
+
# row keys to `"9e"`. The rescan finds it.
|
|
76
|
+
# 2. `CCTF Recommendation 2009-02` parses as the literal number
|
|
77
|
+
# `2009-02`, while the row keys on `2`. No row carries that number, so
|
|
78
|
+
# a rescan cannot help — only re-reading the tail as number-plus-year.
|
|
79
|
+
#
|
|
80
|
+
# @param pubid [Pubid::Bipm::Identifier] the parsed reference
|
|
81
|
+
# @param reference [String, nil] the raw reference, for the retry
|
|
82
|
+
# @return [Array<Hash>] the matching index rows
|
|
83
|
+
def search_index(pubid, reference)
|
|
84
|
+
# Reduce the query once, not once per row. `#exclude` copies the
|
|
85
|
+
# identifier, so rebuilding it per candidate dominated the lookup.
|
|
86
|
+
query_stem = stem pubid, pubid
|
|
87
|
+
rows = index.search(pubid) { |r| pubid_match? r[:id], pubid, query_stem }
|
|
88
|
+
rows = index.search { |r| pubid_match? r[:id], pubid, query_stem } if rows.empty?
|
|
89
|
+
return rows unless rows.empty?
|
|
90
|
+
|
|
91
|
+
retry_pubid = year_number_retry reference
|
|
92
|
+
retry_pubid ? search_index(retry_pubid, nil) : rows
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Re-read a trailing `YYYY-NN` as number `NN` of year `YYYY`
|
|
96
|
+
# (`CCTF Recommendation 2009-02` → `CCTF Recommendation 2 (2009)`). Tried
|
|
97
|
+
# only after a miss, because `NNNN-NN` is also a real BIPM number
|
|
98
|
+
# (`CIPM 2005-06`), so the literal reading has to be preferred.
|
|
99
|
+
#
|
|
100
|
+
# The re-read string is a machine-derived probe, not the caller's
|
|
101
|
+
# reference, so a probe that does not parse is a miss (nil), never a
|
|
102
|
+
# malformed-reference error -- the same rule as ISO's type/stage probe.
|
|
103
|
+
#
|
|
104
|
+
# @param reference [String, nil]
|
|
105
|
+
# @return [Pubid::Bipm::Identifier, nil]
|
|
106
|
+
def year_number_retry(reference)
|
|
107
|
+
match = reference&.match(/\A(?<stem>.+)\s(?<year>\d{4})-(?<number>\d+)\z/)
|
|
108
|
+
return unless match
|
|
109
|
+
|
|
110
|
+
parse_ref "#{match[:stem]} #{match[:number].sub(/\A0+(?=\d)/, '')} (#{match[:year]})"
|
|
111
|
+
rescue ::Pubid::Errors::ParseError
|
|
112
|
+
nil
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Compare a row's identifier with the query. Index rows are stored
|
|
116
|
+
# language- and form-neutral — verified across all committee-document and
|
|
117
|
+
# meeting rows — while a reference may name a language (`(2009, E)`) and
|
|
118
|
+
# always names a form (short `CCTF REC 2` vs long `CCTF Recommendation 2`).
|
|
119
|
+
# The year joins them when the query omits it, mirroring what `Id#==` did
|
|
120
|
+
# with `other_hash.delete(:year) unless hash[:year]`.
|
|
121
|
+
#
|
|
122
|
+
# @param row_id [Pubid::Bipm::Identifier]
|
|
123
|
+
# @param query [Pubid::Bipm::Identifier]
|
|
124
|
+
# @param query_stem [Pubid::Bipm::Identifier, nil] the reduced query, when
|
|
125
|
+
# the caller already built it once for the whole search
|
|
126
|
+
# @return [Boolean]
|
|
127
|
+
def pubid_match?(row_id, query, query_stem = nil)
|
|
128
|
+
# A bare brochure names no edition, so it is a partial reference and
|
|
129
|
+
# cannot equal the `9e v3.01` row. Match any brochure row, which is what
|
|
130
|
+
# the old `{group: "SI", type: "Brochure"}` projection already meant.
|
|
131
|
+
if query.is_a?(::Pubid::Bipm::Identifiers::SiBrochure) && query.edition.nil?
|
|
132
|
+
return row_id.is_a?(::Pubid::Bipm::Identifiers::SiBrochure)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
return false unless row_id.instance_of?(query.class)
|
|
136
|
+
|
|
137
|
+
# `Id#==` treated a document numbered "1" and a number-less one as the
|
|
138
|
+
# same document when both carried a year, so `CIPM Resolution 1 (1879)`
|
|
139
|
+
# reached `CIPM RES (1879)`. pubid has no such rule and the six
|
|
140
|
+
# ordinal-less declarations are only addressable this way, so keep it.
|
|
141
|
+
if number_collapses?(row_id, query)
|
|
142
|
+
keys = stem_keys(query) + [:number]
|
|
143
|
+
return row_id.exclude(*keys) == query.exclude(*keys)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
return false unless cheap_reject_passes?(row_id, query)
|
|
147
|
+
|
|
148
|
+
stem(row_id, query) == (query_stem || stem(query, query))
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# @param row_id [Pubid::Bipm::Identifier]
|
|
152
|
+
# @param query [Pubid::Bipm::Identifier]
|
|
153
|
+
# @return [Boolean] true when one side is number-less, the other is
|
|
154
|
+
# numbered "1", and both carry a year
|
|
155
|
+
def number_collapses?(row_id, query)
|
|
156
|
+
return false unless row_id.year && query.year
|
|
157
|
+
|
|
158
|
+
numbers = [row_id.number.to_s, query.number.to_s]
|
|
159
|
+
numbers.include?("") && numbers.include?("1")
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Attributes the stem never removes, so stem equality implies equality on
|
|
163
|
+
# every one of them. Comparing them first cannot change the answer, it
|
|
164
|
+
# only avoids the reduction — and `#exclude` copies the identifier, which
|
|
165
|
+
# is what made an unguarded compare cost roughly 165x a plain attribute
|
|
166
|
+
# read and turned a rescan into seconds.
|
|
167
|
+
CHEAP_KEYS = %i[number group year issue article].freeze
|
|
168
|
+
|
|
169
|
+
# @param row_id [Pubid::Bipm::Identifier]
|
|
170
|
+
# @param query [Pubid::Bipm::Identifier]
|
|
171
|
+
# @return [Boolean] false as soon as one cheap attribute differs
|
|
172
|
+
def cheap_reject_passes?(row_id, query)
|
|
173
|
+
CHEAP_KEYS.all? do |key|
|
|
174
|
+
# `:year` is dropped from the stem when the query has none, so it is
|
|
175
|
+
# only significant when the query supplies one.
|
|
176
|
+
next true if key == :year && query.year.nil?
|
|
177
|
+
next true unless query.respond_to?(key) && row_id.respond_to?(key)
|
|
178
|
+
|
|
179
|
+
row_id.public_send(key).to_s == query.public_send(key).to_s
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# @param pubid [Pubid::Bipm::Identifier] the identifier to reduce
|
|
184
|
+
# @param query [Pubid::Bipm::Identifier] the query that sets which
|
|
185
|
+
# attributes are significant
|
|
186
|
+
# @return [Pubid::Bipm::Identifier] a copy; the cached row id is untouched
|
|
187
|
+
def stem(pubid, query)
|
|
188
|
+
pubid.exclude(*stem_keys(query))
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
# @param query [Pubid::Bipm::Identifier]
|
|
192
|
+
# @return [Array<Symbol>] the attributes a match must ignore
|
|
193
|
+
def stem_keys(query)
|
|
194
|
+
keys = %i[language form]
|
|
195
|
+
keys << :year if query.year.nil?
|
|
196
|
+
keys
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Parse a user reference with `Pubid::Bipm`, which since pubid `a96e9f45`
|
|
200
|
+
# accepts the loose consumer forms this flavor once needed `Id` for
|
|
201
|
+
# (`CCDS Recommendation 2 (2009)`, `CIPM 111e Réunion (2022)`,
|
|
202
|
+
# `CCTF Meeting 14 (1999)`, `SI Brochure Part 1`, …) and normalizes them
|
|
203
|
+
# to BIPM's canonical spelling. An unrecognized reference raises; like
|
|
204
|
+
# ISO and 3GPP we let it propagate -- relaton-cli rescues
|
|
205
|
+
# Pubid::Errors::Error and renders "... is not a recognized standards
|
|
206
|
+
# identifier".
|
|
207
|
+
#
|
|
208
|
+
# @param reference [String]
|
|
209
|
+
# @return [Pubid::Bipm::Identifier]
|
|
210
|
+
# @raise [Pubid::Errors::ParseError]
|
|
211
|
+
def parse_ref(reference)
|
|
212
|
+
::Pubid::Bipm.parse reference
|
|
213
|
+
end
|
|
214
|
+
|
|
63
215
|
def index
|
|
64
216
|
Relaton::Index.find_or_create(
|
|
65
|
-
:bipm, url: "#{GH_ENDPOINT}
|
|
217
|
+
:bipm, url: "#{GH_ENDPOINT}#{INDEXFILE}.zip", file: "#{INDEXFILE}.yaml",
|
|
218
|
+
pubid_class: ::Pubid::Bipm::Identifier
|
|
66
219
|
)
|
|
67
220
|
end
|
|
68
221
|
|
|
69
|
-
# def match_item(ids, ref_id)
|
|
70
|
-
# ids.find { |id| Id.new(id) == ref_id }
|
|
71
|
-
# end
|
|
72
|
-
|
|
73
222
|
# @param ref [String] the BIPM standard Code to look up (e..g "BIPM B-11")
|
|
74
223
|
# @param year [String] not used
|
|
75
224
|
# @param opts [Hash] not used
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require_relative "id_parser"
|
|
2
1
|
require_relative "../bipm"
|
|
3
2
|
require_relative "data_outcomes_parser"
|
|
4
3
|
require_relative "si_brochure_parser"
|
|
@@ -9,13 +8,38 @@ module Relaton::Bipm
|
|
|
9
8
|
attr_reader :output, :format, :ext, :files, :index, :errors
|
|
10
9
|
|
|
11
10
|
def index
|
|
12
|
-
@index ||= Relaton::Index.find_or_create
|
|
11
|
+
@index ||= Relaton::Index.find_or_create(
|
|
12
|
+
:bipm, file: "#{INDEXFILE}.yaml", pubid_class: ::Pubid::Bipm::Identifier
|
|
13
|
+
)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def log_error(msg)
|
|
16
17
|
Util.error msg
|
|
17
18
|
end
|
|
18
19
|
|
|
20
|
+
#
|
|
21
|
+
# Index a document by its pubid. Guarded defensively: a docnumber the
|
|
22
|
+
# `Pubid::Bipm` grammar can't parse (a legacy/inconsistent id, or a
|
|
23
|
+
# wrong-flavor orphan) is skipped with a warning rather than allowed to
|
|
24
|
+
# corrupt the whole index (`Relaton::Index` rejects an index if a single
|
|
25
|
+
# row fails to deserialize). Mirrors `Relaton::Jcgm::DataFetcher#add_to_index`.
|
|
26
|
+
#
|
|
27
|
+
# Public so `relaton-data-bipm`'s crawler can index its curated `static/`
|
|
28
|
+
# docs through the same guarded, sorted, `_type: pubid:bipm:*` path.
|
|
29
|
+
#
|
|
30
|
+
# @param [String] docnumber the record's primary docidentifier / docnumber
|
|
31
|
+
# @param [String] path repo-relative path to the YAML file
|
|
32
|
+
#
|
|
33
|
+
def add_to_index(docnumber, path)
|
|
34
|
+
# Store the Pubid::Bipm identifier object (not a hash): with pubid_class
|
|
35
|
+
# set, Relaton::Index sorts the index by id number on save and serializes
|
|
36
|
+
# each id to its `_type: pubid:bipm:*` hash, so the published index is
|
|
37
|
+
# already sorted (no "not sorted by id number" warning on consumer fetch).
|
|
38
|
+
index.add_or_update ::Pubid::Bipm.parse(docnumber), path
|
|
39
|
+
rescue StandardError => e
|
|
40
|
+
Util.warn "Skipping index entry for `#{docnumber}` (#{path}): #{e.message}"
|
|
41
|
+
end
|
|
42
|
+
|
|
19
43
|
#
|
|
20
44
|
# Fetch bipm-data-outcomes or si-brochure
|
|
21
45
|
#
|
|
@@ -39,7 +39,7 @@ module Relaton::Bipm
|
|
|
39
39
|
# Parse BIPM meeting and write them to YAML files
|
|
40
40
|
#
|
|
41
41
|
def parse
|
|
42
|
-
dirs = "cctf,cgpm,cipm,ccauv,ccem,ccl,ccm,ccpr,ccqm,ccri,cct,ccu,
|
|
42
|
+
dirs = "cctf,cgpm,cipm,ccauv,ccem,ccl,ccm,ccpr,ccqm,ccri,cct,ccu,jcrb"
|
|
43
43
|
source_path = File.join "bipm-data-outcomes", "{#{dirs}}"
|
|
44
44
|
Dir[source_path].each { |body_dir| fetch_body(body_dir) }
|
|
45
45
|
end
|
|
@@ -270,9 +270,8 @@ module Relaton::Bipm
|
|
|
270
270
|
# @param [Relaton::Bipm::ItemData] item bibliographic item
|
|
271
271
|
# @param [String] path path to YAML file
|
|
272
272
|
#
|
|
273
|
-
def add_to_index(item, path)
|
|
274
|
-
|
|
275
|
-
@data_fetcher.index.add_or_update key, path
|
|
273
|
+
def add_to_index(item, path)
|
|
274
|
+
@data_fetcher.add_to_index item.docnumber, path
|
|
276
275
|
end
|
|
277
276
|
|
|
278
277
|
#
|
|
@@ -92,7 +92,7 @@ module Relaton
|
|
|
92
92
|
#
|
|
93
93
|
def parse(id)
|
|
94
94
|
# str = StringScanner.new id
|
|
95
|
-
match = parse_outcome(id) || parse_brochure(id) || parse_metrologia(id)
|
|
95
|
+
match = parse_outcome(id) || parse_brochure(id) || parse_metrologia(id)
|
|
96
96
|
@id = match.named_captures.compact.transform_keys(&:to_sym)
|
|
97
97
|
self
|
|
98
98
|
rescue StandardError => e
|
|
@@ -167,9 +167,10 @@ module Relaton
|
|
|
167
167
|
%r{^(?<group>Metrologia)(?:\s(?<number>[a-zA-Z0-9\s]+))?$}.match(id)
|
|
168
168
|
end
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
# NOTE: JCGM is no longer served by the BIPM flavor — it has its own
|
|
171
|
+
# `Relaton::Jcgm` flavor (pubid-backed, fetching from relaton-data-jcgm).
|
|
172
|
+
# The old `parse_jcgm` branch and the `JCGM` default-prefix entry were
|
|
173
|
+
# removed together with the `jcgm` harvest dir in data_outcomes_parser.
|
|
173
174
|
|
|
174
175
|
# def parse_gorup_num(str)
|
|
175
176
|
# return unless group = parse_group(str)
|
|
@@ -10,6 +10,27 @@ module Relaton
|
|
|
10
10
|
map_element "part", to: :part
|
|
11
11
|
map_element "appendix", to: :appendix
|
|
12
12
|
end
|
|
13
|
+
|
|
14
|
+
# `Bib::ItemData#ext_to_all_parts!` / `#ext_remove_date` broadcast to
|
|
15
|
+
# `ext.structuredidentifier` as well as to `docidentifier`. This class
|
|
16
|
+
# descends from `Lutaml::Model::Serializable` rather than
|
|
17
|
+
# `Bib::StructuredIdentifier` (BIPM stores a single mapping, not a
|
|
18
|
+
# sequence), so it does not inherit that class's no-op defaults and the
|
|
19
|
+
# broadcast raised `NoMethodError` on every BIPM item.
|
|
20
|
+
#
|
|
21
|
+
# BIPM structured identifiers carry no date, so `remove_date!` has nothing
|
|
22
|
+
# to strip; the year lives on the docidentifier. `part` is real and is
|
|
23
|
+
# cleared. (Identical to `Relaton::Jcgm::StructuredIdentifier`.)
|
|
24
|
+
|
|
25
|
+
def remove_part!
|
|
26
|
+
self.part = nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def remove_date!; end
|
|
30
|
+
|
|
31
|
+
def to_all_parts!
|
|
32
|
+
remove_part!
|
|
33
|
+
end
|
|
13
34
|
end
|
|
14
35
|
end
|
|
15
36
|
end
|
|
@@ -8,7 +8,7 @@ module Relaton
|
|
|
8
8
|
def initialize
|
|
9
9
|
@short = :relaton_bipm
|
|
10
10
|
@prefix = "BIPM"
|
|
11
|
-
@defaultprefix = %r{^(?:BIPM|CCTF|CCDS|CGPM|CIPM|JCRB
|
|
11
|
+
@defaultprefix = %r{^(?:BIPM|CCTF|CCDS|CGPM|CIPM|JCRB)(?!\w)}
|
|
12
12
|
@idtype = "BIPM"
|
|
13
13
|
@datasets = %w[bipm-data-outcomes bipm-si-brochure rawdata-bipm-metrologia]
|
|
14
14
|
end
|
|
@@ -62,7 +62,7 @@ module Relaton
|
|
|
62
62
|
#
|
|
63
63
|
def remove_index_file
|
|
64
64
|
require_relative "../bipm"
|
|
65
|
-
Relaton::Index.find_or_create(:bipm, url: true, file: INDEXFILE).remove_file
|
|
65
|
+
Relaton::Index.find_or_create(:bipm, url: true, file: "#{INDEXFILE}.yaml").remove_file
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../id_parser"
|
|
4
3
|
require_relative "niso_jats_parser"
|
|
5
4
|
|
|
6
5
|
module Relaton::Bipm
|
|
@@ -37,8 +36,7 @@ module Relaton::Bipm
|
|
|
37
36
|
item = NisoJatsParser.parse path, @data_fetcher.errors
|
|
38
37
|
file = "#{item.docidentifier.first.content.downcase.tr(' ', '-')}.#{@data_fetcher.ext}"
|
|
39
38
|
out_path = File.join(@data_fetcher.output, file)
|
|
40
|
-
|
|
41
|
-
@data_fetcher.index.add_or_update key, out_path
|
|
39
|
+
@data_fetcher.add_to_index item.docidentifier.first.content, out_path
|
|
42
40
|
@data_fetcher.write_file out_path, item
|
|
43
41
|
end
|
|
44
42
|
end
|
|
@@ -80,7 +78,7 @@ module Relaton::Bipm
|
|
|
80
78
|
)
|
|
81
79
|
file = "#{id.downcase.gsub(' ', '-')}.#{@data_fetcher.ext}"
|
|
82
80
|
path = File.join(@data_fetcher.output, file)
|
|
83
|
-
@data_fetcher.
|
|
81
|
+
@data_fetcher.add_to_index id, path
|
|
84
82
|
@data_fetcher.write_file path, item
|
|
85
83
|
end
|
|
86
84
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require "nokogiri"
|
|
2
|
-
require_relative "id_parser"
|
|
3
2
|
|
|
4
3
|
module Relaton::Bipm
|
|
5
4
|
class SiBrochureParser
|
|
@@ -51,8 +50,11 @@ module Relaton::Bipm
|
|
|
51
50
|
fix_si_brochure_id item1
|
|
52
51
|
basename = File.join @data_fetcher.output, File.basename(f).sub(/(?:-(?:en|fr))?\.rxl$/, "")
|
|
53
52
|
outfile = "#{basename}.#{@data_fetcher.ext}"
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
# Index by the primary docidentifier content ("BIPM SI Brochure 9e
|
|
54
|
+
# v3.01 (2019/2024, E)"), which `Pubid::Bipm` parses — unlike the bare
|
|
55
|
+
# `docnumber` ("SI Brochure 9e …", no "BIPM" prefix), which it rejects.
|
|
56
|
+
key = primary_id(item1) || item1.docnumber || basename
|
|
57
|
+
@data_fetcher.add_to_index key, outfile
|
|
56
58
|
item =
|
|
57
59
|
if File.exist? outfile
|
|
58
60
|
warn_duplicate = false
|
data/lib/relaton/bipm.rb
CHANGED
|
@@ -4,8 +4,10 @@ require "parslet"
|
|
|
4
4
|
require "relaton/bib"
|
|
5
5
|
require "relaton/index"
|
|
6
6
|
require "relaton/core"
|
|
7
|
+
require "pubid"
|
|
7
8
|
require_relative "version"
|
|
8
9
|
require_relative "bipm/util"
|
|
10
|
+
require_relative "bipm/id_parser"
|
|
9
11
|
require_relative "bipm/item_data"
|
|
10
12
|
require_relative "bipm/model/item"
|
|
11
13
|
require_relative "bipm/model/bibitem"
|
|
@@ -16,7 +18,11 @@ module Relaton
|
|
|
16
18
|
module Bipm
|
|
17
19
|
class Error < StandardError; end
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
# The runtime index is the pubid-backed `index-v2` (`_type: pubid:bipm:*`).
|
|
22
|
+
# The legacy bespoke `{group,type,number,year}` `index-v1` is still published
|
|
23
|
+
# by `relaton-data-bipm`'s crawler (using the retained `Relaton::Bipm::Id`),
|
|
24
|
+
# but this flavor no longer reads or writes it.
|
|
25
|
+
INDEXFILE = "index-v2".freeze
|
|
20
26
|
|
|
21
27
|
# Returns hash of gems versions used to generate the data model.
|
|
22
28
|
# @return [String]
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
module Relaton::Bsi
|
|
4
4
|
# Class methods for search ISO standards.
|
|
5
5
|
class Bibliography
|
|
6
|
+
# pubid identifier types referenced when navigating the parsed object graph.
|
|
7
|
+
Ids = ::Pubid::Bsi::Identifiers
|
|
8
|
+
|
|
6
9
|
class << self
|
|
7
10
|
# @param text [String]
|
|
8
11
|
# @return [Relaton::Bsi::HitCollection]
|
|
@@ -24,52 +27,127 @@ module Relaton::Bsi
|
|
|
24
27
|
#
|
|
25
28
|
# @return [String] Relaton XML serialisation of reference
|
|
26
29
|
def get(code, year = nil, opts = {})
|
|
27
|
-
|
|
28
|
-
year ||= code_parts(code)[:year]
|
|
30
|
+
year ||= publication_year(code)
|
|
29
31
|
ret = bib_get(code, year, opts)
|
|
30
32
|
return nil if ret.nil?
|
|
31
33
|
|
|
32
34
|
ret = ret.to_most_recent_reference unless year || opts[:keep_year]
|
|
33
|
-
# ret = ret.to_all_parts if opts[:all_parts]
|
|
34
35
|
ret
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
38
|
+
# Parse a BSI reference with pubid. An unrecognized reference raises;
|
|
39
|
+
# like ISO and 3GPP we let it propagate -- relaton-cli rescues
|
|
40
|
+
# Pubid::Errors::Error and renders "... is not a recognized standards
|
|
41
|
+
# identifier". A catalogue hit code is a different case: `Hit#pubid`
|
|
42
|
+
# rescues, because one odd Algolia row must not abort the search.
|
|
40
43
|
# @param [String] code document identifier
|
|
44
|
+
# @return [Pubid::Bsi::Identifier]
|
|
45
|
+
# @raise [Pubid::Errors::ParseError]
|
|
46
|
+
def parse(code)
|
|
47
|
+
::Pubid::Bsi::Identifier.parse(code)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Publication year of a reference's base document.
|
|
51
|
+
# @param [String] code document identifier
|
|
52
|
+
# @return [String, nil]
|
|
53
|
+
def publication_year(code)
|
|
54
|
+
year_of parse(code)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Whether a query and a candidate hit denote the same BSI document, at the
|
|
58
|
+
# fuzziness the hit filter asks for. Built entirely on pubid: `base_document`
|
|
59
|
+
# peels supplements/wrappers, `matches?` compares ignoring the publication
|
|
60
|
+
# date, and the `Amendment`/`Corrigendum` `#supplement_type`, `#number` and
|
|
61
|
+
# `#year` supply the amendment type, number and year.
|
|
41
62
|
#
|
|
42
|
-
# @
|
|
43
|
-
#
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
63
|
+
# @param query [Pubid::Bsi::Identifier]
|
|
64
|
+
# @param hit [Pubid::Bsi::Identifier]
|
|
65
|
+
# @param skip_rest [Boolean] ignore the free-text suffix (ExComm / Flex version)
|
|
66
|
+
# @param drop_amd [Boolean] reduce the hit to its base document before
|
|
67
|
+
# matching, so a query for the base document matches a catalogue entry
|
|
68
|
+
# that only exists in amended form (the returned id is de-amended too)
|
|
69
|
+
# @return [Boolean]
|
|
70
|
+
def same_reference?(query, hit, skip_rest: false, drop_amd: false)
|
|
71
|
+
hit = hit.base_document if drop_amd
|
|
72
|
+
|
|
73
|
+
base_match?(query, hit) &&
|
|
74
|
+
same_supplement?(supplement_of(query), supplement_of(hit)) &&
|
|
75
|
+
(skip_rest || rest_marker(query) == rest_marker(hit))
|
|
51
76
|
end
|
|
52
77
|
|
|
53
78
|
private
|
|
54
79
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
80
|
+
# The year of the dated document at the root of a reference. pubid holds
|
|
81
|
+
# an adopted standard (`BS EN ISO 8848:2021`) in `base`, so its
|
|
82
|
+
# `base_document.year` is nil; `#root` reaches the dated document for
|
|
83
|
+
# every form, on the pubid before that change and after it.
|
|
84
|
+
# @param id [Pubid::Bsi::Identifier, nil]
|
|
85
|
+
# @return [String, nil]
|
|
86
|
+
def year_of(id)
|
|
87
|
+
id&.root&.year&.to_s
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Same base document, ignoring the publication date. `:month` is excluded
|
|
91
|
+
# alongside `:date` because Flex identifiers store the month separately, so
|
|
92
|
+
# `exclude(:date)` alone leaves them unequal.
|
|
93
|
+
def base_match?(query, hit)
|
|
94
|
+
query.base_document.matches?(hit.base_document, ignore: %i[date month])
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# The `Amendment`/`Corrigendum` supplement of a reference, if any — peeling
|
|
98
|
+
# an Expert-commentary wrapper first. Both supplements expose
|
|
99
|
+
# `#supplement_type`, `#number` and `#year`.
|
|
100
|
+
def supplement_of(id)
|
|
101
|
+
while id.is_a?(Ids::ExpertCommentary)
|
|
102
|
+
inner = id.base
|
|
103
|
+
break if inner.nil? || inner.equal?(id)
|
|
104
|
+
|
|
105
|
+
id = inner
|
|
106
|
+
end
|
|
107
|
+
return nil unless id.respond_to?(:identifiers) && id.identifiers
|
|
108
|
+
|
|
109
|
+
id.identifiers.find { |i| i.respond_to?(:supplement_type) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Same supplement, with the amendment year treated as optional when the
|
|
113
|
+
# query omits it (a query for "…+A2" matches a hit for "…+A2:2020").
|
|
114
|
+
def same_supplement?(query_supp, hit_supp)
|
|
115
|
+
return hit_supp.nil? if query_supp.nil?
|
|
116
|
+
return false if hit_supp.nil?
|
|
117
|
+
|
|
118
|
+
query_supp.supplement_type == hit_supp.supplement_type &&
|
|
119
|
+
supplement_number(query_supp) == supplement_number(hit_supp) &&
|
|
120
|
+
(supplement_year(query_supp).nil? ||
|
|
121
|
+
supplement_year(query_supp) == supplement_year(hit_supp))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# The number and the year of a supplement. pubid removes the
|
|
125
|
+
# `#supplement_number` / `#supplement_year` aliases and stores the values
|
|
126
|
+
# in `#number` / `#year`. An older pubid still answers the aliases and
|
|
127
|
+
# leaves `#number` / `#year` nil, so the alias wins while it exists.
|
|
128
|
+
# TODO: read `#number` / `#year` directly once pubid `main` has no alias.
|
|
129
|
+
def supplement_number(supp)
|
|
130
|
+
supp.respond_to?(:supplement_number) ? supp.supplement_number : supp.number
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def supplement_year(supp)
|
|
134
|
+
supp.respond_to?(:supplement_year) ? supp.supplement_year : supp.year
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Canonical marker for the free-text suffix pubid parses into a typed
|
|
138
|
+
# wrapper (so an `ExComm` query matches an `Expert Commentary` hit).
|
|
139
|
+
def rest_marker(id)
|
|
140
|
+
return :expert_commentary if id.is_a?(Ids::ExpertCommentary)
|
|
141
|
+
return :"flex_#{id.edition}" if id.is_a?(Ids::Flex) && id.edition
|
|
142
|
+
|
|
143
|
+
nil
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def fetch_ref_err(_code, year, missed_years)
|
|
60
147
|
unless missed_years.empty?
|
|
61
148
|
Util.info "There was no match for `#{year}`, though there " \
|
|
62
149
|
"were matches found for `#{missed_years.join('`, `')}`."
|
|
63
150
|
end
|
|
64
|
-
# if /\d-\d/.match? code
|
|
65
|
-
# warn "[relaton-bsi] The provided document part may not exist, or "\
|
|
66
|
-
# "the document may no longer be published in parts."
|
|
67
|
-
# else
|
|
68
|
-
# warn "[relaton-bsi] If you wanted to cite all document parts for "\
|
|
69
|
-
# "the reference, use \"#{code} (all parts)\".\nIf the document "\
|
|
70
|
-
# "is not a standard, use its document type abbreviation (TS, TR, "\
|
|
71
|
-
# "PAS, Guide)."
|
|
72
|
-
# end
|
|
73
151
|
nil
|
|
74
152
|
end
|
|
75
153
|
|
|
@@ -81,26 +159,20 @@ module Relaton::Bsi
|
|
|
81
159
|
# @return [Relaton::Bsi::HitCollection] a collection of hits
|
|
82
160
|
#
|
|
83
161
|
def search_filter(code)
|
|
84
|
-
|
|
162
|
+
query = parse(code)
|
|
85
163
|
Util.info "Fetching from shop.bsigroup.com ...", key: code
|
|
86
|
-
|
|
87
|
-
Util.info "Could not parse the reference", key: code
|
|
88
|
-
return []
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
search(code).filter_hits!(cp)
|
|
164
|
+
search(code).filter_hits!(query)
|
|
92
165
|
end
|
|
93
166
|
|
|
94
|
-
# Sort through the results
|
|
95
|
-
# and
|
|
96
|
-
#
|
|
97
|
-
# Only expects the first page of results to be populated.
|
|
98
|
-
# Does not match corrigenda etc (e.g. ISO 3166-1:2006/Cor 1:2007)
|
|
99
|
-
# If no match, returns any years which caused mismatch, for error reporting
|
|
167
|
+
# Sort through the results, and return the first result that matches the
|
|
168
|
+
# code and matches the year (if provided), and which has a title.
|
|
169
|
+
# If no match, returns any years which caused mismatch, for error reporting.
|
|
100
170
|
def results_filter(result, year)
|
|
101
171
|
missed_years = []
|
|
102
172
|
result.each do |r|
|
|
103
|
-
|
|
173
|
+
# The hit's own parse: a kept hit always parsed, and its base
|
|
174
|
+
# document's year is the same after a `drop_amd` rewrite.
|
|
175
|
+
pyear = year_of r.pubid
|
|
104
176
|
return { ret: r.item } if (!year || year == pyear) && r.item
|
|
105
177
|
|
|
106
178
|
missed_years << pyear
|
data/lib/relaton/bsi/hit.rb
CHANGED
|
@@ -10,5 +10,19 @@ module Relaton::Bsi
|
|
|
10
10
|
def item
|
|
11
11
|
@item ||= Scraper.parse_page self
|
|
12
12
|
end
|
|
13
|
+
|
|
14
|
+
# The hit's reference parsed with pubid, memoized so the (up to three) hit
|
|
15
|
+
# filter passes don't re-parse it. `nil` when pubid can't parse the code:
|
|
16
|
+
# the Algolia catalogue carries codes like `BS 381C SET:1996 (R2002)`, and
|
|
17
|
+
# one such row must not abort the search. (A malformed *query* raises; see
|
|
18
|
+
# `Bibliography.parse`.)
|
|
19
|
+
# @return [Pubid::Bsi::Identifier, nil]
|
|
20
|
+
def pubid
|
|
21
|
+
return @pubid if defined?(@pubid)
|
|
22
|
+
|
|
23
|
+
@pubid = Bibliography.parse(hit[:code])
|
|
24
|
+
rescue StandardError
|
|
25
|
+
@pubid = nil
|
|
26
|
+
end
|
|
13
27
|
end
|
|
14
28
|
end
|