FilterBaseDocumentSource.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. "use strict";
  2. /**
  3. * A base class for filter document sources
  4. * @class FilterBaseDocumentSource
  5. * @namespace mungedb-aggregate.pipeline.documentSources
  6. * @module mungedb-aggregate
  7. * @constructor
  8. * @param [ctx] {ExpressionContext}
  9. **/
  10. var FilterBaseDocumentSource = module.exports = function FilterBaseDocumentSource(ctx){
  11. if (arguments.length > 1) throw new Error("up to one arg expected");
  12. base.call(this, ctx);
  13. this.unstarted = true;
  14. this.hasNext = false;
  15. this.current = null;
  16. }, klass = FilterBaseDocumentSource, base = require('./DocumentSource'), proto = klass.prototype = Object.create(base.prototype, {constructor:{value:klass}});
  17. //TODO: Need to implement coalesce()
  18. //TODO: Need to implement optimize()
  19. /**
  20. * Find the next acceptable source document, if there are any left.
  21. * @method findNext
  22. **/
  23. proto.findNext = function findNext() {
  24. /* only do this the first time */
  25. if (this.unstarted) {
  26. this.hasNext = !this.source.eof();
  27. this.unstarted = false;
  28. }
  29. while(this.hasNext) {
  30. var document = this.source.getCurrent();
  31. this.hasNext = this.source.advance();
  32. if (this.accept(document)) {
  33. this.current = document;
  34. return;
  35. }
  36. }
  37. this.current = null;
  38. };
  39. /**
  40. * Is the source at EOF?
  41. * @method eof
  42. **/
  43. proto.eof = function eof() {
  44. if (this.unstarted)
  45. this.findNext();
  46. return (this.current === null);
  47. };
  48. /**
  49. * Advance the state of the DocumentSource so that it will return the next Document.
  50. * The default implementation returns false, after checking for interrupts.
  51. * Derived classes can call the default implementation in their own implementations in order to check for interrupts.
  52. *
  53. * @method advance
  54. * @returns {Boolean} whether there is another document to fetch, i.e., whether or not getCurrent() will succeed. This default implementation always returns false.
  55. **/
  56. proto.advance = function advance() {
  57. base.prototype.advance.call(this); // check for interrupts
  58. if (this.unstarted)
  59. this.findNext();
  60. /**
  61. * This looks weird after the above, but is correct. Note that calling
  62. * getCurrent() when first starting already yields the first document
  63. * in the collection. Calling advance() without using getCurrent()
  64. * first will skip over the first item.
  65. **/
  66. this.findNext();
  67. return (this.current !== null);
  68. };
  69. /**
  70. * some implementations do the equivalent of verify(!eof()) so check eof() first
  71. * @method getCurrent
  72. * @returns {Document} the current Document without advancing
  73. **/
  74. proto.getCurrent = function getCurrent() {
  75. if (this.unstarted)
  76. this.findNext();
  77. if (this.current === null) throw new Error("This should never happen");
  78. return this.current;
  79. };
  80. /**
  81. * Test the given document against the predicate and report if it should be accepted or not.
  82. * @param {object} document the document to test
  83. * @returns {bool} true if the document matches the filter, false otherwise
  84. **/
  85. proto.accept = function accept(document) {
  86. throw new Error("not implemented");
  87. };
  88. /**
  89. * Create a JSONObj suitable for Matcher construction.
  90. *
  91. * This is used after filter analysis has moved as many filters to
  92. * as early a point as possible in the document processing pipeline.
  93. * See db/Matcher.h and the associated wiki documentation for the
  94. * format. This conversion is used to move back to the low-level
  95. * find() Cursor mechanism.
  96. *
  97. * @param builder the builder to write to
  98. **/
  99. proto.toMatcherJson = function toMatcherJson(builder) {
  100. throw new Error("not implemented");
  101. };