Net-Z3950-SimpleServer

 view release on metacpan or  search on metacpan

SimpleServer.pm  view on Meta::CPAN


The argument hash passed to the init handler has the form

  $args = {
				    ## Response parameters:

	     PEER_NAME =>  "",      ## Name or IP address of connecting client
	     IMP_ID    =>  "",      ## Z39.50 Implementation ID
	     IMP_NAME  =>  "",      ## Z39.50 Implementation name
	     IMP_VER   =>  "",      ## Z39.50 Implementation version
	     ERR_CODE  =>  0,       ## Error code, cnf. Z39.50 manual
	     ERR_STR   =>  "",      ## Error string (additional info.)
	     USER      =>  "xxx"    ## If Z39.50 authentication is used,
	     			    ## this member contains user name
	     PASS      =>  "yyy"    ## Under same conditions, this member
	     			    ## contains the password in clear text
	     GROUP     =>  "zzz"    ## Under same conditions, this member
				    ## contains the group in clear text
	     GHANDLE   =>  $obj     ## Global handle specified at creation
	     HANDLE    =>  undef    ## Handler of Perl data structure
	  };

The HANDLE member can be used to store any scalar value which will then
be provided as input to all subsequent calls (i.e. for searching, record
retrieval, etc.). A common use of the handle is to store a reference to
a hash which may then be used to store session-specific parameters.
If you have any session-specific information (such as a list of
result sets or a handle to a back-end search engine of some sort),
it is always best to store them in a private session structure -
rather than leaving them in global variables in your script.

The Implementation ID, name and version are only really used by Z39.50
client developers to see what kind of server they're dealing with.
Filling these in is optional.

The ERR_CODE should be left at 0 (the default value) if you wish to
accept the connection. Any other value is interpreted as a failure
and the client will be shown the door, with the code and the
associated additional information, ERR_STR returned.

=head2 Search handler

Similarly, the search handler is called with a reference to an
anonymous hash. The structure is the following:

  $args = {
                                     ## Request parameters:

    GHANDLE             =>  $obj     # Global handle specified at creation
    HANDLE              =>  ref,     # Your session reference.
    SETNAME             =>  "id",    # ID of the result set
    REPL_SET            =>  0,       # Replace set if already existing?
    DATABASES           =>  ["xxx"], # Reference to a list of databases to search
    QUERY               =>  "query", # The query expression as a PQF string
    RPN                 =>  $obj,    # Reference to a Net::Z3950::APDU::Query
    CQL                 =>  $x,      # A CQL query, if this is provided instead of Type-1
    SRW_SORTKEYS        =>  $x,      # XXX to be described
    PID                 =>  $x,      # XXX to be described
    PRESENT_NUMBER      =>  $x,      # XXX to be described
    EXTRA_ARGS          =>  $x,      # XXX to be described
    INPUTFACETS         =>  $x,      # Specification of facets required: see below.

                                     ## Response parameters:

    ERR_CODE            =>  0,       # Error code (0=Successful search)
    ERR_STR             =>  "",      # Error string
    HITS                =>  0,       # Number of matches
    ESTIMATED_HIT_COUNT =>  $x,      # XXX to be described
    EXTRA_RESPONSE_DATA =>  $x,      # XXX to be described
    OUTPUTFACETS        =>  $x       # Facets returned: see below.
  };

Note that a search which finds 0 hits is considered successful in
Z39.50 terms - you should only set the ERR_CODE to a non-zero value
if there was a problem processing the request. The Z39.50 standard
provides a comprehensive list of standard diagnostic codes, and you
should use these whenever possible.

=head3 Query structures

In Z39.50, the most comment kind of query is the so-called Type-1
_query, a tree-structure of terms combined by operators, the terms
being qualified by lists of attributes.

The QUERY parameter presented this tree to the search function in the
Prefix Query Format (PQF) which is used in many applications based on
the YAZ toolkit. The full grammar is described in the YAZ manual.

The following are all examples of valid queries in the PQF.

	dylan

	"bob dylan"

	@or "dylan" "zimmerman"

	@set Result-1

	@or @and bob dylan @set Result-1

	@and @attr 1=1 "bob dylan" @attr 1=4 "slow train coming"

	@attrset @attr 4=1 @attr 1=4 "self portrait"

