poi-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jhei...@apache.org
Subject cvs commit: jakarta-poi/src/java/org/apache/poi/hssf/record/aggregates RowRecordsAggregate.java ValueRecordsAggregate.java
Date Thu, 07 Oct 2004 03:37:16 GMT
jheight     2004/10/06 20:37:16

  Modified:    src/java/org/apache/poi/hssf/model Sheet.java
               src/java/org/apache/poi/hssf/record DBCellRecord.java
                        IndexRecord.java
               src/java/org/apache/poi/hssf/record/aggregates
                        RowRecordsAggregate.java ValueRecordsAggregate.java
  Log:
  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
  
  Revision  Changes    Path
  1.48      +85 -190   jakarta-poi/src/java/org/apache/poi/hssf/model/Sheet.java
  
  Index: Sheet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/model/Sheet.java,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- Sheet.java	23 Aug 2004 08:52:28 -0000	1.47
  +++ Sheet.java	7 Oct 2004 03:37:15 -0000	1.48
  @@ -46,7 +46,7 @@
    * @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 @@
               {
                   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;
  @@ -723,51 +732,6 @@
        * 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.
  -     *
        * @param offset to begin write at
        * @param data   array containing the binary representation of the records in this
sheet
        *
  @@ -778,47 +742,75 @@
           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;
  -
  -        // 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());
  -        // }
  +        int pos       = offset;
  +        boolean haveSerializedIndex = false;
  +
           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));
  +            
  +            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);
  +              }
  +            }
   
  -            //// 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.");
  -//            }
  -
  -            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)
  @@ -1379,118 +1371,6 @@
       }
   
       /**
  -     * 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
        * @see org.apache.poi.hssf.record.Record
  @@ -2147,6 +2027,21 @@
           for (int k = 0; k < records.size(); k++)
           {
               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;
       }
  
  
  
  1.9       +10 -3     jakarta-poi/src/java/org/apache/poi/hssf/record/DBCellRecord.java
  
  Index: DBCellRecord.java
  ===================================================================
  RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/DBCellRecord.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- DBCellRecord.java	23 Aug 2004 08:52:31 -0000	1.8
  +++ DBCellRecord.java	7 Oct 2004 03:37:16 -0000	1.9
  @@ -21,16 +21,18 @@
   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 @@
           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();
       }
  @@ -188,6 +190,11 @@
       public int getRecordSize()
       {
           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()
  
  
  
  1.8       +7 -0      jakarta-poi/src/java/org/apache/poi/hssf/record/IndexRecord.java
  
  Index: IndexRecord.java
  ===================================================================
  RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/IndexRecord.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- IndexRecord.java	23 Aug 2004 08:52:32 -0000	1.7
  +++ IndexRecord.java	7 Oct 2004 03:37:16 -0000	1.8
  @@ -184,6 +184,13 @@
       {
           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()
       {
  
  
  
  1.11      +113 -28   jakarta-poi/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java
  
  Index: RowRecordsAggregate.java
  ===================================================================
  RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- RowRecordsAggregate.java	23 Aug 2004 08:52:28 -0000	1.10
  +++ RowRecordsAggregate.java	7 Oct 2004 03:37:16 -0000	1.11
  @@ -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;
   
  @@ -94,30 +95,90 @@
       {
           return lastrow;
       }
  +    
  +    /** 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;
  +    }
   
  -	/*
  -	 * 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;
  +    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 @@
        * @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;
       }
  
  
  
  1.17      +344 -272  jakarta-poi/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java
  
  Index: ValueRecordsAggregate.java
  ===================================================================
  RCS file: /home/cvs/jakarta-poi/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- ValueRecordsAggregate.java	23 Aug 2004 08:52:28 -0000	1.16
  +++ ValueRecordsAggregate.java	7 Oct 2004 03:37:16 -0000	1.17
  @@ -1,272 +1,344 @@
  -
  -/* ====================================================================
  -   Copyright 2002-2004   Apache Software Foundation
  -
  -   Licensed under the Apache License, Version 2.0 (the "License");
  -   you may not use this file except in compliance with the License.
  -   You may obtain a copy of the License at
  -
  -       http://www.apache.org/licenses/LICENSE-2.0
  -
  -   Unless required by applicable law or agreed to in writing, software
  -   distributed under the License is distributed on an "AS IS" BASIS,
  -   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  -   See the License for the specific language governing permissions and
  -   limitations under the License.
  -==================================================================== */
  -
  -
  -package org.apache.poi.hssf.record.aggregates;
  -
  -import org.apache.poi.hssf.record.*;
  -
  -import java.util.Iterator;
  -import java.util.List;
  -import java.util.TreeMap;
  -
  -/**
  - *
  - * Aggregate value records together.  Things are easier to handle that way.
  - *
  - * @author  andy
  - * @author  Glen Stampoultzis (glens at apache.org)
  - * @author Jason Height (jheight at chariot dot net dot au)
  - */
  -
  -public class ValueRecordsAggregate
  -    extends Record
  -{
  -    public final static short sid       = -1000;
  -    int                       firstcell = -1;
  -    int                       lastcell  = -1;
  -    TreeMap                   records   = null;
  -//    int                       size      = 0;
  -
  -    /** Creates a new instance of ValueRecordsAggregate */
  -
  -    public ValueRecordsAggregate()
  -    {
  -        records = new TreeMap();
  -    }
  -
  -    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))
  -        {
  -            firstcell = cell.getColumn();
  -        }
  -        if ((cell.getColumn() > lastcell) || (lastcell == -1))
  -        {
  -            lastcell = cell.getColumn();
  -        }
  -    }
  -
  -    public void removeCell(CellValueRecordInterface cell)
  -    {
  -  //      size -= (( Record ) cell).getRecordSize();
  -
  -        // XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn());
  -        records.remove(cell);
  -    }
  -
  -    public int getPhysicalNumberOfCells()
  -    {
  -        return records.size();
  -    }
  -
  -    public int getFirstCellNum()
  -    {
  -        return firstcell;
  -    }
  -
  -    public int getLastCellNum()
  -    {
  -        return lastcell;
  -    }
  -
  -    public int construct(int offset, List records)
  -    {
  -        int k = 0;
  -
  -        FormulaRecordAggregate lastFormulaAggregate = null;
  -
  -        for (k = offset; k < records.size(); k++)
  -        {
  -            Record rec = ( Record ) records.get(k);
  -
  -            if (rec instanceof StringRecord == false && !rec.isInValueSection()
&& !(rec instanceof UnknownRecord))
  -            {
  -                break;
  -            }
  -            if (rec instanceof FormulaRecord)
  -            {
  -                lastFormulaAggregate = new FormulaRecordAggregate((FormulaRecord)rec, null);
  -                insertCell( lastFormulaAggregate );
  -            }
  -            else if (rec instanceof StringRecord)
  -            {
  -                lastFormulaAggregate.setStringRecord((StringRecord)rec);
  -            }
  -            else if (rec instanceof SharedFormulaRecord)
  -            {
  -            	//these follow the first formula in a group
  -            	lastFormulaAggregate.setSharedFormulaRecord((SharedFormulaRecord)rec);
  -            }
  -            else if (rec.isValue())
  -            {
  -                insertCell(( CellValueRecordInterface ) rec);
  -            }
  -        }
  -        return k;
  -    }
  -
  -    /**
  -     * called by the class that is responsible for writing this sucker.
  -     * Subclasses should implement this so that their data is passed back in a
  -     * byte array.
  -     *
  -     * @param offset to begin writing at
  -     * @param data byte array containing instance data
  -     * @return number of bytes written
  -     */
  -
  -    public int serialize(int offset, byte [] data)
  -    {
  -        Iterator itr = records.values().iterator();
  -        int      pos = offset;
  -
  -        while (itr.hasNext())
  -        {
  -            pos += (( Record ) itr.next()).serialize(pos, data);
  -        }
  -        return pos - offset;
  -    }
  -    /**
  -     * called by the constructor, should set class level fields.  Should throw
  -     * runtime exception for bad/icomplete data.
  -     *
  -     * @param data raw data
  -     * @param size size of data
  -     * @param offset of the record's data (provided a big array of the file)
  -     */
  -
  -    protected void fillFields(byte [] data, short size, int offset)
  -    {
  -    }
  -
  -    /**
  -     * called by constructor, should throw runtime exception in the event of a
  -     * record passed with a differing ID.
  -     *
  -     * @param id alleged id for this record
  -     */
  -
  -    protected void validateSid(short id)
  -    {
  -    }
  -
  -    /**
  -     * return the non static version of the id for this record.
  -     */
  -
  -    public short getSid()
  -    {
  -        return sid;
  -    }
  -
  -    public int getRecordSize() {
  -    
  -        int size = 0;
  -        Iterator irecs = records.values().iterator();
  -        
  -        while (irecs.hasNext()) {
  -                size += (( Record ) irecs.next()).getRecordSize();
  -        }
  -
  -        return size;
  -//        return size;
  -    }
  -
  -    public Iterator getIterator()
  -    {
  -        return records.values().iterator();
  -    }
  -
  -    /** Performs a deep clone of the record*/
  -    public Object clone() {
  -      ValueRecordsAggregate rec = new ValueRecordsAggregate();
  -      for (Iterator valIter = getIterator(); valIter.hasNext();) {
  -        CellValueRecordInterface val = (CellValueRecordInterface)((CellValueRecordInterface)valIter.next()).clone();
  -        rec.insertCell(val);
  -      }
  -      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;
  - *   }
  - *
  - *
  - * }
  - */
  +
  +/* ====================================================================
  +   Copyright 2002-2004   Apache Software Foundation
  +
  +   Licensed under the Apache License, Version 2.0 (the "License");
  +   you may not use this file except in compliance with the License.
  +   You may obtain a copy of the License at
  +
  +       http://www.apache.org/licenses/LICENSE-2.0
  +
  +   Unless required by applicable law or agreed to in writing, software
  +   distributed under the License is distributed on an "AS IS" BASIS,
  +   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  +   See the License for the specific language governing permissions and
  +   limitations under the License.
  +==================================================================== */
  +
  +
  +package org.apache.poi.hssf.record.aggregates;
  +
  +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.
  + *
  + * @author  andy
  + * @author  Glen Stampoultzis (glens at apache.org)
  + * @author Jason Height (jheight at chariot dot net dot au)
  + */
  +
  +public class ValueRecordsAggregate
  +    extends Record
  +{
  +    public final static short sid       = -1000;
  +    int                       firstcell = -1;
  +    int                       lastcell  = -1;
  +    TreeMap                   records   = null;
  +
  +   /** 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 */
  +
  +    public ValueRecordsAggregate()
  +    {
  +        records = new TreeMap();
  +    }
  +
  +    public void insertCell(CellValueRecordInterface cell)
  +    {
  +        Object o = records.put(cell, cell);
  +
  +        if ((cell.getColumn() < firstcell) || (firstcell == -1))
  +        {
  +            firstcell = cell.getColumn();
  +        }
  +        if ((cell.getColumn() > lastcell) || (lastcell == -1))
  +        {
  +            lastcell = cell.getColumn();
  +        }
  +    }
  +
  +    public void removeCell(CellValueRecordInterface cell)
  +    {
  +        records.remove(cell);
  +    }
  +
  +    public int getPhysicalNumberOfCells()
  +    {
  +        return records.size();
  +    }
  +
  +    public int getFirstCellNum()
  +    {
  +        return firstcell;
  +    }
  +
  +    public int getLastCellNum()
  +    {
  +        return lastcell;
  +    }
  +
  +    public int construct(int offset, List records)
  +    {
  +        int k = 0;
  +
  +        FormulaRecordAggregate lastFormulaAggregate = null;
  +
  +        for (k = offset; k < records.size(); k++)
  +        {
  +            Record rec = ( Record ) records.get(k);
  +
  +            if (rec instanceof StringRecord == false && !rec.isInValueSection()
&& !(rec instanceof UnknownRecord))
  +            {
  +                break;
  +            }
  +            if (rec instanceof FormulaRecord)
  +            {
  +                lastFormulaAggregate = new FormulaRecordAggregate((FormulaRecord)rec, null);
  +                insertCell( lastFormulaAggregate );
  +            }
  +            else if (rec instanceof StringRecord)
  +            {
  +                lastFormulaAggregate.setStringRecord((StringRecord)rec);
  +            }
  +            else if (rec instanceof SharedFormulaRecord)
  +            {
  +            	//these follow the first formula in a group
  +            	lastFormulaAggregate.setSharedFormulaRecord((SharedFormulaRecord)rec);
  +            }
  +            else if (rec.isValue())
  +            {
  +                insertCell(( CellValueRecordInterface ) rec);
  +            }
  +        }
  +        return k;
  +    }
  +
  +    /**
  +     * called by the class that is responsible for writing this sucker.
  +     * Subclasses should implement this so that their data is passed back in a
  +     * byte array.
  +     *
  +     * @param offset to begin writing at
  +     * @param data byte array containing instance data
  +     * @return number of bytes written
  +     */
  +
  +    public int serialize(int offset, byte [] data)
  +    {
  +      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())
  +        {
  +            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.
  +     *
  +     * @param data raw data
  +     * @param size size of data
  +     * @param offset of the record's data (provided a big array of the file)
  +     */
  +
  +    protected void fillFields(byte [] data, short size, int offset)
  +    {
  +    }
  +
  +    /**
  +     * called by constructor, should throw runtime exception in the event of a
  +     * record passed with a differing ID.
  +     *
  +     * @param id alleged id for this record
  +     */
  +
  +    protected void validateSid(short id)
  +    {
  +    }
  +
  +    /**
  +     * return the non static version of the id for this record.
  +     */
  +
  +    public short getSid()
  +    {
  +        return sid;
  +    }
  +
  +    public int getRecordSize() {
  +    
  +        int size = 0;
  +        Iterator irecs = records.values().iterator();
  +        
  +        while (irecs.hasNext()) {
  +                size += (( Record ) irecs.next()).getRecordSize();
  +        }
  +
  +        return size;
  +    }
  +
  +    public Iterator getIterator()
  +    {
  +        return records.values().iterator();
  +    }
  +
  +    /** Performs a deep clone of the record*/
  +    public Object clone() {
  +      ValueRecordsAggregate rec = new ValueRecordsAggregate();
  +      for (Iterator valIter = getIterator(); valIter.hasNext();) {
  +        CellValueRecordInterface val = (CellValueRecordInterface)((CellValueRecordInterface)valIter.next()).clone();
  +        rec.insertCell(val);
  +      }
  +      return rec;
  +    }
  +}
  \ No newline at end of file
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: poi-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: poi-dev-help@jakarta.apache.org


Mime
View raw message