View | Details | Raw Unified | Return to bug 53372
Collapse All | Expand All

(-)src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java (-22 / +90 lines)
Lines 17-29 Link Here
17
package org.apache.poi.hssf.model;
17
package org.apache.poi.hssf.model;
18
18
19
import junit.framework.TestCase;
19
import junit.framework.TestCase;
20
import org.apache.poi.ddf.EscherContainerRecord;
20
import org.apache.poi.ddf.EscherDggRecord;
21
import org.apache.poi.ddf.EscherDggRecord;
22
import org.apache.poi.ddf.EscherRecord;
21
import org.apache.poi.hssf.HSSFTestDataSamples;
23
import org.apache.poi.hssf.HSSFTestDataSamples;
22
import org.apache.poi.hssf.record.*;
24
import org.apache.poi.hssf.record.*;
23
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
25
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
24
import org.apache.poi.hssf.usermodel.HSSFSheet;
26
import org.apache.poi.hssf.usermodel.*;
25
import org.apache.poi.hssf.usermodel.HSSFTestHelper;
26
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
27
import org.apache.poi.util.HexRead;
27
import org.apache.poi.util.HexRead;
28
28
29
import java.io.*;
29
import java.io.*;
Lines 35-53 Link Here
35
 * @author Evgeniy Berlog
35
 * @author Evgeniy Berlog
36
 */
36
 */
37
public class TestDrawingAggregate extends TestCase {
37
public class TestDrawingAggregate extends TestCase {
38
    private static byte[] toByteArray(List<RecordBase> records){
38
39
    private int spgrCount = 0;
40
    private int spCount = 0;
41
    private int shapeCount = 0;
42
    private int shGroupCount = 0;
43
44
    /*
45
     * EscherAggregate must have for each SpgrContainer HSSFShapeGroup and for each SpContainer HSSFShape
46
     */
47
    private void checkEscherAndShapesCount(EscherAggregate agg, HSSFSheet sheet) {
48
        /*
49
        HSSFPatriarch patriarch = HSSFTestHelper.createTestPatriarch(sheet, agg);
50
        agg.setPatriarch(patriarch);
51
        EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg);
52
        EscherContainerRecord mainContainer = EscherAggregate.getMainSpgrContainer(agg);
53
        calculateShapesCount(agg.getPatriarch());
54
        calculateEscherContainersCount(mainContainer);
55
56
        assertEquals(spgrCount, shGroupCount);
57
        assertEquals(spCount - spgrCount - 1, shapeCount);
58
        */
59
    }
60
61
    private void calculateEscherContainersCount(EscherContainerRecord spgr) {
62
        for (EscherRecord record : spgr.getChildRecords()) {
63
            if (EscherContainerRecord.SP_CONTAINER == record.getRecordId()) {
64
                spCount++;
65
                continue;
66
            }
67
            if (EscherContainerRecord.SPGR_CONTAINER == record.getRecordId()) {
68
                spgrCount++;
69
                calculateEscherContainersCount((EscherContainerRecord) record);
70
            }
71
        }
72
    }
73
74
    private void calculateShapesCount(HSSFShapeContainer group) {
75
        for (HSSFShape shape : (List<HSSFShape>) group.getChildren()) {
76
            if (shape instanceof HSSFShapeGroup) {
77
                shGroupCount++;
78
                calculateShapesCount((HSSFShapeGroup) shape);
79
            } else {
80
                shapeCount++;
81
            }
82
        }
83
    }
84
85
39
            ByteArrayOutputStream out = new ByteArrayOutputStream();
86
    private static byte[] toByteArray(List<RecordBase> records) {
40
            for(RecordBase rb : records) {
87
        ByteArrayOutputStream out = new ByteArrayOutputStream();
41
                    Record r = (Record)rb;
88
        for (RecordBase rb : records) {
42
                    try {
89
            Record r = (Record) rb;
43
                            out.write(r.serialize());
44
                        } catch (IOException e){
90
            try {
91
                out.write(r.serialize());
45
                            throw new RuntimeException(e);
92
            } catch (IOException e) {
46
                        }
47
                }
48
            return out.toByteArray();
49
        }
93
                throw new RuntimeException(e);
94
            }
95
        }
96
        return out.toByteArray();
97
    }
50
98
99
    public void testSolverContainerMustBeSavedDuringSerialization(){
100
        HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SolverContainerAfterSPGR.xls");
101
        HSSFSheet sh = wb.getSheetAt(0);
102
        InternalSheet ish = HSSFTestHelper.getSheetForTest(sh);
103
        sh.getDrawingPatriarch();
104
        EscherAggregate agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
105
        assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3);
106
        assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER);
107
        wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
108
        sh = wb.getSheetAt(0);
109
        sh.getDrawingPatriarch();
110
        ish = HSSFTestHelper.getSheetForTest(sh);
111
        agg = (EscherAggregate) ish.findFirstRecordBySid(EscherAggregate.sid);
112
        assertEquals(agg.getEscherRecords().get(0).getChildRecords().size(), 3);
113
        assertEquals(agg.getEscherRecords().get(0).getChild(2).getRecordId(), EscherContainerRecord.SOLVER_CONTAINER);
114
115
    }
