KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > ddf > EscherRecord


1
2 /* ====================================================================
3    Copyright 2002-2004 Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 ==================================================================== */

17         
18 package org.apache.poi.ddf;
19
20 import org.apache.poi.util.LittleEndian;
21
22 import java.io.PrintWriter JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.List JavaDoc;
25
26 /**
27  * The base abstract record from which all escher records are defined. Subclasses will need
28  * to define methods for serialization/deserialization and for determining the record size.
29  *
30  * @author Glen Stampoultzis
31  */

32 abstract public class EscherRecord
33 {
34     private short options;
35     private short recordId;
36
37     /**
38      * Create a new instance
39      */

40     public EscherRecord()
41     {
42     }
43
44     /**
45      * Delegates to fillFields(byte[], int, EscherRecordFactory)
46      *
47      * @see #fillFields(byte[], int, org.apache.poi.ddf.EscherRecordFactory)
48      */

49     protected int fillFields( byte[] data, EscherRecordFactory f )
50     {
51         return fillFields( data, 0, f );
52     }
53
54     /**
55      * The contract of this method is to deserialize an escher record including
56      * it's children.
57      *
58      * @param data The byte array containing the serialized escher
59      * records.
60      * @param offset The offset into the byte array.
61      * @param recordFactory A factory for creating new escher records.
62      * @return The number of bytes written.
63      */

64     public abstract int fillFields( byte[] data, int offset, EscherRecordFactory recordFactory );
65
66     /**
67      * Reads the 8 byte header information and populates the <code>options</code>
68      * and <code>recordId</code> records.
69      *
70      * @param data the byte array to read from
71      * @param offset the offset to start reading from
72      * @return the number of bytes remaining in this record. This
73      * may include the children if this is a container.
74      */

75     protected int readHeader( byte[] data, int offset )
76     {
77         EscherRecordHeader header = EscherRecordHeader.readHeader(data, offset);
78         options = header.getOptions();
79         recordId = header.getRecordId();
80         return header.getRemainingBytes();
81     }
82
83     /**
84      * Determine whether this is a container record by inspecting the option
85      * field.
86      * @return true is this is a container field.
87      */

88     public boolean isContainerRecord()
89     {
90         return (options & (short)0x000f) == (short)0x000f;
91     }
92
93     /**
94      * @return The options field for this record. All records have one.
95      */

96     public short getOptions()
97     {
98         return options;
99     }
100
101     /**
102      * Set the options this this record. Container records should have the
103      * last nibble set to 0xF.
104      */

105     public void setOptions( short options )
106     {
107         this.options = options;
108     }
109
110     /**
111      * Serializes to a new byte array. This is done by delegating to
112      * serialize(int, byte[]);
113      *
114      * @return the serialized record.
115      * @see #serialize(int, byte[])
116      */

117     public byte[] serialize()
118     {
119         byte[] retval = new byte[getRecordSize()];
120
121         serialize( 0, retval );
122         return retval;
123     }
124
125     /**
126      * Serializes to an existing byte array without serialization listener.
127      * This is done by delegating to serialize(int, byte[], EscherSerializationListener).
128      *
129      * @param offset the offset within the data byte array.
130      * @param data the data array to serialize to.
131      * @return The number of bytes written.
132      *
133      * @see #serialize(int, byte[], org.apache.poi.ddf.EscherSerializationListener)
134      */

135     public int serialize( int offset, byte[] data)
136     {
137         return serialize( offset, data, new NullEscherSerializationListener() );
138     }
139
140     /**
141      * Serializes the record to an existing byte array.
142      *
143      * @param offset the offset within the byte array
144      * @param data the data array to serialize to
145      * @param listener a listener for begin and end serialization events. This
146      * is useful because the serialization is
147      * hierarchical/recursive and sometimes you need to be able
148      * break into that.
149      * @return the number of bytes written.
150      */

151     public abstract int serialize( int offset, byte[] data, EscherSerializationListener listener );
152
153     /**
154      * Subclasses should effeciently return the number of bytes required to
155      * serialize the record.
156      *
157      * @return number of bytes
158      */

159     abstract public int getRecordSize();
160
161     /**
162      * Return the current record id.
163      *
164      * @return The 16 bit record id.
165      */

166     public short getRecordId()
167     {
168         return recordId;
169     }
170
171     /**
172      * Sets the record id for this record.
173      */

174     public void setRecordId( short recordId )
175     {
176         this.recordId = recordId;
177     }
178
179     /**
180      * @return Returns the children of this record. By default this will
181      * be an empty list. EscherCotainerRecord is the only record
182      * that may contain children.
183      *
184      * @see EscherContainerRecord
185      */

186     public List JavaDoc getChildRecords() { return Collections.EMPTY_LIST; }
187
188     /**
189      * Sets the child records for this record. By default this will throw
190      * an exception as only EscherContainerRecords may have children.
191      *
192      * @param childRecords Not used in base implementation.
193      */

194     public void setChildRecords( List JavaDoc childRecords ) { throw new IllegalArgumentException JavaDoc("This record does not support child records."); }
195
196     /**
197      * Escher records may need to be clonable in the future.
198      */

199     public Object JavaDoc clone()
200     {
201         throw new RuntimeException JavaDoc( "The class " + getClass().getName() + " needs to define a clone method" );
202     }
203
204     /**
205      * Returns the indexed child record.
206      */

207     public EscherRecord getChild( int index )
208     {
209         return (EscherRecord) getChildRecords().get(index);
210     }
211
212     /**
213      * The display methods allows escher variables to print the record names
214      * according to their hierarchy.
215      *
216      * @param w The print writer to output to.
217      * @param indent The current indent level.
218      */

219     public void display(PrintWriter JavaDoc w, int indent)
220     {
221         for (int i = 0; i < indent * 4; i++) w.print(' ');
222         w.println(getRecordName());
223     }
224
225     /**
226      * Subclasses should return the short name for this escher record.
227      */

228     public abstract String JavaDoc getRecordName();
229
230     /**
231      * Returns the instance part of the option record.
232      *
233      * @return The instance part of the record
234      */

235     public short getInstance()
236     {
237         return (short) ( options >> 4 );
238     }
239
240     /**
241      * This class reads the standard escher header.
242      */

243     static class EscherRecordHeader
244     {
245         private short options;
246         private short recordId;
247         private int remainingBytes;
248
249         private EscherRecordHeader()
250         {
251         }
252
253         public static EscherRecordHeader readHeader( byte[] data, int offset )
254         {
255             EscherRecordHeader header = new EscherRecordHeader();
256             header.options = LittleEndian.getShort(data, offset);
257             header.recordId = LittleEndian.getShort(data, offset + 2);
258             header.remainingBytes = LittleEndian.getInt( data, offset + 4 );
259             return header;
260         }
261
262
263         public short getOptions()
264         {
265             return options;
266         }
267
268         public short getRecordId()
269         {
270             return recordId;
271         }
272
273         public int getRemainingBytes()
274         {
275             return remainingBytes;
276         }
277
278         public String JavaDoc toString()
279         {
280             return "EscherRecordHeader{" +
281                     "options=" + options +
282                     ", recordId=" + recordId +
283                     ", remainingBytes=" + remainingBytes +
284                     "}";
285         }
286
287
288     }
289
290 }
291
Popular Tags