KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > hssf > record > EscherAggregate


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

16
17 package org.apache.poi.hssf.record;
18
19 import org.apache.poi.ddf.*;
20 import org.apache.poi.hssf.usermodel.*;
21 import org.apache.poi.hssf.model.AbstractShape;
22 import org.apache.poi.hssf.model.TextboxShape;
23 import org.apache.poi.hssf.model.DrawingManager;
24 import org.apache.poi.hssf.model.ConvertAnchor;
25
26 import java.util.*;
27
28 /**
29  * This class is used to aggregate the MSODRAWING and OBJ record
30  * combinations. This is necessary due to the bizare way in which
31  * these records are serialized. What happens is that you get a
32  * combination of MSODRAWING -> OBJ -> MSODRAWING -> OBJ records
33  * but the escher records are serialized _across_ the MSODRAWING
34  * records.
35  * <p>
36  * It gets even worse when you start looking at TXO records.
37  * <p>
38  * So what we do with this class is aggregate lazily. That is
39  * we don't aggregate the MSODRAWING -> OBJ records unless we
40  * need to modify them.
41  *
42  *
43  * @author Glen Stampoultzis (glens at apache.org)
44  */

45 public class EscherAggregate extends AbstractEscherHolderRecord
46 {
47     public static final short sid = 9876;
48
49     public static final short ST_MIN = (short) 0;
50     public static final short ST_NOT_PRIMATIVE = ST_MIN;
51     public static final short ST_RECTANGLE = (short) 1;
52     public static final short ST_ROUNDRECTANGLE = (short) 2;
53     public static final short ST_ELLIPSE = (short) 3;
54     public static final short ST_DIAMOND = (short) 4;
55     public static final short ST_ISOCELESTRIANGLE = (short) 5;
56     public static final short ST_RIGHTTRIANGLE = (short) 6;
57     public static final short ST_PARALLELOGRAM = (short) 7;
58     public static final short ST_TRAPEZOID = (short) 8;
59     public static final short ST_HEXAGON = (short) 9;
60     public static final short ST_OCTAGON = (short) 10;
61     public static final short ST_PLUS = (short) 11;
62     public static final short ST_STAR = (short) 12;
63     public static final short ST_ARROW = (short) 13;
64     public static final short ST_THICKARROW = (short) 14;
65     public static final short ST_HOMEPLATE = (short) 15;
66     public static final short ST_CUBE = (short) 16;
67     public static final short ST_BALLOON = (short) 17;
68     public static final short ST_SEAL = (short) 18;
69     public static final short ST_ARC = (short) 19;
70     public static final short ST_LINE = (short) 20;
71     public static final short ST_PLAQUE = (short) 21;
72     public static final short ST_CAN = (short) 22;
73     public static final short ST_DONUT = (short) 23;
74     public static final short ST_TEXTSIMPLE = (short) 24;
75     public static final short ST_TEXTOCTAGON = (short) 25;
76     public static final short ST_TEXTHEXAGON = (short) 26;
77     public static final short ST_TEXTCURVE = (short) 27;
78     public static final short ST_TEXTWAVE = (short) 28;
79     public static final short ST_TEXTRING = (short) 29;
80     public static final short ST_TEXTONCURVE = (short) 30;
81     public static final short ST_TEXTONRING = (short) 31;
82     public static final short ST_STRAIGHTCONNECTOR1 = (short) 32;
83     public static final short ST_BENTCONNECTOR2 = (short) 33;
84     public static final short ST_BENTCONNECTOR3 = (short) 34;
85     public static final short ST_BENTCONNECTOR4 = (short) 35;
86     public static final short ST_BENTCONNECTOR5 = (short) 36;
87     public static final short ST_CURVEDCONNECTOR2 = (short) 37;
88     public static final short ST_CURVEDCONNECTOR3 = (short) 38;
89     public static final short ST_CURVEDCONNECTOR4 = (short) 39;
90     public static final short ST_CURVEDCONNECTOR5 = (short) 40;
91     public static final short ST_CALLOUT1 = (short) 41;
92     public static final short ST_CALLOUT2 = (short) 42;
93     public static final short ST_CALLOUT3 = (short) 43;
94     public static final short ST_ACCENTCALLOUT1 = (short) 44;
95     public static final short ST_ACCENTCALLOUT2 = (short) 45;
96     public static final short ST_ACCENTCALLOUT3 = (short) 46;
97     public static final short ST_BORDERCALLOUT1 = (short) 47;
98     public static final short ST_BORDERCALLOUT2 = (short) 48;
99     public static final short ST_BORDERCALLOUT3 = (short) 49;
100     public static final short ST_ACCENTBORDERCALLOUT1 = (short) 50;
101     public static final short ST_ACCENTBORDERCALLOUT2 = (short) 51;
102     public static final short ST_ACCENTBORDERCALLOUT3 = (short) 52;
103     public static final short ST_RIBBON = (short) 53;
104     public static final short ST_RIBBON2 = (short) 54;
105     public static final short ST_CHEVRON = (short) 55;
106     public static final short ST_PENTAGON = (short) 56;
107     public static final short ST_NOSMOKING = (short) 57;
108     public static final short ST_SEAL8 = (short) 58;
109     public static final short ST_SEAL16 = (short) 59;
110     public static final short ST_SEAL32 = (short) 60;
111     public static final short ST_WEDGERECTCALLOUT = (short) 61;
112     public static final short ST_WEDGERRECTCALLOUT = (short) 62;
113     public static final short ST_WEDGEELLIPSECALLOUT = (short) 63;
114     public static final short ST_WAVE = (short) 64;
115     public static final short ST_FOLDEDCORNER = (short) 65;
116     public static final short ST_LEFTARROW = (short) 66;
117     public static final short ST_DOWNARROW = (short) 67;
118     public static final short ST_UPARROW = (short) 68;
119     public static final short ST_LEFTRIGHTARROW = (short) 69;
120     public static final short ST_UPDOWNARROW = (short) 70;
121     public static final short ST_IRREGULARSEAL1 = (short) 71;
122     public static final short ST_IRREGULARSEAL2 = (short) 72;
123     public static final short ST_LIGHTNINGBOLT = (short) 73;
124     public static final short ST_HEART = (short) 74;
125     public static final short ST_PICTUREFRAME = (short) 75;
126     public static final short ST_QUADARROW = (short) 76;
127     public static final short ST_LEFTARROWCALLOUT = (short) 77;
128     public static final short ST_RIGHTARROWCALLOUT = (short) 78;
129     public static final short ST_UPARROWCALLOUT = (short) 79;
130     public static final short ST_DOWNARROWCALLOUT = (short) 80;
131     public static final short ST_LEFTRIGHTARROWCALLOUT = (short) 81;
132     public static final short ST_UPDOWNARROWCALLOUT = (short) 82;
133     public static final short ST_QUADARROWCALLOUT = (short) 83;
134     public static final short ST_BEVEL = (short) 84;
135     public static final short ST_LEFTBRACKET = (short) 85;
136     public static final short ST_RIGHTBRACKET = (short) 86;
137     public static final short ST_LEFTBRACE = (short) 87;
138     public static final short ST_RIGHTBRACE = (short) 88;
139     public static final short ST_LEFTUPARROW = (short) 89;
140     public static final short ST_BENTUPARROW = (short) 90;
141     public static final short ST_BENTARROW = (short) 91;
142     public static final short ST_SEAL24 = (short) 92;
143     public static final short ST_STRIPEDRIGHTARROW = (short) 93;
144     public static final short ST_NOTCHEDRIGHTARROW = (short) 94;
145     public static final short ST_BLOCKARC = (short) 95;
146     public static final short ST_SMILEYFACE = (short) 96;
147     public static final short ST_VERTICALSCROLL = (short) 97;
148     public static final short ST_HORIZONTALSCROLL = (short) 98;
149     public static final short ST_CIRCULARARROW = (short) 99;
150     public static final short ST_NOTCHEDCIRCULARARROW = (short) 100;
151     public static final short ST_UTURNARROW = (short) 101;
152     public static final short ST_CURVEDRIGHTARROW = (short) 102;
153     public static final short ST_CURVEDLEFTARROW = (short) 103;
154     public static final short ST_CURVEDUPARROW = (short) 104;
155     public static final short ST_CURVEDDOWNARROW = (short) 105;
156     public static final short ST_CLOUDCALLOUT = (short) 106;
157     public static final short ST_ELLIPSERIBBON = (short) 107;
158     public static final short ST_ELLIPSERIBBON2 = (short) 108;
159     public static final short ST_FLOWCHARTPROCESS = (short) 109;
160     public static final short ST_FLOWCHARTDECISION = (short) 110;
161     public static final short ST_FLOWCHARTINPUTOUTPUT = (short) 111;
162     public static final short ST_FLOWCHARTPREDEFINEDPROCESS = (short) 112;
163     public static final short ST_FLOWCHARTINTERNALSTORAGE = (short) 113;
164     public static final short ST_FLOWCHARTDOCUMENT = (short) 114;
165     public static final short ST_FLOWCHARTMULTIDOCUMENT = (short) 115;
166     public static final short ST_FLOWCHARTTERMINATOR = (short) 116;
167     public static final short ST_FLOWCHARTPREPARATION = (short) 117;
168     public static final short ST_FLOWCHARTMANUALINPUT = (short) 118;
169     public static final short ST_FLOWCHARTMANUALOPERATION = (short) 119;
170     public static final short ST_FLOWCHARTCONNECTOR = (short) 120;
171     public static final short ST_FLOWCHARTPUNCHEDCARD = (short) 121;
172     public static final short ST_FLOWCHARTPUNCHEDTAPE = (short) 122;
173     public static final short ST_FLOWCHARTSUMMINGJUNCTION = (short) 123;
174     public static final short ST_FLOWCHARTOR = (short) 124;
175     public static final short ST_FLOWCHARTCOLLATE = (short) 125;
176     public static final short ST_FLOWCHARTSORT = (short) 126;
177     public static final short ST_FLOWCHARTEXTRACT = (short) 127;
178     public static final short ST_FLOWCHARTMERGE = (short) 128;
179     public static final short ST_FLOWCHARTOFFLINESTORAGE = (short) 129;
180     public static final short ST_FLOWCHARTONLINESTORAGE = (short) 130;
181     public static final short ST_FLOWCHARTMAGNETICTAPE = (short) 131;
182     public static final short ST_FLOWCHARTMAGNETICDISK = (short) 132;
183     public static final short ST_FLOWCHARTMAGNETICDRUM = (short) 133;
184     public static final short ST_FLOWCHARTDISPLAY = (short) 134;
185     public static final short ST_FLOWCHARTDELAY = (short) 135;
186     public static final short ST_TEXTPLAINTEXT = (short) 136;
187     public static final short ST_TEXTSTOP = (short) 137;
188     public static final short ST_TEXTTRIANGLE = (short) 138;
189     public static final short ST_TEXTTRIANGLEINVERTED = (short) 139;
190     public static final short ST_TEXTCHEVRON = (short) 140;
191     public static final short ST_TEXTCHEVRONINVERTED = (short) 141;
192     public static final short ST_TEXTRINGINSIDE = (short) 142;
193     public static final short ST_TEXTRINGOUTSIDE = (short) 143;
194     public static final short ST_TEXTARCHUPCURVE = (short) 144;
195     public static final short ST_TEXTARCHDOWNCURVE = (short) 145;
196     public static final short ST_TEXTCIRCLECURVE = (short) 146;
197     public static final short ST_TEXTBUTTONCURVE = (short) 147;
198     public static final short ST_TEXTARCHUPPOUR = (short) 148;
199     public static final short ST_TEXTARCHDOWNPOUR = (short) 149;
200     public static final short ST_TEXTCIRCLEPOUR = (short) 150;
201     public static final short ST_TEXTBUTTONPOUR = (short) 151;
202     public static final short ST_TEXTCURVEUP = (short) 152;
203     public static final short ST_TEXTCURVEDOWN = (short) 153;
204     public static final short ST_TEXTCASCADEUP = (short) 154;
205     public static final short ST_TEXTCASCADEDOWN = (short) 155;
206     public static final short ST_TEXTWAVE1 = (short) 156;
207     public static final short ST_TEXTWAVE2 = (short) 157;
208     public static final short ST_TEXTWAVE3 = (short) 158;
209     public static final short ST_TEXTWAVE4 = (short) 159;
210     public static final short ST_TEXTINFLATE = (short) 160;
211     public static final short ST_TEXTDEFLATE = (short) 161;
212     public static final short ST_TEXTINFLATEBOTTOM = (short) 162;
213     public static final short ST_TEXTDEFLATEBOTTOM = (short) 163;
214     public static final short ST_TEXTINFLATETOP = (short) 164;
215     public static final short ST_TEXTDEFLATETOP = (short) 165;
216     public static final short ST_TEXTDEFLATEINFLATE = (short) 166;
217     public static final short ST_TEXTDEFLATEINFLATEDEFLATE = (short) 167;
218     public static final short ST_TEXTFADERIGHT = (short) 168;
219     public static final short ST_TEXTFADELEFT = (short) 169;
220     public static final short ST_TEXTFADEUP = (short) 170;
221     public static final short ST_TEXTFADEDOWN = (short) 171;
222     public static final short ST_TEXTSLANTUP = (short) 172;
223     public static final short ST_TEXTSLANTDOWN = (short) 173;
224     public static final short ST_TEXTCANUP = (short) 174;
225     public static final short ST_TEXTCANDOWN = (short) 175;
226     public static final short ST_FLOWCHARTALTERNATEPROCESS = (short) 176;
227     public static final short ST_FLOWCHARTOFFPAGECONNECTOR = (short) 177;
228     public static final short ST_CALLOUT90 = (short) 178;
229     public static final short ST_ACCENTCALLOUT90 = (short) 179;
230     public static final short ST_BORDERCALLOUT90 = (short) 180;
231     public static final short ST_ACCENTBORDERCALLOUT90 = (short) 181;
232     public static final short ST_LEFTRIGHTUPARROW = (short) 182;
233     public static final short ST_SUN = (short) 183;
234     public static final short ST_MOON = (short) 184;
235     public static final short ST_BRACKETPAIR = (short) 185;
236     public static final short ST_BRACEPAIR = (short) 186;
237     public static final short ST_SEAL4 = (short) 187;
238     public static final short ST_DOUBLEWAVE = (short) 188;
239     public static final short ST_ACTIONBUTTONBLANK = (short) 189;
240     public static final short ST_ACTIONBUTTONHOME = (short) 190;
241     public static final short ST_ACTIONBUTTONHELP = (short) 191;
242     public static final short ST_ACTIONBUTTONINFORMATION = (short) 192;
243     public static final short ST_ACTIONBUTTONFORWARDNEXT = (short) 193;
244     public static final short ST_ACTIONBUTTONBACKPREVIOUS = (short) 194;
245     public static final short ST_ACTIONBUTTONEND = (short) 195;
246     public static final short ST_ACTIONBUTTONBEGINNING = (short) 196;
247     public static final short ST_ACTIONBUTTONRETURN = (short) 197;
248     public static final short ST_ACTIONBUTTONDOCUMENT = (short) 198;
249     public static final short ST_ACTIONBUTTONSOUND = (short) 199;
250     public static final short ST_ACTIONBUTTONMOVIE = (short) 200;
251     public static final short ST_HOSTCONTROL = (short) 201;
252     public static final short ST_TEXTBOX = (short) 202;
253     public static final short ST_NIL = (short) 0x0FFF;
254
255     protected HSSFPatriarch patriarch;
256
257     /** Maps shape container objects to their OBJ records */
258     private Map shapeToObj = new HashMap();
259     private DrawingManager drawingManager;
260     private short drawingGroupId;
261
262     public EscherAggregate( DrawingManager drawingManager )
263     {
264         this.drawingManager = drawingManager;
265     }
266
267     /**
268      * @return Returns the current sid.
269      */

270     public short getSid()
271     {
272         return sid;
273     }
274
275     /**
276      * Unused since this is an aggregate record. Use createAggregate().
277      *
278      * @see #createAggregate
279      */

280     protected void fillFields( byte[] data, short size, int offset )
281     {
282         throw new IllegalStateException JavaDoc( "Should not reach here" );
283     }
284
285     /**
286      * Calculates the string representation of this record. This is
287      * simply a dump of all the records.
288      */

289     public String JavaDoc toString()
290     {
291         String JavaDoc nl = System.getProperty( "line.separtor" );
292
293         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
294         result.append( '[' ).append( getRecordName() ).append( ']' + nl );
295         for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); )
296         {
297             EscherRecord escherRecord = (EscherRecord) iterator.next();
298             result.append( escherRecord.toString() );
299         }
300         result.append( "[/" ).append( getRecordName() ).append( ']' + nl );
301
302         return result.toString();
303     }
304
305     /**
306      * Collapses the drawing records into an aggregate.
307      */

