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.BitField;
59   import org.apache.poi.util.LittleEndian;
60   
61   /**
62    * Title:        Row Record<P>
63    * Description:  stores the row information for the sheet. <P>
64    * REFERENCE:  PG 379 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P>
65    * @author Andrew C. Oliver (acoliver at apache dot org)
66    * @author Jason Height (jheight at chariot dot net dot au)
67    * @version 2.0-pre
68    */
69   
70   public class RowRecord
71       extends Record
72       implements Comparable
73   {
74       public final static short sid = 0x208;
75       //private short             field_1_row_number;
76       private int             field_1_row_number;
77       private short             field_2_first_col;
78       private short             field_3_last_col;   // plus 1
79       private short             field_4_height;
80       private short             field_5_optimize;   // hint field for gui, can/should be set to zero
81   
82       // for generated sheets.
83       private short             field_6_reserved;
84       private short             field_7_option_flags;
85       private BitField          outlineLevel  = new BitField(0x07);
86   
87       // bit 3 reserved
88       private BitField          colapsed      = new BitField(0x10);
89       private BitField          zeroHeight    = new BitField(0x20);
90       private BitField          badFontHeight = new BitField(0x40);
91       private BitField          formatted     = new BitField(0x80);
92       private short             field_8_xf_index;   // only if isFormatted
93   
94       public RowRecord()
95       {
96       }
97   
98       /**
99        * Constructs a Row record and sets its fields appropriately.
100       *
101       * @param id     id must be 0x208 or an exception will be throw upon validation
102       * @param size  the size of the data area of the record
103       * @param data  data of the record (should not contain sid/len)
104       */
105  
106      public RowRecord(short id, short size, byte [] data)
107      {
108          super(id, size, data);
109      }
110  
111      /**
112       * Constructs a Row record and sets its fields appropriately.
113       *
114       * @param id     id must be 0x208 or an exception will be throw upon validation
115       * @param size  the size of the data area of the record
116       * @param data  data of the record (should not contain sid/len)
117       * @param offset of the record data
118       */
119  
120      public RowRecord(short id, short size, byte [] data, int offset)
121      {
122          super(id, size, data, offset);
123      }
124  
125      protected void validateSid(short id)
126      {
127          if (id != sid)
128          {
129              throw new RecordFormatException("NOT A valid ROW RECORD");
130          }
131      }
132  
133      protected void fillFields(byte [] data, short size, int offset)
134      {
135          //field_1_row_number   = LittleEndian.getShort(data, 0 + offset);
136          field_1_row_number   = LittleEndian.getUShort(data, 0 + offset);
137          field_2_first_col    = LittleEndian.getShort(data, 2 + offset);
138          field_3_last_col     = LittleEndian.getShort(data, 4 + offset);
139          field_4_height       = LittleEndian.getShort(data, 6 + offset);
140          field_5_optimize     = LittleEndian.getShort(data, 8 + offset);
141          field_6_reserved     = LittleEndian.getShort(data, 10 + offset);
142          field_7_option_flags = LittleEndian.getShort(data, 12 + offset);
143          field_8_xf_index     = LittleEndian.getShort(data, 14 + offset);
144      }
145  
146      /**
147       * set the logical row number for this row (0 based index)
148       * @param row - the row number
149       */
150  
151      //public void setRowNumber(short row)
152      public void setRowNumber(int row)
153      {
154          field_1_row_number = row;
155      }
156  
157      /**
158       * set the logical col number for the first cell this row (0 based index)
159       * @param col - the col number
160       */
161  
162      public void setFirstCol(short col)
163      {
164          field_2_first_col = col;
165      }
166  
167      /**
168       * set the logical col number for the last cell this row (0 based index)
169       * @param col - the col number
170       */
171  
172      public void setLastCol(short col)
173      {
174          field_3_last_col = col;
175      }
176  
177      /**
178       * set the height of the row
179       * @param height of the row
180       */
181  
182      public void setHeight(short height)
183      {
184          field_4_height = height;
185      }
186  
187      /**
188       * set whether to optimize or not (set to 0)
189       * @param optimize (set to 0)
190       */
191  
192      public void setOptimize(short optimize)
193      {
194          field_5_optimize = optimize;
195      }
196  
197      /**
198       * sets the option bitmask.  (use the individual bit setters that refer to this
199       * method)
200       * @param options - the bitmask
201       */
202  
203      public void setOptionFlags(short options)
204      {
205          field_7_option_flags = options;
206      }
207  
208      // option bitfields
209  
210      /**
211       * set the outline level of this row
212       * @param ol - the outline level
213       * @see #setOptionFlags(short)
214       */
215  
216      public void setOutlineLevel(short ol)
217      {
218          field_7_option_flags =
219              outlineLevel.setShortValue(field_7_option_flags, ol);
220      }
221  
222      /**
223       * set whether or not to colapse this row
224       * @param c - colapse or not
225       * @see #setOptionFlags(short)
226       */
227  
228      public void setColapsed(boolean c)
229      {
230          field_7_option_flags = colapsed.setShortBoolean(field_7_option_flags,
231                  c);
232      }
233  
234      /**
235       * set whether or not to display this row with 0 height
236       * @param z  height is zero or not.
237       * @see #setOptionFlags(short)
238       */
239  
240      public void setZeroHeight(boolean z)
241      {
242          field_7_option_flags =
243              zeroHeight.setShortBoolean(field_7_option_flags, z);
244      }
245  
246      /**
247       * set whether the font and row height are not compatible
248       * @param  f  true if they aren't compatible (damn not logic)
249       * @see #setOptionFlags(short)
250       */
251  
252      public void setBadFontHeight(boolean f)
253      {
254          field_7_option_flags =
255              badFontHeight.setShortBoolean(field_7_option_flags, f);
256      }
257  
258      /**
259       * set whether the row has been formatted (even if its got all blank cells)
260       * @param f  formatted or not
261       * @see #setOptionFlags(short)
262       */
263  
264      public void setFormatted(boolean f)
265      {
266          field_7_option_flags = formatted.setShortBoolean(field_7_option_flags,
267                  f);
268      }
269  
270      // end bitfields
271  
272      /**
273       * if the row is formatted then this is the index to the extended format record
274       * @see org.apache.poi.hssf.record.ExtendedFormatRecord
275       * @param index to the XF record
276       */
277  
278      public void setXFIndex(short index)
279      {
280          field_8_xf_index = index;
281      }
282  
283      /**
284       * get the logical row number for this row (0 based index)
285       * @return row - the row number
286       */
287  
288      //public short getRowNumber()
289      public int getRowNumber()
290      {
291          return field_1_row_number;
292      }
293  
294      /**
295       * get the logical col number for the first cell this row (0 based index)
296       * @return col - the col number
297       */
298  
299      public short getFirstCol()
300      {
301          return field_2_first_col;
302      }
303  
304      /**
305       * get the logical col number for the last cell this row (0 based index)
306       * @return col - the col number
307       */
308  
309      public short getLastCol()
310      {
311          return field_3_last_col;
312      }
313  
314      /**
315       * get the height of the row
316       * @return height of the row
317       */
318  
319      public short getHeight()
320      {
321          return field_4_height;
322      }
323  
324      /**
325       * get whether to optimize or not (set to 0)
326       * @return optimize (set to 0)
327       */
328  
329      public short getOptimize()
330      {
331          return field_5_optimize;
332      }
333  
334      /**
335       * gets the option bitmask.  (use the individual bit setters that refer to this
336       * method)
337       * @return options - the bitmask
338       */
339  
340      public short getOptionFlags()
341      {
342          return field_7_option_flags;
343      }
344  
345      // option bitfields
346  
347      /**
348       * get the outline level of this row
349       * @return ol - the outline level
350       * @see #getOptionFlags()
351       */
352  
353      public short getOutlineLevel()
354      {
355          return outlineLevel.getShortValue(field_7_option_flags);
356      }
357  
358      /**
359       * get whether or not to colapse this row
360       * @return c - colapse or not
361       * @see #getOptionFlags()
362       */
363  
364      public boolean getColapsed()
365      {
366          return (colapsed.isSet(field_7_option_flags));
367      }
368  
369      /**
370       * get whether or not to display this row with 0 height
371       * @return - z height is zero or not.
372       * @see #getOptionFlags()
373       */
374  
375      public boolean getZeroHeight()
376      {
377          return zeroHeight.isSet(field_7_option_flags);
378      }
379  
380      /**
381       * get whether the font and row height are not compatible
382       * @return - f -true if they aren't compatible (damn not logic)
383       * @see #getOptionFlags()
384       */
385  
386      public boolean getBadFontHeight()
387      {
388          return badFontHeight.isSet(field_7_option_flags);
389      }
390  
391      /**
392       * get whether the row has been formatted (even if its got all blank cells)
393       * @return formatted or not
394       * @see #getOptionFlags()
395       */
396  
397      public boolean getFormatted()
398      {
399          return formatted.isSet(field_7_option_flags);
400      }
401  
402      // end bitfields
403  
404      /**
405       * if the row is formatted then this is the index to the extended format record
406       * @see org.apache.poi.hssf.record.ExtendedFormatRecord
407       * @return index to the XF record or bogus value (undefined) if isn't formatted
408       */
409  
410      public short getXFIndex()
411      {
412          return field_8_xf_index;
413      }
414  
415      public boolean isInValueSection()
416      {
417          return true;
418      }
419  
420      public String toString()
421      {
422          StringBuffer buffer = new StringBuffer();
423  
424          buffer.append("[ROW]\n");
425          buffer.append("    .rownumber      = ")
426              .append(Integer.toHexString(getRowNumber())).append("\n");
427          buffer.append("    .firstcol       = ")
428              .append(Integer.toHexString(getFirstCol())).append("\n");
429          buffer.append("    .lastcol        = ")
430              .append(Integer.toHexString(getLastCol())).append("\n");
431          buffer.append("    .height         = ")
432              .append(Integer.toHexString(getHeight())).append("\n");
433          buffer.append("    .optimize       = ")
434              .append(Integer.toHexString(getOptimize())).append("\n");
435          buffer.append("    .reserved       = ")
436              .append(Integer.toHexString(field_6_reserved)).append("\n");
437          buffer.append("    .optionflags    = ")
438              .append(Integer.toHexString(getOptionFlags())).append("\n");
439          buffer.append("        .outlinelvl = ")
440              .append(Integer.toHexString(getOutlineLevel())).append("\n");
441          buffer.append("        .colapsed   = ").append(getColapsed())
442              .append("\n");
443          buffer.append("        .zeroheight = ").append(getZeroHeight())
444              .append("\n");
445          buffer.append("        .badfontheig= ").append(getBadFontHeight())
446              .append("\n");
447          buffer.append("        .formatted  = ").append(getFormatted())
448              .append("\n");
449          buffer.append("    .xfindex        = ")
450              .append(Integer.toHexString(getXFIndex())).append("\n");
451          buffer.append("[/ROW]\n");
452          return buffer.toString();
453      }
454  
455      public int serialize(int offset, byte [] data)
456      {
457          LittleEndian.putShort(data, 0 + offset, sid);
458          LittleEndian.putShort(data, 2 + offset, ( short ) 16);
459          //LittleEndian.putShort(data, 4 + offset, getRowNumber());
460          LittleEndian.putShort(data, 4 + offset, ( short ) getRowNumber());
461          LittleEndian.putShort(data, 6 + offset, getFirstCol() == -1 ? (short)0 : getFirstCol());
462          LittleEndian.putShort(data, 8 + offset, getLastCol() == -1 ? (short)0 : getLastCol());
463          LittleEndian.putShort(data, 10 + offset, getHeight());
464          LittleEndian.putShort(data, 12 + offset, getOptimize());
465          LittleEndian.putShort(data, 14 + offset, field_6_reserved);
466          LittleEndian.putShort(data, 16 + offset, getOptionFlags());
467  
468  //    LittleEndian.putShort(data,18,getOutlineLevel());
469          LittleEndian.putShort(data, 18 + offset, getXFIndex());
470          return getRecordSize();
471      }
472  
473      public int getRecordSize()
474      {
475          return 20;
476      }
477  
478      public short getSid()
479      {
480          return this.sid;
481      }
482  
483      public int compareTo(Object obj)
484      {
485          RowRecord loc = ( RowRecord ) obj;
486  
487          if (this.getRowNumber() == loc.getRowNumber())
488          {
489              return 0;
490          }
491          if (this.getRowNumber() < loc.getRowNumber())
492          {
493              return -1;
494          }
495          if (this.getRowNumber() > loc.getRowNumber())
496          {
497              return 1;
498          }
499          return -1;
500      }
501  
502      public boolean equals(Object obj)
503      {
504          if (!(obj instanceof RowRecord))
505          {
506              return false;
507          }
508          RowRecord loc = ( RowRecord ) obj;
509  
510          if (this.getRowNumber() == loc.getRowNumber())
511          {
512              return true;
513          }
514          return false;
515      }
516  
517      public Object clone() {
518        RowRecord rec = new RowRecord();
519        rec.field_1_row_number = field_1_row_number;
520        rec.field_2_first_col = field_2_first_col;
521        rec.field_3_last_col = field_3_last_col;
522        rec.field_4_height = field_4_height;
523        rec.field_5_optimize = field_5_optimize;
524        rec.field_6_reserved = field_6_reserved;
525        rec.field_7_option_flags = field_7_option_flags;
526        rec.field_8_xf_index = field_8_xf_index;
527        return rec;
528      }
529  }
530