relaton-iec 1.14.1 → 1.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64b4e21a953edecfca9d2ccb0b9dde4e91f8d7e6ced8ce5be3c825142f5e853b
4
- data.tar.gz: c8478d74927f064b4c2711fbd916a1fb68ac1ee6ffa5ecde681c3374816ac024
3
+ metadata.gz: 4d00653dcd13da1fbfe251bd51366bcb0e038980a6a5598e8d06e90e93c25a5c
4
+ data.tar.gz: 1f70ddc26bc98c7a8da254e8eb7b31a28508c06763ebc3ab4de44dfc008b5465
5
5
  SHA512:
6
- metadata.gz: e65980c0a520d2244db616e3dcced3a97e0ca3c8c8aed4a9a856eeca4badd5cd0a8bd3748207b5e52c58154066a291e0797b3c8b2c67b4d2472418f050acde6d
7
- data.tar.gz: 22894e978223c56b60aab15c4a497982e8b783ab857dd20386a81485eb19b87283d7da5d903a11dd90fb91230fc576b2e5ce3b70a05cc57c664595376b829e98
6
+ metadata.gz: b4b1f3a22cfa10e630795cebe87ee63ef4e803f4ca276d1f94b37ab09e940d9abc430ab66fbd80e781c1dd8055dd948209f767449139d23bbc42ecbe4e4501cf
7
+ data.tar.gz: 9ad6a0084b3144ffde1c06237265ca2a6e73ae3762c4dc210ae199a70bdd931866f3db0dfdc1ebbbf17d3714942c33346dc9fb8ae1233910433ba6391bdd7281
data/Gemfile CHANGED
@@ -4,3 +4,9 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in relaton_iec.gemspec
6
6
  gemspec
7
+
8
+ gem "pry-byebug"
9
+ gem "ruby-jing"
10
+ gem "simplecov"
11
+ gem "vcr"
12
+ gem "webmock"
data/README.adoc CHANGED
@@ -47,25 +47,24 @@ hit_collection = RelatonIec::IecBibliography.search("60050")
47
47
  => <RelatonIec::HitCollection:0x007fe0d7126f28 @ref=60050 @fetched=false>
48
48
 
49
49
  hit_collection.first
50
- => <RelatonIec::Hit:0x007fe1068b4d10 @text="60050" @fetched="false" @fullIdentifier="" @title="IEC 60050-102:2007">
50
+ => <RelatonIec::Hit:0x000000000003e8 @text="60050" @fetched="false" @fullIdentifier="" @title="IEC 60050-05:1935">
51
51
 
52
52
  item = hit_collection[2].fetch
53
53
  => #<RelatonIec::IecBibliographicItem:0x007fe1171a06f8
54
54
  ...
55
55
 
56
56
  item.docidentifier
