relaton 3.0.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/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 +99 -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,161 +1,30 @@
|
|
|
1
|
+
require_relative "recommendation_fields"
|
|
2
|
+
|
|
1
3
|
module Relaton
|
|
2
4
|
module Itu
|
|
5
|
+
# Live-lookup ITU-T Recommendation parser. All field extraction lives in the
|
|
6
|
+
# shared RecommendationFields module (reused by the offline DataParserT
|
|
7
|
+
# harvester); this class only binds the module's `agent`/`idrec`/`imp` hooks.
|
|
3
8
|
class RecommendationParser
|
|
4
|
-
include
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
include RecommendationFields
|
|
10
|
+
|
|
11
|
+
# @param agent [Mechanize] the HTTP agent (was a Hit before decoupling)
|
|
12
|
+
# @param idrec [String, Integer] the recommendation record id
|
|
13
|
+
# @param imp [Boolean] Implementers' Guide flag
|
|
14
|
+
# @param cache [#fetch, #warm] cross-row cache for the family-invariant
|
|
15
|
+
# endpoints. Defaults to NullCache, i.e. off — only the offline
|
|
16
|
+
# harvester passes a real one, so the live lookup path keeps exactly the
|
|
17
|
+
# behaviour and the request count it had before the cache existed.
|
|
18
|
+
def initialize(agent, idrec, imp, cache: NullCache.instance)
|
|
19
|
+
@agent = agent
|
|
13
20
|
@idrec = idrec
|
|
14
21
|
@imp = imp
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def doc
|
|
18
|
-
@doc ||= begin
|
|
19
|
-
url = (imp ? IMPLGUIDES : RECHDR) % { idrec: idrec }
|
|
20
|
-
resp = get_data url
|
|
21
|
-
imp ? resp.first : resp
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# @return [String, nil]
|
|
26
|
-
def fetch_edition
|
|
27
|
-
self_edition&.dig("Version")
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# @return [Array<Relaton::Bib::Title>]
|
|
31
|
-
def fetch_titles
|
|
32
|
-
title = imp ? doc["imp_title_e"] : doc["rec_title"]
|
|
33
|
-
return [] if title.nil? || title.empty?
|
|
34
|
-
|
|
35
|
-
Relaton::Bib::Title.from_string title, "en", "Latn"
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# @return [Relaton::Bib::Status, nil]
|
|
39
|
-
def fetch_status
|
|
40
|
-
inforce = imp ? imp_status : doc["status"]
|
|
41
|
-
return if inforce.nil? || inforce.empty?
|
|
42
|
-
|
|
43
|
-
status = inforce == "In force" ? "Published" : "Withdrawal"
|
|
44
|
-
Relaton::Bib::Status.new(stage: Relaton::Bib::Status::Stage.new(content: status))
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# @return [Array<Relaton::Bib::Date>]
|
|
48
|
-
def fetch_dates
|
|
49
|
-
array(doc_date).map { |on| Relaton::Bib::Date.new(type: "published", at: on) }
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# @return [Array<Relaton::Bib::LocalizedMarkedUpString>]
|
|
53
|
-
def fetch_abstract
|
|
54
|
-
array(doc["summary"]).map do |content|
|
|
55
|
-
Relaton::Bib::Abstract.new(content: content, language: "en", script: "Latn")
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# @return [Array<Relaton::Bib::Uri>]
|
|
60
|
-
def fetch_source
|
|
61
|
-
link = imp ? doc["imp_dms_link"] : doc["handle_id"]
|
|
62
|
-
links = [Relaton::Bib::Uri.new(type: "src", content: link)]
|
|
63
|
-
links << Relaton::Bib::Uri.new(type: "pdf", content: doc["handle_id_pdf_link"]) if doc["handle_id_pdf_link"]
|
|
64
|
-
imp_word_link { |wlink| links << Relaton::Bib::Uri.new(type: "word", content: wlink) }
|
|
65
|
-
links
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def doc_date
|
|
69
|
-
return @doc_date if defined? @doc_date
|
|
70
|
-
|
|
71
|
-
date = imp ? doc["imp_approval_date"] : doc["approval_date"]
|
|
72
|
-
@doc_date = Date.parse(date).to_s rescue date # rubocop:disable Style/RescueModifier
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# @return [Array<Relaton::Bib::Relation>]
|
|
76
|
-
def fetch_relations
|
|
77
|
-
relations = []
|
|
78
|
-
editions.each do |ed|
|
|
79
|
-
next if ed["idrec"] == idrec
|
|
80
|
-
|
|
81
|
-
relations << create_relation("hasEdition", ed["title"], ed["rec_name"])
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
supplements.each { |supp| relations << create_relation("complementOf", supp["title_text"], supp["rec_name"]) }
|
|
85
|
-
relations
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
# Fetch the study group name from the recommendation HTML page.
|
|
89
|
-
# @return [String, nil]
|
|
90
|
-
def fetch_workgroup
|
|
91
|
-
url = "https://www.itu.int/ITU-T/recommendations/rec.aspx?rec=#{idrec}&lang=en"
|
|
92
|
-
page = hit.hit_collection.agent.get(url)
|
|
93
|
-
wg = page.at('//span[contains(@id, "uc_rec_main_info1_rpt_main_ctl00_Label8")]/a')
|
|
94
|
-
wg&.text
|
|
95
|
-
rescue StandardError
|
|
96
|
-
nil
|
|
22
|
+
@cache = cache
|
|
97
23
|
end
|
|
98
24
|
|
|
99
25
|
private
|
|
100
26
|
|
|
101
|
-
attr_reader :
|
|
102
|
-
|
|
103
|
-
def get_data(url)
|
|
104
|
-
JSON.parse request_document(url).body
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def request_document(url)
|
|
108
|
-
hit.hit_collection.agent.get url
|
|
109
|
-
rescue Mechanize::ResponseCodeError, SocketError, Timeout::Error, Errno::ECONNRESET,
|
|
110
|
-
EOFError, Net::ProtocolError, OpenSSL::SSL::SSLError => e
|
|
111
|
-
raise Relaton::RequestError, "Could not access #{url}: #{e.message}"
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def editions
|
|
115
|
-
@editions ||= begin
|
|
116
|
-
url = RECEDITIONS % { idrec: idrec }
|
|
117
|
-
get_data(url) || []
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def self_edition
|
|
122
|
-
@self_edition ||= editions.find { |ed| ed["idrec"] == idrec }
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def imp_status
|
|
126
|
-
self_edition&.dig("status")
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def imp_word_link
|
|
130
|
-
return unless doc["imp_dms_link"]
|
|
131
|
-
|
|
132
|
-
@doc_page ||= request_document(doc["imp_dms_link"])
|
|
133
|
-
wrd_elm = @doc_page.at("//font[contains(.,'Word')]/../..")
|
|
134
|
-
yield wrd_elm[:href] if block_given? && wrd_elm
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def create_relation(type, title_text, id)
|
|
138
|
-
titles = []
|
|
139
|
-
if title_text && !title_text.empty?
|
|
140
|
-
titles << Relaton::Bib::Title.new(content: title_text, language: "en", script: "Latn")
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
fref = titles.empty? ? id : nil
|
|
144
|
-
did = Relaton::Bib::Docidentifier.new(type: "ITU", content: id, primary: true)
|
|
145
|
-
bibitem = Relaton::Bib::ItemData.new(title: titles, formattedref: (fref ? Relaton::Bib::Formattedref.new(content: fref) : nil), docidentifier: [did])
|
|
146
|
-
Relaton::Bib::Relation.new(type: type, bibitem: bibitem)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def supplements
|
|
150
|
-
@supplements ||= begin
|
|
151
|
-
if imp
|
|
152
|
-
[]
|
|
153
|
-
else
|
|
154
|
-
url = RECSUPPLEMENTS % { idrec: idrec }
|
|
155
|
-
get_data(url) || []
|
|
156
|
-
end
|
|
157
|
-
end
|
|
158
|
-
end
|
|
27
|
+
attr_reader :agent, :idrec, :imp, :cache
|
|
159
28
|
end
|
|
160
29
|
end
|
|
161
30
|
end
|
data/lib/relaton/itu/scraper.rb
CHANGED
|
@@ -78,19 +78,29 @@ module Relaton
|
|
|
78
78
|
def parser
|
|
79
79
|
@parser ||= begin
|
|
80
80
|
if idrec
|
|
81
|
-
RecommendationParser.new hit, idrec, imp
|
|
81
|
+
RecommendationParser.new hit.hit_collection.agent, idrec, imp
|
|
82
82
|
else
|
|
83
83
|
RadioRegulationsParser.new hit
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
#
|
|
88
|
+
# The primary docid comes from the hit's code; a recommendation additionally
|
|
89
|
+
# carries the equivalent ISO/IEC(/IEEE) identifier, which used to be part of
|
|
90
|
+
# the search result's media name and now comes from the recommendation
|
|
91
|
+
# header's `iso_number` via the shared `RecommendationFields#iso_docid`.
|
|
92
|
+
# Both are guarded on `idrec` — `RadioRegulationsParser` (RR/OB) parses an
|
|
93
|
+
# HTML page and has neither `rec_name` nor `iso_docid`.
|
|
94
|
+
#
|
|
89
95
|
# @return [Array<Relaton::Bib::Docidentifier>]
|
|
90
96
|
def docid
|
|
91
97
|
@docid ||= begin
|
|
92
98
|
docids = hit.hit[:code].to_s.split(" | ").map { |c| createdocid(c) }
|
|
93
|
-
|
|
99
|
+
if idrec
|
|
100
|
+
docids << createdocid("ITU-T #{parser.doc['rec_name']}") if docids.empty?
|
|
101
|
+
iso = parser.iso_docid
|
|
102
|
+
docids << iso if iso
|
|
103
|
+
end
|
|
94
104
|
docids
|
|
95
105
|
end
|
|
96
106
|
end
|
data/lib/relaton/itu.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require "mechanize"
|
|
2
2
|
require "parslet"
|
|
3
|
+
require "pubid"
|
|
3
4
|
require "digest/md5"
|
|
4
5
|
require "relaton/index"
|
|
5
6
|
require "relaton/bib"
|
|
@@ -17,7 +18,7 @@ require_relative "itu/bibliography"
|
|
|
17
18
|
|
|
18
19
|
module Relaton
|
|
19
20
|
module Itu
|
|
20
|
-
INDEXFILE = "index-
|
|
21
|
+
INDEXFILE = "index-v2"
|
|
21
22
|
|
|
22
23
|
class Error < StandardError; end
|
|
23
24
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require "net/http"
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
module Jcgm
|
|
5
|
+
# Retrieval for JCGM (Joint Committee for Guides in Metrology) publications.
|
|
6
|
+
# Index-backed (no scraping): the reference is parsed with `Pubid::Jcgm`,
|
|
7
|
+
# matched against the pre-built index (whose rows are `Pubid::Jcgm::Identifier`
|
|
8
|
+
# hashes, deserialized via `pubid_class`), and the matching per-document YAML
|
|
9
|
+
# is fetched from the `relaton/relaton-data-jcgm` GitHub repo.
|
|
10
|
+
module Bibliography
|
|
11
|
+
ENDPOINT = "https://raw.githubusercontent.com/relaton/relaton-data-jcgm/main/".freeze
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
#
|
|
15
|
+
# Search for a JCGM publication by its identifier.
|
|
16
|
+
#
|
|
17
|
+
# @param text [String, Pubid::Jcgm::Identifier] e.g. "JCGM 200:2012" or
|
|
18
|
+
# "JCGM 17th Meeting (2012)"
|
|
19
|
+
# @param year [String, nil] edition year (optional; may be embedded)
|
|
20
|
+
# @param _opts [Hash] options (unused)
|
|
21
|
+
#
|
|
22
|
+
# @return [Relaton::Jcgm::Item, nil]
|
|
23
|
+
#
|
|
24
|
+
def search(text, year = nil, _opts = {}) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
25
|
+
pubid = parse_ref(text)
|
|
26
|
+
Util.info "Fetching from Relaton repository ...", key: pubid.to_s
|
|
27
|
+
row = index.search(pubid) { |r| pubid_match?(r[:id], pubid, year) }
|
|
28
|
+
.max_by { |r| r[:id].year.to_i }
|
|
29
|
+
unless row
|
|
30
|
+
Util.info "Not found.", key: pubid.to_s
|
|
31
|
+
return
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
uri = URI("#{ENDPOINT}#{row[:file]}")
|
|
35
|
+
resp = Net::HTTP.get_response uri
|
|
36
|
+
unless resp.code == "200"
|
|
37
|
+
raise Relaton::RequestError, "Could not access #{uri}: HTTP #{resp.code}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
item = Relaton::Jcgm::Item.from_yaml resp.body
|
|
41
|
+
Util.info "Found: `#{item.docidentifier.first&.content}`", key: pubid.to_s
|
|
42
|
+
item.tap { |i| i.fetched = Date.today.to_s }
|
|
43
|
+
rescue SocketError, Errno::EINVAL, Errno::ECONNRESET, EOFError,
|
|
44
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
|
45
|
+
Net::ProtocolError, Net::ReadTimeout, OpenSSL::SSL::SSLError,
|
|
46
|
+
Errno::ETIMEDOUT => e
|
|
47
|
+
raise Relaton::RequestError, "Could not access #{uri}: #{e.message}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @see #search
|
|
51
|
+
def get(ref, year = nil, opts = {})
|
|
52
|
+
search(ref, year, opts)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
# Parse a reference into a Pubid::Jcgm identifier. An unrecognized
|
|
58
|
+
# reference raises; like ISO and 3GPP we let it propagate --
|
|
59
|
+
# relaton-cli rescues Pubid::Errors::Error and renders "... is not a
|
|
60
|
+
# recognized standards identifier". The `search` rescue lists transport
|
|
61
|
+
# errors only, so it does not swallow the parse error.
|
|
62
|
+
def parse_ref(text)
|
|
63
|
+
return text unless text.is_a?(String)
|
|
64
|
+
|
|
65
|
+
::Pubid::Jcgm.parse(text)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def index
|
|
69
|
+
Relaton::Index.find_or_create(
|
|
70
|
+
:jcgm,
|
|
71
|
+
url: "#{ENDPOINT}#{INDEXFILE}.zip",
|
|
72
|
+
file: "#{INDEXFILE}.yaml",
|
|
73
|
+
pubid_class: ::Pubid::Jcgm::Identifier,
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# `row_id` and `query` are both `Pubid::Jcgm::Identifier` instances.
|
|
78
|
+
# Matching is pubid's asymmetric subset match (`Pubid::SubsetMatch`):
|
|
79
|
+
# the reference on the left, the row on the right, and a component the
|
|
80
|
+
# reference omits matches any value. Guides distinguish editions by year
|
|
81
|
+
# (`JCGM 200:2008` vs `:2012`), so a reference without a year reaches
|
|
82
|
+
# both and the latest edition is picked by `max_by` in #search. Meetings
|
|
83
|
+
# distinguish by number (`17th` vs `18th`), which the reference states,
|
|
84
|
+
# so they never collapse together. The type is the identifier's class,
|
|
85
|
+
# and `===` requires the same class, so cross-type collisions cannot
|
|
86
|
+
# occur. The `year` argument lets a caller pin an edition the reference
|
|
87
|
+
# string omitted; a year the reference states is compared by `===`
|
|
88
|
+
# itself.
|
|
89
|
+
def pubid_match?(row_id, query, year)
|
|
90
|
+
wanted_year = (query.year || year)&.to_s
|
|
91
|
+
query === row_id &&
|
|
92
|
+
(wanted_year.nil? || row_id.year.to_s == wanted_year)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require_relative "../jcgm"
|
|
2
|
+
require_relative "meetings_parser"
|
|
3
|
+
|
|
4
|
+
module Relaton::Jcgm
|
|
5
|
+
# Harvests the JCGM **meeting proceedings** from the `jcgm/meetings-{en,fr}`
|
|
6
|
+
# dirs of a local checkout of metanorma/bipm-data-outcomes, writing one Relaton
|
|
7
|
+
# YAML per meeting and indexing each by its `Pubid::Jcgm` identifier.
|
|
8
|
+
#
|
|
9
|
+
# The curated guide/GUM/VIM records are **not** harvested here: they are
|
|
10
|
+
# hand-maintained YAMLs that live in the data repo's own `static/` dir, so the
|
|
11
|
+
# data repo's `crawler.rb` indexes them (like relaton-data-bipm's crawler does)
|
|
12
|
+
# by looping `static/**` and calling the public, guarded {#add_to_index} —
|
|
13
|
+
# keeping the "which static files" policy in the data repo while the guarded,
|
|
14
|
+
# sorted, `_type: pubid:jcgm:*` indexing mechanism stays here.
|
|
15
|
+
class DataFetcher < Relaton::Core::DataFetcher
|
|
16
|
+
attr_reader :output, :format, :ext, :files, :errors
|
|
17
|
+
|
|
18
|
+
def index
|
|
19
|
+
@index ||= Relaton::Index.find_or_create(
|
|
20
|
+
:jcgm, file: "#{INDEXFILE}.yaml", pubid_class: ::Pubid::Jcgm::Identifier
|
|
21
|
+
)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def log_error(msg) = Util.error msg
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# @param [String] source dataset name ("bipm-data-outcomes")
|
|
28
|
+
#
|
|
29
|
+
def fetch(source)
|
|
30
|
+
MeetingsParser.parse(self) if source == "bipm-data-outcomes"
|
|
31
|
+
index.save
|
|
32
|
+
report_errors
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# Save document to file
|
|
37
|
+
#
|
|
38
|
+
# @param [String] path Path to file
|
|
39
|
+
# @param [Relaton::Jcgm::ItemData] item document to save
|
|
40
|
+
# @param [Boolean, nil] warn_duplicate Warn if document already exists
|
|
41
|
+
#
|
|
42
|
+
def write_file(path, item, warn_duplicate: true)
|
|
43
|
+
content = serialize item
|
|
44
|
+
if @files.include?(path)
|
|
45
|
+
Util.warn "File #{path} already exists" if warn_duplicate
|
|
46
|
+
else
|
|
47
|
+
@files << path
|
|
48
|
+
end
|
|
49
|
+
File.write path, content, encoding: "UTF-8"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
#
|
|
53
|
+
# Index a document by its pubid. Guarded defensively: a docnumber the
|
|
54
|
+
# `Pubid::Jcgm` grammar can't parse is skipped with a warning rather than
|
|
55
|
+
# allowed to corrupt the whole index (`Relaton::Index` rejects an index if a
|
|
56
|
+
# single row fails to deserialize). All current JCGM records parse on pubid
|
|
57
|
+
# main; the guard protects against a future malformed record.
|
|
58
|
+
#
|
|
59
|
+
# Public so the data repo's crawler can index its curated `static/` guides
|
|
60
|
+
# through the same guarded, sorted, pubid-backed path the meetings use.
|
|
61
|
+
#
|
|
62
|
+
# @param [String] docnumber the record's docnumber (e.g. "JCGM 17th Meeting (2012)")
|
|
63
|
+
# @param [String] path repo-relative path to the YAML file
|
|
64
|
+
#
|
|
65
|
+
def add_to_index(docnumber, path)
|
|
66
|
+
# Store the Pubid::Jcgm identifier object (not its hash): with pubid_class
|
|
67
|
+
# set, Relaton::Index then sorts the index by id number on save and
|
|
68
|
+
# serializes each id to its `_type: pubid:jcgm:*` hash, so the published
|
|
69
|
+
# index is already sorted (no "not sorted by id number" warning on fetch).
|
|
70
|
+
index.add_or_update ::Pubid::Jcgm.parse(docnumber), path
|
|
71
|
+
rescue StandardError => e
|
|
72
|
+
Util.warn "Skipping index entry for `#{docnumber}` (#{path}): #{e.message}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def to_xml(item) = item.to_xml bibdata: true
|
|
76
|
+
|
|
77
|
+
def to_yaml(item) = item.to_yaml
|
|
78
|
+
|
|
79
|
+
def to_bibxml(item) = item.to_rfcxml
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Jcgm
|
|
3
|
+
# A JCGM document identifier, backed by `Pubid::Jcgm` (mirrors OIML's
|
|
4
|
+
# pubid-backed Docidentifier). Parsing is best-effort: forms pubid doesn't
|
|
5
|
+
# recognise (e.g. the combined bilingual docidentifiers and the French
|
|
6
|
+
# `réunion` form) leave `pubid` nil via the `content=` rescue rather than
|
|
7
|
+
# raising during deserialization.
|
|
8
|
+
class Docidentifier < Bib::Docidentifier
|
|
9
|
+
attr_reader :pubid
|
|
10
|
+
|
|
11
|
+
# Capture the inherited content setter before overriding #content=, so
|
|
12
|
+
# #refresh_content! can write the re-rendered string back WITHOUT
|
|
13
|
+
# re-parsing (a re-parse would rebuild @pubid from the string, which may
|
|
14
|
+
# not even parse back — e.g. an all-parts wrapper's own "(all parts)"
|
|
15
|
+
# rendering — and would discard whatever mutation was just made).
|
|
16
|
+
alias_method :store_content, :content=
|
|
17
|
+
|
|
18
|
+
def initialize(attrs = {}, options = {})
|
|
19
|
+
pubid = attrs.is_a?(Hash) ? attrs.delete(:pubid) : nil
|
|
20
|
+
attrs[:content] ||= pubid.to_s if pubid
|
|
21
|
+
super
|
|
22
|
+
@pubid = pubid if pubid
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def content=(value)
|
|
26
|
+
super
|
|
27
|
+
@pubid = ::Pubid::Jcgm.parse(value) if value
|
|
28
|
+
rescue StandardError
|
|
29
|
+
@pubid = nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The class carried `#pubid` but none of `Bib::Docidentifier`'s abstract
|
|
33
|
+
# `remove_part!` / `remove_date!` / `to_all_parts!`, so it looked migrated
|
|
34
|
+
# while still raising `NotImplementedError` on every JCGM item through
|
|
35
|
+
# `Bib::ItemData#to_all_parts` / `#to_most_recent_reference` — and
|
|
36
|
+
# `NotImplementedError` descends from `ScriptError`, so a caller's
|
|
37
|
+
# `rescue => e` did not catch it.
|
|
38
|
+
#
|
|
39
|
+
# `Pubid::Jcgm` keeps the publication date in `date` (a
|
|
40
|
+
# `Components::Date`, unlike EASC's and GOST's plain `year`), so
|
|
41
|
+
# `remove_date!` clears that: `JCGM 100:2008` -> `JCGM 100`. `part` and
|
|
42
|
+
# `subpart` come from the pubid base class and are unused by JCGM today,
|
|
43
|
+
# so `remove_part!` is a no-op for the rendered string — implemented so it
|
|
44
|
+
# never raises.
|
|
45
|
+
#
|
|
46
|
+
# The mutation is applied to the identifier **and to its `#root`**. A
|
|
47
|
+
# supplement/corrigendum wraps the document it amends in `base`, and it
|
|
48
|
+
# exposes its own `date=` while carrying nil there — the year lives on the
|
|
49
|
+
# base. Clearing only the wrapper is therefore a silent no-op:
|
|
50
|
+
# `JCGM 200:2008 Corrigendum` keeps its 2008. Clearing the root as well
|
|
51
|
+
# gives `JCGM 200 Corrigendum`. `#root` is the same accessor
|
|
52
|
+
# `Relaton::Index::Type#candidates_by_number` narrows on, so the two stay
|
|
53
|
+
# consistent.
|
|
54
|
+
#
|
|
55
|
+
# Every write is guarded by `respond_to?`, and all three no-op when
|
|
56
|
+
# `@pubid` is nil — the common case the `content=` rescue exists for (the
|
|
57
|
+
# combined bilingual docidentifiers and the French `réunion` form).
|
|
58
|
+
|
|
59
|
+
def remove_part!
|
|
60
|
+
clear_attr!(:part)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def remove_date!
|
|
64
|
+
clear_attr!(:date)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def to_all_parts!
|
|
68
|
+
return if !@pubid || @pubid.all_parts?
|
|
69
|
+
|
|
70
|
+
# `#exclude` (no args) rebuilds a full independent copy, including
|
|
71
|
+
# the `#root` of a supplement/corrigendum — `remove_part!`/
|
|
72
|
+
# `remove_date!` mutate BOTH `@pubid` and its root in place (see
|
|
73
|
+
# `clear_attr!`), so even a shallow `.dup` would still lose the
|
|
74
|
+
# original date to that mutation.
|
|
75
|
+
original = @pubid.exclude
|
|
76
|
+
remove_part!
|
|
77
|
+
remove_date!
|
|
78
|
+
@pubid = original.to_all_parts
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def clear_attr!(attr)
|
|
84
|
+
return unless @pubid
|
|
85
|
+
|
|
86
|
+
targets = [@pubid]
|
|
87
|
+
targets << @pubid.root if @pubid.respond_to?(:root) && !@pubid.root.equal?(@pubid)
|
|
88
|
+
targets.each do |id|
|
|
89
|
+
next unless id.respond_to?("#{attr}=")
|
|
90
|
+
|
|
91
|
+
id.public_send("#{attr}=", nil)
|
|
92
|
+
id.subpart = nil if attr == :part && id.respond_to?(:subpart=)
|
|
93
|
+
end
|
|
94
|
+
refresh_content!
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def refresh_content!
|
|
98
|
+
store_content(@pubid.to_s) if @pubid
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Jcgm
|
|
3
|
+
# JCGM document types. Meetings are `meeting-report`; the guides/GUM/VIM
|
|
4
|
+
# records carry `international-standard` (the shape they were filed with
|
|
5
|
+
# under BIPM). The list is intentionally not enforced as an enum so any
|
|
6
|
+
# unforeseen dataset value still round-trips (mirrors OIML's Doctype).
|
|
7
|
+
class Doctype < Bib::Doctype
|
|
8
|
+
TYPES = %w[meeting-report guide international-standard vocabulary
|
|
9
|
+
monographie rapport].freeze
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require_relative "doctype"
|
|
2
|
+
require_relative "structured_identifier"
|
|
3
|
+
|
|
4
|
+
module Relaton
|
|
5
|
+
module Jcgm
|
|
6
|
+
# JCGM bibliographic item extension. JCGM records are BIPM-shaped, so this
|
|
7
|
+
# mirrors `Relaton::Bipm::Ext`: a JCGM `Doctype` and a single
|
|
8
|
+
# `structuredidentifier` (overriding the base collection). `flavor`,
|
|
9
|
+
# `schema_version`, `subdoctype`, `ics` come from the shared `Bib::Ext`.
|
|
10
|
+
class Ext < Bib::Ext
|
|
11
|
+
attribute :doctype, Doctype
|
|
12
|
+
attribute :structuredidentifier, StructuredIdentifier
|
|
13
|
+
|
|
14
|
+
xml do
|
|
15
|
+
map_element "structuredidentifier", to: :structuredidentifier
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
key_value do
|
|
19
|
+
map_element "structuredidentifier", to: :structuredidentifier
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require_relative "item_data"
|
|
2
|
+
require_relative "ext"
|
|
3
|
+
require_relative "docidentifier"
|
|
4
|
+
|
|
5
|
+
module Relaton
|
|
6
|
+
module Jcgm
|
|
7
|
+
class Item < Bib::Item
|
|
8
|
+
model ItemData
|
|
9
|
+
|
|
10
|
+
attribute :ext, Ext
|
|
11
|
+
attribute :docidentifier, Docidentifier, collection: true,
|
|
12
|
+
initialize_empty: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require_relative "relation"
|
|
18
|
+
|
|
19
|
+
Relaton::Jcgm::Item.attribute :relation, Relaton::Jcgm::Relation,
|
|
20
|
+
collection: true, initialize_empty: true
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module Jcgm
|
|
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
|