Просмотр исходного кода

Merge pull request #9 from RiveraGroup/feature/mongo_2.6.5_expressions_Variadic

Feature/mongo 2.6.5 expressions variadic
tonyennis 11 лет назад
Родитель
Сommit
c78aa6c1e2

+ 5 - 4
lib/pipeline/expressions/AddExpression.js

@@ -8,17 +8,18 @@
  * @constructor
  * @constructor
  **/
  **/
 var AddExpression = module.exports = function AddExpression(){
 var AddExpression = module.exports = function AddExpression(){
-	if (arguments.length !== 0) throw new Error("zero args expected");
+//	if (arguments.length !== 0) throw new Error("zero args expected");
 	base.call(this);
 	base.call(this);
-}, klass = AddExpression, NaryExpression = require("./NaryExpression"), base = NaryExpression, proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+}, klass = AddExpression, base = require("./VariadicExpressionT")(klass), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
 	Expression = require("./Expression");
 	Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
+klass.opName = "$add";
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$add";
+	return klass.opName
 };
 };
 
 
 /**
 /**
@@ -39,4 +40,4 @@ proto.evaluateInternal = function evaluateInternal(vars) {
 
 
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$add",base.parse(AddExpression));
+Expression.registerExpression(klass.opName,base.parse(klass));

+ 5 - 10
lib/pipeline/expressions/AndExpression.js

@@ -12,15 +12,9 @@
  * @constructor
  * @constructor
  **/
  **/
 var AndExpression = module.exports = function AndExpression() {
 var AndExpression = module.exports = function AndExpression() {
-	if (arguments.length !== 0) throw new Error("zero args expected");
+//	if (arguments.length !== 0) throw new Error("zero args expected");
 	base.call(this);
 	base.call(this);
-}, klass = AndExpression,
-	base = require("./NaryExpression"),
-	proto = klass.prototype = Object.create(base.prototype, {
-		constructor: {
-			value: klass
-		}
-	});
+}, klass = AndExpression, base = require(".VariadicExpressionT")(klass), proto = klass.prototype = Object.create(base.prototype, {constructor: {value: klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
@@ -29,8 +23,9 @@ var Value = require("../Value"),
 	Expression = require("./Expression");
 	Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
+klass.opName = "$and";
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-	return "$and";
+	return klass.opName;
 };
 };
 
 
 /**
 /**
@@ -75,6 +70,6 @@ proto.optimize = function optimize() {
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$and", base.parse(AndExpression));
+Expression.registerExpression(klass.opName, base.parse(klass));
 
 
 //TODO: proto.toMatcherBson
 //TODO: proto.toMatcherBson

+ 8 - 10
lib/pipeline/expressions/ConcatExpression.js

@@ -12,15 +12,16 @@ var Expression = require("./Expression");
 var ConcatExpression = module.exports = function ConcatExpression(){
 var ConcatExpression = module.exports = function ConcatExpression(){
 	if (arguments.length !== 0) throw new Error("zero args expected");
 	if (arguments.length !== 0) throw new Error("zero args expected");
 	base.call(this);
 	base.call(this);
-}, klass = ConcatExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+}, klass = ConcatExpression, base = require("./VariadicExpressionT")(klass), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value");
 var Value = require("../Value");
 var Expression = require("./Expression");
 var Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
+klass.opName = "$concat";
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$concat";
+	return klass.opName;
 };
 };
 
 
 /**
 /**
@@ -28,16 +29,13 @@ proto.getOpName = function getOpName(){
  * @method evaluate
  * @method evaluate
  **/
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
-    var n = this.operands.length;
-
     return this.operands.map(function(x) {
     return this.operands.map(function(x) {
-	var y = x.evaluateInternal(vars);
-	if(typeof(y) !== "string") {
-	    throw new Error("$concat only supports strings - 16702");
-	}
+		var y = x.evaluateInternal(vars);
+		if(typeof(y) !== "string") {
+	    	throw new Error("$concat only supports strings - 16702");
+		}
 	return y;
 	return y;
     }).join("");
     }).join("");
 };
 };
 
 
-
-Expression.registerExpression("$concat", base.parse(ConcatExpression));
+Expression.registerExpression(klass.opName, base.parse(klass));

+ 5 - 4
lib/pipeline/expressions/MultiplyExpression.js