308     public static EscherAggregate createAggregate( List records, int locFirstDrawingRecord, DrawingManager drawingManager )
309     {
310         // Keep track of any shape records created so we can match them back to the object id's.
311
// Textbox objects are also treated as shape objects.
312
final List shapeRecords = new ArrayList();
313         EscherRecordFactory recordFactory = new DefaultEscherRecordFactory()
314         {
315             public EscherRecord createRecord( byte[] data, int offset )
316             {
317                 EscherRecord r = super.createRecord( data, offset );
318                 if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID || r.getRecordId() == EscherTextboxRecord.RECORD_ID )
319                 {
320                     shapeRecords.add( r );
321                 }
322                 return r;
323             }
324         };
325
326         // Calculate the size of the buffer
327
EscherAggregate agg = new EscherAggregate(drawingManager);
328         int loc = locFirstDrawingRecord;
329         int dataSize = 0;
330         while ( loc + 1 < records.size()
331                 && sid( records, loc ) == DrawingRecord.sid
332                 && isObjectRecord( records, loc + 1 ) )
333         {
334             dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length;
335             loc += 2;
336         }
337
338         // Create one big buffer
339
byte buffer[] = new byte[dataSize];
340         int offset = 0;
341         loc = locFirstDrawingRecord;
342         while ( loc + 1 < records.size()
343                 && sid( records, loc ) == DrawingRecord.sid
344                 && isObjectRecord( records, loc + 1 ) )
345         {
346             DrawingRecord drawingRecord = (DrawingRecord) records.get( loc );
347             System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length );
348             offset += drawingRecord.getData().length;
349             loc += 2;
350         }
351
352         // Decode the shapes
353
// agg.escherRecords = new ArrayList();
354
int pos = 0;
355         while ( pos < dataSize )
356         {
357             EscherRecord r = recordFactory.createRecord( buffer, pos );
358             int bytesRead = r.fillFields( buffer, pos, recordFactory );
359             agg.addEscherRecord( r );
360             pos += bytesRead;
361         }
362
363         // Associate the object records with the shapes
364
loc = locFirstDrawingRecord;
365         int shapeIndex = 0;
366         agg.shapeToObj = new HashMap();
367         while ( loc + 1 < records.size()
368                 && sid( records, loc ) == DrawingRecord.sid
369                 && isObjectRecord( records, loc + 1 ) )
370         {
371             Record objRecord = (Record) records.get( loc + 1 );
372             agg.shapeToObj.put( shapeRecords.get( shapeIndex++ ), objRecord );
373             loc += 2;
374         }
375
376         return agg;
377
378     }
379
380     /**
381      * Serializes this aggregate to a byte array. Since this is an aggregate
382      * record it will effectively serialize the aggregated records.
383      *
384      * @param offset The offset into the start of the array.
385      * @param data The byte array to serialize to.
386      * @return The number of bytes serialized.
387      */

