lib/relaton/db.rb in relaton-0.2.5 vs lib/relaton/db.rb in relaton-0.2.6
- old
+ new
@@ -1,39 +1,40 @@
-require "pstore"
+# require "pstore"
require_relative "registry"
+require_relative 'db_cache'
module Relaton
class RelatonError < StandardError; end
class Db
SUPPORTED_GEMS = %w[isobib ietfbib gbbib iecbib].freeze
- # @param global_cache [String] filename of global DB
- # @param local_cache [String] filename of local DB
+ # @param global_cache [String] directory of global DB
+ # @param local_cache [String] directory of local DB
def initialize(global_cache, local_cache)
register_gems
+ @registry = Relaton::Registry.instance
@db = open_cache_biblio(global_cache)
@local_db = open_cache_biblio(local_cache, global: false)
@db_name = global_cache
@local_db_name = local_cache
- @registry = Relaton::Registry.instance
end
def register_gems
- puts "[relaton] detecting backends:"
+ puts "[relaton] Info: detecting backends:"
SUPPORTED_GEMS.each do |b|
- puts b
+ # puts b
begin
require b
rescue LoadError
- puts "[relaton] backend #{b} not present"
+ puts "[relaton] Error: backend #{b} not present"
end
end
end
# The class of reference requested is determined by the prefix of the code:
- # GB Standard for gbbib, IETF for ietfbib, ISO for isobib, IEC or IEV for iecbib,
+ # GB Standard for gbbib, IETF for ietfbib, ISO for isobib, IEC or IEV for iecbib,
# @param code [String] the ISO standard Code to look up (e.g. "ISO 9000")
# @param year [String] the year the standard was published (optional)
# @param opts [Hash] options; restricted to :all_parts if all-parts reference is required
# @return [String] Relaton XML serialisation of reference
def fetch(code, year = nil, opts = {})
@@ -61,148 +62,159 @@
# @param key [String]
# @return [Hash]
def load_entry(key)
unless @local_db.nil?
- entry = @local_db.transaction { @local_db[key] }
+ entry = @local_db[key]
return entry if entry
end
- @db.transaction { @db[key] }
+ @db[key]
end
# @param key [String]
# @param value [Hash]
# @option value [Date] "fetched"
# @option value [IsoBibItem::IsoBibliographicItem] "bib"
def save_entry(key, value)
- @db.nil? or @db.transaction { @db[key] = value }
- @local_db.nil? or @local_db.transaction { @local_db[key] = value }
+ @db.nil? || (@db[key] = value)
+ @local_db.nil? || (@local_db[key] = value)
end
# list all entries as a serialization
+ # @return [String]
def to_xml
db = @local_db || @db || return
- db.transaction do
- Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
- xml.documents do
- db.roots.reject { |key| key == :version }.
- each { |key| db[key]&.fetch("bib")&.to_xml(xml, {}) }
- end
- end.to_xml
- end
+ Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
+ xml.documents do
+ xml.parent.add_child db.all.join(" ")
+ end
+ end.to_xml
end
private
+ # @param code [String] code of standard
+ # @return [Symbol] standard class name
def standard_class(code)
@registry.processors.each do |name, processor|
return name if /^#{processor.prefix}/.match(code) ||
- processor.defaultprefix.match(code)
+ processor.defaultprefix.match(code)
end
allowed = @registry.processors.reduce([]) do |m, (_k, v)|
m << v.prefix
end
warn "#{code} does not have a recognised prefix: #{allowed.join(', ')}"
nil
end
# TODO: i18n
+ # Fofmat ID
+ # @param code [String]
+ # @param year [String]
+ # @param opts [Hash]
+ # @param stdClass [Symbol]
+ # @return [Array]
def std_id(code, year, opts, stdclass)
prefix, code = strip_id_wrapper(code, stdclass)
ret = code
ret += ":#{year}" if year
ret += " (all parts)" if opts[:all_parts]
["#{prefix}(#{ret})", code]
end
+ # Find prefix and clean code
+ # @param code [String]
+ # @param stdClass [Symbol]
+ # @return [Array]
def strip_id_wrapper(code, stdclass)
prefix = @registry.processors[stdclass].prefix
code = code.sub(/^#{prefix}\((.+)\)$/, "\\1")
[prefix, code]
end
- def bib_retval(entry)
- entry["bib"] == "not_found" ? nil : entry["bib"]
+ def bib_retval(entry, stdclass)
+ entry =~ /^not_found/ ? nil : @registry.processors[stdclass].from_xml(entry)
end
# @param code [String]
# @param year [String]
# @param opts [Hash]
# @param stdclass [Symbol]
def check_bibliocache(code, year, opts, stdclass)
id, searchcode = std_id(code, year, opts, stdclass)
db = @local_db || @db
altdb = @local_db && @db ? @db : nil
- return bib_retval(new_bib_entry(searchcode, year, opts, stdclass)) if db.nil?
- db.transaction do
- db.delete(id) unless valid_bib_entry?(db[id], year)
- if altdb
- altdb.transaction do
- db[id] ||= altdb[id]
- db[id] ||= new_bib_entry(searchcode, year, opts, stdclass)
- altdb[id] = db[id] if !valid_bib_entry?(altdb[id], year)
- bib_retval(db[id])
- end
- else
- db[id] ||= new_bib_entry(searchcode, year, opts, stdclass)
- bib_retval(db[id])
- end
+ return bib_retval(new_bib_entry(searchcode, year, opts, stdclass), stdclass) if db.nil?
+
+ db.delete(id) unless db.valid_entry?(id, year)
+ if altdb
+ db[id] ||= altdb[id]
+ db[id] ||= new_bib_entry(searchcode, year, opts, stdclass)
+ altdb[id] = db[id] if !altdb.valid_entry?(id, year)
+ else
+ db[id] ||= new_bib_entry(searchcode, year, opts, stdclass)
end
+ bib_retval(db[id], stdclass)
end
# hash uses => , because the hash is imported from JSON
# @param code [String]
# @param year [String]
# @param opts [Hash]
# @param stdclass [Symbol]
# @return [Hash]
def new_bib_entry(code, year, opts, stdclass)
bib = @registry.processors[stdclass].get(code, year, opts)
- bib = "not_found" if bib.nil?
- { "fetched" => Date.today, "bib" => bib }
+ bib = "not_found #{Date.today}" if bib.nil? || bib.empty?
+ bib
end
# if cached reference is undated, expire it after 60 days
# @param bib [Hash]
# @param year [String]
- def valid_bib_entry?(bib, year)
- bib&.is_a?(Hash) && bib&.has_key?("bib") && bib&.has_key?("fetched") &&
- (year || Date.today - bib["fetched"] < 60)
- end
+ # def valid_bib_entry?(bib, year)
+ # bib&.is_a?(Hash) && bib&.has_key?("bib") && bib&.has_key?("fetched") &&
+ # (year || Date.today - bib["fetched"] < 60)
+ # end
- # @param filename [String] DB filename
+ # @param dir [String] DB directory
# @param global [TrueClass, FalseClass]
# @return [PStore]
- def open_cache_biblio(filename, global: true)
- return nil if filename.nil?
- db = PStore.new filename
- if File.exist? filename
+ def open_cache_biblio(dir, global: true)
+ return nil if dir.nil?
+ db = DbCache.new dir
+ if File.exist? dir
if global
- unless check_cache_version(db)
- File.delete filename
+ unless db.check_version?
+ FileUtils.rm_rf dir + '/.'
warn "Global cache version is obsolete and cleared."
end
- set_cache_version db
- elsif check_cache_version(db) then db
+ db.set_version
+ elsif db.check_version? then db
else
warn "Local cache version is obsolete."
nil
end
- else
- set_cache_version db
+ else db.set_version
end
end
- def check_cache_version(cache_db)
- cache_db.transaction { cache_db[:version] == VERSION }
- end
+ # Check if version of the DB match to the gem version.
+ # @param cache_db [String] DB directory
+ # @return [TrueClass, FalseClass]
+ # def check_cache_version(cache_db)
+ # cache_db.transaction { cache_db[:version] == VERSION }
+ # end
- def set_cache_version(cache_db)
- unless File.exist? cache_db.path
- cache_db.transaction { cache_db[:version] = VERSION }
- end
- cache_db
- end
+ # Set version of the DB to the gem version.
+ # @param cache_db [String] DB directory
+ # @return [Pstore]
+ # def set_cache_version(cache_db)
+ # unless File.exist? cache_db.path
+ # cache_db.transaction { cache_db[:version] = VERSION }
+ # end
+ # cache_db
+ # end
# @param enstry [String] entry in XML format
# @return [IsoBibItem::IsoBibliographicItem]
# def from_xml(entry)
# IsoBibItem.from_xml entry # will be unmarshaller