Add classes for visitor traversal
[cql-java-moved-to-github.git] / src / main / java / org / z3950 / zing / cql / CQLBooleanNode.java
1
2 package org.z3950.zing.cql;
3 import java.util.List;
4 import java.util.Properties;
5
6 /**
7  * Represents a boolean node in a CQL parse-tree.
8  *
9  */
10 public abstract class CQLBooleanNode extends CQLNode {
11
12     private CQLNode left;
13
14     /**
15      * The root of a parse-tree representing the left-hand side.
16      */
17     public CQLNode getLeftOperand() {
18         return left;
19     }
20
21     private CQLNode right;
22
23     /**
24      * The root of a parse-tree representing the right-hand side.
25      */
26     public CQLNode getRightOperand() {
27         return right;
28     }
29
30     ModifierSet ms;
31
32     /**
33      * The set of modifiers that are applied to this boolean.
34      */
35     public List<Modifier> getModifiers() {
36         return ms.getModifiers();
37     }
38
39     protected CQLBooleanNode(CQLNode left, CQLNode right, ModifierSet ms) {
40         this.left = left;
41         this.right = right;
42         this.ms = ms;
43     }
44
45     @Override
46     public void traverse(CQLNodeVisitor visitor) {
47       visitor.onBooleanNode(this);
48       left.traverse(visitor);
49       right.traverse(visitor);
50     }
51
52
53     @Override
54     void toXCQLInternal(XCQLBuilder b, int level,
55         List<CQLPrefix> prefixes, List<ModifierSet> sortkeys) {
56         b.indent(level).append("<triple>\n");
57         renderPrefixes(b, level + 1, prefixes);
58         ms.toXCQLInternal(b, level + 1, "boolean", "value");
59         b.indent(level + 1).append("<leftOperand>\n");
60         left.toXCQLInternal(b, level + 2);
61         b.indent(level + 1).append("</leftOperand>\n");
62         b.indent(level + 1).append("<rightOperand>\n");
63         right.toXCQLInternal(b, level + 2);
64         b.indent(level + 1).append("</rightOperand>\n");
65         renderSortKeys(b, level + 1, sortkeys);
66         b.indent(level).append("</triple>\n");
67     }
68
69     @Override
70     public String toCQL() {
71         // ### We don't always need parens around the operands
72         return ("(" + left.toCQL() + ")" +
73                 " " + ms.toCQL() + " " +
74                 "(" + right.toCQL() + ")");
75     }
76
77     @Override
78     public String toPQF(Properties config) throws PQFTranslationException {
79         return ("@" + opPQF() +
80                 " " + left.toPQF(config) +
81                 " " + right.toPQF(config));
82     }
83
84     // represents the operation for PQF: overridden for CQLProxNode
85     String opPQF() { return ms.getBase(); }
86
87     @Override
88     public byte[] toType1BER(Properties config) throws PQFTranslationException {
89         System.out.println("in CQLBooleanNode.toType1BER(): PQF=" +
90                            toPQF(config));
91         byte[] rpn1 = left.toType1BER(config);
92         byte[] rpn2 = right.toType1BER(config);
93         byte[] op = opType1();
94         byte[] rpnStructure = new byte[rpn1.length+rpn2.length+op.length+4];
95         
96         // rpnRpnOp
97         int offset = putTag(CONTEXT, 1, CONSTRUCTED, rpnStructure, 0);
98
99         rpnStructure[offset++] = (byte)(0x80&0xff); // indefinite length
100         System.arraycopy(rpn1, 0, rpnStructure, offset, rpn1.length);
101         offset += rpn1.length;
102         System.arraycopy(rpn2, 0, rpnStructure, offset, rpn2.length);
103         offset += rpn2.length;
104         System.arraycopy(op, 0, rpnStructure, offset, op.length);
105         offset += op.length;
106         rpnStructure[offset++] = 0x00; // end rpnRpnOp
107         rpnStructure[offset++] = 0x00;
108         return rpnStructure;
109     }
110
111     abstract byte[] opType1();
112 }