116
51
    /**
117
    /**
52
     * test reading drawing aggregate from a test file from Bugzilla 45129
118
     * test reading drawing aggregate from a test file from Bugzilla 45129
53
     */
119
     */
Lines 107-112 Link Here
107
        byte[] dgBytesAfterSave = agg.serialize();
173
        byte[] dgBytesAfterSave = agg.serialize();
108
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
174
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
109
        assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
175
        assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
176
        checkEscherAndShapesCount(agg, sh);
110
    }
177
    }
111
178
112
    /**
179
    /**
Lines 174-180 Link Here
174
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
241
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
175
        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
242
        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
176
243
177
244
        checkEscherAndShapesCount(agg, sh);
178
    }
245
    }
179
246
180
247
Lines 185-205 Link Here
185
        List<RecordBase> records = isheet.getRecords();
252
        List<RecordBase> records = isheet.getRecords();
186
253
187
        HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb);
254
        HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb);
188
        InternalSheet isheet2 = HSSFTestHelper.getSheetForTest( wb2.getSheetAt(0));
255
        InternalSheet isheet2 = HSSFTestHelper.getSheetForTest(wb2.getSheetAt(0));
189
        List<RecordBase> records2 = isheet2.getRecords();
256
        List<RecordBase> records2 = isheet2.getRecords();
190
257
191
        assertEquals(records.size(), records2.size());
258
        assertEquals(records.size(), records2.size());
192
        for(int i = 0; i < records.size(); i++) {
259
        for (int i = 0; i < records.size(); i++) {
193
            RecordBase r1 = records.get(i);
260
            RecordBase r1 = records.get(i);
194
            RecordBase r2 = records2.get(i);
261
            RecordBase r2 = records2.get(i);
195
            assertTrue(r1.getClass() == r2.getClass());
262
            assertTrue(r1.getClass() == r2.getClass());
196
            assertEquals(r1.getRecordSize(), r2.getRecordSize());
263
            assertEquals(r1.getRecordSize(), r2.getRecordSize());
197
            if(r1 instanceof Record ){
264
            if (r1 instanceof Record) {
198
                assertEquals(((Record)r1).getSid(), ((Record)r2).getSid());
265
                assertEquals(((Record) r1).getSid(), ((Record) r2).getSid());
199
                assertTrue(Arrays.equals(((Record) r1).serialize(), ((Record) r2).serialize()));
266
                assertTrue(Arrays.equals(((Record) r1).serialize(), ((Record) r2).serialize()));
200
            }
267
            }
201
        }
268
        }
202
203
    }
269
    }
204
270
205
    public void testSerializeDrawingWithComments() throws IOException {
271
    public void testSerializeDrawingWithComments() throws IOException {
Lines 257-262 Link Here
257
        byte[] dgBytesAfterSave = agg.serialize();
323
        byte[] dgBytesAfterSave = agg.serialize();
258
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
324
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
259
        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
325
        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
326
        checkEscherAndShapesCount(agg, sh);
260
    }
327
    }
261
328
262
329
Lines 314-320 Link Here
314
381
315
        byte[] dgBytesAfterSave = agg.serialize();
382
        byte[] dgBytesAfterSave = agg.serialize();
316
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
383
        assertEquals("different size of drawing data before and after save", dgBytes.length, dgBytesAfterSave.length);
317
        assertTrue("drawing data brefpore and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
384
        assertTrue("drawing data before and after save is different", Arrays.equals(dgBytes, dgBytesAfterSave));
385
        checkEscherAndShapesCount(agg, sh);
318
    }
386
    }
319
387
320
    public void testUnhandledContinue() {
388
    public void testUnhandledContinue() {
(-)src/java/org/apache/poi/hssf/usermodel/HSSFClientAnchor.java (+8 lines)
Lines 17-22 Link Here
17
17
18
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
19
19
20
import org.apache.poi.ddf.EscherClientAnchorRecord;
20
import org.apache.poi.ss.usermodel.ClientAnchor;
21
import org.apache.poi.ss.usermodel.ClientAnchor;
21
22
22
23
Lines 33-38 Link Here
33
    int row2;
34
    int row2;
34
    int anchorType;
35
    int anchorType;
35
36
37
    private EscherClientAnchorRecord escherClientAnchorRecord;
38
39
    public HSSFClientAnchor(EscherClientAnchorRecord escherClientAnchorRecord) {
40
        this.escherClientAnchorRecord = escherClientAnchorRecord;
41
        //TODO set properties or read properties from EscherRecord ?
42
    }
43
36
    /**
44
    /**
37
     * Creates a new client anchor and defaults all the anchor positions to 0.
45
     * Creates a new client anchor and defaults all the anchor positions to 0.
38
     */
