3 for (var i = 0; i < n; i++)
9 var CQLModifier = function () {
15 CQLModifier.prototype = {
16 toXCQL: function (n) {
17 var s = indent(n+1) + "<modifier>\n";
18 s = s + indent(n+2) + "<name>" + this.name + "</name>\n";
19 if (this.relation != null)
21 + "<relation>" + this.relation + "</relation>\n";
22 if (this.value != null)
24 + "<value>" + this.value +"</value>\n";
25 s = s + indent(n+1) + "</modifier>\n";
30 var CQLSearchClause = function (field, fielduri, relation, relationuri,
33 this.fielduri = fielduri;
34 this.relation = relation;
35 this.relationuri = relationuri;
36 this.modifiers = modifiers;
40 CQLSearchClause.prototype = {
41 toXCQL: function (n) {
42 var s = indent(n) + "<searchClause>\n";
43 if (this.fielduri.length > 0)
45 s = s + indent(n+1) + "<prefixes>\n" +
46 indent(n+2) + "<prefix>\n" +
47 indent(n+3) + "<identifier>" + this.fielduri +
49 indent(n+2) + "</prefix>\n" +
50 indent(n+1) + "</prefixes>\n";
52 s = s + indent(n+1) + "<index>" + this.field + "</index>\n";
53 s = s + indent(n+1) + "<relation>\n";
54 if (this.relationuri.length > 0) {
56 "<identifier>" + this.relationuri + "</identifier>\n";
58 s = s + indent(n+2) + "<value>" + this.relation + "</value>\n";
59 if (this.modifiers.length > 0) {
60 s = s + indent(n+2) + "<modifiers>\n";
61 for (var i = 0; i < this.modifiers.length; i++)
62 s = s + this.modifiers[i].toXCQL(n+2);
63 s = s + indent(n+2) + "</modifiers>\n";
65 s = s + indent(n+1) + "</relation>\n";
66 s = s + indent(n+1) + "<term>" + this.term + "</term>\n";
67 s = s + indent(n) + "</searchClause>\n";
72 var CQLBoolean = function() {
74 this.modifiers = null;
79 CQLBoolean.prototype = {
80 toXCQL: function (n) {
81 var s = indent(n) + "<triple>\n";
82 s = s + indent(n+1) + "<boolean>\n" +
83 indent(n+2) + "<value>" + this.op + "</value>\n";
84 if (this.modifiers.length > 0) {
85 s = s + indent(n+2) + "<modifiers>\n";
86 for (var i = 0; i < this.modifiers.length; i++)
87 s = s + this.modifiers[i].toXCQL(n+2);
88 s = s + indent(n+2) + "</modifiers>\n";
90 s = s + indent(n+1) + "</boolean>\n";
91 s = s + indent(n+1) + "<leftOperand>\n" +
92 this.left.toXCQL(n+2) + indent(n+1) + "</leftOperand>\n";
94 s = s + indent(n+1) + "<rightOperand>\n" +
95 this.right.toXCQL(n+2) + indent(n+1) + "</rightOperand>\n";
96 s = s + indent(n) + "</triple>\n";
101 var CQLParser = function () {
108 this.prefixes = new Object();
112 CQLParser.prototype = {
113 parse: function (query) {
115 throw new Error("The query to be parsed cannot be empty");
118 this.ql = this.qs.length;
121 this.tree = this._parseQuery("cql.serverChoice", "scr", new Array());
123 throw new Error("EOF expected");
125 toXCQL: function () {
126 return this.tree.toXCQL();
128 _parseQuery: function(field, relation, modifiers) {
129 var left = this._parseSearchClause(field, relation, modifiers);
130 while (this.look == "s" && (
131 this.lval == "and" ||
133 this.lval == "not" ||
134 this.lval == "prox")) {
135 var b = new CQLBoolean();
138 b.modifiers = this._parseModifiers();
140 b.right = this._parseSearchClause(field, relation, modifiers);
145 _parseModifiers: function() {
146 var ar = new Array();
147 while (this.look == "/") {
149 if (this.look != "s" && this.look != "q")
150 throw new Error("Invalid modifier.")
152 var name = this.lval;
154 if (this.look.length > 0
155 && this._strchr("<>=", this.look.charAt(0))) {
158 if (this.look != "s" && this.look != "q")
159 throw new Error("Invalid relation within the modifier.");
161 var m = new CQLModifier();
168 var m = new CQLModifier();
177 _parseSearchClause: function(field, relation, modifiers) {
178 if (this.look == "(") {
180 var b = this._parseQuery(field, relation, modifiers);
181 if (this.look == ")")
184 throw new Error("Missing closing parenthesis.");
187 } else if (this.look == "s" || this.look == "q") {
188 var first = this.val; // dont know if field or term yet
190 if (this.look == "q" ||
192 this.lval != "and" &&
194 this.lval != "not" &&
195 this.lval != "prox")) {
196 var rel = this.val; // string relation
198 return this._parseSearchClause(first, rel,
199 this._parseModifiers());
200 } else if (this.look.length > 0
201 && this._strchr("<>=", this.look.charAt(0))) {
202 var rel = this.look; // other relation <, = ,etc
204 return this._parseSearchClause(first, rel,
205 this._parseModifiers());
207 // it's a search term
208 var pos = field.indexOf('.');
211 pre = field.substring(0, pos);
213 var uri = this._lookupPrefix(pre);
215 field = field.substring(pos+1);
217 pos = relation.indexOf('.');
221 pre = relation.substring(0, pos);
223 var reluri = this._lookupPrefix(pre);
224 if (reluri.Length > 0)
225 relation = relation.Substring(pos+1);
227 var sc = new CQLSearchClause(field,
236 } else if (this.look == ">") {
238 if (this.look != "s" && this.look != "q")
239 throw new Error("Expecting string or a quoted expression.");
241 var first = this.lval;
243 if (this.look == "=")
246 if (this.look != "s" && this.look != "q")
247 throw new Error("Expecting string or a quoted expression.");
249 this._addPrefix(first, this.lval);
251 return this._parseQuery(field, relation, modifiers);
253 this._addPrefix("default", first);
254 return this._parseQuery(field, relation, modifiers);
257 throw new Error("Invalid search clause.");
262 while (this.qi < this.ql
263 && this._strchr(" \t\r\n", this.qs.charAt(this.qi)))
265 if (this.qi == this.ql) {
269 var c = this.qs.charAt(this.qi);
270 if (this._strchr("()/", c)) {
273 } else if (this._strchr("<>=", c)) {
276 while (this.qi < this.ql
277 && this._strchr("<>=", this.qs.charAt(this.qi))) {
278 this.look = this.look + this.qs.charAt(this.qi);
281 } else if (this._strchr("\"'", c)) {
286 while (this.qi < this.ql
287 && this.qs.charAt(this.qi) != mark) {
288 if (this.qs.charAt(this.qi) == '\\'
289 && this.qi < this.ql-1)
291 this.val = this.val + this.qs.charAt(this.qi);
294 this.lval = this.val.toLowerCase();
295 if (this.qi < this.ql)
300 while (this.qi < this.ql
301 && !this._strchr("()/<>= \t\r\n", this.qs.charAt(this.qi))) {
302 this.val = this.val + this.qs.charAt(this.qi);
305 this.lval = this.val.toLowerCase();
308 _strchr: function (s, ch) {
309 return s.indexOf(ch) >= 0
311 _lookupPrefix: function(name) {
312 return this.prefixes[name] ? this.prefixes[name] : "";
314 _addPrefix: function(name, value) {
315 //overwrite existing items
316 this.prefixes[name] = value;