blob: c179b382567dc2b65d74a4fce3d3b2a9a8020832 [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
33 $.ajax({
34 type : 'GET',
genia.likes.science@gmail.com5a7c2d72013-06-06 00:54:28 -070035 url : endpoint,
36 data : payload,
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070037 dataType : "json",
genia.likes.science@gmail.com5a7c2d72013-06-06 00:54:28 -070038 success : function(response) {
39 if (response && response["error-code"]) {
40
41 alert("Error [Code" + response["error-code"][0] + "]: " + response["error-code"][1]);
42
43 } else if (response && response["results"]) {
44
45 var fn_callback = myThis._callbacks["sync"];
46 fn_callback(response, myThis._extras);
47
48 } else if (response["handle"]) {
49
50 var fn_callback = myThis._callbacks["async"];
51 fn_callback(response, myThis._extras);
52
53 } else if (response["status"]) {
54
55 var fn_callback = myThis._callbacks["sync"];
56 fn_callback(response, myThis._extras);
57 }
genia.likes.science@gmail.com512454d2013-05-28 03:32:20 -070058 }
59 });
60
61 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070062};
63
64
genia.likes.science@gmail.com5a7c2d72013-06-06 00:54:28 -070065
66
67
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070068AExpression.prototype.val = function() {
69
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070070 var value = "";
71
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070072 // If there is a dataverse defined, provide it.
73 if (this._properties.hasOwnProperty("dataverse")) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070074 value += "use dataverse " + this._properties["dataverse"] + ";\n";
75 };
76
77 if (this._properties.hasOwnProperty("value")) {
78 value += this._properties["value"];
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070079 }
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070080
81 return value;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -070082};
83
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -070084// @param expressionValue [String]
85AExpression.prototype.set = function(expressionValue) {
86 this._properties["value"] = expressionValue;
87 return this;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -070088};
89
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -070090
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -070091AExpression.prototype.error = function(msg) {
92 return "Asterix FunctionExpression Error: " + msg;
93};
94
95
96// FunctionExpression
97// Parent: AsterixExpression
98//
99// @param options [Various],
100// @key function [String], a function to be applid to the expression
101// @key expression [AsterixExpression or AsterixClause] an AsterixExpression/Clause to which the fn will be applied
102function FunctionExpression(options) {
103
104 // Initialize superclass
105 AExpression.call(this);
106
107 // Possible to initialize a function epxression without inputs, or with them
108 this.bind(options);
109
110 // Return object
111 return this;
112}
113
114
115FunctionExpression.prototype = Object.create(AExpression.prototype);
116FunctionExpression.prototype.constructor = FunctionExpression;
117
118
119FunctionExpression.prototype.bind = function(options) {
120
121 AExpression.prototype.bind.call(this, options);
122
123 var options = options || {};
124
125 if (options.hasOwnProperty("function")) {
126 this._properties["function"] = options["function"];
127 }
128
129 if (options.hasOwnProperty("expression")) {
130 this._properties["expression"] = options["expression"];
131 }
132
133 return this;
134};
135
136FunctionExpression.prototype.val = function () {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700137 return this._properties["function"] + "(" + this._properties["expression"].val() + ")";
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700138};
139
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700140
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700141// FLWOGR ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
142// Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700143//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700144// WhereClause ::= "where" Expression
145// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
genia.likes.science@gmail.comb4cb6b32013-05-29 04:30:38 -0700146//
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700147// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
148// LimitClause ::= "limit" Expression ( "offset" Expression )?
149// DistinctClause ::= "distinct" "by" Expression ( "," Expression )*
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700150
151
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700152// FLWOGRExpression
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700153//
154// FLWOGRExpression ::= ( ForClause | LetClause ) ( Clause )* "return" Expression
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700155function FLWOGRExpression (options) {
156 // Initialize superclass
157 AExpression.call(this);
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700158
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700159 this._properties["clauses"] = [];
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700160 this._properties["minSize"] = 0;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700161
162 // Bind options and return
163 this.bind(options);
164 return this;
genia.likes.science@gmail.com90d08722013-05-28 04:40:12 -0700165}
166
167
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700168FLWOGRExpression.prototype = Object.create(AExpression.prototype);
169FLWOGRExpression.prototype.constructor = FLWOGRExpression;
170
171
172FLWOGRExpression.prototype.bind = function(options) {
173 AExpression.prototype.bind.call(this, options);
174
175 var options = options || {};
176
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700177 if (options instanceof SetStatement) {
178 this._properties["clauses"].push(options);
179 this._properties["minSize"] += 1;
180 }
181
182 if (this._properties["clauses"].length <= this._properties["minSize"]) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700183 // Needs to start with for or let clause
184 if (options instanceof ForClause || options instanceof LetClause) {
185 this._properties["clauses"].push(options);
186 }
187 } else {
188 if (options instanceof AQLClause) {
189 this._properties["clauses"].push(options);
190 }
191 }
192
193 return this;
194};
195
196
197FLWOGRExpression.prototype.val = function() {
198 var value = AExpression.prototype.val.call(this);
199
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700200 var clauseValues = [];
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700201 for (var c in this._properties["clauses"]) {
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700202 clauseValues.push(this._properties["clauses"][c].val());
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700203 }
204
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700205 return value + clauseValues.join("\n");// + ";";
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700206};
207
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700208
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700209// AQLClause
210//
211// Base Clause ::= ForClause | LetClause | WhereClause | OrderbyClause | GroupClause | LimitClause | DistinctClause
212function AQLClause() {
213 this._properties = {};
214 this._properties["clause"] = "";
215}
216
217AQLClause.prototype.val = function() {
218 var value = this._properties["clause"];
219
220 if (this._properties.hasOwnProperty("return")) {
221 value += " return " + this._properties["return"].val();
222 }
223
224 return value;
225};
226
227AQLClause.prototype.bind = function(options) {
228 var options = options || {};
229
230 if (options.hasOwnProperty("return")) {
231 this._properties["return"] = options["return"];
232 }
233
234 return this;
235};
236
genia.likes.science@gmail.com39578302013-05-31 04:42:26 -0700237AQLClause.prototype.set = function(value) {
238 this._properties["clause"] = value;
239 return this;
240};
241
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700242
243// ForClause
244//
245// Grammar:
246// "for" Variable ( "at" Variable )? "in" ( Expression )
247//
248// @param for_variable [String], REQUIRED, first variable in clause
249// @param at_variable [String], NOT REQUIRED, first variable in clause
250// @param expression [AsterixExpression], REQUIRED, expression to evaluate
251//
252// TODO Error Checking
253function ForClause(for_variable, at_variable, expression) {
254 AQLClause.call(this);
255
256 // at_variable is optional, check if defined
257 var at = typeof at_variable ? at_variable : null;
258
259 // Prepare clause
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700260 this._properties["clause"] = "for " + for_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700261 if (at != null) {
genia.likes.science@gmail.com2c678ea2013-06-05 19:49:24 -0700262 this._properties["clause"] += " at " + at_variable;
genia.likes.science@gmail.com73dcc702013-05-28 04:21:28 -0700263 }
264 this._properties["clause"] += " in " + expression.val();
265 return this;
266}
267
268ForClause.prototype = Object.create(AQLClause.prototype);
269ForClause.prototype.constructor = ForClause;
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700270
271
272// LetClause
273//
274// Grammar:
275// LetClause ::= "let" Variable ":=" Expression
276//
277// @param let_variable [String]
278// @param expression [AExpression]
279//
280// TODO Vigorous error checking
281function LetClause(let_variable, expression) {
282 AQLClause.call(this);
283
284 this._properties["clause"] = "let $" + let_variable + " := ";
285 this._properties["clause"] += expression.val();
286
287 return this;
288}
289
290LetClause.prototype = Object.create(AQLClause.prototype);
291LetClause.prototype.constructor = LetClause;
292
293
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700294// ReturnClause
295//
296// Grammar:
297// return [AQLExpression]
298function ReturnClause(expression) {
299 AQLClause.call(this);
300
301 this._properties["clause"] = "return ";
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700302 if (expression instanceof AExpression || expression instanceof AQLClause) {
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700303 this._properties["clause"] += expression.val();
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700304 } else if ( Object.getPrototypeOf( expression ) === Object.prototype ) {
305
306 this._properties["clause"] += "{";
307 var returnStatements = [];
308 for (returnValue in expression) {
309
310 if (expression[returnValue] instanceof AExpression) {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700311 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue].val());
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700312 } else if (typeof expression[returnValue] == "string") {
genia.likes.science@gmail.comfba7cc82013-05-31 04:04:08 -0700313 returnStatements.push('"' + returnValue + '" ' + " : " + expression[returnValue]);
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700314 }
315 }
316 this._properties["clause"] += returnStatements.join(",\n");
317 this._properties["clause"] += "}";
318
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700319 } else {
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700320 this._properties["clause"] += new AExpression().set(expression).val();
genia.likes.science@gmail.com5ca104c2013-05-29 05:39:26 -0700321 }
322
323 return this;
324}
325
326ReturnClause.prototype = Object.create(AQLClause.prototype);
327ReturnClause.prototype.constructor = ReturnClause;
328
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700329ReturnClause.prototype.val = function () {
330 return this._properties["clause"];
331};
332
333
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700334// WhereClause
335//
336// Grammar:
337// ::= "where" Expression
338//
339// @param expression [BooleanExpression], pushes this expression onto the stack
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700340function WhereClause(expression) {
341 AQLClause.call(this);
342
343 this._properties["stack"] = [];
344
345 this.bind(expression);
346
347 return this;
348}
349
350
351WhereClause.prototype = Object.create(AQLClause.prototype);
352WhereClause.prototype.constructor = WhereClause;
353
354
355WhereClause.prototype.bind = function(expression) {
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700356 if (expression instanceof AExpression) {
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700357 this._properties["stack"].push(expression);
358 }
359};
360
361
362WhereClause.prototype.val = function() {
363 var value = "where ";
364
365 var count = this._properties["stack"].length - 1;
366 while (count >= 0) {
367 value += this._properties["stack"][count].val() + " ";
368 count -= 1;
369 }
370
371 return value;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700372};
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700373
374
genia.likes.science@gmail.com2ba32242013-05-31 03:10:48 -0700375// LimitClause
376// Grammar:
377// LimitClause ::= "limit" Expression ( "offset" Expression )?
378//
379// @param limitExpression [REQUIRED, AQLExpression]
380// @param offsetExpression [OPTIONAL, AQLExpression]
381function LimitClause(limitExpression, offsetExpression) {
382
383 AQLClause.call(this);
384
385 // limitExpression required
386 this._properties["clause"] = "limit " + limitExpression.val();
387
388 // Optional: Offset
389 var offset = typeof offsetExpression ? offsetExpression : null;
390 if (offset != null) {
391 this._properties["clause"] += " offset " + offsetExpression.val();
392 }
393
394 return this;
395}
396
397LimitClause.prototype = Object.create(AQLClause.prototype);
398LimitClause.prototype.constructor = LimitClause;
399
400
401// OrderbyClause
402//
403// Grammar:
404// OrderbyClause ::= "order" "by" Expression ( ( "asc" ) | ( "desc" ) )? ( "," Expression ( ( "asc" ) | ( "desc" ) )? )*
405//
406// @params AQLExpressions and asc/desc strings, in any quantity. At least one required.
407function OrderbyClause() {
408
409 AQLClause.call(this);
410
411 // At least one argument expression is required, and first should be expression
412 if (arguments.length == 0 || !(arguments[0] instanceof AExpression)) {
413 // TODO Not sure which error to throw for an empty OrderBy but this should fail.
414 alert("Order By Error");
415 this._properties["clause"] = null;
416 return this;
417 }
418
419 var expc = 0;
420 var expressions = [];
421
422 while (expc < arguments.length) {
423
424 var expression = "";
425
426 if (arguments[expc] instanceof AExpression) {
427 expression += arguments[expc].val();
428 }
429
430 var next = expc + 1;
431 if (next < arguments.length && (arguments[next] == "asc" || arguments[next] == "desc")) {
432 expc++;
433 expression += " " + arguments[expc];
434 }
435
436 expressions.push(expression);
437
438 expc++;
439 }
440
441 this._properties["clause"] = "order by " + expressions.join(", ");
442 return this;
443}
444
445OrderbyClause.prototype = Object.create(AQLClause.prototype);
446OrderbyClause.prototype.constructor = OrderbyClause;
447
448
genia.likes.science@gmail.com6e392912013-05-31 03:46:59 -0700449// GroupClause
450//
451// Grammar:
452// GroupClause ::= "group" "by" ( Variable ":=" )? Expression ( "," ( Variable ":=" )? Expression )* ( "decor" Variable ":=" Expression ( "," "decor" Variable ":=" Expression )* )? "with" VariableRef ( "," VariableRef )*
453function GroupClause() {
454 AQLClause.call(this);
455
456 if (arguments.length == 0) {
457 // TODO Not sure which error to throw for an empty GroupBy but this should fail.
458 alert("Group Error");
459 this._properties["clause"] = null;
460 return this;
461 }
462
463 var expc = 0;
464 var expressions = [];
465 var variableRefs = [];
466 var isDecor = false;
467
468 while (expc < arguments.length) {
469
470 if (arguments[expc] instanceof AExpression) {
471
472 isDecor = false;
473 expressions.push(arguments[expc].val());
474
475 } else if (typeof arguments[expc] == "string") {
476
477 // Special keywords, decor & with
478 if (arguments[expc] == "decor") {
479 isDecor = true;
480 } else if (arguments[expc] == "with") {
481 isDecor = false;
482 expc++;
483 while (expc < arguments.length) {
484 variableRefs.push("$" + arguments[expc]);
485 expc++;
486 }
487
488 // Variables and variable refs
489 } else {
490
491 var nextc = expc + 1;
492 var expression = "";
493
494 if (isDecor) {
495 expression += "decor ";
496 isDecor = false;
497 }
498
499 expression += "$" + arguments[expc] + " := " + arguments[nextc].val();
500 expressions.push(expression);
501 expc++;
502 }
503 }
504
505 expc++;
506 }
507
508 this._properties["clause"] = "group by " + expressions.join(", ") + " with " + variableRefs.join(", ");
509 return this;
510}
511
512GroupClause.prototype = Object.create(AQLClause.prototype);
513GroupClause.prototype.constructor = GroupClause;
514
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700515// BooleanExpression
516//
517// TODO
518function BooleanExpression(expression) {
519 this.value = expression;
genia.likes.science@gmail.com6fd7b2e2013-05-31 00:40:28 -0700520 alert("Debugging Bool: " + arguments.length + " " + expression);
genia.likes.science@gmail.com38612632013-05-28 13:11:52 -0700521}
522
523BooleanExpression.prototype.val = function() {
524 return this.value;
525}
genia.likes.science@gmail.com79e603a2013-05-31 10:03:23 -0700526
527
528// SetStatement
529//
530// Grammar
531// "set" Identifier StringLiteral
532function SetStatement (identifier, stringLiteral) {
533 AExpression.call(this);
534
535 var statement = "set " + identifier + ' "' + stringLiteral + '";';
536
537 AExpression.prototype.set.call(this, statement);
538
539 return this;
540}
541
542SetStatement.prototype = Object.create(AExpression.prototype);
543SetStatement.prototype.constructor = SetStatement;
genia.likes.science@gmail.come34c57b2013-05-31 10:15:49 -0700544
545
546// Quantified Expression
547//
548// Grammar
549// QuantifiedExpression ::= ( ( "some" ) | ( "every" ) ) Variable "in" Expression ( "," Variable "in" Expression )* "satisfies" Expression
550//
551// @param String some/every
552// @param [AExpression]
553// @param [Aexpression] satisfiesExpression
554function QuantifiedExpression (keyword, expressions, satisfiesExpression) {
555 AExpression.call(this);
556
557 var expression = keyword + " ";
558 var varsInExpressions = [];
559
560 for (var varInExpression in expressions) {
561 varsInExpressions.push(varInExpression + " in " + expressions[varInExpression].val());
562 }
563 expression += varsInExpressions.join(", ") + " satisfies " + satisfiesExpression.val();
564
565 AExpression.prototype.set.call(this, expression);
566
567 return this;
568}
569
570QuantifiedExpression.prototype = Object.create(AExpression.prototype);
571QuantifiedExpression.prototype.constructor = QuantifiedExpression;
genia.likes.science@gmail.com64ca88e2013-05-31 10:40:39 -0700572
573QuantifiedExpression.prototype.val = function() {
574 var value = AExpression.prototype.val.call(this);
575 return "(" + value + ")";
576};
genia.likes.science@gmail.com44ff94a2013-05-31 11:09:34 -0700577
578
579// Functions that can be used to call core expressions/clauses more cleanly
580function AFLWOGR () {
581
582}
583
584function AClause () {
585
586}
587
588function ALetClause () {
589
590}
591
592function AWhereClause () {
593
594}
595
596function AOrderbyClause () {
597
598}
599
600function AGroupClause () {
601
602}
603
604function ALimitClause () {
605
606}
607
608function ADistinctClause () {
609
610}
611
612function AVariable () {
613
614}