46
     */
(-)src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java (-1 / +22 lines)
Lines 22-30 Link Here
22
import java.util.List;
22
import java.util.List;
23
23
24
import org.apache.poi.ddf.EscherComplexProperty;
24
import org.apache.poi.ddf.EscherComplexProperty;
25
import org.apache.poi.ddf.EscherContainerRecord;
25
import org.apache.poi.ddf.EscherOptRecord;
26
import org.apache.poi.ddf.EscherOptRecord;
26
import org.apache.poi.ddf.EscherProperty;
27
import org.apache.poi.ddf.EscherProperty;
27
import org.apache.poi.ddf.EscherBSERecord;
28
import org.apache.poi.ddf.EscherBSERecord;
29
import org.apache.poi.ddf.EscherSpgrRecord;
28
import org.apache.poi.hssf.record.EscherAggregate;
30
import org.apache.poi.hssf.record.EscherAggregate;
29
import org.apache.poi.ss.usermodel.Chart;
31
import org.apache.poi.ss.usermodel.Chart;
30
import org.apache.poi.util.StringUtil;
32
import org.apache.poi.util.StringUtil;
Lines 314-317 Link Here
314
		throw new RuntimeException("NotImplemented");
316
		throw new RuntimeException("NotImplemented");
315
	}
317
	}
316
318
317
}
319
320
    void buildShapeTree(){
321
        EscherContainerRecord dgContainer = _boundAggregate.getEscherContainer();
322
        EscherContainerRecord spgrConrainer = dgContainer.getChildContainers().get(0);
323
        List<EscherContainerRecord> spgrChildren = spgrConrainer.getChildContainers();
324
325
        for(int i = 0; i < spgrChildren.size(); i++){
326
            EscherContainerRecord spContainer = spgrChildren.get(i);
327
            if (i == 0){
328
                EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
329
                setCoordinates(
330
                        spgr.getRectX1(), spgr.getRectY1(),
331
                        spgr.getRectX2(), spgr.getRectY2()
332
                );
333
            } else {
334
                HSSFShapeFactory.createShapeTree(spContainer, _boundAggregate, this);
335
            }
336
        }
337
    }
338
}
(-)src/java/org/apache/poi/hssf/usermodel/HSSFRectangle.java (+15 lines)
Line 0 Link Here
1
package org.apache.poi.hssf.usermodel;
2
3
import org.apache.poi.ddf.EscherContainerRecord;
4
import org.apache.poi.hssf.record.ObjRecord;
5
6
/**
7
 * @author Evgeniy Berlog
8
 * @date 08.06.12
9
 */
10
public class HSSFRectangle extends HSSFShape{
11
12
    public HSSFRectangle(EscherContainerRecord spContainer, ObjRecord objRecord) {
13
        super(spContainer, objRecord);
14
    }
15
}
(-)src/java/org/apache/poi/hssf/usermodel/HSSFChildAnchor.java (+9 lines)
Lines 18-24 Link Here
18
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
19
19
20
20
21
import org.apache.poi.ddf.EscherChildAnchorRecord;
22
21
public final class HSSFChildAnchor extends HSSFAnchor {
23
public final class HSSFChildAnchor extends HSSFAnchor {
24
25
    private EscherChildAnchorRecord escherChildAnchorRecord;
26
27
    public HSSFChildAnchor(EscherChildAnchorRecord escherChildAnchorRecord) {
28
        this.escherChildAnchorRecord = escherChildAnchorRecord;
29
    }
30
22
    public HSSFChildAnchor()
31
    public HSSFChildAnchor()
23
    {
32
    {
24
    }
33
    }
(-)src/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java (+11 lines)
Lines 31-34 Link Here
31
     */
31
     */
32
    List getChildren();
32
    List getChildren();
33
33
34
    /**
35
     * add shape to the list of child records
36
     * @param shape
37
     */
38
    public void addShape(HSSFShape shape);
39
40
    /**
41
     * set coordinates of this group relative to the parent
42
     */
43
    void setCoordinates( int x1, int y1, int x2, int y2 );
44
34
}
45
}
(-)src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (-2 / +6 lines)
Lines 1738-1749 Link Here
1738
        if(agg == null) return null;
