From: mike Date: Wed, 6 Nov 2002 00:05:57 +0000 (+0000) Subject: Towards 0.2 -- X-Git-Tag: v1.5~236 X-Git-Url: http://git.indexdata.com/?p=cql-java-moved-to-github.git;a=commitdiff_plain;h=df372083094087da8590a526e0222c81c9ae7fc0 Towards 0.2 -- - Fix the order of proximity parameters in accordance with the updated official grammar, which now specifies proximity operators of the form prox//// 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 " 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. --- diff --git a/Changes b/Changes new file mode 100644 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//// + 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 " 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 --- 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 index 0000000..9c4abbf --- /dev/null +++ b/etc/pqf.properties @@ -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." 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 diff --git a/src/org/z3950/zing/cql/CQLAndNode.java b/src/org/z3950/zing/cql/CQLAndNode.java index 57cde12..1f5157f 100644 --- a/src/org/z3950/zing/cql/CQLAndNode.java +++ b/src/org/z3950/zing/cql/CQLAndNode.java @@ -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; diff --git a/src/org/z3950/zing/cql/CQLBooleanNode.java b/src/org/z3950/zing/cql/CQLBooleanNode.java index 56c212f..a3c3749 100644 --- a/src/org/z3950/zing/cql/CQLBooleanNode.java +++ b/src/org/z3950/zing/cql/CQLBooleanNode.java @@ -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) + "\n" + booleanXQL(level+1) + left.toXCQL(level+1) + @@ -23,13 +31,14 @@ public abstract class CQLBooleanNode extends CQLNode { indent(level) + "\n"); } + // Represents the boolean operation itself: overridden for CQLProxNode String booleanXQL(int level) { return(indent(level) + "\n" + indent(level+1) + "" + op() + "\n" + indent(level) + "\n"); } - String toCQL() { + public String toCQL() { // ### We don't always need parens around the operands return "(" + left.toCQL() + ") " + op() + " (" + right.toCQL() + ")"; } diff --git a/src/org/z3950/zing/cql/CQLGenerator.java b/src/org/z3950/zing/cql/CQLGenerator.java index 991f60d..c0f05ce 100644 --- a/src/org/z3950/zing/cql/CQLGenerator.java +++ b/src/org/z3950/zing/cql/CQLGenerator.java @@ -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 generate_x() method * for each grammar element X. * - * @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 http://zing.z3950.org/cql/index.html */ @@ -125,11 +125,11 @@ public class CQLGenerator { * method, or decompiled into CQL using its toCQL * 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); diff --git a/src/org/z3950/zing/cql/CQLNode.java b/src/org/z3950/zing/cql/CQLNode.java index d36c11f..24a2d27 100644 --- a/src/org/z3950/zing/cql/CQLNode.java +++ b/src/org/z3950/zing/cql/CQLNode.java @@ -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. + *

+ * @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. + *

+ * @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. + *

+ * @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 < is translated to + * &lt;. + */ + protected static String xq(String str) { return Utils.xq(str); } } diff --git a/src/org/z3950/zing/cql/CQLNotNode.java b/src/org/z3950/zing/cql/CQLNotNode.java index 3eb1f7a..a2a64c2 100644 --- a/src/org/z3950/zing/cql/CQLNotNode.java +++ b/src/org/z3950/zing/cql/CQLNotNode.java @@ -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; diff --git a/src/org/z3950/zing/cql/CQLOrNode.java b/src/org/z3950/zing/cql/CQLOrNode.java index 7dc253c..bacca98 100644 --- a/src/org/z3950/zing/cql/CQLOrNode.java +++ b/src/org/z3950/zing/cql/CQLOrNode.java @@ -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; diff --git a/src/org/z3950/zing/cql/CQLParser.java b/src/org/z3950/zing/cql/CQLParser.java index 79abc31..59cedf8 100644 --- a/src/org/z3950/zing/cql/CQLParser.java +++ b/src/org/z3950/zing/cql/CQLParser.java @@ -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 http://zing.z3950.org/cql/index.html */ @@ -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 { * -c 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] []"); + System.err.println( + "Usage: CQLParser [-c] [-p []"); 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); + } } } diff --git a/src/org/z3950/zing/cql/CQLProxNode.java b/src/org/z3950/zing/cql/CQLProxNode.java index 1b9abe9..8c69ecc 100644 --- a/src/org/z3950/zing/cql/CQLProxNode.java +++ b/src/org/z3950/zing/cql/CQLProxNode.java @@ -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, incomplete, proximity node with the + * specified left-hand side. No right-hand side is specified at + * this stage: that must be specified later, using the + * addSecondSubterm() method. (That may seem odd, but + * it's just easier to write the parser that way.) + *

+ * 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 type and + * value to a proximity node. Valid types are + * relation, distance, unit and + * ordering. + *

+ * For information on the semantics of these paramaters, see + * section 3.1 (Proximity) of + * A Gentle Introduction to CQL. + */ 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"); } diff --git a/src/org/z3950/zing/cql/CQLRelation.java b/src/org/z3950/zing/cql/CQLRelation.java index ff8db8f..6d7e138 100644 --- a/src/org/z3950/zing/cql/CQLRelation.java +++ b/src/org/z3950/zing/cql/CQLRelation.java @@ -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"); + } } diff --git a/src/org/z3950/zing/cql/CQLTermNode.java b/src/org/z3950/zing/cql/CQLTermNode.java index fda7147..5889354 100644 --- a/src/org/z3950/zing/cql/CQLTermNode.java +++ b/src/org/z3950/zing/cql/CQLTermNode.java @@ -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 qualifier, + * relation and term. The first two may be + * null, but the term 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) + "\n" + indent(level+1) + "" + xq(qualifier) + "\n" + relation.toXCQL(level+1) + @@ -28,7 +42,7 @@ public class CQLTermNode extends CQLNode { indent(level) + "\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 || diff --git a/src/org/z3950/zing/cql/Makefile b/src/org/z3950/zing/cql/Makefile index 5b2ca73..fd3a211 100644 --- a/src/org/z3950/zing/cql/Makefile +++ b/src/org/z3950/zing/cql/Makefile @@ -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 index 0000000..3d184bd --- /dev/null +++ b/src/org/z3950/zing/cql/MissingParameterException.java @@ -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); + } +} diff --git a/src/org/z3950/zing/cql/ModifierSet.java b/src/org/z3950/zing/cql/ModifierSet.java index 3e45fb7..4f61bed 100644 --- a/src/org/z3950/zing/cql/ModifierSet.java +++ b/src/org/z3950/zing/cql/ModifierSet.java @@ -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 index cfd549d..0000000 --- a/src/org/z3950/zing/cql/ParameterMissingException.java +++ /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 index 0000000..ba43baf --- /dev/null +++ b/src/org/z3950/zing/cql/UnknownQualifierException.java @@ -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 index 0000000..6029bf4 --- /dev/null +++ b/src/org/z3950/zing/cql/UnknownRelationException.java @@ -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); + } +} diff --git a/src/org/z3950/zing/cql/Utils.java b/src/org/z3950/zing/cql/Utils.java index 3c06f7c..6777e46 100644 --- a/src/org/z3950/zing/cql/Utils.java +++ b/src/org/z3950/zing/cql/Utils.java @@ -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) {