X-Git-Url: http://jsfdemo.indexdata.com/?a=blobdiff_plain;f=src%2Forg%2Fz3950%2Fzing%2Fcql%2FCQLNode.java;h=28521268ca9d5df8f15780c48e6cebbf92be0868;hb=8e35f984081a29de9b53af7c1b2fbf981c474d88;hp=b619bbb827ccd613b503428cf5c65361f93041e7;hpb=dbe5e770526df9b0b8d09cfce0ebe23c3fd00bad;p=cql-java-moved-to-github.git diff --git a/src/org/z3950/zing/cql/CQLNode.java b/src/org/z3950/zing/cql/CQLNode.java index b619bbb..2852126 100644 --- a/src/org/z3950/zing/cql/CQLNode.java +++ b/src/org/z3950/zing/cql/CQLNode.java @@ -1,31 +1,337 @@ -// $Id: CQLNode.java,v 1.3 2002-10-25 16:04:44 mike Exp $ +// $Id: CQLNode.java,v 1.25 2007-06-27 22:39:55 mike Exp $ package org.z3950.zing.cql; +import java.util.Properties; +import java.util.Vector; /** - * Represents a node in a CQL parse-tree ... - * ### + * Represents a node in a CQL parse-tree. * - * @version $Id: CQLNode.java,v 1.3 2002-10-25 16:04:44 mike Exp $ + * @version $Id: CQLNode.java,v 1.25 2007-06-27 22:39:55 mike Exp $ */ public abstract class CQLNode { - abstract String toXCQL(int level); - abstract String toCQL(); + CQLNode() {} // prevent javadoc from documenting this - protected String indent(int level) { - String x = ""; - while (level-- > 0) { - x += " "; + /** + * Returns the name of the result-set to which this query is a + * reference, if and only if the entire query consists only of a + * result-set reference. If it's anything else, including a + * boolean combination of a result-set reference with something + * else, then null is returned instead. + * @return the name of the referenced result-set + */ + public String getResultSetName() { + return null; + } + + /** + * 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.
+ */
+ public String toXCQL(int level) {
+ return toXCQL(level, new Vector
+ * @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();
+
+ /**
+ * Renders a parse-tree into a Yaz-style PQF string.
+ * PQF, or Prefix Query Format, is a cryptic but powerful notation
+ * that can be trivially mapped, one-to-one, int Z39.50 Type-1 and
+ * Type-101 queries. A specification for the format can be found
+ * in
+ * Chapter 7 (Supporting Tools) of the
+ * YAZ manual.
+ *
+ * @param config
+ * A Properties object containing configuration
+ * information that specifies the mapping from CQL indexes,
+ * relations, etc. to Type-1 attributes. The mapping
+ * specification is described in the CQL-Java distribution's
+ * sample PQF-mapping configuration file,
+ * etc/pqf.properties, which see.
+ * @return
+ * A String containing a PQF query equivalent to the parse-tree
+ * whose root is this node.
+ */
+ abstract public String toPQF(Properties config)
+ 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 < is translated to
+ * <.
+ */
+ 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
+ * primarily for SRW-to-Z39.50 gateways.
+ *
+ * @param config
+ * A Properties object containing configuration
+ * information that specifies the mapping from CQL indexes,
+ * relations, etc. to Type-1 attributes. The mapping
+ * specification is described in the CQL-Java distribution's
+ * sample PQF-mapping configuration file,
+ * etc/pqf.properties, which see.
+ * @return
+ * A byte array containing the BER packet.
+ * @see
+ * ftp://ftp.rsasecurity.com/pub/pkcs/ascii/layman.asc
+ */
+ abstract public byte[] toType1BER(Properties config)
+ throws PQFTranslationException;
+
+ // ANS.1 classes
+ protected static final int UNIVERSAL = 0;
+ protected static final int APPLICATION = 1;
+ protected static final int CONTEXT = 2;
+ protected static final int PRIVATE = 3;
+
+ // ASN.1 tag forms
+ protected static final int PRIMITIVE = 0;
+ protected static final int CONSTRUCTED = 1;
+
+ // ASN.1 UNIVERSAL data types
+ public static final byte BOOLEAN = 1;
+ public static final byte INTEGER = 2;
+ public static final byte BITSTRING = 3;
+ public static final byte OCTETSTRING = 4;
+ public static final byte NULL = 5;
+ public static final byte OBJECTIDENTIFIER = 6;
+ public static final byte OBJECTDESCRIPTOR = 7;
+ public static final byte EXTERNAL = 8;
+ public static final byte ENUMERATED = 10;
+ public static final byte SEQUENCE = 16;
+ public static final byte SET = 17;
+ public static final byte VISIBLESTRING = 26;
+ public static final byte GENERALSTRING = 27;
+
+ protected static final int putTag(int asn1class, int fldid, int form,
+ byte[] record, int offset) {
+ if (fldid < 31)
+ record[offset++] = (byte)(fldid + asn1class*64 + form*32);
+ else {
+ record[offset++] = (byte)(31 + asn1class*64 + form*32);
+ if (fldid < 128)
+ record[offset++] = (byte)(fldid);
+ else {
+ record[offset++] = (byte)(128 + fldid/128);
+ record[offset++] = (byte)(fldid % 128);
+ }
+ }
+ return offset;
+ }
+
+ /**
+ * Put a length directly into a BER record.
+ *
+ * @param len length to put into record
+ * @return the new, incremented value of the offset parameter.
+ */
+ public // ### shouldn't this be protected?
+ static final int putLen(int len, byte[] record, int offset) {
+
+ if (len < 128)
+ record[offset++] = (byte)len;
+ else {
+ int t;
+ record[offset] = (byte)(lenLen(len) - 1);
+ for (t = record[offset]; t > 0; t--) {
+ record[offset+t] = (byte)(len & 0xff);
+ len >>= 8;
+ }
+ t = offset;
+ offset += (record[offset]&0xff) + 1;
+ record[t] += 128; // turn on bit 8 in length byte.
+ }
+ return offset;
+ }
+
+ /**
+ * Get the length needed to represent the given length.
+ *
+ * @param length determine length needed to encode this
+ * @return length needed to encode given length
+ */
+ protected // ### shouldn't this be private?
+ static final int lenLen(int length) {
+
+ return ((length < 128) ? 1 :
+ (length < 256) ? 2 :
+ (length < 65536L) ? 3 : 4);
+ }
+
+ /**
+ * Get the length needed to represent the given number.
+ *
+ * @param num determine length needed to encode this
+ * @return length needed to encode given number
+ */
+ protected static final int numLen(long num) {
+ num = num < 0 ? -num : num;
+ // ### Wouldn't this be better done algorithmically?
+ // Or at least with the constants expressed in hex?
+ return ((num < 128) ? 1 :
+ (num < 32768) ? 2 :
+ (num < 8388608) ? 3 :
+ (num < 2147483648L) ? 4 :
+ (num < 549755813888L) ? 5 :
+ (num < 140737488355328L) ? 6 :
+ (num < 36028797018963968L) ? 7 : 8);
+ }
+
+ /**
+ * Put a number into a given buffer
+ *
+ * @param num number to put into buffer
+ * @param record buffer to use
+ * @param offset offset into buffer
+ * @return the new, incremented value of the offset parameter.
+ */
+ protected static final int putNum(long num, byte record[], int offset) {
+ int cnt=numLen(num);
+
+ for (int count = cnt - 1; count >= 0; count--) {
+ record[offset+count] = (byte)(num & 0xff);
+ num >>= 8;
+ }
+ return offset+cnt;
+ }
+
+ // Used only by the makeOID() method
+ private static final java.util.Hashtable