CondExpression.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. "use strict";
  2. /**
  3. * $cond expression; @see evaluate
  4. * @class CondExpression
  5. * @namespace mungedb-aggregate.pipeline.expressions
  6. * @module mungedb-aggregate
  7. * @constructor
  8. **/
  9. var CondExpression = module.exports = function CondExpression(vars) {
  10. if (arguments.length !== 0) throw new Error("zero args expected");
  11. base.call(this);
  12. }, klass = CondExpression,
  13. base = require("./FixedArityExpression")(klass, 3),
  14. proto = klass.prototype = Object.create(base.prototype, {
  15. constructor: {
  16. value: klass
  17. }
  18. });
  19. // DEPENDENCIES
  20. var Value = require("../Value"),
  21. Expression = require("./Expression");
  22. // PROTOTYPE MEMBERS
  23. klass.opName = "$cond";
  24. proto.getOpName = function getOpName() {
  25. return klass.opName;
  26. };
  27. klass.parse = function parse(expr, vps) {
  28. // There may only be one argument - an array of 3 items, or a hash containing 3 keys.
  29. //this.checkArgLimit(3);
  30. // if not an object, return;
  31. if (typeof(expr) !== Object)
  32. return Expression.parse(expr, vps);
  33. if(!(klass.opName in expr)) {
  34. throw new Error("Invalid expression. Expected to see '"+klass.opName+"'");
  35. }
  36. var ret = new CondExpression();
  37. // If this is an Object and not an array, verify all the bits are specified.
  38. // If this is an Object that is an array, verify there are three bits.
  39. var args = Expression.parseOperand(expr, vps);
  40. // what is args? If it is an array of scalars (array mode) or an array of objects (object mode), we're ok.
  41. // In the latter case, I am very not ok with the assuming if, then, and else are in a known order which is
  42. // what the original code implies. It looks like if we see an 'if' we set this.operands[0]. If we see 'then', we set
  43. // this.operands[1], and if we see 'else' we set operands[2]. Bugcheck on unknown values. Bugcheck on insufficent
  44. // numbers of values, AKA !== 3
  45. if (args[0] !== "if")
  46. throw new Error("Missing 'if' parameter to $cond");
  47. if (args[1] !== "then")
  48. throw new Error("Missing 'then' parameter to $cond");
  49. if (args[2] !== "else")
  50. throw new Error("Missing 'else' parameter to $cond");
  51. return ret;
  52. };
  53. /**
  54. * Use the $cond operator with the following syntax:
  55. * { $cond: { if: <boolean-expression>, then: <true-case>, else: <false-case-> } }
  56. * -or-
  57. * { $cond: [ <boolean-expression>, <true-case>, <false-case> ] }
  58. * @method evaluate
  59. **/
  60. proto.evaluateInternal = function evaluateInternal(vars) {
  61. var pCond1 = this.operands[0].evaluateInternal(vars);
  62. this.idx = 0;
  63. if (pCond1.coerceToBool()) {
  64. this.idx = 1;
  65. } else {
  66. this.idx = 2;
  67. }
  68. return this.operands[this.idx].evaluateInternal(vars);
  69. };
  70. /** Register Expression */
  71. Expression.registerExpression(klass.opName, klass.parse);