package org.apache.poi.ddf;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
public final class UnknownEscherRecord extends EscherRecord implements Cloneable {
private static final int MAX_RECORD_LENGTH = 100_000_000;
private static final byte[] NO_BYTES = new byte[0];
private byte[] thedata = NO_BYTES;
private List<EscherRecord> _childRecords;
public UnknownEscherRecord() {
_childRecords = new ArrayList<>();
}
@Override
public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
int bytesRemaining = readHeader( data, offset );
int available = data.length - (offset + 8);
if (bytesRemaining > available) {
bytesRemaining = available;
}
if (isContainerRecord()) {
int bytesWritten = 0;
thedata = new byte[0];
offset += 8;
bytesWritten += 8;
while ( bytesRemaining > 0 ) {
EscherRecord child = recordFactory.createRecord( data, offset );
int childBytesWritten = child.fillFields( data, offset, recordFactory );
bytesWritten += childBytesWritten;
offset += childBytesWritten;
bytesRemaining -= childBytesWritten;
getChildRecords().add( child );
}
return bytesWritten;
}
if (bytesRemaining < 0) {
bytesRemaining = 0;
}
thedata = IOUtils.safelyAllocate(bytesRemaining, MAX_RECORD_LENGTH);
System.arraycopy( data, offset + 8, thedata, 0, bytesRemaining );
return bytesRemaining + 8;
}
@Override
public int serialize(int offset, byte[] data, EscherSerializationListener listener) {
listener.beforeRecordSerialize( offset, getRecordId(), this );
LittleEndian.putShort(data, offset, getOptions());
LittleEndian.putShort(data, offset+2, getRecordId());
int remainingBytes = thedata.length;
for (EscherRecord r : _childRecords) {
remainingBytes += r.getRecordSize();
}
LittleEndian.putInt(data, offset+4, remainingBytes);
System.arraycopy(thedata, 0, data, offset+8, thedata.length);
int pos = offset+8+thedata.length;
for (EscherRecord r : _childRecords) {
pos += r.serialize(pos, data, listener );
}
listener.afterRecordSerialize( pos, getRecordId(), pos - offset, this );
return pos - offset;
}
public byte[] getData() {
return thedata;
}
@Override
public int getRecordSize() {
return 8 + thedata.length;
}
@Override
public List<EscherRecord> getChildRecords() {
return _childRecords;
}
@Override
public void setChildRecords(List<EscherRecord> childRecords) {
_childRecords = childRecords;
}
@Override
public UnknownEscherRecord clone() {
UnknownEscherRecord uer = new UnknownEscherRecord();
uer.thedata = this.thedata.clone();
uer.setOptions(this.getOptions());
uer.setRecordId(this.getRecordId());
return uer;
}
@Override
public String getRecordName() {
return "Unknown 0x" + HexDump.toHex(getRecordId());
}
public void addChildRecord(EscherRecord childRecord) {
getChildRecords().add( childRecord );
}
@Override
protected Object[][] getAttributeMap() {
int numCh = getChildRecords().size();
List<Object> chLst = new ArrayList<>(numCh * 2 + 2);
chLst.add("children");
chLst.add(numCh);
for (EscherRecord er : _childRecords) {
chLst.add(er.getRecordName());
chLst.add(er);
}
return new Object[][] {
{ "isContainer", isContainerRecord() },
chLst.toArray(),
{ "Extra Data", thedata }
};
}
}