Towards 0.2 --
authormike <mike>
Wed, 6 Nov 2002 00:05:57 +0000 (00:05 +0000)
committermike <mike>
Wed, 6 Nov 2002 00:05:57 +0000 (00:05 +0000)
- Fix the order of proximity parameters in accordance with the
  updated official grammar, which now specifies proximity
  operators of the form
prox/<relation>/<distance>/<unit>/<ordering>
  as in ``foo prox/<=/3/sentence bar''.
- Make the necessary parts of the CQLNode class and its
  subclasses public.  This means that client code can now walk
  through parse-trees and so implement its own back-end
  (e.g. to build BER-friendly data structures using whatever
  Z39.50 toolkit is preferred.)
- Add javadoc comments for CQLNode and subclasses.
- Add the toPQF(Properties p) method to CQLNode and subclasses.
(### NOT YET FINISHED)
- Add UnknownQualifierException and UnknownRelationException.
- Add "-p <props-file>" option to the CQLParser test-harness,
  indicating that the parsed tree is to be rendered to PQF.
- Add etc/pqf.properties to configure to toPQF() method.
- Rename ParameterMissingException to MissingParameterException.

20 files changed:
Changes [new file with mode: 0644]
README
etc/pqf.properties [new file with mode: 0644]
src/org/z3950/zing/cql/CQLAndNode.java
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/CQLNotNode.java
src/org/z3950/zing/cql/CQLOrNode.java
src/org/z3950/zing/cql/CQLParser.java
src/org/z3950/zing/cql/CQLProxNode.java
src/org/z3950/zing/cql/CQLRelation.java
src/org/z3950/zing/cql/CQLTermNode.java
src/org/z3950/zing/cql/Makefile
src/org/z3950/zing/cql/MissingParameterException.java [new file with mode: 0644]
src/org/z3950/zing/cql/ModifierSet.java
src/org/z3950/zing/cql/ParameterMissingException.java [deleted file]
src/org/z3950/zing/cql/UnknownQualifierException.java [new file with mode: 0644]
src/org/z3950/zing/cql/UnknownRelationException.java [new file with mode: 0644]
src/org/z3950/zing/cql/Utils.java

diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..cc072fe
--- /dev/null
+++ b/Changes
@@ -0,0 +1,27 @@
+$Id: Changes,v 1.1 2002-11-06 00:05:57 mike Exp $
+
+Revision history for "cql-java"
+
+0.2  (IN PROGRESS)
+       - Fix the order of proximity parameters in accordance with the
+         updated official grammar, which now specifies proximity
+         operators of the form
+               prox/<relation>/<distance>/<unit>/<ordering>
+         as in ``foo prox/<=/3/sentence bar''.
+       - Make the necessary parts of the CQLNode class and its
+         subclasses public.  This means that client code can now walk
+         through parse-trees and so implement its own back-end
+         (e.g. to build BER-friendly data structures using whatever
+         Z39.50 toolkit is preferred.)
+       - Add javadoc comments for CQLNode and subclasses.
+       - Add the toPQF(Properties p) method to CQLNode and subclasses.
+               (### NOT YET FINISHED)
+       - Add UnknownQualifierException and UnknownRelationException.
+       - Add "-p <props-file>" option to the CQLParser test-harness,
+         indicating that the parsed tree is to be rendered to PQF.
+       - Add etc/pqf.properties to configure to toPQF() method.
+       - Rename ParameterMissingException to MissingParameterException.
+
+0.1  Sun Nov  3 20:58:27 2002
+       - First public release.
+
diff --git a/README b/README
index e06bf2b..ee96d8a 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-$Id: README,v 1.13 2002-11-05 17:20:30 mike Exp $
+$Id: README,v 1.14 2002-11-06 00:05:58 mike Exp $
 
 cql-java - a free CQL compiler, and other CQL tools, for Java
 
@@ -114,13 +114,14 @@ All the other free CQL compilers everyone's going to write  :-)
 THINGS TO DO
 ------------
 
-* ### Make necessary parts of CQLNode etc. public.
-
 * ### Fix bug where "9x" is parsed as two tokens, a TT_NUMBER followed
   by a TT_WORD.  The problem here is that I don't think it's actually
   possible to fix this without throwing out StreakTokenizer and
   rolling our own, which we absolutely _don't_ want to do.
 
+* Write javadoc comments for CQLRelation, ModifierSet and the
+  Exception classes.
+
 * Allow keywords to be used unquoted as search terms.
 
 * Some niceties for the cql-decompiling back-end:
diff --git a/etc/pqf.properties b/etc/pqf.properties
new file mode 100644 (file)
index 0000000..9c4abbf
--- /dev/null
@@ -0,0 +1,62 @@
+# $Id: pqf.properties,v 1.1 2002-11-06 00:05:58 mike Exp $
+#
+# Propeties file to drive org.z3950.zing.cql.CQLNode's toPQF()
+# back-end.  This specifies the interpretation of various CQL
+# qualifiers in terms of Type-1 query attributes.
+#
+dc.title                       = 1=4
+dc.subject                     = 1=21
+dc.creator                     = 1=1003
+dc.editor                      = 1=1020
+dc.publisher                   = 1=1018
+dc.description                 = 1=62  # "abstract"
+dc.date                                = 1=30
+dc.resourceType                        = 1=1031        # guesswork: "Material-type"
+dc.format                      = 1=1034        # guesswork: "Content-type"
+dc.resourceIdentifier          = 1=12  # "Local number"
+dc.source                      = 1=1019        # "Record-source"
+dc.language                    = 1=54  # "Code--language"
+dc.relation                    = 1=?   ###
+dc.coverage                    = 1=?   ###
+dc.rights                      = 1=?   ###
+#
+# Aside from the mainstream qualifiers -- the Dublin Core stuff, Bath
+# Profile stuff and suchlike -- this file may also specific a few
+# special qualifiers in the "cql-java" pseudo-qualifier-set, and these
+# affect the translation of qualifiers into Type-1 attributes as
+# follows:
+#
+# Relation attributes are selected according to the CQL relation by
+# looking up the "cql-java.relation.<relation>" property:
+#
+cql-java.relation.<            = 2=1
+cql-java.relation.<=           = 2=2
+cql-java.relation.=            = 2=3
+cql-java.relation.exact                = 2=3
+cql-java.relation.>=           = 2=4
+cql-java.relation.>            = 2=5
+cql-java.relation.<>           = 2=6
+#
+#      ### Should add support for relation modifiers
+#
+# Position attributes may be specified for anchored terms (those
+# beginning with "^", which is stripped) and unanchored (those not
+# beginning with "^").  This may change when we get a BIB-1 truncation
+# attribute that says "do what CQL does".
+#
+cql-java.position.anchored     = 3=1   # "first in field"
+cql-java.position.unanchored   = 3=3   # "any position in field"
+#
+# Structure attributes may be specified for individual relations; a
+# default structure attribute my be specified by the pseudo-relation
+# "*", to be used whenever a relation not listed here occurs.
+#
+cql-java.structure.exact       = 4=108 # phrase
+cql-java.structure.*           = 4=1   # phrase
+#
+# Finally, any additional attributes that should always be included
+# with each term can be specified in the "cql-java.always" property.
+#
+cql-java.always                        = 5=104 6=1
+# 5=104: some kind of vaguely CQL-like masking, IIRC.
+# 6=1: completeness = incomplete subfield
index 57cde12..1f5157f 100644 (file)
@@ -1,15 +1,17 @@
-// $Id: CQLAndNode.java,v 1.4 2002-10-31 22:22:01 mike Exp $
+// $Id: CQLAndNode.java,v 1.5 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 
 
 /**
  * Represents an AND node in a CQL parse-tree.
- * ##
  *
- * @version    $Id: CQLAndNode.java,v 1.4 2002-10-31 22:22:01 mike Exp $
+ * @version    $Id: CQLAndNode.java,v 1.5 2002-11-06 00:05:58 mike Exp $
  */
 public class CQLAndNode extends CQLBooleanNode {
+    /**
+     * Creates a new AND node with the specified left- and right-hand sides.
+     */
     public CQLAndNode(CQLNode left, CQLNode right) {
        this.left = left;
        this.right = right;
index 56c212f..a3c3749 100644 (file)
@@ -1,21 +1,29 @@
-// $Id: CQLBooleanNode.java,v 1.6 2002-10-31 22:22:01 mike Exp $
+// $Id: CQLBooleanNode.java,v 1.7 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 
 
 /**
  * Represents a boolean node in a CQL parse-tree.
- * ##
  *
- * @version    $Id: CQLBooleanNode.java,v 1.6 2002-10-31 22:22:01 mike Exp $
+ * @version    $Id: CQLBooleanNode.java,v 1.7 2002-11-06 00:05:58 mike Exp $
  */
 public abstract class CQLBooleanNode extends CQLNode {
-    protected CQLNode left;
-    protected CQLNode right;
+    CQLBooleanNode() {}                // prevent javadoc from documenting this
+
+    /**
+     * The root of a parse-tree representing the left-hand side.
+     */ 
+    public CQLNode left;
+
+    /**
+     * The root of a parse-tree representing the right-hand side.
+     */ 
+    public CQLNode right;
 
     abstract String op();
 
-    String toXCQL(int level) {
+    public String toXCQL(int level) {
        return (indent(level) + "<triple>\n" +
                booleanXQL(level+1) +
                left.toXCQL(level+1) +
@@ -23,13 +31,14 @@ public abstract class CQLBooleanNode extends CQLNode {
                indent(level) + "</triple>\n");
     }
 
+    // Represents the boolean operation itself: overridden for CQLProxNode
     String booleanXQL(int level) {
        return(indent(level) + "<boolean>\n" +
               indent(level+1) + "<value>" + op() + "</value>\n" +
               indent(level) + "</boolean>\n");
     }
 
-    String toCQL() {
+    public String toCQL() {
        // ### We don't always need parens around the operands
        return "(" + left.toCQL() + ") " + op() + " (" + right.toCQL() + ")";
     }
index 991f60d..c0f05ce 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLGenerator.java,v 1.3 2002-11-03 16:49:38 mike Exp $
+// $Id: CQLGenerator.java,v 1.4 2002-11-06 00:05:58 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.3 2002-11-03 16:49:38 mike Exp $
+ * @version    $Id: CQLGenerator.java,v 1.4 2002-11-06 00:05:58 mike Exp $
  * @see                <A href="http://zing.z3950.org/cql/index.html"
  *                     >http://zing.z3950.org/cql/index.html</A>
  */
@@ -125,11 +125,11 @@ public class CQLGenerator {
      * method, or decompiled into CQL using its <TT>toCQL</TT>
      * method.
      */
-    public CQLNode generate() throws ParameterMissingException {
+    public CQLNode generate() throws MissingParameterException {
        return generate_cql_query();
     }
 
-    private CQLNode generate_cql_query() throws ParameterMissingException {
+    private CQLNode generate_cql_query() throws MissingParameterException {
        if (!maybe("complexQuery")) {
            return generate_search_clause();
        }
@@ -149,7 +149,7 @@ public class CQLGenerator {
        return generate_search_clause();
     }
 
-    private CQLNode generate_search_clause() throws ParameterMissingException {
+    private CQLNode generate_search_clause() throws MissingParameterException {
        if (maybe("complexClause")) {
            return generate_cql_query();
        }
@@ -183,14 +183,14 @@ public class CQLGenerator {
        return qualifier;
     }
 
-    private CQLRelation generate_relation() throws ParameterMissingException {
+    private CQLRelation generate_relation() throws MissingParameterException {
        String base = generate_base_relation();
        CQLRelation rel = new CQLRelation(base);
        // ### should generate modifiers too
        return rel;
     }
 
-    private String generate_base_relation() throws ParameterMissingException {
+    private String generate_base_relation() throws MissingParameterException {
        if (maybe("equalsRelation")) {
            return "=";
        } else if (maybe("numericRelation")) {
@@ -242,10 +242,10 @@ public class CQLGenerator {
        return "";              // shut up compiler warning
     }
 
-    boolean maybe(String param) throws ParameterMissingException {
+    boolean maybe(String param) throws MissingParameterException {
        String probability = params.getProperty(param);
        if (probability == null)
-           throw new ParameterMissingException(param);
+           throw new MissingParameterException(param);
 
        double dice = rnd.nextDouble();
        double threshhold = new Double(probability).doubleValue();
@@ -301,8 +301,7 @@ public class CQLGenerator {
        String configFile = args[0];
        InputStream f = new FileInputStream(configFile);
        if (f == null)
-           throw new FileNotFoundException("getResourceAsStream(" +
-                                           configFile + ")");
+           throw new FileNotFoundException(configFile);
 
        Properties params = new Properties();
        params.load(f);
index d36c11f..24a2d27 100644 (file)
@@ -1,31 +1,61 @@
-// $Id: CQLNode.java,v 1.10 2002-11-05 17:21:30 mike Exp $
+// $Id: CQLNode.java,v 1.11 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
+import java.util.Properties;
 
 
 /**
  * Represents a node in a CQL parse-tree.
- * ##
  *
- * @version    $Id: CQLNode.java,v 1.10 2002-11-05 17:21:30 mike Exp $
+ * @version    $Id: CQLNode.java,v 1.11 2002-11-06 00:05:58 mike Exp $
  */
 public abstract class CQLNode {
+    CQLNode() {}               // prevent javadoc from documenting this
+
+    /**
+     * Translates a parse-tree into an XCQL document.
+     * <P>
+     * @param level
+     * The number of levels to indent the top element of the XCQL
+     * document.  This will typically be 0 when invoked by an
+     * application; it takes higher values when this method is
+     * invoked recursively for nodes further down the tree.
+     * @return
+     * A String containing an XCQL document equivalent to the
+     * parse-tree whose root is this node.
+     */
     abstract public String toXCQL(int level);
+
+    /**
+     * Decompiles a parse-tree into a CQL query.
+     * <P>
+     * @return
+     * A String containing a CQL query equivalent to the parse-tree
+     * whose root is this node, so that compiling that query will
+     * yield an identical tree.
+     */
     abstract public String toCQL();
 
-    // Utility-function abbreviations for the use of subclasses
+    /**
+     * Renders a parse-tree into a Yaz-style PQF string.
+     * <P>
+     * @return
+     * A String containing a PQF query equivalent to the parse-tree
+     * whose root is this node.  This may be fed into the tool of
+     * your choice to obtain a BER-encoded packet.
+     */
+    abstract public String toPQF(Properties config)
+       throws UnknownQualifierException, UnknownRelationException;
+
+    /**
+     * Returns a String of spaces for indenting to the specified level.
+     */
     protected static String indent(int level) { return Utils.indent(level); }
-    protected static String xq(String str) { return Utils.xq(str); }
 
-    // Test harness
-    public static void main (String[] args) {
-       CQLNode n1 = new CQLTermNode("dc.author",
-                                    new CQLRelation("="),
-                                    "kernighan");
-       CQLNode n2 = new CQLTermNode("dc.title",
-                                    new CQLRelation("all"),
-                                    "elements style");
-       CQLNode root = new CQLAndNode(n1, n2);
-       System.out.println(root.toXCQL(0));
-    }
+    /**
+     * Returns the argument String quoted for XML.
+     * For example, each occurrence of <TT>&lt;</TT> is translated to
+     * <TT>&amp;lt;</TT>.
+     */
+    protected static String xq(String str) { return Utils.xq(str); }
 }
index 3eb1f7a..a2a64c2 100644 (file)
@@ -1,15 +1,17 @@
-// $Id: CQLNotNode.java,v 1.4 2002-10-31 22:22:01 mike Exp $
+// $Id: CQLNotNode.java,v 1.5 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 
 
 /**
  * Represents a NOT node in a CQL parse-tree.
- * ##
  *
- * @version    $Id: CQLNotNode.java,v 1.4 2002-10-31 22:22:01 mike Exp $
+ * @version    $Id: CQLNotNode.java,v 1.5 2002-11-06 00:05:58 mike Exp $
  */
 public class CQLNotNode extends CQLBooleanNode {
+    /**
+     * Creates a new NOT node with the specified left- and right-hand sides.
+     */
     public CQLNotNode(CQLNode left, CQLNode right) {
        this.left = left;
        this.right = right;
index 7dc253c..bacca98 100644 (file)
@@ -1,15 +1,17 @@
-// $Id: CQLOrNode.java,v 1.4 2002-10-31 22:22:01 mike Exp $
+// $Id: CQLOrNode.java,v 1.5 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 
 
 /**
  * Represents an OR node in a CQL parse-tree.
- * ##
  *
- * @version    $Id: CQLOrNode.java,v 1.4 2002-10-31 22:22:01 mike Exp $
+ * @version    $Id: CQLOrNode.java,v 1.5 2002-11-06 00:05:58 mike Exp $
  */
 public class CQLOrNode extends CQLBooleanNode {
+    /**
+     * Creates a new OR node with the specified left- and right-hand sides.
+     */
     public CQLOrNode(CQLNode left, CQLNode right) {
        this.left = left;
        this.right = right;
index 79abc31..59cedf8 100644 (file)
@@ -1,14 +1,18 @@
-// $Id: CQLParser.java,v 1.14 2002-11-03 16:49:38 mike Exp $
+// $Id: CQLParser.java,v 1.15 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 import java.io.IOException;
 import java.util.Vector;
+import java.util.Properties;
+import java.io.InputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 
 
 /**
  * Compiles CQL strings into parse trees of CQLNode subtypes.
  *
- * @version    $Id: CQLParser.java,v 1.14 2002-11-03 16:49:38 mike Exp $
+ * @version    $Id: CQLParser.java,v 1.15 2002-11-06 00:05:58 mike Exp $
  * @see                <A href="http://zing.z3950.org/cql/index.html"
  *                     >http://zing.z3950.org/cql/index.html</A>
  */
@@ -150,9 +154,9 @@ public class CQLParser {
                switch (i) {
                    // Order should be: relation/distance/unit/ordering
                    // For now, use MA's: unit/relation/distance/ordering
-               case 1: gatherProxRelation(node); break;
-               case 2: gatherProxDistance(node); break;
-               case 0: gatherProxUnit(node); break;
+               case 0: gatherProxRelation(node); break;
+               case 1: gatherProxDistance(node); break;
+               case 2: gatherProxUnit(node); break;
                case 3: gatherProxOrdering(node); break;
                }
            }
@@ -291,19 +295,27 @@ public class CQLParser {
      * <TT>-c</TT> option is supplied].
      */
     public static void main (String[] args) {
-       boolean canonicalise = false;
+       char mode = 'x';        // x=XCQL, c=CQL, p=PQF
+       String pfile = null;
+
        Vector argv = new Vector();
        for (int i = 0; i < args.length; i++) {
            argv.add(args[i]);
        }
 
        if (argv.size() > 0 && argv.get(0).equals("-c")) {
-           canonicalise = true;
+           mode = 'c';
+           argv.remove(0);
+       } else if (argv.size() > 1 && argv.get(0).equals("-p")) {
+           mode = 'p';
+           argv.remove(0);
+           pfile = (String) argv.get(0);
            argv.remove(0);
        }
 
        if (argv.size() > 1) {
-           System.err.println("Usage: CQLParser [-c] [<CQL-query>]");
+           System.err.println(
+               "Usage: CQLParser [-c] [-p <pqf-properties> [<CQL-query>]");
            System.err.println("If unspecified, query is read from stdin");
            System.exit(1);
        }
@@ -324,15 +336,9 @@ public class CQLParser {
        }
 
        CQLParser parser = new CQLParser();
-       CQLNode root;
+       CQLNode root = null;
        try {
            root = parser.parse(cql);
-           debug("root='" + root + "'");
-           if (canonicalise) {
-               System.out.println(root.toCQL());
-           } else {
-               System.out.print(root.toXCQL(0));
-           }
        } catch (CQLParseException ex) {
            System.err.println("Syntax error: " + ex.getMessage());
            System.exit(3);
@@ -340,5 +346,25 @@ public class CQLParser {
            System.err.println("Can't compile query: " + ex.getMessage());
            System.exit(4);
        }
+
+       try {
+           if (mode == 'c') {
+               System.out.println(root.toCQL());
+           } else if (mode == 'p') {
+               InputStream f = new FileInputStream(pfile);
+               if (f == null)
+                   throw new FileNotFoundException(pfile);
+
+               Properties config = new Properties();
+               config.load(f);
+               f.close();
+               System.out.println(root.toPQF(config));
+           } else {
+               System.out.print(root.toXCQL(0));
+           }
+       } catch (java.io.IOException ex) {
+           System.err.println("Can't render query: " + ex.getMessage());
+           System.exit(5);
+       }
     }
 }
index 1b9abe9..8c69ecc 100644 (file)
@@ -1,24 +1,39 @@
-// $Id: CQLProxNode.java,v 1.1 2002-10-31 22:22:01 mike Exp $
+// $Id: CQLProxNode.java,v 1.2 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 
 
 /**
  * Represents a proximity node in a CQL parse-tree.
- * ##
+ * The left- and right-hand-sides must be satisfied by parts of the
+ * candidate records which are sufficiently close to each other, as
+ * specified by a set of proximity parameters.
  *
- * @version    $Id: CQLProxNode.java,v 1.1 2002-10-31 22:22:01 mike Exp $
+ * @version    $Id: CQLProxNode.java,v 1.2 2002-11-06 00:05:58 mike Exp $
  */
 public class CQLProxNode extends CQLBooleanNode {
     ModifierSet ms;
 
+    /**
+     * Creates a new, <I>incomplete</I>, proximity node with the
+     * specified left-hand side.  No right-hand side is specified at
+     * this stage: that must be specified later, using the
+     * <TT>addSecondSubterm()</TT> method.  (That may seem odd, but
+     * it's just easier to write the parser that way.)
+     * <P>
+     * Proximity paramaters may be added at any time, before or after
+     * the right-hand-side sub-tree is added.
+     */
     public CQLProxNode(CQLNode left) {
        ms = new ModifierSet("prox");
        this.left = left;
        // this.right left unresolved for now ...
     }
 
-    // ... delayed "second half" of the constructor
+    /**
+     * Sets the right-hand side of the proximity node whose
+     * left-hand-side was specified at creation time.
+     */
     public void addSecondSubterm(CQLNode right) {
        this.right = right;
     }
@@ -27,10 +42,23 @@ public class CQLProxNode extends CQLBooleanNode {
        return ms.toCQL();
     }
 
+    /**
+     * Adds a modifier of the specified <TT>type</TT> and
+     * <TT>value</TT> to a proximity node.  Valid types are
+     * <TT>relation</TT>, <TT>distance</TT>, <TT>unit</TT> and
+     * <TT>ordering</TT>.
+     * <P>
+     * For information on the semantics of these paramaters, see
+     * <A href="http://zing.z3950.org/cql/intro.html#3.1"
+     * >section 3.1 (Proximity)</A> of
+     * <I>A Gentle Introduction to CQL</I></A>.
+     */
     public void addModifier(String type, String value) {
        ms.addModifier(type, value);
     }
 
+    // ### should have a public method to retrieve all modifiers
+
     String booleanXQL(int level) {
        return ms.toXCQL(level, "boolean");
     }
index ff8db8f..6d7e138 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: CQLRelation.java,v 1.2 2002-10-31 22:22:01 mike Exp $
+// $Id: CQLRelation.java,v 1.3 2002-11-06 00:05:58 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.2 2002-10-31 22:22:01 mike Exp $
+ * @version    $Id: CQLRelation.java,v 1.3 2002-11-06 00:05:58 mike Exp $
  */
 public class CQLRelation extends CQLNode {
     ModifierSet ms;
@@ -17,10 +17,16 @@ public class CQLRelation extends CQLNode {
        ms = new ModifierSet(base);
     }
 
+    public String getBase() {
+       return ms.getBase();
+    }
+
     public void addModifier(String modifier) {
        ms.addModifier(null, modifier);
     }
 
+    // ### should have a public method to retrieve all modifiers
+
     public String toXCQL(int level) {
        return ms.toXCQL(level, "relation");
     }
@@ -28,4 +34,9 @@ public class CQLRelation extends CQLNode {
     public String toCQL() {
        return ms.toCQL();
     }
+
+    public String toPQF(Properties config)
+       throws UnknownQualifierException, UnknownRelationException {
+       throw Error("CQLRelation.toPQF() can never be called");
+    }
 }
index fda7147..5889354 100644 (file)
@@ -1,26 +1,40 @@
-// $Id: CQLTermNode.java,v 1.6 2002-10-31 22:22:01 mike Exp $
+// $Id: CQLTermNode.java,v 1.7 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
+import java.util.Properties;
+import java.util.Vector;
 
 
 /**
  * Represents a terminal node in a CQL parse-tree.
- * ##
+ * A term node consists of the term String itself, together with,
+ * optionally, a qualifier string and a relation.  Neither or both of
+ * these must be provided - you can't have a qualifier without a
+ * relation or vice versa.
  *
- * @version    $Id: CQLTermNode.java,v 1.6 2002-10-31 22:22:01 mike Exp $
+ * @version    $Id: CQLTermNode.java,v 1.7 2002-11-06 00:05:58 mike Exp $
  */
 public class CQLTermNode extends CQLNode {
     private String qualifier;
     private CQLRelation relation;
     private String term;
 
+    /**
+     * Creates a new term node with the specified <TT>qualifier</TT>,
+     * <TT>relation</TT> and <TT>term</TT>.  The first two may be
+     * <TT>null</TT>, but the <TT>term</TT> may not.
+     */
     public CQLTermNode(String qualifier, CQLRelation relation, String term) {
        this.qualifier = qualifier;
        this.relation = relation;
        this.term = term;
     }
 
-    String toXCQL(int level) {
+    public String getQualifier() { return qualifier; }
+    public CQLRelation getRelation() { return relation; }
+    public String getTerm() { return term; }
+
+    public String toXCQL(int level) {
        return (indent(level) + "<searchClause>\n" +
                indent(level+1) + "<index>" + xq(qualifier) + "</index>\n" +
                relation.toXCQL(level+1) +
@@ -28,7 +42,7 @@ public class CQLTermNode extends CQLNode {
                indent(level) + "</searchClause>\n");
     }
 
-    String toCQL() {
+    public String toCQL() {
        String quotedQualifier = maybeQuote(qualifier);
        String quotedTerm = maybeQuote(term);
        String res = quotedTerm;
@@ -41,6 +55,43 @@ public class CQLTermNode extends CQLNode {
        return res;
     }
 
+    public String toPQF(Properties config)
+       throws UnknownQualifierException, UnknownRelationException {
+       Vector attrs = new Vector();
+
+       if (qualifier != null) {
+           String s = config.getProperty(qualifier);
+           if (s == null)
+               throw new UnknownQualifierException(qualifier);
+           attrs.add(s);
+       } else {
+           // ### get a default access point from properties?
+       }
+
+       if (relation != null) {
+           String rel = relation.getBase();
+           // ### handle "any" and "all"
+           String s = config.getProperty("cql-java.relation." + rel);
+           if (s == null)
+               throw new UnknownRelationException(rel);
+           attrs.add(s);
+       } else {
+           // ### get a default relation from properties?
+       }
+
+       // ### handle position attributes
+       // ### handle structure attributes
+       // ### handle "always" attributes
+
+       // ### should split Vector elements on spaces
+       String s = "";
+       for (int i = 0; i < attrs.size(); i++) {
+           s += "@attr " + (String) attrs.get(i) + " ";
+       }
+
+       return s + maybeQuote(term);
+    }
+
     static String maybeQuote(String str) {
        // There _must_ be a better way to make this test ...
        if (str.length() == 0 ||
index 5b2ca73..fd3a211 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.6 2002-11-04 12:55:23 mike Exp $
+# $Id: Makefile,v 1.7 2002-11-06 00:05:58 mike Exp $
 
 DOCDIR = ../../../../../docs
 
@@ -7,7 +7,8 @@ OBJ = Utils.class \
        CQLAndNode.class CQLOrNode.class CQLNotNode.class \
        CQLRelation.class CQLProxNode.class ModifierSet.class \
        CQLParser.class CQLLexer.class CQLParseException.class \
-       CQLGenerator.class ParameterMissingException.class
+       CQLGenerator.class MissingParameterException.class \
+       UnknownQualifierException.class UnknownRelationException.class
 
 ../../../../../lib/cql-java.jar: $(OBJ)
        cd ../../../..; jar cf ../lib/cql-java.jar org/z3950/zing/cql/*.class
diff --git a/src/org/z3950/zing/cql/MissingParameterException.java b/src/org/z3950/zing/cql/MissingParameterException.java
new file mode 100644 (file)
index 0000000..3d184bd
--- /dev/null
@@ -0,0 +1,16 @@
+// $Id: MissingParameterException.java,v 1.1 2002-11-06 00:05:58 mike Exp $
+
+package org.z3950.zing.cql;
+import java.lang.Exception;
+
+
+/**
+ * Exception indicating that a required property was not specified.
+ *
+ * @version    $Id: MissingParameterException.java,v 1.1 2002-11-06 00:05:58 mike Exp $
+ */
+public class MissingParameterException extends Exception {
+    MissingParameterException(String s) {
+       super(s);
+    }
+}
index 3e45fb7..4f61bed 100644 (file)
@@ -1,4 +1,4 @@
-// $Id: ModifierSet.java,v 1.2 2002-11-02 01:20:42 mike Exp $
+// $Id: ModifierSet.java,v 1.3 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 import java.util.Vector;
@@ -11,7 +11,7 @@ import java.lang.StringBuffer;
  * CQLProxNode - two functionally very separate classes that happen to
  * require the same data structures and functionality.
  *
- * @version $Id: ModifierSet.java,v 1.2 2002-11-02 01:20:42 mike Exp $
+ * @version $Id: ModifierSet.java,v 1.3 2002-11-06 00:05:58 mike Exp $
  */
 public class ModifierSet {
     String base;
@@ -22,6 +22,10 @@ public class ModifierSet {
        modifiers = new Vector();
     }
 
+    public String getBase() {
+       return base;
+    }
+
     public void addModifier(String type, String value) {
        Vector modifier = new Vector();
        modifier.add(type);
diff --git a/src/org/z3950/zing/cql/ParameterMissingException.java b/src/org/z3950/zing/cql/ParameterMissingException.java
deleted file mode 100644 (file)
index cfd549d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// $Id: ParameterMissingException.java,v 1.1 2002-10-30 09:19:26 mike Exp $
-
-package org.z3950.zing.cql;
-import java.lang.Exception;
-
-
-/**
- * Exception indicating that a required property was not specified.
- *
- * @version    $Id: ParameterMissingException.java,v 1.1 2002-10-30 09:19:26 mike Exp $
- */
-public class ParameterMissingException extends Exception {
-    ParameterMissingException(String s) {
-       super(s);
-    }
-}
diff --git a/src/org/z3950/zing/cql/UnknownQualifierException.java b/src/org/z3950/zing/cql/UnknownQualifierException.java
new file mode 100644 (file)
index 0000000..ba43baf
--- /dev/null
@@ -0,0 +1,20 @@
+// $Id: UnknownQualifierException.java,v 1.1 2002-11-06 00:05:58 mike Exp $
+
+package org.z3950.zing.cql;
+import java.lang.Exception;
+
+
+/**
+ * Exception indicating that a qualifier was not recognised.
+ * At compilation time, we accept any syntactically valid qualifier;
+ * but when rendering a tree out as PQF, we need to translate the
+ * qualifiers into sets of Type-1 query attributes.  If we can't do
+ * that, we throw one of these babies.
+ *
+ * @version $Id: UnknownQualifierException.java,v 1.1 2002-11-06 00:05:58 mike Exp $
+ */
+public class UnknownQualifierException extends Exception {
+    UnknownQualifierException(String s) {
+       super(s);
+    }
+}
diff --git a/src/org/z3950/zing/cql/UnknownRelationException.java b/src/org/z3950/zing/cql/UnknownRelationException.java
new file mode 100644 (file)
index 0000000..6029bf4
--- /dev/null
@@ -0,0 +1,20 @@
+// $Id: UnknownRelationException.java,v 1.1 2002-11-06 00:05:58 mike Exp $
+
+package org.z3950.zing.cql;
+import java.lang.Exception;
+
+
+/**
+ * Exception indicating that a relation was not recognised.
+ * At compilation time, we accept any syntactically valid relation;
+ * but when rendering a tree out as PQF, we need to translate the
+ * relations into sets of Type-1 query attributes.  If we can't do
+ * that, we throw one of these babies.
+ *
+ * @version $Id: UnknownRelationException.java,v 1.1 2002-11-06 00:05:58 mike Exp $
+ */
+public class UnknownRelationException extends Exception {
+    UnknownRelationException(String s) {
+       super(s);
+    }
+}
index 3c06f7c..6777e46 100644 (file)
@@ -1,13 +1,13 @@
-// $Id: Utils.java,v 1.1 2002-10-31 22:23:19 mike Exp $
+// $Id: Utils.java,v 1.2 2002-11-06 00:05:58 mike Exp $
 
 package org.z3950.zing.cql;
 
 
 /**
  * Utility functions for the org.z3950.zing.cql package.
- * ##
+ * Not intended for use outside this package.
  *
- * @version    $Id: Utils.java,v 1.1 2002-10-31 22:23:19 mike Exp $
+ * @version    $Id: Utils.java,v 1.2 2002-11-06 00:05:58 mike Exp $
  */
 class Utils {
     static String indent(int level) {