relaton 1.7.5 → 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 (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 +3 -0
  6. data/lib/relaton/config.rb +7 -3
  7. data/lib/relaton/db.rb +199 -99
  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 +23 -23
  23. data/spec/vcr_cassetes/api_relaton_org.yml +33 -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 +10 -10
  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 +133 -68
  31. data/spec/vcr_cassetes/fisp_140.yml +4 -4
  32. data/spec/vcr_cassetes/gb_t_20223_2006.yml +9 -9
  33. data/spec/vcr_cassetes/iec_60050_102_2007.yml +30 -28
  34. data/spec/vcr_cassetes/iec_combined_included.yml +81 -85
  35. data/spec/vcr_cassetes/ieee_528_2019.yml +19 -17
  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 +23 -23
  39. data/spec/vcr_cassetes/iso_19115_1.yml +20 -20
  40. data/spec/vcr_cassetes/iso_19115_1_2.yml +42 -42
  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 +45 -45
  44. data/spec/vcr_cassetes/itu_combined_included.yml +813 -681
  45. data/spec/vcr_cassetes/ogc_19_025r1.yml +1325 -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 +4 -4
  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 +126 -51
  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: a8c7a7a21ac269d14d0d4532e4a7ee8d28fa9446bf7c7b59e0ddb71b5a21b681
4
- data.tar.gz: 31332da1783e054318a74808417dd8d3cc924a31f73cd7f35470b9d769c9aad8
3
+ metadata.gz: 7613bdf8be768f76e3e24d8727210075cd8ad8d4e24924ec5d19d28473cd933f
4
+ data.tar.gz: 1332d1463afd07385d3aacb917a2f621b572e802b25ec64d5d5f87781b6c6ef6
5
5
  SHA512:
6
- metadata.gz: 0a8cdaf3cad2830b90f27305a788a2710bcf542f47fa4a56a374cce17519626f9f5914c3c2f5ab37eb3488cfb6949ea55af3e6e9fd3ce3dce9e0aaf653be8e5f
7
- data.tar.gz: 7b7d5e8e20cdc91c3e0d30ce0492d79c937a772b7d67c7041f04447210f3bf2045a3c95472d61a3bb7760e9d45b96e948979ba4b4ef4bbc497678cc270badf05
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/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"
@@ -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,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 = nil # "http://0.0.0.0:9292"
20
24
  end
21
25
  end
22
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,51 +6,66 @@ 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
- @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,31 @@ 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
+ 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
+
164
195
  # @param file [String] file path
165
196
  # @param yml [String] content in YAML format
166
197
  # @param text [String, nil] text to serach
@@ -187,20 +218,27 @@ module Relaton
187
218
  end
188
219
 
189
220
  # @param file [String] file path
190
- # @param content [String] content in XML or YAmL format
221
+ # @param content [String] content in XML or YAML format
191
222
  # @param edition [String, nil] edition to filter
192
223
  # @param year [Integer, nil] year to filter
193
224
  # @return [BibliographicItem, nil]
194
225
  def search_edition_year(file, content, edition, year) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
195
226
  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 })
227
+ item = if file.match?(/xml$/) then processor.from_xml(content)
228
+ else processor.hash_to_bib(YAML.safe_load(content))
229
+ end
230
+ item if (edition.nil? || item.edition == edition) && (year.nil? ||
231
+ item.date.detect { |d| d.type == "published" && d.on(:year).to_s == year.to_s })
199
232
  end
200
233
 
234
+ #
235
+ # Look up text in the XML elements attributes and content
236
+ #
201
237
  # @param xml [String] content in XML format
202
238
  # @param text [String, nil] text to serach
239
+ #
203
240
  # @return [Boolean]
241
+ #
204
242
  def match_xml_text(xml, text)
