Integrate Ralph's changes.
[cql-java-moved-to-github.git] / src / org / z3950 / zing / cql / CQLProxNode.java
1 // $Id: CQLProxNode.java,v 1.7 2002-12-05 17:14:52 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.7 2002-12-05 17:14:52 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 modifiers, each represented by a two-element
62      *  <TT>Vector</TT>, in which element 0 is the modifier type
63      *  (e.g. <TT>distance</TT> or <TT>ordering</TT>) and element 1 is
64      *  the associated value (e.g. <TT>3</TT> or <TT>unordered</TT>).
65      */
66     public Vector[] getModifiers() {
67         return ms.getModifiers();
68     }
69
70     String op() {
71         return ms.toCQL();
72     }
73
74     String opXCQL(int level) {
75         return ms.toXCQL(level, "boolean");
76     }
77
78     /*
79      * proximity ::= exclusion distance ordered relation which-code unit-code.
80      * exclusion ::= '1' | '0' | 'void'.
81      * distance ::= integer.
82      * ordered ::= '1' | '0'.
83      * relation ::= integer.
84      * which-code ::= 'known' | 'private' | integer.
85      * unit-code ::= integer.
86      */
87     String opPQF() {
88         int relCode = getRelCode();
89         int unitCode = getProxUnitCode();
90
91         String res = "prox " +
92             "0 " +
93             ms.modifier("distance") + " " +
94             (ms.modifier("ordering").equals("ordered") ? 1 : 0) + " " +
95             relCode + " " +
96             "1 " +
97             unitCode;
98
99         return res;
100     }
101
102     private int getRelCode() {
103         String rel = ms.modifier("relation");
104         if (rel.equals("<")) {
105             return 1;
106         } else if (rel.equals("<=")) {
107             return 2;
108         } else if (rel.equals("=")) {
109             return 3;
110         } else if (rel.equals(">=")) {
111             return 4;
112         } else if (rel.equals(">")) {
113             return 5;
114         } else if (rel.equals("<>")) {
115             return 6;
116         }
117         return 0;
118     }
119
120     private int getProxUnitCode() {
121         String unit = ms.modifier("unit");
122         if (unit.equals("word")) {
123             return 2;
124         } else if (unit.equals("sentence")) {
125             return 3;
126         } else if (unit.equals("paragraph")) {
127             return 4;
128         } else if (unit.equals("element")) {
129             return 8;
130         }
131         return 0;
132     }
133
134
135     byte[] opType1() {
136         byte[] op = new byte[100];
137         int offset, value;
138         offset = putTag(CONTEXT, 46, CONSTRUCTED, op, 0); // Operator
139         op[offset++] = (byte)(0x80&0xff); // indefinite length
140
141         offset = putTag(CONTEXT, 3, CONSTRUCTED, op, offset); // prox
142         op[offset++] = (byte)(0x80&0xff); // indefinite length
143
144         offset = putTag(CONTEXT, 1, PRIMITIVE, op, offset); // exclusion
145         value = 0; // false
146         offset = putLen(numLen(value), op, offset);
147         offset = putNum(value, op, offset);
148
149         offset = putTag(CONTEXT, 2, PRIMITIVE, op, offset); // distance
150         value = Integer.parseInt(ms.modifier("distance"));
151         offset = putLen(numLen(value), op, offset);
152         offset = putNum(value, op, offset);
153
154         offset = putTag(CONTEXT, 3, PRIMITIVE, op, offset); // ordered
155         value = ms.modifier("ordering").equals("ordered") ? 1 : 0;
156         offset = putLen(numLen(value), op, offset);
157         offset = putNum(value, op, offset);
158
159         offset = putTag(CONTEXT, 4, PRIMITIVE, op, offset); // relationType
160         value = getRelCode();
161         offset = putLen(numLen(value), op, offset);
162         offset = putNum(value, op, offset);
163
164         offset = putTag(CONTEXT, 5, CONSTRUCTED, op, offset); // proximityUnitCode
165         op[offset++] = (byte)(0x80&0xff); // indefinite length
166         offset = putTag(CONTEXT, 1, PRIMITIVE, op, offset); // known
167         value = getProxUnitCode();
168         offset = putLen(numLen(value), op, offset);
169         offset = putNum(value, op, offset);
170         op[offset++] = 0x00; // end of proximityUnitCode
171         op[offset++] = 0x00;
172
173         op[offset++] = 0x00; // end of prox
174         op[offset++] = 0x00;
175         op[offset++] = 0x00; // end of Operator
176         op[offset++] = 0x00;
177
178         byte[] o = new byte[offset];
179         System.arraycopy(op, 0, o, 0, offset);
180         return o;
181     }
182 }