blob: f0a75280ec74a1f2ae7f377b6af53ebc466b9cc3 [file] [log] [blame]
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -07001// Temporary AsterixExpression Placeholder
2function AExpression () {
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -07003 this._properties = {};
4 this._success = function() {};
5
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -07006 return this;
7}
8
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -07009
10AExpression.prototype.bind = function(options) {
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070011 var options = options || {};
12
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070013 if (options.hasOwnProperty("dataverse")) {
14 this._properties["dataverse"] = options["dataverse"];
15 }
16
17 if (options.hasOwnProperty("success")) {
18 this._success = options["success"];
19 }
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -070020
21 if (options.hasOwnProperty("return")) {
22 this._properties["return"] = " return " + options["return"].val();
23 }
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070024};
25
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070026
genia.likes.science@gmail.com5a7c2d72013-06-06 00:54:28 -070027AExpression.prototype.run = function(endpoint, payload, callbacks, extras) {
28
29 this._extras = extras;
30 this._callbacks = callbacks;
31 myThis = this;
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070032
genia.likes.science@gmail.com1d825142013-06-06 08:01:31 -070033 $.getJSON( endpoint, payload, function (response) {
34 //alert("DEBUG: Run Response: " + JSON.stringify(response));
35
36 if (response && response["error-code"]) {
37
38 alert("Error [Code" + response["error-code"][0] + "]: " + response["error-code"][1]);
39
40 } else if (response && response["results"]) {
41
42 var fn_callback = myThis._callbacks["sync"];
43 fn_callback(response, myThis._extras);
44
45 } else if (response["handle"]) {
46
47 var fn_callback = myThis._callbacks["async"];
48 fn_callback(response, myThis._extras);
49
50 } else if (response["status"]) {
51
52 var fn_callback = myThis._callbacks["sync"];
53 fn_callback(response, myThis._extras);
54 }
55 })
56 .error(function() {
57 alert("error");
58 });
59
60 /*$.ajax({
61 "type" : 'GET',
62 "url" : endpoint,
63 "data" : payload,
64 "dataType" : "json",
65 "success" : function(response) {
66
67 alert("DEBUG: Run Response: " + JSON.stringify(response));
68
genia.likes.science@gmail.com5a7c2d72013-06-06 00:54:28 -070069 if (response && response["error-code"]) {
70
71 alert("Error [Code" + response["error-code"][0] + "]: " + response["error-code"][1]);
72
73 } else if (response && response["results"]) {
74
75 var fn_callback = myThis._callbacks["sync"];
76 fn_callback(response, myThis._extras);
77
78 } else if (response["handle"]) {
79
80 var fn_callback = myThis._callbacks["async"];
81 fn_callback(response, myThis._extras);
82
83 } else if (response["status"]) {
84
85 var fn_callback = myThis._callbacks["sync"];
86 fn_callback(response, myThis._extras);
87 }
genia.likes.science@gmail.com1d825142013-06-06 08:01:31 -070088 },
89 "error": function (xhr, ajaxOptions, thrownError) {
90 alert("AJAX ERROR " + thrownError);
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070091 }
genia.likes.science@gmail.com1d825142013-06-06 08:01:31 -070092 });*/
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070093
94 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070095};
96
97
98AExpression.prototype.val = function() {
99
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700100 var value = "";
101
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700102 // If there is a dataverse defined, provide it.
103 if (this._properties.hasOwnProperty("dataverse")) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700104 value += "use dataverse " + this._properties["dataverse"] + ";\n";
105 };
106
107 if (this._properties.hasOwnProperty("value")) {
108 value += this._properties["value"];
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700109 }
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700110
111 return value;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700112};
113
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700114// @param expressionValue [String]
115AExpression.prototype.set = function(expressionValue) {
116 this._properties["value"] = expressionValue;
117 return this;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700118};
119
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700120
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700121AExpression.prototype.error = function(msg) {
122 return "Asterix FunctionExpression Error: " + msg;
123};
124
125
126// FunctionExpression
127// Parent: AsterixExpression
128//
129// @param options [Various],
130// @key function [String], a function to be applid to the expression
131// @key expression [AsterixExpression or AsterixClause] an AsterixExpression/Clause to which the fn will be applied
132function FunctionExpression(options) {
133
134 // Initialize superclass
135 AExpression.call(this);
136
137 // Possible to initialize a function epxression without inputs, or with them
138 this.bind(options);
139
140 // Return object
141 return this;
142}
143
144
145FunctionExpression.prototype = Object.create(AExpression.prototype);
146FunctionExpression.prototype.constructor = FunctionExpression;
147
148
149FunctionExpression.prototype.bind = function(options) {
150
151 AExpression.prototype.bind.call(this, options);
152
153 var options = options || {};
154
155 if (options.hasOwnProperty("function")) {
156 this._properties["function"] = options["function"];
157 }
158
159 if (options.hasOwnProperty("expression")) {
160 this._properties["expression"] = options["expression"];
161 }
162
163 return this;
164};
165
166FunctionExpression.prototype.val = function () {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700167 return this._properties["function"] + "(" + this._properties["expression"].val() + ")";
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700168};
169
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700170
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700171// FLWOGR ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
172// Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700173//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700174// WhereClause ::= "where" Expression
175// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
genia.likes.science@gmail.comb4cb6b32013-05-29 04:30:38 -0700176//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700177// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
178// LimitClause ::= "limit" Expression ( "offset" Expression )?
179// DistinctClause ::= "distinct" "by" Expression ( "," Expression )*
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700180
181
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700182// FLWOGRExpression
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700183//
184// FLWOGRExpression ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700185function FLWOGRExpression (options) {
186 // Initialize superclass
187 AExpression.call(this);
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700188
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700189 this._properties["clauses"] = [];
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700190 this._properties["minSize"] = 0;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700191
192 // Bind options and return
193 this.bind(options);
194 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700195}
196
197
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700198FLWOGRExpression.prototype = Object.create(AExpression.prototype);
199FLWOGRExpression.prototype.constructor = FLWOGRExpression;
200
201
202FLWOGRExpression.prototype.bind = function(options) {
203 AExpression.prototype.bind.call(this, options);
204
205 var options = options || {};
206
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700207 if (options instanceof SetStatement) {
208 this._properties["clauses"].push(options);
209 this._properties["minSize"] += 1;
210 }
211
212 if (this._properties["clauses"].length <= this._properties["minSize"]) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700213 // Needs to start with for or let clause
214 if (options instanceof ForClause || options instanceof LetClause) {
215 this._properties["clauses"].push(options);
216 }
217 } else {
218 if (options instanceof AQLClause) {
219 this._properties["clauses"].push(options);
220 }
221 }
222
223 return this;
224};
225
226
227FLWOGRExpression.prototype.val = function() {
228 var value = AExpression.prototype.val.call(this);
229
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700230 var clauseValues = [];
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700231 for (var c in this._properties["clauses"]) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700232 clauseValues.push(this._properties["clauses"][c].val());
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700233 }
234
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700235 return value + clauseValues.join("\n");// + ";";
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700236};
237
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700238
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700239// AQLClause
240//
241// Base Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
242function AQLClause() {
243 this._properties = {};
244 this._properties["clause"] = "";
245}
246
247AQLClause.prototype.val = function() {
248 var value = this._properties["clause"];
249
250 if (this._properties.hasOwnProperty("return")) {
251 value += " return " + this._properties["return"].val();
252 }
253
254 return value;
255};
256
257AQLClause.prototype.bind = function(options) {
258 var options = options || {};
259
260 if (options.hasOwnProperty("return")) {
261 this._properties["return"] = options["return"];
262 }
263
264 return this;
265};
266
genia.likes.science@gmail.com39578302013-05-31 04:42:26 -0700267AQLClause.prototype.set = function(value) {
268 this._properties["clause"] = value;
269 return this;
270};
271
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700272
273// ForClause
274//
275// Grammar:
276// "for" Variable ( "at" Variable )? "in" ( Expression )
277//
278// @param for_variable [String], REQUIRED, first variable in clause
279// @param at_variable [String], NOT REQUIRED, first variable in clause
280// @param expression [AsterixExpression], REQUIRED, expression to evaluate
281//
282// TODO Error Checking
283function ForClause(for_variable, at_variable, expression) {
284 AQLClause.call(this);
285
286 // at_variable is optional, check if defined
287 var at = typeof at_variable ? at_variable : null;
288
289 // Prepare clause
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700290 this._properties["clause"] = "for " + for_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700291 if (at != null) {
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700292 this._properties["clause"] += " at " + at_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700293 }
294 this._properties["clause"] += " in " + expression.val();
295 return this;
296}
297
298ForClause.prototype = Object.create(AQLClause.prototype);
299ForClause.prototype.constructor = ForClause;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700300
301
302// LetClause
303//
304// Grammar:
305// LetClause ::= "let" Variable ":=" Expression
306//
307// @param let_variable [String]
308// @param expression [AExpression]
309//
310// TODO Vigorous error checking
311function LetClause(let_variable, expression) {
312 AQLClause.call(this);
313
314 this._properties["clause"] = "let $" + let_variable + " := ";
315 this._properties["clause"] += expression.val();
316
317 return this;
318}
319
320LetClause.prototype = Object.create(AQLClause.prototype);
321LetClause.prototype.constructor = LetClause;
322
323
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700324// ReturnClause
325//
326// Grammar:
327// return [AQLExpression]
328function ReturnClause(expression) {
329 AQLClause.call(this);
330
331 this._properties["clause"] = "return ";
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700332 if (expression instanceof AExpression || expression instanceof AQLClause) {
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700333 this._properties["clause"] += expression.val();
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700334 } else if ( Object.getPrototypeOf( expression ) === Object.prototype ) {
335
336 this._properties["clause"] += "{";
337 var returnStatements = [];
338 for (returnValue in expression) {
339
340 if (expression[returnValue] instanceof AExpression) {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700341 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue].val());
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700342 } else if (typeof expression[returnValue] == "string") {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700343 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue]);
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700344 }
345 }
346 this._properties["clause"] += returnStatements.join(",\n");
347 this._properties["clause"] += "}";
348
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700349 } else {
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700350 this._properties["clause"] += new AExpression().set(expression).val();
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700351 }
352
353 return this;
354}
355
356ReturnClause.prototype = Object.create(AQLClause.prototype);
357ReturnClause.prototype.constructor = ReturnClause;
358
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700359ReturnClause.prototype.val = function () {
360 return this._properties["clause"];
361};
362
363
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700364// WhereClause
365//
366// Grammar:
367// ::= "where" Expression
368//
369// @param expression [BooleanExpression], pushes this expression onto the stack
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700370function WhereClause(expression) {
371 AQLClause.call(this);
372
373 this._properties["stack"] = [];
374
375 this.bind(expression);
376
377 return this;
378}
379
380
381WhereClause.prototype = Object.create(AQLClause.prototype);
382WhereClause.prototype.constructor = WhereClause;
383
384
385WhereClause.prototype.bind = function(expression) {
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700386 if (expression instanceof AExpression) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700387 this._properties["stack"].push(expression);
388 }
389};
390
391
392WhereClause.prototype.val = function() {
393 var value = "where ";
394
395 var count = this._properties["stack"].length - 1;
396 while (count >= 0) {
397 value += this._properties["stack"][count].val() + " ";
398 count -= 1;
399 }
400
401 return value;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700402};
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700403
404
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700405// LimitClause
406// Grammar:
407// LimitClause ::= "limit" Expression ( "offset" Expression )?
408//
409// @param limitExpression [REQUIRED, AQLExpression]
410// @param offsetExpression [OPTIONAL, AQLExpression]
411function LimitClause(limitExpression, offsetExpression) {
412
413 AQLClause.call(this);
414
415 // limitExpression required
416 this._properties["clause"] = "limit " + limitExpression.val();
417
418 // Optional: Offset
419 var offset = typeof offsetExpression ? offsetExpression : null;
420 if (offset != null) {
421 this._properties["clause"] += " offset " + offsetExpression.val();
422 }
423
424 return this;
425}
426
427LimitClause.prototype = Object.create(AQLClause.prototype);
428LimitClause.prototype.constructor = LimitClause;
429
430
431// OrderbyClause
432//
433// Grammar:
434// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
435//
436// @params AQLExpressions and asc/desc strings, in any quantity. At least one required.
437function OrderbyClause() {
438
439 AQLClause.call(this);
440
441 // At least one argument expression is required, and first should be expression
442 if (arguments.length == 0 || !(arguments[0] instanceof AExpression)) {
443 // TODO Not sure which error to throw for an empty OrderBy but this should fail.
444 alert("Order By Error");
445 this._properties["clause"] = null;
446 return this;
447 }
448
449 var expc = 0;
450 var expressions = [];
451
452 while (expc < arguments.length) {
453
454 var expression = "";
455
456 if (arguments[expc] instanceof AExpression) {
457 expression += arguments[expc].val();
458 }
459
460 var next = expc + 1;
461 if (next < arguments.length && (arguments[next] == "asc" || arguments[next] == "desc")) {
462 expc++;
463 expression += " " + arguments[expc];
464 }
465
466 expressions.push(expression);
467
468 expc++;
469 }
470
471 this._properties["clause"] = "order by " + expressions.join(", ");
472 return this;
473}
474
475OrderbyClause.prototype = Object.create(AQLClause.prototype);
476OrderbyClause.prototype.constructor = OrderbyClause;
477
478
genia.likes.science@gmail.com6e392912013-05-31 03:46:59 -0700479// GroupClause
480//
481// Grammar:
482// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
483function GroupClause() {
484 AQLClause.call(this);
485
486 if (arguments.length == 0) {
487 // TODO Not sure which error to throw for an empty GroupBy but this should fail.
488 alert("Group Error");
489 this._properties["clause"] = null;
490 return this;
491 }
492
493 var expc = 0;
494 var expressions = [];
495 var variableRefs = [];
496 var isDecor = false;
497
498 while (expc < arguments.length) {
499
500 if (arguments[expc] instanceof AExpression) {
501
502 isDecor = false;
503 expressions.push(arguments[expc].val());
504
505 } else if (typeof arguments[expc] == "string") {
506
507 // Special keywords, decor & with
508 if (arguments[expc] == "decor") {
509 isDecor = true;
510 } else if (arguments[expc] == "with") {
511 isDecor = false;
512 expc++;
513 while (expc < arguments.length) {
514 variableRefs.push("$" + arguments[expc]);
515 expc++;
516 }
517
518 // Variables and variable refs
519 } else {
520
521 var nextc = expc + 1;
522 var expression = "";
523
524 if (isDecor) {
525 expression += "decor ";
526 isDecor = false;
527 }
528
529 expression += "$" + arguments[expc] + " := " + arguments[nextc].val();
530 expressions.push(expression);
531 expc++;
532 }
533 }
534
535 expc++;
536 }
537
538 this._properties["clause"] = "group by " + expressions.join(", ") + " with " + variableRefs.join(", ");
539 return this;
540}
541
542GroupClause.prototype = Object.create(AQLClause.prototype);
543GroupClause.prototype.constructor = GroupClause;
544
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700545// BooleanExpression
546//
547// TODO
548function BooleanExpression(expression) {
549 this.value = expression;
genia.likes.science@gmail.com6fd7b2e2013-05-31 00:40:28 -0700550 alert("Debugging Bool: " + arguments.length + " " + expression);
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700551}
552
553BooleanExpression.prototype.val = function() {
554 return this.value;
555}
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700556
557
558// SetStatement
559//
560// Grammar
561// "set" Identifier StringLiteral
562function SetStatement (identifier, stringLiteral) {
563 AExpression.call(this);
564
565 var statement = "set " + identifier + ' "' + stringLiteral + '";';
566
567 AExpression.prototype.set.call(this, statement);
568
569 return this;
570}
571
572SetStatement.prototype = Object.create(AExpression.prototype);
573SetStatement.prototype.constructor = SetStatement;
genia.likes.science@gmail.come34c57b2013-05-31 10:15:49 -0700574
575
576// Quantified Expression
577//
578// Grammar
579// QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression ( "," Variable "in" Expression )* "satisfies" Expression
580//
581// @param String some/every
582// @param [AExpression]
583// @param [Aexpression] satisfiesExpression
584function QuantifiedExpression (keyword, expressions, satisfiesExpression) {
585 AExpression.call(this);
586
587 var expression = keyword + " ";
588 var varsInExpressions = [];
589
590 for (var varInExpression in expressions) {
591 varsInExpressions.push(varInExpression + " in " + expressions[varInExpression].val());
592 }
593 expression += varsInExpressions.join(", ") + " satisfies " + satisfiesExpression.val();
594
595 AExpression.prototype.set.call(this, expression);
596
597 return this;
598}
599
600QuantifiedExpression.prototype = Object.create(AExpression.prototype);
601QuantifiedExpression.prototype.constructor = QuantifiedExpression;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700602
603QuantifiedExpression.prototype.val = function() {
604 var value = AExpression.prototype.val.call(this);
605 return "(" + value + ")";
606};
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700607
608
609// Functions that can be used to call core expressions/clauses more cleanly
610function AFLWOGR () {
611
612}
613
614function AClause () {
615
616}
617
618function ALetClause () {
619
620}
621
622function AWhereClause () {
623
624}
625
626function AOrderbyClause () {
627
628}
629
630function AGroupClause () {
631
632}
633
634function ALimitClause () {
635
636}
637
638function ADistinctClause () {
639
640}
641
642function AVariable () {
643
644}