Package com.extentech.formats.XLS

Source Code of com.extentech.formats.XLS.Index$dbCellPointer

/*
* --------- BEGIN COPYRIGHT NOTICE ---------
* Copyright 2002-2012 Extentech Inc.
* Copyright 2013 Infoteria America Corp.
*
* This file is part of OpenXLS.
*
* OpenXLS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* OpenXLS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with OpenXLS.  If not, see
* <http://www.gnu.org/licenses/>.
* ---------- END COPYRIGHT NOTICE ----------
*/
package com.extentech.formats.XLS;

import java.io.Serializable;
import java.util.Arrays;

import com.extentech.toolkit.ByteTools;
import com.extentech.toolkit.CompatibleVector;
import com.extentech.toolkit.Logger;


/**<b>Index: Index Record 0x20B</b><br>
   
    Index records are written after the Bof record for each Boundsheet.
    <p><pre>
   
    offset  name        size    contents
    ---   
    4       Reserved    4       Must be zero
    8       rwMic       4       First row that exists on the sheet
    12      rwMac       4       Last row that exists on the sheet, plus 1
    16      Reserved    4       Pointer to DIMENSIONS record for Boundsheet
    20      rgibRw      var     Array of file offsets to the Dbcell records
                                for each block of ROW records.  A block
                                contains up to 32 ROW records.
  
  
    When a record value changes in size, it fires a CellChangeEvent
    which cascades through the other associated objects.
       
    The record size change has the following effect on INDEX record fields:

       1. ALL Dbcell records in the file starting with the one
       containing the changed record move.  This requires updating
       the dbcellpointers (rgibRw) in ALL INDEX records which
       are located after the changed Dbcell within the file stream.
       
   </p></pre>
   
* @see WorkBook
* @see Boundsheet
* @see Dbcell
* @see Row
* @see Cell
* @see XLSRecord
*/

public final class Index extends com.extentech.formats.XLS.XLSRecord implements XLSConstants 
{
    /**
  * serialVersionUID
  */
  private static final long serialVersionUID = -753407655976707961L;
  private int rwMic;
    private int rwMac;
    private int dbnum = 0;
//    private dbCellPointer[] dbcellarray; not used
    private CompatibleVector dbcells = new CompatibleVector();
    private int indexnum;
    private static int defaultsize = 16;
    private Dimensions dims;

    /** create a new INDEX rec
    */
    public static XLSRecord getPrototype(){
        Index idx  = new Index();
        byte[] dt = new byte[defaultsize]; // default val
        idx.originalsize = defaultsize;
      idx.setData(dt);
      idx.setOpcode(INDEX);
      idx.setLength((short)defaultsize);
      idx.init();
      return idx;
    }

    /** fire the cell change event

    public void fireCellChangeEvent(CellChangeEvent c){
        // do its thing
       // this.doCellSizeChangeAction(c);
        // then pass it along...
       //  this.getSheet().fireCellChangeEvent(c);
    }    */
   
    void setDimensions(Dimensions d){
         this.dims = d;  
    }
   
   
    // Not used??
    void setDimensionsOffset(int offset) {
        byte[] recData = this.getData();
        byte[] newoff = ByteTools.cLongToLEBytes(offset);
        System.arraycopy(newoff, 0, recData, 12, 4);
        this.setData(recData);
    }
    /** set the index number for
        addressing.
   */
    public void setIndexNum(int n){indexnum = n;}
    
    /** get the index number for
        addressing.
    */
    public int getIndexNum(){return indexnum;}
   
   
    /** add an associated Dbcell object
        to this INDEX.
     */
    void addDBCell(Dbcell dbc){
    boolean bAdd= true;
/* KSC: TESTING testLostBorders bug   for (int i= 0; i < dbcells.size() && bAdd; i++) {
      if (Arrays.equals(((Dbcell) dbcells.get(i)).data,  dbc.data))
      bAdd= false;
    }*/
    if (bAdd) {
//        if(!dbcells.contains(dbc)){
            dbc.setDBCNum(dbnum++);
            dbcells.add(dbc);
//        }
    }
    }
   
    void resetDBCells() {
      dbnum= 0;
      dbcells= new CompatibleVector();
    }
  
    /** Update the Dbcell Pointers
     *
     * At this point the index should have all of it's dbcells in place, as well as
     * thier offsets being populated, so all that should need to be done is to create
     * the index correctly out of its values
    */
   
    void updateDbcellPointers(){
        streamer = getSheet().streamer;
        // first, get the collection of Rows from sheet
        Boundsheet bs = this.getSheet();
        Row[] rowz = bs.getRows();
        if (rowz.length!=0) {
        this.updateRowDimensions(rowz[0].getRowNumber(), rowz[(rowz.length)-1].getRowNumber());
        }
        // create the new Dbcells if any rows exist within the sheet
      
        // rebuild the record with the correct length body data to fit the new dbcells
        int arrsize = 16 +(dbcells.size() * 4);
        byte[] newBytes = new byte[arrsize];
        Dbcell dbc = null;
        System.arraycopy(this.getData(), 0, newBytes, 0, 16);
        int offset=16;
        for (int i=0;i<dbcells.size();i++) {
            Dbcell db = (Dbcell)dbcells.elementAt(i);
            int dbOff = db.getOffset();
            byte[] b = ByteTools.cLongToLEBytes(dbOff);
            newBytes[offset++]=b[0];
            newBytes[offset++]=b[1];
            newBytes[offset++]=b[2];
            newBytes[offset++]=b[3];
        }
        this.setData(newBytes);     
    }
     
     
    /** update the dimensions info based on Dimensions rec
    */
    void updateDimensions(){
        byte[] rkdata = this.getData();
        byte[] newb = ByteTools.cLongToLEBytes(dims.offset);
        rkdata[12] = newb[0];
        rkdata[13] = newb[1];
        rkdata[14] = newb[2];
        rkdata[15] = newb[3];

        /* these should match rwMic/rwMac on dimensions rec
        dims.rwMic;
        dims.rwMac;
        */
    }
   