1738
        if(agg == null) return null;
1739
1739
1740
        _patriarch = new HSSFPatriarch(this, agg);
1740
        _patriarch = new HSSFPatriarch(this, agg);
1741
        agg.setPatriarch(_patriarch);
1741
        _patriarch.buildShapeTree();
1742
1742
1743
        //HSSFShapeFactory.createShapeTree();
1744
        //agg.setPatriarch(_patriarch);
1745
        //EscherAggregate.createShapeTree(EscherAggregate.getMainSpgrContainer(agg), agg.getPatriarch(), agg);
1746
1743
        // Have it process the records into high level objects
1747
        // Have it process the records into high level objects
1744
        //  as best it can do (this step may eat anything
1748
        //  as best it can do (this step may eat anything
1745
        //  that isn't supported, you were warned...)
1749
        //  that isn't supported, you were warned...)
1746
        agg.convertRecordsToUserModel();
1750
//        agg.convertRecordsToUserModel();
1747
1751
1748
        // Return what we could cope with
1752
        // Return what we could cope with
1749
        return _patriarch;
1753
        return _patriarch;
(-)src/java/org/apache/poi/hssf/usermodel/HSSFUnknownShape.java (+33 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 *    contributor license agreements.  See the NOTICE file distributed with
4
 *    this work for additional information regarding copyright ownership.
5
 *    The ASF licenses this file to You under the Apache License, Version 2.0
6
 *    (the "License"); you may not use this file except in compliance with
7
 *    the License.  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.hssf.usermodel;
19
20
import org.apache.poi.ddf.EscherContainerRecord;
21
import org.apache.poi.ddf.EscherRecord;
22
import org.apache.poi.hssf.record.ObjRecord;
23
24
/**
25
 * @author Evgeniy Berlog
26
 * date: 05.06.12
27
 */
28
public class HSSFUnknownShape extends HSSFShape {
29
30
    public HSSFUnknownShape(EscherRecord spContainer, ObjRecord objRecord) {
31
        super((EscherContainerRecord) spContainer, objRecord);
32
    }
33
}
(-)src/java/org/apache/poi/hssf/usermodel/HSSFShapeGroup.java (+40 lines)
Lines 17-22 Link Here
17
17
18
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
19
19
20
import org.apache.poi.ddf.EscherChildAnchorRecord;
21
import org.apache.poi.ddf.EscherClientAnchorRecord;
22
import org.apache.poi.ddf.EscherContainerRecord;
23
import org.apache.poi.ddf.EscherRecord;
24
import org.apache.poi.ddf.EscherSpgrRecord;
25
import org.apache.poi.hssf.model.TextboxShape;
26
import org.apache.poi.hssf.record.EscherAggregate;
27
import org.apache.poi.hssf.record.ObjRecord;
28
20
import java.util.ArrayList;
29
import java.util.ArrayList;
21
import java.util.List;
30
import java.util.List;
22
import java.util.Iterator;
31
import java.util.Iterator;
Lines 37-43 Link Here
37
    int x2 = 1023;
46
    int x2 = 1023;
38
    int y2 = 255;
47
    int y2 = 255;
39
48
49
    public HSSFShapeGroup(EscherContainerRecord spgrContainer, ObjRecord objRecord) {
50
        super(spgrContainer, objRecord);
40
51
52
        // read internal and external coordinates from spgrContainer
53
        EscherContainerRecord spContainer = spgrContainer.getChildContainers().get(0);
54
        for(EscherRecord ch : spContainer.getChildRecords()){
55
            switch(ch.getRecordId()) {
56
                case EscherSpgrRecord.RECORD_ID:
57
                    EscherSpgrRecord spgr = (EscherSpgrRecord)ch;
58
                    setCoordinates(
59
                            spgr.getRectX1(), spgr.getRectY1(),
60
                            spgr.getRectX2(), spgr.getRectY2()
61
                    );
62
                    break;
63
                case EscherClientAnchorRecord.RECORD_ID:
64
                    this.anchor = EscherAggregate.toClientAnchor((EscherClientAnchorRecord)ch);
65
                    // TODO anchor = new HSSFClientAnchor((EscherChildAnchorRecord)ch);
66
                    break;
67
                case EscherChildAnchorRecord.RECORD_ID:
68
                    this.anchor = EscherAggregate.toChildAnchor((EscherChildAnchorRecord)ch);
69
                    // TODO anchor = new HSSFChildAnchor((EscherClientAnchorRecord)ch);
70
                    break;
71
            }
72
        }
73
74
    }
75
41
    public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor )
76
    public HSSFShapeGroup( HSSFShape parent, HSSFAnchor anchor )
