relaton 2.1.0 → 2.2.0.pre.alpha.1

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/CLAUDE.md +8 -0
  4. data/Gemfile +8 -0
  5. data/lib/relaton/db/cache.rb +232 -0
  6. data/lib/relaton/db/config.rb +24 -0
  7. data/lib/relaton/db/registry.rb +119 -0
  8. data/lib/relaton/db/util.rb +9 -0
  9. data/lib/relaton/db/version.rb +5 -0
  10. data/lib/relaton/db/workers_pool.rb +22 -0
  11. data/lib/relaton/db.rb +21 -206
  12. data/lib/relaton/version.rb +1 -1
  13. data/lib/relaton.rb +2 -10
  14. data/relaton.gemspec +47 -36
  15. data/spec/relaton/config_spec.rb +1 -1
  16. data/spec/relaton/db_cache_spec.rb +4 -4
  17. data/spec/relaton/db_spec.rb +18 -7
  18. data/spec/relaton/registry_spec.rb +39 -39
  19. data/spec/relaton/util_spec.rb +1 -1
  20. data/spec/relaton_meta_spec.rb +25 -0
  21. data/spec/relaton_spec.rb +163 -88
  22. data/spec/spec_helper.rb +2 -2
  23. data/spec/vcr_cassetes/api_relaton_org.yml +8 -8
  24. data/spec/vcr_cassetes/api_relaton_org_unavailable.yml +76 -79
  25. data/spec/vcr_cassetes/cc_dir_10005_2019.yml +80 -77
  26. data/spec/vcr_cassetes/cipm_meeting_43.yml +1372 -1380
  27. data/spec/vcr_cassetes/gb_t_20223_2006.yml +500 -504
  28. data/spec/vcr_cassetes/iso_19115_1.yml +17204 -13047
  29. data/spec/vcr_cassetes/iso_19115_1_2.yml +193 -240
  30. data/spec/vcr_cassetes/iso_19115_1_std.yml +17207 -13050
  31. data/spec/vcr_cassetes/iso_19115_all_parts.yml +116 -160
  32. data/spec/vcr_cassetes/iso_19133_2005.yml +78 -82
  33. data/spec/vcr_cassetes/iso_combined_applied.yml +186 -232
  34. data/spec/vcr_cassetes/iso_combined_included.yml +187 -233
  35. data/spec/vcr_cassetes/ogc_19_025r1.yml +211 -208
  36. data/spec/vcr_cassetes/omg_ami4ccm_1_0.yml +246 -246
  37. data/spec/vcr_cassetes/rfc_8341.yml +1026 -1020
  38. metadata +133 -78
  39. data/.rubocop.yml +0 -12
  40. data/lib/relaton/config.rb +0 -24
  41. data/lib/relaton/db_cache.rb +0 -230
  42. data/lib/relaton/registry.rb +0 -118
  43. data/lib/relaton/util.rb +0 -7
  44. data/lib/relaton/workers_pool.rb +0 -21
  45. data/spec/vcr_cassetes/3gpp_tr_00_01u_umts_3_0_0.yml +0 -12720
  46. data/spec/vcr_cassetes/cie_001_1980.yml +0 -401
  47. data/spec/vcr_cassetes/doi_10_6028_nist_ir_8245.yml +0 -86
  48. data/spec/vcr_cassetes/ecma_6.yml +0 -112
  49. data/spec/vcr_cassetes/en_10160_1999.yml +0 -13624
  50. data/spec/vcr_cassetes/ieee_528_2019.yml +0 -2786
  51. data/spec/vcr_cassetes/iso_dis.yml +0 -157
