relaton 1.7.6 → 1.8.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.rubocop.yml +1 -1
  4. data/docs/README.adoc +20 -11
  5. data/lib/relaton.rb +1 -0
  6. data/lib/relaton/config.rb +7 -3
  7. data/lib/relaton/db.rb +213 -101
  8. data/lib/relaton/db_cache.rb +44 -125
  9. data/lib/relaton/registry.rb +3 -2
  10. data/lib/relaton/storage.rb +186 -0
  11. data/lib/relaton/util.rb +3 -1
  12. data/lib/relaton/version.rb +1 -1
  13. data/lib/relaton/workers_pool.rb +1 -3
  14. data/relaton.gemspec +24 -19
  15. data/spec/relaton/config_spec.rb +1 -1
  16. data/spec/relaton/db_cache_spec.rb +2 -2
  17. data/spec/relaton/db_spec.rb +65 -16
  18. data/spec/relaton/regirtry_spec.rb +10 -2
  19. data/spec/relaton/storage_spec.rb +130 -0
  20. data/spec/relaton_spec.rb +61 -13
  21. data/spec/spec_helper.rb +4 -0
  22. data/spec/vcr_cassetes/19133_2005.yml +22 -22
  23. data/spec/vcr_cassetes/api_relaton_org.yml +51 -0
  24. data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +182 -0
  25. data/spec/vcr_cassetes/async_fetch.yml +4854 -0
  26. data/spec/vcr_cassetes/bsi_bs_en_iso_8848.yml +159 -0
  27. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +12 -12
  28. data/spec/vcr_cassetes/cen_en_10160_1999.yml +249 -0
  29. data/spec/vcr_cassetes/cie_001_1980.yml +7 -7
  30. data/spec/vcr_cassetes/ecma_6.yml +7 -7
  31. data/spec/vcr_cassetes/fisp_140.yml +8 -10
  32. data/spec/vcr_cassetes/gb_t_20223_2006.yml +9 -9
  33. data/spec/vcr_cassetes/iec_60050_102_2007.yml +35 -33
  34. data/spec/vcr_cassetes/iec_combined_included.yml +87 -89
  35. data/spec/vcr_cassetes/ieee_528_2019.yml +20 -18
  36. data/spec/vcr_cassetes/iho_b_11.yml +7 -7
  37. data/spec/vcr_cassetes/iso_111111119115_1.yml +5 -5
  38. data/spec/vcr_cassetes/iso_19115.yml +22 -22
  39. data/spec/vcr_cassetes/iso_19115_1.yml +21 -21
  40. data/spec/vcr_cassetes/iso_19115_1_2.yml +41 -41
  41. data/spec/vcr_cassetes/iso_awi_14093.yml +182 -0
  42. data/spec/vcr_cassetes/iso_combined_applied.yml +42 -42
  43. data/spec/vcr_cassetes/iso_combined_included.yml +43 -43
  44. data/spec/vcr_cassetes/itu_combined_included.yml +813 -681
  45. data/spec/vcr_cassetes/ogc_19_025r1.yml +1350 -1158
  46. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +43 -0
  47. data/spec/vcr_cassetes/rfc_8341.yml +7 -7
  48. data/spec/vcr_cassetes/sp_800_38b.yml +8 -10
  49. data/spec/vcr_cassetes/un_rtade_cefact_2004_32.yml +34 -34
  50. data/spec/vcr_cassetes/w3c_json_ld11.yml +17 -17
  51. metadata +122 -47
  52. data/localcache/iec/iec_60050_102_2007.xml +0 -58
  53. data/localcache/iec/version +0 -1
  54. data/spec/vcr_cassetes/iso_awi_24229.yml +0 -182
  55. data/spec/vcr_cassetes/ogm_ami4ccm_1_0.yml +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fdf3d2a7e0d55bf5b5edf65ef0e6f1f3d3ce5648388b6bae43127040df90d881
4
- data.tar.gz: d3cc65b7002c57f6e72c86dccfab92956a992fcfef9ce836ec5b3b4806646e88
3
+ metadata.gz: 9d954779afa85cdbe30b00b6780f4fe2ea261839da0f82855dca6e63fe8be77d
4
+ data.tar.gz: e7549980e5771e74412291428b8010ad4d6a7720526b98169b97dac82539e909
5
5
  SHA512:
6
- metadata.gz: ae4cba856c12417b10308310c14aec5e2d4452c0c24a4fe30b597d57b7c142e138e858fb97ad452bb29488e3d5d4b0a6bc1fde8dcc41bd4bb10c837315dc7257
7
- data.tar.gz: e47b6c8e2feb25956d77df52352a474936168854263aeb354d526890b63428d420eeebdc7be6f6547689ec5a25e5a1b2045c72d82680ae7e234c5d1d42023579
6
+ metadata.gz: 466c2e7c24c972df07bf9548b0dac26ec0eb2c03d7c8716abba50cc7a95f83dd58c903b3b99a99fbddcb3afa1d68518c93082acee68034ec3d3230e10d4f0b25
7
+ data.tar.gz: 3f4fb6fd8750375862ae109d8d50654372fa3d8e1b6b8eb966e827a026cd4c99f1790a68068c6785a93c6a2c459b6c1506a1768aef881025fa12914cffd0708b
@@ -16,7 +16,7 @@ jobs:
16
16
  strategy:
17
17
  fail-fast: false
18
18
  matrix:
19
- ruby: [ '2.7', '2.6', '2.5', '2.4' ]
19
+ ruby: [ '2.7', '2.6', '2.5' ]
20
20
  os: [ ubuntu-latest, windows-latest, macos-latest ]
21
21
  experimental: [ false ]
22
22
  include:
data/.rubocop.yml CHANGED
@@ -5,6 +5,6 @@
5
5
  inherit_from:
6
6
  - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
7
7
  AllCops:
8
- TargetRubyVersion: 2.4
8
+ TargetRubyVersion: 2.5
9
9
  Rails:
10
10
  Enabled: false
data/docs/README.adoc CHANGED
@@ -106,14 +106,18 @@ db = Relaton::Db.new("globalcache", "localcache")
106
106
 
107
107
  ==== Move DB
108
108
 
109
- `Relaton::Db#mv(new_globalcache_dir, new_localcahe_dir)` moves DB directories to new location.
109
+ `Relaton::Db#mv(new_dir, type: :global)` moves DB directory to new location. Returns path to new directory if successful, or `nil` if target directiory exists.
110
110
 
111
- * `new_globalcahe_dir` - (String or nil) new globalcache location
112
- * `new_localcahe_dir` - (String or nil) new localcache location
111
+ * `new_dir` - (String) new cache location
112
+ * `type` - (Symbol) type of cache DB. Allowed values are: `:global`, `:local`. Default is `:global`.
113
113
 
114
114
  [source,ruby]
115
115
  ----
116
- db.mv("new_globalcache_dir", "new_localcahe_dir")
116
+ db.mv("new_global_dir")
117
+ => "new_global_dir"
118
+
119
+ db.mv("new_local_dir", type: :local)
120
+ => "new_local_dir"
117
121
  ----
118
122
 
119
123
  ==== Clear DB
@@ -178,14 +182,19 @@ x = db.fetch_db("ISO 5749")
178
182
  # prepare queue for results
179
183
  results = Queue.new
180
184
 
181
- # fetch document
182
- db.fetch_async("ISO 19115") do |result|
183
- results << { "ISO 19115" => result }
185
+ # references ot fetch
186
+ refs = ["ISO 19011", "ISO 19115"]
187
+
188
+ # fetch documents
189
+ refs.each do |ref|
190
+ db.fetch_async(ref) do |doc|
191
+ results << [ref, doc]
192
+ end
184
193
  end
185
- # fetch other documets the same way
186
194
 
187
195
  # wait until documets fetching
188
- while x = results.pop
196
+ refs.size.times do
197
+ ref, doc = results.pop
189
198
  # do thatever you need with result x
190
199
  end
191
200
  ----
@@ -330,7 +339,7 @@ ISO/IEC DIR 1
330
339
  ISO/IEC DIR 2 IEC
331
340
  ISO/IEC DIR 2 ISO
332
341
  ISO/IEC DIR IEC SUP
333
- ISO/IEC DIR 1 ISO SUP
342
+ ISO/IEC DIR 1 JTC SUP
334
343
  ----
335
344
 
336
345
  === Get document type
@@ -368,7 +377,7 @@ x.to_xml bibdata: true
368
377
  db.load_entry("ISO(ISO 19011)")
369
378
  => "<bibdata type="standard">
370
379
  ...
371
- <?bibdata>"
380
+ </bibdata>"
372
381
  ----
373
382
 
374
383
  === Entry manipulation
