internal Cell nextCell;//see getLeafDocs

            /// <remarks>This is the primary algorithm; recursive.  Returns null if finds none.</remarks>
            /// <exception cref="System.IO.IOException"></exception>
            internal SmallDocSet Visit(Cell cell, Bits acceptContains)
            {
                if (termsEnum == null)
                {
                    //signals all done
                    return(null);
                }

                ContainsPrefixTreeFilter outerInstance = (ContainsPrefixTreeFilter)base.outerInstance;

                //Leaf docs match all query shape
                SmallDocSet leafDocs = GetLeafDocs(cell, acceptContains);
                // Get the AND of all child results (into combinedSubResults)
                SmallDocSet combinedSubResults = null;
                //   Optimization: use null subCellsFilter when we know cell is within the query shape.
                IShape subCellsFilter = outerInstance.queryShape;

                if (cell.Level != 0 && ((cell.ShapeRel == SpatialRelation.NOT_SET || cell.ShapeRel == SpatialRelation.WITHIN)))
                {
                    subCellsFilter = null;
                    Debug.Assert(cell.Shape.Relate(outerInstance.queryShape) == SpatialRelation.WITHIN);
                }
                ICollection <Cell> subCells = cell.GetSubCells(subCellsFilter);

                foreach (Cell subCell in subCells)
                {
                    if (!SeekExact(subCell))
                    {
                        combinedSubResults = null;
                    }
                    else if (subCell.Level == outerInstance.detailLevel)
                    {
                        combinedSubResults = GetDocs(subCell, acceptContains);
                    }
                    else if (!outerInstance.multiOverlappingIndexedShapes &&
                             subCell.ShapeRel == SpatialRelation.WITHIN)
                    {
                        combinedSubResults = GetLeafDocs(subCell, acceptContains); //recursion
                    }
                    else
                    {
                        combinedSubResults = Visit(subCell, acceptContains);
                    }

                    if (combinedSubResults == null)
                    {
                        break;
                    }

                    acceptContains = combinedSubResults;//has the 'AND' effect on next iteration
                }

                // Result: OR the leaf docs with AND of all child results
                if (combinedSubResults != null)
                {
                    if (leafDocs == null)
                    {
                        return(combinedSubResults);
                    }
                    return(leafDocs.Union(combinedSubResults));//union is 'or'
                }
                return(leafDocs);
            }
 public ContainsVisitor(ContainsPrefixTreeFilter outerInstance, AtomicReaderContext context, Bits acceptDocs)
     : base(outerInstance, context, acceptDocs)
 {
 }
 /// <exception cref="System.IO.IOException"></exception>
 public ContainsVisitor(ContainsPrefixTreeFilter _enclosing, AtomicReaderContext context
     , IBits acceptDocs)
     : base(_enclosing, context, acceptDocs)
 {
     this._enclosing = _enclosing;
 }
 /// <exception cref="System.IO.IOException"></exception>
 public ContainsVisitor(ContainsPrefixTreeFilter _enclosing, AtomicReaderContext context
                        , IBits acceptDocs)
     : base(_enclosing, context, acceptDocs)
 {
     this._enclosing = _enclosing;
 }
 /// <summary>NOTE: modifies and returns either "this" or "other"</summary>
 public virtual ContainsPrefixTreeFilter.SmallDocSet Union(ContainsPrefixTreeFilter.SmallDocSet
     other)
 {
     ContainsPrefixTreeFilter.SmallDocSet bigger;
     ContainsPrefixTreeFilter.SmallDocSet smaller;
     if (other.intSet.Size > this.intSet.Size)
     {
         bigger = other;
         smaller = this;
     }
     else
     {
         bigger = this;
         smaller = other;
     }
     //modify bigger
     foreach (int v in smaller.intSet.keys)
     {
         if (v == smaller.intSet.emptyVal)
         {
             continue;
         }
         bigger.Set(v);
     }
     return bigger;
 }