From 3ba44bb7023ad2e1d312b7858066525a536522c3 Mon Sep 17 00:00:00 2001 From: mike Date: Tue, 13 Jun 2006 16:44:20 +0000 Subject: [PATCH] - Add new function Net::Z3950::ZOOM::query_ccl2rpn(), for client-side CCL compilation. - Add new ZOOM::Query::CCL2RPN class, encapsulating CCL compiler functionality as a Query subclass. This allows client-side CCL to be used for both search and scan. - Add two new error-codes, CCL_CONFIG and CCL_PARSE, returned by the client-side CCL facilities. - Supply a sample CCL profile file: samples/ccl/default.bib, copied from the same-named file distributed with YAZ. - The test-scripts t/12-query.t and t/22-query.t are extended to also test client-side CCL searching. - The test-scripts t/15-scan.t and t/25-scan.t are extended to also test client-side CCL scanning. - Documentation updated to describe use of CCL. --- Changes | 16 +++++++++++++++- MANIFEST | 3 ++- Makefile.PL | 6 +++--- ZOOM.xs | 8 +++++++- lib/Net/Z3950/ZOOM.pm | 8 +++++--- lib/ZOOM.pm | 24 +++++++++++++++++++++++- lib/ZOOM.pod | 35 +++++++++++++++++++++++++++++++---- samples/ccl/default.bib | 45 +++++++++++++++++++++++++++++++++++++++++++++ t/15-scan.t | 22 +++++++++++++++++++--- t/25-scan.t | 18 +++++++++++++++--- 10 files changed, 165 insertions(+), 20 deletions(-) create mode 100644 samples/ccl/default.bib diff --git a/Changes b/Changes index c7288f9..3c8890c 100644 --- a/Changes +++ b/Changes @@ -1,8 +1,22 @@ -$Id: Changes,v 1.34 2006-06-05 16:34:40 mike Exp $ +$Id: Changes,v 1.35 2006-06-13 16:44:20 mike Exp $ Revision history for Perl extension Net::Z3950::ZOOM. 1.09 [IN PROGRESS] + - Add new function Net::Z3950::ZOOM::query_ccl2rpn(), for + client-side CCL compilation. + - Add new ZOOM::Query::CCL2RPN class, encapsulating CCL + compiler functionality as a Query subclass. This allows + client-side CCL to be used for both search and scan. + - Add two new error-codes, CCL_CONFIG and CCL_PARSE, + returned by the client-side CCL facilities. + - Supply a sample CCL profile file: samples/ccl/default.bib, + copied from the same-named file distributed with YAZ. + - The test-scripts t/12-query.t and t/22-query.t are extended + to also test client-side CCL searching. + - The test-scripts t/15-scan.t and t/25-scan.t are extended + to also test client-side CCL scanning. + - Documentation updated to describe use of CCL. - Add a nice, simple update client: samples/zoom/update.pl 1.08 Thu May 11 22:40:41 BST 2006 diff --git a/MANIFEST b/MANIFEST index 4725e94..c8daea4 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,4 +1,4 @@ -# $Id: MANIFEST,v 1.29 2006-06-05 16:35:49 mike Exp $ +# $Id: MANIFEST,v 1.30 2006-06-13 16:44:20 mike Exp $ Changes Makefile.PL @@ -35,6 +35,7 @@ lib/Net/Z3950.pm MANIFEST.SKIP META.yml Module meta-data (added by MakeMaker) samples/README +samples/ccl/default.bib samples/cql/pqf.properties samples/records/esdd0006.grs samples/net-z3950-zoom/zoomtst1.pl diff --git a/Makefile.PL b/Makefile.PL index 007986a..0f317b2 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,4 @@ -# $Id: Makefile.PL,v 1.10 2006-05-11 21:40:29 mike Exp $ +# $Id: Makefile.PL,v 1.11 2006-06-13 16:44:21 mike Exp $ use 5.008; use ExtUtils::MakeMaker; @@ -16,7 +16,7 @@ will also need to install "libyaz-dev" in order to build this module. } chomp($yazver); -check_version($yazver, "2.1.11"); +check_version($yazver, "2.1.21"); # For Windows use # $yazinc = '-Ic:\yaz\include' @@ -38,7 +38,7 @@ WriteMakefile( # Un-comment this if you add C files to link with later: # OBJECT => '$(O_FILES)', # link all the C files too # Use this to test for illegal code that GCC stupidly permits by default: -# OPTIMIZE => "-Wdeclaration-after-statement" + OPTIMIZE => "-Wdeclaration-after-statement -g -O0" ); diff --git a/ZOOM.xs b/ZOOM.xs index b49aa91..ce41632 100644 --- a/ZOOM.xs +++ b/ZOOM.xs @@ -1,4 +1,4 @@ -/* $Id: ZOOM.xs,v 1.40 2006-04-19 20:11:21 mike Exp $ */ +/* $Id: ZOOM.xs,v 1.41 2006-06-13 16:44:21 mike Exp $ */ #include "EXTERN.h" #include "perl.h" @@ -327,6 +327,12 @@ ZOOM_query_cql2rpn(s, str, conn) ZOOM_connection conn int +ZOOM_query_ccl2rpn(s, str, conn) + ZOOM_query s + const char* str + ZOOM_connection conn + +int ZOOM_query_prefix(s, str) ZOOM_query s const char* str diff --git a/lib/Net/Z3950/ZOOM.pm b/lib/Net/Z3950/ZOOM.pm index 25e354e..e45a470 100644 --- a/lib/Net/Z3950/ZOOM.pm +++ b/lib/Net/Z3950/ZOOM.pm @@ -1,4 +1,4 @@ -# $Id: ZOOM.pm,v 1.22 2006-06-05 16:36:24 mike Exp $ +# $Id: ZOOM.pm,v 1.23 2006-06-13 16:44:21 mike Exp $ package Net::Z3950::ZOOM; @@ -13,10 +13,10 @@ XSLoader::load('Net::Z3950::ZOOM', $VERSION); my($vs, $ss) = ("x" x 100, "x" x 100); # allocate space for these strings my $version = Net::Z3950::ZOOM::yaz_version($vs, $ss); -if ($version < 0x02010B && ! -f "/tmp/ignore-ZOOM-YAZ-version-mismatch") { +if ($version < 0x020115 && ! -f "/tmp/ignore-ZOOM-YAZ-version-mismatch") { warn <<__EOT__; *** WARNING! -ZOOM-Perl requires at least version 2.1.11 of YAZ, but is currently +ZOOM-Perl requires at least version 2.1.21 of YAZ, but is currently running against only version $vs (sys-string '$ss'). Some things may not work. __EOT__ @@ -40,6 +40,8 @@ sub ERROR_UNSUPPORTED_QUERY { 10009 } sub ERROR_INVALID_QUERY { 10010 } sub ERROR_CQL_PARSE { 10011 } sub ERROR_CQL_TRANSFORM { 10012 } +sub ERROR_CCL_CONFIG { 10013 } +sub ERROR_CCL_PARSE { 10014 } # Event types, as returned from connection_last_event() sub EVENT_NONE { 0 } diff --git a/lib/ZOOM.pm b/lib/ZOOM.pm index 8ac0c93..f553382 100644 --- a/lib/ZOOM.pm +++ b/lib/ZOOM.pm @@ -1,4 +1,4 @@ -# $Id: ZOOM.pm,v 1.33 2006-04-12 12:00:48 mike Exp $ +# $Id: ZOOM.pm,v 1.34 2006-06-13 16:44:21 mike Exp $ use strict; use warnings; @@ -41,6 +41,8 @@ sub UNSUPPORTED_QUERY { Net::Z3950::ZOOM::ERROR_UNSUPPORTED_QUERY } sub INVALID_QUERY { Net::Z3950::ZOOM::ERROR_INVALID_QUERY } sub CQL_PARSE { Net::Z3950::ZOOM::ERROR_CQL_PARSE } sub CQL_TRANSFORM { Net::Z3950::ZOOM::ERROR_CQL_TRANSFORM } +sub CCL_CONFIG { Net::Z3950::ZOOM::ERROR_CCL_CONFIG } +sub CCL_PARSE { Net::Z3950::ZOOM::ERROR_CCL_PARSE } # The following are added specifically for this OO interface sub CREATE_QUERY { 20001 } sub QUERY_CQL { 20002 } @@ -544,6 +546,26 @@ sub new { } +# It's distressing how very similar this is to CQL2RPN +package ZOOM::Query::CCL2RPN; +our @ISA = qw(ZOOM::Query); + +sub new { + my $class = shift(); + my($string, $conn) = @_; + + my $q = Net::Z3950::ZOOM::query_create() + or ZOOM::_oops(ZOOM::Error::CREATE_QUERY); + # check() throws the exception we want; but we only want it on failure! + Net::Z3950::ZOOM::query_ccl2rpn($q, $string, $conn->_conn()) == 0 + or $conn->_check(); + + return bless { + _query => $q, + }, $class; +} + + package ZOOM::Query::PQF; our @ISA = qw(ZOOM::Query); diff --git a/lib/ZOOM.pod b/lib/ZOOM.pod index 669db1c..fc72bdd 100644 --- a/lib/ZOOM.pod +++ b/lib/ZOOM.pod @@ -1,4 +1,4 @@ -# $Id: ZOOM.pod,v 1.35 2006-04-12 12:03:10 mike Exp $ +# $Id: ZOOM.pod,v 1.36 2006-06-13 16:44:21 mike Exp $ use strict; use warnings; @@ -50,12 +50,13 @@ C, C and C. -Of these, the Query class is abstract, and has three concrete +Of these, the Query class is abstract, and has four concrete subclasses: C, -C +C, +C and -C. +C. Finally, it also provides a C module which supplies a useful general-purpose logging facility. @@ -1020,6 +1021,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 +=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 + +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 class in the ZOOM Abstract @@ -1050,6 +1066,13 @@ if compilation fails, then diagnostic information is cached in the Connection and be retrieved using C<$conn-Eerrcode()> and related methods. + $conn->option(cclfile => "samples/ccl/default.bib"); + $q = new ZOOM::Query::CCL2RPN('ti=dinosaur', $conn); + +For the C subclass, too, the Connection must be +passed into the constructor, for the same reasons as when client-side +CQL compilation is used. + =head4 sortby() $q->sortby("1=4 >i 1=21 >s"); @@ -1226,6 +1249,10 @@ C, C, C, C, +C, +C, +C, +C, C, C, C, diff --git a/samples/ccl/default.bib b/samples/ccl/default.bib new file mode 100644 index 0000000..978d71d --- /dev/null +++ b/samples/ccl/default.bib @@ -0,0 +1,45 @@ +# CCL field mappings +# $Id: default.bib,v 1.1 2006-06-13 16:44:21 mike Exp $ +# +# The rule below is used when no fields are specified +term t=l,r s=al +# +# Simple rule for a field called "clean" +clean t=l,r +# +# Rules for some BIB-1 fields +au u=1 s=pw +ti u=4 s=pw +isbn u=7 +issn u=8 +cc u=20 +su u=21 s=pw +date u=30 r=r +dp u=31 r=r +da u=32 r=r +la u=54 s=pw +ab u=62 s=pw +note u=63 s=pw +af u=1006 s=pw +# +# Rules for a few GILS fields +north gils-attset,u=2040 r=o +south gils-attset,u=2041 r=o +east gils-attset,u=2038 r=o +west gils-attest,u=2039 r=o +distributor gils-attset,u=2000 s=pw +distributorname gils-attset,u=2001 s=pw + +# Explain fields +ExplainCategory exp1,1=1 +HumanStringLanguage exp1,1=2 +DatabaseName exp1,1=3 +TargetName exp1,1=4 +AttributeSetOID exp1,1=5 +RecordSyntaxOID exp1,1=6 +TagSetOID exp1,1=7 +ExtededServiceOID exp1,1=8 +DateAdded exp1,1=9 +DateChanged exp1,1=10 +DateExpires exp1,1=11 +ElementSetName exp1,1=12 diff --git a/t/15-scan.t b/t/15-scan.t index f9236c4..cc8a75f 100644 --- a/t/15-scan.t +++ b/t/15-scan.t @@ -1,11 +1,11 @@ -# $Id: 15-scan.t,v 1.9 2005-12-21 00:43:54 mike Exp $ +# $Id: 15-scan.t,v 1.10 2006-06-13 16:44:21 mike Exp $ # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl 15-scan.t' use strict; use warnings; -use Test::More tests => 81; +use Test::More tests => 87; BEGIN { use_ok('Net::Z3950::ZOOM') }; @@ -77,6 +77,22 @@ ok(defined $term && $len eq length($term), Net::Z3950::ZOOM::scanset_destroy($ss); ok(1, "destroyed third scanset"); +# Now using CCL +Net::Z3950::ZOOM::connection_option_set($conn, cclfile => + "samples/ccl/default.bib"); +$q = Net::Z3950::ZOOM::query_create(); +Net::Z3950::ZOOM::query_ccl2rpn($q, 'ti=w', $conn); +($ss, $n) = scan($conn, 1, $q, 4); +# Get last term and use it as seed for next scan +$term = Net::Z3950::ZOOM::scanset_term($ss, $n-1, $occ, $len); +ok(Net::Z3950::ZOOM::scanset_option_get($ss, "position") == 1, + "seed-term is start of returned list"); +ok(defined $term && $len eq length($term), + "got last title term '$term' to use as seed"); + +Net::Z3950::ZOOM::scanset_destroy($ss); +ok(1, "destroyed fourth scanset"); + # We want the seed-term to be in "position zero", i.e. just before the start Net::Z3950::ZOOM::connection_option_set($conn, position => 0); ($ss, $n) = scan($conn, 0, "\@attr 1=4 $term", 2); @@ -89,7 +105,7 @@ ok(Net::Z3950::ZOOM::scanset_option_get($ss, "position") eq "fruit", "option setting/getting works"); Net::Z3950::ZOOM::scanset_destroy($ss); -ok(1, "destroyed fourth scanset"); +ok(1, "destroyed fifth scanset"); # There is no obvious use for scanset_option_set(), and little to be # done with scanset_option_get(); and I can't find a server that diff --git a/t/25-scan.t b/t/25-scan.t index d0a4f86..eb5d07c 100644 --- a/t/25-scan.t +++ b/t/25-scan.t @@ -1,11 +1,11 @@ -# $Id: 25-scan.t,v 1.7 2005-12-21 00:43:54 mike Exp $ +# $Id: 25-scan.t,v 1.8 2006-06-13 16:44:21 mike Exp $ # Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl 25-scan.t' use strict; use warnings; -use Test::More tests => 81; +use Test::More tests => 87; BEGIN { use_ok('ZOOM') }; @@ -71,6 +71,18 @@ ok(defined $term, $ss->destroy(); ok(1, "destroyed third scanset"); +$conn->option(cclfile => "samples/ccl/default.bib"); +($ss, $n) = scan($conn, 1, new ZOOM::Query::CCL2RPN('ti=w', $conn), 4); +# Get last term and use it as seed for next scan +($term, $occ) = $ss->term($n-1); +ok($ss->option("position") == 1, + "seed-term is start of returned list"); +ok(defined $term, + "got last title term '$term' to use as seed"); + +$ss->destroy(); +ok(1, "destroyed fourth scanset"); + # We want the seed-term to be in "position zero", i.e. just before the start $conn->option(position => 0); ($ss, $n) = scan($conn, 0, "\@attr 1=4 $term", 2); @@ -83,7 +95,7 @@ ok($ss->option("position") eq "fruit", "option setting/getting works"); $ss->destroy(); -ok(1, "destroyed fourth scanset"); +ok(1, "destroyed fifth scanset"); # Some more testing still to do: see comment in "15-scan.t" -- 1.7.10.4