-# $Id: ZOOM.pod,v 1.19 2005-12-13 15:30:26 mike Exp $
+### Add documentation for logging.
+
+# $Id: ZOOM.pod,v 1.26 2005-12-22 11:58:03 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>), a single utility function C<diag_str()> in the C<ZOOM>
-package itself, and eight classes:
+C<ZOOM::Event>), two utility functions C<diag_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 two concrete
+Of these, the Query class is abstract, and has three concrete
subclasses:
-C<ZOOM::Query::CQL>
+C<ZOOM::Query::CQL>,
+C<ZOOM::Query::PQF>
and
-C<ZOOM::Query::PQF>.
+C<ZOOM::Query::CQL2RPN>.
Many useful ZOOM applications can be built using only the Connection,
ResultSet, Record and Exception classes, as in the example
code-snippet above.
you don't need to test for success after each call. See the section
below on the Exception class for details.
-=head1 UTILITY FUNCTION
+=head1 UTILITY FUNCTIONS
=head2 ZOOM::diag_str()
irrespective of whether it is a member of the C<ZOOM::Error>
enumeration or drawn from the BIB-1 diagnostic set.
+=head2 ZOOM::event()
+
+B<Warning.>
+Lark's vomit. Do not read this section.
+
+ $which = ZOOM::event([ $conn1, $conn2, $conn3 ]);
+
+Used only in complex asynchronous applications, this function takes a
+reference to a list of Connection objects, waits until an event
+occurs on any one of them, and returns an integer indicating which of
+the connections it occurred on. The return value is a 1-based index
+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.
+
=head1 CLASSES
The eight ZOOM classes are described here in ``sensible order'':
of records resulting from the search.
Since queries using PQF (Prefix Query Format) are so common, we make
-them a special case by providing a C<search_prefix()> method. This is
+them a special case by providing a C<search_pqf()> method. This is
identical to C<search()> except that it accepts a string containing
the query rather than an object, thereby obviating the need to create
a C<ZOOM::Query::PQF> object. See the documentation of that class for
information about PQF.
-=head4 scan()
+=head4 scan() / scan_pqf()
+
+ $rs = $conn->scan(new ZOOM::Query::CQL('title=dinosaur'));
+ # The next two lines are equivalent
+ $rs = $conn->scan(new ZOOM::Query::PQF('@attr 1=4 dinosaur'));
+ $rs = $conn->scan_pqf('@attr 1=4 dinosaur');
Many Z39.50 servers allow you to browse their indexes to find terms to
search for. This is done using the C<scan> method, which creates and
four words ``Back'', ``Empire'', ``Strikes'' and ``The'', interleaved
with words from other titles in the same index.
-All of this is done by using a single term from the PQF query as the
-C<scan()> argument. (At present, only PQF is supported, although
-there is no reason in principle why CQL and other query syntaxes
-should not be supported in future). The attributes associated with
+All of this is done by using a Query object representing a query of a
+single term as the C<scan()> argument. The attributes associated with
the term indicate which index is to be used, and the term itself
indicates the point in the index at which to start the scan. For
-example, if the argument is C<@attr 1=4 fish>, then
+example, if the argument is the query C<@attr 1=4 fish>, then
=over 4
but overriding this can be useful to get a high-level overview of the
index.
+Since scans using PQF (Prefix Query Format) are so common, we make
+them a special case by providing a C<scan_pqf()> method. This is
+identical to C<scan()> except that it accepts a string containing the
+query rather than an object, thereby obviating the need to create a
+C<ZOOM::Query::PQF> object.
+
=back
=head4 package()
Extended Service. An options block may optionally be passed in. See
the C<ZOOM::Package> documentation.
+=head4 last_event()
+
+ if ($conn->last_event() == ZOOM::Event::CONNECT) {
+ print "Connected!\n";
+ }
+
+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.
+
=head4 destroy()
$conn->destroy()
There is no C<new()> method nor any other explicit constructor. The
only way to create a new ResultSet is by using C<search()> (or
-C<search_prefix()>) on a Connection.
+C<search_pqf()>) on a Connection.
See the description of the C<Result Set> class in the ZOOM Abstract
API at
C<search()> on a Connection; because PQF is such a common special
case, the shortcut Connection method C<search_pqf()> is provided.
-The following Query subclasses are provided, both of the providing the
+The following Query subclasses are provided, each providing the
same set of methods described below:
=over 4
and in a slight out-of-date but nevertheless useful tutorial at
http://zing.z3950.org/cql/intro.html
+=item ZOOM::Query::CQL2RPN
+
+Implements CQL by compiling it on the client-side into a Z39.50
+Type-1 (RPN) query, and sending that. This provides essentially the
+same functionality as C<ZOOM::Query::CQL>, but it will work against
+any standard Z39.50 server rather than only against the small subset
+that support CQL natively. The drawback is that, because the
+compilation is done on the client side, a configuration file is
+required to direct the mapping of CQL constructs such as index names,
+relations and modifiers into Type-1 query attributes. An example CQL
+configuration file is included in the ZOOM-Perl distribution, in the
+file C<samples/cql/pqf.properties>
+
=back
See the description of the C<Query> class in the ZOOM Abstract
=head4 new()
- $q = new ZOOM::Query::CQL('title=dinosaur'));
- $q = new ZOOM::Query::PQF('@attr 1=4 dinosaur'));
+ $q = new ZOOM::Query::CQL('title=dinosaur');
+ $q = new ZOOM::Query::PQF('@attr 1=4 dinosaur');
Creates a new query object, compiling the query passed as its argument
according to the rules of the particular query-type being
instantiated. If compilation fails, an exception is thrown.
Otherwise, the query may be passed to the C<Connection> method
-<search()>.
+C<search()>.
+
+ $conn->option(cqlfile => "samples/cql/pqf.properties");
+ $q = new ZOOM::Query::CQL2RPN('title=dinosaur', $conn);
+
+Note that for the C<ZOOM::Query::CQL2RPN> subclass, the Connection
+must also be passed into the constructor. This is used for two
+purposes: first, its C<cqlfile> option is used to find the CQL
+configuration file that directs the translations into RPN; and second,
+if compilation fails, then diagnostic information is cached in the
+Connection and be retrieved using C<$conn-E<gt>errcode()> and related
+methods.
=head4 sortby()
specification language is the same as the C<yaz> sort-specification
type of the C<ResultSet> method C<sort()>, described above.
-B<It ought to be possible to sort by CQL query, too, but at present
-limitations in the underlying ZOOM-C library make this impossible.>
-
=head4 destroy()
$p->destroy()
=head4 new()
-I<###>
+ $o1 = new ZOOM::Options();
+ $o1and2 = new ZOOM::Options($o1);
+ $o3 = new ZOOM::Options();
+ $o1and3and4 = new ZOOM::Options($o1, $o3);
+
+Creates and returns a new option set. One or two (but no more)
+existing option sets may be passed as arguments, in which case they
+become ``parents'' of the new set, which thereby ``inherits'' their
+options, the values of the first parent overriding those of the second
+when both have a value for the same key. An option set that inherits
+from a parent that has its own parents also inherits the grandparent's
+options, and so on.
-=head4 option()
+=head4 option() / option_binary()
-I<###>
+ $o->option(preferredRecordSyntax => "usmarc");
+ $o->option_binary(iconBlob => "foo\0bar");
+ die if length($o->option_binary("iconBlob") != 7);
-=head4 option_binary()
+These methods are used to get and set options within a set, and behave
+the same way as the same-named C<Connection> methods - see above. As
+with the C<Connection> methods, values passed to and retrieved using
+C<option()> are interpreted as NUL-terminated, while those passed to
+and retrieved from C<option_binary()> are binary-clean.
-I<###>
+=head4 bool()
-=head4 bool() / int()
+ $o->option(x => "T");
+ $o->option(y => "F");
+ assert($o->bool("x", 1));
+ assert(!$o->bool("y", 1));
+ assert($o->bool("z", 1));
-I<###>
+The first argument is a key, and the second is a default value.
+Returns the value associated with the specified key as a boolean, or
+the default value if the key has not been set. The values C<T> (upper
+case) and C<1> are considered true; all other values (including C<t>
+(lower case) and non-zero integers other than one) are considered
+false.
+
+This method is provided in ZOOM-C because in a statically typed
+language it's convenient to have the result returned as an
+easy-to-test type. In a dynamically typed language such as Perl, this
+problem doesn't arise, so C<bool()> is nearly useless; but it is made
+available in case applications need to duplicate the idiosyncratic
+interpretation of truth and falsehood and ZOOM-C uses.
+
+=head4 int()
+
+ $o->option(x => "012");
+ assert($o->int("x", 20) == 12);
+ assert($o->int("y", 20) == 20);
+
+Returns the value associated with the specified key as an integer, or
+the default value if the key has not been set. See the description of
+C<bool()> for why you almost certainly don't want to use this.
=head4 set_int()
-I<###>
+ $o->set_int(x => "29");
+
+Sets the value of the specified option as an integer. Of course, Perl
+happily converts strings to integers on its own, so you can just use
+C<option()> for this, but C<set_int()> is guaranteed to use the same
+string-to-integer conversion as ZOOM-C does, which might occasionally
+be useful. Though I can't imagine how.
=head4 set_callback()
-I<###>
+ sub cb {
+ ($udata, $key) = @;
+ return "$udata-$key-$udata";
+ }
+ $o->set_callback(\&cb, "xyz");
+ assert($o->option("foo") eq "xyz-foo-xyz");
+
+This method allows a callback function to be installed in an option
+set, so that the values of options can be calculated algorithmically
+rather than, as usual, looked up in a table. Along with the callback
+function itself, an additional datum is provided: when an option is
+subsequently looked up, this datum is passed to the callback function
+along with the key; and its return value is returned to the caller as
+the value of the option.
+
+B<Warning.>
+Although it ought to be possible to specify callback function using
+the C<\&name> syntax above, or a literal C<sub { code }> code
+reference, the complexities of the Perl-internal memory management
+system mean that the function must currently be specified as a string
+containing the fully-qualified name, e.g. C<"main::cb">.>
+
+B<Warning.>
+The current implementation of the this method leaks memory, not only
+when the callback is installed, but on every occasion that it is
+consulted to look up an option value.
=head4 destroy()
-I<###>
+ $o->destroy()
+
+Destroys an Options object, freeing its resources. It is an error to
+reuse an Options object that has been C<destroy()>ed.
=head1 ENUMERATIONS