You will need to write a recursive function or something similar to
parse incoming query expressions, and this is usually where a lot of
the work in writing a database-backend happens. Fortunately, you don't
need to support any more functionality than you want to. For instance,
it is perfectly legal to not accept boolean operators, but you should
try to return good error codes if you run into something you can't or
won't support.

A more convenient alternative to the QUERY member is the RPN
member, which is a reference to a Net::Z3950::APDU::Query object
representing the RPN query tree.  The structure of that object is
supposed to be self-documenting, but here's a brief summary of what
you get:

=over 4

=item *

C<Net::Z3950::APDU::Query> is a hash with two fields:

Z<>

=over 4

=item C<attributeSet>

SimpleServer.pm  view on Meta::CPAN


=item C<attributeType>

An integer indicating the type of the attribute - for example, under
the BIB-1 attribute set, type 1 indicates a ``use'' attribute, type 2
a ``relation'' attribute, etc.

=item C<attributeValue>

An integer or string indicating the value of the attribute - for example, under
BIB-1, if the attribute type is 1, then value 4 indicates a title
search and 7 indicates an ISBN search; but if the attribute type is
2, then value 4 indicates a ``greater than or equal'' search, and 102
indicates a relevance match.

=back

=back

All of these classes except C<Attributes> and C<Attribute> are
subclasses of the abstract class C<Net::Z3950::RPN::Node>.  That class
has a single method, C<toPQF()>, which may be used to turn an RPN
tree, or part of one, back into a textual prefix query.

Note that, apart to C<toPQF()>, none of these classes have any methods at
all: the blessing into classes is largely just a documentation thing
so that, for example, if you do

	{ use Data::Dumper; print Dumper($args->{RPN}) }

you get something fairly human-readable.  But of course, the type
distinction between the three different kinds of boolean node is
important.

By adding your own methods to these classes (building what I call
``augmented classes''), you can easily build code that walks the tree
of the incoming RPN.  Take a look at C<samples/render-search.pl> for a
sample implementation of such an augmented classes technique.

Finally, when SimpleServer is invoked using SRU/SRW (and indeed using
Z39.50 if the unusual type-104 query is used), the query that is
_passed is expressed in CQL, the Contextual Query Language. In this
case, the query string is made available in the CQL argument.

=head3 Facets

Servers may support the provision of facets -- counted lists of field
values which may subsequently be be used as query terms to narrow the
search.

In SRU, facets may be requested by the C<facetLimit> parameter,
L<as documented in the OASIS standard that formalises the SRU specification|http://docs.oasis-open.org/search-ws/searchRetrieve/v1.0/os/part3-sru2.0/searchRetrieve-v1.0-os-part3-sru2.0.html#_Toc324162453>.
Its value is a string consisting of a comma-separated list of facet
specifications. Each facet specification consists of of a count, a
colon and a fieldname. For example, C<facetLimit=10:title,5:author>
asks for ten title facets and five author facets.

=head4 Request format

The facet request is passed to the search-handler function in the
INPUTFACETS parameter. Its value is rather complex, due to backwards
compatibility with Z39.50:

=over 4

=item *

The top-level value is a C<Net::Z3950::FacetList> array.

=item *

This is an array of C<Net::Z3950::FacetField> objects.

=item *

Each of these is an object with two members, C<attributes> and
C<terms>.

=item *

C<attributes> has type C<Net::Z3950::RPN::Attributes> and is a list of
objects of type C<Net::Z3950::RPN::Attribute>.

=item *

Each attribute has two elements, C<attributeType> and
C<attributeValue>. Each value is interpreted according to its
type. The meanings of the types are as follows:

=over 4

=item 1

The name of the field to provide values of the facets.

=item 2

The order in which to sort the values. (But it's not clear how this is
to be interpreted: it may be implementation dependent.)

=item 3

The number of facets to include for the specified field.

=item 4

The first facet to include in the response: for example, if this is
11, then the first ten facts should be skipped.

=back

=back