@@ -9,17 +9,18 @@
  * @constructor
  * @constructor
  **/
  **/
 var MultiplyExpression = module.exports = function MultiplyExpression(){
 var MultiplyExpression = module.exports = function MultiplyExpression(){
-	if (arguments.length !== 0) throw new Error("Zero args expected");
+	//if (arguments.length !== 0) throw new Error("Zero args expected");
 	base.call(this);
 	base.call(this);
-}, klass = MultiplyExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+}, klass = MultiplyExpression, base = require("./VariadicExpressionT")(klass), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
  Expression = require("./Expression");
  Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
+klass.opName = "$multiply";
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$multiply";
+	return klass.opName;
 };
 };
 
 
 /**
 /**
@@ -38,4 +39,4 @@ proto.evaluateInternal = function evaluateInternal(vars){
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$multiply", base.parse(MultiplyExpression));
+Expression.registerExpression(klass.opName, base.parse(klass));

+ 5 - 4
lib/pipeline/expressions/OrExpression.js

@@ -9,9 +9,9 @@
  * @constructor
  * @constructor
  **/
  **/
 var OrExpression = module.exports = function OrExpression(){
 var OrExpression = module.exports = function OrExpression(){
-	if (arguments.length !== 0) throw new Error("zero args expected");
+//	if (arguments.length !== 0) throw new Error("zero args expected");
 	base.call(this);
 	base.call(this);
-}, klass = OrExpression, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+}, klass = OrExpression, base = require("./VariadicExpressionT")(klass), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
@@ -20,8 +20,9 @@ var Value = require("../Value"),
 	Expression = require("./Expression");
 	Expression = require("./Expression");
 
 
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
+klass.opName = "$or";
 proto.getOpName = function getOpName(){
 proto.getOpName = function getOpName(){
-	return "$or";
+	return klass.opName;
 };
 };
 
 
 /**
 /**
@@ -64,4 +65,4 @@ proto.optimize = function optimize() {
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$or", base.parse(OrExpression));
+Expression.registerExpression(klass.opName, base.parse(klass));

+ 12 - 17
lib/pipeline/expressions/ToLowerExpression.js

@@ -1,6 +1,6 @@
 "use strict";
 "use strict";
-
-/**
+	
+/** 
  * A $toLower pipeline expression.
  * A $toLower pipeline expression.
  * @see evaluateInternal
  * @see evaluateInternal
  * @class ToLowerExpression
  * @class ToLowerExpression
@@ -8,29 +8,24 @@
  * @module mungedb-aggregate
  * @module mungedb-aggregate
  * @constructor
  * @constructor
  **/
  **/
-var ToLowerExpression = module.exports = function ToLowerExpression() {
-	this.nargs = 1;
+var ToLowerExpression = module.exports = function ToLowerExpression(){
 	base.call(this);
 	base.call(this);
-}, klass = ToLowerExpression,
-	base = require("./NaryExpression"),
-	proto = klass.prototype = Object.create(base.prototype, {
-		constructor: {
-			value: klass
-		}
-	});
+}, klass = ToLowerExpression, base = require("./FixedArityExpressionT")(klass, 1), proto = klass.prototype = Object.create(base.prototype, {constructor: {value: klass}});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
 	Expression = require("./Expression");
 	Expression = require("./Expression");
 
 
+klass.opName = "$toLower";
+
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
-proto.getOpName = function getOpName() {
-	return "$toLower";
+proto.getOpName = function getOpName(){
+	return klass.opName;
 };
 };
 
 