    /** return the associated Dbcell objects
        for this INDEX.
    */
    Dbcell[] getDBCells(){
        Object[] obj = dbcells.toArray();
        Dbcell[] dbcs = new Dbcell[obj.length];
        System.arraycopy(obj, 0, dbcs, 0, obj.length);
        return dbcs;
    }
   
  public void init() {
    super.init();
    // 1st 4 are reseverd-0
    rwMic= ByteTools.readInt(this.getBytesAt(4, 4));
    rwMac= ByteTools.readInt(this.getBytesAt(8, 4));
    // next 4 are position of defColWidth record - skip
/* no need to read in dbcell offsets as we don't do anything with it
*     int pos= 16;
    int recsize= 4; // KSC added   
    int numdbcells = (this.getLength()-pos)/recsize; 
//    dbcellarray = new dbCellPointer[numdbcells];
    // rest of data is position of dbCell records: rgibRw (variable): An array of FilePointer. Each FilePointer specifies the file position of each referenced DBCell record
    for(int i = 0;i< numdbcells;i++){
        if(DEBUGLEVEL > 6)Logger.logInfo("Index -> initializing dbcell pointer: " + i);
        byte[] bite = this.getBytesAt(pos,4);
        dbCellPointer pointer = new dbCellPointer(bite);
        pos += 4;
//        dbcellarray[i] = pointer;
    }
//    */
  }

    /** compute the location of Dbcell records using
        the INDEX dbcellpointers and the firstBof record position
        in the workbook.
       
        NOT USED
    *
    int getDbcellPosition(int pointernum){
        int firstBofloc = wkbook.getFirstBof().offset;
        byte[] b = dbcellarray[pointernum].cdb;
        int pointerloc = ByteTools.readInt(b[0],b[1],b[2],b[3]);
        return pointerloc + firstBofloc;
    }*/
   
    /** file offset to the Dbcell record
    */
    class dbCellPointer implements Serializable{
       
        /**
    * serialVersionUID
    */
    private static final long serialVersionUID = -5132922970171084839L;
    int cellloc = 0;
        int datasiz = 0;
        short s2,s3;
        byte[] cdb = new byte[4];
       
        dbCellPointer(byte[] b){
            cdb = b;
            cellloc = (int) ByteTools.readShort(b[0],b[1]);
            datasiz = (int) ByteTools.readShort(b[2],b[3]);
        }

      /*** Updates location of Dbcell pointer and data size(?)
      */
        void adjustPosition(int i){
            cellloc += i;
            datasiz += i;
        }
       
        byte[] getBytes(){
            byte[] bite = new byte[4];
            System.arraycopy(ByteTools.shortToLEBytes((short)cellloc), 0, bite, 0, 2);
            System.arraycopy(ByteTools.shortToLEBytes((short)datasiz), 0, bite , 2, 2);           
            return bite;
        }  
    }
   
    /** update the min/max cols and rows
        8       rwMic       4       First row that exists on the sheet
        12      rwMac       4       Last row that exists on the sheet, plus 1
    */
    public void updateRowDimensions(int lowRow, int hiRow){
        byte[] rw = ByteTools.cLongToLEBytes(lowRow);
        System.arraycopy(rw, 0, this.getData(), 4, 4);
        rw = ByteTools.cLongToLEBytes(hiRow+1);
        System.arraycopy(rw, 0, this.getData(), 8, 4);           
    }   
   
    /**
     * Called from streamer, this updates individual dbcell offset values.
     *
     * Will only run correctly if called sequentially, ie dboffset [0], [1], [2]
     * @param DbcellNumber - which dbcell to update
     * @param DbOffset - the pure offset from beginning of file
     */
    void setDbcellPosition(int DbcellNumber, int DbOffset) {
        if (offsetStart == 0) {
            offsetStart = this.getSheet().getMyBof().getOffset();
        }
        int insertOffset = DbOffset - offsetStart;
        if (DEBUGLEVEL > 10) {
            Logger.logInfo("Setting DBBiffRec Position, offsetStart:"+ offsetStart + " & InsertOffset = " + insertOffset);
        }
        offsetStart += insertOffset;
        int insertloc = 16 + (DbcellNumber*4);
        byte[] off = ByteTools.cLongToLEBytes(insertOffset);
        System.arraycopy(off, 0, data, insertloc, 4);    
       
    }
    int offsetStart = 0;
   
   
    /**
     * Prestream for Index is going to create the correct size record, and populate the correct number of dbcells.
     * The actual values will not yet be populated, but the record sizes will be correct in order to get offsets
     * working correctly.
     *
     * Once offsets are correctly calculated in bytestreamer.stream, we can come back and
     * populate without the getIndex call overhead.
     *
    */
    public void preStream() {      
        // rebuild the record with the correct length body data to fit the new dbcells
        this.getData();
        int arrsize = 16 +(dbcells.size() * 4);
        byte[] newBytes = new byte[arrsize];
        Dbcell dbc = null;
        // KSC: Changed from copying 12 bytes to copying 16 bytes to keep DIMENSIONS reference
        System.arraycopy(this.getData(), 0, newBytes, 0, 16);
        this.setData(newBytes);
    }
}

TOP

Related Classes of com.extentech.formats.XLS.Index$dbCellPointer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.