So for example, the SRU facet specification
C<facetLimit=10:title,5:author> would be translated as a
C<Net::Z3950::FacetList> list of two C<Net::Z3950::FacetField>s. The
C<attributes> of the first would be [1="title", 3=10], and those of
the second would be [1="author", 3=5].

It is not clear what the purpose of C<terms> is, but for the record,
this is how it is represented:

=over 4

=item *

C<terms> is a C<Net::Z3950::FacetTerms> array.

=item *

This is an array of C<Net::Z3950::FacetTerm> objects.

=item *

Each of these is an object with two members, C<term> and C<count>. The
first of these is an integer, the second a string.

=back

=head4 Response format

Having generated facets corresponding to the request, the search
handler should return them in the C<OUTPUTFACETS> argument. The
structure of this response is similar to that of the request:

=over 4

=item *

The top-level value is a C<Net::Z3950::FacetList> array.

=item *

This is an array of C<Net::Z3950::FacetField> objects.

=item *

Each of these is an object with two members, C<attributes> and
C<terms>.

=item *

C<attributes> has type C<Net::Z3950::RPN::Attributes> and is a list of
objects of type C<Net::Z3950::RPN::Attribute>.

=item *

Each attribute has two elements, C<attributeType> and
C<attributeValue>. Each value is interpreted according to its
type. The meanings of the types are as follows:

=over 4

=item 1

The name of the field for which terms are provided.

=back

(That is the only type used.)

=item *

C<terms> is a C<Net::Z3950::FacetTerms> array.

=item *

This is an array of C<Net::Z3950::FacetTerm> objects.

=item *

Each of these is an object with two members, C<term> and C<count>. The
first of these is a string containing one of the facet terms, and the
second is an integer indicating how many times it occurs in the
records that were found by the search.

=back

The example SimpleServer applicaation server C<ztest.pl> includes code
that shows how to examine the INPUTFACETS data structure and create
the OUTPUTFACETS structure.

=head2 Present handler

The presence of a present handler in a SimpleServer front-end is optional.
Each time a client wishes to retrieve records, the present service is
called. The present service allows the origin to request a certain number
of records retrieved from a given result set.
When the present handler is called, the front-end server should prepare a
result set for fetching. In practice, this means to get access to the
data from the backend database and store the data in a temporary fashion
for fast and efficient fetching. The present handler does *not* fetch
anything. This task is taken care of by the fetch handler, which will be
called the correct number of times by the YAZ library. More about this
below.
If no present handler is implemented in the front-end, the YAZ toolkit
will take care of a minimum of preparations itself. This default present
handler is sufficient in many situations, where only a small amount of
records are expected to be retrieved. If on the other hand, large result
sets are likely to occur, the implementation of a reasonable present
handler can gain performance significantly.

The information exchanged between client and present handle is:

  $args = {
				    ## Client/server request:

	     GHANDLE   =>  $obj     ## Global handle specified at creation
	     HANDLE    =>  ref,     ## Reference to datastructure
	     SETNAME   =>  "id",    ## Result set ID
	     START     =>  xxx,     ## Start position
	     COMP      =>  "",	    ## Desired record composition
	     SCHEMA_OID => "",      ## Z39.50 schema (OID), if any
	     NUMBER    =>  yyy,	    ## Number of requested records


				    ## Response parameters:

	     HITS      =>  zzz,	    ## Number of returned records
	     ERR_CODE  =>  0,	    ## Error code
	     ERR_STR   =>  ""	    ## Error message
          };


=head2 Fetch handler

The fetch handler is asked to retrieve a SINGLE record from a given
result set (the front-end server will automatically call the fetch
handler as many times as required).

The parameters exchanged between the server and the fetch handler are:

  $args = {
				    ## Client/server request:

	     GHANDLE   =>  $obj     ## Global handle specified at creation
	     HANDLE    =>  ref	    ## Reference to data structure
	     SETNAME   =>  "id"     ## ID of the requested result set
	     OFFSET    =>  nnn      ## Record offset number
	     REQ_FORM  =>  "n.m.k.l"## Client requested format OID
	     COMP      =>  "xyz"    ## Formatting instructions



( run in 1.643 second using v1.01-cache-2.11-cpan-39bf76dae61 )