001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hssf.record;
019:
020: import org.apache.poi.ddf.DefaultEscherRecordFactory;
021: import org.apache.poi.ddf.EscherRecord;
022: import org.apache.poi.ddf.EscherRecordFactory;
023: import org.apache.poi.ddf.NullEscherSerializationListener;
024: import org.apache.poi.util.LittleEndian;
025:
026: import java.util.ArrayList;
027: import java.util.Iterator;
028: import java.util.List;
029:
030: /**
031: * The escher container record is used to hold escher records. It is abstract and
032: * must be subclassed for maximum benefit.
033: *
034: * @author Glen Stampoultzis (glens at apache.org)
035: * @author Michael Zalewski (zalewski at optonline.net)
036: */
037: public abstract class AbstractEscherHolderRecord extends Record {
038: private static boolean DESERIALISE;
039: static {
040: try {
041: DESERIALISE = (System.getProperty("poi.deserialize.escher") != null);
042: } catch (SecurityException e) {
043: DESERIALISE = false;
044: }
045: }
046:
047: private List escherRecords;
048: private byte[] rawData;
049:
050: public AbstractEscherHolderRecord() {
051: escherRecords = new ArrayList();
052: }
053:
054: /**
055: * Constructs a Bar record and sets its fields appropriately.
056: *
057: * @param in the RecordInputstream to read the record from
058: */
059: public AbstractEscherHolderRecord(RecordInputStream in) {
060: super (in);
061:
062: }
063:
064: /**
065: * Checks the sid matches the expected side for this record
066: *
067: * @param id the expected sid.
068: */
069: protected void validateSid(short id) {
070: if (id != getSid()) {
071: throw new RecordFormatException("Not an escher record");
072: }
073: }
074:
075: protected void fillFields(RecordInputStream in) {
076: escherRecords = new ArrayList();
077: if (!DESERIALISE) {
078: rawData = in.readRemainder();
079: } else {
080: byte[] data = in.readAllContinuedRemainder();
081: convertToEscherRecords(0, data.length, data);
082: }
083: }
084:
085: private void convertToEscherRecords(int offset, int size,
086: byte[] data) {
087: EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
088: int pos = offset;
089: while (pos < offset + size) {
090: EscherRecord r = recordFactory.createRecord(data, pos);
091: int bytesRead = r.fillFields(data, pos, recordFactory);
092: escherRecords.add(r);
093: pos += bytesRead;
094: }
095: }
096:
097: public String toString() {
098: StringBuffer buffer = new StringBuffer();
099:
100: final String nl = System.getProperty("line.separator");
101: buffer.append('[' + getRecordName() + ']' + nl);
102: if (escherRecords.size() == 0)
103: buffer.append("No Escher Records Decoded" + nl);
104: for (Iterator iterator = escherRecords.iterator(); iterator
105: .hasNext();) {
106: EscherRecord r = (EscherRecord) iterator.next();
107: buffer.append(r.toString());
108: }
109: buffer.append("[/" + getRecordName() + ']' + nl);
110:
111: return buffer.toString();
112: }
113:
114: protected abstract String getRecordName();
115:
116: public int serialize(int offset, byte[] data) {
117: LittleEndian.putShort(data, 0 + offset, getSid());
118: LittleEndian.putShort(data, 2 + offset,
119: (short) (getRecordSize() - 4));
120: if (escherRecords.size() == 0 && rawData != null) {
121: LittleEndian.putShort(data, 0 + offset, getSid());
122: LittleEndian.putShort(data, 2 + offset,
123: (short) (getRecordSize() - 4));
124: System.arraycopy(rawData, 0, data, 4 + offset,
125: rawData.length);
126: return rawData.length + 4;
127: } else {
128: LittleEndian.putShort(data, 0 + offset, getSid());
129: LittleEndian.putShort(data, 2 + offset,
130: (short) (getRecordSize() - 4));
131:
132: int pos = offset + 4;
133: for (Iterator iterator = escherRecords.iterator(); iterator
134: .hasNext();) {
135: EscherRecord r = (EscherRecord) iterator.next();
136: pos += r.serialize(pos, data,
137: new NullEscherSerializationListener());
138: }
139: }
140: return getRecordSize();
141: }
142:
143: // public int serialize(int offset, byte[] data)
144: // {
145: // if (escherRecords.size() == 0 && rawData != null)
146: // {
147: // System.arraycopy( rawData, 0, data, offset, rawData.length);
148: // return rawData.length;
149: // }
150: // else
151: // {
152: // collapseShapeInformation();
153: //
154: // LittleEndian.putShort(data, 0 + offset, getSid());
155: // LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
156: //
157: // int pos = offset + 4;
158: // for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
159: // {
160: // EscherRecord r = (EscherRecord) iterator.next();
161: // pos += r.serialize(pos, data, new NullEscherSerializationListener() );
162: // }
163: //
164: // return getRecordSize();
165: // }
166: // }
167:
168: /**
169: * Size of record (including 4 byte header)
170: */
171: public int getRecordSize() {
172: if (escherRecords.size() == 0 && rawData != null) {
173: return rawData.length + 4;
174: } else {
175: int size = 4;
176: for (Iterator iterator = escherRecords.iterator(); iterator
177: .hasNext();) {
178: EscherRecord r = (EscherRecord) iterator.next();
179: size += r.getRecordSize();
180: }
181: return size;
182: }
183: }
184:
185: //
186: // /**
187: // * Size of record (including 4 byte header)
188: // */
189: // public int getRecordSize()
190: // {
191: // if (escherRecords.size() == 0 && rawData != null)
192: // {
193: // return rawData.length;
194: // }
195: // else
196: // {
197: // collapseShapeInformation();
198: //
199: // int size = 4;
200: // for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
201: // {
202: // EscherRecord r = (EscherRecord) iterator.next();
203: // size += r.getRecordSize();
204: // }
205: // return size;
206: // }
207: // }
208:
209: public abstract short getSid();
210:
211: public Object clone() {
212: throw new IllegalStateException("Not implemented yet.");
213: }
214:
215: public void addEscherRecord(int index, EscherRecord element) {
216: escherRecords.add(index, element);
217: }
218:
219: public boolean addEscherRecord(EscherRecord element) {
220: return escherRecords.add(element);
221: }
222:
223: public List getEscherRecords() {
224: return escherRecords;
225: }
226:
227: public void clearEscherRecords() {
228: escherRecords.clear();
229: }
230:
231: public EscherRecord getEscherRecord(int index) {
232: return (EscherRecord) escherRecords.get(index);
233: }
234:
235: /**
236: * Big drawing group records are split but it's easier to deal with them
237: * as a whole group so we need to join them together.
238: */
239: public void join(AbstractEscherHolderRecord record) {
240: int length = this .rawData.length + record.getRawData().length;
241: byte[] data = new byte[length];
242: System.arraycopy(rawData, 0, data, 0, rawData.length);
243: System.arraycopy(record.getRawData(), 0, data, rawData.length,
244: record.getRawData().length);
245: rawData = data;
246: }
247:
248: public void processContinueRecord(byte[] record) {
249: int length = this .rawData.length + record.length;
250: byte[] data = new byte[length];
251: System.arraycopy(rawData, 0, data, 0, rawData.length);
252: System
253: .arraycopy(record, 0, data, rawData.length,
254: record.length);
255: rawData = data;
256: }
257:
258: public byte[] getRawData() {
259: return rawData;
260: }
261:
262: public void setRawData(byte[] rawData) {
263: this .rawData = rawData;
264: }
265:
266: /**
267: * Convert raw data to escher records.
268: */
269: public void decode() {
270: convertToEscherRecords(0, rawData.length, rawData);
271: }
272:
273: } // END OF CLASS
|