Move from sgml to nxml indentation YPP-15
[yazpp-moved-to-github.git] / doc / book.xml
1 <?xml version="1.0" standalone="no"?>
2 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
3     "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
4 [
5      <!ENTITY % local SYSTEM "local.ent">
6      %local;
7      <!ENTITY % entities SYSTEM "entities.ent">
8      %entities;
9      <!ENTITY % idcommon SYSTEM "common/common.ent">
10      %idcommon;
11 ]>
12 <book id="yazpp">
13  <bookinfo>
14   <title>YAZ++ User's Guide and Reference</title>
15   <authorgroup>
16    <author><firstname>Mike</firstname><surname>Taylor</surname></author>
17    <author><firstname>Adam</firstname><surname>Dickmeiss</surname></author>
18    </authorgroup>
19   <copyright>
20    <year>&copyright-year;</year>
21    <holder>Index Data Aps</holder>
22   </copyright>
23   <abstract>
24    <simpara>
25     <ulink url="&url.yazplusplus;">YAZ++</ulink>
26     is a set of libraries and header files that make it easier
27     to use the popular C-language
28     <ulink url="&url.yaz;">YAZ toolkit</ulink>
29     from C++, together with some utilities written using these
30     libraries.  It includes an implementation of the C++ binding for
31     ZOOM (<link linkend="zoom">ZOOM-C++</link>).
32    </simpara>
33    <simpara>
34     This manual covers version &version;.
35     </simpara>
36    <simpara>
37    </simpara>
38    <simpara>
39     <inlinemediaobject>
40      <imageobject>
41       <imagedata fileref="common/id.png" format="PNG"/>
42      </imageobject>
43     </inlinemediaobject>
44    </simpara>
45   </abstract>
46  </bookinfo>
47  <chapter id="introduction">
48   <title>Introduction</title>
49   <para>
50    <ulink url="&url.yazplusplus;">YAZ++</ulink>
51    is a C++ layer for YAZ and implements the ANSI
52    <ulink url="&url.z39.50;">Z39.50</ulink> protocol for information
53    retrieval (client and server side).
54   </para>
55   <para>
56    The YAZ++ packages also features a ZOOM interface for C++ (
57    <ulink url="&url.zoom.bind.cplusplus;">ZOOM C++</ulink>).
58   </para>
59   <para>
60    Later versions (0.7+) of YAZ++ also supports SRU.
61   </para>
62   <section id="licensing">
63    <title>Licensing</title>
64    <para>
65     YAZ++ and ZOOM-C++ is is covered
66     by Revised <link linkend="license">BSD License</link>.
67    </para>
68   </section>
69  </chapter>
70 <chapter id="installation">
71   <title>Installation</title>
72   <para>
73    You need a C++ compiler to compile and use YAZ++.
74    The software was implemented using <ulink url="&url.gcc;">GCC</ulink>
75    so we know that works well with YAZ++. From time to time the
76    software is compiled on Windows using Visual C++.
77    Other compilers should work too. Let us know of portability
78    problems, etc. with your system.
79   </para>
80   <para>
81    YAZ++ is built on top of the
82    <ulink url="&url.yaz;">YAZ</ulink>
83    toolkit.
84    You need to install that first.
85    For some platforms there are binary packages for YAZ.
86   </para>
87   <section id="unix">
88    <title>Installation on Unix (from source)</title>
89    <para>On UNIX, the software is compiled as follows:
90     <screen>
91      $ ./configure
92      $ make
93      $ su
94      # make install
95     </screen>
96    </para>
97    <para>
98     You can supply options for the <literal>configure</literal> script.
99     The most useful ones are:
100     <variablelist>
101      <varlistentry>
102       <term><literal>--prefix </literal>directory</term>
103       <listitem><para>
104         Specifies installation prefix. By default
105         <filename>/usr/local</filename> is used.
106        </para></listitem>
107      </varlistentry>
108      <varlistentry>
109       <term><literal>--with-yaz </literal>directory</term>
110       <listitem><para>
111         Specifies the location of <filename>yaz-config</filename>.
112         The <filename>yaz-config</filename> program is generated in
113         the source directory of YAZ as well as the binaries
114         directory when YAZ is installed (via make install).
115         </para>
116        <para>
117         If you don't supply this option, <literal>configure</literal> will
118         look for <filename>yaz-config</filename> in directories of the
119         <envar>PATH</envar> environment - which is nearly always
120         what you want.
121        </para></listitem>
122      </varlistentry>
123     </variablelist>
124     For the whole list of <literal>configure</literal> options, refer
125     to the help:
126     <literal>./configure --help</literal>.
127    </para>
128    <para>
129     Configure uses GNU's C/C++ compiler if available. To specify another
130     compiler, set <literal>CXX</literal>. To use other compiler flags,
131     specify <literal>CXXFLAGS</literal>. To use <literal>CC</literal>
132     with debugging you could use:
133     <screen>
134      CXXFLAGS="-g" CXX=CC ./configure
135     </screen>
136    </para>
137    <para>
138     This is what you have after successful compilation:
139     <variablelist>
140      <varlistentry>
141       <term><filename>src/libyazpp.la</filename></term>
142       <listitem><para>
143        The YAZ++ library.
144        This library gets installed in your libraries directory
145        (<parameter>prefix</parameter><filename>/lib</filename>).
146       </para></listitem>
147      </varlistentry>
148      <varlistentry>
149       <term><filename>src/libzoompp.la</filename></term>
150       <listitem><para>
151        The <link linkend="zoom">ZOOM-C++</link> library.
152        This library gets installed in your libraries directory
153        (<parameter>prefix</parameter><filename>/lib</filename>).
154       </para></listitem>
155      </varlistentry>
156      <varlistentry>
157       <term><filename>include/yazpp/*.h</filename></term>
158       <listitem><para>
159        Various C++ header files, which you'll need for YAZ++
160        development. All these are installed in your header files area
161        (<parameter>prefix</parameter><filename>/include/yazpp</filename>).
162       </para></listitem>
163      </varlistentry>
164      <varlistentry>
165       <term><filename>yazpp-config</filename></term>
166       <listitem><para>
167        A Bourne shell-script utility that returns the values of the
168        <envar>CFLAGS</envar> and <envar>LIBS</envar>
169        environment variables
170        needed in order to compile your applications with the YAZ++
171        library.  This script gets installed in your binaries directory
172        (<parameter>prefix</parameter><filename>/bin</filename>).
173       </para></listitem>
174      </varlistentry>
175      <varlistentry>
176       <term><filename>zoom/zclient</filename></term>
177       <listitem><para>
178        ZOOM C++ demonstration client that uses the ZOOM C++ classes.
179        This client does not get installed in the system directories.
180       </para></listitem>
181      </varlistentry>
182      <varlistentry>
183       <term><filename>src/yaz-my-client</filename></term>
184       <listitem><para>
185        YAZ C++ demonstration client. This client does not
186        get installed in the system directories.
187       </para></listitem>
188      </varlistentry>
189      <varlistentry>
190       <term><filename>src/yaz-my-server</filename></term>
191       <listitem><para>
192         YAZ C++ demonstration server. This server does not
193         get installed in the system directories.
194        </para></listitem>
195      </varlistentry>
196     </variablelist>
197    </para>
198   </section>
199   <section id="windows">
200    <title>Installation on Windows</title>
201    <para>
202     YAZ++ is shipped with "makefiles" for the NMAKE tool that comes
203     with <ulink url="&url.vstudio;">Microsoft Visual Studio</ulink>.
204     Version 2003 (7) and 2005 (8) has been tested.
205     We expect that YAZ++ compiles with versions 5 and 6 as well.
206    </para>
207    <para>
208     Start a command prompt and switch the sub directory
209     <filename>WIN</filename> where the file <filename>makefile</filename>
210     is located. Customize the installation by editing the
211     <filename>makefile</filename> file (for example by using notepad).
212    </para>
213    <para>
214     The following summarizes the most important settings in that file:
215     <variablelist>
216      <varlistentry><term><literal>DEBUG</literal></term>
217       <listitem><para>
218         If set to 1, the software is
219         compiled with debugging libraries (code generation is
220         multi-threaded debug DLL).
221         If set to 0, the software is compiled with release libraries
222         (code generation is multi-threaded DLL).
223        </para></listitem>
224      </varlistentry>
225      <varlistentry><term><filename>YAZ_DIR</filename></term>
226       <listitem><para>
227         Specifies the directory of the YAZ source.
228        </para></listitem>
229      </varlistentry>
230     </variablelist>
231    </para>
232    <para>
233     When satisfied with the settings in the makefile, type
234     <screen>
235      nmake
236     </screen>
237    </para>
238    <tip>
239     <para>
240      If the <filename>nmake</filename> command is not found on your system
241      you probably haven't defined the environment variables required to
242      use that tool. To fix that, find and run the batch file
243      <filename>vcvars32.bat</filename>. You need to run it from within
244      the command prompt or set the environment variables "globally";
245      otherwise it doesn't work.
246     </para>
247    </tip>
248    <para>
249     If you wish to recompile YAZ++ - for example if you modify
250     settings in the <filename>makefile</filename> you can delete
251     object files, etc by running.
252     <screen>
253      nmake clean
254     </screen>
255    </para>
256    <para>
257     The following files are generated upon successful compilation:
258     <variablelist>
259      <varlistentry>
260       <term><filename>bin/yazpp5.dll</filename></term>
261       <listitem><para>
262        YAZ++ DLL . Includes ZOOM C++ as well.
263        For the debug version <filename>lib/yazpp5d.dll</filename>
264        is created instead.
265      </para></listitem></varlistentry>
266      <varlistentry>
267       <term><filename>lib/yazpp5.lib</filename></term>
268       <listitem><para>
269        Import library for <filename>yazpp5.dll</filename>.
270        For the debug version <filename>lib/yazpp5d.lib</filename>
271        is created instead.
272      </para></listitem></varlistentry>
273      <varlistentry>
274       <term><filename>bin/yaz-my-client.exe</filename></term>
275       <listitem><para>
276        Z39.50 client demonstrating the YAZ++ API.
277      </para></listitem></varlistentry>
278      <varlistentry>
279       <term><filename>bin/yaz-my-server.exe</filename></term>
280       <listitem><para>
281        Z39.50 server demonstrating the YAZ++ API.
282      </para></listitem></varlistentry>
283      <varlistentry>
284       <term><filename>bin/zclient.exe</filename></term>
285       <listitem><para>
286        ZOOM C++ demo client. A simple WIN32 console application.
287      </para></listitem></varlistentry>
288     </variablelist>
289    </para>
290   </section>
291  </chapter>
292  <chapter id="zoom">
293   <title>ZOOM-C++</title>
294   <sect1 id="zoom-introduction">
295    <title>Introduction</title>
296    <para>
297     <ulink url="&url.zoom;">ZOOM</ulink>
298     is the emerging standard API for information retrieval programming
299     using the Z39.50 protocol.  ZOOM's
300     <ulink url="&url.zoom.api;">Abstract API</ulink>
301     specifies semantics for classes representing key IR concepts such as
302     connections, queries, result sets and records; and there are various
303     <ulink url="&url.zoom.bind;">bindings</ulink>
304     specifying how those concepts should be represented in various
305     programming languages.
306    </para>
307    <para>
308     The YAZ++ library includes an implementation of the <ulink
309     url="&url.zoom.bind.cplusplus;">C++ binding</ulink>
310     for ZOOM, enabling quick, easy development of client applications.
311    </para>
312    <para>
313     For example, here is a tiny Z39.50 client that fetches and displays
314     the MARC record for Farlow &amp; Brett Surman's
315     <citetitle>The Complete Dinosaur</citetitle>
316     from the Library of Congress's Z39.50 server:
317    </para>
318    <programlisting>
319     #include &lt;iostream&gt;
320     #include &lt;yazpp/zoom.h&gt;
321
322     using namespace ZOOM;
323
324     int main(int argc, char **argv)
325     {
326         connection conn("z3950.loc.gov", 7090);
327         conn.option("databaseName", "Voyager");
328         conn.option("preferredRecordSyntax", "USMARC");
329         resultSet rs(conn, prefixQuery("@attr 1=7 0253333490"));
330         const record *rec = rs.getRecord(0);
331         cout &lt;&lt; rec-&gt;render() &lt;&lt; endl;
332     }
333    </programlisting>
334    <note>
335     <para>
336      For the sake of simplicity, this program does not check
337      for errors: we show a more robust version of the same program
338      <link linkend="revised-sample">later</link>.)
339     </para>
340    </note>
341    <para>
342     YAZ++'s implementation of the C++ binding is a thin layer over YAZ's
343     implementation of the C binding.  For information on the supported
344     options and other such details, see the ZOOM-C documentation, which
345     can be found on-line at
346     <ulink url="&url.yaz.zoom;"/>
347    </para>
348    <para>
349     All of the classes defined by ZOOM-C++ are in the
350     <literal>ZOOM</literal> namespace.  We will now consider
351     the five main classes in turn:
352     <itemizedlist>
353      <listitem>
354       <para>
355        <literal>connection</literal>
356       </para>
357      </listitem>
358      <listitem>
359       <para>
360        <literal>query</literal> and its subclasses
361        <literal>prefixQuery</literal> and
362        <literal>CCLQuery</literal>
363       </para>
364      </listitem>
365      <listitem>
366       <para>
367        <literal>resultSet</literal>
368       </para>
369      </listitem>
370      <listitem>
371       <para>
372        <literal>record</literal>
373       </para>
374      </listitem>
375      <listitem>
376       <para>
377        <literal>exception</literal> and its subclasses
378        <literal>systemException</literal>,
379        <literal>bib1Exception</literal> and
380        <literal>queryException</literal>
381       </para>
382      </listitem>
383     </itemizedlist>
384    </para>
385   </sect1>
386   <sect1 id="zoom-connection">
387    <title><literal>ZOOM::connection</literal></title>
388    <para>
389     A <literal>ZOOM::connection</literal> object represents an open
390     connection to a Z39.50 server.  Such a connection is forged by
391     constructing a <literal>connection</literal> object.
392    </para>
393    <para>
394     The class has this declaration:
395    </para>
396    <synopsis>
397     class connection {
398     public:
399       connection (const char *hostname, int portnum);
400       ~connection ();
401       const char *option (const char *key) const;
402       const char *option (const char *key, const char *val);
403     };
404    </synopsis>
405    <para>
406     When a new <literal>connection</literal> is created, the hostname
407     and port number of a Z39.50 server must be supplied, and the
408     network connection is forged and wrapped in the new object.  If the
409     connection can't be established - perhaps because the hostname
410     couldn't be resolved, or there is no server listening on the
411     specified port - then an
412     <link linkend="zoom-exception"><literal>exception</literal></link>
413     is thrown.
414    </para>
415    <para>
416     The only other methods on a <literal>connection</literal> object
417     are for getting and setting options.  Any name-value pair of
418     strings may be set as options, and subsequently retrieved, but
419     certain options have special meanings which are understood by the
420     ZOOM code and affect the behaviour of the object that carries
421     them.  For example, the value of the
422     <literal>databaseName</literal> option is used as the name of the
423     database to query when a search is executed against the
424     <literal>connection</literal>.  For a full list of such special
425     options, see the ZOOM abstract API and the ZOOM-C documentation
426     (links below).
427    </para>
428    <sect2 id="connection.references">
429     <title>References</title>
430     <itemizedlist>
431      <listitem>
432       <para>
433        <ulink url="http://zoom.z3950.org/api/zoom-1.3.html#3.2">
434        Section 3.2 (Connection) of the ZOOM Abstract API</ulink>
435       </para>
436      </listitem>
437      <listitem>
438       <para>
439        <ulink url="&url.yaz.zoom.connections;">
440        The Connections section f the ZOOM-C documentation</ulink>
441       </para>
442      </listitem>
443     </itemizedlist>
444    </sect2>
445   </sect1>
446   <sect1 id="zoom-query">
447    <title><literal>ZOOM::query</literal> and subclasses</title>
448    <para>
449     The <literal>ZOOM::query</literal> class is a virtual base class,
450     representing a query to be submitted to a server.  This class has
451     no methods, but two (so far) concrete subclasses, each implementing
452     a specific query notation.
453    </para>
454    <sect2 id="zoom-prefixQuery">
455     <title><literal>ZOOM::prefixQuery</literal></title>
456     <synopsis>
457     class prefixQuery : public query {
458     public:
459       prefixQuery (const char *pqn);
460       ~prefixQuery ();
461     };
462     </synopsis>
463     <para>
464      This class enables a query to be created by compiling YAZ's
465      cryptic but powerful
466      <ulink url="&url.yaz.pqf;">Prefix Query Notation (PQN)</ulink>.
467     </para>
468    </sect2>
469    <sect2 id="zoom-CCLQuery">
470     <title><literal>ZOOM::CCLQuery</literal></title>
471     <synopsis>
472     class CCLQuery : public query {
473     public:
474       CCLQuery (const char *ccl, void *qualset);
475       ~CCLQuery ();
476     };
477     </synopsis>
478     <para>
479      This class enables a query to be created using the simpler but
480      less expressive
481      <ulink url="&url.yaz.ccl;">Common Command Language (CCL)</ulink>.
482      The qualifiers recognised by the CCL parser are specified in an
483      external configuration file in the format described by the YAZ
484      documentation.
485     </para>
486     <para>
487      If query construction fails for either type of
488      <literal>query</literal> object - typically because the query
489      string itself is not valid PQN or CCL - then an
490      <link linkend="zoom-exception"><literal>exception</literal></link>
491      is thrown.
492     </para>
493    </sect2>
494    <sect2 id="queries.discussion">
495     <title>Discussion</title>
496     <para>
497      It will be readily recognised that these objects have no methods
498      other than their constructors: their only role in life is to be
499      used in searching, by being passed to the
500      <literal>resultSet</literal> class's constructor.
501     </para>
502     <para>
503      Given a suitable set of CCL qualifiers, the following pairs of
504      queries are equivalent:
505     </para>
506     <screen>
507      prefixQuery("dinosaur");
508      CCLQuery("dinosaur");
509
510      prefixQuery("@and complete dinosaur");
511      CCLQuery("complete and dinosaur");
512
513      prefixQuery("@and complete @or dinosaur pterosaur");
514      CCLQuery("complete and (dinosaur or pterosaur)");
515
516      prefixQuery("@attr 1=7 0253333490");
517      CCLQuery("isbn=0253333490");
518     </screen>
519    </sect2>
520    <sect2 id="query.references">
521     <title>References</title>
522     <itemizedlist>
523      <listitem>
524       <para>
525        <ulink url="http://zoom.z3950.org/api/zoom-1.3.html#3.3">
526         Section 3.3 (Query) of the ZOOM Abstract API
527        </ulink>
528       </para>
529     </listitem>
530     <listitem>
531      <para>
532       <ulink url="&url.yaz.zoom.query;">
533        The Queries section of the ZOOM-C documentation
534       </ulink>
535      </para>
536     </listitem>
537     </itemizedlist>
538    </sect2>
539   </sect1>
540   <sect1 id="zoom-resultset">
541    <title><literal>ZOOM::resultSet</literal></title>
542    <para>
543     A <literal>ZOOM::resultSet</literal> object represents a set of
544     records identified by a query that has been executed against a
545     particular connection.  The sole purpose of both
546     <literal>connection</literal> and <literal>query</literal> objects
547     is that they can be used to create new
548     <literal>resultSet</literal>s - that is, to perform a search on the
549     server on the remote end of the connection.
550    </para>
551    <para>
552     The class has this declaration:
553    </para>
554    <synopsis>
555     class resultSet {
556     public:
557       resultSet (connection &amp;c, const query &amp;q);
558       ~resultSet ();
559       const char *option (const char *key) const;
560       const char *option (const char *key, const char *val);
561       size_t size () const;
562       const record *getRecord (size_t i) const;
563     };
564    </synopsis>
565    <para>
566     New <literal>resultSet</literal>s are created by the constructor,
567     which is passed a <literal>connection</literal>, indicating the
568     server on which the search is to be performed, and a
569     <literal>query</literal>, indicating what search to perform.  If
570     the search fails - for example, because the query uses attributes
571     that the server doesn't implement - then an
572     <link linkend="zoom-exception"><literal>exception</literal></link>
573     is thrown.
574    </para>
575    <para>
576     Like <literal>connection</literal>s, <literal>resultSet</literal>
577     objects can carry name-value options.  The special options which
578     affect ZOOM-C++'s behaviour are the same as those for ZOOM-C and
579     are described in its documentation (link below).  In particular,
580     the <literal>preferredRecordSyntax</literal> option may be set to
581     a string such as ``USMARC'', ``SUTRS'' etc. to indicate what the
582     format in which records should be retrieved; and the
583     <literal>elementSetName</literal> option indicates whether brief
584     records (``B''), full records (``F'') or some other composition
585     should be used.
586    </para>
587    <para>
588     The <literal>size()</literal> method returns the number of records
589     in the result set.  Zero is a legitimate value: a search that finds
590     no records is not the same as a search that fails.
591    </para>
592    <para>
593     Finally, the <literal>getRecord</literal> method returns the
594     <parameter>i</parameter>th record from the result set, where
595     <parameter>i</parameter> is zero-based: that is, legitmate values
596     range from zero up to one less than the result-set size.  If the
597     method fails, for example because the requested record is out of
598     range, it <literal>throw</literal>s an
599     <link linkend="zoom-exception"><literal>exception</literal></link>.
600    </para>
601    <sect2 id="resultset.references">
602     <title>References</title>
603     <itemizedlist>
604      <listitem>
605       <para>
606        <ulink url="http://zoom.z3950.org/api/zoom-1.3.html#3.4"
607               >Section 3.4 (Result Set) of the ZOOM Abstract API</ulink>
608       </para>
609      </listitem>
610      <listitem>
611       <para>
612        <ulink url="&url.yaz.zoom.resultsets;"
613               >The Result Sets section of the ZOOM-C documentation</ulink>
614       </para>
615      </listitem>
616     </itemizedlist>
617    </sect2>
618   </sect1>
619   <sect1 id="zoom-record">
620    <title><literal>ZOOM::record</literal></title>
621    <para>
622     A <literal>ZOOM::record</literal> object represents a chunk of data
623     from a <literal>resultSet</literal> returned from a server.
624    </para>
625    <para>
626     The class has this declaration:
627    </para>
628    <synopsis>
629     class record {
630     public:
631       ~record ();
632       enum syntax {
633         UNKNOWN, GRS1, SUTRS, USMARC, UKMARC, XML
634       };
635       record *clone () const;
636       syntax recsyn () const;
637       const char *render () const;
638       const char *rawdata () const;
639     };
640    </synopsis>
641    <para>
642     Records returned from Z39.50 servers are encoded using a record
643     syntax: the various national MARC formats are commonly used for
644     bibliographic data, GRS-1 or XML for complex structured data, SUTRS
645     for simple human-readable text, etc.  The
646     <literal>record::syntax</literal> enumeration specifies constants
647     representing common record syntaxes, and the
648     <literal>recsyn()</literal> method returns the value corresponding
649     to the record-syntax of the record on which it is invoked.
650     <note>
651      <para>
652       Because this interface uses an enumeration, it is difficult to
653       extend to other record syntaxes - for example, DANMARC, the MARC
654       variant widely used in Denmark.  We might either grow the
655       enumeration substantially, or change the interface to return
656       either an integer or a string.
657      </para>
658     </note>
659    </para>
660    <para>
661     The simplest thing to do with a retrieved record is simply to
662     <literal>render()</literal> it.  This returns a human-readable, but
663     not necessarily very pretty, representation of the contents of the
664     record.  This is useful primarily for testing and debugging, since
665     the application has no control over how the record appears.
666     (The application must <emphasis>not</emphasis>
667     <literal>delete</literal> the returned string - it is ``owned'' by
668     the record object.)
669    </para>
670    <para>
671     More sophisticated applications will want to deal with the raw data
672     themselves: the <literal>rawdata()</literal> method returns it.
673     Its format will vary depending on the record syntax: SUTRS, MARC
674     and XML records are returned ``as is'', and GRS-1 records as a
675     pointer to their top-level node, which is a
676     <literal>Z_GenericRecord</literal> structure as defined in the
677     <literal>&lt;yaz/z-grs.h&gt;</literal> header file.
678     (The application must <emphasis>not</emphasis>
679     <literal>delete</literal> the returned data - it is ``owned'' by
680     the record object.)
681    </para>
682    <para>
683     Perceptive readers will notice that there are no methods for access
684     to individual fields within a record.  That's because the different
685     record syntaxes are so different that there is no even a uniform
686     notion of what a field is across them all, let alone a sensible way
687     to implement such a function.  Fetch the raw data instead, and pick
688     it apart ``by hand''.
689    </para>
690    <sect2 id="zoom.memory.management">
691     <title>Memory Management</title>
692     <para>
693      The <literal>record</literal> objects returned from
694      <literal>resultSet::getRecord()</literal> are ``owned'' by the
695      result set object: that means that the application is not
696      responsible for <literal>delete</literal>ing them - each
697      <literal>record</literal> is automatically deallocated when the
698      <literal>resultSet</literal> that owns it is
699      <literal>delete</literal>d.
700     </para>
701     <para>
702      Usually that's what you want: it means that you can easily fetch a
703      record, use it and forget all about it, like this:
704     </para>
705     <programlisting>
706      resultSet rs(conn, query);
707      cout &lt;&lt; rs.getRecord(0)-&gt;render();
708     </programlisting>
709     <para>
710      But sometimes you want a <literal>record</literal> to live on past
711      the lifetime of the <literal>resultSet</literal> from which it was
712      fetched.  In this case, the <literal>clone(f)</literal> method can
713      be used to make an autonomous copy.  The application must
714      <literal>delete</literal> it when it doesn't need it any longer:
715     </para>
716     <programlisting>
717     record *rec;
718     {
719         resultSet rs(conn, query);
720         rec = rs.getRecord(0)-&gt;clone();
721         // `rs' goes out of scope here, and is deleted
722     }
723     cout &lt;&lt; rec-&gt;render();
724     delete rec;
725     </programlisting>
726    </sect2>
727    <sect2 id="record.references">
728     <title>References</title>
729     <itemizedlist>
730      <listitem>
731       <para>
732        <ulink url="http://zoom.z3950.org/api/zoom-1.3.html#3.5"
733               >Section 3.5 (Record) of the ZOOM Abstract API</ulink>
734       </para>
735      </listitem>
736      <listitem>
737       <para>
738        <ulink url="&url.yaz.zoom.records;"
739               >The Records section of the ZOOM-C documentation</ulink>
740       </para>
741      </listitem>
742     </itemizedlist>
743    </sect2>
744   </sect1>
745   <sect1 id="zoom-exception">
746    <title><literal>ZOOM::exception</literal> and subclasses</title>
747    <para>
748     The <literal>ZOOM::exception</literal> class is a virtual base
749     class, representing a diagnostic generated by the ZOOM-C++ library
750     or returned from a server.  Its subclasses represent particular
751     kinds of error.
752    </para>
753    <para>
754     When any of the ZOOM methods fail, they respond by
755     <literal>throw</literal>ing an object of type
756     <literal>exception</literal> or one of its subclasses.  This most
757     usually happens with the <literal>connection</literal> constructor,
758     the various query constructors, the <literal>resultSet</literal>
759     constructor (which is actually the searching method) and
760     <literal>resultSet::getRecord()</literal>.
761    </para>
762    <para>
763     The base class has this declaration:
764    </para>
765    <synopsis>
766     class exception {
767     public:
768       exception (int code);
769       int errcode () const;
770       const char *errmsg () const;
771     };
772    </synopsis>
773    <para>
774     It has three concrete subclasses:
775    </para>
776    <sect2 id="zoom-systemException">
777     <title><literal>ZOOM::systemException</literal></title>
778     <synopsis>
779      class systemException: public exception {
780      public:
781        systemException ();
782        int errcode () const;
783        const char *errmsg () const;
784      };
785     </synopsis>
786     <para>
787      Represents a ``system error'', typically indicating that a system
788      call failed - often in the low-level networking code that
789      underlies Z39.50.  <literal>errcode()</literal> returns the value
790      that the system variable <literal>errno</literal> had at the time
791      the exception was constructed; and <literal>errmsg()</literal>
792      returns a human-readable error-message corresponidng to that error
793      code.
794     </para>
795    </sect2>
796    <sect2 id="zoom-bib1Exception">
797     <title><literal>ZOOM::bib1Exception</literal></title>
798     <synopsis>
799      class bib1Exception: public exception {
800      public:
801        bib1Exception (int errcode, const char *addinfo);
802        int errcode () const;
803        const char *errmsg () const;
804        const char *addinfo () const;
805      };
806     </synopsis>
807     <para>
808      Represents an error condition communicated by a Z39.50 server.
809      <literal>errcode()</literal> returns the BIB-1 diagnostic code of
810      the error, and <literal>errmsg()</literal> a human-readable error
811      message corresponding to that code.  <literal>addinfo()</literal>
812      returns any additional information associated with the error.
813     </para>
814     <para>
815      For example, if a ZOOM application tries to search in the
816      ``Voyager'' database of a server that does not have a database of
817      that name, a <literal>bib1Exception</literal> will be thrown in
818      which <literal>errcode()</literal> returns 109,
819      <literal>errmsg()</literal> returns the corresponding error
820      message ``Database unavailable'' and <literal>addinfo()</literal>
821      returns the name of the requested, but unavailable, database.
822     </para>
823    </sect2>
824    <sect2 id="zoom-queryException">
825     <title><literal>ZOOM::queryException</literal></title>
826     <synopsis>
827      class queryException: public exception {
828      public:
829        static const int PREFIX = 1;
830        static const int CCL = 2;
831        queryException (int qtype, const char *source);
832        int errcode () const;
833        const char *errmsg () const;
834        const char *addinfo () const;
835      };
836     </synopsis>
837     <para>
838      This class represents an error in parsing a query into a form that
839      a Z39.50 can understand.  It must be created with the
840      <literal>qtype</literal> parameter equal to one of the query-type
841      constants, which can be retrieved via the
842      <literal>errcode()</literal> method; <literal>errmsg()</literal>
843      returns an error-message specifying which kind of query was
844      malformed; and <literal>addinfo()</literal> returns a copy of the
845      query itself (that is, the value of <literal>source</literal> with
846      which the exception object was created.)
847     </para>
848    </sect2>
849    <sect2 id="revised-sample">
850     <title>Revised Sample Program</title>
851     <para>
852      Now we can revise the sample program from the
853      <link linkend="zoom-introduction">introduction</link>
854      to catch exceptions and report any errors:
855     </para>
856     <programlisting>
857     /* g++ -o zoom-c++-hw zoom-c++-hw.cpp -lzoompp -lyaz */
858
859     #include &lt;iostream&gt;
860     #include &lt;yazpp/zoom.h&gt;
861
862     using namespace ZOOM;
863
864     int main(int argc, char **argv)
865     {
866         try {
867             connection conn("z3950.loc.gov", 7090);
868             conn.option("databaseName", "Voyager");
869             conn.option("preferredRecordSyntax", "USMARC");
870             resultSet rs(conn, prefixQuery("@attr 1=7 0253333490"));
871             const record *rec = rs.getRecord(0);
872             cout &lt;&lt; rec-&gt;render() &lt;&lt; endl;
873         } catch (systemException &amp;e) {
874             cerr &lt;&lt; "System error " &lt;&lt;
875                 e.errcode() &lt;&lt; " (" &lt;&lt; e.errmsg() &lt;&lt; ")" &lt;&lt; endl;
876         } catch (bib1Exception &amp;e) {
877             cerr &lt;&lt; "BIB-1 error " &lt;&lt; 
878                 e.errcode() &lt;&lt; " (" &lt;&lt; e.errmsg() &lt;&lt; "): " &lt;&lt; e.addinfo() &lt;&lt; endl;
879         } catch (queryException &amp;e) {
880             cerr &lt;&lt; "Query error " &lt;&lt;
881                 e.errcode() &lt;&lt; " (" &lt;&lt; e.errmsg() &lt;&lt; "): " &lt;&lt; e.addinfo() &lt;&lt; endl;
882         } catch (exception &amp;e) {
883             cerr &lt;&lt; "Error " &lt;&lt;
884                 e.errcode() &lt;&lt; " (" &lt;&lt; e.errmsg() &lt;&lt; ")" &lt;&lt; endl;
885         }
886     }
887     </programlisting>
888     <para>
889      The heart of this program is the same as in the original version,
890      but it's now wrapped in a <literal>try</literal> block followed by
891      several <literal>catch</literal> blocks which try to give helpful
892      diagnostics if something goes wrong.
893     </para>
894     <para>
895      The first such block diagnoses system-level errors such as memory
896      exhaustion or a network connection being broken by a server's
897      untimely death; the second catches errors at the Z39.50 level,
898      such as a server's report that it can't provide records in USMARC
899      syntax; the third is there in case there's something wrong with
900      the syntax of the query (although in this case it's correct); and
901      finally, the last <literal>catch</literal> block is a
902      belt-and-braces measure to be sure that nothing escapes us.
903     </para>
904    </sect2>
905    <sect2 id="exception.references">
906     <title>References</title>
907     <itemizedlist>
908      <listitem>
909       <para>
910        <ulink url="http://zoom.z3950.org/api/zoom-1.3.html#3.7"
911               >Section 3.7 (Exception) of the ZOOM Abstract API</ulink>
912       </para>
913      </listitem>
914      <listitem>
915       <para>
916        <ulink url="&url.z39.50.diagnostics;">Bib-1 Diagnostics</ulink> on the
917        <ulink url="&url.z39.50;">Z39.50 Maintenance Agency</ulink> site.
918       </para>
919      </listitem>
920     </itemizedlist>
921     <para>
922      Because C does not support exceptions, ZOOM-C has no API element
923      that corresponds directly with ZOOM-C++'s
924      <literal>exception</literal> class and its subclasses.  The
925      closest thing is the <literal>ZOOM_connection_error</literal>
926      function described in
927      <ulink url="&url.yaz.zoom.connections;"
928             >The Connections section</ulink> of the documentation.
929     </para>
930    </sect2>
931   </sect1>
932  </chapter>
933  <chapter id="api">
934   <title>YAZ C++ API</title>
935   <para>
936    The YAZ C++ API is an client - and server API that exposes
937    all YAZ features. The API doesn't hide YAZ C data structures, but
938    provides a set of useful high-level objects for creating clients -
939    and servers.
940   </para>
941   <para>
942    All definitions from YAZ++ are part of namespace
943    <literal>yazpp_1</literal>.
944   </para>
945   <para>
946    The following sections include a short description of the
947    interfaces and implementations (concrete classes).
948   </para>
949   <para>
950    In order to understand the structure, you should look at the
951    example client <filename>yaz-my-client.cpp</filename> and
952    the example server <filename>yaz-my-server.cpp</filename>.
953    If that is too easy, you can always turn to the implementation
954    of the proxy itself and send us a patch if you implement a new
955    useful feature.
956   </para>
957   <note>
958    <para>
959     The documentation here is very limited. We plan to enhance it -
960     provided there is interest for it.
961    </para>
962   </note>
963   <section id="interfaces"><title>Interfaces</title>
964    <section id="ISocketObservable"><title>ISocketObservable</title>
965     <para>
966      This interface is capable of observing sockets.
967      When a socket even occurs it invokes an object implementing the
968      <link linkend="ISocketObserver">ISocketObserver</link>
969      interface.
970     </para>
971     <synopsis>
972      #include &lt;yazpp/socket-observer.h>
973
974      class my_socketobservable : public ISocketObservable {
975         // Add an observer interested in socket fd
976         virtual void addObserver(int fd, ISocketObserver *observer) = 0;
977         // Delete an observer
978         virtual void deleteObserver(ISocketObserver *observer) = 0;
979         // Delete all observers
980         virtual void deleteObservers() = 0;
981         // Specify the events that the observer is interested in.
982         virtual void maskObserver(ISocketObserver *observer,
983                                   int mask) = 0;
984         // Specify timeout
985         virtual void timeoutObserver(ISocketObserver *observer,
986                                      int timeout)=0;
987      };
988     </synopsis>
989    </section>
990    <section id="ISocketObserver">
991     <title>ISocketObserver</title>
992     <para>
993      This interface is interested in socket events supporting
994      the <link linkend="ISocketObservable">ISocketObservable</link>
995      interface.
996     </para>
997     <synopsis>
998      #include &lt;yazpp/socket-observer.h>
999
1000      class my_socketobserver : public ISocketObserver {
1001          public:
1002           // Notify the observer that something happened to socket
1003           virtual void socketNotify(int event) = 0;
1004      }
1005     </synopsis>
1006    </section>
1007    <section id="IPDU_Observable">
1008     <title>IPDU_Observable</title>
1009     <para>
1010      This interface is is responsible for sending - and receiving PDUs over
1011      the network (YAZ COMSTACK). When events occur, an instance
1012      implementing <link linkend="IPDU_Observer">IPDU_Observer</link>
1013      is notified.
1014     </para>
1015     <synopsis>
1016      #include &lt;yazpp/pdu-observer.h>
1017
1018      class my_pduobservable : public IPDU_Observable {
1019        public:
1020          // Send encoded PDU buffer of specified length
1021          virtual int send_PDU(const char *buf, int len) = 0;
1022          // Connect with server specified by addr.
1023          virtual void connect(IPDU_Observer *observer,
1024                      const char *addr) = 0;
1025          // Listen on address addr.
1026          virtual void listen(IPDU_Observer *observer, const char *addr)=0;
1027          // Close connection
1028          virtual void close() = 0;
1029          // Make clone of this object using this interface
1030          virtual IPDU_Observable *clone() = 0;
1031          // Destroy completely
1032          virtual void destroy() = 0;
1033          // Set Idle Time
1034          virtual void idleTime (int timeout) = 0;
1035          // Get peername
1036          virtual const char *getpeername() = 0;
1037
1038          virtual ~IPDU_Observable();
1039      };
1040     </synopsis>
1041    </section>
1042    <section id="IPDU_Observer">
1043     <title>IPDU_Observer</title>
1044     <para>
1045      This interface is interested in PDUs and using an object implementing
1046      <link linkend="IPDU_Observable">IPDU_Observable</link>.
1047     </para>
1048     <synopsis>
1049      #include &lt;yazpp/pdu-observer.h>
1050
1051      class my_pduobserver : public IPDU_Observer {
1052        public:
1053          // A PDU has been received
1054          virtual void recv_PDU(const char *buf, int len) = 0;
1055          // Called when Iyaz_PDU_Observable::connect was successful.
1056          virtual void connectNotify() = 0;
1057          // Called whenever the connection was closed
1058          virtual void failNotify() = 0;
1059          // Called whenever there is a timeout
1060          virtual void timeoutNotify() = 0;
1061          // Make clone of observer using IPDU_Observable interface
1062          virtual IPDU_Observer *sessionNotify(
1063          IPDU_Observable *the_PDU_Observable, int fd) = 0;
1064      };
1065     </synopsis>
1066    </section>
1067    <section id="query">
1068     <title>Yaz_Query</title>
1069     <para>
1070      Abstract query.
1071     </para>
1072     <synopsis>
1073      #include &lt;yazpp/query.h>
1074      class my_query : public Yaz_Query {
1075        public:
1076          // Print query in buffer described by str and len
1077          virtual void print (char *str, int len) = 0;
1078      };
1079     </synopsis>
1080    </section>
1081   </section>
1082   <section id="implementations">
1083    <title>Implementations</title>
1084    <section id="Yaz_SocketManager">
1085     <title>Yaz_SocketManager</title>
1086     <para>
1087      This class implements the <link linkend="ISocketObservable">
1088      ISocketObservable</link> interface and is a portable
1089      socket wrapper around the select call.
1090      This implementation is useful for daemons,
1091      command line clients, etc.
1092     </para>
1093     <synopsis>
1094      #include &lt;yazpp/socket-manager.h>
1095
1096      class SocketManager : public ISocketObservable {
1097        public:
1098          // Add an observer
1099          virtual void addObserver(int fd, ISocketObserver *observer);
1100          // Delete an observer
1101          virtual void deleteObserver(ISocketObserver *observer);
1102          // Delete all observers
1103          virtual void deleteObservers();
1104          // Set event mask for observer
1105          virtual void maskObserver(ISocketObserver *observer, int mask);
1106          // Set timeout
1107          virtual void timeoutObserver(ISocketObserver *observer,
1108                                   unsigned timeout);
1109          // Process one event. return > 0 if event could be processed;
1110          int processEvent();
1111          SocketManager();
1112          virtual ~SocketManager();
1113      };
1114     </synopsis>
1115    </section>
1116    <section id="PDU_Assoc">
1117     <title>PDU_Assoc</title>
1118     <para>
1119      This class implements the interfaces
1120      <link linkend="IPDU_Observable">IPDU_Observable</link>
1121      and
1122      <link linkend="ISocketObserver">ISocketObserver</link>.
1123      This object implements a non-blocking client/server channel
1124      that transmits BER encoded PDUs (or those offered by YAZ COMSTACK).
1125     </para>
1126     <synopsis>
1127      #include &lt;yazpp/pdu-assoc.h>
1128
1129      class PDU_Assoc : public IPDU_Observable,
1130                                  ISocketObserver {
1131        public:
1132          COMSTACK comstack(const char *type_and_host, void **vp);
1133          // Create object using specified socketObservable
1134          PDU_Assoc(ISocketObservable *socketObservable);
1135          // Create Object using existing comstack
1136          PDU_Assoc(ISocketObservable *socketObservable,
1137                   COMSTACK cs);
1138          // Close socket and destroy object.
1139          virtual ~PDU_Assoc();
1140          // Clone the object
1141          IPDU_Observable *clone();
1142          // Send PDU
1143          int send_PDU(const char *buf, int len);
1144          // connect to server (client role)
1145          void connect(IPDU_Observer *observer, const char *addr);
1146          // listen for clients (server role)
1147          void listen(IPDU_Observer *observer, const char *addr);
1148          // Socket notification
1149          void socketNotify(int event);
1150          // Close socket
1151          void close();
1152          // Close and destroy
1153          void destroy();
1154          // Set Idle Time
1155          void idleTime (int timeout);
1156          // Child start...
1157          virtual void childNotify(COMSTACK cs);
1158      };
1159     </synopsis>
1160    </section>
1161    <section id="Z_Assoc">
1162     <title>Z_Assoc</title>
1163     <para>
1164      This class implements the interface
1165      <link linkend="IPDU_Observer">IPDU_Obserer</link>.
1166      This object implements a Z39.50 client/server channel AKA
1167      Z-Association.
1168     </para>
1169     <synopsis>
1170      #include &lt;yazpp/z-assoc.h>
1171
1172      class Z_Assoc : public IPDU_Observer {
1173        public:
1174          // Create object using the PDU Observer specified
1175          Z_Assoc(IPDU_Observable *the_PDU_Observable);
1176          // Destroy association and close PDU Observer
1177          virtual ~Z_Assoc();
1178          // Receive PDU
1179          void recv_PDU(const char *buf, int len);
1180          // Connect notification
1181          virtual void connectNotify() = 0;
1182          // Failure notification
1183          virtual void failNotify() = 0;
1184          // Timeout notification
1185          virtual void timeoutNotify() = 0;
1186          // Timeout specify
1187          void timeout(int timeout);
1188          // Begin Z39.50 client role
1189          void client(const char *addr);
1190          // Begin Z39.50 server role
1191          void server(const char *addr);
1192          // Close connection
1193          void close();
1194
1195          // Decode Z39.50 PDU.
1196          Z_APDU *decode_Z_PDU(const char *buf, int len);
1197          // Encode Z39.50 PDU.
1198          int encode_Z_PDU(Z_APDU *apdu, char **buf, int *len);
1199          // Send Z39.50 PDU
1200          int send_Z_PDU(Z_APDU *apdu);
1201          // Receive Z39.50 PDU
1202          virtual void recv_Z_PDU(Z_APDU *apdu) = 0;
1203          // Create Z39.50 PDU with reasonable defaults
1204          Z_APDU *create_Z_PDU(int type);
1205          // Request Alloc
1206          ODR odr_encode ();
1207          ODR odr_decode ();
1208          ODR odr_print ();
1209          void set_APDU_log(const char *fname);
1210          const char *get_APDU_log();
1211
1212          // OtherInformation
1213          void get_otherInfoAPDU(Z_APDU *apdu, Z_OtherInformation ***oip);
1214          Z_OtherInformationUnit *update_otherInformation (
1215                Z_OtherInformation **otherInformationP, int createFlag,
1216                int *oid, int categoryValue, int deleteFlag);
1217          void set_otherInformationString (
1218                Z_OtherInformation **otherInformationP,
1219                int *oid, int categoryValue,
1220                const char *str);
1221          void set_otherInformationString (
1222                Z_OtherInformation **otherInformation,
1223                int oidval, int categoryValue,
1224                const char *str);
1225          void set_otherInformationString (
1226                Z_APDU *apdu,
1227                int oidval, int categoryValue,
1228                const char *str);
1229
1230          Z_ReferenceId *getRefID(char* str);
1231          Z_ReferenceId **get_referenceIdP(Z_APDU *apdu);
1232          void transfer_referenceId(Z_APDU *from, Z_APDU *to);
1233
1234          const char *get_hostname();
1235      };
1236     </synopsis>
1237    </section>
1238    <section id="IR_Assoc">
1239     <title>IR_Assoc</title>
1240     <para>
1241      This object is just a specialization of
1242      <link linkend="Z_Assoc">Z_Assoc</link> and provides
1243      more facilities for the Z39.50 client role.
1244     </para>
1245     <synopsis>
1246      #include &lt;yazpp/ir-assoc.h>
1247
1248      class IR_Assoc : public Z_Assoc {
1249        ...
1250      };
1251     </synopsis>
1252     <para>
1253      The example client, <filename>yaz-my-client.cpp</filename>,
1254      uses this class.
1255     </para>
1256    </section>
1257    <section id="Z_Server">
1258     <title>Z_Server</title>
1259     <para>
1260      This object is just a specialization of
1261      <link linkend="Z_Assoc">Z_Assoc</link> and provides
1262      more facilities for the Z39.50 server role.
1263     </para>
1264     <synopsis>
1265      #include &lt;yazpp/z-server.h>
1266
1267      class My_Server : public Z_Server {
1268        ...
1269      };
1270     </synopsis>
1271     <para>
1272      The example server, <filename>yaz-my-server.cpp</filename>,
1273      uses this class.
1274     </para>
1275    </section>
1276   </section>
1277  </chapter>
1278  <appendix id="license">
1279   <title>License</title>
1280   <para>
1281    Copyright &copy; &copyright-year; Index Data.
1282   </para>
1283   <para>
1284    All rights reserved.
1285   </para>
1286   <para>
1287    Redistribution and use in source and binary forms, with or without
1288    modification, are permitted provided that the following conditions are met:
1289   </para>
1290   <itemizedlist>
1291    <listitem>
1292     <para>
1293      Redistributions of source code must retain the above copyright
1294      notice, this list of conditions and the following disclaimer.
1295     </para>
1296    </listitem>
1297    <listitem>
1298     <para>
1299      Redistributions in binary form must reproduce the above copyright
1300      notice, this list of conditions and the following disclaimer in the
1301      documentation and/or other materials provided with the distribution.
1302     </para>
1303    </listitem>
1304    <listitem>
1305     <para>
1306      Neither the name of Index Data nor the names of its contributors
1307      may be used to endorse or promote products derived from this
1308      software without specific prior written permission.
1309     </para>
1310    </listitem>
1311   </itemizedlist>
1312   <para>
1313    THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
1314    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1315    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1316    DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR
1317    ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1318    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1319    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1320    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1321    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1322    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1323    SUCH DAMAGE.
1324   </para>
1325  </appendix>
1326 </book>
1327
1328 <!-- Keep this comment at the end of the file
1329 Local variables:
1330 mode: nxml
1331 nxml-child-indent: 1
1332 End:
1333 -->
1334