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