KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > biff > WritableRecordData


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20 package jxl.biff;
21
22 import common.Assert;
23 import common.Logger;
24
25 import jxl.read.biff.Record;
26
27 /**
28  * Extension of the standard RecordData which is used to support those
29  * records which, once read, may also be written
30  */

31 public abstract class WritableRecordData extends RecordData
32                                          implements ByteData
33 {
34   /**
35    * The logger
36    */

37   private static Logger logger = Logger.getLogger(WritableRecordData.class);
38   /**
39    * The maximum length allowed by Excel for any record length
40    */

41   protected static final int maxRecordLength = 8228;
42
43   /**
44    * Constructor used by the writable records
45    *
46    * @param t the biff type of this record
47    */

48   protected WritableRecordData(Type t)
49   {
50     super(t);
51   }
52
53   /**
54    * Constructor used when reading a record
55    *
56    * @param t the raw data read from the biff file
57    */

58   protected WritableRecordData(Record t)
59   {
60     super(t);
61   }
62
63   /**
64    * Used when writing out records. This portion of the method handles the
65    * biff code and the length of the record and appends on the data retrieved
66    * from the subclasses
67    *
68    * @return the full record data to be written out to the compound file
69    */

70   public final byte[] getBytes()
71   {
72     byte[] data = getData();
73
74     int dataLength = data.length;
75
76     // Don't the call the automatic continuation code for now
77
// Assert.verify(dataLength <= maxRecordLength - 4);
78
// If the bytes length is greater than the max record length
79
// then split out the data set into continue records
80
if (data.length > maxRecordLength - 4)
81     {
82       dataLength = maxRecordLength - 4;
83       data = handleContinueRecords(data);
84     }
85
86     byte[] bytes = new byte[data.length + 4];
87
88     System.arraycopy(data, 0, bytes, 4, data.length);
89
90     IntegerHelper.getTwoBytes(getCode(), bytes, 0);
91     IntegerHelper.getTwoBytes(dataLength, bytes, 2);
92
93     return bytes;
94   }
95
96   /**
97    * The number of bytes for this record exceeds the maximum record
98    * length, so a continue is required
99    * @param data the raw data
100    * @return the continued data
101    */

102   private byte[] handleContinueRecords(byte[] data)
103   {
104     // Deduce the number of continue records
105
int continuedData = data.length - (maxRecordLength - 4);
106     int numContinueRecords = continuedData / (maxRecordLength - 4) + 1;
107
108     // Create the new byte array, allowing for the continue records
109
// code and length
110
byte[] newdata = new byte[data.length + numContinueRecords * 4];
111
112     // Copy the bona fide record data into the beginning of the super
113
// record
114
System.arraycopy(data, 0, newdata, 0, maxRecordLength - 4);
115     int oldarraypos = maxRecordLength - 4;
116     int newarraypos = maxRecordLength - 4;
117
118     // Now handle all the continue records
119
for (int i = 0; i < numContinueRecords; i++)
120     {
121       // The number of bytes to add into the new array
122
int length = Math.min(data.length - oldarraypos, maxRecordLength - 4);
123
124       // Add in the continue record code
125
IntegerHelper.getTwoBytes(Type.CONTINUE.value, newdata, newarraypos);
126       IntegerHelper.getTwoBytes(length, newdata, newarraypos + 2);
127
128       // Copy in as much of the new data as possible
129
System.arraycopy(data, oldarraypos, newdata, newarraypos + 4, length);
130
131       // Update the position counters
132
oldarraypos += length;
133       newarraypos += length + 4;
134     }
135
136     return newdata;
137   }
138
139   /**
140    * Abstract method called by the getBytes method. Subclasses implement
141    * this method to incorporate their specific binary data - excluding the
142    * biff code and record length, which is handled by this class
143    *
144    * @return subclass specific biff data
145    */

146   protected abstract byte[] getData();
147 }
148
Popular Tags