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