388     public int serialize( int offset, byte[] data )
389     {
390         convertUserModelToRecords();
391
392         // Determine buffer size
393
List records = getEscherRecords();
394         int size = getEscherRecordSize( records );
395         byte[] buffer = new byte[size];
396
397
398         // Serialize escher records into one big data structure and keep note of ending offsets.
399
final List spEndingOffsets = new ArrayList();
400         final List shapes = new ArrayList();
401         int pos = 0;
402         for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
403         {
404             EscherRecord e = (EscherRecord) iterator.next();
405             pos += e.serialize( pos, buffer, new EscherSerializationListener()
406             {
407                 public void beforeRecordSerialize( int offset, short recordId, EscherRecord record )
408                 {
409                 }
410
411                 public void afterRecordSerialize( int offset, short recordId, int size, EscherRecord record )
412                 {
413                     if ( recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID )
414                     {
415                         spEndingOffsets.add( new Integer JavaDoc( offset ) );
416                         shapes.add( record );
417                     }
418                 }
419             } );
420         }
421         // todo: fix this
422
shapes.add( 0, null );
423         spEndingOffsets.add( 0, null );
424
425         // Split escher records into separate MSODRAWING and OBJ, TXO records. (We don't break on
426
// the first one because it's the patriach).
427
pos = offset;
428         for ( int i = 1; i < shapes.size(); i++ )
429         {
430             int endOffset = ( (Integer JavaDoc) spEndingOffsets.get( i ) ).intValue() - 1;
431             int startOffset;
432             if ( i == 1 )
433                 startOffset = 0;
434             else
435                 startOffset = ( (Integer JavaDoc) spEndingOffsets.get( i - 1 ) ).intValue();
436
437             // Create and write a new MSODRAWING record
438
DrawingRecord drawing = new DrawingRecord();
439             byte[] drawingData = new byte[endOffset - startOffset + 1];
440             System.arraycopy( buffer, startOffset, drawingData, 0, drawingData.length );
441             drawing.setData( drawingData );
442             int temp = drawing.serialize( pos, data );
443             pos += temp;
444
445             // Write the matching OBJ record
446
Record obj = (Record) shapeToObj.get( shapes.get( i ) );
447             temp = obj.serialize( pos, data );
448             pos += temp;
449
450         }
451
452         int bytesWritten = pos - offset;
453         if ( bytesWritten != getRecordSize() )
454             throw new RecordFormatException( bytesWritten + " bytes written but getRecordSize() reports " + getRecordSize() );
455         return bytesWritten;
456     }
457
458     /**
459      * How many bytes do the raw escher records contain.
460      * @param records List of escher records
461      * @return the number of bytes
462      */

