Prechádzať zdrojové kódy

Refs #1661: Added `$ifNull` expression to `munge` and hacked in a partial conversion of `Aggregator#getGraph()` to `munge` so I can use it in building relationships in the NGS report

http://source.rd.rcg.local/trac/eagle6/changeset/1414/Eagle6_SVN
Kyle Davis 12 rokov pred
rodič
commit
1edb84e6ed

+ 1 - 0
lib/pipeline/expressions/Expression.js

@@ -151,6 +151,7 @@ var Expression = module.exports = (function(){
 					new OpDesc("$gte", CompareExpression.bind(null, Expression.CmpOp.GTE), OpDesc.FIXED_COUNT, 2),
 					new OpDesc("$hour", require("./HourExpression"), OpDesc.FIXED_COUNT, 1),
 					new OpDesc("$ifNull", require("./IfNullExpression"), OpDesc.FIXED_COUNT, 2),
+					new OpDesc("$indexOf", require("./IndexOfExpression"), OpDesc.FIXED_COUNT, 2),
 					new OpDesc("$lt", CompareExpression.bind(null, Expression.CmpOp.LT), OpDesc.FIXED_COUNT, 2),
 					new OpDesc("$lte", CompareExpression.bind(null, Expression.CmpOp.LTE), OpDesc.FIXED_COUNT, 2),
 					new OpDesc("$minute", require("./MinuteExpression"), OpDesc.FIXED_COUNT, 1),

+ 4 - 4
lib/pipeline/expressions/IfNullExpression.js

@@ -1,9 +1,9 @@
 var IfNullExpression = module.exports = (function(){
 	// CONSTRUCTOR
-	/** 
-	 * An $ifNull pipeline expression. 
+	/**
+	 * An $ifNull pipeline expression.
 	 *
-	 * @see evaluate 
+	 * @see evaluate
 	 * @class IfNullExpression
 	 * @namespace munge.pipeline.expressions
 	 * @module munge
@@ -25,7 +25,7 @@ var IfNullExpression = module.exports = (function(){
 	};
 
 	/**
-	* Use the $ifNull operator with the following syntax: { $ifNull: [ <expression>, <replacement-if-null> ] } 
+	* Use the $ifNull operator with the following syntax: { $ifNull: [ <expression>, <replacement-if-null> ] }
 	**/
 	proto.evaluate = function evaluate(doc){
 		this.checkArgCount(2);

+ 42 - 0
lib/pipeline/expressions/IndexOfExpression.js

@@ -0,0 +1,42 @@
+var IndexOfExpression = module.exports = (function(){
+	// CONSTRUCTOR
+	/**
+	 * An $indexOf pipeline expression.
+	 *
+	 * @see evaluate
+	 * @class IndexOfExpression
+	 * @namespace munge.pipeline.expressions
+	 * @module munge
+	 * @constructor
+	**/
+	var klass = function IndexOfExpression(){
+		if(arguments.length !== 0) throw new Error("zero args expected");
+		base.call(this);
+	}, base = require("./NaryExpression"), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+
+	// PROTOTYPE MEMBERS
+	proto.getOpName = function getOpName(){
+		return "$indexOf";
+	};
+
+	proto.addOperand = function addOperand(expr) {
+		this.checkArgLimit(2);
+		base.prototype.addOperand.call(this, expr);
+	};
+
+	/**
+	* Use the $indexOf operator with the following syntax: { $indexOf: [ <needle>, <haystack> ] }
+	* @method evaluate
+	**/
+	proto.evaluate = function evaluate(doc){
+		this.checkArgCount(2);
+		var left = this.operands[0].evaluate(doc);
+		if (left === undefined) return undefined;
+		var right = this.operands[1].evaluate(doc);
+		if (right === undefined) return undefined;
+		if (!(right instanceof Array)) throw new Error("UserAssertion: expected the 2nd arg of the $indexOf expression to be an Array but got " + (typeof right === "object" ? right.constructor.name : typeof right));
+		return right.indexOf(left);
+	};
+
+	return klass;
+})();

+ 68 - 0
test/lib/pipeline/expressions/IndexOfExpression.js

@@ -0,0 +1,68 @@
+var assert = require("assert"),
+	IndexOfExpression = require("../../../../lib/pipeline/expressions/IndexOfExpression"),
+	Expression = require("../../../../lib/pipeline/expressions/Expression");
+
+module.exports = {
+
+	"IndexOfExpression": {
+
+		"constructor()": {
+
+			"should not throw Error when constructing without args": function testConstructor(){
+				assert.doesNotThrow(function(){
+					new IndexOfExpression();
+				});
+			}
+
+		},
+
+		"#getOpName()": {
+
+			"should return the correct op name; $indexOf": function testOpName(){
+				assert.equal(new IndexOfExpression().getOpName(), "$indexOf");
+			}
+
+		},
+
+		"#getFactory()": {
+
+			"should return the constructor for this class": function factoryIsConstructor(){
+				assert.strictEqual(new IndexOfExpression().getFactory(), undefined);
+			}
+
+		},
+
+		"#evaluate()": {
+
+			"should return the index of the first match if found": function testFound(){
+				assert.strictEqual(Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({needle:1, haystack:[1,2,3]}), 0);
+				assert.strictEqual(Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({needle:3, haystack:[1,2,3]}), 2);
+			},
+
+			"should return `-1` if not found": function testNotFound(){
+				assert.strictEqual(Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({needle:0, haystack:[1,2,3]}), -1);
+			},
+
+			"should return `undefined` if the 1st arg (the `needle`) is undefined or missing": function testNeedleUndefinedOrMissing(){
+				assert.strictEqual(Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({needle:undefined, haystack:[1,2,3]}), undefined);
+				assert.strictEqual(Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({haystack:[1,2,3]}), undefined);
+			},
+
+			"should return `undefined` if the 1st arg (the `haystack`) is undefined or missing": function testHaystackUndefinedOrMissing(){
+				assert.strictEqual(Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({needle:0, haystack:undefined}), undefined);
+				assert.strictEqual(Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({needle:0}), undefined);
+			},
+
+			"should throw if 2nd arg (the `haystack`) is not an `Array`": function testHaystackNonArray(){
+				assert.throws(function(){
+					Expression.parseOperand({$indexOf:["$needle", "$haystack"]}).evaluate({needle:0, haystack:0});
+				});
+			}
+
+		}
+
+	}
+
+};
+
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);