57
- => [#<RelatonBib::DocumentIdentifier:0x00007f876539d1b0 @id="IEC 60050-112:2010", @language=nil, @primary=true, @scope=nil, @script=nil, @type="IEC">,
58
- #<RelatonBib::DocumentIdentifier:0x00007f876539d070
59
- @id="urn:iec:std:iec:60050-112:2010:::en",
57
+ => [#<RelatonBib::DocumentIdentifier:0x00007ff1b52a2b60 @id="IEC 60050-07:1956", @language=nil, @primary=true, @scope=nil, @script=nil, @type="IEC">,
58
+ #<RelatonBib::DocumentIdentifier:0x00007ff1b52a2a98
59
+ @id="urn:iec:std:iec:60050-07:1956-01:::",
60
60
  @language=nil,
61
61
  @primary=nil,
62
62
  @scope=nil,
63
63
  @script=nil,
64
64
  @type="URN">]
65
- [6] pry(main)>
66
65
 
67
66
  item.docidentifier.detect { |di| di.type == "URN" }.id
68
- => "urn:iec:std:iec:60050-112:2010:::en"
67
+ => "urn:iec:std:iec:60050-07:1956-01:::"
69
68
  ----
70
69
 
71
70
  === Fetch document by keywords
@@ -79,8 +78,8 @@ item.docidentifier.detect { |di| di.type == "URN" }.id
79
78
  [source,ruby]
80
79
  ----
81
80
  item = RelatonIec::IecBibliography.get("IEC 60050-112:2010")
82
- [relaton-iec] ("IEC 60050-112") fetching...
83
- [relaton-iec] ("IEC 60050-112") found IEC 60050-112:2010
81
+ [relaton-iec] ("IEC 60050-112:2010") fetching...
82
+ [relaton-iec] ("IEC 60050-112:2010") found IEC 60050-112:2010
84
83
  => #<RelatonIec::IecBibliographicItem:0x00007f876525e8d0
85
84
  ...
86
85
 
@@ -104,15 +103,12 @@ item.docidentifier.first
104
103
 
105
104
  === Search for ISO/IEC Directives
106
105
 
107
- The ISO/IEC Directives are stored in a static cache in a relaton gem. It needs to use the relaton gem to fetch the ISO/IEC Directives. The following references are allowed to fetch:
106
+ The following references are allowed to fetch:
108
107
 
109
- - ISO/IEC DIR 1 - Procedures for the technical work
110
- - ISO/IEC DIR 1 IEC SUP - Procedures for the technical work Procedures specific to IEC
111
- - ISO/IEC DIR 1 ISO SUP - Consolidated ISO Supplement -- Procedures specific to ISO
112
- - ISO/IEC DIR 2 IEC - Principles and rules for the structure and drafting of ISO and IEC documents
113
- - ISO/IEC DIR 2 ISO - Principles and rules for the structure and drafting of ISO and IEC documents
114
- - ISO/IEC DIR IEC SUP - Procedures specific to IEC
115
- - ISO/IEC DIR JTC 1 SUP - Procedures specific to JTC 1
108
+ - `IEC 61360-4 DB` - IEC/SC 3D - Common Data Dictionary (CDD - V2.0015.0001)
109
+ - `ISO/IEC DIR 1 IEC SUP` - Procedures for the technical work - Procedures specific to IEC
110
+ - `ISO/IEC DIR 2 IEC` - Principles and rules for the structure and drafting of ISO and IEC documents
111
+ - 'ISO/IEC DIR IEC SUP' - Procedures specific to IEC
116
112
 
117
113
  === XML serialization
118
114
 
@@ -125,22 +121,22 @@ Possible options:
125
121
  ----
126
122
  item.to_xml
127
123
  => "<bibitem id="IEC60050-112-2010" type="standard" schema-version="v1.2.1">
128
- <fetched>2022-12-03</fetched>
129
- <title type="title-main" format="text/plain" language="en" script="Latn">International Electrotechnical Vocabulary (IEV)</title>
130
- <title type="title-part" format="text/plain" language="en" script="Latn">Part 112: Quantities and units</title>
124
+ <fetched>2023-03-01</fetched>
131
125
  <title type="main" format="text/plain" language="en" script="Latn">International Electrotechnical Vocabulary (IEV) - Part 112: Quantities and units</title>
126
+ <title type="main" format="text/plain" language="fr" script="Latn">Vocabulaire Electrotechnique International (IEV) - Partie 112: Grandeurs et unités</title>
127
+ <title type="main" format="text/plain" language="es" script="Latn">Versión Oficial En español - Vocabulario Electrotécnico Internacional. Parte 112: Magnitudes y unidades.</title>
132
128
  <uri type="src">https://webstore.iec.ch/publication/162</uri>
133
129
  ...
134
130
  </bibitem>"
135
131
 
136
132
  item.to_xml bibdata: true
137
133
  => "<bibdata type="standard" schema-version="v1.2.1">
138
- <fetched>2022-12-03</fetched>
139
- <title type="title-main" format="text/plain" language="en" script="Latn">International Electrotechnical Vocabulary (IEV)</title>
140
- <title type="title-part" format="text/plain" language="en" script="Latn">Part 112: Quantities and units</title>
134
+ <fetched>2023-03-01</fetched>
141
135
  <title type="main" format="text/plain" language="en" script="Latn">International Electrotechnical Vocabulary (IEV) - Part 112: Quantities and units</title>
136
+ <title type="main" format="text/plain" language="fr" script="Latn">Vocabulaire Electrotechnique International (IEV) - Partie 112: Grandeurs et unités</title>
137
+ <title type="main" format="text/plain" language="es" script="Latn">Versión Oficial En español - Vocabulario Electrotécnico Internacional. Parte 112: Magnitudes y unidades.</title>
142
138
  <uri type="src">https://webstore.iec.ch/publication/162</uri>
143
- <uri type="obp">/preview/info_iec60050-112%7Bed1.0%7Db.pdf</uri>
139
+ <uri type="obp">https://webstore.iec.ch/preview/info_iec60050-112{ed1.0}b.pdf</uri>
144
140
  ...
145
141
  <ext schema-version="v1.0.0">
146
142
  <doctype>international-standard</doctype>
@@ -163,8 +159,16 @@ Each IEC document has `src` type link and optional `obp` type link.
163
159
  [source,ruby]
164
160
  ----
165
161
  item.link
166
- => [#<RelatonBib::TypedUri:0x00007ffe9d9b6420 @content=#<Addressable::URI:0x80c URI:https://webstore.iec.ch/publication/162>, @type="src">,
167
- #<RelatonBib::TypedUri:0x00007ffe9d9af080 @content=#<Addressable::URI:0x820 URI:/preview/info_iec60050-112%7Bed1.0%7Db.pdf>, @type="obp">]
162
+ => [#<RelatonBib::TypedUri:0x00007ff1d50e9e20
163
+ @content=#<Addressable::URI:0x2260 URI:https://webstore.iec.ch/publication/162>,
164
+ @language=nil,
165
+ @script=nil,
166
+ @type="src">,
167
+ #<RelatonBib::TypedUri:0x00007ff1d50e9498
168
+ @content=#<Addressable::URI:0x2274 URI:https://webstore.iec.ch/preview/info_iec60050-112{ed1.0}b.pdf>,
169
+ @language=nil,
170
+ @script=nil,
171
+ @type="obp">]
168
172
  ----
169
173
 
170
174
  === Create bibliographic item from Hash
@@ -172,7 +176,8 @@ item.link
172
176
  [source,ruby]
173
177
  ----
174
178
  hash = YAML.load_file "spec/examples/hit.yaml"
175
- => {"id"=>"IEC61058-2-4-1995+AMD1-2003CSV",
179
+ => {"schema-version"=>"v1.2.1",
180
+ "id"=>"IEC61058-2-4-1995+AMD1-2003CSV",
176
181
  ...
177
182
 
178
183
  RelatonIec::IecBibliographicItem.from_hash hash
@@ -233,6 +238,28 @@ RelatonIec.urn_to_code "urn:iec:std:iec:60034-1:1969::csv:en-fr:plus:amd:1:1977:
233
238
  => ["IEC 60034-1:1969+AMD1:1977+AMD2:1979+AMD3:1980 CSV", "en-fr"]
234
239
  ----
235
240
 
241
+ === Fetch data
242
+
243
+ This gem uses the https://bitbucket.org/sdo-hapi/api-specifications/wiki/Guidelines[Harmonized API] as a data source. The following options are available:
244
+ - `iec-harmonized-all` - fetches all the documents using the API
245
+ - `iec-harmonized-latest` - fetches the latest documents using the API
246
+
247
+ The method `RelatonIec::DataFetcher.new(source, output: "data", format: "yaml").fetch` fetches IEC documents from the dataset and saves them to the `./data` folder in YAML format.
248
+ Arguments:
249
+
250
+ - `source` - data source. Possible values: `iec-harmonized-all`, `iec-harmonized-latest` (default `iec-harmonized-latest`).
251
+ - `output` - folder to save documents (default './data').
252
+ - `format` - the format in which the documents are saved. Possible formats are: `yaml`, `xml`, `bibxxml` (default `yaml`).
253
+
254
+ [source,ruby]
255
+ ----
256
+ RelatonIec::DataFetcher.new.fetch
257
+ Started at: 2022-06-23 09:36:55 +0200
258
+ Stopped at: 2022-06-23 09:36:58 +0200
259
+ Done in: 752 sec.
260
+ => nil
261
+ ----
262
+
236
263
  == Development
237
264
 
238
265
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,190 @@
1
+ module RelatonIec
2
+ class DataFetcher
3
+ ENTRYPOINT = "https://api.iec.ch/harmonized/publications?size=100&sortBy=urn&page=".freeze
4
+ CREDENTIAL = "https://api.iec.ch/oauth/client_credential/accesstoken?grant_type=client_credentials".freeze
5
+ LAST_CHANGE_FILE = "last_change.txt".freeze
6
+
7
+ #
8
+ # Initialize new instance.
9
+ #
10
+ # @param [String] source source name (iec-harmonized-all, iec-harmonized-latest)
11
+ # @param [String] output output directory
12
+ # @param [String] format format of output files (xml, bibxml, yaml)
13
+ #
14
+ def initialize(source = "iec-harmonised-latest", output: "data", format: "yaml")
15
+ @output = output
16
+ @format = format
17
+ @ext = format.sub(/^bib/, "")
18
+ @files = []
19
+ # @index = Index.new "index.yaml"
20
+ @last_change = File.read(LAST_CHANGE_FILE, encoding: "UTF-8") if File.exist? LAST_CHANGE_FILE
21
+ @last_change_max = @last_change.to_s
22
+ @all = source == "iec-harmonised-all"
23
+ end
24
+
25
+ def last_change_max(date)
26
+ @last_change_max = date if @last_change_max < date
27
+ end
28
+
29
+ def save_last_change
30
+ return if @last_change_max.empty?
31
+
32
+ File.write LAST_CHANGE_FILE, @last_change_max, encoding: "UTF-8"
33
+ end
34
+
35
+ #
36
+ # Fetch data from IEC.
37
+ #
38
+ def fetch # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
39
+ t1 = Time.now
40
+ puts "Started at: #{t1}"
41
+
42
+ if @all
43
+ FileUtils.rm_rf @output
44
+ end
45
+ FileUtils.mkdir_p @output
46
+ fetch_all
47
+ create_index
48
+ save_last_change
49
+
50
+ t2 = Time.now
51
+ puts "Stopped at: #{t2}"
52
+ puts "Done in: #{(t2 - t1).round} sec."
53
+ rescue StandardError => e
54
+ warn e.message
55
+ warn e.backtrace.join("\n")
56
+ end
57
+
58
+ def create_index
59
+ index = Relaton::Index.find_or_create :IEC, file: "index1.yaml"
60
+ index.remove_all
61
+ Dir["{#{@output},static}/*.yaml"].each do |file|
62
+ item = YAML.load_file file
63
+ id = item["docid"].detect { |i| i["primary"] }["id"]
64
+ index.add_or_update id, file
65
+ end
66
+ index.save
67
+ end
68
+
69
+ #
70
+ # Add static files to index.
71
+ #
72
+ # @return [void]
73
+ #
74
+ # def add_static_files_to_index
75
+ # Dir["static/*.yaml"].each do |file|
76
+ # pub = RelatonBib.parse_yaml File.read(file, encoding: "UTF-8")
77
+ # pubid = RelatonBib.array(pub["docid"]).detect { |id| id["primary"] }["id"]
78
+ # @index.add pubid, file
79
+ # end
80
+ # end
81
+
82
+ #
83
+ # Fetch documents from IEC API.
84
+ #
85
+ # @return [void]
86
+ #
87
+ def fetch_all # rubocop:disable Metrics/MethodLength
88
+ page = 0
89
+ next_page = true
90
+ while next_page
91
+ res = fetch_page_token page
92
+ unless res.code == "200"
93
+ warn "[relaton-iec] #{res.body}"
94
+ break
95
+ end
96
+ json = JSON.parse res.body
97
+ json["publication"].each { |pub| fetch_pub pub }
98
+ page += 1
99
+ next_page = res["link"]&.include? "rel=\"last\""
100
+ end
101
+ end
102
+
103
+ #
104
+ # Fetch page. If response code is 401, then get new access token and try
105
+ #
106
+ # @param [Integer] page page number
107
+ #
108
+ # @return [Net::HTTP::Response] response
109
+ #
110
+ def fetch_page_token(page)
111
+ res = fetch_page page
112
+ if res.code == "401"
113
+ @access_token = nil
114
+ res = fetch_page page
115
+ end
116
+ res
117
+ end
118
+
119
+ #
120
+ # Fetch page from IEC API.
121
+ #
122
+ # @param [Integer] page page number
123
+ #
124
+ # @return [Net::HTTP::Response] response
125
+ #
126
+ def fetch_page(page)
127
+ url = "#{ENTRYPOINT}#{page}"
128
+ if !@all && @last_change
129
+ url += "&lastChangeTimestampFrom=#{@last_change}"
130
+ end
131
+ uri = URI url
132
+ req = Net::HTTP::Get.new uri
133
+ req["Authorization"] = "Bearer #{access_token}"
134
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
135
+ http.request req
136
+ end
137
+ end
138
+
139
+ #
140
+ # Get access token.
141
+ #
142
+ # @return [String] access token
143
+ #
144
+ def access_token # rubocop:disable Metrics/AbcSize
145
+ @access_token ||= begin
146
+ uri = URI CREDENTIAL
147
+ req = Net::HTTP::Get.new uri
148
+ req.basic_auth ENV.fetch("IEC_HAPI_PROJ_PUBS_KEY"), ENV.fetch("IEC_HAPI_PROJ_PUBS_SECRET")
149
+ res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
150
+ http.request req
151
+ end
152
+ JSON.parse(res.body)["access_token"]
153
+ end
154
+ end
155
+
156
+ #
157
+ # Fetch publication and save it to file.
158
+ #
159
+ # @param [Hash] pub publication
160
+ #
161
+ def fetch_pub(pub) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
162
+ bib = DataParser.new(pub).parse
163
+ did = bib.docidentifier.detect &:primary
164
+ file = File.join(@output, "#{did.id.downcase.gsub(/[:\s\/]/, '_')}.#{@ext}")
165
+ if @files.include? file then warn "File #{file} exists."
166
+ else
167
+ @files << file
168
+ # @index.add index_id(pub), file, pub["lastChangeTimestamp"]
169
+ end
170
+ last_change_max pub["lastChangeTimestamp"]
171
+ content = case @format
172
+ when "xml" then bib.to_xml bibdata: true
173
+ when "yaml", "yml" then bib.to_hash.to_yaml
174
+ when "bibxml" then bib.to_bibxml
175
+ end
176
+ File.write file, content, encoding: "UTF-8"
177
+ end
178
+
179
+ def index_id(pub)
180
+ /-(?<part>\d+)/ =~ pub["reference"]
181
+ title = pub.dig("title", 0, "value")
182
+ return pub["reference"] unless part && title
183
+
184
+ ids = title.scan(/(?<=-\sPart\s)#{part[0]}\d+(?=:)/).map do |m|
185
+ pub["reference"].sub(/-#{part}/, "-#{m}")
186
+ end
187
+ ids.size > 1 ? ids : pub["reference"]
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,289 @@
1
+ module RelatonIec
2
+ class DataParser
3
+ DOMAIN = "https://webstore.iec.ch"
4
+
5
+ ATTRS = %i[
6
+ docid structuredidentifier language script title doctype
7
+ ics date contributor editorialgroup abstract copyright link relation
8
+ ].freeze
9
+
10
+ ABBREVS = {
11
+ "ISO" => ["International Organization for Standardization", "www.iso.org"],
12
+ "IEC" => ["International Electrotechnical Commission", "www.iec.ch"],
13
+ "IEEE" => ["Institute of Electrical and Electronics Engineers", "www.ieee.org"],
14
+ "ASTM" => ["American Society of Testing Materials", "www.astm.org"],
15
+ "CISPR" => ["International special committee on radio interference", "www.iec.ch"],
16
+ }.freeze
17
+
18
+ #
19
+ # Initialize new instance.
20
+ #
21
+ # @param [Hash] pub document data
22
+ #
23
+ def initialize(pub)
24
+ @pub = pub
25
+ end
26
+
27
+ #
28
+ # Parse document.
29
+ #
30
+ # @return [RelatonIec::IecBibliographicItem] bib item
31
+ #
32
+ def parse # rubocop:disable Metrics/AbcSize
33
+ args = ATTRS.each_with_object({}) { |a, h| h[a] = send a }
34
+ args[:docstatus] = RelatonBib::DocumentStatus.new stage: @pub["status"]
35
+ args[:edition] = @pub["edition"]
36
+ args[:price_code] = @pub["priceInfo"]["priceCode"]
37
+ args[:place] = ["Geneva"]
38
+ IecBibliographicItem.new(**args)
39
+ end
40
+
41
+ #
42
+ # Parse document identifiers.
43
+ #
44
+ # @return [Array<RelatonBib::DocumentIdentifier>] document identifiers
45
+ #
46
+ def docid
47
+ ids = []
48
+ ids << RelatonBib::DocumentIdentifier.new(id: @pub["reference"], type: "IEC", primary: true)
49
+ urnid = "urn:#{@pub['urnAlt'][0]}"
50
+ ids << RelatonBib::DocumentIdentifier.new(id: urnid, type: "URN")
51
+ end
52
+
53
+ #
54
+ # Parse structured identifier.
55
+ #
56
+ # @return [RelatonIsoBib::StructuredIdentifier] structured identifier
57
+ #
58
+ def structuredidentifier
59
+ m = @pub["reference"].match(
60
+ /(?<=\s)(?<project>\w+)(?:-(?<part>\w*)(?:-(?<subpart>\w*))?)?/,
61
+ )
62
+ RelatonIsoBib::StructuredIdentifier.new(
63
+ project_number: m[:project], part: m[:part], subpart: m[:subpart],
64
+ type: "IEC", id: @pub["reference"]
65
+ )
66
+ end
67
+
68
+ #
69
+ # Parse languages.
70
+ #
71
+ # @return [Array<String>] languages
72
+ #
73
+ def language
74
+ @pub["title"].map { |t| t["lang"] }.uniq
75
+ end
76
+
77
+ #
78
+ # Parse scripts.
79
+ #
80
+ # @return [Array<String>] scripts
81
+ #
82
+ def script
83
+ language.each_with_object([]) do |l, s|
84
+ scr = lang_to_script l
85
+ s << scr if scr && !s.include?(scr)
86
+ end
87
+ end
88
+
89
+ #
90
+ # Detect script.
91
+ #
92
+ # @param [String] lang language
93
+ #
94
+ # @return [String] script
95
+ #
96
+ def lang_to_script(lang)
97
+ case lang
98
+ when "en", "fr", "es" then "Latn"
99
+ end
100
+ end
101
+
102
+ #
103
+ # Parse titles.
104
+ #
105
+ # @return [Array<RelatonBib::TypedTitleString>] titles
106
+ #
107
+ def title
108
+ @pub["title"].map do |t|
109
+ RelatonBib::TypedTitleString.new(
110
+ content: t["value"], language: t["lang"], script: lang_to_script(t["lang"]), type: "main",
111
+ )
112
+ end
113
+ end
114
+
115
+ #
116
+ # Parse editorial group.
117
+ #
118
+ # @return [Hash] editorial group
119
+ #
120
+ def editorialgroup
121
+ return unless @pub["committee"]
122
+
123
+ wg = @pub["committee"]["reference"]
124
+ {
125
+ technical_committee: [{
126
+ name: wg,
127
+ type: "technicalCommittee",
128
+ number: wg.match(/\d+/)&.to_s&.to_i,
129
+ }],
130
+ }
131
+ end
132
+
133
+ #
134
+ # Parse abstract.
135
+ #
136
+ # @return [Array<RelatonBib::FormattedString>] abstract
137
+ #
138
+ def abstract
139
+ @pub["abstract"]&.map do |a|
140
+ RelatonBib::FormattedString.new(
141
+ content: a["content"], language: a["lang"], script: lang_to_script(a["lang"]),
142
+ format: a["format"]
143
+ )
144
+ end
145
+ end
146
+
147
+ # @return [Array<Hash>]
148
+ def copyright # rubocop:disable Metrics/AbcSize
149
+ from = @pub["reference"].match(/(?<=:)\d{4}/).to_s
150
+ from = @pub["releaseDate"]&.match(/\d{4}/).to_s if from.empty?
151
+ return [] if from.nil? || from.empty?
152
+
153
+ abbreviation = @pub["reference"].match(/.*?(?=\s)/).to_s
154
+ owner = abbreviation.split("/").map do |abbrev|
155
+ name, url = ABBREVS[abbrev]
156
+ { name: name, abbreviation: abbrev, url: url }
157
+ end
158
+ [{ owner: owner, from: from }]
159
+ end
160
+
161
+ #
162
+ # Fetche ics.
163
+ #
164
+ # @return [Array<RelatonIsoBib::Ics>] ics
165
+ #
166
+ def ics
167
+ return [] unless @pub["classifications"]
168
+
169
+ @pub["classifications"].select { |c| c["type"] == "ICS" }.map do |c|
170
+ RelatonIsoBib::Ics.new(c["value"])
171
+ end
172
+ end
173
+
174
+ #
175
+ # Parse dates.
176
+ #
177
+ # @return [Array<RelatonBib::BibliographicDate>] dates
178
+ #
179
+ def date
180
+ {
181
+ "published" => "publicationDate",
182
+ "stable-until" => "stabilityDate",
183
+ "confirmed" => "confirmationDate",
184
+ "obsoleted" => "dateOfWithdrawal",
185
+ }.reduce([]) do |a, (k, v)|
186
+ next a unless @pub[v]
187
+
188
+ a << RelatonBib::BibliographicDate.new(type: k, on: @pub[v])
189
+ end
190
+ end
191
+
192
+ #
193
+ # Parse contributors.
194
+ #
195
+ # @return [Array<Hash>] contributors
196
+ #
197
+ def contributor
198
+ @pub["reference"].sub(/\s.*/, "").split("/").map do |abbrev|
199
+ name, url = ABBREVS[abbrev]
200
+ { entity: { name: name, url: url, abbreviation: abbrev },
201
+ role: [type: "publisher"] }
202
+ end
203
+ end
204
+
205
+ #
206
+ # Parse links.
207
+ #
208
+ # @return [Array<RelatonBib::TypedUri>] links
209
+ #
210
+ def link
211
+ url = "#{DOMAIN}/publication/#{urn_id}"
212
+ l = [RelatonBib::TypedUri.new(content: url, type: "src")]
213
+ RelatonBib.array(@pub["releaseItems"]).each_with_object(l) do |r, a|
214
+ next unless r["type"] == "PREVIEW"
215
+
216
+ url = "#{DOMAIN}/preview/#{r['contentRef']['fileName']}"
217
+ a << RelatonBib::TypedUri.new(content: url, type: "obp")
218
+ end
219
+ end
220
+
221
+ #
222
+ # Extract URN ID from URN.
223
+ #
224
+ # @return [String] URN ID
225
+ #
226
+ def urn_id
227
+ @pub["urn"].split(":").last
228
+ end
229
+
230
+ #
231
+ # Parse document type.
232
+ #
233
+ # @return [String] document type
234
+ #
235
+ def doctype
236
+ case @pub["stdType"]
237
+ when "IS" then "international-standard"
238
+ when "TR" then "technical-report"
239
+ when "TS" then "technical-specification"
240
+ when "PAS" then "publicly-available-specification"
241
+ when "SRD" then "system-reference-delivrabble"
242
+ else @pub["stdType"].downcase
243
+ end
244
+ end
245
+
246
+ #
247
+ # Parse relation.
248
+ #
249
+ # @return [Array<RelatonBib::DocumentRelation>] relation
250
+ #
251
+ def relation # rubocop:disable Metrics/MethodLength
252
+ try = 0
253
+ begin
254
+ uri = URI "#{DOMAIN}/webstore/webstore.nsf/AjaxRequestXML?" \
255
+ "Openagent&url=#{urn_id}"
256
+ resp = Net::HTTP.get_response uri
257
+ doc = Nokogiri::XML resp.body
258
+ create_relations doc
259
+ rescue StandardError => e
260
+ try += 1
261
+ try < 3 ? retry : raise(e)
262
+ end
263
+ end
264
+
265
+ #
266
+ # Create relations.
267
+ #
268
+ # @param [Nokogiri::XML::Document] doc XML document
269
+ #
270
+ # @return [Array<Hash>] relations
271
+ #
272
+ def create_relations(doc) # rubocop:disable Metrics/MethodLength
273
+ doc.xpath('//ROW[STATUS[.!="PREPARING" and .!="PUBLISHED"]]')
274
+ .map do |r|
275
+ r_type = r.at("STATUS").text.downcase
276
+ type = case r_type
277
+ when "revised", "replaced" then "updates"
278
+ when "withdrawn" then "obsoletes"
279
+ else r_type
280
+ end
281
+ ref = r.at("FULL_NAME").text
282
+ fref = RelatonBib::FormattedRef.new content: ref, format: "text/plain"
283
+ docid = RelatonBib::DocumentIdentifier.new(id: ref, type: "IEC", primary: true)
284
+ bibitem = IecBibliographicItem.new(formattedref: fref, docid: [docid])
285
+ RelatonBib::DocumentRelation.new type: type, bibitem: bibitem
286
+ end
287
+ end
288
+ end
289
+ end
@@ -3,16 +3,32 @@
3
3
  module RelatonIec
4
4
  # Hit.
5
5
  class Hit < RelatonBib::Hit
6
+ GHURL = "https://raw.githubusercontent.com/relaton/relaton-data-iec/main/"
7
+
6
8
  attr_writer :fetch
7
9
 
8
10
  # Parse page.
9
11
  # @return [RelatonIec::IecBibliographicItem]
10
12
  def fetch
11
- @fetch ||= Scrapper.parse_page @hit
13
+ @fetch ||= begin
14
+ url = "#{GHURL}#{hit[:file]}"
15
+ resp = Net::HTTP.get URI(url)
16
+ hash = YAML.safe_load resp
17
+ hash["fetched"] = Date.today.to_s
18
+ IecBibliographicItem.from_hash hash
19
+ end
12
20
  end
13
21
 
14
22
  def part
15
23
  @part ||= hit[:code].match(/(?<=-)[\w-]+/)&.to_s
16
24
  end
25
+
26
+ def inspect
27
+ "<#{self.class}:#{format('%<id>#.14x', id: object_id << 1)} " \
28
+ "@text=\"#{@hit_collection&.text}\" " \
29
+ "@fetched=\"#{!@fetch.nil?}\" " \
30
+ "@fullIdentifier=\"#{@fetch&.shortref(nil, no_year: true)}\" " \
31
+ "@title=\"#{@hit[:code]}\">"
32
+ end
17
33
  end
18
34
  end