X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=lib%2FZOOM.pm;h=0b13a2b50dee17d80bacf3d49b9194fb3297d6d6;hb=b0a0bb77b9ea56c10672a382d69969f6c2333d25;hp=523d73ca0680cf0948b0731187f1553b2bed1d47;hpb=5b9518b8d0aa435e6d19021c039a7f66406da676;p=ZOOM-Perl-moved-to-github.git diff --git a/lib/ZOOM.pm b/lib/ZOOM.pm index 523d73c..0b13a2b 100644 --- a/lib/ZOOM.pm +++ b/lib/ZOOM.pm @@ -1,4 +1,4 @@ -# $Id: ZOOM.pm,v 1.17 2005-11-09 17:08:03 mike Exp $ +# $Id: ZOOM.pm,v 1.28 2006-04-03 14:00:00 mike Exp $ use strict; use warnings; @@ -7,7 +7,6 @@ use Net::Z3950::ZOOM; package ZOOM; - # Member naming convention: hash-element names which begin with an # underscore represent underlying ZOOM-C object descriptors; those # which lack them represent Perl's ZOOM objects. (The same convention @@ -40,6 +39,8 @@ sub TIMEOUT { Net::Z3950::ZOOM::ERROR_TIMEOUT } sub UNSUPPORTED_PROTOCOL { Net::Z3950::ZOOM::ERROR_UNSUPPORTED_PROTOCOL } sub UNSUPPORTED_QUERY { Net::Z3950::ZOOM::ERROR_UNSUPPORTED_QUERY } sub INVALID_QUERY { Net::Z3950::ZOOM::ERROR_INVALID_QUERY } +sub CQL_PARSE { Net::Z3950::ZOOM::ERROR_CQL_PARSE } +sub CQL_TRANSFORM { Net::Z3950::ZOOM::ERROR_CQL_TRANSFORM } # The following are added specifically for this OO interface sub CREATE_QUERY { 20001 } sub QUERY_CQL { 20002 } @@ -47,6 +48,8 @@ sub QUERY_PQF { 20003 } sub SORTBY { 20004 } sub CLONE { 20005 } sub PACKAGE { 20006 } +sub SCANTERM { 20007 } +sub LOGLEVEL { 20008 } # The "Event" package contains constants returned by last_event() package ZOOM::Event; @@ -81,16 +84,19 @@ sub diag_str { return "can't clone record"; } elsif ($code == ZOOM::Error::PACKAGE) { return "can't create package"; + } elsif ($code == ZOOM::Error::SCANTERM) { + return "can't retrieve term from scan-set"; + } elsif ($code == ZOOM::Error::LOGLEVEL) { + return "unregistered log-level"; } return Net::Z3950::ZOOM::diag_str($code); } -### More of the ZOOM::Exception instantiations should use this sub _oops { - my($code, $addinfo) = @_; + my($code, $addinfo, $diagset) = @_; - die new ZOOM::Exception($code, diag_str($code), $addinfo); + die new ZOOM::Exception($code, diag_str($code), $addinfo, $diagset); } # ---------------------------------------------------------------------------- @@ -99,13 +105,13 @@ package ZOOM::Exception; sub new { my $class = shift(); - my($code, $message, $addinfo) = @_; - ### support diag-set, too + my($code, $message, $addinfo, $diagset) = @_; return bless { code => $code, message => $message, addinfo => $addinfo, + diagset => $diagset || "ZOOM", }, $class; } @@ -124,6 +130,21 @@ sub addinfo { return $this->{addinfo}; } +sub diagset { + my $this = shift(); + return $this->{diagset}; +} + +sub render { + my $this = shift(); + my $res = "ZOOM error " . $this->code() . ' "' . $this->message() . '"'; + $res .= ' (addinfo: "' . $this->addinfo() . '")' if $this->addinfo(); + $res .= " from diag-set '" . $this->diagset() . "'" if $this->diagset(); + return $res; +} + +# This means that untrapped exceptions render nicely. +use overload '""' => \&render; # ---------------------------------------------------------------------------- @@ -253,33 +274,29 @@ package ZOOM::Connection; sub new { my $class = shift(); - my($host, $port) = @_; + my($host, $port, @options) = @_; - my $_conn = Net::Z3950::ZOOM::connection_new($host, $port); - my($errcode, $errmsg, $addinfo) = (undef, "dummy", "dummy"); - $errcode = Net::Z3950::ZOOM::connection_error($_conn, $errmsg, $addinfo); - die new ZOOM::Exception($errcode, $errmsg, $addinfo) if $errcode; - - return bless { + my $_conn = Net::Z3950::ZOOM::connection_new($host, $port || 0); + my $conn = bless { host => $host, port => $port, _conn => $_conn, }; -} -sub create { - my $class = shift(); - my($options) = @_; + while (@options >= 2) { + my $key = shift(@options); + my $val = shift(@options); + $conn->option($key, $val); + } - my $_conn = Net::Z3950::ZOOM::connection_create($options->_opts()); - return bless { - host => undef, - port => undef, - _conn => $_conn, - }; + die "Odd number of options specified" + if @options; + + $conn->_check(); + return $conn; } -# PRIVATE to this class +# PRIVATE to this class and to ZOOM::Query::CQL2RPN::new() sub _conn { my $this = shift(); @@ -290,6 +307,28 @@ sub _conn { return $_conn; } +sub _check { + my $this = shift(); + + my($errcode, $errmsg, $addinfo, $diagset) = (undef, "x", "x", "x"); + $errcode = Net::Z3950::ZOOM::connection_error_x($this->_conn(), $errmsg, + $addinfo, $diagset); + die new ZOOM::Exception($errcode, $errmsg, $addinfo, $diagset) + if $errcode; +} + +sub create { + my $class = shift(); + my($options) = @_; + + my $_conn = Net::Z3950::ZOOM::connection_create($options->_opts()); + return bless { + host => undef, + port => undef, + _conn => $_conn, + }; +} + sub error_x { my $this = shift(); @@ -314,15 +353,18 @@ sub addinfo { return Net::Z3950::ZOOM::connection_addinfo($this->_conn()); } +sub diagset { + my $this = shift(); + return Net::Z3950::ZOOM::connection_diagset($this->_conn()); +} + sub connect { my $this = shift(); my($host, $port) = @_; + $port = 0 if !defined $port; Net::Z3950::ZOOM::connection_connect($this->_conn(), $host, $port); - my($errcode, $errmsg, $addinfo) = (undef, "dummy", "dummy"); - $errcode = Net::Z3950::ZOOM::connection_error($this->_conn(), - $errmsg, $addinfo); - die new ZOOM::Exception($errcode, $errmsg, $addinfo) if $errcode; + $this->_check(); # No return value } @@ -357,11 +399,7 @@ sub search { my $_rs = Net::Z3950::ZOOM::connection_search($this->_conn(), $query->_query()); - my($errcode, $errmsg, $addinfo) = (undef, "dummy", "dummy"); - $errcode = Net::Z3950::ZOOM::connection_error($this->_conn(), - $errmsg, $addinfo); - die new ZOOM::Exception($errcode, $errmsg, $addinfo) if $errcode; - + $this->_check(); return _new ZOOM::ResultSet($this, $query, $_rs); } @@ -370,27 +408,29 @@ sub search_pqf { my($pqf) = @_; my $_rs = Net::Z3950::ZOOM::connection_search_pqf($this->_conn(), $pqf); - my($errcode, $errmsg, $addinfo) = (undef, "dummy", "dummy"); - $errcode = Net::Z3950::ZOOM::connection_error($this->_conn(), - $errmsg, $addinfo); - die new ZOOM::Exception($errcode, $errmsg, $addinfo) if $errcode; - + $this->_check(); return _new ZOOM::ResultSet($this, $pqf, $_rs); } -sub scan { +sub scan_pqf { my $this = shift(); my($startterm) = @_; my $_ss = Net::Z3950::ZOOM::connection_scan($this->_conn(), $startterm); - my($errcode, $errmsg, $addinfo) = (undef, "dummy", "dummy"); - $errcode = Net::Z3950::ZOOM::connection_error($this->_conn(), - $errmsg, $addinfo); - die new ZOOM::Exception($errcode, $errmsg, $addinfo) if $errcode; - + $this->_check(); return _new ZOOM::ScanSet($this, $startterm, $_ss); } +sub scan { + my $this = shift(); + my($query) = @_; + + my $_ss = Net::Z3950::ZOOM::connection_scan1($this->_conn(), + $query->_query()); + $this->_check(); + return _new ZOOM::ScanSet($this, $query, $_ss); +} + sub package { my $this = shift(); my($options) = @_; @@ -465,6 +505,25 @@ sub new { } +package ZOOM::Query::CQL2RPN; +our @ISA = qw(ZOOM::Query); + +sub new { + my $class = shift(); + my($string, $conn) = @_; + + my $q = Net::Z3950::ZOOM::query_create() + or ZOOM::_oops(ZOOM::Error::CREATE_QUERY); + # check() throws the exception we want; but we only want it on failure! + Net::Z3950::ZOOM::query_cql2rpn($q, $string, $conn->_conn()) == 0 + or $conn->_check(); + + return bless { + _query => $q, + }, $class; +} + + package ZOOM::Query::PQF; our @ISA = qw(ZOOM::Query); @@ -542,7 +601,12 @@ sub record { my($which) = @_; my $_rec = Net::Z3950::ZOOM::resultset_record($this->_rs(), $which); - ### Check for error -- but how? + $this->{conn}->_check(); + + # Even if no error has occurred, I think record() might + # legitimately return undef if we're running in asynchronous mode + # and the record just hasn't been retrieved yet. This goes double + # for record_immediate(). return undef if !defined $_rec; # For some reason, I have to use the explicit "->" syntax in order @@ -557,7 +621,8 @@ sub record_immediate { my $_rec = Net::Z3950::ZOOM::resultset_record_immediate($this->_rs(), $which); - ### Check for error -- but how? + $this->{conn}->_check(); + # The record might legitimately not be there yet return undef if !defined $_rec; return ZOOM::Record->_new($this, $which, $_rec); @@ -575,6 +640,7 @@ sub records { my $raw = Net::Z3950::ZOOM::resultset_records($this->_rs(), $start, $count, $return_records); + # By design, $raw may be undefined (if $return_records is true) return undef if !defined $raw; # We need to package up the returned records in ZOOM::Record objects @@ -645,22 +711,27 @@ sub _rec { sub render { my $this = shift(); - my $len = 0; - my $string = Net::Z3950::ZOOM::record_get($this->_rec(), "render", $len); - # I don't think we need '$len' at all. ### Probably the Perl-to-C - # glue code should use the value of `len' as well as the opaque - # data-pointer returned, to ensure that the SV contains all of the - # returned data and does not stop at the first NUL character in - # binary data. Carefully check the ZOOM_record_get() documentation. - return $string; + return $this->get("render", @_); } sub raw { my $this = shift(); + return $this->get("raw", @_); +} + +sub get { + my $this = shift(); + my($type, $args) = @_; + + $type = "$type;$args" if defined $args; my $len = 0; - my $string = Net::Z3950::ZOOM::record_get($this->_rec(), "raw", $len); - # See comment about $len in render() + my $string = Net::Z3950::ZOOM::record_get($this->_rec(), $type, $len); + # I don't think we need '$len' at all. ### Probably the Perl-to-C + # glue code should use the value of `len' as well as the opaque + # data-pointer returned, to ensure that the SV contains all of the + # returned data and does not stop at the first NUL character in + # binary data. Carefully check the ZOOM_record_get() documentation. return $string; } @@ -698,7 +769,12 @@ sub _new { return bless { conn => $conn, - startterm => $startterm, + startterm => $startterm,# This is not currently used, which is + # just as well since it could be + # either a string (when the SS is + # created with scan()) or a + # ZOOM::Query object (when it's + # created with scan1()) _ss => $_ss, }, $class; } @@ -737,8 +813,9 @@ sub term { my($occ, $len) = (0, 0); my $term = Net::Z3950::ZOOM::scanset_term($this->_ss(), $which, - $occ, $len); - return undef if !defined $term; + $occ, $len) + or ZOOM::_oops(ZOOM::Error::SCANTERM); + die "length of term '$term' differs from returned len=$len" if length($term) != $len; @@ -751,8 +828,9 @@ sub display_term { my($occ, $len) = (0, 0); my $term = Net::Z3950::ZOOM::scanset_display_term($this->_ss(), $which, - $occ, $len); - return undef if !defined $term; + $occ, $len) + or ZOOM::_oops(ZOOM::Error::SCANTERM); + die "length of display term '$term' differs from returned len=$len" if length($term) != $len; @@ -815,10 +893,7 @@ sub send { my($type) = @_; Net::Z3950::ZOOM::package_send($this->_p(), $type); - my($errcode, $errmsg, $addinfo) = (undef, "dummy", "dummy"); - $errcode = Net::Z3950::ZOOM::connection_error($this->{conn}->_conn(), - $errmsg, $addinfo); - die new ZOOM::Exception($errcode, $errmsg, $addinfo) if $errcode; + $this->{conn}->_check(); } sub destroy { @@ -829,4 +904,41 @@ sub destroy { } +# There follows trivial support for YAZ logging. This is wired out +# into the Net::Z3950::ZOOM package, and we here provide wrapper +# functions -- nothing more than aliases, really -- in the ZOOM::Log +# package. There really is no point in inventing an OO interface. +# +# Passing @_ directly to the underlying Net::Z3950::ZOOM::* functions +# doesn't work, for reasons that I can't begin to fathom, and that +# don't particularly interest me. Unpacking into scalars and passing +# those _does_ work, so that's what we do. + +package ZOOM::Log; + +sub mask_str { my($a) = @_; Net::Z3950::ZOOM::yaz_log_mask_str($a); } +sub module_level { my($a) = @_; Net::Z3950::ZOOM::yaz_log_module_level($a); } +sub init { my($a, $b, $c) = @_; + Net::Z3950::ZOOM::yaz_log_init($a, $b, $c) } +sub init_file { my($a) = @_; Net::Z3950::ZOOM::yaz_log_init_file($a) } +sub init_level { my($a) = @_; Net::Z3950::ZOOM::yaz_log_init_level($a) } +sub init_prefix { my($a) = @_; Net::Z3950::ZOOM::yaz_log_init_prefix($a) } +sub time_format { my($a) = @_; Net::Z3950::ZOOM::yaz_log_time_format($a) } +sub init_max_size { my($a) = @_; Net::Z3950::ZOOM::yaz_log_init_max_size($a) } + +sub log { + my($level, @message) = @_; + + if ($level !~ /^(0x)?\d+$/) { + # Assuming its log-level name, we look it up. + my $num = module_level($level); + ZOOM::_oops(ZOOM::Error::LOGLEVEL, $level) + if $num == 0; + $level = $num; + } + + Net::Z3950::ZOOM::yaz_log($level, join("", @message)); +} + + 1;