- Change the XCQL output to include the nasty and redundant
authormike <mike>
Wed, 20 Nov 2002 01:15:14 +0000 (01:15 +0000)
committermike <mike>
Wed, 20 Nov 2002 01:15:14 +0000 (01:15 +0000)
  (but official) <leftOperand> and <rightOperand> wrapper
  elements.
- Change the XCQL output to use the nasty (but official)
  rendition of prefix-mapping: a <prefixes> element,
  containing one of more <prefix>es may appear at the top
  level of either a <searchClause> or a <triple>.
Also, improve the text/regression scaffolding somewhat.

13 files changed:
Changes
src/org/z3950/zing/cql/CQLBooleanNode.java
src/org/z3950/zing/cql/CQLGenerator.java
src/org/z3950/zing/cql/CQLNode.java
src/org/z3950/zing/cql/CQLParser.java
src/org/z3950/zing/cql/CQLPrefixNode.java
src/org/z3950/zing/cql/CQLProxNode.java
src/org/z3950/zing/cql/CQLRelation.java
src/org/z3950/zing/cql/CQLTermNode.java
test/regression/Makefile
test/regression/README
test/regression/runtests
test/regression/showtest

diff --git a/Changes b/Changes
index 959e97c..0611311 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,4 +1,4 @@
-$Id: Changes,v 1.15 2002-11-19 17:23:26 mike Exp $
+$Id: Changes,v 1.16 2002-11-20 01:15:14 mike Exp $
 
 Revision history for "cql-java"
 See the bottom of this file for a list of things still to do.
@@ -9,13 +9,20 @@ See the bottom of this file for a list of things still to do.
        - Make prefix-maps bind loosely, so that ``>dc=x a and b''
          applies the dc=x binding to both the ``a'' and ``b''
          sub-queries.
