class Alexandria::BookProviders::Z3950Provider
Public Class Methods
new(name = "Z3950", fullname = "Z39.50")
click to toggle source
Calls superclass method
Alexandria::BookProviders::AbstractProvider::new
# File lib/alexandria/book_providers/z3950.rb, line 20 def initialize(name = "Z3950", fullname = "Z39.50") super prefs.add("hostname", _("Hostname"), "") prefs.add("port", _("Port"), 7090) prefs.add("database", _("Database"), "") prefs.add("record_syntax", _("Record syntax"), "USMARC", ["USMARC", "UNIMARC", "SUTRS"]) prefs.add("username", _("Username"), "", nil, false) prefs.add("password", _("Password"), "", nil, false) prefs.add("charset", _("Charset encoding"), "ISO-8859-1") # HACK : piggybacking support prefs.add("piggyback", "Piggyback", true, [true, false]) prefs.read end
Public Instance Methods
books_from_resultset(resultset, isbn)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 56 def books_from_resultset(resultset, isbn) case prefs["record_syntax"] when /MARC$/ books_from_marc(resultset, isbn) when "SUTRS" books_from_sutrs(resultset) else raise NoResultsError end end
search(criterion, type)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 36 def search(criterion, type) prefs.read criterion = criterion.encode(prefs["charset"]) isbn = type == SEARCH_BY_ISBN ? criterion : nil criterion = canonicalise_criterion(criterion, type) conn_count = request_count(type) resultset = search_records(criterion, type, conn_count) log.debug { "total #{resultset.length}" } results = books_from_resultset(resultset, isbn) raise NoResultsError if results.empty? type == SEARCH_BY_ISBN ? results.first : results end
url(_book)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 52 def url(_book) nil end
Private Instance Methods
books_from_marc(resultset, isbn)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 122 def books_from_marc(resultset, isbn) results = [] resultset[0..9].each do |record| marc_txt = record.render(prefs["charset"], "UTF-8") log.debug { marc_txt } if $DEBUG File.open(",marc.txt", "wb") do |f| # DEBUG f.write(marc_txt) end end book = nil begin mappings = Alexandria::PseudoMarcParser::USMARC_MAPPINGS if prefs["hostname"] == "z3950.bnf.fr" mappings = Alexandria::PseudoMarcParser::BNF_FR_MAPPINGS end # try pseudo-marc parser first (it seems to have more luck) book = Alexandria::PseudoMarcParser.marc_text_to_book(marc_txt, mappings) if book.nil? # failing that, try the genuine MARC parser book = marc_to_book(marc_txt, isbn) end rescue StandardError => ex log.warn { ex } log.warn { ex.backtrace } end results << [book] unless book.nil? end results end
books_from_sutrs(_resultset)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 78 def books_from_sutrs(_resultset) # SUTRS needs to be decoded separately, because each Z39.50 server has a # different one. raise NoResultsError end
canonicalise_criterion(criterion, type)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 73 def canonicalise_criterion(criterion, type) criterion = Library.canonicalise_isbn(criterion) if type == SEARCH_BY_ISBN criterion end
marc?()
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 155 def marc? prefs["record_syntax"].end_with?("MARC") end
marc_to_book(marc_txt, isbn)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 84 def marc_to_book(marc_txt, isbn) begin marc = MARC::Record.new_from_marc(marc_txt, forgiving: true) rescue StandardError => ex log.error { ex.message } log.error { ex.backtrace.join("> \n") } begin marc = MARC::Record.new(marc_txt) rescue StandardError => ex log.error { ex.message } log.error { ex.backtrace.join("> \n") } raise ex end end log.debug do msg = "Parsing MARC" msg += "\n title: #{marc.title}" msg += "\n authors: #{marc.authors.join(', ')}" msg += "\n isbn: #{marc.isbn}, #{isbn}" msg += "\n publisher: #{marc.publisher}" msg += "\n publish year: #{marc.publish_year}" if marc.respond_to?(:publish_year) msg += "\n edition: #{marc.edition}" msg end return if marc.title.nil? # or marc.authors.empty? isbn ||= marc.isbn isbn = Library.canonicalise_ean(isbn) Book.new(marc.title, marc.authors, isbn, (marc.publisher || ""), marc.respond_to?(:publish_year) ? marc.publish_year.to_i : nil, (marc.edition || "")) end
request_count(type)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 69 def request_count(type) type == SEARCH_BY_ISBN ? 1 : 10 # results to retrieve end
search_records(criterion, type, conn_count)
click to toggle source
# File lib/alexandria/book_providers/z3950.rb, line 159 def search_records(criterion, type, conn_count) options = {} unless prefs["username"].empty? || prefs["password"].empty? options["user"] = prefs["username"] options["password"] = prefs["password"] end hostname = prefs["hostname"] port = prefs["port"].to_i log.debug { "hostname #{hostname} port #{port} options #{options}" } conn = ZOOM::Connection.new(options).connect(hostname, port) conn.database_name = prefs["database"] conn.preferred_record_syntax = prefs["record_syntax"] conn.element_set_name = "F" conn.count = conn_count attr = case type when SEARCH_BY_ISBN then [7] when SEARCH_BY_TITLE then [4] when SEARCH_BY_AUTHORS then [1, 1003] when SEARCH_BY_KEYWORD then [1016] end pqf = "" attr.each { |att| pqf += "@attr 1=#{att} " } pqf += '"' + criterion.upcase + '"' log.debug { "pqf is #{pqf}, syntax #{prefs['record_syntax']}" } begin if prefs.variable_named("piggyback") && !prefs["piggyback"] log.debug { "setting conn.piggyback to false" } conn.piggyback = false end conn.search(pqf) rescue StandardError => ex if /1005/.match?(ex.message) && prefs.variable_named("piggyback") && prefs["piggyback"] log.error { "Z39.50 search failed:: #{ex.message}" } log.info { "Turning off piggybacking for this provider" } prefs.variable_named("piggyback").new_value = false retry end raise ex end end