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

(-)src/testcases/org/apache/poi/hssf/model/TestDrawingAggregate.java (-21 / +152 lines)
Lines 1-18 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
==================================================================== */
1
package org.apache.poi.hssf.model;
17
package org.apache.poi.hssf.model;
2
18
3
import junit.framework.TestCase;
19
import junit.framework.TestCase;
20
import org.apache.poi.ddf.EscherClientDataRecord;
21
import org.apache.poi.ddf.EscherContainerRecord;
4
import org.apache.poi.ddf.EscherDggRecord;
22
import org.apache.poi.ddf.EscherDggRecord;
23
import org.apache.poi.ddf.EscherRecord;
24
import org.apache.poi.ddf.EscherSpRecord;
5
import org.apache.poi.hssf.HSSFTestDataSamples;
25
import org.apache.poi.hssf.HSSFTestDataSamples;
6
import org.apache.poi.hssf.record.ContinueRecord;
26
import org.apache.poi.hssf.record.*;
7
import org.apache.poi.hssf.record.DrawingRecord;
8
import org.apache.poi.hssf.record.EOFRecord;
9
import org.apache.poi.hssf.record.EscherAggregate;
10
import org.apache.poi.hssf.record.ObjRecord;
11
import org.apache.poi.hssf.record.Record;
12
import org.apache.poi.hssf.record.RecordBase;
13
import org.apache.poi.hssf.record.RecordFactory;
14
import org.apache.poi.hssf.record.TextObjectRecord;
15
import org.apache.poi.hssf.record.WindowTwoRecord;
16
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
27
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
17
import org.apache.poi.hssf.usermodel.HSSFSheet;
28
import org.apache.poi.hssf.usermodel.HSSFSheet;
18
import org.apache.poi.hssf.usermodel.HSSFTestHelper;
29
import org.apache.poi.hssf.usermodel.HSSFTestHelper;
Lines 20-26 Link Here
20
import org.apache.poi.util.HexRead;
31
import org.apache.poi.util.HexRead;
21
32
22
import java.io.ByteArrayInputStream;
33
import java.io.ByteArrayInputStream;
34
import java.util.ArrayList;
35
import java.util.LinkedHashMap;
23
import java.util.List;
36
import java.util.List;
37
import java.util.Map;
24
38
25
/**
39
/**
26
 * @author Yegor Kozlov
40
 * @author Yegor Kozlov
Lines 28-33 Link Here
28
 */
42
 */
29
public class TestDrawingAggregate extends TestCase {
43
public class TestDrawingAggregate extends TestCase {
30
    /**
44
    /**
45
     * Serialize escher aggregate, read back and assert that the drawing data is preserved.
46
     *
47
     * @param agg the aggregate to test
48
     * @return verified aggregate (serialized and read back)
49
     */
50
    public static EscherAggregate assertWriteAndReadBack(EscherAggregate agg) {
51
        byte[] dgBytes = agg.serialize();
52
53
54
        List<Record> dgRecords = RecordFactory.createRecords(new ByteArrayInputStream(dgBytes));
55
56
        DrawingManager2 drawingManager = new DrawingManager2(new EscherDggRecord());
57
58
        // create a dummy sheet consisting of our test data
59
        InternalSheet sheet = InternalSheet.createSheet();
60
        List<RecordBase> records = sheet.getRecords();
61
        records.clear();
62
        records.addAll(dgRecords);
63
        records.add(EOFRecord.instance);
64
65
66
        sheet.aggregateDrawingRecords(drawingManager, false);
67
        assertEquals("drawing was not fully aggregated", 2, records.size());
68
        assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate);
69
        assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);
70
        EscherAggregate agg2 = (EscherAggregate) records.get(0);
71
72
        assertEquals(agg.getEscherRecords().size(), agg2.getEscherRecords().size());
73
74
        // assert that both pre- and after- serialize aggregates have the same xml representation
75
        for (int i = 0; i < agg.getEscherRecords().size(); i++) {
76
            EscherRecord r1 = agg.getEscherRecords().get(i);
77
            EscherRecord r2 = agg2.getEscherRecords().get(i);
78
79
            assertEquals(r1.toXml(), r2.toXml());
80
        }
81
82
        return agg2;
83
    }
84
85
    /**
86
     * assert that mapping of Obj records to escher shape containers is the same in both aggregates
87
     */