-/**
- * Takes a single string and converts that string to lowercase, returning the result. All uppercase letters become lowercase.
- **/
+/** 
+* Takes a single string and converts that string to lowercase, returning the result. All uppercase letters become lowercase. 
+**/
 proto.evaluateInternal = function evaluateInternal(vars) {
 proto.evaluateInternal = function evaluateInternal(vars) {
 	var val = this.operands[0].evaluateInternal(vars),
 	var val = this.operands[0].evaluateInternal(vars),
 		str = Value.coerceToString(val);
 		str = Value.coerceToString(val);
@@ -38,4 +33,4 @@ proto.evaluateInternal = function evaluateInternal(vars) {
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$toLower", base.parse(ToLowerExpression));
+Expression.registerExpression(klass.opName, base.parse(klass));

+ 5 - 10
lib/pipeline/expressions/ToUpperExpression.js

@@ -9,23 +9,18 @@
  * @constructor
  * @constructor
  **/
  **/
 var ToUpperExpression = module.exports = function ToUpperExpression() {
 var ToUpperExpression = module.exports = function ToUpperExpression() {
-	this.nargs = 1;
 	base.call(this);
 	base.call(this);
-}, klass = ToUpperExpression,
-	base = require("./NaryExpression"),
-	proto = klass.prototype = Object.create(base.prototype, {
-		constructor: {
-			value: klass
-		}
-	});
+}, klass = ToUpperExpression, base = require("./FixedArityExpressionT")(klass, 1), proto = klass.prototype = Object.create(base.prototype, {constructor: {value: klass }});
 
 
 // DEPENDENCIES
 // DEPENDENCIES
 var Value = require("../Value"),
 var Value = require("../Value"),
 	Expression = require("./Expression");
 	Expression = require("./Expression");
 
 
+klass.opName = "$toUpper";
+
 // PROTOTYPE MEMBERS
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 proto.getOpName = function getOpName() {
-	return "$toUpper";
+	return klass.opName;
 };
 };
 
 
 /**
 /**
@@ -38,4 +33,4 @@ proto.evaluateInternal = function evaluateInternal(vars) {
 };
 };
 
 
 /** Register Expression */
 /** Register Expression */
-Expression.registerExpression("$toUpper", base.parse(ToUpperExpression));
+Expression.registerExpression(klass.opName, base.parse(klass));

+ 20 - 0
lib/pipeline/expressions/VariadicExpressionT.js

@@ -0,0 +1,20 @@
+"use strict";
+
+/**
+ * A factory and base class for all expressions that are variadic (AKA they accept any number of arguments)
+ * @class VariadicExpressionT
+ * @namespace mungedb-aggregate.pipeline.expressions
+ * @module mungedb-aggregate
+ * @constructor
+ **/
+
+var VariadicExpressionT = module.exports = function VariadicExpressionT(SubClass) {
+
+	var VariadicExpression = function VariadicExpression() {
+		if (arguments.length !== 0) throw new Error((SubClass.opName || "(unspecified)") + ": zero args expected");
+		base.call(this);
+	}, klass = VariadicExpression, base = require("./NaryExpressionT")(SubClass), proto = klass.prototype = Object.create(base.prototype, {constructor: {value: klass}});
+
+	return VariadicExpression;
+};
+

+ 6 - 1
test/lib/pipeline/expressions/AddExpression.js → test/lib/pipeline/expressions/AddExpression_test.js

@@ -15,8 +15,13 @@ module.exports = {
 				assert.doesNotThrow(function(){
 				assert.doesNotThrow(function(){
 					new AddExpression();
 					new AddExpression();
 				});
 				});
-			}
+			},
 
 
+			"should throw Error when constructing with args": function testConstructor(){
+				assert.throws(function(){
+					new AddExpression(1);
+				});
+			}
 		},
 		},
 
 
 		"#getOpName()": {
 		"#getOpName()": {

+ 6 - 0
test/lib/pipeline/expressions/AndExpression.js → test/lib/pipeline/expressions/AndExpression_test.js

@@ -14,6 +14,12 @@ module.exports = {
 				assert.doesNotThrow(function(){
 				assert.doesNotThrow(function(){
 					new AndExpression();
 					new AndExpression();
 				});
 				});
+			},
+
+			"should throw Error when constructing with args": function testConstructor(){
+				assert.throws(function(){
+					new AndExpression(1);
+				});
 			}
 			}
 
 
 		},
 		},

+ 12 - 2
test/lib/pipeline/expressions/ConcatExpression.js → test/lib/pipeline/expressions/ConcatExpression_test.js

@@ -14,8 +14,12 @@ module.exports = {
 				assert.doesNotThrow(function(){
 				assert.doesNotThrow(function(){
 					new ConcatExpression();
 					new ConcatExpression();
 				});
 				});
+			},
+			"should throw Error when constructing with args": function testConstructor(){
+				assert.throws(function(){
+					new ConcatExpression("should die");
+				});
 			}
 			}
