relaton 3.0.0.pre.alpha.4 → 3.0.0.pre.alpha.6
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/lib/relaton/3gpp/bibliography.rb +19 -6
- data/lib/relaton/3gpp/processor.rb +6 -0
- data/lib/relaton/adobe/processor.rb +9 -0
- data/lib/relaton/bib/converter/csl.rb +110 -0
- data/lib/relaton/bib/converter/ris.rb +104 -0
- data/lib/relaton/bib/converter/titles.rb +24 -0
- data/lib/relaton/bib/item_data.rb +23 -0
- data/lib/relaton/bib/model/item.rb +6 -6
- data/lib/relaton/bib/sanitizer.rb +71 -30
- data/lib/relaton/bib.rb +10 -0
- data/lib/relaton/bipm/bibliography.rb +24 -21
- data/lib/relaton/bipm/processor.rb +1 -0
- data/lib/relaton/bipm/rawdata_bipm_metrologia/affiliations.rb +6 -6
- data/lib/relaton/bipm/si_brochure_parser.rb +2 -2
- data/lib/relaton/bsi/bibliography.rb +26 -23
- data/lib/relaton/bsi/processor.rb +5 -0
- data/lib/relaton/calconnect/bibliography.rb +6 -6
- data/lib/relaton/calconnect/hit_collection.rb +4 -1
- data/lib/relaton/ccsds/bibliography.rb +16 -10
- data/lib/relaton/ccsds/hit_collection.rb +1 -1
- data/lib/relaton/ccsds/processor.rb +13 -0
- data/lib/relaton/cen/bibliography.rb +27 -24
- data/lib/relaton/cen/hit_collection.rb +1 -1
- data/lib/relaton/cen/processor.rb +5 -0
- data/lib/relaton/cen/scraper.rb +9 -9
- data/lib/relaton/cie/bibliography.rb +11 -9
- data/lib/relaton/cie/data_fetcher.rb +18 -18
- data/lib/relaton/cie/processor.rb +1 -0
- data/lib/relaton/cie/scrapper.rb +15 -8
- data/lib/relaton/cie.rb +1 -1
- data/lib/relaton/cloud.rb +127 -0
- data/lib/relaton/core/hit_collection.rb +6 -10
- data/lib/relaton/core/processor.rb +121 -0
- data/lib/relaton/core/request_error.rb +21 -3
- data/lib/relaton/db/cache.rb +474 -148
- data/lib/relaton/db/cache_entry.rb +42 -0
- data/lib/relaton/db/registry.rb +152 -0
- data/lib/relaton/db.rb +275 -102
- data/lib/relaton/doi/crossref.rb +23 -6
- data/lib/relaton/doi/processor.rb +1 -0
- data/lib/relaton/easc/processor.rb +1 -0
- data/lib/relaton/ecma/bibliography.rb +18 -13
- data/lib/relaton/ecma/data_fetcher.rb +1 -1
- data/lib/relaton/ecma/data_parser.rb +1 -1
- data/lib/relaton/ecma/edition_parser.rb +2 -2
- data/lib/relaton/ecma/memento_parser.rb +4 -4
- data/lib/relaton/ecma/standard_parser.rb +6 -6
- data/lib/relaton/etsi/bibliography.rb +8 -7
- data/lib/relaton/etsi/processor.rb +1 -0
- data/lib/relaton/gb/bibliography.rb +20 -12
- data/lib/relaton/gb/gb_scraper.rb +5 -5
- data/lib/relaton/gb/scraper.rb +16 -16
- data/lib/relaton/gb/sec_scraper.rb +8 -8
- data/lib/relaton/gb/t_scraper.rb +5 -5
- data/lib/relaton/gost/processor.rb +1 -0
- data/lib/relaton/iala/bibliography.rb +15 -12
- data/lib/relaton/iala/processor.rb +1 -0
- data/lib/relaton/iana/bibliography.rb +12 -12
- data/lib/relaton/iana/data_fetcher.rb +3 -3
- data/lib/relaton/iana/parser.rb +12 -5
- data/lib/relaton/iana/processor.rb +9 -0
- data/lib/relaton/iec/bibliography.rb +18 -7
- data/lib/relaton/iec/data_parser.rb +24 -9
- data/lib/relaton/iec/processor.rb +11 -0
- data/lib/relaton/iec.rb +1 -1
- data/lib/relaton/ieee/bibliography.rb +19 -13
- data/lib/relaton/ieee/data_fetcher.rb +1 -1
- data/lib/relaton/ieee/processor.rb +24 -0
- data/lib/relaton/ieee/rawbib_id_parser.rb +2 -2
- data/lib/relaton/ietf/bibliography.rb +11 -9
- data/lib/relaton/ietf/data_fetcher.rb +1 -1
- data/lib/relaton/ietf/processor.rb +1 -0
- data/lib/relaton/ietf/rfc/entry.rb +15 -19
- data/lib/relaton/ietf/scraper.rb +5 -4
- data/lib/relaton/iho/processor.rb +1 -0
- data/lib/relaton/index/file_io.rb +2 -2
- data/lib/relaton/index/pool.rb +4 -3
- data/lib/relaton/index/shard_source.rb +1 -1
- data/lib/relaton/index/type.rb +2 -5
- data/lib/relaton/isbn/open_library.rb +11 -7
- data/lib/relaton/isbn/processor.rb +10 -0
- data/lib/relaton/iso/bibliography.rb +11 -9
- data/lib/relaton/iso/data_parser.rb +2 -2
- data/lib/relaton/iso/processor.rb +5 -0
- data/lib/relaton/iso/scraper.rb +20 -20
- data/lib/relaton/itu/bibliography.rb +107 -16
- data/lib/relaton/itu/data_crawler_r.rb +2 -2
- data/lib/relaton/itu/hit_collection.rb +64 -52
- data/lib/relaton/itu/processor.rb +1 -0
- data/lib/relaton/itu/scraper.rb +13 -3
- data/lib/relaton/itu.rb +0 -2
- data/lib/relaton/jis/bibliography.rb +22 -11
- data/lib/relaton/jis/data_fetcher.rb +4 -4
- data/lib/relaton/jis/processor.rb +1 -0
- data/lib/relaton/jis/scraper.rb +8 -8
- data/lib/relaton/nist/bibliography.rb +25 -21
- data/lib/relaton/oasis/bibliography.rb +16 -13
- data/lib/relaton/oasis/browser_agent.rb +2 -2
- data/lib/relaton/oasis/data_parser.rb +5 -5
- data/lib/relaton/oasis/data_parser_utils.rb +2 -2
- data/lib/relaton/oasis/data_part_parser.rb +7 -7
- data/lib/relaton/ogc/bibliography.rb +15 -14
- data/lib/relaton/ogc/hit_collection.rb +9 -7
- data/lib/relaton/ogc/processor.rb +13 -0
- data/lib/relaton/oiml/processor.rb +1 -0
- data/lib/relaton/omg/bibliography.rb +9 -9
- data/lib/relaton/omg/scraper.rb +14 -13
- data/lib/relaton/omg.rb +1 -1
- data/lib/relaton/plateau/bibliography.rb +9 -7
- data/lib/relaton/plateau/hit_collection.rb +2 -1
- data/lib/relaton/plateau/processor.rb +1 -0
- data/lib/relaton/un/bibliography.rb +21 -10
- data/lib/relaton/un/processor.rb +1 -0
- data/lib/relaton/version.rb +1 -1
- data/lib/relaton/w3c/processor.rb +1 -0
- data/lib/relaton/xsf/bibliography.rb +11 -6
- data/lib/relaton.rb +13 -0
- metadata +60 -14
- data/lib/relaton/itu/pubid.rb +0 -199
|
@@ -8,23 +8,27 @@ module Relaton
|
|
|
8
8
|
|
|
9
9
|
ENDPOINT = "http://openlibrary.org/api/volumes/brief/isbn/".freeze
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
# @param ref [String, Pubid::Isbn::Identifier] an ISBN-10 or ISBN-13
|
|
12
|
+
# @return [Relaton::Bib::ItemData, nil]
|
|
13
|
+
def get(ref, _date = nil, _opts = {}) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
14
|
+
Util.info "Fetching from OpenLibrary ...", key: ref.to_s
|
|
15
|
+
|
|
16
|
+
# A parsed pubid gives its digits (`raw`); `Isbn#parse` validates them
|
|
17
|
+
# and converts an ISBN-10 to ISBN-13, as for a String.
|
|
18
|
+
isbn = Isbn.new(ref.is_a?(String) ? ref : ref.raw).parse
|
|
15
19
|
unless isbn
|
|
16
|
-
Util.info "Incorrect ISBN.", key: ref
|
|
20
|
+
Util.info "Incorrect ISBN.", key: ref.to_s
|
|
17
21
|
return
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
resp = request_api isbn
|
|
21
25
|
unless resp
|
|
22
|
-
Util.info "Not found.", key: ref
|
|
26
|
+
Util.info "Not found.", key: ref.to_s
|
|
23
27
|
return
|
|
24
28
|
end
|
|
25
29
|
|
|
26
30
|
bib = Parser.parse resp
|
|
27
|
-
Util.info "Found: `#{bib.docidentifier.first.content}`", key: ref
|
|
31
|
+
Util.info "Found: `#{bib.docidentifier.first.content}`", key: ref.to_s
|
|
28
32
|
bib
|
|
29
33
|
end
|
|
30
34
|
|
|
@@ -8,6 +8,7 @@ module Relaton
|
|
|
8
8
|
def initialize # rubocop:disable Lint/MissingSuper
|
|
9
9
|
@short = :relaton_isbn
|
|
10
10
|
@prefix = "ISBN"
|
|
11
|
+
@pubid_identifier = :Isbn # Db cache key
|
|
11
12
|
@defaultprefix = /^ISBN\s/
|
|
12
13
|
@idtype = "ISBN"
|
|
13
14
|
@datasets = %w[]
|
|
@@ -22,6 +23,15 @@ module Relaton
|
|
|
22
23
|
::Relaton::Isbn::OpenLibrary.get(code, date, opts)
|
|
23
24
|
end
|
|
24
25
|
|
|
26
|
+
# `OpenLibrary.get` reads an incorrect ISBN as a miss, so a reference
|
|
27
|
+
# pubid cannot parse (it checks the check digit too) gets no key here
|
|
28
|
+
# either: it is not cached.
|
|
29
|
+
def cache_pubid(ref)
|
|
30
|
+
super
|
|
31
|
+
rescue StandardError
|
|
32
|
+
nil
|
|
33
|
+
end
|
|
34
|
+
|
|
25
35
|
#
|
|
26
36
|
# @param xml [String]
|
|
27
37
|
# @return [Relaton::Bib::Bibitem]
|
|
@@ -24,7 +24,9 @@ module Relaton
|
|
|
24
24
|
raise Relaton::RequestError, e.message
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
# @param ref [String] the ISO standard Code to
|
|
27
|
+
# @param ref [String, Pubid::Iso::Identifier] the ISO standard Code to
|
|
28
|
+
# look up (e..g "ISO 9000"), or the parse that Relaton::Db routed with
|
|
29
|
+
# (relaton#205); a pubid is never mutated
|
|
28
30
|
# @param year [String, NilClass] the year the standard was published
|
|
29
31
|
# @param opts [Hash] options; restricted to :all_parts if all-parts
|
|
30
32
|
# @option opts [Boolean] :all_parts if all-parts reference is required
|
|
@@ -33,21 +35,21 @@ module Relaton
|
|
|
33
35
|
#
|
|
34
36
|
# @return [RelatonIsoBib::IsoBibliographicItem] Bibliographic item
|
|
35
37
|
def get(ref, year = nil, opts = {}) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity,Metrics/AbcSize
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
query_pubid = ::Pubid::Iso::Identifier.parse(code)
|
|
38
|
+
query_pubid = if ref.is_a?(String)
|
|
39
|
+
::Pubid::Iso::Identifier.parse(ref.gsub("\u2013", "-"))
|
|
40
|
+
else
|
|
41
|
+
ref
|
|
42
|
+
end
|
|
43
43
|
if year&.respond_to?(:to_i)
|
|
44
|
+
# Copy first: a caller's pubid is also its Db cache key.
|
|
45
|
+
query_pubid = query_pubid.class.from_hash(query_pubid.to_hash)
|
|
44
46
|
query_pubid.root.date = ::Pubid::Components::Date.new(year: year.to_s)
|
|
45
47
|
end
|
|
46
48
|
query_pubid = query_pubid.to_all_parts if opts[:all_parts]
|
|
47
49
|
Util.info "Fetching from Relaton repository ...", key: query_pubid.to_s
|
|
48
50
|
|
|
49
51
|
hits, missed_year_ids = isobib_search_filter(query_pubid, opts)
|
|
50
|
-
tip_ids = look_up_with_any_types_stages(hits, ref, opts)
|
|
52
|
+
tip_ids = look_up_with_any_types_stages(hits, ref.to_s, opts)
|
|
51
53
|
|
|
52
54
|
date_filter = opts[:publication_date_before] || opts[:publication_date_after]
|
|
53
55
|
if date_filter && !query_pubid.all_parts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "moxml"
|
|
4
4
|
require_relative "../iso"
|
|
5
5
|
require_relative "scraper"
|
|
6
6
|
|
|
@@ -331,7 +331,7 @@ module Relaton
|
|
|
331
331
|
end
|
|
332
332
|
|
|
333
333
|
def strip_html(html)
|
|
334
|
-
|
|
334
|
+
Moxml.new.parse_fragment(html).map(&:text).join.strip.gsub(/\s+/, " ")
|
|
335
335
|
end
|
|
336
336
|
|
|
337
337
|
# ---- copyright -------------------------------------------------------
|
|
@@ -39,6 +39,11 @@ module Relaton
|
|
|
39
39
|
DataFetcher.fetch(source, **opts)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
# `Bibliography.get` applies a year to the document the reference names.
|
|
43
|
+
def fold_year(pubid, year)
|
|
44
|
+
fold_year_on_root pubid, year
|
|
45
|
+
end
|
|
46
|
+
|
|
42
47
|
# @param xml [String]
|
|
43
48
|
# @return [RelatonIsoBib::IsoBibliographicItem]
|
|
44
49
|
def from_xml(xml)
|
data/lib/relaton/iso/scraper.rb
CHANGED
|
@@ -95,7 +95,7 @@ module Relaton
|
|
|
95
95
|
def id
|
|
96
96
|
return @id if defined?(@id)
|
|
97
97
|
|
|
98
|
-
did = @doc.
|
|
98
|
+
did = @doc.at_xpath("//h1/span[1]")
|
|
99
99
|
@errors[:id] &&= did.nil?
|
|
100
100
|
@id = did && did.text.split(" | ").first.strip
|
|
101
101
|
end
|
|
@@ -117,7 +117,7 @@ module Relaton
|
|
|
117
117
|
def edition
|
|
118
118
|
return @edition if defined?(@edition)
|
|
119
119
|
|
|
120
|
-
ed = @doc.
|
|
120
|
+
ed = @doc.at_xpath("//div[div[.='Edition']]/text()[last()]")
|
|
121
121
|
@errors[:edition] &&= ed.nil?
|
|
122
122
|
@edition = ed && Bib::Edition.new(content: ed.text.match(/\d+$/).to_s)
|
|
123
123
|
end
|
|
@@ -172,7 +172,7 @@ module Relaton
|
|
|
172
172
|
langs = languages.each_with_object([]) do |l, s|
|
|
173
173
|
# Don't need to get page for en. We already have it.
|
|
174
174
|
d = l[:path] ? get_page(l[:path])[0] : @doc
|
|
175
|
-
unless d.
|
|
175
|
+
unless d.at_xpath("//h5[@class='help-block'][.='недоступно на русском языке']")
|
|
176
176
|
s << l
|
|
177
177
|
titles += fetch_title(d, l[:lang])
|
|
178
178
|
|
|
@@ -208,7 +208,7 @@ module Relaton
|
|
|
208
208
|
|
|
209
209
|
# Get page.
|
|
210
210
|
# @param path [String] page's path
|
|
211
|
-
# @return [Array<
|
|
211
|
+
# @return [Array<Moxml::Document, String>]
|
|
212
212
|
def get_page(path) # rubocop:disable Metrics/MethodLength
|
|
213
213
|
try = 0
|
|
214
214
|
begin
|
|
@@ -276,12 +276,12 @@ module Relaton
|
|
|
276
276
|
# @param [Net::HTTPOK] resp HTTP response
|
|
277
277
|
# @param [URI::HTTPS] uri URI of the page
|
|
278
278
|
#
|
|
279
|
-
# @return [
|
|
279
|
+
# @return [Moxml::Document] document
|
|
280
280
|
# @raise [Relaton::RequestError] if the page could not be parsed
|
|
281
281
|
#
|
|
282
282
|
def try_if_fail(resp, uri)
|
|
283
283
|
10.times do
|
|
284
|
-
doc =
|
|
284
|
+
doc = Moxml.new.parse_html(resp.body)
|
|
285
285
|
# stop trying if page has a document id
|
|
286
286
|
return doc if item_ref(doc)
|
|
287
287
|
|
|
@@ -312,12 +312,12 @@ module Relaton
|
|
|
312
312
|
#
|
|
313
313
|
# Parse ID from the document.
|
|
314
314
|
#
|
|
315
|
-
# @param [
|
|
315
|
+
# @param [Moxml::Document] doc document to parse
|
|
316
316
|
#
|
|
317
317
|
# @return [String, nil] ID
|
|
318
318
|
#
|
|
319
319
|
def item_ref(doc)
|
|
320
|
-
ref = doc.
|
|
320
|
+
ref = doc.at_xpath("//main//section/div/div/div//h1/span[1]")
|
|
321
321
|
@errors[:reference] &&= ref.nil?
|
|
322
322
|
ref&.text&.strip
|
|
323
323
|
end
|
|
@@ -334,7 +334,7 @@ module Relaton
|
|
|
334
334
|
def stage_code
|
|
335
335
|
return @stage_code if defined?(@stage_code)
|
|
336
336
|
|
|
337
|
-
stc = @doc.
|
|
337
|
+
stc = @doc.at_xpath("//ul[@class='dropdown-menu']/li[@class='active']/a/span[@class='stage-code']")
|
|
338
338
|
@errors[:stage] &&= stc.nil?
|
|
339
339
|
@stage_code = stc&.text
|
|
340
340
|
end
|
|
@@ -351,7 +351,7 @@ module Relaton
|
|
|
351
351
|
rels = @doc.xpath(
|
|
352
352
|
"//ul[@class='steps']/li", "//div[contains(@class, 'sub-step')]"
|
|
353
353
|
).reduce([]) do |a, r|
|
|
354
|
-
type, date = relation_type(r.
|
|
354
|
+
type, date = relation_type(r.at_xpath("h4|h5").text.strip)
|
|
355
355
|
next a if types.include?(type)
|
|
356
356
|
|
|
357
357
|
a + create_relations(r, type, date)
|
|
@@ -383,7 +383,7 @@ module Relaton
|
|
|
383
383
|
#
|
|
384
384
|
# Create relations.
|
|
385
385
|
#
|
|
386
|
-
# @param [
|
|
386
|
+
# @param [Moxml::Element] rel relation element
|
|
387
387
|
# @param [String] type relation type
|
|
388
388
|
# @param [Hash{Symbol=>String}] date relation document date
|
|
389
389
|
# @option date [String] :type date type
|
|
@@ -400,7 +400,7 @@ module Relaton
|
|
|
400
400
|
end
|
|
401
401
|
|
|
402
402
|
# Fetch titles.
|
|
403
|
-
# @param doc [
|
|
403
|
+
# @param doc [Moxml::Document]
|
|
404
404
|
# @param lang [String]
|
|
405
405
|
# @return [Array<RelatonBib::TypedTitleString>]
|
|
406
406
|
def fetch_title(doc, lang) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
|
@@ -417,7 +417,7 @@ module Relaton
|
|
|
417
417
|
end
|
|
418
418
|
|
|
419
419
|
def parse_titles(doc)
|
|
420
|
-
# head = doc.
|
|
420
|
+
# head = doc.at_xpath "//nav[contains(@class,'heading-condensed')]"
|
|
421
421
|
ttls = doc.xpath("//h1[@class='stdTitle']/span[position()>1]").map(&:text)
|
|
422
422
|
return ttls if @errors[:title] &&= ttls.empty?
|
|
423
423
|
|
|
@@ -455,14 +455,14 @@ module Relaton
|
|
|
455
455
|
def fetch_dates # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
456
456
|
dates = []
|
|
457
457
|
%r{^[^\s]+\s[\d-]+:(?<ref_date_str>\d{4})} =~ id
|
|
458
|
-
pub_date_str = @doc.
|
|
458
|
+
pub_date_str = @doc.at_xpath("//span[@itemprop='releaseDate']")
|
|
459
459
|
@errors[:date_pub] &&= pub_date_str.nil?
|
|
460
460
|
if ref_date_str
|
|
461
461
|
dates += parse_date_from_id ref_date_str, pub_date_str
|
|
462
462
|
elsif pub_date_str
|
|
463
463
|
dates << Bib::Date.new(type: "published", at: pub_date_str.text)
|
|
464
464
|
end
|
|
465
|
-
corr_data = @doc.
|
|
465
|
+
corr_data = @doc.at_xpath "//span[@itemprop='dateModified']"
|
|
466
466
|
@errors[:date_corr] &&= corr_data.nil?
|
|
467
467
|
dates << Bib::Date.new(type: "corrected", at: corr_data.text) if corr_data
|
|
468
468
|
dates
|
|
@@ -522,13 +522,13 @@ module Relaton
|
|
|
522
522
|
#
|
|
523
523
|
def fetch_source(url) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength
|
|
524
524
|
source = [Bib::Uri.new(type: "src", content: url)]
|
|
525
|
-
obp = @doc.
|
|
525
|
+
obp = @doc.at_xpath("//a[.='Read sample']")
|
|
526
526
|
@errors[:link_obp] &&= obp.nil?
|
|
527
527
|
source << Bib::Uri.new(type: "obp", content: obp[:href]) if obp
|
|
528
|
-
rss = @doc.
|
|
528
|
+
rss = @doc.at_xpath("//a[contains(@href, 'rss')]")
|
|
529
529
|
@errors[:link_rss] &&= rss.nil?
|
|
530
530
|
source << Bib::Uri.new(type: "rss", content: DOMAIN + rss[:href]) if rss
|
|
531
|
-
pub = @doc.
|
|
531
|
+
pub = @doc.at_xpath "//p[contains(., 'publicly available')]/a",
|
|
532
532
|
"//p[contains(., 'can be downloaded from the')]/a"
|
|
533
533
|
@errors[:link_pub] &&= pub.nil?
|
|
534
534
|
source << Bib::Uri.new(type: "pub", content: pub[:href]) if pub
|
|
@@ -542,7 +542,7 @@ module Relaton
|
|
|
542
542
|
owner_name = ref.match(/.*?(?=\s)/).to_s
|
|
543
543
|
from = ref.match(/(?<=:)\d{4}/).to_s
|
|
544
544
|
if from.empty?
|
|
545
|
-
date = @doc.
|
|
545
|
+
date = @doc.at_xpath(
|
|
546
546
|
"//span[@itemprop='releaseDate']",
|
|
547
547
|
"//ul[@id='stages']/li[contains(@class,'active')]/ul/li[@class='active']/a/span[@class='stage-date']",
|
|
548
548
|
)
|
|
@@ -585,7 +585,7 @@ module Relaton
|
|
|
585
585
|
# @return [Relaton::Bib::Contributor, nil]
|
|
586
586
|
#
|
|
587
587
|
def fetch_editorialgroup_contributor # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
588
|
-
wg = @doc.
|
|
588
|
+
wg = @doc.at_xpath(
|
|
589
589
|
"//div[contains(., 'Technical Committe')]" \
|
|
590
590
|
"/following-sibling::span/a",
|
|
591
591
|
)
|
|
@@ -5,35 +5,97 @@ module Relaton
|
|
|
5
5
|
module Bibliography
|
|
6
6
|
extend self
|
|
7
7
|
|
|
8
|
-
#
|
|
8
|
+
# Supplements that print the date of the recommendation they amend
|
|
9
|
+
# first, "ITU-T G.989.2 (2014) Amd. 1 (04/2016)": their edition is the
|
|
10
|
+
# base's.
|
|
11
|
+
AMENDING = [
|
|
12
|
+
::Pubid::Itu::Identifiers::Amendment, ::Pubid::Itu::Identifiers::Corrigendum,
|
|
13
|
+
::Pubid::Itu::Identifiers::Errata, ::Pubid::Itu::Identifiers::Addendum,
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
16
|
+
# Parts of a recommendation that print its date first when it has one,
|
|
17
|
+
# "ITU-T Z.100 (06/2021) Annex F1", and their own date otherwise.
|
|
18
|
+
ANNEXED = [
|
|
19
|
+
::Pubid::Itu::Identifiers::AnnexOfRecommendation,
|
|
20
|
+
::Pubid::Itu::Identifiers::AppendixOfRecommendation,
|
|
21
|
+
].freeze
|
|
22
|
+
|
|
23
|
+
# @param refid [Pubid::Itu::Identifier, String] a document reference; a
|
|
24
|
+
# String that Pubid::Itu cannot parse raises Pubid::Errors::ParseError
|
|
9
25
|
# @return [Relaton::Itu::HitCollection]
|
|
10
26
|
def search(refid)
|
|
11
27
|
if refid.is_a? String
|
|
12
28
|
warn_incorrect_ref(refid)
|
|
13
|
-
refid = Pubid.parse refid
|
|
29
|
+
refid = ::Pubid::Itu.parse refid
|
|
14
30
|
end
|
|
15
31
|
HitCollection.new(refid).tap(&:search)
|
|
16
32
|
end
|
|
17
33
|
|
|
18
|
-
# @param
|
|
34
|
+
# @param ref [String, Pubid::Itu::Identifier] the ITU standard Code to
|
|
35
|
+
# look up, or its parse from Relaton::Db (relaton#205); #with_year
|
|
36
|
+
# copies, so the pubid is not changed
|
|
19
37
|
# @param year [String] the year the standard was published (optional)
|
|
20
38
|
# @param opts [Hash] options
|
|
21
39
|
# @return [Relaton::Bib::ItemData, nil]
|
|
22
|
-
def get(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
def get(ref, year = nil, opts = {})
|
|
41
|
+
if ref.is_a? String
|
|
42
|
+
warn_incorrect_ref(ref)
|
|
43
|
+
ref = ::Pubid::Itu.parse(ref)
|
|
44
|
+
end
|
|
45
|
+
refid = with_year ref, year
|
|
26
46
|
|
|
27
47
|
ret = itubib_get1(refid)
|
|
28
48
|
return nil if ret.nil?
|
|
29
49
|
|
|
30
|
-
|
|
50
|
+
unless edition_year(refid) || opts[:keep_year]
|
|
51
|
+
ret = ret.to_most_recent_reference
|
|
52
|
+
end
|
|
31
53
|
ret = ret.to_all_parts if opts[:all_parts]
|
|
32
54
|
ret
|
|
33
55
|
end
|
|
34
56
|
|
|
57
|
+
# The year a reference selects its hits by. It is read the way a hit
|
|
58
|
+
# code's first date is: for an amending supplement, it is the year of
|
|
59
|
+
# the recommendation it amends. HitCollection uses it too.
|
|
60
|
+
#
|
|
61
|
+
# @param refid [Pubid::Itu::Identifier]
|
|
62
|
+
# @return [String, nil]
|
|
63
|
+
def edition_year(refid)
|
|
64
|
+
return refid.base&.year if amending?(refid)
|
|
65
|
+
return refid.base&.year || refid.year if annexed?(refid)
|
|
66
|
+
|
|
67
|
+
refid.year
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# The identifier a reference is a part of: the recommendation an
|
|
71
|
+
# amending supplement, an annex or an appendix belongs to; else itself.
|
|
72
|
+
# A series or recommendation supplement is a document of its own.
|
|
73
|
+
#
|
|
74
|
+
# @param refid [Pubid::Itu::Identifier]
|
|
75
|
+
# @return [Pubid::Itu::Identifier]
|
|
76
|
+
def document(refid)
|
|
77
|
+
amending?(refid) || annexed?(refid) ? refid.base : refid
|
|
78
|
+
end
|
|
79
|
+
|
|
35
80
|
private
|
|
36
81
|
|
|
82
|
+
# @param refid [Pubid::Itu::Identifier]
|
|
83
|
+
# @param year [String, nil] the year passed beside the reference
|
|
84
|
+
# @return [Pubid::Itu::Identifier] refid, dated with year when it has
|
|
85
|
+
# no year of its own
|
|
86
|
+
def with_year(refid, year)
|
|
87
|
+
return refid if year.nil? || edition_year(refid)
|
|
88
|
+
|
|
89
|
+
hash = refid.to_hash
|
|
90
|
+
dated = amending?(refid) ? hash["base"] : hash
|
|
91
|
+
dated["year"] = year.to_s
|
|
92
|
+
::Pubid::Itu::Identifier.from_hash hash
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def amending?(refid) = AMENDING.any? { |klass| refid.is_a? klass }
|
|
96
|
+
|
|
97
|
+
def annexed?(refid) = ANNEXED.any? { |klass| refid.is_a? klass }
|
|
98
|
+
|
|
37
99
|
def warn_incorrect_ref(ref)
|
|
38
100
|
if ref =~ /(ITU[\s-]T\s\w)\.(Suppl\.|Annex)\s?(\w?\d+)/
|
|
39
101
|
correct_ref = "#{$~[1]} #{$~[2]} #{$~[3]}"
|
|
@@ -45,30 +107,59 @@ module Relaton
|
|
|
45
107
|
Util.info "Not found.", key: refid.to_s
|
|
46
108
|
# one hit per edition means a year can repeat (a recommendation and its
|
|
47
109
|
# amendment); the requested year itself is not a "different year" hint
|
|
48
|
-
|
|
110
|
+
year = edition_year(refid)
|
|
111
|
+
years = missed_years.uniq.reject { |y| y == year }
|
|
49
112
|
if years.any?
|
|
50
113
|
plural = years.size > 1 ? "s" : ""
|
|
51
|
-
Util.info "There was no match for `#{
|
|
52
|
-
"found for `#{years.join('`, `')}`
|
|
114
|
+
Util.info "There was no match for `#{year}` year, though there " \
|
|
115
|
+
"were matches found for `#{years.join('`, `')}` " \
|
|
116
|
+
"year#{plural}.", key: refid.to_s
|
|
53
117
|
end
|
|
54
118
|
nil
|
|
55
119
|
end
|
|
56
120
|
|
|
121
|
+
# Keep the hits that are the referenced document, in any edition:
|
|
122
|
+
# #isobib_results_filter picks the year afterwards. The date is ignored,
|
|
123
|
+
# and the version only when the reference names none. Everything else
|
|
124
|
+
# must be equal, so a supplement, or a Report for a Recommendation, never
|
|
125
|
+
# matches.
|
|
126
|
+
#
|
|
127
|
+
# Not `===`: it reads a missing `subseries` as "any value", so
|
|
128
|
+
# `ITU-T H.264` would keep `ITU-T H.264.1`.
|
|
57
129
|
def search_filter(refid)
|
|
58
|
-
|
|
59
|
-
|
|
130
|
+
ignore = %i[year month day]
|
|
131
|
+
ignore << :version unless stated_version?(refid)
|
|
132
|
+
search(refid).select do |i|
|
|
60
133
|
next true unless i.hit[:code]
|
|
61
134
|
|
|
62
|
-
|
|
63
|
-
refid
|
|
135
|
+
hit = ::Pubid::Itu.parse(i.hit[:code])
|
|
136
|
+
refid.matches?(hit, ignore: ignore) && same_own_date?(refid, hit)
|
|
137
|
+
rescue ::Pubid::Errors::ParseError
|
|
138
|
+
false # a live hit ITU spells in a form nothing can identify
|
|
64
139
|
end
|
|
65
140
|
end
|
|
66
141
|
|
|
142
|
+
# A version on the reference, or on the recommendation it amends.
|
|
143
|
+
def stated_version?(refid)
|
|
144
|
+
id = document(refid)
|
|
145
|
+
id.respond_to?(:version) && !id.version.nil?
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# `ignore:` drops the date at every level, but an amending supplement's
|
|
149
|
+
# own date tells two "Amd. 1" to different editions apart.
|
|
150
|
+
def same_own_date?(refid, hit)
|
|
151
|
+
return true unless amending?(refid)
|
|
152
|
+
|
|
153
|
+
own = refid.to_hash.slice("year", "month", "day")
|
|
154
|
+
own.all? { |key, value| hit.to_hash[key] == value }
|
|
155
|
+
end
|
|
156
|
+
|
|
67
157
|
def isobib_results_filter(result, refid)
|
|
68
158
|
missed_years = []
|
|
159
|
+
year = edition_year(refid)
|
|
69
160
|
result.each do |r|
|
|
70
161
|
/\((?:\d{2}\/)?(?<pyear>\d{4})\)/ =~ r.hit[:code]
|
|
71
|
-
if !
|
|
162
|
+
if !year || year == pyear
|
|
72
163
|
ret = r.item
|
|
73
164
|
return { ret: ret } if ret
|
|
74
165
|
end
|
|
@@ -564,7 +564,7 @@ module Relaton
|
|
|
564
564
|
# the first cell, the title in the second.
|
|
565
565
|
#
|
|
566
566
|
# @param url [String]
|
|
567
|
-
# @return [Array<Array(String,
|
|
567
|
+
# @return [Array<Array(String, Moxml::Element, Moxml::NodeSet)>]
|
|
568
568
|
def rows(url)
|
|
569
569
|
get(url).search("//a[contains(@href,'parent=R-')]").filter_map do |a|
|
|
570
570
|
id = a[:href].to_s[PARENT_RE, :id]
|
|
@@ -576,7 +576,7 @@ module Relaton
|
|
|
576
576
|
# The title cell carries an optional red annotation ("Note - Suppressed on
|
|
577
577
|
# …"), which is not part of the title.
|
|
578
578
|
#
|
|
579
|
-
# @param cell [
|
|
579
|
+
# @param cell [Moxml::Element, nil]
|
|
580
580
|
# @return [String]
|
|
581
581
|
def title_text(cell)
|
|
582
582
|
return "" unless cell
|