relaton 1.7.9 → 1.8.pre2

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.rubocop.yml +1 -1
  4. data/lib/relaton.rb +3 -0
  5. data/lib/relaton/config.rb +4 -2
  6. data/lib/relaton/db.rb +106 -52
  7. data/lib/relaton/db_cache.rb +38 -125
  8. data/lib/relaton/registry.rb +1 -0
  9. data/lib/relaton/storage.rb +186 -0
  10. data/lib/relaton/version.rb +1 -1
  11. data/relaton.gemspec +23 -19
  12. data/spec/relaton/db_cache_spec.rb +2 -2
  13. data/spec/relaton/db_spec.rb +17 -0
  14. data/spec/relaton/regirtry_spec.rb +9 -1
  15. data/spec/relaton/storage_spec.rb +130 -0
  16. data/spec/relaton_spec.rb +48 -7
  17. data/spec/spec_helper.rb +4 -0
  18. data/spec/vcr_cassetes/19133_2005.yml +17 -17
  19. data/spec/vcr_cassetes/api_relaton_org.yml +33 -0
  20. data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +182 -0
  21. data/spec/vcr_cassetes/async_fetch.yml +2037 -1606
  22. data/spec/vcr_cassetes/bsi_bs_en_iso_8848.yml +17 -17
  23. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +10 -10
  24. data/spec/vcr_cassetes/cen_en_10160_1999.yml +249 -0
  25. data/spec/vcr_cassetes/cie_001_1980.yml +7 -7
  26. data/spec/vcr_cassetes/ecma_6.yml +7 -7
  27. data/spec/vcr_cassetes/fisp_140.yml +4 -4
  28. data/spec/vcr_cassetes/gb_t_20223_2006.yml +9 -9
  29. data/spec/vcr_cassetes/iec_60050_102_2007.yml +23 -23
  30. data/spec/vcr_cassetes/iec_combined_included.yml +81 -79
  31. data/spec/vcr_cassetes/ieee_528_2019.yml +38 -38
  32. data/spec/vcr_cassetes/iho_b_11.yml +7 -7
  33. data/spec/vcr_cassetes/iso_111111119115_1.yml +3 -3
  34. data/spec/vcr_cassetes/iso_19115.yml +19 -19
  35. data/spec/vcr_cassetes/iso_19115_1.yml +18 -18
  36. data/spec/vcr_cassetes/iso_19115_1_2.yml +35 -35
  37. data/spec/vcr_cassetes/iso_awi_14093.yml +182 -0
  38. data/spec/vcr_cassetes/iso_combined_applied.yml +38 -38
  39. data/spec/vcr_cassetes/iso_combined_included.yml +34 -34
  40. data/spec/vcr_cassetes/itu_combined_included.yml +456 -459
  41. data/spec/vcr_cassetes/ogc_19_025r1.yml +1222 -1163
  42. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +43 -0
  43. data/spec/vcr_cassetes/rfc_8341.yml +7 -7
  44. data/spec/vcr_cassetes/sp_800_38b.yml +4 -4
  45. data/spec/vcr_cassetes/un_rtade_cefact_2004_32.yml +29 -29
  46. data/spec/vcr_cassetes/w3c_json_ld11.yml +17 -17
  47. metadata +107 -46
  48. data/spec/vcr_cassetes/iso_awi_24229.yml +0 -182
  49. data/spec/vcr_cassetes/ogm_ami4ccm_1_0.yml +0 -43
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b14a266fd6fd230fc37d8e2e6843bd48c37019136dc6006a27a89668ecf7af2
4
- data.tar.gz: 3eb6ba9aaa798ab5b763328712e4051184ff2c9de1659791198ca8a7a21726c7
3
+ metadata.gz: 7613bdf8be768f76e3e24d8727210075cd8ad8d4e24924ec5d19d28473cd933f
4
+ data.tar.gz: 1332d1463afd07385d3aacb917a2f621b572e802b25ec64d5d5f87781b6c6ef6
5
5
  SHA512:
6
- metadata.gz: 13a0f6f87426975dbf87e9eefd69d3f519e3a178452039eb9d036725e4c7bdd676ebe0d228a07b3512d296b6d4153cc1e88c72589baa702fb8ac1de717204783
7
- data.tar.gz: e748db6725c7d027b38e1140dc60d74cdea86304f2380d9251cc9d07f143d0536e4b7e1bb63dea35ddd464e2969e08c03f6cde10a426f19e0a8959ecf7a6281f
6
+ metadata.gz: dd636d5da683476ff6abf8a0c686bd9b7112cbbbda7c19f96249b75a6ecb8a4cb4c5764eeead68e949003b8f460574b50fabbcbe2f838ff9f104cb52adda45ba
7
+ data.tar.gz: 75ec0ed77c187b48baef584702b10cd5add0938325a19a40eac6e0217c86b7f769f30ad2561c612ab4fd2c0905c03e8c94797c92ce28a034215cf88bfc8d5f09
@@ -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/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"
@@ -7,3 +8,5 @@ require "relaton/db_cache"
7
8
  require "relaton/version"
8
9
  require "relaton/registry"
9
10
  require "relaton/processor"
11
+ require "relaton/registry"
12
+ require "relaton/db_cache"
@@ -12,13 +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
18
  @logs = %i(info error) # allowed values: :info, :warning, :error, :debug
19
19
 
20
20
  # @TODO change to true when we start using api.relaton.org
21
- @use_api = false
21
+ @use_api = true
22
+ @api_mode = false
23
+ @api_host = nil # "http://0.0.0.0:9292"
22
24
  end
23
25
  end
24
26
 
data/lib/relaton/db.rb CHANGED
@@ -1,7 +1,3 @@
1
- require "yaml"
2
- require_relative "registry"
3
- require_relative "db_cache"
4
-
5
1
  module Relaton
6
2
  class RelatonError < StandardError; end
7
3
 
@@ -10,12 +6,16 @@ module Relaton
10
6
  # @param local_cache [String] directory of local DB
11
7
  def initialize(global_cache, local_cache)
12
8
  @registry = Relaton::Registry.instance
13
- gpath = global_cache && File.expand_path(global_cache)
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
14
16
  @db = open_cache_biblio(gpath, type: :global)
15
- lpath = local_cache && File.expand_path(local_cache)
16
17
  @local_db = open_cache_biblio(lpath, type: :local)
17
- @static_db = open_cache_biblio File.expand_path("../relaton/static_cache",
18
- __dir__)
18
+ @static_db = open_cache_biblio File.expand_path "../relaton/static_cache", __dir__
19
19
  @queues = {}
20
20
  end
21
21
 
@@ -25,10 +25,8 @@ module Relaton
25
25
  # @return [String, nil]
26
26
  def mv(new_dir, type: :global)
27
27
  case type
28
- when :global
29
- @db&.mv new_dir
30
- when :local
31
- @local_db&.mv new_dir
28
+ when :global then @db&.mv new_dir
29
+ when :local then @local_db&.mv new_dir
32
30
  end
33
31
  end
34
32
 
@@ -89,22 +87,18 @@ module Relaton
89
87
  result = @static_db.all do |file, yml|
90
88
  search_yml file, yml, text, edition, year
91
89
  end.compact
92
- db = @db || @local_db
93
- if db
94
- result += db.all do |file, xml|
95
- search_xml file, xml, text, edition, year
96
- end.compact
90
+ if (db = @db || @local_db)
91
+ result += db.all { |f, x| search_xml f, x, text, edition, year }.compact
97
92
  end
98
93
  result
99
94
  end
100
95
 
101
96
  # Fetch asynchronously
102
97
  def fetch_async(code, year = nil, opts = {}, &_block) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
103
- stdclass = standard_class code
104
- if stdclass
98
+ if (stdclass = standard_class code)
105
99
  unless @queues[stdclass]
106
100
  processor = @registry.processors[stdclass]
