Add classes for visitor traversal
[cql-java-moved-to-github.git] / src / main / java / org / z3950 / zing / cql / CQLNode.java
index d300782..221da44 100644 (file)
@@ -1,17 +1,19 @@
-// $Id: CQLNode.java,v 1.26 2007-07-03 13:36:03 mike Exp $
 
 package org.z3950.zing.cql;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Properties;
-import java.util.Vector;
+
 
 
 /**
  * Represents a node in a CQL parse-tree.
  *
- * @version    $Id: CQLNode.java,v 1.26 2007-07-03 13:36:03 mike Exp $
  */
 public abstract class CQLNode {
-    CQLNode() {}               // prevent javadoc from documenting this
+  
+    public abstract void traverse(CQLNodeVisitor visitor);
 
     /**
      * Returns the name of the result-set to which this query is a
@@ -28,52 +30,51 @@ public abstract class CQLNode {
     /**
      * 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.
      */
-    public String toXCQL(int level) {
-       return toXCQL(level, null);
+    public String toXCQL() {
+        StringBuilder sb = new StringBuilder();
+       toXCQLInternal(new XCQLBuilder(sb), 0);
+        return sb.toString();
     }
 
-    public String toXCQL(int level, Vector<CQLPrefix> prefixes) {
-       return toXCQL(level, prefixes, null);
+    void toXCQLInternal(XCQLBuilder b, int level) {
+        toXCQLInternal(b, level, null, null);
     }
 
-    abstract public String toXCQL(int level, Vector<CQLPrefix> prefixes,
-                                 Vector<ModifierSet> sortkeys);
+    abstract void toXCQLInternal(XCQLBuilder b, int level,
+      List<CQLPrefix> prefixes, List<ModifierSet> sortkeys);
 
-    protected static String renderPrefixes(int level, Vector prefixes) {
+    static void renderPrefixes(XCQLBuilder b,
+        int level, List<CQLPrefix> prefixes) {
        if (prefixes == null || prefixes.size() == 0)
-           return "";
-       String res = indent(level) + "<prefixes>\n";
+           return;
+       b.indent(level).append("<prefixes>\n");
        for (int i = 0; i < prefixes.size(); i++) {
-           CQLPrefix p = (CQLPrefix) prefixes.get(i);
-           res += indent(level+1) + "<prefix>\n";
+           CQLPrefix p = prefixes.get(i);
+           b.indent(level+1).append("<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";
+               b.indent(level + 2).append("<name>").
+                    append(p.name).append("</name>\n");
+            b.indent(level + 2).append("<identifier>").
+                append(p.identifier).append("</identifier>\n");
+            b.indent(level+1).append("</prefix>\n");
        }
-       return res + indent(level) + "</prefixes>\n";
+       b.indent(level).append("</prefixes>\n");
     }
 
-    protected static String renderSortKeys(int level,
-                                          Vector<ModifierSet> sortkeys) {
+    static void renderSortKeys(XCQLBuilder b, int level,
+                                          List<ModifierSet> sortkeys) {
        if (sortkeys == null || sortkeys.size() == 0)
-           return "";
-       String res = indent(level) + "<sortKeys>\n";
+           return;
+       b.indent(level).append("<sortKeys>\n");
        for (int i = 0; i < sortkeys.size(); i++) {
            ModifierSet key = sortkeys.get(i);
-           res += key.sortKeyToXCQL(level+1);
+           key.toXCQLInternal(b, level+1, "key", "index");
        }
-       return res + indent(level) + "</sortKeys>\n";
+       b.indent(level).append("</sortKeys>\n");
     }
 
     /**
@@ -111,18 +112,6 @@ public abstract class CQLNode {
        throws PQFTranslationException;
 
     /**
-     * Returns a String of spaces for indenting to the specified level.
-     */
-    protected static String indent(int level) { return Utils.indent(level); }
-
-    /**
-     * 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); }
-
-    /**
      * Renders a parser-tree into a BER-endoded packet representing an
      * equivalent Z39.50 Type-1 query.  If you don't know what that
      * means, then you don't need this method :-)  This is useful
@@ -261,8 +250,8 @@ public abstract class CQLNode {
     }
 
     // Used only by the makeOID() method
-    private static final java.util.Hashtable<String, byte[]> madeOIDs =
-       new java.util.Hashtable<String, byte[]>(10);
+    private static final Map<String, byte[]> madeOIDs =
+       new HashMap<String, byte[]>(10);
 
     protected static final byte[] makeOID(String oid) {
         byte[] o;
@@ -350,4 +339,9 @@ public abstract class CQLNode {
         System.arraycopy(qry, 0, q, 0, offset);
         return q;
     }
+    
+    @Override
+    public String toString() {
+        return toCQL();
+    }
 }