X-Git-Url: http://git.indexdata.com/?p=simpleserver-moved-to-github.git;a=blobdiff_plain;f=SimpleServer.pm;h=003efeab45c725a48bab915c4b938e85f6c45f7f;hp=dd8681bc810de8b07a5c12285cabaa3dc50318e2;hb=73cbad3a91f1f244b357cfac07c15f176d18d624;hpb=ee6b14a657009ef2941c524d502b2edaf104341a diff --git a/SimpleServer.pm b/SimpleServer.pm index dd8681b..003efea 100644 --- a/SimpleServer.pm +++ b/SimpleServer.pm @@ -25,7 +25,7 @@ ## ## -## $Id: SimpleServer.pm,v 1.30 2006-12-01 09:38:37 sondberg Exp $ +## $Id: SimpleServer.pm,v 1.40 2007-08-20 11:06:09 mike Exp $ package Net::Z3950::SimpleServer; @@ -39,7 +39,7 @@ require AutoLoader; @ISA = qw(Exporter AutoLoader DynaLoader); @EXPORT = qw( ); -$VERSION = '1.04'; +$VERSION = '1.07'; bootstrap Net::Z3950::SimpleServer $VERSION; @@ -69,6 +69,13 @@ sub launch_server { my $self = shift; my @args = @_; + ### This modal internal interface, in which we set a bunch of + # globals and then call start_server(), is asking for + # trouble. Instead, we should just pass the $self object + # as a parameter into start_server(). + if (defined($self->{GHANDLE})) { + set_ghandle($self->{GHANDLE}); + } if (defined($self->{INIT})) { set_init_handler($self->{INIT}); } @@ -95,16 +102,60 @@ sub launch_server { # Register packages that we will use in translated RPNs +package Net::Z3950::RPN::Node; package Net::Z3950::APDU::Query; +our @ISA = qw(Net::Z3950::RPN::Node); package Net::Z3950::APDU::OID; package Net::Z3950::RPN::And; +our @ISA = qw(Net::Z3950::RPN::Node); package Net::Z3950::RPN::Or; +our @ISA = qw(Net::Z3950::RPN::Node); package Net::Z3950::RPN::AndNot; +our @ISA = qw(Net::Z3950::RPN::Node); package Net::Z3950::RPN::Term; +our @ISA = qw(Net::Z3950::RPN::Node); package Net::Z3950::RPN::RSID; +our @ISA = qw(Net::Z3950::RPN::Node); package Net::Z3950::RPN::Attributes; package Net::Z3950::RPN::Attribute; + +# Utility method for re-rendering Type-1 query back down to PQF +package Net::Z3950::RPN::Node; + +sub toPQF { + my $this = shift(); + my $class = ref $this; + + if ($class eq "Net::Z3950::APDU::Query") { + my $res = ""; + my $set = $this->{attributeSet}; + $res .= "\@attrset $set " if defined $set; + return $res . $this->{query}->toPQF(); + } elsif ($class eq "Net::Z3950::RPN::Or") { + return '@or ' . $this->[0]->toPQF() . ' ' . $this->[1]->toPQF(); + } elsif ($class eq "Net::Z3950::RPN::And") { + return '@and ' . $this->[0]->toPQF() . ' ' . $this->[1]->toPQF(); + } elsif ($class eq "Net::Z3950::RPN::AndNot") { + return '@not ' . $this->[0]->toPQF() . ' ' . $this->[1]->toPQF(); + } elsif ($class eq "Net::Z3950::RPN::RSID") { + return '@set ' . $this->{id}; + } elsif ($class ne "Net::Z3950::RPN::Term") { + die "unknown PQF node-type '$class'"; + } + + my $res = ""; + foreach my $attr (@{ $this->{attributes} }) { + $res .= "\@attr "; + my $set = $attr->{attributeSet}; + $res .= "$set " if defined $set; + $res .= $attr->{attributeType} . "=" . $attr->{attributeValue} . " "; + } + + return $res . $this->{term}; +} + + # Must revert to original package for Autoloader's benefit package Net::Z3950::SimpleServer; @@ -151,15 +202,14 @@ Net::Z3950::SimpleServer - Simple Perl API for building Z39.50 servers. } } - ## Register custom event handlers: + my $z = new Net::Z3950::SimpleServer(GHANDLE = $someObject, + INIT => \&my_init_handler, + CLOSE => \&my_close_handler, + SEARCH => \&my_search_handler, + FETCH => \&my_fetch_handler); - my $z = new Net::Z3950::SimpleServer( INIT => \&my_init_handler, - CLOSE => \&my_close_handler, - SEARCH => \&my_search_handler, - FETCH => \&my_fetch_handler); ## Launch server: - $z->launch_server("ztest.pl", @ARGV); =head1 DESCRIPTION @@ -218,6 +268,11 @@ means of the SimpleServer object constructor FETCH => \&my_fetch_handler, EXPLAIN => \&my_explain_handler); +In addition, the arguments to the constructor may include GHANDLE, a +global handle which is made available to each invocation of every +callback function. This is typically a reference to either a hash or +an object. + If you want your SimpleServer to start a thread (threaded mode) to handle each incoming Z39.50 request instead of forking a process (forking mode), you need to register the handlers by symbol rather @@ -269,6 +324,7 @@ The argument hash passed to the init handler has the form ## this member contains user name PASS => "yyy" ## Under same conditions, this member ## contains the password in clear text + GHANDLE => $obj ## Global handler specified at creation HANDLE => undef ## Handler of Perl data structure }; @@ -298,6 +354,7 @@ mous hash. The structure is the following: $args = { ## Request parameters: + GHANDLE => $obj ## Global handler specified at creation HANDLE => ref, ## Your session reference. SETNAME => "id", ## ID of the result set REPL_SET => 0, ## Replace set if already existing? @@ -405,9 +462,6 @@ of the result-set is in the C element. =back -(I guess I should make a superclass C and make -all of these subclasses of it. Not done that yet, but will do one day.) - =back =over 4 @@ -456,7 +510,7 @@ a ``relation'' attribute, etc. =item C -An integer indicating the value of the attribute - for example, under +An integer or string indicating the value of the attribute - for example, under BIB-1, if the attribute type is 1, then value 4 indictates a title search and 7 indictates an ISBN search; but if the attribute type is 2, then value 4 indicates a ``greater than or equal'' search, and 102 @@ -466,7 +520,12 @@ indicates a relevance match. =back -Note that, at the moment, none of these classes have any methods at +All of these classes except C and C are +subclasses of the abstract class C. That class +has a single method, C, which may be used to turn an RPN +tree, or part of one, back into a textual prefix query. + +Note that, apart to C, 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 @@ -507,6 +566,7 @@ The informations exchanged between client and present handle are: $args = { ## Client/server request: + GHANDLE => $obj ## Global handler specified at creation HANDLE => ref, ## Reference to datastructure SETNAME => "id", ## Result set ID START => xxx, ## Start position @@ -533,6 +593,7 @@ The parameters exchanged between the server and the fetch handler are $args = { ## Client/server request: + GHANDLE => $obj ## Global handler specified at creation HANDLE => ref ## Reference to data structure SETNAME => "id" ## ID of the requested result set OFFSET => nnn ## Record offset number @@ -581,8 +642,13 @@ an index of a book, you always find something! The parameters exchanged are $args = { ## Client request - HANDLE => $ref ## Reference to data structure + GHANDLE => $obj, ## Global handler specified at creation + HANDLE => $ref, ## Reference to data structure + DATABASES => ["xxx"], ## Reference to a list of data- + ## bases to search TERM => 'start', ## The start term + RPN => $obj, ## Reference to a Net::Z3950::RPN::Term + NUMBER => xx, ## Number of requested terms POS => yy, ## Position of starting point ## within returned list @@ -615,20 +681,31 @@ should point at a data structure of this kind, ... ]; -The $status flag should be assigned one of two values: +The $status flag is only meaningful after a successful scan, and +should be assigned one of two values: - Net::Z3950::SimpleServer::ScanSuccess On success (default) - Net::Z3950::SimpleServer::ScanPartial Less terms returned than requested + Net::Z3950::SimpleServer::ScanSuccess Full success (default) + Net::Z3950::SimpleServer::ScanPartial Fewer terms returned than requested The STEP member contains the requested number of entries in the term-list between two adjacent entries in the response. +A better alternative to the TERM member is the the RPN +member, which is a reference to a Net::Z3950::RPN::Term object +representing the scan cloause. The structure of that object is the +same as for Term objects included as part of the RPN tree passed to +search handlers. This is more useful than the simple TERM because it +includes attributes (e.g. access points associated with the term), +which are discarded by the TERM element. + =head2 Close handler -The argument hash recieved by the close handler has one element only: +The argument hash recieved by the close handler has two elements only: $args = { ## Server provides: + + GHANDLE => $obj ## Global handler specified at creation HANDLE => ref ## Reference to data structure };