- Add new function Net::Z3950::ZOOM::query_ccl2rpn(), for
authormike <mike>
Tue, 13 Jun 2006 16:44:20 +0000 (16:44 +0000)
committermike <mike>
Tue, 13 Jun 2006 16:44:20 +0000 (16:44 +0000)
  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
MANIFEST
Makefile.PL
ZOOM.xs
lib/Net/Z3950/ZOOM.pm
lib/ZOOM.pm
lib/ZOOM.pod
samples/ccl/default.bib [new file with mode: 0644]
t/15-scan.t
t/25-scan.t

diff --git a/Changes b/Changes
index c7288f9..3c8890c 100644 (file)
--- 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
index 4725e94..c8daea4 100644 (file)
--- 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
index 007986a..0f317b2 100644 (file)
@@ -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 (file)
--- 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
index 25e354e..e45a470 100644 (file)
@@ -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 }
index 8ac0c93..f553382 100644 (file)
@@ -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);
 
index 669db1c..fc72bdd 100644 (file)
@@ -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<ZOOM::Record>,
 C<ZOOM::ScanSet>
 and
 C<ZOOM::Package>.
-Of these, the Query class is abstract, and has three concrete
+Of these, the Query class is abstract, and has four concrete
 subclasses:
 C<ZOOM::Query::CQL>,
-C<ZOOM::Query::PQF>
+C<ZOOM::Query::PQF>,
+C<ZOOM::Query::CQL2RPN>
 and
-C<ZOOM::Query::CQL2RPN>.
+C<ZOOM::Query::CCL2RPN>.
 Finally, it also provides a
 C<ZOOM::Query::Log>
 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<samples/cql/pqf.properties>
 
+=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<samples/ccl/default.bib>
+
+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<Query> 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-E<gt>errcode()> and related
 methods.
 
+ $conn->option(cclfile => "samples/ccl/default.bib");
+ $q = new ZOOM::Query::CCL2RPN('ti=dinosaur', $conn);
+
+For the C<ZOOM::Query::CQL2RPN> 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<TIMEOUT>,
 C<UNSUPPORTED_PROTOCOL>,
 C<UNSUPPORTED_QUERY>,
 C<INVALID_QUERY>,
+C<CQL_PARSE>,
+C<CQL_TRANSFORM>,
+C<CCL_CONFIG>,
+C<CCL_PARSE>,
 C<CREATE_QUERY>,
 C<QUERY_CQL>,
 C<QUERY_PQF>,
diff --git a/samples/ccl/default.bib b/samples/ccl/default.bib
new file mode 100644 (file)
index 0000000..978d71d
--- /dev/null
@@ -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
index f9236c4..cc8a75f 100644 (file)
@@ -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
index d0a4f86..eb5d07c 100644 (file)
@@ -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"