42
    {
77
    {
43
        super( parent, anchor );
78
        super( parent, anchor );
Lines 61-66 Link Here
61
        shapes.add(shape);
96
        shapes.add(shape);
62
    }
97
    }
63
98
99
    public void addTextBox(TextboxShape textboxShape){
100
//        HSSFTextbox shape = new HSSFTextbox(this, textboxShape.geanchor);
101
//        shapes.add(textboxShape);
102
    }
103
64
    /**
104
    /**
65
     * Create a new simple shape under this group.
105
     * Create a new simple shape under this group.
66
     * @param anchor    the position of the shape.
106
     * @param anchor    the position of the shape.
(-)src/java/org/apache/poi/hssf/usermodel/HSSFShapeFactory.java (+157 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 *    contributor license agreements.  See the NOTICE file distributed with
4
 *    this work for additional information regarding copyright ownership.
5
 *    The ASF licenses this file to You under the Apache License, Version 2.0
6
 *    (the "License"); you may not use this file except in compliance with
7
 *    the License.  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.hssf.usermodel;
19
20
import org.apache.poi.ddf.EscherClientDataRecord;
21
import org.apache.poi.ddf.EscherContainerRecord;
22
import org.apache.poi.ddf.EscherRecord;
23
import org.apache.poi.ddf.EscherSpRecord;
24
import org.apache.poi.ddf.EscherSpgrRecord;
25
import org.apache.poi.ddf.EscherTextboxRecord;
26
import org.apache.poi.hssf.model.TextboxShape;
27
import org.apache.poi.hssf.record.CommonObjectDataSubRecord;
28
import org.apache.poi.hssf.record.EscherAggregate;
29
import org.apache.poi.hssf.record.NoteRecord;
30
import org.apache.poi.hssf.record.ObjRecord;
31
import org.apache.poi.hssf.record.Record;
32
import org.apache.poi.hssf.record.TextObjectRecord;
33
import org.apache.poi.hssf.usermodel.drawing.HSSFShapeType;
34
35
import java.lang.reflect.Constructor;
36
import java.lang.reflect.InvocationTargetException;
37
import java.util.HashMap;
38
import java.util.List;
39
import java.util.Map;
40
41
/**
42
 * @author evgeniy
43
 * date: 05.06.12
44
 */
