relaton 1.7.3 → 1.7.4

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/docs/README.adoc +141 -2
  3. data/lib/relaton.rb +8 -7
  4. data/lib/relaton/config.rb +2 -1
  5. data/lib/relaton/db.rb +193 -48
  6. data/lib/relaton/db_cache.rb +19 -3
  7. data/lib/relaton/processor.rb +11 -0
  8. data/lib/relaton/version.rb +1 -1
  9. data/lib/relaton/workers_pool.rb +23 -0
  10. data/spec/relaton/db_spec.rb +122 -0
  11. data/spec/relaton/processor_spec.rb +4 -0
  12. data/spec/relaton_spec.rb +10 -15
  13. data/spec/vcr_cassetes/19133_2005.yml +16 -16
  14. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +8 -8
  15. data/spec/vcr_cassetes/ecma_6.yml +8 -6
  16. data/spec/vcr_cassetes/fisp_140.yml +4 -4
  17. data/spec/vcr_cassetes/gb_t_20223_2006.yml +9 -9
  18. data/spec/vcr_cassetes/iec_60050_102_2007.yml +23 -23
  19. data/spec/vcr_cassetes/iec_combined_included.yml +73 -73
  20. data/spec/vcr_cassetes/ieee_528_2019.yml +17 -17
  21. data/spec/vcr_cassetes/iho_b_11.yml +11 -11
  22. data/spec/vcr_cassetes/iso_111111119115_1.yml +4 -4
  23. data/spec/vcr_cassetes/iso_19115.yml +18 -18
  24. data/spec/vcr_cassetes/iso_19115_1.yml +18 -18
  25. data/spec/vcr_cassetes/iso_19115_1_2.yml +32 -32
  26. data/spec/vcr_cassetes/iso_awi_24229.yml +17 -17
  27. data/spec/vcr_cassetes/iso_combined_applied.yml +36 -36
  28. data/spec/vcr_cassetes/iso_combined_included.yml +35 -35
  29. data/spec/vcr_cassetes/itu_combined_included.yml +63 -63
  30. data/spec/vcr_cassetes/ogc_19_025r1.yml +1218 -1122
  31. data/spec/vcr_cassetes/ogm_ami4ccm_1_0.yml +7 -7
  32. data/spec/vcr_cassetes/rfc_8341.yml +47 -15
  33. data/spec/vcr_cassetes/rfc_unsuccess.yml +70 -0
  34. data/spec/vcr_cassetes/sp_800_38b.yml +4 -4
  35. data/spec/vcr_cassetes/un_rtade_cefact_2004_32.yml +31 -29
  36. data/spec/vcr_cassetes/w3c_json_ld11.yml +12 -12
  37. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f957d5a962fa3529fb21f4289ff4dc648029497ec3bf209e084b85c49a336531
4
- data.tar.gz: 6e6ad879c1552c8396c8f365c4bdc9c088197424f695b68b0dbeec9cc272f1a4
3
+ metadata.gz: e745abe47353b4f9a1d6e0621121590fa64ba8083898683d735a4e3f2ee965d2
4
+ data.tar.gz: 100fde35c4b874028be98f497eb1f0ad77b400b1fdc13200e0ccc4b1d971217b
5
5
  SHA512:
6
- metadata.gz: f87f3d11aae3e805fa2fe3d9875692c2004a7b7a51fc1235181f8a4a9b314cf0403e50a4134fb093edc0da2cdb42339a7fe4ee7024e25de92d7923bf5029ab35
7
- data.tar.gz: 2684a909260936e26f9a2b987c667e61d24e96c01f326bc008deaf9358f1dc349f216c239932ee5780325057bfb192426173d1e226c031880743ff4ce0ad4d12
6
+ metadata.gz: 5f50ab12ccc315db33c26a5040d9062fb2be2028f66371bd31cdb19724ed26827bae2453e3509536171f5a2ebd0aa4fd745164593d38bdfa2749007a4d56036f
7
+ data.tar.gz: 10c6d44de29e572ca8683d314da6259e5209ad339e131105bb56d79024df5225de5e7895cefab39be2c4863688e68da42f29ab606b9750e53171152f5148f678
data/docs/README.adoc CHANGED
@@ -64,6 +64,11 @@ e.g. `get("ISO 19115-1", "2014", all_parts: true)` is transformed into a referen
64
64
 
