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.ddf;
019:
020: import org.apache.poi.util.HexDump;
021: import org.apache.poi.util.LittleEndian;
022:
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.ArrayList;
026:
027: /**
028: * This record is used whenever a escher record is encountered that
029: * we do not explicitly support.
030: *
031: * @author Glen Stampoultzis (glens at apache.org)
032: */
033: public class UnknownEscherRecord extends EscherRecord {
034: private static final byte[] NO_BYTES = new byte[0];
035:
036: /** The data for this record not including the the 8 byte header */
037: private byte[] thedata = NO_BYTES;
038: private List childRecords = new ArrayList();
039:
040: public UnknownEscherRecord() {
041: }
042:
043: /**
044: * This method deserializes the record from a byte array.
045: *
046: * @param data The byte array containing the escher record information
047: * @param offset The starting offset into <code>data</code>.
048: * @param recordFactory May be null since this is not a container record.
049: * @return The number of bytes read from the byte array.
050: */
051: public int fillFields(byte[] data, int offset,
052: EscherRecordFactory recordFactory) {
053: int bytesRemaining = readHeader(data, offset);
054: if (isContainerRecord()) {
055: int bytesWritten = 0;
056: thedata = new byte[0];
057: offset += 8;
058: bytesWritten += 8;
059: while (bytesRemaining > 0) {
060: EscherRecord child = recordFactory.createRecord(data,
061: offset);
062: int childBytesWritten = child.fillFields(data, offset,
063: recordFactory);
064: bytesWritten += childBytesWritten;
065: offset += childBytesWritten;
066: bytesRemaining -= childBytesWritten;
067: getChildRecords().add(child);
068: }
069: return bytesWritten;
070: } else {
071: thedata = new byte[bytesRemaining];
072: System.arraycopy(data, offset + 8, thedata, 0,
073: bytesRemaining);
074: return bytesRemaining + 8;
075: }
076: }
077:
078: /**
079: * Writes this record and any contained records to the supplied byte
080: * array.
081: *
082: * @return the number of bytes written.
083: */
084: public int serialize(int offset, byte[] data,
085: EscherSerializationListener listener) {
086: listener.beforeRecordSerialize(offset, getRecordId(), this );
087:
088: LittleEndian.putShort(data, offset, getOptions());
089: LittleEndian.putShort(data, offset + 2, getRecordId());
090: int remainingBytes = thedata.length;
091: for (Iterator iterator = getChildRecords().iterator(); iterator
092: .hasNext();) {
093: EscherRecord r = (EscherRecord) iterator.next();
094: remainingBytes += r.getRecordSize();
095: }
096: LittleEndian.putInt(data, offset + 4, remainingBytes);
097: System.arraycopy(thedata, 0, data, offset + 8, thedata.length);
098: int pos = offset + 8 + thedata.length;
099: for (Iterator iterator = getChildRecords().iterator(); iterator
100: .hasNext();) {
101: EscherRecord r = (EscherRecord) iterator.next();
102: pos += r.serialize(pos, data, listener);
103: }
104:
105: listener.afterRecordSerialize(pos, getRecordId(), pos - offset,
106: this );
107: return pos - offset;
108: }
109:
110: public byte[] getData() {
111: return thedata;
112: }
113:
114: /**
115: * Returns the number of bytes that are required to serialize this record.
116: *
117: * @return Number of bytes
118: */
119: public int getRecordSize() {
120: return 8 + thedata.length;
121: }
122:
123: public List getChildRecords() {
124: return childRecords;
125: }
126:
127: public void setChildRecords(List childRecords) {
128: this .childRecords = childRecords;
129: }
130:
131: public Object clone() {
132: // shallow clone
133: return super .clone();
134: }
135:
136: /**
137: * The short name for this record
138: */
139: public String getRecordName() {
140: return "Unknown 0x" + HexDump.toHex(getRecordId());
141: }
142:
143: public String toString() {
144: String nl = System.getProperty("line.separator");
145:
146: StringBuffer children = new StringBuffer();
147: if (getChildRecords().size() > 0) {
148: children.append(" children: " + nl);
149: for (Iterator iterator = getChildRecords().iterator(); iterator
150: .hasNext();) {
151: EscherRecord record = (EscherRecord) iterator.next();
152: children.append(record.toString());
153: children.append(nl);
154: }
155: }
156:
157: String theDumpHex = "";
158: try {
159: if (thedata.length != 0) {
160: theDumpHex = " Extra Data:" + nl;
161: theDumpHex += HexDump.dump(thedata, 0, 0);
162: }
163: } catch (Exception e) {
164: theDumpHex = "Error!!";
165: }
166:
167: return getClass().getName() + ":" + nl + " isContainer: "
168: + isContainerRecord() + nl + " options: 0x"
169: + HexDump.toHex(getOptions()) + nl + " recordId: 0x"
170: + HexDump.toHex(getRecordId()) + nl + " numchildren: "
171: + getChildRecords().size() + nl + theDumpHex
172: + children.toString();
173: }
174:
175: public void addChildRecord(EscherRecord childRecord) {
176: getChildRecords().add(childRecord);
177: }
178:
179: }
|