1    
2    /* ====================================================================
3     * The Apache Software License, Version 1.1
4     *
5     * Copyright (c) 2002 The Apache Software Foundation.  All rights
6     * reserved.
7     *
8     * Redistribution and use in source and binary forms, with or without
9     * modification, are permitted provided that the following conditions
10    * are met:
11    *
12    * 1. Redistributions of source code must retain the above copyright
13    *    notice, this list of conditions and the following disclaimer.
14    *
15    * 2. Redistributions in binary form must reproduce the above copyright
16    *    notice, this list of conditions and the following disclaimer in
17    *    the documentation and/or other materials provided with the
18    *    distribution.
19    *
20    * 3. The end-user documentation included with the redistribution,
21    *    if any, must include the following acknowledgment:
22    *       "This product includes software developed by the
23    *        Apache Software Foundation (http://www.apache.org/)."
24    *    Alternately, this acknowledgment may appear in the software itself,
25    *    if and wherever such third-party acknowledgments normally appear.
26    *
27    * 4. The names "Apache" and "Apache Software Foundation" and
28    *    "Apache POI" must not be used to endorse or promote products
29    *    derived from this software without prior written permission. For
30    *    written permission, please contact apache@apache.org.
31    *
32    * 5. Products derived from this software may not be called "Apache",
33    *    "Apache POI", nor may "Apache" appear in their name, without
34    *    prior written permission of the Apache Software Foundation.
35    *
36    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47    * SUCH DAMAGE.
48    * ====================================================================
49    *
50    * This software consists of voluntary contributions made by many
51    * individuals on behalf of the Apache Software Foundation.  For more
52    * information on the Apache Software Foundation, please see
53    * <http://www.apache.org/>.
54    */
55   
56   package org.apache.poi.hssf.record;
57   
58   import org.apache.poi.util.LittleEndian;
59   
60   /**
61    * Title: Beginning Of File<P>
62    * Description: Somewhat of a misnomer, its used for the beginning of a set of
63    *              records that have a particular pupose or subject.
64    *              Used in sheets and workbooks.<P>
65    * REFERENCE:  PG 289 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
66    * @author Andrew C. Oliver
67    * @author Jason Height (jheight at chariot dot net dot au)
68    * @version 2.0-pre
69    */
70   
71   public class BOFRecord
72       extends Record
73   {
74   
75       /**
76        * for BIFF8 files the BOF is 0x809.  For earlier versions it was 0x09 or 0x(biffversion)09
77        */
78   
79       public final static short sid = 0x809;
80       private short             field_1_version;
81       private short             field_2_type;
82       private short             field_3_build;
83       private short             field_4_year;
84       private int               field_5_history;
85       private int               field_6_rversion;
86   
87       /**
88        * suggested default (0x06 - BIFF8)
89        */
90   
91       public final static short VERSION             = 0x06;
92   
93       /**
94        * suggested default 0x10d3
95        */
96   
97       public final static short BUILD               = 0x10d3;
98   
99       /**
100       * suggested default  0x07CC (1996)
101       */
102  
103      public final static short BUILD_YEAR          = 0x07CC;   // 1996
104  
105      /**
106       * suggested default for a normal sheet (0x41)
107       */
108  
109      public final static short HISTORY_MASK        = 0x41;
110      public final static short TYPE_WORKBOOK       = 0x05;
111      public final static short TYPE_VB_MODULE      = 0x06;
112      public final static short TYPE_WORKSHEET      = 0x10;
113      public final static short TYPE_CHART          = 0x20;
114      public final static short TYPE_EXCEL_4_MACRO  = 0x40;
115      public final static short TYPE_WORKSPACE_FILE = 0x100;
116  
117      /**
118       * Constructs an empty BOFRecord with no fields set.
119       */
120  
121      public BOFRecord()
122      {
123      }
124  
125      /**
126       * Constructs a BOFRecord and sets its fields appropriately
127       *
128       * @param id     id must be 0x809 or an exception will be throw upon validation
129       * @param size  the size of the data area of the record
130       * @param data  data of the record (should not contain sid/len)
131       */
132  
133      public BOFRecord(short id, short size, byte [] data)
134      {
135          super(id, size, data);
136  
137          // fillFields(data,size);
138      }
139  
140      /**
141       * Constructs a BOFRecord and sets its fields appropriately
142       *
143       * @param id     id must be 0x809 or an exception will be throw upon validation
144       * @param size  the size of the data area of the record
145       * @param data  data of the record (should not contain sid/len)
146       * @param offset the offset of the record's data
147       */
148  
149      public BOFRecord(short id, short size, byte [] data, int offset)
150      {
151          super(id, size, data, offset);
152  
153          // fillFields(data,size);
154      }
155  
156      protected void validateSid(short id)
157      {
158          if (id != sid)
159          {
160              throw new RecordFormatException("NOT A BOF RECORD");
161          }
162      }
163  
164      protected void fillFields(byte [] data, short size, int offset)
165      {
166          field_1_version  = LittleEndian.getShort(data, 0 + offset);
167          field_2_type     = LittleEndian.getShort(data, 2 + offset);
168          field_3_build    = LittleEndian.getShort(data, 4 + offset);
169          field_4_year     = LittleEndian.getShort(data, 6 + offset);
170          field_5_history  = LittleEndian.getInt(data, 8 + offset);
171          field_6_rversion = LittleEndian.getInt(data, 12 + offset);
172      }
173  
174      /**
175       * Version number - for BIFF8 should be 0x06
176       * @see #VERSION
177       * @param short version to be set
178       */
179  
180      public void setVersion(short version)
181      {
182          field_1_version = version;
183      }
184  
185      /**
186       * type of object this marks
187       * @see #TYPE_WORKBOOK
188       * @see #TYPE_VB_MODULE
189       * @see #TYPE_WORKSHEET
190       * @see #TYPE_CHART
191       * @see #TYPE_EXCEL_4_MACRO
192       * @see #TYPE_WORKSPACE_FILE
193       * @param short type to be set
194       */
195  
196      public void setType(short type)
197      {
198          field_2_type = type;
199      }
200  
201      /**
202       * build that wrote this file
203       * @see #BUILD
204       * @param short build number to set
205       */
206  
207      public void setBuild(short build)
208      {
209          field_3_build = build;
210      }
211  
212      /**
213       * Year of the build that wrote this file
214       * @see #BUILD_YEAR
215       * @param short build year to set
216       */
217  
218      public void setBuildYear(short year)
219      {
220          field_4_year = year;
221      }
222  
223      /**
224       * set the history bit mask (not very useful)
225       * @see #HISTORY_MASK
226       * @param int bitmask to set for the history
227       */
228  
229      public void setHistoryBitMask(int bitmask)
230      {
231          field_5_history = bitmask;
232      }
233  
234      /**
235       * set the minimum version required to read this file
236       *
237       * @see #VERSION
238       * @param int version to set
239       */
240  
241      public void setRequiredVersion(int version)
242      {
243          field_6_rversion = version;
244      }
245  
246      /**
247       * Version number - for BIFF8 should be 0x06
248       * @see #VERSION
249       * @return short version number of the generator of this file
250       */
251  
252      public short getVersion()
253      {
254          return field_1_version;
255      }
256  
257      /**
258       * type of object this marks
259       * @see #TYPE_WORKBOOK
260       * @see #TYPE_VB_MODULE
261       * @see #TYPE_WORKSHEET
262       * @see #TYPE_CHART
263       * @see #TYPE_EXCEL_4_MACRO
264       * @see #TYPE_WORKSPACE_FILE
265       * @return short type of object
266       */
267  
268      public short getType()
269      {
270          return field_2_type;
271      }
272  
273      /**
274       * get the build that wrote this file
275       * @see #BUILD
276       * @return short build number of the generator of this file
277       */
278  
279      public short getBuild()
280      {
281          return field_3_build;
282      }
283  
284      /**
285       * Year of the build that wrote this file
286       * @see #BUILD_YEAR
287       * @return short build year of the generator of this file
288       */
289  
290      public short getBuildYear()
291      {
292          return field_4_year;
293      }
294  
295      /**
296       * get the history bit mask (not very useful)
297       * @see #HISTORY_MASK
298       * @return int bitmask showing the history of the file (who cares!)
299       */
300  
301      public int getHistoryBitMask()
302      {
303          return field_5_history;
304      }
305  
306      /**
307       * get the minimum version required to read this file
308       *
309       * @see #VERSION
310       * @return int least version that can read the file
311       */
312  
313      public int getRequiredVersion()
314      {
315          return field_6_rversion;
316      }
317  
318      public String toString()
319      {
320          StringBuffer buffer = new StringBuffer();
321  
322          buffer.append("[BOF RECORD]\n");
323          buffer.append("    .version         = ")
324              .append(Integer.toHexString(getVersion())).append("\n");
325          buffer.append("    .type            = ")
326              .append(Integer.toHexString(getType())).append("\n");
327          buffer.append("    .build           = ")
328              .append(Integer.toHexString(getBuild())).append("\n");
329          buffer.append("    .buildyear       = ").append(getBuildYear())
330              .append("\n");
331          buffer.append("    .history         = ")
332              .append(Integer.toHexString(getHistoryBitMask())).append("\n");
333          buffer.append("    .requiredversion = ")
334              .append(Integer.toHexString(getRequiredVersion())).append("\n");
335          buffer.append("[/BOF RECORD]\n");
336          return buffer.toString();
337      }
338  
339      public int serialize(int offset, byte [] data)
340      {
341          LittleEndian.putShort(data, 0 + offset, sid);
342          LittleEndian.putShort(data, 2 + offset,
343                                (( short ) 0x10));   // 16 byte length
344          LittleEndian.putShort(data, 4 + offset, getVersion());
345          LittleEndian.putShort(data, 6 + offset, getType());
346          LittleEndian.putShort(data, 8 + offset, getBuild());
347          LittleEndian.putShort(data, 10 + offset, getBuildYear());
348          LittleEndian.putInt(data, 12 + offset, getHistoryBitMask());
349          LittleEndian.putInt(data, 16 + offset, getRequiredVersion());
350          return getRecordSize();
351      }
352  
353      public int getRecordSize()
354      {
355          return 20;
356      }
357  
358      public short getSid()
359      {
360          return this.sid;
361      }
362  
363      public Object clone() {
364        BOFRecord rec = new BOFRecord();
365        rec.field_1_version = field_1_version;
366        rec.field_2_type = field_2_type;
367        rec.field_3_build = field_3_build;
368        rec.field_4_year = field_4_year;
369        rec.field_5_history = field_5_history;
370        rec.field_6_rversion = field_6_rversion;
371        return rec;
372      }
373  }
374