data/lib/relaton.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "relaton/util"
2
2
  require "relaton/config"
3
+ require "yaml"
3
4
 
4
5
  require "relaton/workers_pool"
5
6
  require "relaton/db"
@@ -12,11 +12,15 @@ module Relaton
12
12
  end
13
13
 
14
14
  class Configuration
15
- attr_accessor :logs, :use_api
15
+ attr_accessor :logs, :use_api, :api_host, :api_mode
16
16
 
17
17
  def initialize
18
- @logs = %i(warning error)
19
- @use_api = false # @TODO change to true when we start using api.relaton.org
18
+ @logs = %i(info error) # allowed values: :info, :warning, :error, :debug
19
+
20
+ # @TODO change to true when we start using api.relaton.org
21
+ @use_api = true
22
+ @api_mode = false
23
+ @api_host = "https://api.relaton.org/api/v1"
20
24
  end
21
25
  end
22
26
 
data/lib/relaton/db.rb CHANGED
@@ -1,60 +1,71 @@
1
- require "yaml"
2
- require_relative "registry"
3
- require_relative "db_cache"
4
-
5
1
  module Relaton
6
- class RelatonError < StandardError; end
2
+ # class RelatonError < StandardError; end
7
3
 
8
4
  class Db
9
5
  # @param global_cache [String] directory of global DB
10
6
  # @param local_cache [String] directory of local DB
11
- def initialize(global_cache, local_cache)
7
+ def initialize(global_cache, local_cache) # rubocop:disable Metrics/MethodLength
12
8
  @registry = Relaton::Registry.instance
13
- @db = open_cache_biblio(global_cache, type: :global)
14
- @local_db = open_cache_biblio(local_cache, type: :local)
15
- @static_db = open_cache_biblio File.expand_path("../relaton/static_cache", __dir__)
9
+ if Relaton.configuration.api_mode
10
+ gpath = global_cache
11
+ lpath = local_cache
12
+ else
13
+ gpath = global_cache && File.expand_path(global_cache)
14
+ lpath = local_cache && File.expand_path(local_cache)
15
+ end
16
+ @db = open_cache_biblio(gpath, type: :global)
17
+ @local_db = open_cache_biblio(lpath, type: :local)
18
+ @static_db = open_cache_biblio File.expand_path "../relaton/static_cache", __dir__
16
19
  @queues = {}
17
20
  end
18
21
 
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
22
+ # Move global or local caches to anothe dirs
23
+ # @param new_dir [String, nil]
24
+ # @param type: [Symbol]
25
+ # @return [String, nil]
26
+ def mv(new_dir, type: :global)
27
+ case type
28
+ when :global then @db&.mv new_dir
29
+ when :local then @local_db&.mv new_dir
30
+ end
25
31
  end
26
32
 
27
33
  # Clear global and local databases
28
34
  def clear
29
- @db.clear
30
- @local_db.clear
35
+ @db&.clear
36
+ @local_db&.clear
31
37
  end
32
38
 
33
39
  ##
34
40
  # The class of reference requested is determined by the prefix of the code:
35
- # GB Standard for gbbib, IETF for ietfbib, ISO for isobib, IEC or IEV for iecbib,
41
+ # GB Standard for gbbib, IETF for ietfbib, ISO for isobib, IEC or IEV for
42
+ # iecbib,
36
43
  #
37
44
  # @param code [String] the ISO standard Code to look up (e.g. "ISO 9000")
38
45
  # @param year [String] the year the standard was published (optional)
39
46
  #
40
47
  # @param opts [Hash] options
41
48
  # @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
49
+ # @option opts [Boolean] :keep_year If undated reference should return
50
+ # actual reference with year
43
51
  # @option opts [Integer] :retries (1) Number of network retries
44
52
  #
45
- # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
46
- # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
47
- # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
48
- # RelatonNist::NistBibliongraphicItem, RelatonGb::GbbibliographicItem,
49
- # RelatonOgc::OgcBibliographicItem, RelatonCalconnect::CcBibliographicItem]
53
+ # @return [nil, RelatonBib::BibliographicItem,
54
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
55
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
56
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
57
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
58
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
50
59
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
51
- # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
52
- # RelatonW3c::W3cBibliographicItem
60
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
53
61
  ##
54
62
  def fetch(code, year = nil, opts = {})
55
63
  stdclass = standard_class(code) || return
56
64
  processor = @registry.processors[stdclass]
