-# $Id: ZOOM.pod,v 1.30 2006-03-09 12:57:19 mike Exp $
+# $Id: ZOOM.pod,v 1.40 2006-11-03 09:49:38 mike Exp $
use strict;
use warnings;
anyway; but knowing that the same code is running is reassuring.)
The ZOOM module provides two enumerations (C<ZOOM::Error> and
-C<ZOOM::Event>), two utility functions C<diag_str()> and C<event()> in
-the C<ZOOM> package itself, and eight classes:
+C<ZOOM::Event>), three utility functions C<diag_str()>, C<event_str()>
+and C<event()> in the C<ZOOM> package itself, and eight classes:
C<ZOOM::Exception>,
C<ZOOM::Options>,
C<ZOOM::Connection>,
C<ZOOM::ScanSet>
and
C<ZOOM::Package>.
-Of these, the Query class is abstract, and has three concrete
+Of these, the Query class is abstract, and has four concrete
subclasses:
C<ZOOM::Query::CQL>,
-C<ZOOM::Query::PQF>
+C<ZOOM::Query::PQF>,
+C<ZOOM::Query::CQL2RPN>
and
-C<ZOOM::Query::CQL2RPN>.
+C<ZOOM::Query::CCL2RPN>.
Finally, it also provides a
C<ZOOM::Query::Log>
module which supplies a useful general-purpose logging facility.
irrespective of whether it is a member of the C<ZOOM::Error>
enumeration or drawn from the BIB-1 diagnostic set.
-=head2 ZOOM::event()
+=head2 ZOOM::event_str()
-B<Warning.>
-Lark's vomit. Do not read this section.
+ $msg = ZOOM::event_str(ZOOM::Event::RECV_APDU);
- $which = ZOOM::event([ $conn1, $conn2, $conn3 ]);
+Returns a human-readable English-language string corresponding to the
+event code that is its own parameter. This works for any value of the
+C<ZOOM::Event> enumeration.
+
+=head2 ZOOM::event()
+
+ $connsRef = [ $conn1, $conn2, $conn3 ];
+ $which = ZOOM::event($connsRef);
+ $ev = $connsRef->[$which-1]->last_event()
+ if ($which != 0);
Used only in complex asynchronous applications, this function takes a
reference to a list of Connection objects, waits until an event
into the list; 0 is returned if no event occurs within the longest
timeout specified by the C<timeout> options of all the connections.
-B<Warning.>
-This function is not yet implemented.
+See the section below on asynchronous applications.
=head1 CLASSES
including those that must be set before connecting such as
authentication tokens.
+The server-name string is of the form:
+
=over 4
=item
=item http
-SRW connection using SOAP over HTTP.
+SRU connection over HTTP.
=back
-Support for SRU will follow in the fullness of time.
+If the C<http> scheme is used, the particular SRU flavour to be used
+may be specified by the C<sru> option, which takes the following
+values:
+
+=over 4
+
+=item soap
+
+SRU over SOAP (i.e. what used to be called SRW).
+This is the default.
+
+=item get
+
+"SRU Classic" (i.e. SRU over HTTP GET).
+
+=item post
+
+SRU over HTTP POST.
+
+=back
If an error occurs, an exception is thrown. This may indicate a
networking problem (e.g. the host is not found or unreachable), or a
$options = new ZOOM::Options();
$options->option(implementationName => "my client");
+ $options->option(implementationId => 12345);
$conn = create ZOOM::Connection($options)
+ # or
+ $conn = create ZOOM::Connection(implementationName => "my client",
+ implementationId => 12345);
+
$conn->connect($host, 0);
The usual Connection constructor, C<new()> brings a new object into
existence and forges the connection to the server all in one
operation, which is often what you want. For applications that need
-more control, however, these two method separate the two steps,
+more control, however, these two methods separate the two steps,
allowing additional steps in between such as the setting of options.
C<create()> creates and returns a new Connection object, which is
I<not> connected to any server. It may be passed an options block, of
type C<ZOOM::Options> (see below), into which options may be set
-before or after the creation of the Connection. The connection to the
-server may then be forged by the C<connect()> method, the arguments of
-which are the same as those of the C<new()> constructor.
+before or after the creation of the Connection. Alternatively and
+equivalently, C<create()> may be passed a list of key-value option
+pairs directly. The connection to the server may then be forged by
+the C<connect()> method, the arguments of which are the same as those
+of the C<new()> constructor.
=head4 error_x() / errcode() / errmsg() / addinfo() / diagset()
Returns a C<ZOOM::Event> enumerated value indicating the type of the
last event that occurred on the connection. This is used only in
-complex asynchronous applications - see the section below on
-C<ZOOM::Event> for more information.
-
-B<Warning.>
-This method has not been tested.
+complex asynchronous applications - see the sections below on the
+C<ZOOM::Event> enumeration and asynchronous applications.
=head4 destroy()
=head4 render()
- print $rec->render()
+ print $rec->render();
+ print $rec->render("charset=latin1,utf8");
Returns a human-readable representation of the record. Beyond that,
no promises are made: careful programs should not make assumptions
about the format of the returned string.
+If the optional argument is provided, then it is interpreted as in the
+C<get()> method (q.v.)
+
This method is useful mostly for debugging.
=head4 raw()
- use MARC::Record
+ use MARC::Record;
$raw = $rec->raw();
$marc = new_from_usmarc MARC::Record($raw);
+ $trans = $rec->render("charset=latin1,utf8");
Returns an opaque blob of data that is the raw form of the record.
Exactly what this is, and what you can do with it, varies depending on
module; GRS-1 record will be ... gosh, what an interesting question.
But no-one uses GRS-1 any more, do they?
+If the optional argument is provided, then it is interpreted as in the
+C<get()> method (q.v.)
+
+=head4 get()
+
+ $raw = $rec->get("raw");
+ $rendered = $rec->get("render");
+ $trans = $rec->get("render;charset=latin1,utf8");
+ $trans = $rec->get("render", "charset=latin1,utf8");
+
+This is the underlying method used by C<render()> and C<raw()>, and
+which in turn delegates to the C<ZOOM_record_get()> function of the
+underlying ZOOM-C library. Most applications will find it more
+natural to work with C<render()> and C<raw()>.
+
+C<get()> may be called with either one or two arguments. The
+two-argument form is syntactic sugar: the two arguments are simply
+joined with a semi-colon to make a single argument, so the third and
+fourth example invocations above are equivalent. The second argument
+(or portion of the first argument following the semicolon) is used in
+the C<type> argument of C<ZOOM_record_get()>, as described in
+http://www.indexdata.com/yaz/doc/zoom.records.tkl
+This is useful primarily for invoking the character-set transformation
+- in the examples above, from ISO Latin-1 to UTF-8 Unicode.
+
=head4 clone() / destroy()
$rec = $rs->record($i);
configuration file is included in the ZOOM-Perl distribution, in the
file C<samples/cql/pqf.properties>
+=item ZOOM::Query::CCL2RPN
+
+Implements CCL by compiling it on the client-side into a Z39.50 Type-1
+(RPN) query, and sending that. Because the compilation is done on the
+client side, a configuration file is required to direct the mapping of
+CCL constructs such as index names and boolean operators into Type-1
+query attributes. An example CCL configuration file is included in
+the ZOOM-Perl distribution, in the file C<samples/ccl/default.bib>
+
+CCL is syntactically very similar to CQL, but much looser. While CQL
+is an entirely precise language in which each possible query has
+rigorously defined semantics, and is thus suitable for transfer as
+part of a protocol, CCL is best deployed as a human-facing UI
+language.
+
=back
See the description of the C<Query> class in the ZOOM Abstract
Connection and be retrieved using C<$conn-E<gt>errcode()> and related
methods.
+ $conn->option(cclfile => "samples/ccl/default.bib");
+ # or
+ $conn->option(cclqual => "ti u=4 s=pw\nab u=62 s=pw");
+ $q = new ZOOM::Query::CCL2RPN('ti=dinosaur', $conn);
+
+For the C<ZOOM::Query::CCL2RPN> subclass, too, the Connection must be
+passed into the constructor, for the same reasons as when client-side
+CQL compilation is used. The C<cclqual> option, if defined, gives a
+CCL qualification specification inline; otherwise, the contents of the
+file named by the C<cclfile> option are used.
+
=head4 sortby()
$q->sortby("1=4 >i 1=21 >s");
C<UNSUPPORTED_PROTOCOL>,
C<UNSUPPORTED_QUERY>,
C<INVALID_QUERY>,
+C<CQL_PARSE>,
+C<CQL_TRANSFORM>,
+C<CCL_CONFIG>,
+C<CCL_PARSE>,
C<CREATE_QUERY>,
C<QUERY_CQL>,
C<QUERY_PQF>,
return an indication of the last event that occurred on a particular
connection. It always returns a value drawn from this enumeration,
that is, one of C<NONE>, C<CONNECT>, C<SEND_DATA>, C<RECV_DATA>,
-C<TIMEOUT>, C<UNKNOWN>, C<SEND_APDU>, C<RECV_APDU>, C<RECV_RECORD> or
-C<RECV_SEARCH>.
+C<TIMEOUT>, C<UNKNOWN>, C<SEND_APDU>, C<RECV_APDU>, C<RECV_RECORD>,
+C<RECV_SEARCH> or C<ZEND>.
-You almost certainly don't need to know about this. Frankly, I'm not
-sure how to use it myself.
+See the section below on asynchronous applications.
=head1 LOGGING
The log-level argument may be either a numeric value, as returned from
C<module_level()>, or a string containing the module name.
+=head1 ASYNCHRONOUS APPLICATIONS
+
+Although asynchronous applications are conceptually complex, the ZOOM
+support for them is provided through a very simple interface,
+consisting of one option (C<async>), one function (C<ZOOM::event()>),
+one Connection method (C<last_event()> and an enumeration
+(C<ZOOM::Event>).
+
+The approach is as follows:
+
+=over 4
+
+=item Initialisation
+
+Create several connections to the various servers, each of them having
+the option C<async> set, and with whatever additional options are
+required - e.g. the piggyback retrieval record-count can be set so
+that records will be returned in search responses.
+
+=item Operations
+
+Send searches to the connections, request records, etc.
+
+=item Event harvesting
+
+Repeatedly call C<ZOOM::event()> to discover what responses are being
+received from the servers. Each time this function returns, it
+indicates which of the connections has fired; this connection can then
+be interrogated with the C<last_event()> method to discover what event
+has occurred, and the return value - an element of the C<ZOOM::Event>
+enumeration - can be tested to determine what to do next. For
+example, the C<ZEND> event indicates that no further operations are
+outstanding on the connection, so any fetched records can now be
+immediately obtained.
+
+=back
+
+Here is a very short program (omitting all error-checking!) which
+demonstrates this process. It parallel-searches three servers (or more
+of you add them the list), displaying the first record in the
+result-set of each server as soon as it becomes available.
+
+ use ZOOM;
+ @servers = ('z3950.loc.gov:7090/Voyager',
+ 'z3950.indexdata.com:210/gils',
+ 'agricola.nal.usda.gov:7190/Voyager');
+ for ($i = 0; $i < @servers; $i++) {
+ $z[$i] = new ZOOM::Connection($servers[$i], 0,
+ async => 1, # asynchronous mode
+ count => 1, # piggyback retrieval count
+ preferredRecordSyntax => "usmarc");
+ $r[$i] = $z[$i]->search_pqf("mineral");
+ }
+ while (($i = ZOOM::event(\@z)) != 0) {
+ $ev = $z[$i-1]->last_event();
+ print("connection ", $i-1, ": ", ZOOM::event_str($ev), "\n");
+ if ($ev == ZOOM::Event::ZEND) {
+ $size = $r[$i-1]->size();
+ print "connection ", $i-1, ": $size hits\n";
+ print $r[$i-1]->record(0)->render()
+ if $size > 0;
+ }
+ }
+
=head1 SEE ALSO
The ZOOM abstract API,