45
public class HSSFShapeFactory {
46
47
    private static final Map<Short, Class> shapeTypeToClass = new HashMap<Short, Class>(HSSFShapeType.values().length);
48
    private static final ReflectionConstructorShapeCreator shapeCreator = new ReflectionConstructorShapeCreator(shapeTypeToClass);
49
50
    static {
51
        for (HSSFShapeType type: HSSFShapeType.values()){
52
            shapeTypeToClass.put(type.getType(), type.getShape());
53
        }
54
    }
55
56
    private static class ReflectionConstructorShapeCreator {
57
58
        private final Map<Short, Class> shapeTypeToClass;
59
60
        private ReflectionConstructorShapeCreator(Map<Short, Class> shapeTypeToClass) {
61
            this.shapeTypeToClass = shapeTypeToClass;
62
        }
63
64
        public HSSFShape createNewShape(Short type, EscherContainerRecord spContainer, ObjRecord objRecord){
65
            if (!shapeTypeToClass.containsKey(type)){
66
                return new HSSFUnknownShape(spContainer, objRecord);
67
            }
68
            Class clazz = shapeTypeToClass.get(type);
69
            if (null == clazz){
70
                System.out.println("No class attached to shape type: "+type);
71
                return new HSSFUnknownShape(spContainer, objRecord);
72
            }
73
            try{
74
                Constructor constructor = clazz.getConstructor(new Class[]{EscherContainerRecord.class, ObjRecord.class});
75
                return (HSSFShape) constructor.newInstance(spContainer, objRecord);
76
            } catch (NoSuchMethodException e) {
77
                throw new IllegalStateException(clazz.getName() +" doesn't have required for shapes constructor");
78
            } catch (Exception e) {
79
                throw new IllegalStateException("Couldn't create new instance of " + clazz.getName());
80
            }
81
        }
82
    }
83
84
    public static HSSFShape createShape(EscherRecord container, ObjRecord objRecord){
85
        if (0 == container.getChildRecords().size()){
86
            throw new IllegalArgumentException("Couldn't create shape from empty escher container");
87
        }
88
        if (container.getChild(0) instanceof EscherSpgrRecord){
89
            return new HSSFShapeGroup((EscherContainerRecord) container, objRecord);
90
        }
91
92
        //TODO implement cases for all shapes
93
        return new HSSFUnknownShape(container, objRecord);
94
    }
95
96
    public static HSSFShapeGroup createShapeGroup(){
97
        return null;
98
    }
99
100
    public static HSSFShapeGroup createSimpleShape(EscherRecord container, ObjRecord objRecord){
101
        return null;
102
    }
103
104
    public static void createShapeTree(EscherContainerRecord container, EscherAggregate agg, HSSFShapeContainer out){
105
        if(container.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){
106
            HSSFShapeGroup group = new HSSFShapeGroup(container,
107
                    null /* shape containers don't have a associated Obj record*/);
108
            List<EscherContainerRecord> children = container.getChildContainers();
109
            // skip the first child record, it is group descriptor
110
            for(int i = 0; i < children.size(); i++) {
111
                EscherContainerRecord spContainer = children.get(i);
112
                if(i == 0){
113
                    EscherSpgrRecord spgr = (EscherSpgrRecord)spContainer.getChildById(EscherSpgrRecord.RECORD_ID);
114
                    group.setCoordinates(
115
                            spgr.getRectX1(), spgr.getRectY1(),
116
                            spgr.getRectX2(), spgr.getRectY2()
117
                    );
118
                } else {
119
                    createShapeTree(spContainer, agg, group);
120
                }
121
            }
122
            out.addShape(group);
123
        } else if (container.getRecordId() == EscherContainerRecord.SP_CONTAINER){
124
            Map<EscherRecord, Record> shapeToObj = agg.getShapeToObjMapping();
125
            EscherSpRecord spRecord = null;
126
            ObjRecord objRecord = null;
127
            TextObjectRecord txtRecord = null;
128
129
            for(EscherRecord record : container.getChildRecords()) {
130
                switch(record.getRecordId()) {
131
                    case EscherSpRecord.RECORD_ID:
132
                        spRecord = (EscherSpRecord)record;
133
                        break;
134
                    case EscherClientDataRecord.RECORD_ID:
135
                        objRecord = (ObjRecord)shapeToObj.get(record);
136
                        break;
137
                    case EscherTextboxRecord.RECORD_ID:
138
                        txtRecord = (TextObjectRecord)shapeToObj.get(record);
139
                        break;
140
                }
141
            }
142
            if (null != objRecord){
143
                HSSFShape shape = shapeCreator.createNewShape(spRecord.getShapeType(), container, objRecord);
144
                out.addShape(shape);
145
            }
146
            if (null != txtRecord){
147
                //TODO resolve textbox
148
                TextboxShape shape = new TextboxShape(container, txtRecord);
149
//                out.a
150
            }
151
//
152
//            //TODO decide what shape to create based on ObjRecord / EscherSpRecord
153
//            HSSFShape shape = new HSSFUnknownShape(container, objRecord);
154
//            out.addShape(shape);
155
        }
156
    }
157
}
(-)src/testcases/org/apache/poi/hssf/usermodel/HSSFTestHelper.java (-1 / +6 lines)
Lines 18-23 Link Here
18
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
19
import org.apache.poi.hssf.model.InternalSheet;
19
import org.apache.poi.hssf.model.InternalSheet;
20
import org.apache.poi.hssf.model.InternalWorkbook;
20
import org.apache.poi.hssf.model.InternalWorkbook;
21
import org.apache.poi.hssf.record.EscherAggregate;
21
22
22
/**
23
/**
23
 * Helper class for HSSF tests that aren't within the
24
 * Helper class for HSSF tests that aren't within the
Lines 34-37 Link Here
34
	public static InternalSheet getSheetForTest(HSSFSheet sheet) {
35
	public static InternalSheet getSheetForTest(HSSFSheet sheet) {
35
		return sheet.getSheet();
36
		return sheet.getSheet();
36
	}
37
	}
37
}
38
39
    public static HSSFPatriarch createTestPatriarch(HSSFSheet sheet, EscherAggregate agg){
40
        return new HSSFPatriarch(sheet, agg);
41
    }
42
}
(-)src/java/org/apache/poi/hssf/usermodel/HSSFShape.java (-2 / +20 lines)
Lines 17-22 Link Here
17
17
18
package org.apache.poi.hssf.usermodel;
18
package org.apache.poi.hssf.usermodel;
19
19
20
import org.apache.poi.ddf.EscherContainerRecord;
21
import org.apache.poi.hssf.record.ObjRecord;
22
20
/**
23
/**
21
 * An abstract shape.
24
 * An abstract shape.
22
 *
25
 *
Lines 40-46 Link Here
40
    public static final int LINESTYLE_NONE = -1;
43
    public static final int LINESTYLE_NONE = -1;
41
44
42
    // TODO - make all these fields private
45
    // TODO - make all these fields private
43
    final HSSFShape parent;  
46
    HSSFShape parent;
44
    HSSFAnchor anchor;
47
    HSSFAnchor anchor;
45
    HSSFPatriarch _patriarch;  
48
    HSSFPatriarch _patriarch;  
46
    private int _lineStyleColor = 0x08000040;
49
    private int _lineStyleColor = 0x08000040;
Lines 49-63 Link Here
49
    private int _lineStyle = LINESTYLE_SOLID;
52
    private int _lineStyle = LINESTYLE_SOLID;
50
    private boolean _noFill = false;
53
    private boolean _noFill = false;
51
54
55
    private EscherContainerRecord spContainer;
56
    private ObjRecord objRecord;
57
58
    public HSSFShape(EscherContainerRecord spContainer, ObjRecord objRecord){
59
        this.spContainer = spContainer;
60
        this.objRecord = objRecord;
61
    }
52
    /**
62
    /**
53
     * Create a new shape with the specified parent and anchor.
63
     * Create a new shape with the specified parent and anchor.
54
     */