57
- ref = processor.respond_to?(:urn_to_code) ? processor.urn_to_code(code)&.first : code
65
+ ref = if processor.respond_to?(:urn_to_code)
66
+ processor.urn_to_code(code)&.first
67
+ else code
68
+ end
58
69
  ref ||= code
59
70
  result = combine_doc ref, year, opts, stdclass
60
71
  result ||= check_bibliocache(ref, year, opts, stdclass)
@@ -73,19 +84,21 @@ module Relaton
73
84
  # @param year [Integer, nil]
74
85
  # @return [Array]
75
86
  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
87
+ result = @static_db.all do |file, yml|
88
+ search_yml file, yml, text, edition, year
89
+ end.compact
90
+ if (db = @db || @local_db)
91
+ result += db.all { |f, x| search_xml f, x, text, edition, year }.compact
92
+ end
79
93
  result
80
94
  end
81
95
 
82
96
  # Fetch asynchronously
83
97
  def fetch_async(code, year = nil, opts = {}, &_block) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
84
- stdclass = standard_class code
85
- if stdclass
98
+ if (stdclass = standard_class code)
86
99
  unless @queues[stdclass]
87
100
  processor = @registry.processors[stdclass]
88
- wp = WorkersPool.new(processor.threads) { |args| yield fetch *args }
101
+ wp = WorkersPool.new(processor.threads) { |args| yield fetch(*args) }
89
102
  @queues[stdclass] = { queue: Queue.new, workers_pool: wp }
90
103
  Thread.new { process_queue @queues[stdclass] }
91
104
  end
@@ -100,17 +113,18 @@ module Relaton
100
113
  #
101
114
  # @param opts [Hash]
102
115
  # @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
116
+ # @option opts [Boolean] :keep_year If undated reference should return
117
+ # actual reference with year
104
118
  # @option opts [Integer] :retries (1) Number of network retries
105
119
  #
106
- # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
107
- # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
108
- # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
109
- # RelatonNist::NistBibliongraphicItem, RelatonGb::GbbibliographicItem,
110
- # RelatonOgc::OgcBibliographicItem, RelatonCalconnect::CcBibliographicItem]
120
+ # @return [nil, RelatonBib::BibliographicItem,
121
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
122
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
123
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
124
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
125
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
111
126
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
112
- # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
113
- # RelatonW3c::W3cBibliographicItem
127
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
114
128
  def fetch_std(code, year = nil, stdclass = nil, opts = {})
115
129
  std = nil
116
130
  @registry.processors.each do |name, processor|
@@ -153,14 +167,43 @@ module Relaton
153
167
  def to_xml
154
168
  db = @local_db || @db || return
155
169
  Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
156
- xml.documents do
157
- xml.parent.add_child db.all.join(" ")
158
- end
170
+ xml.documents { xml.parent.add_child db.all.join(" ") }
159
171
  end.to_xml
160
172
  end
161
173
 
162
174
  private
163
175
 
176
+ #
177
+ # @param code [String]
178
+ # @param year [String]
179
+ #
180
+ # @param opts [Hash]
181
+ # @option opts [Boolean] :all_parts If all-parts reference is required
182
+ # @option opts [Boolean] :keep_year If undated reference should return
183
+ # actual reference with year
184
+ #
185
+ # @param stdclass [Symbol]
186
+ def fetch_api(code, year, opts, stdclass)
187
+ return unless Relaton.configuration.use_api
188
+
189
+ url = "#{Relaton.configuration.api_host}/document?#{params(code, year, opts)}"
190
+ rsp = Net::HTTP.get_response URI(url)
191
+ @registry.processors[stdclass].from_xml rsp.body if rsp.code == "200"
192
+ end
193
+
194
+ #
195
+ # Make string of parametrs
196
+ #
197
+ # @param [String] code
198
+ # @param [String] year
199
+ # @param [Hash] opts
200
+ #
201
+ # @return [String]
202
+ #
203
+ def params(code, year, opts)
204
+ opts.merge(code: code, year: year).map { |k, v| "#{k}=#{v}" }.join "&"
205
+ end
206
+
164
207
  # @param file [String] file path
165
208
  # @param yml [String] content in YAML format
166
209
  # @param text [String, nil] text to serach
@@ -187,20 +230,27 @@ module Relaton
187
230
  end
188
231
 
189
232
  # @param file [String] file path
