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    * @version 2.0-pre
68    */
69   
70   public class BOFRecord
71       extends Record
72   {
73   
74       /**
75        * for BIFF8 files the BOF is 0x809.  For earlier versions it was 0x09 or 0x(biffversion)09
76        */
77   
78       public final static short sid = 0x809;
79       private short             field_1_version;
80       private short             field_2_type;
81       private short             field_3_build;
82       private short             field_4_year;
83       private int               field_5_history;
84       private int               field_6_rversion;
85   
86       /**
87        * suggested default (0x06 - BIFF8)
88        */
89   
90       public final static short VERSION             = 0x06;
91   
92       /**
93        * suggested default 0x10d3
94        */
95   
96       public final static short BUILD               = 0x10d3;
97   
98       /**
99        * suggested default  0x07CC (1996)
100       */
101  
102      public final static short BUILD_YEAR          = 0x07CC;   // 1996
103  
104      /**
105       * suggested default for a normal sheet (0x41)
106       */
107  
108      public final static short HISTORY_MASK        = 0x41;
109      public final static short TYPE_WORKBOOK       = 0x05;
110      public final static short TYPE_VB_MODULE      = 0x06;
111      public final static short TYPE_WORKSHEET      = 0x10;
112      public final static short TYPE_CHART          = 0x20;
113      public final static short TYPE_EXCEL_4_MACRO  = 0x40;
114      public final static short TYPE_WORKSPACE_FILE = 0x100;
115  
116      /**
117       * Constructs an empty BOFRecord with no fields set.
118       */
119  
120      public BOFRecord()
121      {
122      }
123  
124      /**
125       * Constructs a BOFRecord and sets its fields appropriately
126       *
127       * @param id     id must be 0x809 or an exception will be throw upon validation
128       * @param size  the size of the data area of the record
129       * @param data  data of the record (should not contain sid/len)
130       */
131  
132      public BOFRecord(short id, short size, byte [] data)
133      {
134          super(id, size, data);
135  
136          // fillFields(data,size);
137      }
138  
139      /**
140       * Constructs a BOFRecord and sets its fields appropriately
141       *
142       * @param id     id must be 0x809 or an exception will be throw upon validation
143       * @param size  the size of the data area of the record
144       * @param data  data of the record (should not contain sid/len)
145       * @param offset the offset of the record's data
146       */
147  
148      public BOFRecord(short id, short size, byte [] data, int offset)
149      {
150          super(id, size, data, offset);
151  
152          // fillFields(data,size);
153      }
154  
155      protected void validateSid(short id)
156      {
157          if (id != sid)
158          {
159              throw new RecordFormatException("NOT A BOF RECORD");
160          }
161      }
162  
163      protected void fillFields(byte [] data, short size, int offset)
164      {
165          field_1_version  = LittleEndian.getShort(data, 0 + offset);
166          field_2_type     = LittleEndian.getShort(data, 2 + offset);
167          field_3_build    = LittleEndian.getShort(data, 4 + offset);
168          field_4_year     = LittleEndian.getShort(data, 6 + offset);
169          field_5_history  = LittleEndian.getInt(data, 8 + offset);
170          field_6_rversion = LittleEndian.getInt(data, 12 + offset);
171      }
172  
173      /**
174       * Version number - for BIFF8 should be 0x06
175       * @see #VERSION
176       * @param short version to be set
177       */
178  
179      public void setVersion(short version)
180      {
181          field_1_version = version;
182      }
183  
184      /**
185       * type of object this marks
186       * @see #TYPE_WORKBOOK
187       * @see #TYPE_VB_MODULE
188       * @see #TYPE_WORKSHEET
189       * @see #TYPE_CHART
190       * @see #TYPE_EXCEL_4_MACRO
191       * @see #TYPE_WORKSPACE_FILE
192       * @param short type to be set
193       */
194  
195      public void setType(short type)
196      {
197          field_2_type = type;
198      }
199  
200      /**
201       * build that wrote this file
202       * @see #BUILD
203       * @param short build number to set
204       */
205  
206      public void setBuild(short build)
207      {
208          field_3_build = build;
209      }
210  
211      /**
212       * Year of the build that wrote this file
213       * @see #BUILD_YEAR
214       * @param short build year to set
215       */
216  
217      public void setBuildYear(short year)
218      {
219          field_4_year = year;
220      }
221  
222      /**
223       * set the history bit mask (not very useful)
224       * @see #HISTORY_MASK
225       * @param int bitmask to set for the history
226       */
227  
228      public void setHistoryBitMask(int bitmask)
229      {
230          field_5_history = bitmask;
231      }
232  
233      /**
234       * set the minimum version required to read this file
235       *
236       * @see #VERSION
237       * @param int version to set
238       */
239  
240      public void setRequiredVersion(int version)
241      {
242          field_6_rversion = version;
243      }
244  
245      /**
246       * Version number - for BIFF8 should be 0x06
247       * @see #VERSION
248       * @return short version number of the generator of this file
249       */
250  
251      public short getVersion()
252      {
253          return field_1_version;
254      }
255  
256      /**
257       * type of object this marks
258       * @see #TYPE_WORKBOOK
259       * @see #TYPE_VB_MODULE
260       * @see #TYPE_WORKSHEET
261       * @see #TYPE_CHART
262       * @see #TYPE_EXCEL_4_MACRO
263       * @see #TYPE_WORKSPACE_FILE
264       * @return short type of object
265       */
266  
267      public short getType()
268      {
269          return field_2_type;
270      }
271  
272      /**
273       * get the build that wrote this file
274       * @see #BUILD
275       * @return short build number of the generator of this file
276       */
277  
278      public short getBuild()
279      {
280          return field_3_build;
281      }
282  
283      /**
284       * Year of the build that wrote this file
285       * @see #BUILD_YEAR
286       * @return short build year of the generator of this file
287       */
288  
289      public short getBuildYear()
290      {
291          return field_4_year;
292      }
293  
294      /**
295       * get the history bit mask (not very useful)
296       * @see #HISTORY_MASK
297       * @return int bitmask showing the history of the file (who cares!)
298       */
299  
300      public int getHistoryBitMask()
301      {
302          return field_5_history;
303      }
304  
305      /**
306       * get the minimum version required to read this file
307       *
308       * @see #VERSION
309       * @return int least version that can read the file
310       */
311  
312      public int getRequiredVersion()
313      {
314          return field_6_rversion;
315      }
316  
317      public String toString()
318      {
319          StringBuffer buffer = new StringBuffer();
320  
321          buffer.append("[BOF RECORD]\n");
322          buffer.append("    .version         = ")
323              .append(Integer.toHexString(getVersion())).append("\n");
324          buffer.append("    .type            = ")
325              .append(Integer.toHexString(getType())).append("\n");
326          buffer.append("    .build           = ")
327              .append(Integer.toHexString(getBuild())).append("\n");
328          buffer.append("    .buildyear       = ").append(getBuildYear())
329              .append("\n");
330          buffer.append("    .history         = ")
331              .append(Integer.toHexString(getHistoryBitMask())).append("\n");
332          buffer.append("    .requiredversion = ")
333              .append(Integer.toHexString(getRequiredVersion())).append("\n");
334          buffer.append("[/BOF RECORD]\n");
335          return buffer.toString();
336      }
337  
338      public int serialize(int offset, byte [] data)
339      {
340          LittleEndian.putShort(data, 0 + offset, sid);
341          LittleEndian.putShort(data, 2 + offset,
342                                (( short ) 0x10));   // 16 byte length
343          LittleEndian.putShort(data, 4 + offset, getVersion());
344          LittleEndian.putShort(data, 6 + offset, getType());
345          LittleEndian.putShort(data, 8 + offset, getBuild());
346          LittleEndian.putShort(data, 10 + offset, getBuildYear());
347          LittleEndian.putInt(data, 12 + offset, getHistoryBitMask());
348          LittleEndian.putInt(data, 16 + offset, getRequiredVersion());
349          return getRecordSize();
350      }
351  
352      public int getRecordSize()
353      {
354          return 20;
355      }
356  
357      public short getSid()
358      {
359          return this.sid;
360      }
361  }
362