88
    public static void assertObjectMappingSame(EscherAggregate agg1, EscherAggregate agg2) {
89
90
        // map EscherClientDataRecord and EscherTextboxRecord to their parents
91
        Map<EscherRecord, EscherContainerRecord> map1 = new LinkedHashMap<EscherRecord, EscherContainerRecord>();
92
        for (EscherRecord r : agg1.getEscherRecords()) mapShapeContainers(r, map1);
93
94
        Map<EscherRecord, EscherContainerRecord> map2 = new LinkedHashMap<EscherRecord, EscherContainerRecord>();
95
        for (EscherRecord r : agg2.getEscherRecords()) mapShapeContainers(r, map2);
96
97
        assertEquals("aggregates have different number of shapes", map1.size(), map2.size());
98
99
        // for each EscherClientDataRecord get parent SP_CONTAINER and corresponding ObjRecord
100
        // verify that ObjRecord to
101
        List<EscherRecord> l1 = new ArrayList<EscherRecord>(map1.keySet());
102
        List<EscherRecord> l2 = new ArrayList<EscherRecord>(map2.keySet());
103
        for (int i = 0; i < l1.size(); i++) {
104
            EscherRecord e1 = l1.get(i);
105
            EscherRecord e2 = l2.get(i);
106
            ObjRecord obj1 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg1).get(e1);
107
            ObjRecord obj2 = (ObjRecord) HSSFRecordTestHelper.getShapeToObjForTest(agg2).get(e2);
108
109
            CommonObjectDataSubRecord cmo1 = (CommonObjectDataSubRecord) obj1.getSubRecords().get(0);
110
            CommonObjectDataSubRecord cmo2 = (CommonObjectDataSubRecord) obj2.getSubRecords().get(0);
111
112
            assertEquals(cmo1.getObjectId(), cmo2.getObjectId());
113
            assertEquals(obj1.toString(), obj2.toString());
114
115
            // test that obj parents have the same shapeId, that is, that shape is the same
116
            EscherContainerRecord p1 = map1.get(e1);
117
            EscherContainerRecord p2 = map2.get(e2);
118
            EscherSpRecord sp1 = (EscherSpRecord) p1.getChildById(EscherSpRecord.RECORD_ID);
119
            EscherSpRecord sp2 = (EscherSpRecord) p2.getChildById(EscherSpRecord.RECORD_ID);
120
            assertEquals(sp1.getShapeId(), sp2.getShapeId());
121
122
            assertEquals("wrong shape2obj mapping", sp1.getShapeId() % 1024, cmo1.getObjectId());
123
            assertEquals(p1.toXml(), p2.toXml());
124
        }
125
    }
126
127
    /**
128
     * recursively map EscherClientDataRecords  to their parent shape containers:
129
     * <p/>
130
     * EscherClientDataRecord1 --> EscherContainerRecord1
131
     * EscherClientDataRecord2 --> EscherContainerRecord2
132
     * ...
133
     * <p/>
134
     * TODO: YK: this method can be avoided if we have EscherRecord.getParent()
135
     */
136
    private static void mapShapeContainers(EscherRecord parent, Map<EscherRecord, EscherContainerRecord> map) {
137
        if (parent.isContainerRecord()) {
138
            if (parent.getRecordId() == EscherContainerRecord.SP_CONTAINER) {
139
                // iterate over shape's children and search for EscherClientDataRecord
140
                for (EscherRecord r : parent.getChildRecords()) {
141
                    if (r.getRecordId() == EscherClientDataRecord.RECORD_ID) {
142
                        map.put(r, (EscherContainerRecord) parent);
143
                    }
144
                }
145
            } else {
146
                for (EscherRecord ch : parent.getChildRecords()) {
147
                    mapShapeContainers(ch, map);
148
                }
149
            }
150
        }
151
    }
152
153
    /**
31
     * test reading drawing aggregate from a test file from Bugzilla 45129
154
     * test reading drawing aggregate from a test file from Bugzilla 45129
32
     */
155
     */
