relaton 1.7.5 → 1.8.pre2

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 +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