64
     */
55
    HSSFShape( HSSFShape parent, HSSFAnchor anchor )
65
    public HSSFShape( HSSFShape parent, HSSFAnchor anchor )
56
    {
66
    {
57
        this.parent = parent;
67
        this.parent = parent;
58
        this.anchor = anchor;
68
        this.anchor = anchor;
59
    }
69
    }
60
70
71
    public EscherContainerRecord getSpContainer() {
72
        return spContainer;
73
    }
74
75
    public ObjRecord getObjRecord() {
76
        return objRecord;
77
    }
78
61
    /**
79
    /**
62
     * Gets the parent shape.
80
     * Gets the parent shape.
63
     */
81
     */
(-)src/java/org/apache/poi/hssf/usermodel/drawing/HSSFShapeType.java (+29 lines)
Line 0 Link Here
1
package org.apache.poi.hssf.usermodel.drawing;
2
3
import org.apache.poi.hssf.usermodel.HSSFRectangle;
4
5
/**
6
 * @author Evgeniy Berlog
7
 * date: 08.06.12
8
 */
9
public enum HSSFShapeType {
10
    NOT_PRIMITIVE(0x0, null),
11
    RECTANGLE(0x1, HSSFRectangle.class),
12
    ROUND_RECTANGLE(0x2, null);
13
14
    private Short type;
15
    private Class shape;
16
17
    HSSFShapeType(Integer type, Class shape) {
18
        this.type = type.shortValue();
19
        this.shape = shape;
20
    }
21
22
    public Short getType() {
23
        return type;
24
    }
25
26
    public Class getShape() {
27
        return shape;
28
    }
29
}
(-)src/java/org/apache/poi/hssf/record/EscherAggregate.java (-18 / +34 lines)
Lines 43-58 Link Here
43
import org.apache.poi.hssf.model.ConvertAnchor;
43
import org.apache.poi.hssf.model.ConvertAnchor;
44
import org.apache.poi.hssf.model.DrawingManager2;
44
import org.apache.poi.hssf.model.DrawingManager2;
45
import org.apache.poi.hssf.model.TextboxShape;
45
import org.apache.poi.hssf.model.TextboxShape;
46
import org.apache.poi.hssf.usermodel.HSSFAnchor;
46
import org.apache.poi.hssf.usermodel.*;
47
import org.apache.poi.hssf.usermodel.HSSFChildAnchor;
48
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
49
import org.apache.poi.hssf.usermodel.HSSFPatriarch;
50
import org.apache.poi.hssf.usermodel.HSSFPicture;
51
import org.apache.poi.hssf.usermodel.HSSFShape;
52
import org.apache.poi.hssf.usermodel.HSSFShapeContainer;
53
import org.apache.poi.hssf.usermodel.HSSFShapeGroup;
54
import org.apache.poi.hssf.usermodel.HSSFSimpleShape;
55
import org.apache.poi.hssf.usermodel.HSSFTextbox;
56
import org.apache.poi.util.POILogFactory;
47
import org.apache.poi.util.POILogFactory;
57
import org.apache.poi.util.POILogger;
48
import org.apache.poi.util.POILogger;
58
49
Lines 322-328 Link Here
322
    /**
313
    /**
323
     * list of "tail" records that need to be serialized after all drawing group records
314
     * list of "tail" records that need to be serialized after all drawing group records
324
     */
315
     */
325
    private List tailRec = new ArrayList();
316
    private List<Record> tailRec = new ArrayList<Record>();
326
317
327
    public EscherAggregate(DrawingManager2 drawingManager) {
318
    public EscherAggregate(DrawingManager2 drawingManager) {
328
        this.drawingManager = drawingManager;
319
        this.drawingManager = drawingManager;
Lines 413-419 Link Here
413
        }
404
        }