+       - Change the XCQL output to include the nasty and redundant
+         (but official) <leftOperand> and <rightOperand> wrapper
+         elements.
+       - Change the XCQL output to use the nasty (but official)
+         rendition of prefix-mapping: a <prefixes> element,
+         containing one of more <prefix>es may appear at the top
+         level of either a <searchClause> or a <triple>.
        - Change build process so that javadoc documentation is built
          by "make" in the "docs" directory.
        - Write javadoc comments for CQLRelation and ModifierSet.
        - Other improvements to javadoc comments (e.g. describe the
          `config' parameter to the toPQF() method.)
-       - Include test/regression/xmlpp.pl in the distribution: will
-         be used for testing whether a CQL compiler produces
+       - Include test/regression/xmlpp.pl in the distribution: this
+         is now used for testing whether a CQL compiler produces
          _equivalent_ XCQL to the what's in the regression test,
          rather than requiring byte-identical output.
        - Sort out the licence: I've settled on the LGPL.
@@ -103,4 +110,5 @@ See the bottom of this file for a list of things still to do.
          * Better selection of terms (from a dictionary file?)
          * Introduce wildcard characters into generated terms
          * Generate multi-word terms
+         * Generate prefix-mappings
 
index b0ca761..56fdde2 100644 (file)
@@ -1,13 +1,14 @@
-// $Id: CQLBooleanNode.java,v 1.8 2002-11-06 20:13:45 mike Exp $
+// $Id: CQLBooleanNode.java,v 1.9 2002-11-20 01:15:14 mike Exp $
 
 package org.z3950.zing.cql;
 import java.util.Properties;
+import java.util.Vector;
 
 
 /**
  * Represents a boolean node in a CQL parse-tree.
  *
- * @version    $Id: CQLBooleanNode.java,v 1.8 2002-11-06 20:13:45 mike Exp $
+ * @version    $Id: CQLBooleanNode.java,v 1.9 2002-11-20 01:15:14 mike Exp $
  */
 public abstract class CQLBooleanNode extends CQLNode {
     CQLBooleanNode() {}                // prevent javadoc from documenting this
@@ -22,11 +23,16 @@ public abstract class CQLBooleanNode extends CQLNode {
      */ 
     public CQLNode right;
 
-    public String toXCQL(int level) {
+    public String toXCQL(int level, Vector prefixes) {
        return (indent(level) + "<triple>\n" +
+               renderPrefixes(level+1, prefixes) +
                opXQL(level+1) +
-               left.toXCQL(level+1) +
-               right.toXCQL(level+1) +
+               indent(level+1) + "<leftOperand>\n" +
+               left.toXCQL(level+2, new Vector()) +
+               indent(level+1) + "</leftOperand>\n" +
+               indent(level+1) + "<rightOperand>\n" +
+               right.toXCQL(level+2, new Vector()) +
+               indent(level+1) + "</rightOperand>\n" +
                indent(level) + "</triple>\n");
     }
 
index c0f05ce..747bf52 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLGenerator.java,v 1.4 2002-11-06 00:05:58 mike Exp $
+// $Id: CQLGenerator.java,v 1.5 2002-11-20 01:15:14 mike Exp $
 
 package org.z3950.zing.cql;
 import java.util.Properties;
@@ -22,7 +22,7 @@ import java.io.FileNotFoundException;
  * this distribution - there is a <TT>generate_<I>x</I>()</TT> method
  * for each grammar element <I>X</I>.
  *
- * @version    $Id: CQLGenerator.java,v 1.4 2002-11-06 00:05:58 mike Exp $
+ * @version    $Id: CQLGenerator.java,v 1.5 2002-11-20 01:15:14 mike Exp $
  * @see                <A href="http://zing.z3950.org/cql/index.html"
  *                     >http://zing.z3950.org/cql/index.html</A>
  */
@@ -136,6 +136,7 @@ public class CQLGenerator {
 
        CQLNode node1 = generate_cql_query();
        CQLNode node2 = generate_search_clause();
+       // ### should generate prefix-mapping nodes
        if (maybe("proxOp")) {
            // ### generate proximity nodes
        } else {
index e0fc2e5..5965da6 100644 (file)
@@ -1,13 +1,14 @@
-// $Id: CQLNode.java,v 1.14 2002-11-17 23:29:02 mike Exp $
+// $Id: CQLNode.java,v 1.15 2002-11-20 01:15:15 mike Exp $
 
 package org.z3950.zing.cql;
 import java.util.Properties;
+import java.util.Vector;
 
 
 /**
  * Represents a node in a CQL parse-tree.
  *
- * @version    $Id: CQLNode.java,v 1.14 2002-11-17 23:29:02 mike Exp $
+ * @version    $Id: CQLNode.java,v 1.15 2002-11-20 01:15:15 mike Exp $
  */
 public abstract class CQLNode {
     CQLNode() {}               // prevent javadoc from documenting this
@@ -24,7 +25,27 @@ public abstract class CQLNode {
      * A String containing an XCQL document equivalent to the
      * parse-tree whose root is this node.
      */
-    abstract public String toXCQL(int level);
+    public String toXCQL(int level) {
+       return toXCQL(level, new Vector());
+    }
+
+    abstract public String toXCQL(int level, Vector prefixes);
+
+    protected static String renderPrefixes(int level, Vector prefixes) {
+       if (prefixes.size() == 0)
+           return "";
+       String res = indent(level) + "<prefixes>\n";
+       for (int i = 0; i < prefixes.size(); i++) {
+           CQLPrefix p = (CQLPrefix) prefixes.get(i);
+           res += indent(level+1) + "<prefix>\n";
+           if (p.name != null)
+               res += indent(level+2) + "<name>" + p.name + "</name>\n";
+           res += indent(level+2) +
+               "<identifier>" + p.identifier + "</identifier>\n";
+           res += indent(level+1) + "</prefix>\n";
+       }
+       return res + indent(level) + "</prefixes>\n";
+    }
 
     /**
      * Decompiles a parse-tree into a CQL query.
index 6726999..85ee63b 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLParser.java,v 1.21 2002-11-17 23:29:02 mike Exp $
+// $Id: CQLParser.java,v 1.22 2002-11-20 01:15:15 mike Exp $
 
 package org.z3950.zing.cql;
 import java.io.IOException;
@@ -12,7 +12,7 @@ import java.io.FileNotFoundException;
 /**
  * Compiles CQL strings into parse trees of CQLNode subtypes.
  *
- * @version    $Id: CQLParser.java,v 1.21 2002-11-17 23:29:02 mike Exp $
+ * @version    $Id: CQLParser.java,v 1.22 2002-11-20 01:15:15 mike Exp $
  * @see                <A href="http://zing.z3950.org/cql/index.html"
  *                     >http://zing.z3950.org/cql/index.html</A>
  */
@@ -34,8 +34,10 @@ public class CQLParser {
      * data structure) or, more often, simply rendered out in the
      * desired form using one of the back-ends.  <TT>toCQL()</TT>
      * returns a decompiled CQL query equivalent to the one that was
-     * compiled in the first place; and <TT>toXCQL()</TT> returns an
-     * XML snippet representing the query.
+     * compiled in the first place; <TT>toXCQL()</TT> returns an
+     * XML snippet representing the query; and <TT>toPQF()</TT>
+     * returns the query rendered in Index Data's Prefix Query
+     * Format.
      *
      * @param cql      The query
      * @return         A CQLNode object which is the root of a parse
index 604ef5f..4e603b7 100644 (file)
@@ -1,14 +1,15 @@
-// $Id: CQLPrefixNode.java,v 1.2 2002-11-14 22:07:32 mike Exp $
+// $Id: CQLPrefixNode.java,v 1.3 2002-11-20 01:15:15 mike Exp $
 
 package org.z3950.zing.cql;
 import java.lang.String;
 import java.util.Properties;
+import java.util.Vector;
 
 
 /**
  * Represents a prefix node in a CQL parse-tree.
  *
- * @version    $Id: CQLPrefixNode.java,v 1.2 2002-11-14 22:07:32 mike Exp $
+ * @version    $Id: CQLPrefixNode.java,v 1.3 2002-11-20 01:15:15 mike Exp $
  */
 public class CQLPrefixNode extends CQLNode {
     /**
@@ -32,16 +33,19 @@ public class CQLPrefixNode extends CQLNode {
        this.subtree = subtree;
     }
 
-    public String toXCQL(int level) {
-       String maybeName = "";
-       if (prefix.name != null)
-           maybeName = indent(level+1) + "<name>" + prefix.name + "</name>\n";
-
-       return (indent(level) + "<prefix>\n" + maybeName +
-               indent(level+1) +
-                   "<identifier>" + prefix.identifier + "</identifier>\n" +
-               subtree.toXCQL(level+1) +
-               indent(level) + "</prefix>\n");
+    public String toXCQL(int level, Vector prefixes) {
+//     String maybeName = "";
+//     if (prefix.name != null)
+//         maybeName = indent(level+1) + "<name>" + prefix.name + "</name>\n";
+//
+//     return (indent(level) + "<prefix>\n" + maybeName +
+//             indent(level+1) +
+//                 "<identifier>" + prefix.identifier + "</identifier>\n" +
+//             subtree.toXCQL(level+1, prefixes) +
+//             indent(level) + "</prefix>\n");
+       Vector tmp = new Vector(prefixes);
+       tmp.add(prefix);
+       return subtree.toXCQL(level, tmp);
     }
 
     public String toCQL() {
index b3a8dca..e31bd2c 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLProxNode.java,v 1.3 2002-11-06 20:13:45 mike Exp $
+// $Id: CQLProxNode.java,v 1.4 2002-11-20 01:15:15 mike Exp $
 
 package org.z3950.zing.cql;
 import java.util.Vector;
@@ -10,7 +10,7 @@ import java.util.Vector;
  * candidate records which are sufficiently close to each other, as
  * specified by a set of proximity parameters.
  *
- * @version    $Id: CQLProxNode.java,v 1.3 2002-11-06 20:13:45 mike Exp $
+ * @version    $Id: CQLProxNode.java,v 1.4 2002-11-20 01:15:15 mike Exp $
  */
 public class CQLProxNode extends CQLBooleanNode {
     ModifierSet ms;
@@ -71,7 +71,7 @@ public class CQLProxNode extends CQLBooleanNode {
        return ms.toCQL();
     }
 
-    String opXQL(int level) {
+    String opXQL(int level, Vector prefixes) {
        return ms.toXCQL(level, "boolean");
     }
 
index 36fae4a..6f007bc 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLRelation.java,v 1.6 2002-11-17 23:29:02 mike Exp $
+// $Id: CQLRelation.java,v 1.7 2002-11-20 01:15:15 mike Exp $
 
 package org.z3950.zing.cql;
 import java.util.Vector;
@@ -8,7 +8,7 @@ import java.lang.StringBuffer;
 /**
  * Represents a relation between a CQL qualifier and term.
  *
- * @version    $Id: CQLRelation.java,v 1.6 2002-11-17 23:29:02 mike Exp $
+ * @version    $Id: CQLRelation.java,v 1.7 2002-11-20 01:15:15 mike Exp $
  */
 public class CQLRelation extends CQLNode {
     ModifierSet ms;
@@ -59,7 +59,7 @@ public class CQLRelation extends CQLNode {
        return s;
     }
 
-    public String toXCQL(int level) {
+    public String toXCQL(int level, Vector prefixes) {
        return ms.toXCQL(level, "relation");
     }
 
index 9e7a7b9..49d42b3 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLTermNode.java,v 1.8 2002-11-06 20:13:45 mike Exp $
+// $Id: CQLTermNode.java,v 1.9 2002-11-20 01:15:15 mike Exp $
 
 package org.z3950.zing.cql;
 import java.util.Properties;
@@ -12,7 +12,7 @@ import java.util.Vector;
  * these must be provided - you can't have a qualifier without a
  * relation or vice versa.
  *
- * @version    $Id: CQLTermNode.java,v 1.8 2002-11-06 20:13:45 mike Exp $
+ * @version    $Id: CQLTermNode.java,v 1.9 2002-11-20 01:15:15 mike Exp $
  */
 public class CQLTermNode extends CQLNode {
     private String qualifier;
@@ -34,11 +34,13 @@ public class CQLTermNode extends CQLNode {
     public CQLRelation getRelation() { return relation; }
     public String getTerm() { return term; }
 
-    public String toXCQL(int level) {
+    public String toXCQL(int level, Vector prefixes) {
        return (indent(level) + "<searchClause>\n" +
+               renderPrefixes(level+1, prefixes) +
                indent(level+1) + "<index>" + xq(qualifier) + "</index>\n" +
-               relation.toXCQL(level+1) +
-               indent(level+1) + "<term>" + xq(term) + "</term>\n" +
+               relation.toXCQL(level+1, new Vector()) +
+               indent(level+2) + "<term>" + xq(term) + "</term>\n" +
+               // ######### ^-- this should be "1"
                indent(level) + "</searchClause>\n");
     }
 
index e2f179d..73a705e 100644 (file)
@@ -1,20 +1,32 @@
-# $Id: Makefile,v 1.3 2002-11-08 16:31:24 mike Exp $
+# $Id: Makefile,v 1.4 2002-11-20 01:15:15 mike Exp $
+
+XMLCANONICALISER = ./xmlpp.pl
+# Change this to "cat" if you want to check byte-for-byte identicality
+
+test:
+       ./runtests CQLParser $(XMLCANONICALISER)
+
+test-adam: sections/01/01.xcql
+       ./runtests ../../../srw/cql/cqlparse3 $(XMLCANONICALISER)
+
+test-rob: sections/01/01.xcql
+       ./runtests ../../../rob/CQLParser.py $(XMLCANONICALISER)
+
+reference: sections/01/01.xcql
 
 sections/01/01.xcql: sections
        ./mkanswers CQLParser
 # OR   ./mkanswers ../../srw/cql/cqlparse3
 # OR   ./mkanswers ../../rob/CQLParser.py
+# Depending on which parser you want to use as your reference
 
 sections: mktests queries.raw
        rm -rf sections
        ./mktests queries.raw
 
-adam-tests: sections/01/01.xcql
-       ./runtests ../../../srw/cql/cqlparse3 cat
-
-rob-tests: sections/01/01.xcql
-       ./runtests ../../../rob/CQLParser.py cat
-
 clean:
+       @echo "Nothing to do to 'make clean'"
+
+totally-clean:
        rm -rf sections
 
index fe38ee2..59aa84b 100644 (file)
@@ -1,4 +1,7 @@
-$Id: README,v 1.2 2002-11-19 12:11:48 mike Exp $
+$Id: README,v 1.3 2002-11-20 01:15:15 mike Exp $
+
+cql-java's regression-testing framework
+---------------------------------------
 
 "queries.raw" is the file of test queries as provided by Rob.
 "mktests" parses the raw file into sections and individual queries
@@ -8,13 +11,26 @@ $Id: README,v 1.2 2002-11-19 12:11:48 mike Exp $
     "01/01.cql", "01/02.cql" etc. are the CQL queries themselves.
 "mkanswers" uses a trusted CQL compiler to generate corresponding XCQL.
     "01/01.xcql", "01/02.xcql" etc. are the compiled XCQL queries.
-"runtests" compares the output of a CQL compiler with existing XCQL files.
+
+All of the files described to this point are included in the
+distribution, with the "trusted" outpout produced by my own compiler,
+and used to for regression testing of new versions.  But you're
+welcome to "rm -r sections" and rebuild it to contain the trusted
+compiler output of your choice.
+
+"runtests" compares the output of a CQL compiler with existing XCQL
+files.  In general, use this to compare the results of your own build
+of cql-java with those of my build.  (I'll use it to test new
+versions, and people who've written other compilers can use it to test
+their code.)
 
 "Makefile" controls the building of all this.  You'll need to edit it
 if you want to use different compilers and suchlike from what's
 written into it, so it may be easier to run the tests by hand -- but
 it's a useful reference for the kinds of commands you might need,
-anyway.
+anyway.  In general, "make" will run the regression tests, and "make
+reference" will rebuild the reference results should you wish to do
+that.
 
 So, for example, if you think Rob Sanderson's parser, CQLParser.py, is
 reliable, and you want to test my parser, cql-java's CQLParser class,
@@ -23,13 +39,13 @@ against its results, do this:
        rm -rf sections
        ./mktests queries.raw
        ./mkanswers CQLParser.py
-       ./runtests CQLParser sgmlnorm
+       ./runtests CQLParser ./xmlpp.pl
 
-(Except that sgmlnorm is useless -- gotta find something better.)
-(That something better is xmlpp from DecisionSoft, found at
+The second argument to ./runtests is the name of a program to use to
+normalise XML, so that the trusted output and the output being tested
+can be compared for equivalence rather than just for being
+byte-identical.  (If you want to test for byte-identical XCQL, then
+use "cat" as the second argument.)  xmlpp.pl is a fine XML
+pretty-printer from DecisionSoft, found at
        http://software.decisionsoft.com/tools.html
-which I will probably distribute along with cql-java.)
 
-Also: there's a nasty hack here called "showtest" which, when run like
-``./showtest 07/03'', will show you the ways in which my output
-differs from Adam's.  I'll probably delete it soon.
index 78e4117..32e9707 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 
-# $Id: runtests,v 1.3 2002-11-06 22:03:58 mike Exp $
+# $Id: runtests,v 1.4 2002-11-20 01:15:15 mike Exp $
 
 use IO::File;
 use strict;
@@ -26,7 +26,7 @@ while (<sections/*>) {
        print "  query $_ - $query\n";
        my $correct = read_file("$norman < $afile |");
        my $tested = read_file("$compiler < $qfile | $norman |")
-           or die "can't run test compiler '$compiler | $norman': $!";
+           or warn "test compiler exited non-zero";
        if ($tested ne $correct) {
            print "    *** different XCQL output\n";
            print "=== correct ===\n$correct";
index 496e207..2cf6f7e 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# $Id: showtest,v 1.3 2002-11-06 22:03:58 mike Exp $
+# $Id: showtest,v 1.4 2002-11-20 01:15:15 mike Exp $
 
 if [ $# != 1 ]; then
        echo "Usage: $0 <test-name>" >&2
@@ -9,8 +9,8 @@ if [ $# != 1 ]; then
 fi
 
 ### Warning: nasty hard-coded choices
-( echo "=== Rob ==="
-  ../../../rob/CQLParser.py < sections/$1.cql ) > /tmp/rob
+( echo "=== Adam ==="
+  ../../../srw/cql/cqlparse3 < sections/$1.cql ) > /tmp/adam
 ( echo "=== Mike ==="
   ../../bin/CQLParser < sections/$1.cql ) > /tmp/mike
-sdiff -w 80 /tmp/rob /tmp/mike
+sdiff -w 80 /tmp/adam /tmp/mike