463     private int getEscherRecordSize( List records )
464     {
465         int size = 0;
466         for ( Iterator iterator = records.iterator(); iterator.hasNext(); )
467             size += ( (EscherRecord) iterator.next() ).getRecordSize();
468         return size;
469     }
470
471     /**
472      * The number of bytes required to serialize this record.
473      */

474     public int getRecordSize()
475     {
476         convertUserModelToRecords();
477         List records = getEscherRecords();
478         int rawEscherSize = getEscherRecordSize( records );
479         int drawingRecordSize = rawEscherSize + ( shapeToObj.size() ) * 4;
480         int objRecordSize = 0;
481         for ( Iterator iterator = shapeToObj.values().iterator(); iterator.hasNext(); )
482         {
483             Record r = (Record) iterator.next();
484             objRecordSize += r.getRecordSize();
485         }
486         return drawingRecordSize + objRecordSize;
487     }
488
489     /**
490      * Associates an escher record to an OBJ record or a TXO record.
491      */

492     public Object JavaDoc assoicateShapeToObjRecord( EscherRecord r, Record objRecord )
493     {
494         return shapeToObj.put( r, objRecord );
495     }
496
497     public HSSFPatriarch getPatriarch()
498     {
499         return patriarch;
500     }
501
502     public void setPatriarch( HSSFPatriarch patriarch )
503     {
504         this.patriarch = patriarch;
505     }
506
507     public void clear()
508     {
509         clearEscherRecords();
510         shapeToObj.clear();
511 // lastShapeId = 1024;
512
}
513
514     protected String JavaDoc getRecordName()
515     {
516         return "ESCHERAGGREGATE";
517     }
518
519     // =============== Private methods ========================
520

