package org.apache.poi.ss.formula;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.util.CellReference;
final class FormulaUsedBlankCellSet {
public static final class BookSheetKey {
private final int _bookIndex;
private final int _sheetIndex;
public BookSheetKey(int bookIndex, int sheetIndex) {
_bookIndex = bookIndex;
_sheetIndex = sheetIndex;
}
@Override
public int hashCode() {
return _bookIndex * 17 + _sheetIndex;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof BookSheetKey)) {
return false;
}
BookSheetKey other = (BookSheetKey) obj;
return _bookIndex == other._bookIndex && _sheetIndex == other._sheetIndex;
}
}
private static final class BlankCellSheetGroup {
private final List<BlankCellRectangleGroup> _rectangleGroups;
private int _currentRowIndex;
private int _firstColumnIndex;
private int _lastColumnIndex;
private BlankCellRectangleGroup _currentRectangleGroup;
private int _lastDefinedRow;
public BlankCellSheetGroup(int lastDefinedRow) {
_rectangleGroups = new ArrayList<>();
_currentRowIndex = -1;
_lastDefinedRow = lastDefinedRow;
}
public void addCell(int rowIndex, int columnIndex) {
if (rowIndex > _lastDefinedRow) return;
if (_currentRowIndex == -1) {
_currentRowIndex = rowIndex;
_firstColumnIndex = columnIndex;
_lastColumnIndex = columnIndex;
} else {
if (_currentRowIndex == rowIndex && _lastColumnIndex+1 == columnIndex) {
_lastColumnIndex = columnIndex;
} else {
if (_currentRectangleGroup == null) {
_currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
} else {
if (!_currentRectangleGroup.acceptRow(_currentRowIndex, _firstColumnIndex, _lastColumnIndex)) {
_rectangleGroups.add(_currentRectangleGroup);
_currentRectangleGroup = new BlankCellRectangleGroup(_currentRowIndex, _firstColumnIndex, _lastColumnIndex);
}
}
_currentRowIndex = rowIndex;
_firstColumnIndex = columnIndex;
_lastColumnIndex = columnIndex;
}
}
}
public boolean containsCell(int rowIndex, int columnIndex) {
if (rowIndex > _lastDefinedRow) return true;
for (int i=_rectangleGroups.size()-1; i>=0; i--) {
BlankCellRectangleGroup bcrg = _rectangleGroups.get(i);
if (bcrg.containsCell(rowIndex, columnIndex)) {
return true;
}
}
if(_currentRectangleGroup != null && _currentRectangleGroup.containsCell(rowIndex, columnIndex)) {
return true;
}
if (_currentRowIndex != -1 && _currentRowIndex == rowIndex) {
if (_firstColumnIndex <= columnIndex && columnIndex <= _lastColumnIndex) {
return true;
}
}
return false;
}
}
private static final class BlankCellRectangleGroup {
private final int _firstRowIndex;
private final int _firstColumnIndex;
private final int _lastColumnIndex;
private int _lastRowIndex;
public BlankCellRectangleGroup(int firstRowIndex, int firstColumnIndex, int lastColumnIndex) {
_firstRowIndex = firstRowIndex;
_firstColumnIndex = firstColumnIndex;
_lastColumnIndex = lastColumnIndex;
_lastRowIndex = firstRowIndex;
}
public boolean containsCell(int rowIndex, int columnIndex) {
if (columnIndex < _firstColumnIndex) {
return false;
}
if (columnIndex > _lastColumnIndex) {
return false;
}
if (rowIndex < _firstRowIndex) {
return false;
}
if (rowIndex > _lastRowIndex) {
return false;
}
return true;
}
public boolean acceptRow(int rowIndex, int firstColumnIndex, int lastColumnIndex) {
if (firstColumnIndex != _firstColumnIndex) {
return false;
}
if (lastColumnIndex != _lastColumnIndex) {
return false;
}
if (rowIndex != _lastRowIndex+1) {
return false;
}
_lastRowIndex = rowIndex;
return true;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer(64);
CellReference crA = new CellReference(_firstRowIndex, _firstColumnIndex, false, false);
CellReference crB = new CellReference(_lastRowIndex, _lastColumnIndex, false, false);
sb.append(getClass().getName());
sb.append(" [").append(crA.formatAsString()).append(':').append(crB.formatAsString()).append("]");
return sb.toString();
}
}
private final Map<BookSheetKey, BlankCellSheetGroup> _sheetGroupsByBookSheet;
public FormulaUsedBlankCellSet() {
_sheetGroupsByBookSheet = new HashMap<>();
}
public void addCell(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex, int rowIndex, int columnIndex) {
BlankCellSheetGroup sbcg = getSheetGroup(evalWorkbook, bookIndex, sheetIndex);
sbcg.addCell(rowIndex, columnIndex);
}
private BlankCellSheetGroup getSheetGroup(EvaluationWorkbook evalWorkbook, int bookIndex, int sheetIndex) {
BookSheetKey key = new BookSheetKey(bookIndex, sheetIndex);
BlankCellSheetGroup result = _sheetGroupsByBookSheet.get(key);
if (result == null) {
result = new BlankCellSheetGroup(evalWorkbook.getSheet(sheetIndex).getLastRowNum());
_sheetGroupsByBookSheet.put(key, result);
}
return result;
}
public boolean containsCell(BookSheetKey key, int rowIndex, int columnIndex) {
BlankCellSheetGroup bcsg = _sheetGroupsByBookSheet.get(key);
if (bcsg == null) {
return false;
}
return bcsg.containsCell(rowIndex, columnIndex);
}
public boolean isEmpty() {
return _sheetGroupsByBookSheet.isEmpty();
}
}