Die Klasse Database stellt eine einheitliche
Schnittstelle auf Lingo-Datenbanken bereit. Die Identifizierung der
Datenbank erfolgt über die ID der Datenbank, so wie sie in der
Sprachkonfigurationsdatei de.lang unter
language/dictionary/databases hinterlegt ist.
Das Lesen und Schreiben der Datenbank erfolgt über die Funktionen []() und []=().
# File lib/lingo/database.rb, line 74 def initialize(id, lingo) @id, @lingo, @config, @db = id, lingo, lingo.database_config(id), nil @srcfile = Lingo.find(:dict, @config['name'], relax: true) @crypter = @config.has_key?('crypt') && Crypter.new begin @stofile = Lingo.find(:store, @srcfile) FileUtils.mkdir_p(File.dirname(@stofile)) rescue SourceFileNotFoundError => err @stofile = skip_ext = err.id backend = backend_from_file(@stofile) unless err.name rescue NoWritableStoreError backend = HashStore end use_backend(backend, skip_ext) init_cachable convert unless uptodate? end
# File lib/lingo/database.rb, line 66 def open(*args, &block) new(*args).open(&block) end
# File lib/lingo/database.rb, line 58 def register(klass, ext, prio = -1, meth = true) BACKENDS.insert(prio, name = klass.name[%r::(\w+)Store\z/, 1]) Array(ext).each { |i| BACKEND_BY_EXT[i.prepend('.')] = name } klass.const_set(:EXT, ext) klass.class_eval('def store_ext; EXT; end', __FILE__, __LINE__) if meth end
# File lib/lingo/database.rb, line 122 def [](key) val = _val(key) unless closed? return unless val # Äquvalenzklassen behandeln val.split(FLD_SEP).map { |v| v =~ INDEX_PATTERN ? _val(v) : v }.compact.join(FLD_SEP).split(FLD_SEP) end
# File lib/lingo/database.rb, line 132 def []=(key, val) return if closed? val = val.dup val.concat(retrieve(key)) if hit?(key) val.sort! val.uniq! store(key, val) arg = [key, val.join(FLD_SEP)] _set(*@crypter ? @crypter.encode(*arg) : arg) end
# File lib/lingo/database.rb, line 109 def close @db.close unless closed? @db = nil self end
# File lib/lingo/database.rb, line 96 def closed? @db.nil? || _closed? end
# File lib/lingo/database.rb, line 100 def open @db = _open if closed? block_given? ? yield(self) : self rescue => err raise DatabaseError.new(:open, @stofile, err) ensure close if @db && block_given? end
# File lib/lingo/database.rb, line 116 def to_h {}.tap { |hash| @db.each { |key, val| hash[key.force_encoding(ENC).freeze] = val.force_encoding(ENC) } unless closed? } end
# File lib/lingo/database.rb, line 187 def _clear File.delete(@stofile) if File.exist?(@stofile) end
# File lib/lingo/database.rb, line 195 def _closed? @db.closed? end
# File lib/lingo/database.rb, line 203 def _get(key) @db[key] end
# File lib/lingo/database.rb, line 191 def _open raise NotImplementedError end
# File lib/lingo/database.rb, line 199 def _set(key, val) @db[key] = val end
# File lib/lingo/database.rb, line 207 def _val(key) if val = _get(@crypter ? @crypter.digest(key) : key) val.force_encoding(ENC) @crypter ? @crypter.decode(key, val) : val end end
# File lib/lingo/database.rb, line 163 def backend_from_file(file) ext = File.extname(file) mod = BACKEND_BY_EXT[ext] or raise BackendNotFoundError.new(file) get_backend(mod) or raise BackendNotAvailableError.new(mod, file) end
# File lib/lingo/database.rb, line 218 def convert(verbose = @lingo.config.stderr.tty?) src = Source.get(@config.fetch('txt-format', 'key_value'), @id, @lingo) if lex = @config['use-lex'] a = [{ 'source' => lex.split(SEP_RE), 'mode' => @config['lex-mode'] }, @lingo] d, g = Language::Dictionary.new(*a), Language::Grammar.new(*a); a = nil sep, block = ' ', lambda { |f| (r = d.find_word(f)).unknown? && (c = (r = g.find_compound(f)).compo_form) ? c.form : r.norm } end ShowProgress.new(self, src.size, verbose) { |progress| create { src.each { |key, val| progress[src.pos] if key key.chomp!('.') if lex && key.include?(sep) k = key.split(sep).map!(&block).join(sep) c = k.count(sep) + 1 self[k.split(sep)[0, 3].join(sep)] = ["#{KEY_REF}#{c}"] if c > 3 key, val = k, val.map { |v| v.start_with?('#') ? key + v : v } end end src.set(self, key, val) } uptodate! } } end
# File lib/lingo/database.rb, line 182 def create _clear open { yield } end
# File lib/lingo/database.rb, line 158 def get_backend(mod) self.class.const_get("#{mod}Store") if Object.const_defined?(mod) rescue TypeError, NameError end
# File lib/lingo/database.rb, line 178 def uptodate! @db[SYS_KEY] = @source_key.call end
# File lib/lingo/database.rb, line 170 def uptodate?(file = @stofile) src = Pathname.new(@srcfile) @source_key = lambda { [src.size, src.mtime].join(FLD_SEP) } sys_key = open { @db[SYS_KEY] } if File.exist?(file) sys_key && (!src.exist? || sys_key == @source_key.call) end
# File lib/lingo/database.rb, line 148 def use_backend(backend = nil, skip_ext = false) [ENV['LINGO_BACKEND'], *BACKENDS].each { |mod| backend = get_backend(mod) and break if mod } unless backend extend(@backend = backend || HashStore) @stofile << store_ext if !skip_ext && respond_to?(:store_ext) end
# File lib/lingo/database.rb, line 214 def warn(*msg) @lingo.warn(*msg) end