ソースを参照

Refs #999. Ported FilterBaseDocumentSource from mongo, need to add test cases, since mongo has none.

http://source.rd.rcg.local/trac/eagle6/changeset/1324/Eagle6_SVN
Spencer Rathbun 12 年 前
コミット
d85c97f2f5
1 ファイル変更120 行追加0 行削除
  1. 120 0
      lib/pipeline/documentsource/FilterBaseDocumentSource.js

+ 120 - 0
lib/pipeline/documentsource/FilterBaseDocumentSource.js

@@ -0,0 +1,120 @@
+var FilterBaseDocumentSource = module.exports = (function(){
+	// CONSTRUCTOR
+	/**
+	 * A base class for filter document sources
+	 * 
+	 * @class FilterBaseDocumentSource
+	 * @namespace munge.pipepline.documentsource
+	 * @module munge
+	 * @constructor
+	 * @param	{ExpressionContext}	
+	**/
+	var klass = module.exports = FilterBaseDocumentSource = function FilterBaseDocumentSource(/*pCtx*/){
+		if(arguments.length !== 0) throw new Error("zero args expected");
+		base.call(this);
+		this.unstarted = true;
+		this.hasNext = false;
+		this.pCurrent = null;
+	}, base = require('./DocumentSource'), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
+
+	/**
+	 * Find the next acceptable source document, if there are any left.
+	 *
+	 * @method findNext
+	**/
+	proto.findNext = function findNext() {
+		/* only do this the first time */
+		if (this.unstarted) {
+			this.hasNext = !this.pSource.eof();
+			this.unstarted = false;
+		}
+
+		while(this.hasNext) {
+			pDocument = this.pSource.getCurrent();
+			this.hasNext = this.pSource.advance();
+
+			if (this.accept(pDocument)) {
+				this.pCurrent = pDocument;
+				return;
+			}
+		}
+
+		this.pCurrent.reset();
+	};
+
+	/**
+	 * Is the source at EOF?
+	 * 
+	 * @method	eof
+	**/
+	proto.eof = function eof() {
+		if (this.unstarted)
+			this.findNext();
+		return (this.pCurrent.get() === null);
+	};
+	
+	/**
+	 * 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
+
+		if (this.unstarted)
+			this.findNext();
+
+		/**
+		* This looks weird after the above, but is correct.  Note that calling
+		* getCurrent() when first starting already yields the first document
+		* in the collection.  Calling advance() without using getCurrent()
+		* first will skip over the first item.
+		**/
+		this.findNext();
+		return (this.pCurrent.get() !== null);
+	};
+	
+	/**
+	 * 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() {
+		if (this.unstarted)
+			this.findNext();
+		if (this.pCurrent.get() === null) throw new Error("This should never happen");
+		return pCurrent;
+	};
+
+	/**
+	* Test the given document against the predicate and report if it
+	* should be accepted or not.
+	*
+	* @param {object} pDocument the document to test
+	* @returns {bool} true if the document matches the filter, false otherwise
+	**/
+	proto.accept = function accept(pDocument) {
+		throw new Error("not implemented");
+	};
+
+	/**
+	* Create a BSONObj suitable for Matcher construction.
+	*
+	* This is used after filter analysis has moved as many filters to
+	* as early a point as possible in the document processing pipeline.
+	* See db/Matcher.h and the associated wiki documentation for the
+	* format.  This conversion is used to move back to the low-level
+	* find() Cursor mechanism.
+	*
+	* @param pBuilder the builder to write to
+	**/
+	proto.toMatcherBson = function toMatcherBson(pBuilder) {
+		throw new Error("not implemented");
+	};
+
+	return klass;
+})();