33
    public void test45129() {
156
    public void test45129() {
Lines 69-75 Link Here
69
        // The subrange [19, 388] is expected to be replaced with a EscherAggregate object
192
        // The subrange [19, 388] is expected to be replaced with a EscherAggregate object
70
        DrawingManager2 drawingManager = iworkbook.findDrawingGroup();
193
        DrawingManager2 drawingManager = iworkbook.findDrawingGroup();
71
        int loc = isheet.aggregateDrawingRecords(drawingManager, false);
194
        int loc = isheet.aggregateDrawingRecords(drawingManager, false);
72
        EscherAggregate ag = (EscherAggregate) records.get(loc);
195
        EscherAggregate agg = (EscherAggregate) records.get(loc);
73
196
74
        assertEquals("wrong size of the aggregated sheet records stream", 25, records.size());
197
        assertEquals("wrong size of the aggregated sheet records stream", 25, records.size());
75
        assertTrue(
198
        assertTrue(
Lines 80-87 Link Here
80
        assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(),
203
        assertTrue("records.get(20) is expected to be Window2 but was " + records.get(20).getClass().getSimpleName(),
81
                records.get(20) instanceof WindowTwoRecord);
204
                records.get(20) instanceof WindowTwoRecord);
82
205
83
        // TODO figure out why serialization fails
206
        EscherAggregate agg2 = assertWriteAndReadBack(agg);
84
        // byte[] bytes = ag.serialize();
207
208
        assertObjectMappingSame(agg, agg2);
85
    }
209
    }
86
210
87
    public void testFileWithPictures() {
211
    public void testFileWithPictures() {
Lines 93-102 Link Here
93
217
94
        List<RecordBase> records = isheet.getRecords();
218
        List<RecordBase> records = isheet.getRecords();
95
219
96
        for (RecordBase recordBase : records) {
97
            System.out.println(recordBase.toString());
98
        }
99
100
        // the sheet's drawing is not aggregated
220
        // the sheet's drawing is not aggregated
101
        assertEquals("wrong size of sheet records stream", 315, records.size());
221
        assertEquals("wrong size of sheet records stream", 315, records.size());
102
        // the last record before the drawing block
222
        // the last record before the drawing block
Lines 127-133 Link Here
127
        // The subrange [19, 388] is expected to be replaced with a EscherAggregate object
247
        // The subrange [19, 388] is expected to be replaced with a EscherAggregate object
128
        DrawingManager2 drawingManager = iworkbook.findDrawingGroup();
248
        DrawingManager2 drawingManager = iworkbook.findDrawingGroup();
129
        int loc = isheet.aggregateDrawingRecords(drawingManager, false);
249
        int loc = isheet.aggregateDrawingRecords(drawingManager, false);
130
        EscherAggregate ag = (EscherAggregate) records.get(loc);
250
        EscherAggregate agg = (EscherAggregate) records.get(loc);
131
251
132
        assertEquals("wrong size of the aggregated sheet records stream", 38, records.size());
252
        assertEquals("wrong size of the aggregated sheet records stream", 38, records.size());
133
        assertTrue(
253
        assertTrue(
Lines 137-142 Link Here
137
                records.get(22) instanceof EscherAggregate);
257
                records.get(22) instanceof EscherAggregate);
138
        assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(),
258
        assertTrue("records.get(23) is expected to be Window2 but was " + records.get(23).getClass().getSimpleName(),
139
                records.get(23) instanceof WindowTwoRecord);
259
                records.get(23) instanceof WindowTwoRecord);
260
261
        EscherAggregate agg2 = assertWriteAndReadBack(agg);
262
263
        assertObjectMappingSame(agg, agg2);
140
    }
264
    }
141
265
142
    public void testUnhandledContinue() {
266
    public void testUnhandledContinue() {
Lines 848-855 Link Here
848
        assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);
972
        assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);
849
        EscherAggregate agg = (EscherAggregate) records.get(0);
973
        EscherAggregate agg = (EscherAggregate) records.get(0);
850
974
851
        // TODO figure out why serialization fails
975
        // serialize, read back and assert that the drawing data is preserved
852
//        byte[] writtenBytes = agg.serialize();
976
        EscherAggregate agg2 = assertWriteAndReadBack(agg);
977
978
        assertObjectMappingSame(agg, agg2);
853
    }
979
    }
854
980
855
    public void testUnhandledContinue2() {
981
    public void testUnhandledContinue2() {
Lines 1793-1802 Link Here
1793
        records.addAll(dgRecords);
1919
        records.addAll(dgRecords);
1794
        records.add(EOFRecord.instance);
1920
        records.add(EOFRecord.instance);
1795
1921
1796
1797
        sheet.aggregateDrawingRecords(drawingManager, false);
1922
        sheet.aggregateDrawingRecords(drawingManager, false);
1798
        assertEquals("drawing was not fully aggregated", 2, records.size());
1923
        assertEquals("drawing was not fully aggregated", 2, records.size());
1799
        assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate);
1924
        assertTrue("expected EscherAggregate", records.get(0) instanceof EscherAggregate);
1800
        assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);
1925
        assertTrue("expected EOFRecord", records.get(1) instanceof EOFRecord);