205
243
  %r{((?<attr>=((?<apstr>')|"))|>).*?#{text}.*?(?(<attr>)(?(<apstr>)'|")|<)}mi.match?(xml)
206
244
  end
@@ -211,18 +249,19 @@ module Relaton
211
249
  #
212
250
  # @param opts [Hash] options
213
251
  # @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
252
+ # @option opts [Boolean] :keep_year If undated reference should return
253
+ # actual reference with year
215
254
  # @option opts [Integer] :retries (1) Number of network retries
216
255
  #
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]
256
+ # @return [nil, RelatonBib::BibliographicItem,
257
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
258
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
259
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
260
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
261
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
222
262
  # 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
263
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
264
+ def combine_doc(code, year, opts, stdclass) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
226
265
  if (refs = code.split " + ").size > 1
227
266
  reltype = "derivedFrom"
228
267
  reldesc = nil
@@ -233,11 +272,13 @@ module Relaton
233
272
  end
234
273
 
235
274
  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
275
+ updates = check_bibliocache(refs[0], year, opts, stdclass)
276
+ if updates
277
+ doc.relation << RelatonBib::DocumentRelation.new(bibitem: updates, type: "updates")
278
+ end
279
+ divider = stdclass == :relaton_itu ? " " : "/"
239
280
  refs[1..-1].each_with_object(doc) do |c, d|
240
- bib = check_bibliocache("#{ref}/#{c}", year, opts, stdclass)
281
+ bib = check_bibliocache(refs[0] + divider + c, year, opts, stdclass)
241
282
  if bib
242
283
  d.relation << RelatonBib::DocumentRelation.new(type: reltype, description: reldesc, bibitem: bib)
243
284
  end
@@ -251,11 +292,9 @@ module Relaton
251
292
  return name if /^(urn:)?#{processor.prefix}/i.match?(code) ||
252
293
  processor.defaultprefix.match(code)
253
294
  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(', ')}.
295
+ allowed = @registry.processors.reduce([]) { |m, (_k, v)| m << v.prefix }
296
+ Util.log <<~WARN, :info
297
+ [relaton] #{code} does not have a recognised prefix: #{allowed.join(', ')}.
259
298
  See https://github.com/relaton/relaton/ for instructions on prefixing and wrapping document identifiers to disambiguate them.
260
299
  WARN
261
300
  end
@@ -267,7 +306,8 @@ module Relaton
267
306
  #
268
307
  # @param opts [Hash]
269
308
  # @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
309
+ # @option opts [Boolean] :keep_year If undated reference should return
310
+ # actual reference with year
271
311
  # @option opts [Integer] :retries (1) Number of network retries
272
312
  #
273
313
  # @param stdClass [Symbol]
@@ -292,16 +332,18 @@ module Relaton
292
332
 
293
333
  # @param entry [String] XML string
294
334
  # @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]
335
+ # @return [nil, RelatonBib::BibliographicItem,
336
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
337
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
338
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
339
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
340
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
300
341
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
301
- # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
302
- # RelatonW3c::W3cBibliographicItem
342
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
303
343
  def bib_retval(entry, stdclass)
304
- entry.nil? || entry.match?(/^not_found/) ? nil : @registry.processors[stdclass].from_xml(entry)
344
+ unless entry.nil? || entry.match?(/^not_found/)
345
+ @registry.processors[stdclass].from_xml(entry)
346
+ end
305
347
  end
306
348
 
307
349
  # @param code [String]
@@ -309,22 +351,24 @@ module Relaton
309
351
  #
310
352
  # @param opts [Hash]
311
353
  # @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
354
+ # @option opts [Boolean] :keep_year If undated reference should return
355
+ # actual reference with year
313
356
  # @option opts [Integer] :retries (1) Number of network retries
314
357
  #
315
358
  # @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]
359
+ # @return [nil, RelatonBib::BibliographicItem,
360
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
361
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
362
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
363
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
364
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
321
365
  # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
322
- # RelatonOmg::OmgBibliographicItem RelatinUn::UnBibliographicItem,
323
- # RelatonW3c::W3cBibliographicItem
366
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
324
367
  def check_bibliocache(code, year, opts, stdclass) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
325
368
  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
369
+ if (yaml = @static_db[id])
370
+ return @registry.processors[stdclass].hash_to_bib YAML.safe_load(yaml)
371
+ end
328
372
 
329
373
  db = @local_db || @db
330
374
  altdb = @local_db && @db ? @db : nil
@@ -350,24 +394,29 @@ module Relaton
350
394
  bib_retval(db[id], stdclass)
351
395
  end
352
396
 
397
+ #
353
398
  # @param code [String]
354
399
  # @param year [String]
355
400
  #
356
401
  # @param opts [Hash]
357
402
  # @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
403
+ # @option opts [Boolean] :keep_year If undated reference should return
404
+ # actual reference with year
359
405
  # @option opts [Integer] :retries (1) Number of network retries
360
406
  #
361
407
  # @param stdclass [Symbol]
362
408
  # @param db [Relaton::DbCache,`NilClass]
363
409
  # @param id [String] docid
410
+ #
364
411
  # @return [String]
412
+ #
365
413
  def new_bib_entry(code, year, opts, stdclass, **args) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
366
414
  bib = net_retry(code, year, opts, stdclass, opts.fetch(:retries, 1))
367
415
  bib_id = bib&.docidentifier&.first&.id
368
416
 
369
417
  # 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})")}}
418
+ if args[:db] && args[:id] &&
419
+ bib_id && args[:id] !~ %r{#{Regexp.quote("(#{bib_id})")}}
371
420
  bid = std_id(bib.docidentifier.first.id, nil, {}, stdclass).first
372
421
  args[:db][bid] ||= bib_entry bib
373
422
  "redirection #{bid}"
@@ -375,8 +424,27 @@ module Relaton
375
424
  end
376
425
  end
377
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
+ #
378
439
  # @raise [RelatonBib::RequestError]
440
+ # @return [RelatonBib::BibliographicItem]
441
+ #
379
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
380
448
  @registry.processors[stdclass].get(code, year, opts)
381
449
  rescue RelatonBib::RequestError => e
382
450
  raise e unless retries > 1
@@ -384,22 +452,23 @@ module Relaton
384
452
  net_retry(code, year, opts, stdclass, retries - 1)
385
453
  end
386
454
 
387
- # @param bib [RelatonGb::GbBibliongraphicItem, RelatonIsoBib::IsoBibliographicItem,
388
- # RelatonIetf::IetfBibliographicItem, RelatonItu::ItuBibliographicItem,
389
- # RelatonNist::NistBibliongraphicItem, RelatonOgc::OgcBibliographicItem]
455
+ # @param bib [RelatonBib::BibliographicItem,
456
+ # RelatonIsoBib::IsoBibliographicItem, RelatonItu::ItuBibliographicItem,
457
+ # RelatonIetf::IetfBibliographicItem, RelatonIec::IecBibliographicItem,
458
+ # RelatonIeee::IeeeBibliographicItem, RelatonNist::NistBibliongraphicItem,
459
+ # RelatonGb::GbbibliographicItem, RelatonOgc::OgcBibliographicItem,
460
+ # RelatonCalconnect::CcBibliographicItem, RelatinUn::UnBibliographicItem,
461
+ # RelatonBipm::BipmBibliographicItem, RelatonIho::IhoBibliographicItem,
462
+ # RelatonOmg::OmgBibliographicItem, RelatonW3c::W3cBibliographicItem]
390
463
  # @return [String] XML or "not_found mm-dd-yyyy"
391
464
  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
465
+ bib.respond_to?(:to_xml) ? bib.to_xml(bibdata: true) : "not_found #{Date.today}"
397
466
  end
398
467
 
399
468
  # @param dir [String, nil] DB directory
400
469
  # @param type [Symbol]
401
470
  # @return [Relaton::DbCache, NilClass]
402
- def open_cache_biblio(dir, type: :static)
471
+ def open_cache_biblio(dir, type: :static) # rubocop:disable Metrics/MethodLength
403
472
  return nil if dir.nil?
404
473
 
405
474
  db = DbCache.new dir, type == :static ? "yml" : "xml"
@@ -408,9 +477,11 @@ module Relaton
408
477
  Dir["#{dir}/*/"].each do |fdir|
409
478
  next if db.check_version?(fdir)
410
479
 
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."
480
+ FileUtils.rm_rf(fdir, secure: true)
481
+ Util.log(
482
+ "[relaton] WARNING: cache #{fdir}: version is obsolete and cache is "\
483
+ "cleared.", :warning
484
+ )
414
485
  end
415
486
  db
416
487
  end
@@ -419,8 +490,37 @@ module Relaton
419
490
  # @option qwp [Queue] :queue The queue of references to fetch
420
491
  # @option qwp [Relaton::WorkersPool] :workers_pool The pool of workers
421
492
  def process_queue(qwp)
422
- while args = qwp[:queue].pop
423
- qwp[:workers_pool] << args
493
+ while args = qwp[:queue].pop; qwp[:workers_pool] << args end
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"
424
524
  end
425
525
  end
426
526
  end