65
65
  === Create DB
66
66
 
67
+ `Relaton::Db#new(globalcache, localcache)` creates new DB. Returns Relaton::Db instance.
68
+
69
+ * `globalcache` - (String or nil) path to globalcache directory
70
+ * `localcache` - (String or nil) path to localcache directory
71
+
67
72
  [source,ruby]
68
73
  ----
69
74
  require "relaton"
@@ -97,9 +102,42 @@ db = Relaton::Db.new("globalcache", "localcache")
97
102
  ...
98
103
  ----
99
104
 
105
+ === Modify DB
106
+
107
+ ==== Move DB
108
+
109
+ `Relaton::Db#mv(new_globalcache_dir, new_localcahe_dir)` moves DB directories to new location.
110
+
111
+ * `new_globalcahe_dir` - (String or nil) new globalcache location
112
+ * `new_localcahe_dir` - (String or nil) new localcache location
113
+
114
+ [source,ruby]
115
+ ----
116
+ db.mv("new_globalcache_dir", "new_localcahe_dir")
117
+ ----
118
+
119
+ ==== Clear DB
120
+
121
+ `Relaton::Db#clear` removes all entries form DB
122
+
100
123
  === Fetch documens
101
124
 
102
- ==== Fetch by references
125
+ ==== Fetch document by references
126
+
127
+ There are 3 fetching methods:
128
+
129
+ * `Relaton::Db#fetch(reference, year, options)` - fetches document from local cache or remote source.
130
+ * `Relaton::Db#fetch_db(reference, year, options)` - fetches document from local cache
131
+ * `Relaton::Db#fetch_async(reference, year, options, &block)` - fetches document asynchronously
132
+
133
+ Arguments:
134
+
135
+ * `reference` - (String) reference to fethc document
136
+ * `year` - (String or nil) year to filter relult (optional)
137
+ * `options` - (Hash) hash of options. Alloved options:
138
+ - `:all_parts` - (Boolean) should be `true` if all-parts reference is required
139
+ - `:keep_yer` - (Boolean) should be `true` if undated reference should return actual reference with year
140
+ - `:retries` - (Number) number of network retries. Default 1
103
141
 
104
142
  [source,ruby]
105
143
  ----
@@ -114,7 +152,7 @@ x = db.fetch("ISO 19011")
114
152
  => #<RelatonIsoBib::IsoBibliographicItem:0x007fb1d0ab2f00
115
153
  ...
116
154
 
117
- x = db.fetch("ISO 19011", "2011")
155
+ x = db.fetch("ISO 19011", "2011", retries: 3)
118
156
  [relaton-iso] ("ISO 19011") fetching...
119
157
  [relaton-iso] ("ISO 19011") found ISO 19011:2011
120
158
  => #<RelatonIsoBib::IsoBibliographicItem:0x007fb1d2593068
@@ -125,6 +163,31 @@ x = db.fetch("ISO 19115", nil, all_parts: true)
125
163
  [relaton-iso] ("ISO 19115") found ISO 19115 (all parts)
126
164
  => #<RelatonIsoBib::IsoBibliographicItem:0x007fb1d0ae8bf0
127
165
  ...
166
+
167
+ # Fetchig from local cache
168
+
169
+ x = db.fetch("ISO 19011")
170
+ => #<RelatonIsoBib::IsoBibliographicItem:0x007fde5f48a9f0
171
+ ...
172
+
173
+ x = db.fetch_db("ISO 5749")
174
+ => nil
175
+
176
+ # Fetching asynchronously
177
+
178
+ # prepare queue for results
179
+ results = Queue.new
180
+
181
+ # fetch document
182
+ db.fetch_async("ISO 19115") do |result|
183
+ results << { "ISO 19115" => result }
184
+ end
185
+ # fetch other documets the same way
186
+
187
+ # wait until documets fetching
188
+ while x = results.pop
189
+ # do thatever you need with result x
190
+ end
128
191
  ----
129
192
 
130
193
  ==== Fetch by URN
@@ -192,6 +255,82 @@ bib.relation[1].bibitem.docidentifier[0].id
192
255
  [source,ruby]