1926
1927
        EscherAggregate agg = (EscherAggregate) records.get(0);
1928
1929
        EscherAggregate agg2 = assertWriteAndReadBack(agg);
1930
1931
        assertObjectMappingSame(agg, agg2);
1801
    }
1932
    }
1802
}
1933
}
(-)src/java/org/apache/poi/ddf/EscherArrayProperty.java (+3 lines)
Lines 62-67 Link Here
62
    }
62
    }
63
63
64
    public int getNumberOfElementsInArray() {
64
    public int getNumberOfElementsInArray() {
65
        if (emptyComplexPart){
66
            return 0;
67
        }
65
        return LittleEndian.getUShort(_complexData, 0);
68
        return LittleEndian.getUShort(_complexData, 0);
66
    }
69
    }
67
70
(-)src/testcases/org/apache/poi/hssf/record/HSSFRecordTestHelper.java (+17 lines)
Line 0 Link Here
1
package org.apache.poi.hssf.record;
2
3
import org.apache.poi.ddf.EscherRecord;
4
5
import java.util.Map;
6
7
/**
8
 * @author Evgeniy Berlog
9
 * date: 30.05.12
10
 */
11
public class HSSFRecordTestHelper {
12
13
    public static Map<EscherRecord, Record> getShapeToObjForTest(EscherAggregate agg){
14
        return agg.shapeToObj;
15
    }
16
17
}
(-)src/java/org/apache/poi/hssf/record/EscherAggregate.java (-4 / +4 lines)
Lines 288-294 Link Here
288
	protected HSSFPatriarch patriarch;
288
	protected HSSFPatriarch patriarch;
289
289
290
	/** Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */
290
	/** Maps shape container objects to their {@link TextObjectRecord} or {@link ObjRecord} */
291
	private Map<EscherRecord, Record> shapeToObj = new HashMap<EscherRecord, Record>();
291
	Map<EscherRecord, Record> shapeToObj = new HashMap<EscherRecord, Record>();
292
	private DrawingManager2 drawingManager;
292
	private DrawingManager2 drawingManager;
293
	private short drawingGroupId;
293
	private short drawingGroupId;
294
294
Lines 371-377 Link Here
371
				&& sid( records, loc ) == DrawingRecord.sid
371
				&& sid( records, loc ) == DrawingRecord.sid
372
				&& isObjectRecord( records, loc + 1 ) )
372
				&& isObjectRecord( records, loc + 1 ) )
373
		{
373
		{
374
			dataSize += ( (DrawingRecord) records.get( loc ) ).getData().length;
374
			dataSize += ( (DrawingRecord) records.get( loc ) ).getRecordData().length;
375
			loc += 2;
375
			loc += 2;
376
            while ( loc + 1 < records.size()
376
            while ( loc + 1 < records.size()
377
                    && sid( records, loc ) == ContinueRecord.sid
377
                    && sid( records, loc ) == ContinueRecord.sid
Lines 391-398 Link Here
391
				&& isObjectRecord( records, loc + 1 ) )
391
				&& isObjectRecord( records, loc + 1 ) )
392
		{
392
		{
393
			DrawingRecord drawingRecord = (DrawingRecord) records.get( loc );
393
			DrawingRecord drawingRecord = (DrawingRecord) records.get( loc );
394
			System.arraycopy( drawingRecord.getData(), 0, buffer, offset, drawingRecord.getData().length );
394
			System.arraycopy( drawingRecord.getRecordData(), 0, buffer, offset, drawingRecord.getRecordData().length );
395
			offset += drawingRecord.getData().length;
395
			offset += drawingRecord.getRecordData().length;
396
			loc += 2;
396
			loc += 2;
397
            while ( loc + 1 < records.size()
397
            while ( loc + 1 < records.size()
398
                    && sid( records, loc ) == ContinueRecord.sid
398
                    && sid( records, loc ) == ContinueRecord.sid
(-)src/java/org/apache/poi/hssf/record/DrawingRecord.java (+4 lines)
Lines 64-69 Link Here
64
        return recordData;
64
        return recordData;
65
    }
65
    }
66
66
67
    public byte[] getRecordData(){
68
        return recordData;
69
    }
70
67
    public void setData(byte[] thedata) {
71
    public void setData(byte[] thedata) {
68
    	if (thedata == null) {
72
    	if (thedata == null) {
69
    		throw new IllegalArgumentException("data must not be null");
73
    		throw new IllegalArgumentException("data must not be null");

Return to bug 53010