<chapter id="soap"><title>SOAP and SRU</title>
  <sect1 id="soap.introduction"><title>Introduction</title>
    <para>
      &yaz; uses a very simple implementation of 
      <ulink url="&url.soap;">SOAP</ulink> that only,
      currenly, supports what is sufficient to offer SRU SOAP functionality.
      The implementation uses the 
      <ulink url="&url.libxml2.api.tree;">tree API</ulink> of
      libxml2 to encode and decode SOAP packages.
    </para>
    <para>
      Like the Z39.50 ASN.1 module, the &yaz; SRU implementation uses
      simple C structs to represent SOAP packages as well as
      HTTP packages.
    </para>
  </sect1>
  <sect1 id="soap.http"><title>HTTP</title>
    <para>
      &yaz; only offers HTTP as transport carrier for SOAP, but it is
      relatively easy to change that.
    </para>
    <para>
      The following definition of <literal>Z_GDU</literal> (Generic Data
      Unit) allows for both HTTP and Z39.50 in one packet.
    </para>
    <synopsis>
#include &lt;yaz/zgdu.h&gt;

#define Z_GDU_Z3950         1
#define Z_GDU_HTTP_Request  2
#define Z_GDU_HTTP_Response 3
typedef struct {
  int which;
  union {
    Z_APDU *z3950;
    Z_HTTP_Request *HTTP_Request;
    Z_HTTP_Response *HTTP_Response;
  } u;
} Z_GDU ;
    </synopsis>
    <para>
      The corresponding Z_GDU encoder/decoder is <function>z_GDU</function>.
      The <literal>z3950</literal> is any of the known BER encoded Z39.50
      APDUs.
      <literal>HTTP_Request</literal> and <literal>HTTP_Response</literal>
      is the HTTP Request and Response respectively.
    </para>
  </sect1>
  <sect1 id="soap.xml"><title>SOAP Packages</title>
    <para>
      Every SOAP package in &yaz; is represented as follows:
      <synopsis>
#include &lt;yaz/soap.h&gt;

typedef struct {
    char *fault_code;
    char *fault_string;
    char *details;
} Z_SOAP_Fault;

typedef struct {
    int no;
    char *ns;
    void *p;
} Z_SOAP_Generic;

#define Z_SOAP_fault 1
#define Z_SOAP_generic 2
#define Z_SOAP_error 3
typedef struct {
    int which;
    union {
        Z_SOAP_Fault   *fault;
        Z_SOAP_Generic *generic;
        Z_SOAP_Fault   *soap_error;
    } u;
    const char *ns;
} Z_SOAP;
      </synopsis>
    </para>
    <para>
      The <literal>fault</literal> and <literal>soap_error</literal>
      arms represent both a SOAP fault - struct
      <literal>Z_SOAP_Fault</literal>. Any other generic
        (valid) package is represented by <literal>Z_SOAP_Generic</literal>.
    </para>
    <para>
      The <literal>ns</literal> as part of <literal>Z_SOAP</literal>
      is the namespace for SOAP itself and reflects the SOAP
      version. For version 1.1 it is
      <literal>http://schemas.xmlsoap.org/soap/envelope/</literal>,
      for version 1.2 it is
      <literal>http://www.w3.org/2001/06/soap-envelope</literal>.
    </para>
    <synopsis>
int z_soap_codec(ODR o, Z_SOAP **pp,
                 char **content_buf, int *content_len,
                 Z_SOAP_Handler *handlers);
    </synopsis>
    <para>
      The <literal>content_buf</literal> and <literal>content_len</literal>
      is XML buffer and length of buffer respectively.
    </para>
    <para>
      The <literal>handlers</literal> is a list of SOAP codec
      handlers - one handler for each service namespace. For SRU SOAP, the
      namespace would be <literal>http://www.loc.gov/zing/srw/v1.0/</literal>.
    </para>
    <para>
      When decoding, the <function>z_soap_codec</function>
      inspects the XML content
      and tries to match one of the services namespaces of the
      supplied handlers. If there is a match a handler function
      is invoked which decodes that particular SOAP package.
      If successful, the returned <literal>Z_SOAP</literal> package will be
      of type <literal>Z_SOAP_Generic</literal>.
      Member <literal>no</literal> is
      set the offset of handler that matched; <literal>ns</literal>
      is set to namespace of matching handler; the void pointer
      <literal>p</literal> is set to the C data structure assocatiated
      with the handler.
    </para>
    <para>
      When a NULL namespace is met (member <literal>ns</literal> bwlow),
      that specifies end-of-list.
    </para>
    <para>
      Each handler is defined as follows:
      <synopsis>
