diff options
author | Josh Micich <josh@apache.org> | 2008-12-01 19:59:46 +0000 |
---|---|---|
committer | Josh Micich <josh@apache.org> | 2008-12-01 19:59:46 +0000 |
commit | bfde2bd0509286969de6c1dac2ea279467022afa (patch) | |
tree | cbb5ec25f56f317fba1f651947890f5c71e8b02f /src/java/org | |
parent | df9e2e4a2952f8137c3c2c2e931a294a88566de0 (diff) | |
download | poi-bfde2bd0509286969de6c1dac2ea279467022afa.tar.gz poi-bfde2bd0509286969de6c1dac2ea279467022afa.zip |
Fix for bug 46312 - ValueRecordsAggregate should handle removal of new empty row
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@722206 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org')
-rw-r--r-- | src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java | 562 |
1 files changed, 287 insertions, 275 deletions
diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java index 27000811ce..6ee871a7f2 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -40,279 +40,291 @@ import org.apache.poi.hssf.record.formula.Ptg; * @author Jason Height (jheight at chariot dot net dot au) */ public final class ValueRecordsAggregate { - private int firstcell = -1; - private int lastcell = -1; - private CellValueRecordInterface[][] records; - - /** Creates a new instance of ValueRecordsAggregate */ - - public ValueRecordsAggregate() - { - records = new CellValueRecordInterface[30][]; // We start with 30 Rows. - } - - public void insertCell(CellValueRecordInterface cell) { - short column = cell.getColumn(); - int row = cell.getRow(); - if (row >= records.length) { - CellValueRecordInterface[][] oldRecords = records; - int newSize = oldRecords.length * 2; - if(newSize<row+1) newSize=row+1; - records = new CellValueRecordInterface[newSize][]; - System.arraycopy(oldRecords, 0, records, 0, oldRecords.length); - } - CellValueRecordInterface[] rowCells = records[row]; - if (rowCells == null) { - int newSize = column + 1; - if(newSize<10) newSize=10; - rowCells = new CellValueRecordInterface[newSize]; - records[row] = rowCells; - } - if (column >= rowCells.length) { - CellValueRecordInterface[] oldRowCells = rowCells; - int newSize = oldRowCells.length * 2; - if(newSize<column+1) newSize=column+1; - // if(newSize>257) newSize=257; // activate? - rowCells = new CellValueRecordInterface[newSize]; - System.arraycopy(oldRowCells, 0, rowCells, 0, oldRowCells.length); - records[row] = rowCells; - } - rowCells[column] = cell; - - if ((column < firstcell) || (firstcell == -1)) { - firstcell = column; - } - if ((column > lastcell) || (lastcell == -1)) { - lastcell = column; - } - } - - public void removeCell(CellValueRecordInterface cell) { - if (cell == null) { - throw new IllegalArgumentException("cell must not be null"); - } - int row = cell.getRow(); - if (row >= records.length) { - throw new RuntimeException("cell row is out of range"); - } - CellValueRecordInterface[] rowCells = records[row]; - if (rowCells == null) { - throw new RuntimeException("cell row is already empty"); - } - short column = cell.getColumn(); - if (column >= rowCells.length) { - throw new RuntimeException("cell column is out of range"); - } - rowCells[column] = null; - } - - public void removeAllCellsValuesForRow(int rowIndex) { - if (rowIndex >= records.length) { - throw new IllegalArgumentException("Specified rowIndex " + rowIndex - + " is outside the allowable range (0.." +records.length + ")"); - } - records[rowIndex] = null; - } - - - public int getPhysicalNumberOfCells() - { - int count=0; - for(int r=0;r<records.length;r++) { - CellValueRecordInterface[] rowCells=records[r]; - if (rowCells != null) - for(short c=0;c<rowCells.length;c++) { - if(rowCells[c]!=null) count++; - } - } - return count; - } - - public int getFirstCellNum() - { - return firstcell; - } - - public int getLastCellNum() - { - return lastcell; - } - - /** - * Processes a single cell value record - * @param sfh used to resolve any shared-formulas/arrays/tables for the current sheet - */ - public void construct(CellValueRecordInterface rec, RecordStream rs, SharedValueManager sfh) { - if (rec instanceof FormulaRecord) { - FormulaRecord formulaRec = (FormulaRecord)rec; - // read optional cached text value - StringRecord cachedText; - Class nextClass = rs.peekNextClass(); - if (nextClass == StringRecord.class) { - cachedText = (StringRecord) rs.getNext(); - } else { - cachedText = null; - } - insertCell(new FormulaRecordAggregate(formulaRec, cachedText, sfh)); - } else { - insertCell(rec); - } - } - - /** Tallies a count of the size of the cell records - * that are attached to the rows in the range specified. - */ - public int getRowCellBlockSize(int startRow, int endRow) { - MyIterator itr = new MyIterator(startRow, endRow); - int size = 0; - while (itr.hasNext()) { - CellValueRecordInterface cell = (CellValueRecordInterface)itr.next(); - int row = cell.getRow(); - if (row > endRow) - break; - if ((row >=startRow) && (row <= endRow)) - size += ((RecordBase)cell).getRecordSize(); - } - return size; - } - - /** Returns true if the row has cells attached to it */ - public boolean rowHasCells(int row) { - if (row > records.length-1) //previously this said row > records.length which means if - return false; // if records.length == 60 and I pass "60" here I get array out of bounds - CellValueRecordInterface[] rowCells=records[row]; //because a 60 length array has the last index = 59 - if(rowCells==null) return false; - for(int col=0;col<rowCells.length;col++) { - if(rowCells[col]!=null) return true; - } - return false; - } - - /** Serializes the cells that are allocated to a certain row range*/ - public int serializeCellRow(final int row, int offset, byte [] data) - { - MyIterator itr = new MyIterator(row, row); - int pos = offset; - - while (itr.hasNext()) - { - CellValueRecordInterface cell = (CellValueRecordInterface)itr.next(); - if (cell.getRow() != row) - break; - pos += (( RecordBase ) cell).serialize(pos, data); - } - return pos - offset; - } - - public void visitCellsForRow(int rowIndex, RecordVisitor rv) { - - CellValueRecordInterface[] cellRecs = records[rowIndex]; - if (cellRecs != null) { - for (int i = 0; i < cellRecs.length; i++) { - CellValueRecordInterface cvr = cellRecs[i]; - if (cvr == null) { - continue; - } - if (cvr instanceof RecordAggregate) { - RecordAggregate agg = (RecordAggregate) cvr; - agg.visitContainedRecords(rv); - } else { - Record rec = (Record) cvr; - rv.visitRecord(rec); - } - } - } - } - - public void updateFormulasAfterRowShift(FormulaShifter shifter, int currentExternSheetIndex) { - for (int i = 0; i < records.length; i++) { - CellValueRecordInterface[] rowCells = records[i]; - if (rowCells == null) { - continue; - } - for (int j = 0; j < rowCells.length; j++) { - CellValueRecordInterface cell = rowCells[j]; - if (cell instanceof FormulaRecordAggregate) { - FormulaRecord fr = ((FormulaRecordAggregate)cell).getFormulaRecord(); - Ptg[] ptgs = fr.getParsedExpression(); // needs clone() inside this getter? - if (shifter.adjustFormula(ptgs, currentExternSheetIndex)) { - fr.setParsedExpression(ptgs); - } - } - } - } - } - - public CellValueRecordInterface[] getValueRecords() { - List temp = new ArrayList(); - - for (int i = 0; i < records.length; i++) { - CellValueRecordInterface[] rowCells = records[i]; - if (rowCells == null) { - continue; - } - for (int j = 0; j < rowCells.length; j++) { - CellValueRecordInterface cell = rowCells[j]; - if (cell != null) { - temp.add(cell); - } - } - } - - CellValueRecordInterface[] result = new CellValueRecordInterface[temp.size()]; - temp.toArray(result); - return result; - } - public Iterator getIterator() - { - return new MyIterator(); - } - - private final class MyIterator implements Iterator { - short nextColumn=-1; - int nextRow,lastRow; - - public MyIterator() - { - this.nextRow=0; - this.lastRow=records.length-1; - findNext(); - } - - public MyIterator(int firstRow,int lastRow) - { - this.nextRow=firstRow; - this.lastRow=lastRow; - findNext(); - } - - public boolean hasNext() { - return nextRow<=lastRow; - } - public Object next() { - Object o=records[nextRow][nextColumn]; - findNext(); - return o; - } - public void remove() { - throw new UnsupportedOperationException("gibt's noch nicht"); - } - - private void findNext() { - nextColumn++; - for(;nextRow<=lastRow;nextRow++) { - //previously this threw array out of bounds... - CellValueRecordInterface[] rowCells=(nextRow < records.length) ? records[nextRow] : null; - if(rowCells==null) { // This row is empty - nextColumn=0; - continue; - } - for(;nextColumn<rowCells.length;nextColumn++) { - if(rowCells[nextColumn]!=null) return; - } - nextColumn=0; - } - } - - } + private static final int MAX_ROW_INDEX = 0XFFFF; + private int firstcell = -1; + private int lastcell = -1; + private CellValueRecordInterface[][] records; + + /** Creates a new instance of ValueRecordsAggregate */ + + public ValueRecordsAggregate() { + records = new CellValueRecordInterface[30][]; // We start with 30 Rows. + } + + public void insertCell(CellValueRecordInterface cell) { + short column = cell.getColumn(); + int row = cell.getRow(); + if (row >= records.length) { + CellValueRecordInterface[][] oldRecords = records; + int newSize = oldRecords.length * 2; + if (newSize < row + 1) + newSize = row + 1; + records = new CellValueRecordInterface[newSize][]; + System.arraycopy(oldRecords, 0, records, 0, oldRecords.length); + } + CellValueRecordInterface[] rowCells = records[row]; + if (rowCells == null) { + int newSize = column + 1; + if (newSize < 10) + newSize = 10; + rowCells = new CellValueRecordInterface[newSize]; + records[row] = rowCells; + } + if (column >= rowCells.length) { + CellValueRecordInterface[] oldRowCells = rowCells; + int newSize = oldRowCells.length * 2; + if (newSize < column + 1) + newSize = column + 1; + // if(newSize>257) newSize=257; // activate? + rowCells = new CellValueRecordInterface[newSize]; + System.arraycopy(oldRowCells, 0, rowCells, 0, oldRowCells.length); + records[row] = rowCells; + } + rowCells[column] = cell; + + if ((column < firstcell) || (firstcell == -1)) { + firstcell = column; + } + if ((column > lastcell) || (lastcell == -1)) { + lastcell = column; + } + } + + public void removeCell(CellValueRecordInterface cell) { + if (cell == null) { + throw new IllegalArgumentException("cell must not be null"); + } + int row = cell.getRow(); + if (row >= records.length) { + throw new RuntimeException("cell row is out of range"); + } + CellValueRecordInterface[] rowCells = records[row]; + if (rowCells == null) { + throw new RuntimeException("cell row is already empty"); + } + short column = cell.getColumn(); + if (column >= rowCells.length) { + throw new RuntimeException("cell column is out of range"); + } + rowCells[column] = null; + } + + public void removeAllCellsValuesForRow(int rowIndex) { + if (rowIndex < 0 || rowIndex > MAX_ROW_INDEX) { + throw new IllegalArgumentException("Specified rowIndex " + rowIndex + + " is outside the allowable range (0.." +MAX_ROW_INDEX + ")"); + } + if (rowIndex >= records.length) { + // this can happen when the client code has created a row, + // and then removes/replaces it before adding any cells. (see bug 46312) + return; + } + + records[rowIndex] = null; + } + + + public int getPhysicalNumberOfCells() { + int count = 0; + for (int r = 0; r < records.length; r++) { + CellValueRecordInterface[] rowCells = records[r]; + if (rowCells != null) { + for (int c = 0; c < rowCells.length; c++) { + if (rowCells[c] != null) + count++; + } + } + } + return count; + } + + public int getFirstCellNum() { + return firstcell; + } + + public int getLastCellNum() { + return lastcell; + } + + /** + * Processes a single cell value record + * @param sfh used to resolve any shared-formulas/arrays/tables for the current sheet + */ + public void construct(CellValueRecordInterface rec, RecordStream rs, SharedValueManager sfh) { + if (rec instanceof FormulaRecord) { + FormulaRecord formulaRec = (FormulaRecord)rec; + // read optional cached text value + StringRecord cachedText; + Class nextClass = rs.peekNextClass(); + if (nextClass == StringRecord.class) { + cachedText = (StringRecord) rs.getNext(); + } else { + cachedText = null; + } + insertCell(new FormulaRecordAggregate(formulaRec, cachedText, sfh)); + } else { + insertCell(rec); + } + } + + /** Tallies a count of the size of the cell records + * that are attached to the rows in the range specified. + */ + public int getRowCellBlockSize(int startRow, int endRow) { + MyIterator itr = new MyIterator(records, startRow, endRow); + int size = 0; + while (itr.hasNext()) { + CellValueRecordInterface cell = (CellValueRecordInterface) itr.next(); + int row = cell.getRow(); + if (row > endRow) { + break; + } + if ((row >= startRow) && (row <= endRow)) { + size += ((RecordBase) cell).getRecordSize(); + } + } + return size; + } + + /** Returns true if the row has cells attached to it */ + public boolean rowHasCells(int row) { + if (row >= records.length) { + return false; + } + CellValueRecordInterface[] rowCells=records[row]; + if(rowCells==null) return false; + for(int col=0;col<rowCells.length;col++) { + if(rowCells[col]!=null) return true; + } + return false; + } + + /** Serializes the cells that are allocated to a certain row range*/ + public int serializeCellRow(final int row, int offset, byte [] data) + { + MyIterator itr = new MyIterator(records, row, row); + int pos = offset; + + while (itr.hasNext()) + { + CellValueRecordInterface cell = (CellValueRecordInterface)itr.next(); + if (cell.getRow() != row) + break; + pos += (( RecordBase ) cell).serialize(pos, data); + } + return pos - offset; + } + + public void visitCellsForRow(int rowIndex, RecordVisitor rv) { + + CellValueRecordInterface[] cellRecs = records[rowIndex]; + if (cellRecs != null) { + for (int i = 0; i < cellRecs.length; i++) { + CellValueRecordInterface cvr = cellRecs[i]; + if (cvr == null) { + continue; + } + if (cvr instanceof RecordAggregate) { + RecordAggregate agg = (RecordAggregate) cvr; + agg.visitContainedRecords(rv); + } else { + Record rec = (Record) cvr; + rv.visitRecord(rec); + } + } + } + } + + public void updateFormulasAfterRowShift(FormulaShifter shifter, int currentExternSheetIndex) { + for (int i = 0; i < records.length; i++) { + CellValueRecordInterface[] rowCells = records[i]; + if (rowCells == null) { + continue; + } + for (int j = 0; j < rowCells.length; j++) { + CellValueRecordInterface cell = rowCells[j]; + if (cell instanceof FormulaRecordAggregate) { + FormulaRecord fr = ((FormulaRecordAggregate)cell).getFormulaRecord(); + Ptg[] ptgs = fr.getParsedExpression(); // needs clone() inside this getter? + if (shifter.adjustFormula(ptgs, currentExternSheetIndex)) { + fr.setParsedExpression(ptgs); + } + } + } + } + } + + public CellValueRecordInterface[] getValueRecords() { + List<CellValueRecordInterface> temp = new ArrayList<CellValueRecordInterface>(); + + for (int i = 0; i < records.length; i++) { + CellValueRecordInterface[] rowCells = records[i]; + if (rowCells == null) { + continue; + } + for (int j = 0; j < rowCells.length; j++) { + CellValueRecordInterface cell = rowCells[j]; + if (cell != null) { + temp.add(cell); + } + } + } + + CellValueRecordInterface[] result = new CellValueRecordInterface[temp.size()]; + temp.toArray(result); + return result; + } + public Iterator getIterator() { + return new MyIterator(records); + } + + private static final class MyIterator implements Iterator { + private final CellValueRecordInterface[][] records; + private short nextColumn = -1; + private int nextRow, lastRow; + + public MyIterator(CellValueRecordInterface[][] pRecords) { + this(pRecords, 0, pRecords.length - 1); + } + + public MyIterator(CellValueRecordInterface[][] pRecords, int firstRow, int lastRow) { + records = pRecords; + this.nextRow = firstRow; + this.lastRow = lastRow; + findNext(); + } + + public boolean hasNext() { + return nextRow <= lastRow; + } + + public Object next() { + Object o = records[nextRow][nextColumn]; + findNext(); + return o; + } + + public void remove() { + throw new UnsupportedOperationException("gibt's noch nicht"); + } + + private void findNext() { + nextColumn++; + for (; nextRow <= lastRow; nextRow++) { + // previously this threw array out of bounds... + CellValueRecordInterface[] rowCells = (nextRow < records.length) ? records[nextRow] + : null; + if (rowCells == null) { // This row is empty + nextColumn = 0; + continue; + } + for (; nextColumn < rowCells.length; nextColumn++) { + if (rowCells[nextColumn] != null) + return; + } + nextColumn = 0; + } + } + + } } |