Browse Source

Refs #1006. Ported limit and tests. A few of the tests need to be fleshed out before this is done

http://source.rd.rcg.local/trac/eagle6/changeset/1331/Eagle6_SVN
Spencer Rathbun 12 years ago
parent
commit
6cade93f5d

+ 118 - 0
lib/pipeline/documentSources/LimitDocumentSource.js

@@ -0,0 +1,118 @@
+var LimitDocumentSource = module.exports = (function(){
+	// CONSTRUCTOR
+	/**
+	 * A document source limiter
+	 * 
+	 * @class LimitDocumentSource
+	 * @namespace munge.pipepline.documentsource
+	 * @module munge
+	 * @constructor
+	 * @param {Object} query the match query to use
+	**/
+	var klass = module.exports = LimitDocumentSource = function LimitDocumentSource(/* pCtx*/){
+		if(arguments.length !== 0) throw new Error("zero args expected");
+		base.call(this);
+		this.limit = 0;
+		this.count = 0;
+	}, base = require('./DocumentSource'), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+
+	proto.getSourceName = function getSourceName(){
+		return "$limit";
+	};
+	
+	proto.getFactory = function getFactory(){
+		return klass;	// using the ctor rather than a separate .create() method
+	};
+
+	klass.GetDepsReturn = {
+        SEE_NEXT:"SEE_NEXT", // Add the next Source's deps to the set
+	};
+
+	/**
+	 * Coalesce limits together
+	 *
+	 * @param {Object} nextSource the next source
+	 * @return {bool} return whether we can coalese together
+	**/
+	proto.coalesce = function coalesce(nextSource) {
+		nextLimit =	nextSource.get();
+
+		/* if it's not another $skip, we can't coalesce */
+		if (!nextLimit)
+			return false;
+		/* we need to limit by the minimum of the two limits */
+		if (nextLimit.limit < this.limit)
+			this.limit = nextLimit.limit;
+		return true;
+	};
+
+    /**
+     * Is the source at EOF?
+     * 
+     * @method	eof
+    **/
+    proto.eof = function eof() {
+		return this.pSource.eof() || this.count >= this.limit;
+    };
+
+    /**
+     * some implementations do the equivalent of verify(!eof()) so check eof() first
+     * 
+     * @method	getCurrent
+     * @returns	{Document}	the current Document without advancing
+    **/
+    proto.getCurrent = function getCurrent() {
+		return this.pSource.getCurrent();
+    };
+
+	/**
+	 * Advance the state of the DocumentSource so that it will return the next Document.  
+	 * The default implementation returns false, after checking for interrupts. 
+	 * Derived classes can call the default implementation in their own implementations in order to check for interrupts.
+	 * 
+	 * @method	advance
+	 * @returns	{Boolean}	whether there is another document to fetch, i.e., whether or not getCurrent() will succeed.  This default implementation always returns false.
+	**/
+	proto.advance = function advance() {
+		base.prototype.advance.call(this); // check for interrupts
+		++this.count;
+		if (this.count >= this.limit) {
+			return false;
+		}
+		this.pCurrent = this.pSource.getCurrent();
+		return this.pSource.advance();
+
+	};
+
+	/**
+	 * Create an object that represents the document source.  The object
+	 * will have a single field whose name is the source's name.  This
+	 * will be used by the default implementation of addToJsonArray()
+	 * to add this object to a pipeline being represented in JSON.
+	 * 
+	 * @method	sourceToJson
+	 * @param	{Object} builder	JSONObjBuilder: a blank object builder to write to
+	 * @param	{Boolean}	explain	create explain output
+	**/
+	proto.sourceToJson = function sourceToJson(builder, explain) {
+		builder.$limit = this.limit;
+	};
+
+	/**
+	 * Creates a new LimitDocumentSource with the input number as the limit
+	 *
+	 * @param {Number} JsonElement this thing is *called* Json, but it expects a number
+	**/
+	proto.createFromJson = function createFromJson(JsonElement) {
+		//if (!(JsonElement instanceof Number)) throw new Error("code 15957; the limit must be specified as a number");
+
+		var nextLimit = proto.getFactory();
+
+		nextLimit.limit = JsonElement;
+		if ((nextLimit.limit <= 0) || isNaN(nextLimit.limit)) throw new Error("code 15958; the limit must be positive");
+
+		return nextLimit;
+	};
+
+	return klass;
+})();

+ 105 - 0
test/lib/pipeline/documentSources/LimitDocumentSource.js

@@ -0,0 +1,105 @@
+var assert = require("assert"),
+	LimitDocumentSource = require("../../../../lib/pipeline/documentSources/LimitDocumentSource");
+
+module.exports = {
+
+	"LimitDocumentSource": {
+
+		"constructor()": {
+
+			"should not throw Error when constructing without args": function testConstructor(){
+				assert.doesNotThrow(function(){
+					new LimitDocumentSource();
+				});
+			}
+
+		},
+
+		"#getSourceName()": {
+
+			"should return the correct source name; $limit": function testSourceName(){
+				var lds = new LimitDocumentSource();
+				assert.strictEqual(lds.getSourceName(), "$limit");
+			}
+
+		},
+
+		"#getFactory()": {
+
+			"should return the constructor for this class": function factoryIsConstructor(){
+				assert.strictEqual(new LimitDocumentSource().getFactory(), LimitDocumentSource);
+			}
+
+		},
+
+		/*
+		"#coalesce()": {
+
+			"should return false if nextSource is not $skip": function dontSkip(){
+			},
+			"should return true if nextSource is $skip": function changeLimit(){
+			}
+
+		},
+
+		"#eof()": {
+
+			"should return true if there are no more sources": function noSources(){
+			},
+			"should return true if limit is hit": function hitLimit(){
+			}
+
+		},
+
+		"#getCurrent()": {
+
+			"should return the current document source": function currSource(){
+				var lds = new LimitDocumentSource();
+				lds.limit = 1;
+				lds.pSource = { item:1 };
+				assert.strictEqual(lds.getCurrent(), { item:1 }); 
+			}
+
+		},
+
+		"#advance()": {
+
+			"should return true for moving to the next source": function nextSource(){
+			},
+
+			"should return false for no sources remaining": function noMoar(){
+			}
+
+		},
+		*/
+
+		"#sourceToJson()": {
+
+			"should create an object with a key $limit and the value equal to the limit": function sourceToJsonTest(){
+				var lds = new LimitDocumentSource();
+				lds.limit = 9;
+				var t = {};
+				lds.sourceToJson(t, false);
+				assert.deepEqual(t, { "$limit": 9 });
+			}
+
+		},
+
+		"#createFromJson()": {
+
+			"should return a new LimitDocumentSource object from an input number": function createTest(){
+				var lds = new LimitDocumentSource();
+				var t = lds.createFromJson(5);
+				assert.strictEqual(t, LimitDocumentSource);
+				assert.strictEqual(t.limit, 5);
+			}
+
+		}
+
+
+	}
+
+};
+
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
+