Update copyright year
[ZOOM-Perl-moved-to-github.git] / lib / ZOOM.pod
index 51d6023..20fb9a1 100644 (file)
@@ -1,5 +1,3 @@
-# $Id: ZOOM.pod,v 1.29 2006-02-20 11:30:58 mike Exp $
-
 use strict;
 use warnings;
 
@@ -11,7 +9,8 @@ ZOOM - Perl extension implementing the ZOOM API for Information Retrieval
 
  use ZOOM;
  eval {
-     $conn = new ZOOM::Connection($host, $port)
+     $conn = new ZOOM::Connection($host, $port,
+                                  databaseName => "mydb");
      $conn->option(preferredRecordSyntax => "usmarc");
      $rs = $conn->search_pqf('@attr 1=4 dinosaur');
      $n = $rs->size();
@@ -38,8 +37,8 @@ API such as ZOOM is that all implementations should be compatible
 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>,
@@ -49,12 +48,13 @@ C<ZOOM::Record>,
 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.
@@ -96,12 +96,27 @@ C<ZOOM::Connection::errcode()>,
 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::diag_srw_str()
 
-B<Warning.>
-Lark's vomit.  Do not read this section.
+ $msg = ZOOM::diag_srw_str(18);
+
+Returns a human-readable English-language string corresponding to the
+specified SRW error code.
 
- $which = ZOOM::event([ $conn1, $conn2, $conn3 ]);
+=head2 ZOOM::event_str()
+
+ $msg = ZOOM::event_str(ZOOM::Event::RECV_APDU);
+
+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
@@ -110,8 +125,7 @@ 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.
+See the section below on asynchronous applications.
 
 =head1 CLASSES
 
@@ -159,6 +173,9 @@ http://zoom.z3950.org/api/zoom-current.html#3.2
  $conn = new ZOOM::Connection("indexdata.dk:210/gils");
  $conn = new ZOOM::Connection("tcp:indexdata.dk:210/gils");
  $conn = new ZOOM::Connection("http:indexdata.dk:210/gils");
+ $conn = new ZOOM::Connection("indexdata.dk", 210,
+                               databaseName => "mydb",
+                               preferredRecordSyntax => "marc");
 
 Creates a new Connection object, and immediately connects it to the
 specified server.  If you want to make a new Connection object but
@@ -170,6 +187,16 @@ argument.  In the former case, the arguments are the name and port
 number of the Z39.50 server to connect to; in the latter case, the
 single argument is a YAZ service-specifier string of the form
 
+When the two-option form is used (which may be done using a vacuous
+second argument of zero), any number of additional argument pairs may
+be provided, which are interpreted as key-value pairs to be set as
+options after the Connection object is created but before it is
+connected to the server.  This is a convenient way to set options,
+including those that must be set before connecting such as
+authentication tokens.
+
+The server-name string is of the form:
+
 =over 4
 
 =item
@@ -203,11 +230,30 @@ local filesystem.
 
 =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
@@ -218,21 +264,28 @@ request).
 
  $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, which accepts hostname and port arguments
+like those of the C<new()> constructor.
 
 =head4 error_x() / errcode() / errmsg() / addinfo() / diagset()
 
@@ -257,6 +310,24 @@ returns all four at once.
 
 See the C<ZOOM::Exception> for the interpretation of these elements.
 
+=head4 exception()
+
+ die $conn->exception();
+
+C<exception()> returns the same information as C<error_x()> in the
+form of a C<ZOOM::Exception> object which may be thrown or rendered.
+If no error occurred on the connection, then C<exception()> returns an
+undefined value.
+
+=head4 check()
+
+ $conn->check();
+
+Checks whether an error is pending on the connection, and throw a
+C<ZOOM::Exception> object if so.  Since errors are thrown as they
+occur for synchronous connections, there is no need ever to call this
+except in asynchronous applications.
+
 =head4 option() / option_binary()
 
  print("server is '", $conn->option("serverImplementationName"), "'\n");
@@ -406,11 +477,8 @@ the C<ZOOM::Package> documentation.
 
 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()
 
@@ -475,7 +543,7 @@ Returns the number of records in the result set.
 The C<record()> method returns a C<ZOOM::Record> object representing
 a record from result-set, whose position is indicated by the argument
 passed in.  This is a zero-based index, so that legitimate values
-range from zero to C<$rs->size()-1>.
+range from zero to C<$rs-E<gt>size()-1>.
 
 The C<record_immediate()> API is identical, but it never invokes a
 network operation, merely returning the record from the ResultSet's
@@ -501,7 +569,7 @@ wants to display a whole list of results.  Conversely, the software's
 strategy might be always to ask for blocks of a twenty records:
 that's great for assembling long lists of things, but wasteful when
 only one record is wanted.  The problem is that the ZOOM module can't
-tell, when you call C<$rs->record()>, what your intention is.
+tell, when you call C<$rs-E<gt>record()>, what your intention is.
 
 But you can tell it.  The C<records()> method fetches a sequence of
 records, all in one go.  It takes three arguments: the first is the
@@ -591,21 +659,54 @@ http://zoom.z3950.org/api/zoom-current.html#3.5
 
 =head3 Methods
 
+=head4 error() / exception()
+
+ if ($rec->error()) {
+     my($code, $msg, $addinfo, $dset) = $rec->error();
+     print "error $code, $msg ($addinfo) from $dset set\n";
+     die $rec->exception();
+ }
+
+These functions test for surrogate diagnostics associated with a
+record: that is, errors pertaining to a particular record rather than
+to the fetch-some-records operation as a whole.  (The latter are known
+in Z39.50 as non-surrogate diagnostics, and are reported as exceptions
+thrown by searches.)  If a particular record can't be obtained - for
+example, because it is not available in the requested record syntax -
+then the record object obtained from the result-set, when interrogated
+with these functions, will report the error.
+
+C<error()> returns the error-code, a human-readable message,
+additional information and the name of the diagnostic set that the
+error is from.  When called in a scalar context, it just returns the
+error-code.  Since error 0 means "no error", it can be used as a
+boolean has-there-been-an-error indicator.
+
+C<exception()> returns the same information in the form of a
+C<ZOOM::Exception> object which may be thrown or rendered.  If no
+error occurred on the record, then C<exception()> returns an undefined
+value.
+
 =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
@@ -615,6 +716,31 @@ that can be decoded by software such as the fine C<Marc::Record>
 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);
@@ -974,6 +1100,21 @@ 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>
 
+=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
@@ -1004,6 +1145,17 @@ if compilation fails, then diagnostic information is cached in the
 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");
@@ -1174,12 +1326,16 @@ C<MEMORY>,
 C<ENCODE>,
 C<DECODE>,
 C<CONNECTION_LOST>,
-C<INIT>,
+C<ZINIT>,
 C<INTERNAL>,
 C<TIMEOUT>,
 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>,
@@ -1213,11 +1369,10 @@ applications - The C<ZOOM::Connection::last_event()> method is used to
 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
 
@@ -1324,6 +1479,70 @@ called.
 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,
@@ -1347,7 +1566,7 @@ Mike Taylor, E<lt>mike@indexdata.comE<gt>
 
 =head1 COPYRIGHT AND LICENCE
 
-Copyright (C) 2005 by Index Data.
+Copyright (C) 2005-2014 by Index Data.
 
 This library is free software; you can redistribute it and/or modify
 it under the same terms as Perl itself, either Perl version 5.8.4 or,