# $Header: /home/cvsroot/NetZ3950/Z3950.pm,v 1.22 2003/05/07 10:10:00 mike Exp $ package Net::Z3950; use strict; use Carp; use vars qw($VERSION @ISA @EXPORT $AUTOLOAD); require Exporter; require DynaLoader; require AutoLoader; @ISA = qw(Exporter DynaLoader); $VERSION = '0.34'; sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant() # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my $constname; ($constname = $AUTOLOAD) =~ s/.*:://; croak "& not defined" if $constname eq 'constant'; my $val = constant($constname, @_ ? $_[0] : 0); if ($! != 0) { if ($! =~ /Invalid/) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { croak "Your vendor has not defined Net::Z3950 macro $constname"; } } no strict 'refs'; *$AUTOLOAD = sub () { $val }; goto &$AUTOLOAD; } bootstrap Net::Z3950 $VERSION; =head1 NAME Net::Z3950 - Perl extension for talking to Z39.50 servers. =head1 SYNOPSIS (This code blocks in reads: see below for sample non-blocking code which allows multiple servers to be searched in parallel.) use Net::Z3950; $conn = new Net::Z3950::Connection('server.host.name', 210) or die $!; $rs = $conn->search('au=kernighan or su=unix') or die $conn->errmsg(); my $n = $rs->size(); print "found $n records:\n"; foreach $i (1..$n) { $rec = $rs->record($i) or die $rs->errmsg(); print $rec->render(); } $conn->close(); =head1 DESCRIPTION This module provides a Perl interface to the Z39.50 information retrieval protocol (aka. ISO 23950), a mature and powerful protocol used in application domains as diverse as bibliographic information, geo-spatial mapping, museums and other cultural heritage information, and structured vocabulary navigation. C is an implementation of the Perl binding for ZOOM, the Z39.50 Objct Orientation Model. Bindings for the same abstract API are, or will be, available in other languages including C, C++, Java and Tcl. Two basic approaches are possible to building clients with this module: =over 4 =item * The simple synchronous approach considers blocking reads acceptable, and therefore allows a straightforward style of imperative programming. This approach is suitable for clients which only talk to one server at a time, and is exemplified by the code in the SYNOPSIS section above. =item * The more complex asynchronous approach, appropriate for clients which multiplex simultaneous connections, requires a slightly less familiar event-driven programming style, as exemplified in the ASYNCHRONOUS SYNOPSIS section below. =back (The simpler synchronous interface functions are implemented as a thin layer on top of the asynchronous functions.) =head1 ASYNCHRONOUS SYNOPSIS (This code does not block in reads, and so is suitable for broadcast clients which search multiple servers simultaneously: see above for simpler sample code that blocks in reads.) I<### To be written> =cut # Define the operation-code enumeration. The values here are chosen # to be in a distinctive range (i.e. 3950 plus a small integer) so # that if they are misused in another context, they're easy to spot. package Net::Z3950::Op; sub Error { 3951 } sub Init { 3952 } sub Search { 3953 } sub Get { 3954 } package Net::Z3950; # Define the record-syntax enumeration. These values must be kept # synchronised with the values implied by the oid_value enumeration in # the header file "yaz/oid.h" package Net::Z3950::RecordSyntax; sub UNIMARC { 16 } sub INTERMARC { 17 } sub CCF { 18 } sub USMARC { 19 } sub UKMARC { 20 } sub NORMARC { 21 } sub LIBRISMARC { 22 } sub DANMARC { 23 } sub FINMARC { 24 } sub MAB { 25 } sub CANMARC { 26 } sub SBN { 27 } sub PICAMARC { 28 } sub AUSMARC { 29 } sub IBERMARC { 30 } sub CATMARC { 31 } sub MALMARC { 32 } sub EXPLAIN { 33 } sub SUTRS { 34 } sub OPAC { 35 } sub SUMMARY { 36 } sub GRS0 { 37 } sub GRS1 { 38 } sub EXTENDED { 39 } sub TEXT_HTML { 70 } sub TEXT_XML { 80 } sub APPLICATION_XML { 81 } package Net::Z3950; # Define the reason-for-decodeAPDU()-failure enumeration. This must # be kept synchronised with the values #defined in "yazwrap/yazwrap.h" package Net::Z3950::Reason; sub EOF { 23951 } # read EOF from connection (server gone) sub Incomplete { 23952 } # read bytes, but not yet a whole APDU sub Malformed { 23953 } # couldn't decode APDU (malformed) sub BadAPDU { 23954 } # APDU was well-formed but unrecognised sub Error { 23955 } # some other error (consult errno) package Net::Z3950; # Define the query-type enumeration. This must be kept synchronised # with the values #defined in "yazwrap/yazwrap.h" package Net::Z3950::QueryType; sub Prefix { 39501 } # Yaz's "@attr"-ish forward-Polish notation sub CCL { 39502 } # Send CCL string to server ``as is'' sub CCL2RPN { 39503 } # Convert CCL to RPN (type-1) locally package Net::Z3950; ### Move to Net::Z3950::APDU.pm? Not currently used anyway # Define the result-set-status enumeration, used by the # `resultSetStatus' field in the Net::Z3950::SearchResponse class in cases # where `searchStatus' is false (indicating failure). This must be # kept synchronised with the ASN.1 for the structure described in # section 3.2.2.1.11 of the Z39.50 standard itself. package Net::Z3950::ResultSetStatus; sub Subset { 1 } sub Interim { 2 } sub None { 3 } package Net::Z3950; ### Move to Net::Z3950::APDU.pm? # Define the present-status enumeration, used by the `presentStatus' # field in the Net::Z3950::SearchResponse class in cases where # `searchStatus' is true (indicating success). This must be kept # synchronised with the ASN.1 for the structure described in section # 3.2.2.1.11 of the Z39.50 standard itself. package Net::Z3950::PresentStatus; sub Success { 0 } sub Partial1 { 1 } sub Partial2 { 2 } sub Partial3 { 3 } sub Partial4 { 4 } sub Failure { 5 } package Net::Z3950; # Include modules implementing Net::Z3950 classes use Net::Z3950::Manager; use Net::Z3950::Connection; use Net::Z3950::APDU; use Net::Z3950::ResultSet; use Net::Z3950::Record; =head1 FUNCTIONS The C module itself provides very few functions: most of the functionality is provided by the daughter modules included by C - C, C, I =cut =head2 errstr() $errcode = $conn->errcode(); $errmsg = Net::Z3950::errmsg($errcode); print "error $errcode ($errmsg)\n"; Returns an English-language string describing the error indicated by the Z39.50 BIB-1 diagnostic error code I<$errcode>. =cut sub errstr { my($errcode) = @_; return "not yet available (try again later)" if $errcode == 0; return diagbib1_str($errcode); } =head2 opstr() $str = Net::Z3950::opstr($conn->errop()); print "error occurred in $str\n"; Returns an English-language string describing the operation indicated by the argument, which must be one of the C constants described in the documentation for the C class's C method. =cut sub opstr { my($op) = @_; return "error" if $op == Net::Z3950::Op::Error; return "search" if $op == Net::Z3950::Op::Search; return "get" if $op == Net::Z3950::Op::Get; return "unknown op " . $op; } =head1 AUTHOR Mike Taylor Emike@tecc.co.ukE First version Tuesday 23rd May 2000. =head1 SEE ALSO The ZOOM API for Z39.50, of which this is an implementation, is fully specified at http://zoom.z3950.org where links to other implementations may also be found. This module is built on Index Data's Yaz (Yet Another Z39.50) toolkit, which is freely available at http://indexdata.dk/yaz/ Index Data also provide a variety of other useful Z39.50 software including the free server/database Zebra, the commercial server/database Z'mbol, a Tcl interface to Z39.50 called Ir/Tcl, and a free web-to-Z39.50 gateway called Zap. See their home page at http://indexdata.dk/ The best source of information about Z39.50 itself is the official Mainenance Agency at http://lcweb.loc.gov/z3950/agency/ =cut 1; __END__