Removed ModifierSet, since base class now has this.
[cql-java-moved-to-github.git] / src / org / z3950 / zing / cql / CQLProxNode.java
1 // $Id: CQLProxNode.java,v 1.10 2007-06-29 10:24:03 mike Exp $
2
3 package org.z3950.zing.cql;
4 import java.util.Vector;
5
6
7 /**
8  * Represents a proximity node in a CQL parse-tree.
9  * The left- and right-hand-sides must be satisfied by parts of the
10  * candidate records which are sufficiently close to each other, as
11  * specified by a set of proximity parameters.
12  *
13  * @version     $Id: CQLProxNode.java,v 1.10 2007-06-29 10:24:03 mike Exp $
14  */
15 public class CQLProxNode extends CQLBooleanNode {
16     /**
17      * Creates a new, <I>incomplete</I>, proximity node with the
18      * specified left-hand side.  No right-hand side is specified at
19      * this stage: that must be specified later, using the
20      * <TT>addSecondSubterm()</TT> method.  (That may seem odd, but
21      * it's just easier to write the parser that way.)
22      * <P>
23      * Proximity paramaters may be added at any time, before or after
24      * the right-hand-side sub-tree is added.
25      */
26     public CQLProxNode(CQLNode left) {
27         super(left, null, new ModifierSet("prox"));
28         // this.right left unresolved for now ...
29     }
30
31     /**
32      * Sets the right-hand side of the proximity node whose
33      * left-hand-side was specified at creation time.
34      */
35     public void addSecondSubterm(CQLNode right) {
36         this.right = right;
37     }
38
39     /**
40      * Adds a modifier of the specified <TT>type</TT>,
41      * <TT>comparison</TT> and <TT>value</TT> to a proximity node.
42      */
43     public void addModifier(String type, String comparison, String value) {
44         ms.addModifier(type, comparison, value);
45     }
46
47     /**
48      * Returns an array of the modifiers associated with a proximity
49      * node.
50      * @return
51      *  An array of Modifier objects.
52      */
53     public Vector<Modifier> getModifiers() {
54         return ms.getModifiers();
55     }
56
57     String op() {
58         return ms.toCQL();
59     }
60
61     /*
62      * proximity ::= exclusion distance ordered relation which-code unit-code.
63      * exclusion ::= '1' | '0' | 'void'.
64      * distance ::= integer.
65      * ordered ::= '1' | '0'.
66      * relation ::= integer.
67      * which-code ::= 'known' | 'private' | integer.
68      * unit-code ::= integer.
69      */
70     String opPQF() {
71         int relCode = getRelCode();
72         int unitCode = getProxUnitCode();
73
74         String res = "prox " +
75             "0 " +
76             ms.modifier("distance") + " " +
77             (ms.modifier("ordering").equals("ordered") ? 1 : 0) + " " +
78             relCode + " " +
79             "1 " +
80             unitCode;
81
82         return res;
83     }
84
85     private int getRelCode() {
86         String rel = ms.modifier("relation");
87         if (rel.equals("<")) {
88             return 1;
89         } else if (rel.equals("<=")) {
90             return 2;
91         } else if (rel.equals("=")) {
92             return 3;
93         } else if (rel.equals(">=")) {
94             return 4;
95         } else if (rel.equals(">")) {
96             return 5;
97         } else if (rel.equals("<>")) {
98             return 6;
99         }
100         return 0;
101     }
102
103     private int getProxUnitCode() {
104         String unit = ms.modifier("unit");
105         if (unit.equals("word")) {
106             return 2;
107         } else if (unit.equals("sentence")) {
108             return 3;
109         } else if (unit.equals("paragraph")) {
110             return 4;
111         } else if (unit.equals("element")) {
112             return 8;
113         }
114         return 0;
115     }
116
117
118     byte[] opType1() {
119         byte[] op = new byte[100];
120         int offset, value;
121         offset = putTag(CONTEXT, 46, CONSTRUCTED, op, 0); // Operator
122         op[offset++] = (byte)(0x80&0xff); // indefinite length
123
124         offset = putTag(CONTEXT, 3, CONSTRUCTED, op, offset); // prox
125         op[offset++] = (byte)(0x80&0xff); // indefinite length
126
127         offset = putTag(CONTEXT, 1, PRIMITIVE, op, offset); // exclusion
128         value = 0; // false
129         offset = putLen(numLen(value), op, offset);
130         offset = putNum(value, op, offset);
131
132         offset = putTag(CONTEXT, 2, PRIMITIVE, op, offset); // distance
133         value = Integer.parseInt(ms.modifier("distance"));
134         offset = putLen(numLen(value), op, offset);
135         offset = putNum(value, op, offset);
136
137         offset = putTag(CONTEXT, 3, PRIMITIVE, op, offset); // ordered
138         value = ms.modifier("ordering").equals("ordered") ? 1 : 0;
139         offset = putLen(numLen(value), op, offset);
140         offset = putNum(value, op, offset);
141
142         offset = putTag(CONTEXT, 4, PRIMITIVE, op, offset); // relationType
143         value = getRelCode();
144         offset = putLen(numLen(value), op, offset);
145         offset = putNum(value, op, offset);
146
147         offset = putTag(CONTEXT, 5, CONSTRUCTED, op, offset); // proximityUnitCode
148         op[offset++] = (byte)(0x80&0xff); // indefinite length
149         offset = putTag(CONTEXT, 1, PRIMITIVE, op, offset); // known
150         value = getProxUnitCode();
151         offset = putLen(numLen(value), op, offset);
152         offset = putNum(value, op, offset);
153         op[offset++] = 0x00; // end of proximityUnitCode
154         op[offset++] = 0x00;
155
156         op[offset++] = 0x00; // end of prox
157         op[offset++] = 0x00;
158         op[offset++] = 0x00; // end of Operator
159         op[offset++] = 0x00;
160
161         byte[] o = new byte[offset];
162         System.arraycopy(op, 0, o, 0, offset);
163         return o;
164     }
165 }