107
- wp = WorkersPool.new(processor.threads) { |args| yield fetch *args }
101
+ wp = WorkersPool.new(processor.threads) { |args| yield fetch(*args) }
108
102
  @queues[stdclass] = { queue: Queue.new, workers_pool: wp }
109
103
  Thread.new { process_queue @queues[stdclass] }
110
104
  end
@@ -173,14 +167,31 @@ module Relaton
173
167
  def to_xml
174
168
  db = @local_db || @db || return
175
169
  Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
176
- xml.documents do
177
- xml.parent.add_child db.all.join(" ")
178
- end
170
+ xml.documents { xml.parent.add_child db.all.join(" ") }
179
171
  end.to_xml
180
172
  end
181
173
 
182
174
  private
183
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
+ params = opts.merge(code: code, year: year).map { |k, v| "#{k}=#{v}" }.join "&"
190
+ url = "#{Relaton.configuration.api_host}/api/v1/fetch?#{params}"
191
+ rsp = Net::HTTP.get_response URI(url)
192
+ @registry.processors[stdclass].from_xml rsp.body if rsp.code == "200"
193
+ end
194
+
184
195
  # @param file [String] file path
185
196
  # @param yml [String] content in YAML format
186
197
  # @param text [String, nil] text to serach
@@ -207,7 +218,7 @@ module Relaton
207
218
  end
208
219
 
209
220
  # @param file [String] file path
210
- # @param content [String] content in XML or YAmL format
221
+ # @param content [String] content in XML or YAML format
211
222
  # @param edition [String, nil] edition to filter
212
223
  # @param year [Integer, nil] year to filter
213
224
  # @return [BibliographicItem, nil]
@@ -220,9 +231,14 @@ module Relaton
220
231
  item.date.detect { |d| d.type == "published" && d.on(:year).to_s == year.to_s })
221
232
  end
222
233
 
234
+ #
235
+ # Look up text in the XML elements attributes and content
236
+ #
223
237
  # @param xml [String] content in XML format
224
238
  # @param text [String, nil] text to serach
239
+ #
225
240
  # @return [Boolean]
241
+ #
226
242
  def match_xml_text(xml, text)