190
- # @param content [String] content in XML or YAmL format
233
+ # @param content [String] content in XML or YAML format
191
234
  # @param edition [String, nil] edition to filter
192
235
  # @param year [Integer, nil] year to filter
193
236
  # @return [BibliographicItem, nil]
194
237
  def search_edition_year(file, content, edition, year) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
195
238
  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 })
239
+ item = if file.match?(/xml$/) then processor.from_xml(content)
240
+ else processor.hash_to_bib(YAML.safe_load(content))
241
+ end
242
+ item if (edition.nil? || item.edition == edition) && (year.nil? ||
243
+ item.date.detect { |d| d.type == "published" && d.on(:year).to_s == year.to_s })
199
244
  end
200
245
 
246
+ #
247
+ # Look up text in the XML elements attributes and content
248
+ #
201
249
  # @param xml [String] content in XML format
202
250
  # @param text [String, nil] text to serach
251
+ #
203
252
  # @return [Boolean]
253
+ #
204
254
  def match_xml_text(xml, text)
205
255
  %r{((?<attr>=((?<apstr>')|"))|>).*?#{text}.*?(?(<attr>)(?(<apstr>)'|")|<)}mi.match?(xml)
206
256
  end
@@ -211,18 +261,19 @@ module Relaton
211
261
  #
212
262
  # @param opts [Hash] options
213
263
  # @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
264
+ # @option opts [Boolean] :keep_year If undated reference should return
265
+ # actual reference with year
215
266
  # @option opts [Integer] :retries (1) Number of network retries
216
267
  #
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]
268
+ # @return [nil, RelatonBib::BibliographicItem,
269
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
270
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
271
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
272
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
273
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
222
274
  # 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
275
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
276
+ def combine_doc(code, year, opts, stdclass) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
226
277
  if (refs = code.split " + ").size > 1
227
278
  reltype = "derivedFrom"
228
279
  reldesc = nil
@@ -233,11 +284,13 @@ module Relaton
233
284
  end
234
285
 
235
286
  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
287
+ updates = check_bibliocache(refs[0], year, opts, stdclass)
288
+ if updates
289
+ doc.relation << RelatonBib::DocumentRelation.new(bibitem: updates, type: "updates")
290
+ end
291
+ divider = stdclass == :relaton_itu ? " " : "/"
239
292
  refs[1..-1].each_with_object(doc) do |c, d|
240
- bib = check_bibliocache("#{ref}/#{c}", year, opts, stdclass)
293
+ bib = check_bibliocache(refs[0] + divider + c, year, opts, stdclass)
241
294
  if bib
242
295
  d.relation << RelatonBib::DocumentRelation.new(type: reltype, description: reldesc, bibitem: bib)
243
296
  end
@@ -251,11 +304,9 @@ module Relaton
251
304
  return name if /^(urn:)?#{processor.prefix}/i.match?(code) ||
252
305
  processor.defaultprefix.match(code)
253
306
  end
254
- allowed = @registry.processors.reduce([]) do |m, (_k, v)|
255
- m << v.prefix
256
- end
257
- warn <<~WARN
258
- #{code} does not have a recognised prefix: #{allowed.join(', ')}.
307
+ allowed = @registry.processors.reduce([]) { |m, (_k, v)| m << v.prefix }
308
+ Util.log <<~WARN, :info
309
+ [relaton] #{code} does not have a recognised prefix: #{allowed.join(', ')}.
259
310
  See https://github.com/relaton/relaton/ for instructions on prefixing and wrapping document identifiers to disambiguate them.
260
311
  WARN
261
312
  end
@@ -267,7 +318,8 @@ module Relaton
267
318
  #
268
319
  # @param opts [Hash]
269
320
  # @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
321
+ # @option opts [Boolean] :keep_year If undated reference should return
322
+ # actual reference with year
271
323
  # @option opts [Integer] :retries (1) Number of network retries
272
324
  #
273
325
  # @param stdClass [Symbol]
@@ -292,16 +344,18 @@ module Relaton
292
344
 
293
345
  # @param entry [String] XML string
294
346
  # @param stdclass [Symbol]
295
- # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
296
- # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
297
- # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
298
- # RelatonNist::NistBibliongraphicItem, RelatonGb::GbbibliographicItem,
299
- # RelatonOgc::OgcBibliographicItem, RelatonCalconnect::CcBibliographicItem]
347
+ # @return [nil, RelatonBib::BibliographicItem,
348
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
349
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
350
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
351
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
352
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
300
353
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
301
- # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
302
- # RelatonW3c::W3cBibliographicItem
354
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
303
355
  def bib_retval(entry, stdclass)
304
- entry.nil? || entry.match?(/^not_found/) ? nil : @registry.processors[stdclass].from_xml(entry)
356
+ unless entry.nil? || entry.match?(/^not_found/)
357
+ @registry.processors[stdclass].from_xml(entry)
358
+ end
305
359
  end
306
360
 
307
361
  # @param code [String]
@@ -309,22 +363,24 @@ module Relaton
309
363
  #
310
364
  # @param opts [Hash]
311
365
  # @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
366
+ # @option opts [Boolean] :keep_year If undated reference should return
367
+ # actual reference with year
313
368
  # @option opts [Integer] :retries (1) Number of network retries
314
369
  #
315
370
  # @param stdclass [Symbol]
316
- # @return [nil, RelatonBib::BibliographicItem, RelatonIsoBib::IsoBibliographicItem,
317
- # RelatonItu::ItuBibliographicItem, RelatonIetf::IetfBibliographicItem,
318
- # RelatonIec::IecBibliographicItem, RelatonIeee::IeeeBibliographicItem,
319
- # RelatonNist::NistBibliongraphicItem, RelatonGb::GbbibliographicItem,
320
- # RelatonOgc::OgcBibliographicItem, RelatonCalconnect::CcBibliographicItem]
371
+ # @return [nil, RelatonBib::BibliographicItem,
372
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
373
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
374
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
375
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
376
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
321
377
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
322
- # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
323
- # RelatonW3c::W3cBibliographicItem
378
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
324
379
  def check_bibliocache(code, year, opts, stdclass) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
325
380
  id, searchcode = std_id(code, year, opts, stdclass)
326
- yaml = @static_db[id]
327
- return @registry.processors[stdclass].hash_to_bib YAML.safe_load(yaml) if yaml
381
+ if (yaml = @static_db[id])
382
+ return @registry.processors[stdclass].hash_to_bib YAML.safe_load(yaml)
383
+ end
328
384
 
329
385
  db = @local_db || @db
330
386
  altdb = @local_db && @db ? @db : nil
@@ -350,24 +406,29 @@ module Relaton
350
406
  bib_retval(db[id], stdclass)
351
407
  end
352
408
 
409
+ #
353
410
  # @param code [String]
354
411
  # @param year [String]
355
412
  #
356
413
  # @param opts [Hash]
357
414
  # @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
415
+ # @option opts [Boolean] :keep_year If undated reference should return
416
+ # actual reference with year
359
417
  # @option opts [Integer] :retries (1) Number of network retries
360
418
  #
361
419
  # @param stdclass [Symbol]
362
420
  # @param db [Relaton::DbCache,`NilClass]
363
421
  # @param id [String] docid
422
+ #
364
423
  # @return [String]
424
+ #
365
425
  def new_bib_entry(code, year, opts, stdclass, **args) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
366
426
  bib = net_retry(code, year, opts, stdclass, opts.fetch(:retries, 1))
367
427
  bib_id = bib&.docidentifier&.first&.id
368
428
 
369
429
  # when docid doesn't match bib's id then return a reference to bib's id
370
- if args[:db] && args[:id] && bib_id && args[:id] !~ %r{#{Regexp.quote("(#{bib_id})")}}
430
+ if args[:db] && args[:id] &&
431
+ bib_id && args[:id] !~ %r{#{Regexp.quote("(#{bib_id})")}}
371
432
  bid = std_id(bib.docidentifier.first.id, nil, {}, stdclass).first
372
433
  args[:db][bid] ||= bib_entry bib
373
434
  "redirection #{bid}"
@@ -375,8 +436,27 @@ module Relaton
375
436
  end
376
437
  end
377
438
 
439
+ #
440
+ # @param code [String]
441
+ # @param year [String]
442
+ #
443
+ # @param opts [Hash]
444
+ # @option opts [Boolean] :all_parts If all-parts reference is required
445
+ # @option opts [Boolean] :keep_year If undated reference should return
446
+ # actual reference with year
447
+ #
448
+ # @param stdclass [Symbol]
449
+ # @param retries [Integer] remain Number of network retries
450
+ #
378
451
  # @raise [RelatonBib::RequestError]
452
+ # @return [RelatonBib::BibliographicItem]
453
+ #
379
454
  def net_retry(code, year, opts, stdclass, retries)
455
+ doc = fetch_api code, year, opts, stdclass
456
+ return doc if doc
457
+
458
+ @registry.processors[stdclass].get(code, year, opts)
459
+ rescue Errno::ECONNREFUSED
380
460
  @registry.processors[stdclass].get(code, year, opts)
381
461
  rescue RelatonBib::RequestError => e
382
462
  raise e unless retries > 1
@@ -384,22 +464,23 @@ module Relaton
384
464
  net_retry(code, year, opts, stdclass, retries - 1)
385
465
  end
386
466
 
387
- # @param bib [RelatonGb::GbBibliongraphicItem, RelatonIsoBib::IsoBibliographicItem,
388
- # RelatonIetf::IetfBibliographicItem, RelatonItu::ItuBibliographicItem,
389
- # RelatonNist::NistBibliongraphicItem, RelatonOgc::OgcBibliographicItem]
467
+ # @param bib [RelatonBib::BibliographicItem,
468
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
469
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
470
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
471
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
472
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
473
+ # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
474
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
390
475
  # @return [String] XML or "not_found mm-dd-yyyy"
391
476
  def bib_entry(bib)
392
- if bib.respond_to? :to_xml
393
- bib.to_xml(bibdata: true)
394
- else
395
- "not_found #{Date.today}"
396
- end
477
+ bib.respond_to?(:to_xml) ? bib.to_xml(bibdata: true) : "not_found #{Date.today}"
397
478
  end
398
479
 
399
480
  # @param dir [String, nil] DB directory
400
481
  # @param type [Symbol]
401
482
  # @return [Relaton::DbCache, NilClass]
402
- def open_cache_biblio(dir, type: :static)
483
+ def open_cache_biblio(dir, type: :static) # rubocop:disable Metrics/MethodLength
403
484
  return nil if dir.nil?
404
485
 
405
486
  db = DbCache.new dir, type == :static ? "yml" : "xml"
@@ -408,9 +489,11 @@ module Relaton
408
489
  Dir["#{dir}/*/"].each do |fdir|
409
490
  next if db.check_version?(fdir)
410
491
 
411
- FileUtils.rm_rf(Dir.glob(fdir + "/*"), secure: true)
412
- db.set_version fdir
413
- warn "[relaton] cache #{fdir}: version is obsolete and cache is cleared."
492
+ FileUtils.rm_rf(fdir, secure: true)
493
+ Util.log(
494
+ "[relaton] WARNING: cache #{fdir}: version is obsolete and cache is "\
495
+ "cleared.", :warning
496
+ )
414
497
  end
415
498
  db
416
499
  end
@@ -419,8 +502,37 @@ module Relaton
419
502
  # @option qwp [Queue] :queue The queue of references to fetch
420
503
  # @option qwp [Relaton::WorkersPool] :workers_pool The pool of workers
421
504
  def process_queue(qwp)
422
- while args = qwp[:queue].pop
423
- qwp[:workers_pool] << args
505
+ while args = qwp[:queue].pop; qwp[:workers_pool] << args end
506
+ end
507
+
508
+ class << self
509
+ # Initialse and return relaton instance, with local and global cache names
510
+ # local_cache: local cache name; none created if nil; "relaton" created
511
+ # if empty global_cache: boolean to create global_cache
512
+ # flush_caches: flush caches
513
+ def init_bib_caches(**opts) # rubocop:disable Metrics/CyclomaticComplexity
514
+ globalname = global_bibliocache_name if opts[:global_cache]
515
+ localname = local_bibliocache_name(opts[:local_cache])
516
+ flush_caches globalname, localname if opts[:flush_caches]
517
+ Relaton::Db.new(globalname, localname)
518
+ end
519
+
520
+ private
521
+
522
+ def flush_caches(gcache, lcache)
523
+ FileUtils.rm_rf gcache unless gcache.nil?
524
+ FileUtils.rm_rf lcache unless lcache.nil?
525
+ end
526
+
527
+ def global_bibliocache_name
528
+ Relaton.configuration.api_mode ? "cache" : "#{Dir.home}/.relaton/cache"
529
+ end
530
+
531
+ def local_bibliocache_name(cachename)
532
+ return nil if Relaton.configuration.api_mode || cachename.nil?
533
+
534
+ cachename = "relaton" if cachename.empty?
535
+ "#{cachename}/cache"
424
536
  end
425
537
  end
426
538
  end