blob: 078c37c9686c1850cd2f9dda00c245f74eccc409 [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 }
genia.likes.science@gmail.com1d825142013-06-06 08:01:31 -070055 });
56
57 /*$.ajax({
58 "type" : 'GET',
59 "url" : endpoint,
60 "data" : payload,
61 "dataType" : "json",
62 "success" : function(response) {
63
64 alert("DEBUG: Run Response: " + JSON.stringify(response));
65
genia.likes.science@gmail.com5a7c2d72013-06-06 00:54:28 -070066 if (response && response["error-code"]) {
67
68 alert("Error [Code" + response["error-code"][0] + "]: " + response["error-code"][1]);
69
70 } else if (response && response["results"]) {
71
72 var fn_callback = myThis._callbacks["sync"];
73 fn_callback(response, myThis._extras);
74
75 } else if (response["handle"]) {
76
77 var fn_callback = myThis._callbacks["async"];
78 fn_callback(response, myThis._extras);
79
80 } else if (response["status"]) {
81
82 var fn_callback = myThis._callbacks["sync"];
83 fn_callback(response, myThis._extras);
84 }
genia.likes.science@gmail.com1d825142013-06-06 08:01:31 -070085 },
86 "error": function (xhr, ajaxOptions, thrownError) {
87 alert("AJAX ERROR " + thrownError);
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070088 }
genia.likes.science@gmail.com1d825142013-06-06 08:01:31 -070089 });*/
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070090
91 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070092};
93
94
95AExpression.prototype.val = function() {
96
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070097 var value = "";
98
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070099 // If there is a dataverse defined, provide it.
100 if (this._properties.hasOwnProperty("dataverse")) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700101 value += "use dataverse " + this._properties["dataverse"] + ";\n";
102 };
103
104 if (this._properties.hasOwnProperty("value")) {
105 value += this._properties["value"];
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700106 }
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700107
108 return value;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700109};
110
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700111// @param expressionValue [String]
112AExpression.prototype.set = function(expressionValue) {
113 this._properties["value"] = expressionValue;
114 return this;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700115};
116
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700117
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700118AExpression.prototype.error = function(msg) {
119 return "Asterix FunctionExpression Error: " + msg;
120};
121
122
123// FunctionExpression
124// Parent: AsterixExpression
125//
126// @param options [Various],
127// @key function [String], a function to be applid to the expression
128// @key expression [AsterixExpression or AsterixClause] an AsterixExpression/Clause to which the fn will be applied
129function FunctionExpression(options) {
130
131 // Initialize superclass
132 AExpression.call(this);
133
134 // Possible to initialize a function epxression without inputs, or with them
135 this.bind(options);
136
137 // Return object
138 return this;
139}
140
141
142FunctionExpression.prototype = Object.create(AExpression.prototype);
143FunctionExpression.prototype.constructor = FunctionExpression;
144
145
146FunctionExpression.prototype.bind = function(options) {
147
148 AExpression.prototype.bind.call(this, options);
149
150 var options = options || {};
151
152 if (options.hasOwnProperty("function")) {
153 this._properties["function"] = options["function"];
154 }
155
156 if (options.hasOwnProperty("expression")) {
157 this._properties["expression"] = options["expression"];
158 }
159
160 return this;
161};
162
163FunctionExpression.prototype.val = function () {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700164 return this._properties["function"] + "(" + this._properties["expression"].val() + ")";
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700165};
166
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700167
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700168// FLWOGR ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
169// Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700170//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700171// WhereClause ::= "where" Expression
172// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
genia.likes.science@gmail.comb4cb6b32013-05-29 04:30:38 -0700173//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700174// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
175// LimitClause ::= "limit" Expression ( "offset" Expression )?
176// DistinctClause ::= "distinct" "by" Expression ( "," Expression )*
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700177
178
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700179// FLWOGRExpression
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700180//
181// FLWOGRExpression ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700182function FLWOGRExpression (options) {
183 // Initialize superclass
184 AExpression.call(this);
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700185
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700186 this._properties["clauses"] = [];
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700187 this._properties["minSize"] = 0;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700188
189 // Bind options and return
190 this.bind(options);
191 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700192}
193
194
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700195FLWOGRExpression.prototype = Object.create(AExpression.prototype);
196FLWOGRExpression.prototype.constructor = FLWOGRExpression;
197
198
199FLWOGRExpression.prototype.bind = function(options) {
200 AExpression.prototype.bind.call(this, options);
201
202 var options = options || {};
203
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700204 if (options instanceof SetStatement) {
205 this._properties["clauses"].push(options);
206 this._properties["minSize"] += 1;
207 }
208
209 if (this._properties["clauses"].length <= this._properties["minSize"]) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700210 // Needs to start with for or let clause
211 if (options instanceof ForClause || options instanceof LetClause) {
212 this._properties["clauses"].push(options);
213 }
214 } else {
215 if (options instanceof AQLClause) {
216 this._properties["clauses"].push(options);
217 }
218 }
219
220 return this;
221};
222
223
224FLWOGRExpression.prototype.val = function() {
225 var value = AExpression.prototype.val.call(this);
226
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700227 var clauseValues = [];
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700228 for (var c in this._properties["clauses"]) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700229 clauseValues.push(this._properties["clauses"][c].val());
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700230 }
231
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700232 return value + clauseValues.join("\n");// + ";";
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700233};
234
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700235
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700236// AQLClause
237//
238// Base Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
239function AQLClause() {
240 this._properties = {};
241 this._properties["clause"] = "";
242}
243
244AQLClause.prototype.val = function() {
245 var value = this._properties["clause"];
246
247 if (this._properties.hasOwnProperty("return")) {
248 value += " return " + this._properties["return"].val();
249 }
250
251 return value;
252};
253
254AQLClause.prototype.bind = function(options) {
255 var options = options || {};
256
257 if (options.hasOwnProperty("return")) {
258 this._properties["return"] = options["return"];
259 }
260
261 return this;
262};
263
genia.likes.science@gmail.com39578302013-05-31 04:42:26 -0700264AQLClause.prototype.set = function(value) {
265 this._properties["clause"] = value;
266 return this;
267};
268
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700269
270// ForClause
271//
272// Grammar:
273// "for" Variable ( "at" Variable )? "in" ( Expression )
274//
275// @param for_variable [String], REQUIRED, first variable in clause
276// @param at_variable [String], NOT REQUIRED, first variable in clause
277// @param expression [AsterixExpression], REQUIRED, expression to evaluate
278//
279// TODO Error Checking
280function ForClause(for_variable, at_variable, expression) {
281 AQLClause.call(this);
282
283 // at_variable is optional, check if defined
284 var at = typeof at_variable ? at_variable : null;
285
286 // Prepare clause
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700287 this._properties["clause"] = "for " + for_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700288 if (at != null) {
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700289 this._properties["clause"] += " at " + at_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700290 }
291 this._properties["clause"] += " in " + expression.val();
292 return this;
293}
294
295ForClause.prototype = Object.create(AQLClause.prototype);
296ForClause.prototype.constructor = ForClause;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700297
298
299// LetClause
300//
301// Grammar:
302// LetClause ::= "let" Variable ":=" Expression
303//
304// @param let_variable [String]
305// @param expression [AExpression]
306//
307// TODO Vigorous error checking
308function LetClause(let_variable, expression) {
309 AQLClause.call(this);
310
311 this._properties["clause"] = "let $" + let_variable + " := ";
312 this._properties["clause"] += expression.val();
313
314 return this;
315}
316
317LetClause.prototype = Object.create(AQLClause.prototype);
318LetClause.prototype.constructor = LetClause;
319
320
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700321// ReturnClause
322//
323// Grammar:
324// return [AQLExpression]
325function ReturnClause(expression) {
326 AQLClause.call(this);
327
328 this._properties["clause"] = "return ";
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700329 if (expression instanceof AExpression || expression instanceof AQLClause) {
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700330 this._properties["clause"] += expression.val();
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700331 } else if ( Object.getPrototypeOf( expression ) === Object.prototype ) {
332
333 this._properties["clause"] += "{";
334 var returnStatements = [];
335 for (returnValue in expression) {
336
337 if (expression[returnValue] instanceof AExpression) {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700338 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue].val());
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700339 } else if (typeof expression[returnValue] == "string") {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700340 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue]);
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700341 }
342 }
343 this._properties["clause"] += returnStatements.join(",\n");
344 this._properties["clause"] += "}";
345
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700346 } else {
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700347 this._properties["clause"] += new AExpression().set(expression).val();
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700348 }
349
350 return this;
351}
352
353ReturnClause.prototype = Object.create(AQLClause.prototype);
354ReturnClause.prototype.constructor = ReturnClause;
355
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700356ReturnClause.prototype.val = function () {
357 return this._properties["clause"];
358};
359
360
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700361// WhereClause
362//
363// Grammar:
364// ::= "where" Expression
365//
366// @param expression [BooleanExpression], pushes this expression onto the stack
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700367function WhereClause(expression) {
368 AQLClause.call(this);
369
370 this._properties["stack"] = [];
371
372 this.bind(expression);
373
374 return this;
375}
376
377
378WhereClause.prototype = Object.create(AQLClause.prototype);
379WhereClause.prototype.constructor = WhereClause;
380
381
382WhereClause.prototype.bind = function(expression) {
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700383 if (expression instanceof AExpression) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700384 this._properties["stack"].push(expression);
385 }
386};
387
388
389WhereClause.prototype.val = function() {
390 var value = "where ";
391
392 var count = this._properties["stack"].length - 1;
393 while (count >= 0) {
394 value += this._properties["stack"][count].val() + " ";
395 count -= 1;
396 }
397
398 return value;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700399};
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700400
401
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700402// LimitClause
403// Grammar:
404// LimitClause ::= "limit" Expression ( "offset" Expression )?
405//
406// @param limitExpression [REQUIRED, AQLExpression]
407// @param offsetExpression [OPTIONAL, AQLExpression]
408function LimitClause(limitExpression, offsetExpression) {
409
410 AQLClause.call(this);
411
412 // limitExpression required
413 this._properties["clause"] = "limit " + limitExpression.val();
414
415 // Optional: Offset
416 var offset = typeof offsetExpression ? offsetExpression : null;
417 if (offset != null) {
418 this._properties["clause"] += " offset " + offsetExpression.val();
419 }
420
421 return this;
422}
423
424LimitClause.prototype = Object.create(AQLClause.prototype);
425LimitClause.prototype.constructor = LimitClause;
426
427
428// OrderbyClause
429//
430// Grammar:
431// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
432//
433// @params AQLExpressions and asc/desc strings, in any quantity. At least one required.
434function OrderbyClause() {
435
436 AQLClause.call(this);
437
438 // At least one argument expression is required, and first should be expression
439 if (arguments.length == 0 || !(arguments[0] instanceof AExpression)) {
440 // TODO Not sure which error to throw for an empty OrderBy but this should fail.
441 alert("Order By Error");
442 this._properties["clause"] = null;
443 return this;
444 }
445
446 var expc = 0;
447 var expressions = [];
448
449 while (expc < arguments.length) {
450
451 var expression = "";
452
453 if (arguments[expc] instanceof AExpression) {
454 expression += arguments[expc].val();
455 }
456
457 var next = expc + 1;
458 if (next < arguments.length && (arguments[next] == "asc" || arguments[next] == "desc")) {
459 expc++;
460 expression += " " + arguments[expc];
461 }
462
463 expressions.push(expression);
464
465 expc++;
466 }
467
468 this._properties["clause"] = "order by " + expressions.join(", ");
469 return this;
470}
471
472OrderbyClause.prototype = Object.create(AQLClause.prototype);
473OrderbyClause.prototype.constructor = OrderbyClause;
474
475
genia.likes.science@gmail.com6e392912013-05-31 03:46:59 -0700476// GroupClause
477//
478// Grammar:
479// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
480function GroupClause() {
481 AQLClause.call(this);
482
483 if (arguments.length == 0) {
484 // TODO Not sure which error to throw for an empty GroupBy but this should fail.
485 alert("Group Error");
486 this._properties["clause"] = null;
487 return this;
488 }
489
490 var expc = 0;
491 var expressions = [];
492 var variableRefs = [];
493 var isDecor = false;
494
495 while (expc < arguments.length) {
496
497 if (arguments[expc] instanceof AExpression) {
498
499 isDecor = false;
500 expressions.push(arguments[expc].val());
501
502 } else if (typeof arguments[expc] == "string") {
503
504 // Special keywords, decor & with
505 if (arguments[expc] == "decor") {
506 isDecor = true;
507 } else if (arguments[expc] == "with") {
508 isDecor = false;
509 expc++;
510 while (expc < arguments.length) {
511 variableRefs.push("$" + arguments[expc]);
512 expc++;
513 }
514
515 // Variables and variable refs
516 } else {
517
518 var nextc = expc + 1;
519 var expression = "";
520
521 if (isDecor) {
522 expression += "decor ";
523 isDecor = false;
524 }
525
526 expression += "$" + arguments[expc] + " := " + arguments[nextc].val();
527 expressions.push(expression);
528 expc++;
529 }
530 }
531
532 expc++;
533 }
534
535 this._properties["clause"] = "group by " + expressions.join(", ") + " with " + variableRefs.join(", ");
536 return this;
537}
538
539GroupClause.prototype = Object.create(AQLClause.prototype);
540GroupClause.prototype.constructor = GroupClause;
541
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700542// BooleanExpression
543//
544// TODO
545function BooleanExpression(expression) {
546 this.value = expression;
genia.likes.science@gmail.com6fd7b2e2013-05-31 00:40:28 -0700547 alert("Debugging Bool: " + arguments.length + " " + expression);
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700548}
549
550BooleanExpression.prototype.val = function() {
551 return this.value;
552}
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700553
554
555// SetStatement
556//
557// Grammar
558// "set" Identifier StringLiteral
559function SetStatement (identifier, stringLiteral) {
560 AExpression.call(this);
561
562 var statement = "set " + identifier + ' "' + stringLiteral + '";';
563
564 AExpression.prototype.set.call(this, statement);
565
566 return this;
567}
568
569SetStatement.prototype = Object.create(AExpression.prototype);
570SetStatement.prototype.constructor = SetStatement;
genia.likes.science@gmail.come34c57b2013-05-31 10:15:49 -0700571
572
573// Quantified Expression
574//
575// Grammar
576// QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression ( "," Variable "in" Expression )* "satisfies" Expression
577//
578// @param String some/every
579// @param [AExpression]
580// @param [Aexpression] satisfiesExpression
581function QuantifiedExpression (keyword, expressions, satisfiesExpression) {
582 AExpression.call(this);
583
584 var expression = keyword + " ";
585 var varsInExpressions = [];
586
587 for (var varInExpression in expressions) {
588 varsInExpressions.push(varInExpression + " in " + expressions[varInExpression].val());
589 }
590 expression += varsInExpressions.join(", ") + " satisfies " + satisfiesExpression.val();
591
592 AExpression.prototype.set.call(this, expression);
593
594 return this;
595}
596
597QuantifiedExpression.prototype = Object.create(AExpression.prototype);
598QuantifiedExpression.prototype.constructor = QuantifiedExpression;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700599
600QuantifiedExpression.prototype.val = function() {
601 var value = AExpression.prototype.val.call(this);
602 return "(" + value + ")";
603};
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700604
605
606// Functions that can be used to call core expressions/clauses more cleanly
607function AFLWOGR () {
608
609}
610
611function AClause () {
612
613}
614
615function ALetClause () {
616
617}
618
619function AWhereClause () {
620
621}
622
623function AOrderbyClause () {
624
625}
626
627function AGroupClause () {
628
629}
630
631function ALimitClause () {
632
633}
634
635function ADistinctClause () {
636
637}
638
639function AVariable () {
640
641}