X-Git-Url: http://git.indexdata.com/?p=cql-js-moved-to-github.git;a=blobdiff_plain;f=cql.js;h=2a04c6766901903c3f10289e6b60182bf71aa8a8;hp=3e4f6d177cb399db8f714f1684119fabc187c0f1;hb=68c734cf593dd23d746c6739f42c3b0739fed2a5;hpb=ef1c473eb97976c5839851e06195915de6da6897;ds=sidebyside
diff --git a/cql.js b/cql.js
index 3e4f6d1..2a04c67 100644
--- a/cql.js
+++ b/cql.js
@@ -1,7 +1,9 @@
-function indent(n) {
+var EXPORTED_SYMBOLS = ["CQLParser"];
+
+function indent(n, c) {
var s = "";
for (var i = 0; i < n; i++)
- s = s + " ";
+ s = s + c;
return s;
}
// CQLModifier
@@ -12,19 +14,32 @@ var CQLModifier = function () {
}
CQLModifier.prototype = {
- toXCQL: function (n) {
- var s = indent(n+1) + "\n";
- s = s + indent(n+2) + "" + this.name + "\n";
+ toString: function () {
+ return this.name + this.relation + this.value;
+ },
+
+ toXCQL: function (n, c) {
+ var s = indent(n+1, c) + "\n";
+ s = s + indent(n+2, c) + "" + this.name + "\n";
if (this.relation != null)
- s = s + indent(n+2)
+ s = s + indent(n+2, c)
+ "" + this.relation + "\n";
if (this.value != null)
- s = s + indent(n+2)
+ s = s + indent(n+2, c)
+ "" + this.value +"\n";
- s = s + indent(n+1) + "\n";
+ s = s + indent(n+1, c) + "\n";
+ return s;
+ },
+
+ toFQ: function () {
+ //we ignore modifier relation symbol, for value-less modifiers
+ //we assume 'true'
+ var value = this.value.length > 0 ? this.value : "true";
+ var s = '"'+this.name+'": "'+value+'"';
return s;
}
}
+
// CQLSearchClause
var CQLSearchClause = function (field, fielduri, relation, relationuri,
modifiers, term) {
@@ -37,35 +52,93 @@ var CQLSearchClause = function (field, fielduri, relation, relationuri,
}
CQLSearchClause.prototype = {
- toXCQL: function (n) {
- var s = indent(n) + "\n";
+ toString: function () {
+ var field = this.field;
+ var relation = this.relation;
+ if (field == 'cql.serverChoice' && relation == 'scr') {
+ //avoid redundant field/relation
+ field = null;
+ relation = null;
+ }
+ return (field ? field + ' ' : '') +
+ (relation ? relation : '') +
+ (this.modifiers.length > 0 ? '/' + this.modifiers.join('/') : '') +
+ (relation || this.modifiers.length ? ' ' : '') +
+ '"' + this.term + '"';
+ },
+
+ toXCQL: function (n, c) {
+ var s = indent(n, c) + "\n";
if (this.fielduri.length > 0)
{
- s = s + indent(n+1) + "\n" +
- indent(n+2) + "\n" +
- indent(n+3) + "" + this.fielduri +
+ s = s + indent(n+1, c) + "\n" +
+ indent(n+2, c) + "\n" +
+ indent(n+3, c) + "" + this.fielduri +
"\n" +
- indent(n+2) + "\n" +
- indent(n+1) + "\n";
+ indent(n+2, c) + "\n" +
+ indent(n+1, c) + "\n";
}
- s = s + indent(n+1) + "" + this.field + "\n";
- s = s + indent(n+1) + "\n";
+ s = s + indent(n+1, c) + "" + this.field + "\n";
+ s = s + indent(n+1, c) + "\n";
if (this.relationuri.length > 0) {
- s = s + indent(n+2) +
+ s = s + indent(n+2, c) +
"" + this.relationuri + "\n";
}
- s = s + indent(n+2) + "" + this.relation + "\n";
+ s = s + indent(n+2, c) + "" + this.relation + "\n";
if (this.modifiers.length > 0) {
- s = s + indent(n+2) + "\n";
+ s = s + indent(n+2, c) + "\n";
for (var i = 0; i < this.modifiers.length; i++)
- s = s + this.modifiers[i].toXCQL(n+2);
- s = s + indent(n+2) + "\n";
+ s = s + this.modifiers[i].toXCQL(n+2, c);
+ s = s + indent(n+2, c) + "\n";
}
- s = s + indent(n+1) + "\n";
- s = s + indent(n+1) + "" + this.term + "\n";
- s = s + indent(n) + "\n";
+ s = s + indent(n+1, c) + "\n";
+ s = s + indent(n+1, c) + "" + this.term + "\n";
+ s = s + indent(n, c) + "\n";
return s;
+ },
+
+ toFQ: function () {
+ var s = '{"term": "'+this.term+'"';
+ if (this.field.length > 0 && this.field != 'cql.serverChoice')
+ s+= ', "field": "'+this.field+'"';
+ if (this.relation.length > 0 && this.relation != 'scr')
+ s+= ', "relation": "'+this._mapRelation(this.relation)+'"';
+ for (var i = 0; i < this.modifiers.length; i++) {
+ //since modifiers are mapped to keys, ignore the reserved ones
+ if (this.modifiers[i].name == "term"
+ ||this.modifiers[i].name == "field"
+ ||this.modifiers[i].name == "relation")
+ continue;
+ s += ', ' + this.modifiers[i].toFQ();
+ }
+ s += '}';
+ return s;
+ },
+
+ _mapRelation: function (rel) {
+ switch(rel) {
+ case "<" : return "lt";
+ case ">" : return "gt";
+ case "=" : return "eq";
+ case "<>" : return "ne";
+ case ">=" : return "ge";
+ case "<=" : return "le";
+ default: return rel;
+ }
+ },
+
+ _remapRelation: function (rel) {
+ switch(rel) {
+ case "lt" : return "<";
+ case "gt" : return ">";
+ case "eq" : return "=";
+ case "ne" : return "<>";
+ case "ge" : return ">=";
+ case "le" : return "<=";
+ default: return rel;
+ }
}
+
}
// CQLBoolean
var CQLBoolean = function() {
@@ -76,25 +149,44 @@ var CQLBoolean = function() {
}
CQLBoolean.prototype = {
- toXCQL: function (n) {
- var s = indent(n) + "\n";
- s = s + indent(n+1) + "\n" +
- indent(n+2) + "" + this.op + "\n";
+ toString: function () {
+ return (this.left.op ? '(' + this.left + ')' : this.left) + ' ' +
+ this.op.toUpperCase() +
+ (this.modifiers.length > 0 ? '/' + this.modifiers.join('/') : '') +
+ ' ' + (this.right.op ? '(' + this.right + ')' : this.right);;
+ },
+ toXCQL: function (n, c) {
+ var s = indent(n, c) + "\n";
+ s = s + indent(n+1, c) + "\n" +
+ indent(n+2, c) + "" + this.op + "\n";
if (this.modifiers.length > 0) {
- s = s + indent(n+2) + "\n";
+ s = s + indent(n+2, c) + "\n";
for (var i = 0; i < this.modifiers.length; i++)
- s = s + this.modifiers[i].toXCQL(n+2);
- s = s + indent(n+2) + "\n";
+ s = s + this.modifiers[i].toXCQL(n+2, c);
+ s = s + indent(n+2, c) + "\n";
}
- s = s + indent(n+1) + "\n";
- s = s + indent(n+1) + "\n" +
- this.left.toXCQL(n+2) + indent(n+1) + "\n";
+ s = s + indent(n+1, c) + "\n";
+ s = s + indent(n+1, c) + "\n" +
+ this.left.toXCQL(n+2, c) + indent(n+1, c) + "\n";
- s = s + indent(n+1) + "\n" +
- this.right.toXCQL(n+2) + indent(n+1) + "\n";
- s = s + indent(n) + "\n";
+ s = s + indent(n+1, c) + "\n" +
+ this.right.toXCQL(n+2, c) + indent(n+1, c) + "\n";
+ s = s + indent(n, c) + "\n";
return s;
+ },
+
+ toFQ: function (n, c, nl) {
+ var s = '{"op": "'+this.op+'"';
+ //proximity modifiers
+ for (var i = 0; i < this.modifiers.length; i++)
+ s += ', ' + this.modifiers[i].toFQ();
+ s += ','+nl+indent(n, c)+' "s1": '+this.left.toFQ(n+1, c, nl);
+ s += ','+nl+indent(n, c)+' "s2": '+this.right.toFQ(n+1, c, nl);
+ var fill = n && c ? ' ' : '';
+ s += nl+indent(n-1, c)+fill+'}';
+ return s;
}
+
}
// CQLParser
var CQLParser = function () {
@@ -121,8 +213,73 @@ CQLParser.prototype = {
if (this.look != "")
throw new Error("EOF expected");
},
- toXCQL: function () {
- return this.tree.toXCQL();
+ parseFromFQ: function (query) {
+ if (!query)
+ throw new Error("The query to be parsed cannot be empty");
+ if (typeof query == 'string')
+ query = JSON.parse(query);
+ this.tree = this._parseFromFQ(query);
+ },
+ _parseFromFQ: function (fq) {
+ //op-node
+ if (fq.hasOwnProperty('op')
+ && fq.hasOwnProperty('s1')
+ && fq.hasOwnProperty('s2')) {
+ var node = new CQLBoolean();
+ node.op = fq.op;
+ node.left = this._parseFromFQ(fq.s1);
+ node.right = this._parseFromFQ(fq.s2);
+ //include all other members as modifiers
+ node.modifiers = [];
+ for (var key in fq) {
+ if (key == 'op' || key == 's1' || key == 's2')
+ continue;
+ var mod = new CQLModifier();
+ mod.name = key;
+ mod.relation = '=';
+ mod.value = fq[key];
+ node.modifiers.push(mod);
+ }
+ return node;
+ }
+ //search-clause node
+ if (fq.hasOwnProperty('term')) {
+ var node = new CQLSearchClause();
+ node.term = fq.term;
+ node.field = fq.hasOwnProperty('field')
+ ? fq.field : 'cql.serverChoice';
+ node.relation = fq.hasOwnProperty('relation')
+ ? node._remapRelation(fq.relation) :
+ //HACK: if the field is set, assume '=' rather than scr
+ (fq.hasOwnProperty('field') ? '=' : 'scr');
+ //include all other members as modifiers
+ node.relationuri = '';
+ node.fielduri = '';
+ node.modifiers = [];
+ for (var key in fq) {
+ if (key == 'term' || key == 'field' || key == 'relation')
+ continue;
+ var mod = new CQLModifier();
+ mod.name = key;
+ mod.relation = '=';
+ mod.value = fq[key];
+ node.modifiers.push(mod);
+ }
+ return node;
+ }
+ throw new Error('Unknow node type; '+JSON.stringify(fq));
+ },
+ toXCQL: function (c) {
+ c = typeof c == "undefined" ? ' ' : c;
+ return this.tree.toXCQL(0, c);
+ },
+ toFQ: function (c, nl) {
+ c = typeof c == "undefined" ? ' ' : c;
+ nl = typeof nl == "undefined" ? '\n' : c;
+ return this.tree.toFQ(0, c, nl);
+ },
+ toString: function () {
+ return this.tree.toString();
},
_parseQuery: function(field, relation, modifiers) {
var left = this._parseSearchClause(field, relation, modifiers);