414
405
415
        // Decode the shapes
406
        // Decode the shapes
416
        //		agg.escherRecords = new ArrayList();
407
        // agg.escherRecords = new ArrayList();
417
        int pos = 0;
408
        int pos = 0;
418
        while (pos < buffer.size()) {
409
        while (pos < buffer.size()) {
419
            EscherRecord r = recordFactory.createRecord(buffer.toByteArray(), pos);
410
            EscherRecord r = recordFactory.createRecord(buffer.toByteArray(), pos);
Lines 486-492 Link Here
486
477
487
                public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) {
478
                public void afterRecordSerialize(int offset, short recordId, int size, EscherRecord record) {
488
                    if (recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID) {
479
                    if (recordId == EscherClientDataRecord.RECORD_ID || recordId == EscherTextboxRecord.RECORD_ID) {
489
                        spEndingOffsets.add(Integer.valueOf(offset));
480
                        spEndingOffsets.add(offset);
490
                        shapes.add(record);
481
                        shapes.add(record);
491
                    }
482
                    }
492
                }
483
                }
Lines 501-512 Link Here
501
        pos = offset;
492
        pos = offset;
502
        int writtenEscherBytes = 0;
493
        int writtenEscherBytes = 0;
503
        for (int i = 1; i < shapes.size(); i++) {
494
        for (int i = 1; i < shapes.size(); i++) {
504
            int endOffset = ((Integer) spEndingOffsets.get(i)).intValue() - 1;
495
            int endOffset;
496
            if (i == shapes.size()-1){
497
                endOffset = buffer.length - 1;
498
            } else {
499
                endOffset = (Integer) spEndingOffsets.get(i) - 1;
500
            }
505
            int startOffset;
501
            int startOffset;
506
            if (i == 1)
502
            if (i == 1)
507
                startOffset = 0;
503
                startOffset = 0;
508
            else
504
            else
509
                startOffset = ((Integer) spEndingOffsets.get(i - 1)).intValue();
505
                startOffset = (Integer) spEndingOffsets.get(i - 1);
510
506
511
507
512
            byte[] drawingData = new byte[endOffset - startOffset + 1];
508
            byte[] drawingData = new byte[endOffset - startOffset + 1];
Lines 790-796 Link Here
790
            container.getChildren().add(shape);
786
            container.getChildren().add(shape);
791
    }
787
    }
792
788
793
    private static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) {
789
    public static HSSFClientAnchor toClientAnchor(EscherClientAnchorRecord anchorRecord) {
794
        HSSFClientAnchor anchor = new HSSFClientAnchor();
790
        HSSFClientAnchor anchor = new HSSFClientAnchor();
795
        anchor.setAnchorType(anchorRecord.getFlag());
791
        anchor.setAnchorType(anchorRecord.getFlag());
796
        anchor.setCol1(anchorRecord.getCol1());
792
        anchor.setCol1(anchorRecord.getCol1());
Lines 804-810 Link Here
804
        return anchor;
800
        return anchor;
805
    }
801
    }
806
802
807
    private static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) {
803
    public static HSSFChildAnchor toChildAnchor(EscherChildAnchorRecord anchorRecord) {
808
        HSSFChildAnchor anchor = new HSSFChildAnchor();
804
        HSSFChildAnchor anchor = new HSSFChildAnchor();
809
//        anchor.setAnchorType(anchorRecord.getFlag());
805
//        anchor.setAnchorType(anchorRecord.getFlag());
810
//        anchor.setCol1( anchorRecord.getCol1() );
806
//        anchor.setCol1( anchorRecord.getCol1() );
Lines 1081-1084 Link Here
1081
        return null;
1077
        return null;
1082
    }
1078
    }
1083
1079
1084
}
1080
    /**
1081
     * Returns the mapping  of {@link EscherClientDataRecord} and {@link EscherTextboxRecord}
1082
     * to their {@link TextObjectRecord} or {@link ObjRecord} .
1083
     *
1084
     * We need to access it outside of EscherAggregate when building shapes
1085
     *
1086
     * @return
1087
     */
1088
    public Map<EscherRecord, Record> getShapeToObjMapping(){
1089
        return Collections.unmodifiableMap(shapeToObj);
1090
    }
1091
1092
    /**
1093
     *
1094
     * @return tails records. We need to access them when building shapes.
1095
     * Every HSSFComment shape has a link to a NoteRecord from the tailRec collection.
1096
     */
1097
    public List<Record> getTailRecords(){
1098
        return Collections.unmodifiableList(tailRec);
1099
    }
1100
}

Return to bug 53372