typedef struct {
    char *ns;
    void *client_data;
    Z_SOAP_fun f;
} Z_SOAP_Handler;
      </synopsis>
      The <literal>ns</literal> is namespace of service associated with
      handler <literal>f</literal>. <literal>client_data</literal>
      is user-defined data which is passed to handler.
    </para>
    <para>
      The prototype for a SOAP service handler is:
      <synopsis>
int handler(ODR o, void * ptr, void **handler_data,
            void *client_data, const char *ns);
      </synopsis>
      The <parameter>o</parameter> specifies the mode (decode/encode)
      as usual. The second argument, <parameter>ptr</parameter>,
      is a libxml2 tree node pointer (<literal>xmlNodePtr</literal>)
      and is a pointer to the <literal>Body</literal> element
      of the SOAP package. The <parameter>handler_data</parameter>
      is an opaque pointer to a C definitions associated with the
      SOAP service. <parameter>client_data</parameter> is the pointer
      which was set as part of the <literal>Z_SOAP_handler</literal>.
      Finally, <parameter>ns</parameter> the service namespace.
    </para>
  </sect1>
  <sect1 id="soap.srw"><title>SRU</title>
    <para>
      SRU SOAP is just one implementation of a SOAP handler as described
      in the previous section.
      The encoder/decoder handler for SRU is defined as
      follows:
      <synopsis>
#include &lt;yaz/srw.h&gt;

int yaz_srw_codec(ODR o, void * pptr,
                  Z_SRW_GDU **handler_data,
                  void *client_data, const char *ns);
      </synopsis>
      Here, <literal>Z_SRW_GDU</literal> is either
      searchRetrieveRequest or a searchRetrieveResponse. 
    </para>
    <note>
      <para>
        The xQuery and xSortKeys are not handled yet by
        the SRW implementation of &yaz;. Explain is also missing.
        Future versions of &yaz; will include these features.
      </para>
    </note>
    <para>
      The definition of searchRetrieveRequest is:
      <synopsis>
typedef struct {

#define Z_SRW_query_type_cql  1
#define Z_SRW_query_type_xcql 2
#define Z_SRW_query_type_pqf  3
    int query_type;
    union {
        char *cql;
        char *xcql;
        char *pqf;
    } query;

#define Z_SRW_sort_type_none 1
#define Z_SRW_sort_type_sort 2
#define Z_SRW_sort_type_xSort 3
    int sort_type;
    union {
        char *none;
        char *sortKeys;
        char *xSortKeys;
    } sort;
    int  *startRecord;
    int  *maximumRecords;
    char *recordSchema;
    char *recordPacking;
    char *database;
} Z_SRW_searchRetrieveRequest;
      </synopsis>
      Please observe that data of type xsd:string is represented
      as a char pointer (<literal>char *</literal>). A null pointer
      means that the element is absent.
      Data of type xsd:integer is representd as a pointer to
      an int (<literal>int *</literal>). Again, a null pointer
      us used for absent elements.
    </para>
    <para>
      The SearchRetrieveResponse has the following definition.
      <synopsis>
typedef struct {
    int * numberOfRecords;
    char * resultSetId;
    int * resultSetIdleTime;
    
    Z_SRW_record *records;
    int num_records;

    Z_SRW_diagnostic *diagnostics;
    int num_diagnostics;
    int *nextRecordPosition;
} Z_SRW_searchRetrieveResponse;
      </synopsis>
      The <literal>num_records</literal> and <literal>num_diagnostics</literal>
      is number of returned records and diagnostics respectively and also
      correspond to the "size of" arrays <literal>records</literal>
      and <literal>diagnostics</literal>.
    </para>
    <para>
      A retrieval record is defined as follows:
      <synopsis>
typedef struct {
    char *recordSchema;
    char *recordData_buf;
    int recordData_len;
    int *recordPosition;
} Z_SRW_record;
      </synopsis>
      The record data is defined as a buffer of some length so that
      data can be of any type. SRW 1.0 currenly doesn't allow for this
      (only XML), but future versions might do.
    </para>
    <para>
      And, a diagnostic as:
      <synopsis>
typedef struct {
    int  *code;
    char *details;
} Z_SRW_diagnostic;
      </synopsis>
    </para>
  </sect1>
</chapter>

