relaton 1.7.8 → 1.8.pre4

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