-
 		},
 		},
 
 
 		"#getOpName()": {
 		"#getOpName()": {
@@ -50,8 +54,14 @@ module.exports = {
 
 
 			"should return null if an operand evaluates to null; {$concat:[my,$a]}": function testNull(){
 			"should return null if an operand evaluates to null; {$concat:[my,$a]}": function testNull(){
 				assert.equal(Expression.parseOperand({$concat:["my","$a"]}).evaluate({a:null}), null);
 				assert.equal(Expression.parseOperand({$concat:["my","$a"]}).evaluate({a:null}), null);
-			}
+			},
+
+			"should throw if a non-string is passed in: {$concat:[my,$a]}": function testNull(){
+				assert.throws(function(){
+					Expression.parseOperand({$concat:["my","$a"]}).evaluate({a:100});
+				});
 
 
+			}
 		}
 		}
 
 
 	}
 	}

+ 6 - 0
test/lib/pipeline/expressions/MultiplyExpression.js → test/lib/pipeline/expressions/MultiplyExpression_test.js

@@ -14,6 +14,12 @@ module.exports = {
 				assert.doesNotThrow(function(){
 				assert.doesNotThrow(function(){
 					new MultiplyExpression();
 					new MultiplyExpression();
 				});
 				});
+			},
+
+			"should throw Error when constructing with args": function testConstructor(){
+				assert.throws(function(){
+					new MultiplyExpression(1);
+				});
 			}
 			}
 
 
 		},
 		},

+ 6 - 0
test/lib/pipeline/expressions/OrExpression.js → test/lib/pipeline/expressions/OrExpression_test.js

@@ -14,6 +14,12 @@ module.exports = {
 				assert.doesNotThrow(function(){
 				assert.doesNotThrow(function(){
 					new OrExpression();
 					new OrExpression();
 				});
 				});
+			},
+
+			"should throw Error when constructing with args": function testConstructor(){
+				assert.throws(function(){
+					new OrExpression(1);
+				});
 			}
 			}
 
 
 		},
 		},

+ 7 - 1
test/lib/pipeline/expressions/ToLowerExpression.js → test/lib/pipeline/expressions/ToLowerExpression_test.js

@@ -14,7 +14,13 @@ module.exports = {
 								assert.doesNotThrow(function() {
 								assert.doesNotThrow(function() {
 										new ToLowerExpression();
 										new ToLowerExpression();
 								});
 								});
-						}
+						},
+
+					"should throw Error when constructing with args": function testConstructor(){
+						assert.throws(function(){
+							new ToLowerExpression(1);
+						});
+					}
 
 
 				},
 				},
 
 

+ 7 - 1
test/lib/pipeline/expressions/ToUpperExpression.js → test/lib/pipeline/expressions/ToUpperExpression_test.js

@@ -14,7 +14,13 @@ module.exports = {
 								assert.doesNotThrow(function() {
 								assert.doesNotThrow(function() {
 										new ToUpperExpression();
 										new ToUpperExpression();
 								});
 								});
-						}
+						},
+
+					"should throw Error when constructing with args": function testConstructor(){
+						assert.throws(function(){
+							new ToUpperExpression(1);
+						});
+					}
 
 
 				},
 				},
 
 

+ 36 - 0
test/lib/pipeline/expressions/VariadicExpressionT_test.js

@@ -0,0 +1,36 @@
+"use strict";
+
+var assert = require("assert"),
+	VariadicExpressionT = require("../../../../lib/pipeline/expressions/VariadicExpressionT"),
+	NaryExpressionT = require("../../../../lib/pipeline/expressions/NaryExpressionT");
+
+
+//TODO: refactor these test cases using Expression.parseOperand() or something because these could be a whole lot cleaner...
+module.exports = {
+
+	"VariadicExpression": {
+
+		"constructor()": {
+
+			"should not throw Error when constructing without args": function testConstructor() {
+				assert.doesNotThrow(function () {
+					new VariadicExpressionT({});
+				});
+			},
+
+			"should be an instance of NaryExpression": function () {
+				var VariadicExpressionString = VariadicExpressionT(String);
+				assert.doesNotThrow(function() {
+					var ves = new VariadicExpressionString();
+				});
+				var ves = new VariadicExpressionString();
+				assert(ves.addOperand);
+				assert(ves.validateArguments);
+				//.... and so on. These prove we have a NaryExpression
+			}
+		}
+	}
+};
+
+
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);