Reapplied DBCell etc etc patch to head after it had been clobbered during the move from the rel_2_branch to head.
Refixes bug 9576 git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353605 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
49e1a3d294
commit
f5b0a702a7
@ -46,7 +46,7 @@ import java.util.List;
|
||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Glen Stampoultzis (glens at apache.org)
|
||||
* @author Shawn Laubach (slaubach at apache dot org) Gridlines, Headers, Footers, and PrintSetup
|
||||
* @author Jason Height (jheight at chariot dot net dot au) Clone support
|
||||
* @author Jason Height (jheight at chariot dot net dot au) Clone support. DBCell & Index Record writing support
|
||||
* @author Brian Sanders (kestrel at burdell dot org) Active Cell support
|
||||
*
|
||||
* @see org.apache.poi.hssf.model.Workbook
|
||||
@ -272,6 +272,15 @@ public class Sheet implements Model
|
||||
{
|
||||
retval.windowTwo = (WindowTwoRecord) rec;
|
||||
}
|
||||
else if ( rec.getSid() == DBCellRecord.sid )
|
||||
{
|
||||
rec = null;
|
||||
}
|
||||
else if ( rec.getSid() == IndexRecord.sid )
|
||||
{
|
||||
rec = null;
|
||||
}
|
||||
|
||||
else if ( rec.getSid() == ProtectRecord.sid )
|
||||
{
|
||||
retval.protect = (ProtectRecord) rec;
|
||||
@ -719,51 +728,6 @@ public class Sheet implements Model
|
||||
return preoffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes all records in the sheet into one big byte array. Use this to write
|
||||
* the sheet out.
|
||||
*
|
||||
* @return byte[] array containing the binary representation of the records in this sheet
|
||||
*
|
||||
*/
|
||||
|
||||
public byte [] serialize()
|
||||
{
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
log.log(POILogger.DEBUG, "Sheet.serialize");
|
||||
|
||||
// addDBCellRecords();
|
||||
byte[] retval = null;
|
||||
|
||||
// ArrayList bytes = new ArrayList(4096);
|
||||
int arraysize = getSize();
|
||||
int pos = 0;
|
||||
|
||||
// for (int k = 0; k < records.size(); k++)
|
||||
// {
|
||||
// bytes.add((( Record ) records.get(k)).serialize());
|
||||
//
|
||||
// }
|
||||
// for (int k = 0; k < bytes.size(); k++)
|
||||
// {
|
||||
// arraysize += (( byte [] ) bytes.get(k)).length;
|
||||
// POILogger.DEBUG((new StringBuffer("arraysize=")).append(arraysize)
|
||||
// .toString());
|
||||
// }
|
||||
retval = new byte[ arraysize ];
|
||||
for (int k = 0; k < records.size(); k++)
|
||||
{
|
||||
|
||||
// byte[] rec = (( byte [] ) bytes.get(k));
|
||||
// System.arraycopy(rec, 0, retval, pos, rec.length);
|
||||
pos += (( Record ) records.get(k)).serialize(pos,
|
||||
retval); // rec.length;
|
||||
}
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
log.log(POILogger.DEBUG, "Sheet.serialize returning " + retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes all records in the sheet into one big byte array. Use this to write
|
||||
* the sheet out.
|
||||
@ -778,48 +742,76 @@ public class Sheet implements Model
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
log.log(POILogger.DEBUG, "Sheet.serialize using offsets");
|
||||
|
||||
// addDBCellRecords();
|
||||
// ArrayList bytes = new ArrayList(4096);
|
||||
// int arraysize = getSize(); // 0;
|
||||
int pos = 0;
|
||||
int pos = offset;
|
||||
boolean haveSerializedIndex = false;
|
||||
|
||||
// for (int k = 0; k < records.size(); k++)
|
||||
// {
|
||||
// bytes.add((( Record ) records.get(k)).serialize());
|
||||
//
|
||||
// }
|
||||
// for (int k = 0; k < bytes.size(); k++)
|
||||
// {
|
||||
// arraysize += (( byte [] ) bytes.get(k)).length;
|
||||
// POILogger.DEBUG((new StringBuffer("arraysize=")).append(arraysize)
|
||||
// .toString());
|
||||
// }
|
||||
for (int k = 0; k < records.size(); k++)
|
||||
{
|
||||
// byte[] rec = (( byte [] ) bytes.get(k));
|
||||
// System.arraycopy(rec, 0, data, offset + pos, rec.length);
|
||||
Record record = (( Record ) records.get(k));
|
||||
|
||||
//// uncomment to test record sizes ////
|
||||
// System.out.println( record.getClass().getName() );
|
||||
// byte[] data2 = new byte[record.getRecordSize()];
|
||||
// record.serialize(0, data2 ); // rec.length;
|
||||
// if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4
|
||||
// && record instanceof RowRecordsAggregate == false
|
||||
// && record instanceof ValueRecordsAggregate == false
|
||||
// && record instanceof EscherAggregate == false)
|
||||
// {
|
||||
// throw new RuntimeException("Blah!!! Size off by " + ( LittleEndian.getUShort(data2, 2) - record.getRecordSize() - 4) + " records.");
|
||||
// }
|
||||
int startPos = pos;
|
||||
//Once the rows have been found in the list of records, start
|
||||
//writing out the blocked row information. This includes the DBCell references
|
||||
if (record instanceof RowRecordsAggregate) {
|
||||
pos += ((RowRecordsAggregate)record).serialize(pos, data, cells); // rec.length;
|
||||
} else if (record instanceof ValueRecordsAggregate) {
|
||||
//Do nothing here. The records were serialized during the RowRecordAggregate block serialization
|
||||
} else {
|
||||
pos += record.serialize(pos, data ); // rec.length;
|
||||
}
|
||||
//If the BOF record was just serialized then add the IndexRecord
|
||||
if (record.getSid() == BOFRecord.sid) {
|
||||
//Can there be more than one BOF for a sheet? If not then we can
|
||||
//remove this guard. So be safe it is left here.
|
||||
if (!haveSerializedIndex) {
|
||||
haveSerializedIndex = true;
|
||||
pos += serializeIndexRecord(k, pos, data);
|
||||
}
|
||||
}
|
||||
|
||||
pos += record.serialize(pos + offset, data ); // rec.length;
|
||||
|
||||
}
|
||||
if (log.check( POILogger.DEBUG ))
|
||||
log.log(POILogger.DEBUG, "Sheet.serialize returning ");
|
||||
return pos;
|
||||
return pos-offset;
|
||||
}
|
||||
|
||||
private int serializeIndexRecord(final int BOFRecordIndex, final int offset, byte[] data) {
|
||||
IndexRecord index = new IndexRecord();
|
||||
index.setFirstRow(rows.getFirstRowNum());
|
||||
index.setLastRowAdd1(rows.getLastRowNum()+1);
|
||||
//Calculate the size of the records from the end of the BOF
|
||||
//and up to the RowRecordsAggregate...
|
||||
int sheetRecSize = 0;
|
||||
for (int j = BOFRecordIndex+1; j < records.size(); j++)
|
||||
{
|
||||
Record tmpRec = (( Record ) records.get(j));
|
||||
if (tmpRec instanceof RowRecordsAggregate)
|
||||
break;
|
||||
sheetRecSize+= tmpRec.getRecordSize();
|
||||
}
|
||||
//Add the references to the DBCells in the IndexRecord (one for each block)
|
||||
int blockCount = rows.getRowBlockCount();
|
||||
//Calculate the size of this IndexRecord
|
||||
int indexRecSize = index.getRecordSizeForBlockCount(blockCount);
|
||||
|
||||
int rowBlockOffset = 0;
|
||||
int cellBlockOffset = 0;
|
||||
int dbCellOffset = 0;
|
||||
for (int block=0;block<blockCount;block++) {
|
||||
rowBlockOffset += rows.getRowBlockSize(block);
|
||||
cellBlockOffset += cells.getRowCellBlockSize(rows.getStartRowNumberForBlock(block),
|
||||
rows.getEndRowNumberForBlock(block));
|
||||
//Note: The offsets are relative to the Workbook BOF. Assume that this is
|
||||
//0 for now.....
|
||||
index.addDbcell(offset + indexRecSize + sheetRecSize + dbCellOffset + rowBlockOffset + cellBlockOffset);
|
||||
//Add space required to write the dbcell record(s) (whose references were just added).
|
||||
dbCellOffset += (8 + (rows.getRowCountForBlock(block) * 2));
|
||||
}
|
||||
return index.serialize(offset, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a row record. (does not add it to the records contained in this sheet)
|
||||
*
|
||||
@ -1378,118 +1370,6 @@ public class Sheet implements Model
|
||||
// return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not currently used method to calculate and add dbcell records
|
||||
*
|
||||
*/
|
||||
|
||||
public void addDBCellRecords()
|
||||
{
|
||||
int offset = 0;
|
||||
int recnum = 0;
|
||||
int rownum = 0;
|
||||
//int lastrow = 0;
|
||||
//long lastrowoffset = 0;
|
||||
IndexRecord index = null;
|
||||
|
||||
// ArrayList rowOffsets = new ArrayList();
|
||||
IntList rowOffsets = new IntList();
|
||||
|
||||
for (recnum = 0; recnum < records.size(); recnum++)
|
||||
{
|
||||
Record rec = ( Record ) records.get(recnum);
|
||||
|
||||
if (rec.getSid() == IndexRecord.sid)
|
||||
{
|
||||
index = ( IndexRecord ) rec;
|
||||
}
|
||||
if (rec.getSid() != RowRecord.sid)
|
||||
{
|
||||
offset += rec.serialize().length;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// First Row Record
|
||||
for (; recnum < records.size(); recnum++)
|
||||
{
|
||||
Record rec = ( Record ) records.get(recnum);
|
||||
|
||||
if (rec.getSid() == RowRecord.sid)
|
||||
{
|
||||
rownum++;
|
||||
rowOffsets.add(offset);
|
||||
if ((rownum % 32) == 0)
|
||||
{
|
||||
|
||||
// if this is the last rec in a dbcell block
|
||||
// find the next row or last value record
|
||||
for (int rn = recnum; rn < records.size(); rn++)
|
||||
{
|
||||
rec = ( Record ) records.get(rn);
|
||||
if ((!rec.isInValueSection())
|
||||
|| (rec.getSid() == RowRecord.sid))
|
||||
{
|
||||
|
||||
// here is the next row or last value record
|
||||
records.add(rn,
|
||||
createDBCell(offset, rowOffsets,
|
||||
index));
|
||||
recnum = rn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
if (!rec.isInValueSection())
|
||||
{
|
||||
records.add(recnum, createDBCell(offset, rowOffsets, index));
|
||||
break;
|
||||
}
|
||||
offset += rec.serialize().length;
|
||||
}
|
||||
}
|
||||
|
||||
/** not currently used */
|
||||
|
||||
private DBCellRecord createDBCell(int offset, IntList rowoffsets,
|
||||
IndexRecord index)
|
||||
{
|
||||
DBCellRecord rec = new DBCellRecord();
|
||||
|
||||
rec.setRowOffset(offset - rowoffsets.get(0));
|
||||
|
||||
// test hack
|
||||
rec.addCellOffset(( short ) 0x0);
|
||||
|
||||
// end test hack
|
||||
addDbCellToIndex(offset, index);
|
||||
return rec;
|
||||
}
|
||||
|
||||
/** not currently used */
|
||||
|
||||
private void addDbCellToIndex(int offset, IndexRecord index)
|
||||
{
|
||||
int numdbcells = index.getNumDbcells() + 1;
|
||||
|
||||
index.addDbcell(offset + preoffset);
|
||||
|
||||
// stupid but whenever we add an offset that causes everything to be shifted down 4
|
||||
for (int k = 0; k < numdbcells; k++)
|
||||
{
|
||||
int dbval = index.getDbcellAt(k);
|
||||
|
||||
index.setDbcell(k, dbval + 4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the BOF record
|
||||
* @see org.apache.poi.hssf.record.BOFRecord
|
||||
@ -2148,6 +2028,21 @@ public class Sheet implements Model
|
||||
{
|
||||
retval += (( Record ) records.get(k)).getRecordSize();
|
||||
}
|
||||
//Add space for the IndexRecord
|
||||
final int blocks = rows.getRowBlockCount();
|
||||
retval += IndexRecord.getRecordSizeForBlockCount(blocks);
|
||||
|
||||
//Add space for the DBCell records
|
||||
//Once DBCell per block.
|
||||
//8 bytes per DBCell (non variable section)
|
||||
//2 bytes per row reference
|
||||
int startRetVal = retval;
|
||||
retval += (8 * blocks);
|
||||
for (Iterator itr = rows.getIterator(); itr.hasNext();) {
|
||||
RowRecord row = (RowRecord)itr.next();
|
||||
if (cells.rowHasCells(row.getRowNumber()))
|
||||
retval += 2;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -21,16 +21,18 @@ package org.apache.poi.hssf.record;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
|
||||
/**
|
||||
* Title: DBCell Record (Currently read only. Not required.)
|
||||
* Description: Used to find rows in blocks...TODO<P>
|
||||
* Title: DBCell Record
|
||||
* Description: Used by Excel and other MS apps to quickly find rows in the sheets.<P>
|
||||
* REFERENCE: PG 299/440 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
|
||||
* @author Andrew C. Oliver (acoliver at apache dot org)
|
||||
* @author Jason Height
|
||||
* @version 2.0-pre
|
||||
*/
|
||||
|
||||
public class DBCellRecord
|
||||
extends Record
|
||||
{
|
||||
public final static int BLOCK_SIZE = 32;
|
||||
public final static short sid = 0xd7;
|
||||
private int field_1_row_offset;
|
||||
private short[] field_2_cell_offsets;
|
||||
@ -180,7 +182,7 @@ public class DBCellRecord
|
||||
LittleEndian.putInt(data, 4 + offset, getRowOffset());
|
||||
for (int k = 0; k < getNumCellOffsets(); k++)
|
||||
{
|
||||
LittleEndian.putShort(data, 8 + k + offset, getCellOffsetAt(k));
|
||||
LittleEndian.putShort(data, 8 + 2*k + offset, getCellOffsetAt(k));
|
||||
}
|
||||
return getRecordSize();
|
||||
}
|
||||
@ -190,6 +192,11 @@ public class DBCellRecord
|
||||
return 8 + (getNumCellOffsets() * 2);
|
||||
}
|
||||
|
||||
/** Returns the size of a DBCellRecord when it needs to reference a certain number of rows*/
|
||||
public static int getRecordSizeForRows(int rows) {
|
||||
return 8 + (rows * 2);
|
||||
}
|
||||
|
||||
public short getSid()
|
||||
{
|
||||
return this.sid;
|
||||
|
@ -185,6 +185,13 @@ public class IndexRecord
|
||||
return 20 + (getNumDbcells() * 4);
|
||||
}
|
||||
|
||||
/** Returns the size of an INdexRecord when it needs to index the specified number of blocks
|
||||
*
|
||||
*/
|
||||
public static int getRecordSizeForBlockCount(int blockCount) {
|
||||
return 20 + (4 * blockCount);
|
||||
}
|
||||
|
||||
public short getSid()
|
||||
{
|
||||
return this.sid;
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
package org.apache.poi.hssf.record.aggregates;
|
||||
|
||||
import org.apache.poi.hssf.record.DBCellRecord;
|
||||
import org.apache.poi.hssf.record.Record;
|
||||
import org.apache.poi.hssf.record.RowRecord;
|
||||
|
||||
@ -95,29 +96,89 @@ public class RowRecordsAggregate
|
||||
return lastrow;
|
||||
}
|
||||
|
||||
/*
|
||||
* No need to go through all the records as we're just collecting RowRecords
|
||||
|
||||
public int construct(int offset, List records)
|
||||
{
|
||||
int k = 0;
|
||||
|
||||
for (k = offset; k < records.size(); k++)
|
||||
{
|
||||
Record rec = ( Record ) records.get(k);
|
||||
|
||||
if (!rec.isInValueSection() && !(rec instanceof UnknownRecord))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (rec.getSid() == RowRecord.sid)
|
||||
{
|
||||
insertRow(( RowRecord ) rec);
|
||||
}
|
||||
}
|
||||
return k;
|
||||
/** Returns the number of row blocks.
|
||||
* <p/>The row blocks are goupings of rows that contain the DBCell record
|
||||
* after them
|
||||
*/
|
||||
public int getRowBlockCount() {
|
||||
int size = records.size()/DBCellRecord.BLOCK_SIZE;
|
||||
if ((records.size() % DBCellRecord.BLOCK_SIZE) != 0)
|
||||
size++;
|
||||
return size;
|
||||
}
|
||||
*/
|
||||
|
||||
public int getRowBlockSize(int block) {
|
||||
return 20 * getRowCountForBlock(block);
|
||||
}
|
||||
|
||||
/** Returns the number of physical rows within a block*/
|
||||
public int getRowCountForBlock(int block) {
|
||||
int startIndex = block * DBCellRecord.BLOCK_SIZE;
|
||||
int endIndex = startIndex + DBCellRecord.BLOCK_SIZE - 1;
|
||||
if (endIndex >= records.size())
|
||||
endIndex = records.size()-1;
|
||||
|
||||
return endIndex-startIndex+1;
|
||||
}
|
||||
|
||||
/** Returns the physical row number of the first row in a block*/
|
||||
public int getStartRowNumberForBlock(int block) {
|
||||
//JMH Given that we basically iterate through the rows in order,
|
||||
//For a performance improvement, it would be better to return an instance of
|
||||
//an iterator and use that instance throughout, rather than recreating one and
|
||||
//having to move it to the right position.
|
||||
int startIndex = block * DBCellRecord.BLOCK_SIZE;
|
||||
Iterator rowIter = records.values().iterator();
|
||||
RowRecord row = null;
|
||||
//Position the iterator at the start of the block
|
||||
for (int i=0; i<=startIndex;i++) {
|
||||
row = (RowRecord)rowIter.next();
|
||||
}
|
||||
|
||||
return row.getRowNumber();
|
||||
}
|
||||
|
||||
/** Returns the physical row number of the end row in a block*/
|
||||
public int getEndRowNumberForBlock(int block) {
|
||||
int endIndex = ((block + 1)*DBCellRecord.BLOCK_SIZE)-1;
|
||||
if (endIndex >= records.size())
|
||||
endIndex = records.size()-1;
|
||||
|
||||
Iterator rowIter = records.values().iterator();
|
||||
RowRecord row = null;
|
||||
for (int i=0; i<=endIndex;i++) {
|
||||
row = (RowRecord)rowIter.next();
|
||||
}
|
||||
return row.getRowNumber();
|
||||
}
|
||||
|
||||
|
||||
/** Serializes a block of the rows */
|
||||
private int serializeRowBlock(final int block, final int offset, byte[] data) {
|
||||
final int startIndex = block*DBCellRecord.BLOCK_SIZE;
|
||||
final int endIndex = startIndex + DBCellRecord.BLOCK_SIZE;
|
||||
|
||||
Iterator rowIterator = records.values().iterator();
|
||||
int pos = offset;
|
||||
|
||||
//JMH Given that we basically iterate through the rows in order,
|
||||
//For a performance improvement, it would be better to return an instance of
|
||||
//an iterator and use that instance throughout, rather than recreating one and
|
||||
//having to move it to the right position.
|
||||
int i=0;
|
||||
for (;i<startIndex;i++)
|
||||
rowIterator.next();
|
||||
while(rowIterator.hasNext() && (i++ < endIndex)) {
|
||||
RowRecord row = (RowRecord)rowIterator.next();
|
||||
pos += row.serialize(pos, data);
|
||||
}
|
||||
return pos - offset;
|
||||
}
|
||||
|
||||
public int serialize(int offset, byte [] data) {
|
||||
throw new RuntimeException("The serialize method that passes in cells should be used");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* called by the class that is responsible for writing this sucker.
|
||||
@ -129,14 +190,38 @@ public class RowRecordsAggregate
|
||||
* @return number of bytes written
|
||||
*/
|
||||
|
||||
public int serialize(int offset, byte [] data)
|
||||
public int serialize(int offset, byte [] data, ValueRecordsAggregate cells)
|
||||
{
|
||||
Iterator itr = records.values().iterator();
|
||||
int pos = offset;
|
||||
int pos = offset;
|
||||
|
||||
//DBCells are serialized before row records.
|
||||
final int blockCount = getRowBlockCount();
|
||||
for (int block=0;block<blockCount;block++) {
|
||||
//Serialize a block of rows.
|
||||
//Hold onto the position of the first row in the block
|
||||
final int rowStartPos = pos;
|
||||
//Hold onto the size of this block that was serialized
|
||||
final int rowBlockSize = serializeRowBlock(block, pos, data);
|
||||
pos += rowBlockSize;
|
||||
//Serialize a block of cells for those rows
|
||||
final int startRowNumber = getStartRowNumberForBlock(block);
|
||||
final int endRowNumber = getEndRowNumberForBlock(block);
|
||||
DBCellRecord cellRecord = new DBCellRecord();
|
||||
//Note: Cell references start from the second row...
|
||||
int cellRefOffset = (rowBlockSize-20);
|
||||
for (int row=startRowNumber;row<=endRowNumber;row++) {
|
||||
if (cells.rowHasCells(row)) {
|
||||
final int rowCellSize = cells.serializeCellRow(row, pos, data);
|
||||
pos += rowCellSize;
|
||||
//Add the offset to the first cell for the row into the DBCellRecord.
|
||||
cellRecord.addCellOffset((short)cellRefOffset);
|
||||
cellRefOffset = rowCellSize;
|
||||
}
|
||||
}
|
||||
//Calculate Offset from the start of a DBCellRecord to the first Row
|
||||
cellRecord.setRowOffset(pos - rowStartPos);
|
||||
pos += cellRecord.serialize(pos, data);
|
||||
|
||||
while (itr.hasNext())
|
||||
{
|
||||
pos += (( Record ) itr.next()).serialize(pos, data);
|
||||
}
|
||||
return pos - offset;
|
||||
}
|
||||
|
@ -22,8 +22,10 @@ import org.apache.poi.hssf.record.*;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Aggregate value records together. Things are easier to handle that way.
|
||||
@ -40,7 +42,113 @@ public class ValueRecordsAggregate
|
||||
int firstcell = -1;
|
||||
int lastcell = -1;
|
||||
TreeMap records = null;
|
||||
// int size = 0;
|
||||
|
||||
/** This class is used to find a row in the TreeMap.
|
||||
*
|
||||
* This instance of which is used by the rowHasCells method as the key.
|
||||
*/
|
||||
private class RowComparator implements CellValueRecordInterface, Comparable {
|
||||
private int row;
|
||||
|
||||
public void setRow(int row) {
|
||||
this.row = row;
|
||||
}
|
||||
|
||||
public int compareTo(Object obj) {
|
||||
CellValueRecordInterface cell = (CellValueRecordInterface) obj;
|
||||
|
||||
if (row == cell.getRow()) {
|
||||
return 0;
|
||||
}
|
||||
else if (row < cell.getRow()) {
|
||||
return -1;
|
||||
}
|
||||
else if (row > cell.getRow()){
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
public int getRow() { return row;}
|
||||
public short getColumn() { return 0;}
|
||||
public void setColumn(short col){}
|
||||
public void setXFIndex(short xf){}
|
||||
public short getXFIndex(){return 0;}
|
||||
public boolean isBefore(CellValueRecordInterface i){ return false; }
|
||||
public boolean isAfter(CellValueRecordInterface i){ return false; }
|
||||
public boolean isEqual(CellValueRecordInterface i){ return false; }
|
||||
public Object clone(){ return null;}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates the cell records that exist between the startRow and endRow (inclusive).
|
||||
*
|
||||
* User must ensure that hasNext & next are called insequence for correct
|
||||
* operation. Could fix, but since this is only used internally to the
|
||||
* ValueRecordsAggregate class there doesnt seem much point.
|
||||
*/
|
||||
private class RowCellIterator implements Iterator {
|
||||
private int startRow;
|
||||
private int endRow;
|
||||
private Iterator internalIterator;
|
||||
private CellValueRecordInterface atCell;
|
||||
|
||||
public class RowCellComparator extends RowComparator {
|
||||
public int compareTo(Object obj) {
|
||||
CellValueRecordInterface cell = (CellValueRecordInterface) obj;
|
||||
|
||||
if (getRow() == cell.getRow() && cell.getColumn() == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (getRow() < cell.getRow()) {
|
||||
return -1;
|
||||
}
|
||||
else if (getRow() > cell.getRow()){
|
||||
return 1;
|
||||
}
|
||||
if (cell.getColumn() > 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (cell.getColumn() < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private RowCellComparator rowCellCompare;
|
||||
|
||||
|
||||
public RowCellIterator(int startRow, int endRow) {
|
||||
this.startRow = startRow;
|
||||
this.endRow = endRow;
|
||||
rowCellCompare = new RowCellComparator();
|
||||
rowCellCompare.setRow(startRow);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
if (internalIterator == null) {
|
||||
internalIterator = records.tailMap(rowCellCompare).values().iterator();
|
||||
}
|
||||
if (internalIterator.hasNext()) {
|
||||
atCell = (CellValueRecordInterface) internalIterator.next();
|
||||
return (atCell.getRow() <= endRow);
|
||||
} else return false;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
return atCell;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
//Do Nothing (Not called)
|
||||
}
|
||||
}
|
||||
|
||||
//Only need a single instance of this class, but the row fields
|
||||
//will probably change each use. Instance is only used in the rowHasCells method.
|
||||
public final RowComparator compareRow = new RowComparator();
|
||||
|
||||
/** Creates a new instance of ValueRecordsAggregate */
|
||||
|
||||
@ -51,17 +159,6 @@ public class ValueRecordsAggregate
|
||||
|
||||
public void insertCell(CellValueRecordInterface cell)
|
||||
{
|
||||
/* if (records.get(cell) == null)
|
||||
{
|
||||
size += (( Record ) cell).getRecordSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
size += (( Record ) cell).getRecordSize()
|
||||
- (( Record ) records.get(cell)).getRecordSize();
|
||||
}*/
|
||||
|
||||
// XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn());
|
||||
Object o = records.put(cell, cell);
|
||||
|
||||
if ((cell.getColumn() < firstcell) || (firstcell == -1))
|
||||
@ -76,9 +173,6 @@ public class ValueRecordsAggregate
|
||||
|
||||
public void removeCell(CellValueRecordInterface cell)
|
||||
{
|
||||
// size -= (( Record ) cell).getRecordSize();
|
||||
|
||||
// XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn());
|
||||
records.remove(cell);
|
||||
}
|
||||
|
||||
@ -145,15 +239,49 @@ public class ValueRecordsAggregate
|
||||
|
||||
public int serialize(int offset, byte [] data)
|
||||
{
|
||||
Iterator itr = records.values().iterator();
|
||||
throw new RuntimeException("This method shouldnt be called. ValueRecordsAggregate.serializeCellRow() should be called from RowRecordsAggregate.");
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
RowCellIterator itr = new RowCellIterator(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 += ((Record)cell).getRecordSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Returns true if the row has cells attached to it */
|
||||
public boolean rowHasCells(int row) {
|
||||
compareRow.setRow(row);
|
||||
return records.containsKey(compareRow);
|
||||
}
|
||||
|
||||
/** Serializes the cells that are allocated to a certain row range*/
|
||||
public int serializeCellRow(final int row, int offset, byte [] data)
|
||||
{
|
||||
RowCellIterator itr = new RowCellIterator(row, row);
|
||||
int pos = offset;
|
||||
|
||||
while (itr.hasNext())
|
||||
{
|
||||
pos += (( Record ) itr.next()).serialize(pos, data);
|
||||
CellValueRecordInterface cell = (CellValueRecordInterface)itr.next();
|
||||
if (cell.getRow() != row)
|
||||
break;
|
||||
pos += (( Record ) cell).serialize(pos, data);
|
||||
}
|
||||
return pos - offset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* called by the constructor, should set class level fields. Should throw
|
||||
* runtime exception for bad/icomplete data.
|
||||
@ -197,7 +325,6 @@ public class ValueRecordsAggregate
|
||||
}
|
||||
|
||||
return size;
|
||||
// return size;
|
||||
}
|
||||
|
||||
public Iterator getIterator()
|
||||
@ -215,58 +342,3 @@ public class ValueRecordsAggregate
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* class XYLocator implements Comparable {
|
||||
* private int row = 0;
|
||||
* private int col = 0;
|
||||
* public XYLocator(int row, int col) {
|
||||
* this.row = row;
|
||||
* this.col = col;
|
||||
* }
|
||||
*
|
||||
* public int getRow() {
|
||||
* return row;
|
||||
* }
|
||||
*
|
||||
* public int getCol() {
|
||||
* return col;
|
||||
* }
|
||||
*
|
||||
* public int compareTo(Object obj) {
|
||||
* XYLocator loc = (XYLocator)obj;
|
||||
*
|
||||
* if (this.getRow() == loc.getRow() &&
|
||||
* this.getCol() == loc.getCol() )
|
||||
* return 0;
|
||||
*
|
||||
* if (this.getRow() < loc.getRow())
|
||||
* return -1;
|
||||
*
|
||||
* if (this.getRow() > loc.getRow())
|
||||
* return 1;
|
||||
*
|
||||
* if (this.getCol() < loc.getCol())
|
||||
* return -1;
|
||||
*
|
||||
* if (this.getCol() > loc.getCol())
|
||||
* return 1;
|
||||
*
|
||||
* return -1;
|
||||
*
|
||||
* }
|
||||
*
|
||||
* public boolean equals(Object obj) {
|
||||
* if (!(obj instanceof XYLocator)) return false;
|
||||
*
|
||||
* XYLocator loc = (XYLocator)obj;
|
||||
* if (this.getRow() == loc.getRow()
|
||||
* &&
|
||||
* this.getCol() == loc.getCol()
|
||||
* ) return true;
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
*
|
||||
* }
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user