193
256
  ----
194
257
  bib = db.fetch "ISO 19115-1, Amd 1"
258
+ => ["Chinese Standard", "GB/T 1.1"]
259
+ [relaton-iso] ("ISO 19115-1") fetching...
260
+ [relaton-iso] ("ISO 19115-1") found ISO 19115-1:2014
261
+ [relaton-iso] ("ISO 19115-1/Amd 1") fetching...
262
+ [relaton-iso] ("ISO 19115-1/Amd 1") found ISO 19115-1:2014/Amd 1:2018
263
+ => #<RelatonIsoBib::IsoBibliographicItem:0x007fb09b36d1b8
264
+ ...
265
+ ----
266
+
267
+ ==== Fetch all documents from cache
268
+
269
+ `Relaton::Db#fetch_all(text = nil, edition: nil, year: nil)` - fetches all document from local cache
270
+
271
+ * `text` - (String) filter entries by a text (optional)
272
+ * `edition` - (String) filter entries by an edition (optional)
273
+ * `year` - (Integer) filter entries by a year (optional)
274
+
275
+ [source,ruby]
276
+ ----
277
+ # query for all entries in a cahche
278
+
279
+ items = db.fetch_all
280
+ => [#<RelatonIec::IecBibliographicItem:0x007facda8fdc28
281
+ ...
282
+
283
+ items.size
284
+ => 6
285
+
286
+ # query for all entries in a cahche for a certain string
287
+
288
+ items = db.fetch_all("mathematical terminology")
289
+ => [#<RelatonIec::IecBibliographicItem:0x007ffeae5bd240
290
+ ...
291
+
292
+ items.size
293
+ => 1
294
+
295
+ items[0].docidentifier[0].id
296
+ => "IEC 60050-102:2007"
297
+
298
+ # query for all entries in a cahche for a certain string and edition
299
+
300
+ items = db.fetch_all("system", edition: "2")
301
+ => [#<RelatonIsoBib::IsoBibliographicItem:0x007ffebe2d1be8
302
+ ...
303
+
304
+ items.size
305
+ => 1
306
+
307
+ items[0].docidentifier[0].id
308
+ => "ISO 19011:2011"
309
+
310
+ # query for all entries in a cahche for a certain string and year
311
+
312
+ items = db.fetch_all("system", year: 2018)
313
+ => [#<RelatonIsoBib::IsoBibliographicItem:0x007ffeae645fa0
314
+ ...
315
+
316
+ items.size
317
+ => 1
318
+
319
+ items[0].docidentifier[0].id
320
+ => "ISO 19011 (all parts)"
321
+ ----
322
+
323
+ === Static DB
324
+
325
+ This gem has a static DB which is distributed with it. Now the static contains documents:
326
+ ----
327
+ ISO/IEC DIR 1 IEC SUP
328
+ ISO/IEC DIR 1 ISO SUP
329
+ ISO/IEC DIR 1
330
+ ISO/IEC DIR 2 IEC
331
+ ISO/IEC DIR 2 ISO
332
+ ISO/IEC DIR IEC SUP
333
+ ISO/IEC DIR 1 ISO SUP
195
334
  ----
196
335
 
197
336
  === Get document type
data/lib/relaton.rb CHANGED
@@ -1,8 +1,9 @@
1
- require_relative "relaton/util"
2
- require_relative "relaton/config"
1
+ require "relaton/util"
2
+ require "relaton/config"
3
3
 
4
- require_relative "relaton/db"
5
- require_relative "relaton/db_cache"
6
- require_relative "relaton/version"
7
- require_relative "relaton/registry"
8
- require_relative "relaton/processor"
4
+ require "relaton/workers_pool"
5
+ require "relaton/db"
6
+ require "relaton/db_cache"
7
+ require "relaton/version"
8
+ require "relaton/registry"
9
+ require "relaton/processor"
@@ -12,10 +12,11 @@ module Relaton
12
12
  end
13
13
 
14
14
  class Configuration
15
- attr_accessor :logs
15
+ attr_accessor :logs, :use_api
16
16
 
17
17
  def initialize
18
18
  @logs = %i(warning error)
19
+ @use_api = false # @TODO change to true when we start using api.relaton.org
19
20
  end
20
21
  end
21
22
 
data/lib/relaton/db.rb CHANGED
@@ -12,17 +12,36 @@ module Relaton
12
12
  @registry = Relaton::Registry.instance
13
13
  @db = open_cache_biblio(global_cache, type: :global)
14
14
  @local_db = open_cache_biblio(local_cache, type: :local)
15
- @db_name = global_cache
16
- @local_db_name = local_cache
17
- static_db_name = File.expand_path "../relaton/static_cache", __dir__
18
- @static_db = open_cache_biblio static_db_name
15
+ @static_db = open_cache_biblio File.expand_path("../relaton/static_cache", __dir__)
16
+ @queues = {}
19
17
  end
20
18
 
19
+ # Move global and/or local caches to anothe dirs
20
+ # @param new_global_dir [String, nil]
21
+ # @param new_local_dir [String, nil]
22
+ def mv(new_global_dir, new_local_dir)
23
+ @db.mv new_global_dir
24
+ @local_db.mv new_local_dir
25
+ end
26
+
27
+ # Clear global and local databases
28
+ def clear
29
+ @db.clear
30
+ @local_db.clear
31
+ end
32
+
33
+ ##
21
34
  # The class of reference requested is determined by the prefix of the code:
22
35
  # GB Standard for gbbib, IETF for ietfbib, ISO for isobib, IEC or IEV for iecbib,
36
+ #
23
37
  # @param code [String] the ISO standard Code to look up (e.g. "ISO 9000")
24
38
  # @param year [String] the year the standard was published (optional)
25
- # @param opts [Hash] options; restricted to :all_parts if all-parts reference is required
39
+ #
40
+ # @param opts [Hash] options
41
+ # @option opts [Boolean] :all_parts If all-parts reference is required
42
+ # @option opts [Boolean] :keep_year If undated reference should return actual reference with year
43
+ # @option opts [Integer] :retries (1) Number of network retries
44
+ #
26
45
  # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
27
46
  # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
28
47
  # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
@@ -31,54 +50,59 @@ module Relaton
31
50
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
32
51
  # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
33
52
  # RelatonW3c::W3cBibliographicItem
53
+ ##
34
54
  def fetch(code, year = nil, opts = {})
35
55
  stdclass = standard_class(code) || return
36
56
  processor = @registry.processors[stdclass]
37
57
  ref = processor.respond_to?(:urn_to_code) ? processor.urn_to_code(code)&.first : code
38
58
  ref ||= code
39
- cd = combine_doc ref, year, opts, stdclass
40
- return cd if cd
59
+ result = combine_doc ref, year, opts, stdclass
60
+ result ||= check_bibliocache(ref, year, opts, stdclass)
61
+ result
62
+ end
41
63
 
42
- check_bibliocache(ref, year, opts, stdclass)
64
+ # @see Relaton::Db#fetch
65
+ def fetch_db(code, year = nil, opts = {})
66
+ opts[:fetch_db] = true
67
+ fetch code, year, opts
43
68
  end
44
69
 
45
- # @param code [String]
46
- # @param year [String, nil]
47
- # @param stdslass [String]
48
- # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
49
- # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
50
- # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
51
- # RelatonNist::NistBibliongraphicItem, RelatonGb::GbbibliographicItem,
52
- # RelatonOgc::OgcBibliographicItem, RelatonCalconnect::CcBibliographicItem]
53
- # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
54
- # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
55
- # RelatonW3c::W3cBibliographicItem
56
- def combine_doc(code, year, opts, stdclass) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
57
- if (refs = code.split " + ").size > 1
58
- reltype = "derivedFrom"
59
- reldesc = nil
60
- elsif (refs = code.split ", ").size > 1
61
- reltype = "complements"
62
- reldesc = RelatonBib::FormattedString.new content: "amendment"
63
- else return
64
- end
70
+ # fetch all standards from DB
71
+ # @param test [String, nil]
72
+ # @param edition [String], nil
73
+ # @param year [Integer, nil]
74
+ # @return [Array]
75
+ def fetch_all(text = nil, edition: nil, year: nil)
76
+ result = @static_db.all { |file, yml| search_yml file, yml, text, edition, year }.compact
77
+ db = @db || @local_db
78
+ result += db.all { |file, xml| search_xml file, xml, text, edition, year }.compact if db
79
+ result
80
+ end
65
81
 
66
- doc = @registry.processors[stdclass].hash_to_bib docid: { id: code }
67
- ref = refs[0]
68
- updates = check_bibliocache(ref, year, opts, stdclass)
69
- doc.relation << RelatonBib::DocumentRelation.new(bibitem: updates, type: "updates") if updates
70
- refs[1..-1].each_with_object(doc) do |c, d|
71
- bib = check_bibliocache("#{ref}/#{c}", year, opts, stdclass)
72
- if bib
73
- d.relation << RelatonBib::DocumentRelation.new(type: reltype, description: reldesc, bibitem: bib)
82
+ # Fetch asynchronously
83
+ def fetch_async(code, year = nil, opts = {}, &_block) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
84
+ stdclass = standard_class code
85
+ if stdclass
86
+ unless @queues[stdclass]
87
+ processor = @registry.processors[stdclass]
88
+ wp = WorkersPool.new(processor.threads) { |args| yield fetch *args }
89
+ @queues[stdclass] = { queue: Queue.new, workers_pool: wp }
90
+ Thread.new { process_queue @queues[stdclass] }
74
91
  end
92
+ @queues[stdclass][:queue] << [code, year, opts]
93
+ else yield nil
75
94
  end
76
95
  end
77
96
 
78
97
  # @param code [String]
79
98
  # @param year [String, NilClass]
80
99
  # @param stdclass [Symbol, NilClass]
100
+ #
81
101
  # @param opts [Hash]
102
+ # @option opts [Boolean] :all_parts If all-parts reference is required
103
+ # @option opts [Boolean] :keep_year If undated reference should return actual reference with year
104
+ # @option opts [Integer] :retries (1) Number of network retries
105
+ #
82
106
  # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
83
107
  # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
84
108
  # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
@@ -137,6 +161,89 @@ module Relaton
137
161
 
138
162
  private
139
163
 
164
+ # @param file [String] file path
165
+ # @param yml [String] content in YAML format
166
+ # @param text [String, nil] text to serach
167
+ # @param edition [String, nil] edition to filter
168
+ # @param year [Integer, nil] year to filter
169
+ # @return [BibliographicItem, nil]
170
+ def search_yml(file, yml, text, edition, year)
171
+ item = search_edition_year(file, yml, edition, year)
172
+ return unless item
173
+
174
+ item if match_xml_text(item.to_xml(bibdata: true), text)
175
+ end
176
+
177
+ # @param file [String] file path
178
+ # @param xml [String] content in XML format
179
+ # @param text [String, nil] text to serach
180
+ # @param edition [String, nil] edition to filter
181
+ # @param year [Integer, nil] year to filter
182
+ # @return [BibliographicItem, nil]
183
+ def search_xml(file, xml, text, edition, year)
184
+ return unless text.nil? || match_xml_text(xml, text)
185
+
186
+ search_edition_year(file, xml, edition, year)
187
+ end
188
+
189
+ # @param file [String] file path
190
+ # @param content [String] content in XML or YAmL format
191
+ # @param edition [String, nil] edition to filter
192
+ # @param year [Integer, nil] year to filter
193
+ # @return [BibliographicItem, nil]
194
+ def search_edition_year(file, content, edition, year) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
195
+ processor = @registry.processors[standard_class(file.split("/")[-2])]
196
+ item = file.match?(/xml$/) ? processor.from_xml(content) : processor.hash_to_bib(YAML.safe_load(content))
197
+ item if (edition.nil? || item.edition == edition) &&
198
+ (year.nil? || item.date.detect { |d| d.type == "published" && d.on(:year) == year })
199
+ end
200
+
201
+ # @param xml [String] content in XML format
202
+ # @param text [String, nil] text to serach
203
+ # @return [Boolean]
204
+ def match_xml_text(xml, text)
205
+ %r{((?<attr>=((?<apstr>')|"))|>).*?#{text}.*?(?(<attr>)(?(<apstr>)'|")|<)}mi.match?(xml)
206
+ end
207
+
208
+ # @param code [String]
209
+ # @param year [String, nil]
210
+ # @param stdslass [String]
211
+ #
212
+ # @param opts [Hash] options
213
+ # @option opts [Boolean] :all_parts If all-parts reference is required
214
+ # @option opts [Boolean] :keep_year If undated reference should return actual reference with year
215
+ # @option opts [Integer] :retries (1) Number of network retries
216
+ #
217
+ # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
218
+ # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
219
+ # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
220
+ # RelatonNist::NistBibliongraphicItem, RelatonGb::GbbibliographicItem,
221
+ # RelatonOgc::OgcBibliographicItem, RelatonCalconnect::CcBibliographicItem]
222
+ # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
223
+ # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
224
+ # RelatonW3c::W3cBibliographicItem
225
+ def combine_doc(code, year, opts, stdclass) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
226
+ if (refs = code.split " + ").size > 1
227
+ reltype = "derivedFrom"
228
+ reldesc = nil
229
+ elsif (refs = code.split ", ").size > 1
230
+ reltype = "complements"
231
+ reldesc = RelatonBib::FormattedString.new content: "amendment"
232
+ else return
233
+ end
234
+
235
+ doc = @registry.processors[stdclass].hash_to_bib docid: { id: code }
236
+ ref = refs[0]
237
+ updates = check_bibliocache(ref, year, opts, stdclass)
238
+ doc.relation << RelatonBib::DocumentRelation.new(bibitem: updates, type: "updates") if updates
239
+ refs[1..-1].each_with_object(doc) do |c, d|
240
+ bib = check_bibliocache("#{ref}/#{c}", year, opts, stdclass)
241
+ if bib
242
+ d.relation << RelatonBib::DocumentRelation.new(type: reltype, description: reldesc, bibitem: bib)
243
+ end
244
+ end
245
+ end
246
+
140
247
  # @param code [String] code of standard
141
248
  # @return [Symbol] standard class name
142
249
  def standard_class(code)
@@ -157,7 +264,12 @@ module Relaton
157
264
  # Fofmat ID
158
265
  # @param code [String]
159
266
  # @param year [String]
267
+ #
160
268
  # @param opts [Hash]
269
+ # @option opts [Boolean] :all_parts If all-parts reference is required
270
+ # @option opts [Boolean] :keep_year If undated reference should return actual reference with year
271
+ # @option opts [Integer] :retries (1) Number of network retries
272
+ #
161
273
  # @param stdClass [Symbol]
162
274
  # @return [Array<String>] docid and code
163
275
  def std_id(code, year, opts, stdclass)
@@ -180,7 +292,6 @@ module Relaton
180
292
 
181
293
  # @param entry [String] XML string
182
294
  # @param stdclass [Symbol]
183
- # @param id [String] docid
184
295
  # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
185
296
  # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
186
297
  # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
@@ -189,13 +300,18 @@ module Relaton
189
300
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
190
301
  # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
191
302
  # RelatonW3c::W3cBibliographicItem
192
- def bib_retval(entry, stdclass, _id)
193
- entry.match?(/^not_found/) ? nil : @registry.processors[stdclass].from_xml(entry)
303
+ def bib_retval(entry, stdclass)
304
+ entry.nil? || entry.match?(/^not_found/) ? nil : @registry.processors[stdclass].from_xml(entry)
194
305
  end
195
306
 
196
307
  # @param code [String]
197
308
  # @param year [String]
309
+ #
198
310
  # @param opts [Hash]
311
+ # @option opts [Boolean] :all_parts If all-parts reference is required
312
+ # @option opts [Boolean] :keep_year If undated reference should return actual reference with year
313
+ # @option opts [Integer] :retries (1) Number of network retries
314
+ #
199
315
  # @param stdclass [Symbol]
200
316
  # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
201
317
  # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
@@ -213,31 +329,41 @@ module Relaton
213
329
  db = @local_db || @db
214
330
  altdb = @local_db && @db ? @db : nil
215
331
  if db.nil?
332
+ return if opts[:fetch_db]
333
+
216
334
  bibentry = new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
217
- return bib_retval(bibentry, stdclass, id)
335
+ return bib_retval(bibentry, stdclass)
218
336
  end
219
337
 
220
338
  db.delete(id) unless db.valid_entry?(id, year)
221
339
  if altdb
222
- # db[id] ||= altdb[id]
223
- db.clone_entry id, altdb
340
+ return bib_retval(altdb[id], stdclass) if opts[:fetch_db]
341
+
342
+ db.clone_entry id, altdb if altdb.valid_entry? id, year
224
343
  db[id] ||= new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
225
344
  altdb.clone_entry(id, db) if !altdb.valid_entry?(id, year)
226
345
  else
346
+ return bib_retval(db[id], stdclass) if opts[:fetch_db]
347
+
227
348
  db[id] ||= new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
228
349
  end
229
- bib_retval(db[id], stdclass, id)
350
+ bib_retval(db[id], stdclass)
230
351
  end
231
352
 
232
353
  # @param code [String]
233
354
  # @param year [String]
355
+ #
234
356
  # @param opts [Hash]
357
+ # @option opts [Boolean] :all_parts If all-parts reference is required
358
+ # @option opts [Boolean] :keep_year If undated reference should return actual reference with year
359
+ # @option opts [Integer] :retries (1) Number of network retries
360
+ #
235
361
  # @param stdclass [Symbol]
236
362
  # @param db [Relaton::DbCache,`NilClass]
237
363
  # @param id [String] docid
238
364
  # @return [String]
239
365
  def new_bib_entry(code, year, opts, stdclass, **args) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
240
- bib = @registry.processors[stdclass].get(code, year, opts)
366
+ bib = net_retry(code, year, opts, stdclass, opts.fetch(:retries, 1))
241
367
  bib_id = bib&.docidentifier&.first&.id
242
368
 
243
369
  # when docid doesn't match bib's id then return a reference to bib's id
@@ -245,11 +371,19 @@ module Relaton
245
371
  bid = std_id(bib.docidentifier.first.id, nil, {}, stdclass).first
246
372
  args[:db][bid] ||= bib_entry bib
247
373
  "redirection #{bid}"
248
- else
249
- bib_entry bib
374
+ else bib_entry bib
250
375
  end
251
376
  end
252
377
 
378
+ # @raise [RelatonBib::RequestError]
379
+ def net_retry(code, year, opts, stdclass, retries)
380
+ @registry.processors[stdclass].get(code, year, opts)
381
+ rescue RelatonBib::RequestError => e
382
+ raise e unless retries > 1
383
+
384
+ net_retry(code, year, opts, stdclass, retries - 1)
385
+ end
386
+
253
387
  # @param bib [RelatonGb::GbBibliongraphicItem, RelatonIsoBib::IsoBibliographicItem,
254
388
  # RelatonIetf::IetfBibliographicItem, RelatonItu::ItuBibliographicItem,
255
389
  # RelatonNist::NistBibliongraphicItem, RelatonOgc::OgcBibliographicItem]
@@ -262,21 +396,32 @@ module Relaton
262
396
  end
263
397
  end
264
398
 
265
- # @param dir [String] DB directory
399
+ # @param dir [String, nil] DB directory
266
400
  # @param type [Symbol]
267
401
  # @return [Relaton::DbCache, NilClass]
268
402
  def open_cache_biblio(dir, type: :static)
269
403
  return nil if dir.nil?
270
404
 
271
405
  db = DbCache.new dir, type == :static ? "yml" : "xml"
406
+ return db if type == :static
272
407
 
273
408
  Dir["#{dir}/*/"].each do |fdir|
274
- next if type == :static || db.check_version?(fdir)
409
+ next if db.check_version?(fdir)
275
410
 
276
411
  FileUtils.rm_rf(Dir.glob(fdir + "/*"), secure: true)
412
+ db.set_version fdir
277
413
  warn "[relaton] cache #{fdir}: version is obsolete and cache is cleared."
278
414
  end
279
415
  db
280
416
  end
417
+
418
+ # @param qwp [Hash]
419
+ # @option qwp [Queue] :queue The queue of references to fetch
420
+ # @option qwp [Relaton::WorkersPool] :workers_pool The pool of workers
421
+ def process_queue(qwp)
422
+ while args = qwp[:queue].pop
423
+ qwp[:workers_pool] << args
424
+ end
425
+ end
281
426
  end
282
427
  end