@@ -1,230 +0,0 @@
1
- require "fileutils"
2
- require "timeout"
3
-
4
- module Relaton
5
- class DbCache
6
- # @return [String]
7
- attr_reader :dir
8
-
9
- # @param dir [String] DB directory
10
- def initialize(dir, ext = "xml")
11
- @dir = dir
12
- @ext = ext
13
- FileUtils::mkdir_p dir
14
- end
15
-
16
- # Move caches to anothe dir
17
- # @param new_dir [String, nil]
18
- # @return [String, nil]
19
- def mv(new_dir)
20
- return unless new_dir && @ext == "xml"
21
-
22
- if File.exist? new_dir
23
- Util.info "target directory exists `#{new_dir}`"
24
- return
25
- end
26
-
27
- FileUtils.mv dir, new_dir
28
- @dir = new_dir
29
- end
30
-
31
- # Clear database
32
- def clear
33
- FileUtils.rm_rf Dir.glob "#{dir}/*"
34
- end
35
-
36
- # Save item
37
- # @param key [String]
38
- # @param value [String] Bibitem xml serialization
39
- def []=(key, value)
40
- if value.nil?
41
- delete key
42
- return
43
- end
44
-
45
- prefix_dir = "#{@dir}/#{prefix(key)}"
46
- FileUtils::mkdir_p prefix_dir
47
- set_version prefix_dir
48
- file_safe_write "#{filename(key)}.#{ext(value)}", value
49
- end
50
-
51
- # @param value [String]
52
- # @return [String]
53
- def ext(value)
54
- case value
55
- when /^not_found/ then "notfound"
56
- when /^redirection/ then "redirect"
57
- else @ext
58
- end
59
- end
60
-
61
- # Read item
62
- # @param key [String]
63
- # @return [String]
64
- def [](key)
65
- value = get(key)
66
- if (code = redirect_code value)
67
- self[code]
68
- else
69
- value
70
- end
71
- end
72
-
73
- #
74
- # Save entry from cache of `db` to this cache.
75
- #
76
- # @param [String] key key of the entry
77
- # @param [Relaton::Db] db database
78
- #
79
- def clone_entry(key, db)
80
- self[key] ||= db.get(key)
81
- if (code = redirect_code get(key))
82
- clone_entry code, db
83
- end
84
- end
85
-
86
- # Return fetched date
87
- # @param key [String]
88
- # @return [String]
89
- def fetched(key)
90
- value = self[key]
91
- return unless value
92
-
93
- if value.match?(/^not_found/)
94
- value.match(/\d{4}-\d{2}-\d{2}/).to_s
95
- else
96
- doc = Nokogiri::XML value
97
- doc.at("/bibitem/fetched|bibdata/fetched")&.text
98
- end
99
- end
100
-
101
- # Returns all items
102
- # @return [Array<String>]
103
- def all(&block)
104
- Dir.glob("#{@dir}/**/*.{xml,yml,yaml}").map do |f|
105
- content = File.read(f, encoding: "utf-8")
106
- block ? yield(f, content) : content
107
- end
108
- end
109
-
110
- # Delete item
111
- # @param key [String]
112
- def delete(key)
113
- file = filename key
114
- f = search_ext file
115
- return unless f
116
-
117
- if File.extname(f) == ".redirect"
118
- code = redirect_code get(key)
119
- delete code if code
120
- end
121
- File.delete f
122
- end
123
-
124
- # Check if version of the DB match to the gem grammar hash.
125
- # @param fdir [String] dir pathe to flover cache
126
- # @return [Boolean]
127
- def check_version?(fdir)
128
- version_dir = "#{fdir}/version"
129
- return false unless File.exist? version_dir
130
-
131
- v = File.read version_dir, encoding: "utf-8"
132
- v.strip == self.class.grammar_hash(fdir)
133
- end
134
-
135
- # if cached reference is undated, expire it after 60 days
136
- # @param key [String]
137
- # @param year [String]
138
- def valid_entry?(key, year)
139
- datestr = fetched key
140
- return false unless datestr
141
-
142
- date = Date.parse datestr
143
- year || Date.today - date < 60
144
- end
145
-
146
- # Reads file by a key
147
- #
148
- # @param key [String]
149
- # @return [String, NilClass]
150
- def get(key)
151
- file = filename key
152
- return unless (f = search_ext(file))
153
-
154
- File.read(f, encoding: "utf-8")
155
- end
156
-
157
- # @param fdir [String] dir pathe to flover cache
158
- # @return [String]
159
- def self.grammar_hash(fdir)
160
- type = fdir.split("/").last
161
- Relaton::Registry.instance.by_type(type)&.grammar_hash
162
- end
163
-
164
- private
165
-
166
- # @param value [String]
167
- # @return [String]
168
- def filename(key)
169
- prefcode = key.downcase.match(/^(?<prefix>[^(]+)\((?<code>[^)]+)/)
170
- fn = if prefcode
171
- "#{prefcode[:prefix]}/#{prefcode[:code].gsub(/[:\s\/()]/,
172
- '_').squeeze('_')}"
173
- else
174
- key.gsub(/[-:\s]/, "_")
175
- end
176
- "#{@dir}/#{fn.sub(/(,|_$)/, '')}"
177
- end
178
-
179
- #
180
- # Checks if there is file with xml or txt extension and return filename with
181
- # the extension.
182
- #
183
- # @param file [String]
184
- # @return [String, NilClass]
185
- def search_ext(file)
186
- if File.exist?("#{file}.#{@ext}")
187
- "#{file}.#{@ext}"
188
- elsif File.exist? "#{file}.notfound"
189
- "#{file}.notfound"
190
- elsif File.exist? "#{file}.redirect"
191
- "#{file}.redirect"
192
- end
193
- end
194
-
195
- # Set version of the DB to the gem grammar hash.
196
- # @param fdir [String] dir pathe to flover cache
197
- def set_version(fdir)
198
- file_version = "#{fdir}/version"
199
- unless File.exist? file_version
200
- file_safe_write file_version, self.class.grammar_hash(fdir)
201
- end
202
- end
203
-
204
- # Return item's file name
205
- # @param key [String]
206
- # @return [String]
207
- def prefix(key)
208
- key.downcase.match(/^[^(]+(?=\()/).to_s
209
- end
210
-
211
- # Check if a file content is redirection
212
- #
213
- # @prarm value [String] file content
214
- # @return [String, NilClass] redirection code or nil
215
- def redirect_code(value)
216
- %r{redirection\s(?<code>.*)} =~ value
217
- code
218
- end
219
-
220
- # @param file [String]
221
- # @content [String]
222
- def file_safe_write(file, content)
223
- File.open file, File::RDWR | File::CREAT, encoding: "UTF-8" do |f|
224
- Timeout.timeout(10) { f.flock File::LOCK_EX }
225
- f.write content
226
- f.flock File::LOCK_UN
227
- end
228
- end
229
- end
230
- end
@@ -1,118 +0,0 @@
1
- require "singleton"
2
-
3
- # class Error < StandardError
4
- # end
5
-
6
- module Relaton
7
- class Registry
8
- SUPPORTED_GEMS = %w[
9
- relaton/gb relaton/iec relaton/ietf relaton/iso
10
- relaton/itu relaton/nist relaton/ogc relaton/calconnect
11
- relaton/omg relaton/un relaton/w3c relaton/ieee
12
- relaton/iho relaton/bipm relaton/ecma relaton/cie
13
- relaton/bsi relaton/cen relaton/iana relaton/3gpp
14
- relaton/oasis relaton/doi relaton/jis relaton/xsf
15
- relaton/ccsds relaton/etsi relaton/isbn relaton/plateau
16
- ].freeze
17
-
18
- include Singleton
19
-
20
- attr_reader :processors
21
-
22
- def initialize
23
- @processors = {}
24
- register_gems
25
- end
26
-
27
- def register_gems
28
- # Util.info("Info: detecting backends:")
29
-
30
- SUPPORTED_GEMS.each do |b|
31
- require "#{b}/processor"
32
- register Kernel.const_get "#{gem_to_module_path(b)}::Processor"
33
- rescue LoadError => e
34
- Util.error "backend #{b} not present\n" \
35
- "#{e.message}\n#{e.backtrace.join "\n"}"
36
- end
37
- end
38
-
39
- def register(processor)
40
- raise Error unless processor < Core::Processor
41
-
42
- p = processor.new
43
- return if processors[p.short]
44
-
45
- Util.debug("processor \"#{p.short}\" registered")
46
- processors[p.short] = p
47
- end
48
-
49
- def find_processor(short)
50
- processors[short.to_sym]
51
- end
52
-
53
- # @return [Array<Symbol>]
54
- def supported_processors
55
- processors.keys
56
- end
57
-
58
- #
59
- # Search a rpocessos by dataset name
60
- #
61
- # @param [String] dataset
62
- #
63
- # @return [Relaton::Core::Processor, nil]
64
- #
65
- def find_processor_by_dataset(dataset)
66
- processors.values.detect { |p| p.datasets&.include? dataset }
67
- end
68
-
69
- #
70
- # Find processor by type
71
- #
72
- # @param type [String]
73
- # @return [Relaton::Core::Processor]
74
- def by_type(type)
75
- processors.values.detect { |v| v.prefix == type&.upcase }
76
- end
77
-
78
- def [](stdclass)
79
- processors[stdclass]
80
- end
81
-
82
- #
83
- # Find processor by reference or prefix
84
- #
85
- # @param [String] ref reference or prefix
86
- #
87
- # @return [Relaton::Core::Processor] processor
88
- #
89
- def processor_by_ref(ref)
90
- processors[class_by_ref(ref)]
91
- end
92
-
93
- #
94
- # Find processor by refernce or prefix
95
- #
96
- # @param ref [String] reference or prefix
97
- #
98
- # @return [Symbol, nil] standard class name
99
- #
100
- def class_by_ref(ref)
101
- ref = Regexp.last_match(1) if ref =~ /^\w+\((.*)\)$/
102
- @processors.each do |class_name, processor|
103
- return class_name if /^(urn:)?#{processor.prefix}\b/i.match?(ref) ||
104
- processor.defaultprefix.match(ref)
105
- end
106
- Util.info "`#{ref}` does not have a recognised prefix", key: ref
107
- nil
108
- end
109
-
110
- private
111
-
112
- def gem_to_module_path(gem_name)
113
- gem_name.split("/").map do |part|
114
- part.capitalize.sub("3gpp", "ThreeGpp")
115
- end.join("::")
116
- end
117
- end
118
- end
data/lib/relaton/util.rb DELETED
@@ -1,7 +0,0 @@
1
- module Relaton
2
- module Util
3
- extend Relaton::Bib::Util
4
-
5
- PROGNAME = "relaton".freeze
6
- end
7
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Relaton
4
- # Workers poll.
5
- class WorkersPool
6
- def initialize(workers = 2, &)
7
- # num_workers = workers < 2 ? 2 : workers
8
- @queue = SizedQueue.new(workers * 2)
9
- @threads = Array.new workers do
10
- Thread.new do
11
- while item = @queue.pop; yield(item) end
12
- end
13
- end
14
- end
15
-
16
- def <<(item)
17
- @queue << item
18
- self
19
- end
20
- end
21
- end