227
243
  %r{((?<attr>=((?<apstr>')|"))|>).*?#{text}.*?(?(<attr>)(?(<apstr>)'|")|<)}mi.match?(xml)
228
244
  end
@@ -256,19 +272,15 @@ module Relaton
256
272
  end
257
273
 
258
274
  doc = @registry.processors[stdclass].hash_to_bib docid: { id: code }
259
- ref = refs[0]
260
- updates = check_bibliocache(ref, year, opts, stdclass)
275
+ updates = check_bibliocache(refs[0], year, opts, stdclass)
261
276
  if updates
262
- doc.relation << RelatonBib::DocumentRelation.new(bibitem: updates,
263
- type: "updates")
277
+ doc.relation << RelatonBib::DocumentRelation.new(bibitem: updates, type: "updates")
264
278
  end
265
279
  divider = stdclass == :relaton_itu ? " " : "/"
266
280
  refs[1..-1].each_with_object(doc) do |c, d|
267
- bib = check_bibliocache(ref + divider + c, year, opts, stdclass)
281
+ bib = check_bibliocache(refs[0] + divider + c, year, opts, stdclass)
268
282
  if bib
269
- d.relation << RelatonBib::DocumentRelation.new(
270
- type: reltype, description: reldesc, bibitem: bib
271
- )
283
+ d.relation << RelatonBib::DocumentRelation.new(type: reltype, description: reldesc, bibitem: bib)
272
284
  end
273
285
  end
274
286
  end
@@ -280,9 +292,7 @@ module Relaton
280
292
  return name if /^(urn:)?#{processor.prefix}/i.match?(code) ||
281
293
  processor.defaultprefix.match(code)
282
294
  end
283
- allowed = @registry.processors.reduce([]) do |m, (_k, v)|
284
- m << v.prefix
285
- end
295
+ allowed = @registry.processors.reduce([]) { |m, (_k, v)| m << v.prefix }
286
296
  Util.log <<~WARN, :info
287
297
  [relaton] #{code} does not have a recognised prefix: #{allowed.join(', ')}.
288
298
  See https://github.com/relaton/relaton/ for instructions on prefixing and wrapping document identifiers to disambiguate them.
@@ -331,8 +341,8 @@ module Relaton
331
341
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
332
342
  # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
333
343
  def bib_retval(entry, stdclass)
334
- if entry.nil? || entry.match?(/^not_found/) then nil
335
- else @registry.processors[stdclass].from_xml(entry)
344
+ unless entry.nil? || entry.match?(/^not_found/)
345
+ @registry.processors[stdclass].from_xml(entry)
336
346
  end
337
347
  end
338
348
 
@@ -356,8 +366,7 @@ module Relaton
356
366
  # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
357
367
  def check_bibliocache(code, year, opts, stdclass) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
358
368
  id, searchcode = std_id(code, year, opts, stdclass)
359
- yaml = @static_db[id]
360
- if yaml
369
+ if (yaml = @static_db[id])
361
370
  return @registry.processors[stdclass].hash_to_bib YAML.safe_load(yaml)
362
371
  end
363
372
 
@@ -366,8 +375,7 @@ module Relaton
366
375
  if db.nil?
367
376
  return if opts[:fetch_db]
368
377
 
369
- bibentry = new_bib_entry(searchcode, year, opts, stdclass, db: db,
370
- id: id)
378
+ bibentry = new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
371
379
  return bib_retval(bibentry, stdclass)
372
380
  end
373
381
 
@@ -376,18 +384,17 @@ module Relaton
376
384
  return bib_retval(altdb[id], stdclass) if opts[:fetch_db]
377
385
 
378
386
  db.clone_entry id, altdb if altdb.valid_entry? id, year
379
- db[id] ||= new_bib_entry(searchcode, year, opts, stdclass, db: db,
380
- id: id)
387
+ db[id] ||= new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
381
388
  altdb.clone_entry(id, db) if !altdb.valid_entry?(id, year)
382
389
  else
383
390
  return bib_retval(db[id], stdclass) if opts[:fetch_db]
384
391
 
385
- db[id] ||= new_bib_entry(searchcode, year, opts, stdclass, db: db,
386
- id: id)
392
+ db[id] ||= new_bib_entry(searchcode, year, opts, stdclass, db: db, id: id)
387
393
  end
388
394
  bib_retval(db[id], stdclass)
389
395
  end
390
396
 
397
+ #
391
398
  # @param code [String]
392
399
  # @param year [String]
393
400
  #
@@ -400,7 +407,9 @@ module Relaton
400
407
  # @param stdclass [Symbol]
401
408
  # @param db [Relaton::DbCache,`NilClass]
402
409
  # @param id [String] docid
410
+ #
403
411
  # @return [String]
412
+ #
404
413
  def new_bib_entry(code, year, opts, stdclass, **args) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
405
414
  bib = net_retry(code, year, opts, stdclass, opts.fetch(:retries, 1))
406
415
  bib_id = bib&.docidentifier&.first&.id
@@ -415,8 +424,27 @@ module Relaton
415
424
  end
416
425
  end
417
426
 
427
+ #
428
+ # @param code [String]
429
+ # @param year [String]
430
+ #
431
+ # @param opts [Hash]
432
+ # @option opts [Boolean] :all_parts If all-parts reference is required
433
+ # @option opts [Boolean] :keep_year If undated reference should return
434
+ # actual reference with year
435
+ #
436
+ # @param stdclass [Symbol]
437
+ # @param retries [Integer] remain Number of network retries
438
+ #
418
439
  # @raise [RelatonBib::RequestError]
440
+ # @return [RelatonBib::BibliographicItem]
441
+ #
419
442
  def net_retry(code, year, opts, stdclass, retries)
443
+ doc = fetch_api code, year, opts, stdclass
444
+ return doc if doc
445
+
446
+ @registry.processors[stdclass].get(code, year, opts)
447
+ rescue Errno::ECONNREFUSED
420
448
  @registry.processors[stdclass].get(code, year, opts)
421
449
  rescue RelatonBib::RequestError => e
422
450
  raise e unless retries > 1
@@ -434,11 +462,7 @@ module Relaton
434
462
  # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
435
463
  # @return [String] XML or "not_found mm-dd-yyyy"
436
464
  def bib_entry(bib)
437
- if bib.respond_to? :to_xml
438
- bib.to_xml(bibdata: true)
439
- else
440
- "not_found #{Date.today}"
441
- end
465
+ bib.respond_to?(:to_xml) ? bib.to_xml(bibdata: true) : "not_found #{Date.today}"
442
466
  end
443
467
 
444
468
  # @param dir [String, nil] DB directory
@@ -456,8 +480,7 @@ module Relaton
456
480
  FileUtils.rm_rf(fdir, secure: true)
457
481
  Util.log(
458
482
  "[relaton] WARNING: cache #{fdir}: version is obsolete and cache is "\
459
- "cleared.",
460
- :warning
483
+ "cleared.", :warning
461
484
  )
462
485
  end
463
486
  db
@@ -469,5 +492,36 @@ module Relaton
469
492
  def process_queue(qwp)
470
493
  while args = qwp[:queue].pop; qwp[:workers_pool] << args end
471
494
  end
495
+
496
+ class << self
497
+ # Initialse and return relaton instance, with local and global cache names
498
+ # local_cache: local cache name; none created if nil; "relaton" created
499
+ # if empty global_cache: boolean to create global_cache
500
+ # flush_caches: flush caches
501
+ def init_bib_caches(**opts) # rubocop:disable Metrics/CyclomaticComplexity
502
+ globalname = global_bibliocache_name if opts[:global_cache]
503
+ localname = local_bibliocache_name(opts[:local_cache])
504
+ flush_caches globalname, localname if opts[:flush_caches]
505
+ Relaton::Db.new(globalname, localname)
506
+ end
507
+
508
+ private
509
+
510
+ def flush_caches(gcache, lcache)
511
+ FileUtils.rm_rf gcache unless gcache.nil?
512
+ FileUtils.rm_rf lcache unless lcache.nil?
513
+ end
514
+
515
+ def global_bibliocache_name
516
+ Relaton.configuration.api_mode ? "cache" : "#{Dir.home}/.relaton/cache"
517
+ end
518
+
519
+ def local_bibliocache_name(cachename)
520
+ return nil if Relaton.configuration.api_mode || cachename.nil?
521
+
522
+ cachename = "relaton" if cachename.empty?
523
+ "#{cachename}/cache"
524
+ end
525
+ end
472
526
  end
473
527
  end
@@ -1,5 +1,6 @@
1
1
  require "fileutils"
2
2
  require "timeout"
3
+ require "relaton/storage"
3
4
 
4
5
  module Relaton
5
6
  class DbCache
@@ -10,16 +11,15 @@ module Relaton
10
11
  def initialize(dir, ext = "xml")
11
12
  @dir = dir
12
13
  @ext = ext
13
- FileUtils::mkdir_p @dir
14
- # file_version = "#{@dir}/version"
15
- # set_version # unless File.exist? file_version
14
+ @storage = Storage.instance
15
+ FileUtils::mkdir_p @dir unless Relaton.configuration.api_mode
16
16
  end
17
17
 
18
18
  # Move caches to anothe dir
19
19
  # @param new_dir [String, nil]
20
20
  # @return [String, nil]
21
21
  def mv(new_dir)
22
- return unless new_dir && @ext == "xml"
22
+ return unless new_dir && @ext == "xml" && !Relaton.configuration.api_mode
23
23
 
24
24
  if File.exist? new_dir
25
25
  warn "[relaton] WARNING: target directory exists \"#{new_dir}\""
@@ -32,7 +32,9 @@ module Relaton
32
32
 
33
33
  # Clear database
34
34
  def clear
35
- FileUtils.rm_rf Dir.glob "#{dir}/*" if @ext == "xml" # unless it's static DB
35
+ return if Relaton.configuration.api_mode
36
+
37
+ FileUtils.rm_rf Dir.glob "#{dir}/*" if @ext == "xml" # if it's static DB
36
38
  end
37
39
 
38
40
  # Save item
@@ -43,21 +45,10 @@ module Relaton
43
45
  delete key
44
46
  return
45
47
  end
46
-
47
- prefix_dir = "#{@dir}/#{prefix(key)}"
48
- FileUtils::mkdir_p prefix_dir unless Dir.exist? prefix_dir
49
- set_version prefix_dir
50
- file_safe_write "#{filename(key)}.#{ext(value)}", value
51
- end
52
-
53
- # @param value [String]
54
- # @return [String]
55
- def ext(value)
56
- case value
57
- when /^not_found/ then "notfound"
58
- when /^redirection/ then "redirect"
59
- else @ext
60
- end
48
+ /^(?<pref>[^(]+)(?=\()/ =~ key.downcase
49
+ prefix_dir = "#{@dir}/#{pref}"
50
+ file = "#{filename(key)}.#{ext(value)}"
51
+ @storage.save prefix_dir, file, value
61
52
  end
62
53
 
63
54
  # Read item
@@ -86,7 +77,7 @@ module Relaton
86
77
  value = self[key]
87
78
  return unless value
88
79
 
89
- if value.match? /^not_found/
80
+ if value.match?(/^not_found/)
90
81
  value.match(/\d{4}-\d{2}-\d{2}/).to_s
91
82
  else
92
83
  doc = Nokogiri::XML value
@@ -96,41 +87,21 @@ module Relaton
96
87
 
97
88
  # Returns all items
98
89
  # @return [Array<String>]
99
- def all
100
- Dir.glob("#{@dir}/**/*.{xml,yml,yaml}").sort.map do |f|
101
- content = File.read(f, encoding: "utf-8")
102
- block_given? ? yield(f, content) : content
103
- end
90
+ def all(&block)
91
+ @storage.all(@dir, &block)
104
92
  end
105
93
 
106
94
  # Delete item
107
95
  # @param key [String]
108
96
  def delete(key)
109
- file = filename key
110
- f = search_ext(file)
111
- File.delete f if f
97
+ @storage.delete filename(key)
112
98
  end
113
99
 
114
100
  # Check if version of the DB match to the gem grammar hash.
115
101
  # @param fdir [String] dir pathe to flover cache
116
- # @return [TrueClass, FalseClass]
102
+ # @return [Boolean]
117
103
  def check_version?(fdir)
118
- version_dir = fdir + "/version"
119
- return false unless File.exist? version_dir
120
-
121
- v = File.read version_dir, encoding: "utf-8"
122
- v.strip == grammar_hash(fdir)
123
- end
124
-
125
- # Set version of the DB to the gem grammar hash.
126
- # @param fdir [String] dir pathe to flover cache
127
- # @return [Relaton::DbCache]
128
- def set_version(fdir)
129
- file_version = "#{fdir}/version"
130
- unless File.exist? file_version
131
- file_safe_write file_version, grammar_hash(fdir)
132
- end
133
- self
104
+ @storage.check_version? fdir
134
105
  end
135
106
 
136
107
  # if cached reference is undated, expire it after 60 days
@@ -144,112 +115,54 @@ module Relaton
144
115
  year || Date.today - date < 60
145
116
  end
146
117
 
147
- protected
148
-
149
- # @param fdir [String] dir pathe to flover cache
150
- # @return [String]
151
- def grammar_hash(fdir)
152
- type = fdir.split("/").last
153
- Relaton::Registry.instance.by_type(type)&.grammar_hash
154
- end
155
-
156
118
  # Reads file by a key
157
119
  #
158
120
  # @param key [String]
159
121
  # @return [String, NilClass]
160
122
  def get(key)
161
- file = filename key
162
- return unless (f = search_ext(file))
163
-
164
- File.read(f, encoding: "utf-8")
123
+ @storage.get filename(key), static: @ext == "yml"
165
124
  end
166
125
 
167
126
  private
168
127
 
169
- # Check if a file content is redirection
170
- #
171
- # @prarm value [String] file content
172
- # @return [String, NilClass] redirection code or nil
173
- def redirect?(value)
174
- %r{redirection\s(?<code>.*)} =~ value
175
- code
128
+ # @param value [String]
129
+ # @return [String]
130
+ def ext(value)
131
+ case value
132
+ when /^not_found/ then "notfound"
133
+ when /^redirection/ then "redirect"
134
+ else @ext
135
+ end
176
136
  end
177
137
 
178
138
  # Return item's file name
179
139
  # @param key [String]
180
140
  # @return [String]
181
141
  def filename(key)
182
- prefcode = key.downcase.match /^(?<prefix>[^\(]+)\((?<code>[^\)]+)/
142
+ prefcode = key.downcase.match(/^(?<prefix>[^(]+)\((?<code>[^)]+)/)
183
143
  fn = if prefcode
184
- "#{prefcode[:prefix]}/#{prefcode[:code].gsub(/[-:\s\/\()]/, '_').squeeze('_')}"
144
+ "#{prefcode[:prefix]}/#{prefcode[:code].gsub(/[-:\s\/()]/, '_')
145
+ .squeeze('_')}"
185
146
  else
186
147
  key.gsub(/[-:\s]/, "_")
187
148
  end
188
149
  "#{@dir}/#{fn.sub(/(,|_$)/, '')}"
189
150
  end
190
151
 
152
+ # Check if a file content is redirection
191
153
  #
192
- # Checks if there is file with xml or txt extension and return filename with
193
- # the extension.
194
- #
195
- # @param file [String]
196
- # @return [String, NilClass]
197
- def search_ext(file)
198
- if File.exist?("#{file}.#{@ext}")
199
- "#{file}.#{@ext}"
200
- elsif File.exist? "#{file}.notfound"
201
- "#{file}.notfound"
202
- elsif File.exist? "#{file}.redirect"
203
- "#{file}.redirect"
204
- end
154
+ # @prarm value [String] file content
155
+ # @return [String, NilClass] redirection code or nil
156
+ def redirect?(value)
157
+ %r{redirection\s(?<code>.*)} =~ value
158
+ code
205
159
  end
206
160
 
207
161
  # Return item's subdir
208
162
  # @param key [String]
209
163
  # @return [String]
210
- def prefix(key)
211
- key.downcase.match(/^[^\(]+(?=\()/).to_s
212
- end
213
-
214
- # @param file [String]
215
- # @content [String]
216
- def file_safe_write(file, content)
217
- File.open file, File::RDWR | File::CREAT, encoding: "UTF-8" do |f|
218
- Timeout.timeout(10) { f.flock File::LOCK_EX }
219
- f.write content
220
- end
221
- end
222
-
223
- class << self
224
- private
225
-
226
- def global_bibliocache_name
227
- "#{Dir.home}/.relaton/cache"
228
- end
229
-
230
- def local_bibliocache_name(cachename)
231
- return nil if cachename.nil?
232
-
233
- cachename = "relaton" if cachename.empty?
234
- "#{cachename}/cache"
235
- end
236
-
237
- public
238
-
239
- # Initialse and return relaton instance, with local and global cache names
240
- # local_cache: local cache name; none created if nil; "relaton" created
241
- # if empty global_cache: boolean to create global_cache
242
- # flush_caches: flush caches
243
- def init_bib_caches(opts) # rubocop:disable Metrics/CyclomaticComplexity
244
- globalname = global_bibliocache_name if opts[:global_cache]
245
- localname = local_bibliocache_name(opts[:local_cache])
246
- localname = "relaton" if localname&.empty?
247
- if opts[:flush_caches]
248
- FileUtils.rm_rf globalname unless globalname.nil?
249
- FileUtils.rm_rf localname unless localname.nil?
250
- end
251
- Relaton::Db.new(globalname, localname)
252
- end
253
- end
164
+ # def prefix(key)
165
+ # key.downcase.match(/^[^(]+(?=\()/).to_s
166
+ # end
254
167
  end
255
168
  end