@Override
    public final void visit(Integer cell1Key, Integer cell1Val) {
      // Is it all or not.
      if (query.filterCells[0]) {

        // IS it exact or not
        if (null != matchingCell0) {
          if (query.notValCells[0]) {
            // Exact val match
            if (matchingCell0.intValue() == cell1Key.intValue()) return;
          } else {
            // Not Exact val
            if (matchingCell0.intValue() != cell1Key.intValue()) return;
          }
        } else {
          // Either range or IN
          if (query.inValCells[0]) {
            // IN
            boolean isMatched = false;
            // LOOKING FOR ONE MATCHING
            for (Object obj : query.inValuesAO[0]) {
              Integer objI = (Integer) obj;
              isMatched = cell1Key.intValue() == objI.intValue();

              // ONE MATCHED, NO NEED TO PROCESS
              if (query.notValCells[0]) {
                if (!isMatched) break;
              } else {
                if (isMatched) break;
              }
            }
            if (!isMatched) return; // NONE MATCHED

          } else {
            // RANGE
            boolean isMatched =
                cell1Key.intValue() < cellMin0.intValue()
                    || cell1Key.intValue() > cellMax0.intValue();
            if (query.notValCells[0]) {
              // Not Exact Range
              if (!isMatched) return;
            } else {
              // Exact Range
              if (isMatched) return;
            }
          }
        }
      }

      if (null != plugin) {
        switch (this.mode) {
          case MODE_COLS:
            tablePartsCallback.onRowCols(cell1Key, cell1Val);
            break;
          case MODE_KEY:
            tablePartsCallback.onRowKey(cell1Key);
            break;
        }
      }
    }
  private void iterate(byte[] input, HSearchQuery query, IHSearchPlugin pluginI, int mode)
      throws IOException, NumberFormatException {

    MapperKVBase plugin = castPlugin(pluginI);
    MapperKVBase.TablePartsCallback callback = plugin.getPart();

    Cell2FilterVisitor cell2Visitor = new Cell2FilterVisitor(query, pluginI, callback, mode);

    query.parseValuesConcurrent(new String[] {"Integer", "Integer"});

    cell2Visitor.matchingCell0 = (query.filterCells[0]) ? (Integer) query.exactValCellsO[0] : null;
    Integer matchingCell1 = (query.filterCells[1]) ? (Integer) query.exactValCellsO[1] : null;

    cell2Visitor.cellMin0 =
        (query.minValCells[0] == HSearchQuery.DOUBLE_MIN_VALUE)
            ? null
            : new Double(query.minValCells[0]).intValue();
    Integer cellMin1 =
        (query.minValCells[1] == HSearchQuery.DOUBLE_MIN_VALUE)
            ? null
            : new Double(query.minValCells[1]).intValue();

    cell2Visitor.cellMax0 =
        (query.maxValCells[0] == HSearchQuery.DOUBLE_MAX_VALUE)
            ? null
            : new Double(query.maxValCells[0]).intValue();
    Integer cellMax1 =
        (query.maxValCells[1] == HSearchQuery.DOUBLE_MAX_VALUE)
            ? null
            : new Double(query.maxValCells[1]).intValue();

    cell2Visitor.inValues0 = (query.inValCells[0]) ? (Integer[]) query.inValuesAO[0] : null;
    Integer[] inValues1 = (query.inValCells[1]) ? (Integer[]) query.inValuesAO[1] : null;

    this.table.data = new BytesSection(input);
    if (query.filterCells[1]) {
      if (query.notValCells[1]) this.table.processNot(matchingCell1, cell2Visitor);
      else if (query.inValCells[1]) this.table.processIn(inValues1, cell2Visitor);
      else this.table.process(matchingCell1, cellMin1, cellMax1, cell2Visitor);
    } else {
      this.table.process(cell2Visitor);
    }

    if (null != callback) {
      callback.onReadComplete();
    }
    if (null != plugin) {
      plugin.onReadComplete();
    }
  }