521     private static boolean isObjectRecord( List records, int loc )
522     {
523         return sid( records, loc ) == ObjRecord.sid || sid( records, loc ) == TextObjectRecord.sid;
524     }
525
526     private void convertUserModelToRecords()
527     {
528         if ( patriarch != null )
529         {
530             shapeToObj.clear();
531             clearEscherRecords();
532             if ( patriarch.getChildren().size() != 0 )
533             {
534                 convertPatriarch( patriarch );
535                 EscherContainerRecord dgContainer = (EscherContainerRecord) getEscherRecord( 0 );
536                 EscherContainerRecord spgrContainer = null;
537                 for ( int i = 0; i < dgContainer.getChildRecords().size(); i++ )
538                     if ( dgContainer.getChild( i ).getRecordId() == EscherContainerRecord.SPGR_CONTAINER )
539                         spgrContainer = (EscherContainerRecord) dgContainer.getChild( i );
540                 convertShapes( patriarch, spgrContainer, shapeToObj );
541
542                 patriarch = null;
543             }
544         }
545     }
546
547     private void convertShapes( HSSFShapeContainer parent, EscherContainerRecord escherParent, Map shapeToObj )
548     {
549         if ( escherParent == null ) throw new IllegalArgumentException JavaDoc( "Parent record required" );
550
551         List shapes = parent.getChildren();
552         for ( Iterator iterator = shapes.iterator(); iterator.hasNext(); )
553         {
554             HSSFShape shape = (HSSFShape) iterator.next();
555             if ( shape instanceof HSSFShapeGroup )
556             {
557                 convertGroup( (HSSFShapeGroup) shape, escherParent, shapeToObj );
558             }
559             else
560             {
561                 AbstractShape shapeModel = AbstractShape.createShape(
562                         shape,
563                         drawingManager.allocateShapeId(drawingGroupId) );
564                 shapeToObj.put( findClientData( shapeModel.getSpContainer() ), shapeModel.getObjRecord() );
565                 if ( shapeModel instanceof TextboxShape )
566                 {
567                     EscherRecord escherTextbox = ( (TextboxShape) shapeModel ).getEscherTextbox();
568                     shapeToObj.put( escherTextbox, ( (TextboxShape) shapeModel ).getTextObjectRecord() );
569                     // escherParent.addChildRecord(escherTextbox);
570
}
571                 escherParent.addChildRecord( shapeModel.getSpContainer() );
572             }
573         }
574     }
575
576     private void convertGroup( HSSFShapeGroup shape, EscherContainerRecord escherParent, Map shapeToObj )
577     {
578         EscherContainerRecord spgrContainer = new EscherContainerRecord();
579         EscherContainerRecord spContainer = new EscherContainerRecord();
580         EscherSpgrRecord spgr = new EscherSpgrRecord();
581         EscherSpRecord sp = new EscherSpRecord();
582         EscherOptRecord opt = new EscherOptRecord();
583         EscherRecord anchor;
584         EscherClientDataRecord clientData = new EscherClientDataRecord();
585
586         spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
587         spgrContainer.setOptions( (short) 0x000F );
588         spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );
589         spContainer.setOptions( (short) 0x000F );
590         spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
591         spgr.setOptions( (short) 0x0001 );
592         spgr.setRectX1( shape.getX1() );
593         spgr.setRectY1( shape.getY1() );
594         spgr.setRectX2( shape.getX2() );
595         spgr.setRectY2( shape.getY2() );
596         sp.setRecordId( EscherSpRecord.RECORD_ID );
597         sp.setOptions( (short) 0x0002 );
598         int shapeId = drawingManager.allocateShapeId(drawingGroupId);
599         sp.setShapeId( shapeId );
600         if (shape.getAnchor() instanceof HSSFClientAnchor)
601             sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR );
602         else
603             sp.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_CHILD );
604         opt.setRecordId( EscherOptRecord.RECORD_ID );
605         opt.setOptions( (short) 0x0023 );
606         opt.addEscherProperty( new EscherBoolProperty( EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x00040004 ) );
607         opt.addEscherProperty( new EscherBoolProperty( EscherProperties.GROUPSHAPE__PRINT, 0x00080000 ) );
608
609         anchor = ConvertAnchor.createAnchor( shape.getAnchor() );
610 // clientAnchor.setCol1( ( (HSSFClientAnchor) shape.getAnchor() ).getCol1() );
611
// clientAnchor.setRow1( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow1() );
612
// clientAnchor.setDx1( (short) shape.getAnchor().getDx1() );
613
// clientAnchor.setDy1( (short) shape.getAnchor().getDy1() );
614
// clientAnchor.setCol2( ( (HSSFClientAnchor) shape.getAnchor() ).getCol2() );
615
// clientAnchor.setRow2( (short) ( (HSSFClientAnchor) shape.getAnchor() ).getRow2() );
616
// clientAnchor.setDx2( (short) shape.getAnchor().getDx2() );
617
// clientAnchor.setDy2( (short) shape.getAnchor().getDy2() );
618
clientData.setRecordId( EscherClientDataRecord.RECORD_ID );
619         clientData.setOptions( (short) 0x0000 );
620
621         spgrContainer.addChildRecord( spContainer );
622         spContainer.addChildRecord( spgr );
623         spContainer.addChildRecord( sp );
624         spContainer.addChildRecord( opt );
625         spContainer.addChildRecord( anchor );
626         spContainer.addChildRecord( clientData );
627
628         ObjRecord obj = new ObjRecord();
629         CommonObjectDataSubRecord cmo = new CommonObjectDataSubRecord();
630         cmo.setObjectType( CommonObjectDataSubRecord.OBJECT_TYPE_GROUP );
631         cmo.setObjectId( (short) ( shapeId ) );
632         cmo.setLocked( true );
633         cmo.setPrintable( true );
634         cmo.setAutofill( true );
635         cmo.setAutoline( true );
636         GroupMarkerSubRecord gmo = new GroupMarkerSubRecord();
637         EndSubRecord end = new EndSubRecord();
638         obj.addSubRecord( cmo );
639         obj.addSubRecord( gmo );
640         obj.addSubRecord( end );
641         shapeToObj.put( clientData, obj );
642
643         escherParent.addChildRecord( spgrContainer );
644
645         convertShapes( shape, spgrContainer, shapeToObj );
646
647     }
648
649     private EscherRecord findClientData( EscherContainerRecord spContainer )
650     {
651         for ( Iterator iterator = spContainer.getChildRecords().iterator(); iterator.hasNext(); )
652         {
653             EscherRecord r = (EscherRecord) iterator.next();
654             if ( r.getRecordId() == EscherClientDataRecord.RECORD_ID )
655                 return r;
656         }
657         throw new IllegalArgumentException JavaDoc( "Can not find client data record" );
658     }
659
660     private void convertPatriarch( HSSFPatriarch patriarch )
661     {
662         EscherContainerRecord dgContainer = new EscherContainerRecord();
663         EscherDgRecord dg;
664         EscherContainerRecord spgrContainer = new EscherContainerRecord();
665         EscherContainerRecord spContainer1 = new EscherContainerRecord();
666         EscherSpgrRecord spgr = new EscherSpgrRecord();
667         EscherSpRecord sp1 = new EscherSpRecord();
668
669         dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
670         dgContainer.setOptions( (short) 0x000F );
671         dg = drawingManager.createDgRecord();
672         drawingGroupId = dg.getDrawingGroupId();
673 // dg.setOptions( (short) ( drawingId << 4 ) );
674
// dg.setNumShapes( getNumberOfShapes( patriarch ) );
675
// dg.setLastMSOSPID( 0 ); // populated after all shape id's are assigned.
676
spgrContainer.setRecordId( EscherContainerRecord.SPGR_CONTAINER );
677         spgrContainer.setOptions( (short) 0x000F );
678         spContainer1.setRecordId( EscherContainerRecord.SP_CONTAINER );
679         spContainer1.setOptions( (short) 0x000F );
680         spgr.setRecordId( EscherSpgrRecord.RECORD_ID );
681         spgr.setOptions( (short) 0x0001 ); // don't know what the 1 is for.
682
spgr.setRectX1( patriarch.getX1() );
683         spgr.setRectY1( patriarch.getY1() );
684         spgr.setRectX2( patriarch.getX2() );
685         spgr.setRectY2( patriarch.getY2() );
686         sp1.setRecordId( EscherSpRecord.RECORD_ID );
687         sp1.setOptions( (short) 0x0002 );
688         sp1.setShapeId( drawingManager.allocateShapeId(dg.getDrawingGroupId()) );
689         sp1.setFlags( EscherSpRecord.FLAG_GROUP | EscherSpRecord.FLAG_PATRIARCH );
690
691         dgContainer.addChildRecord( dg );
692         dgContainer.addChildRecord( spgrContainer );
693         spgrContainer.addChildRecord( spContainer1 );
694         spContainer1.addChildRecord( spgr );
695         spContainer1.addChildRecord( sp1 );
696
697         addEscherRecord( dgContainer );
698     }
699
700     /** Retrieve the number of shapes (including the patriarch). */
701 // private int getNumberOfShapes( HSSFPatriarch patriarch )
702
// {
703
// return patriarch.countOfAllChildren();
704
// }
705

706     private static short sid( List records, int loc )
707     {
708         return ( (Record) records.get( loc ) ).getSid();
709     }
710
711
712 }
713
Popular Tags