/* ==================================================================== Licensed to the Apache Software Foundation (ASF) Under one or more contributor license agreements. See the NOTICE file distributed with this work for Additional information regarding copyright ownership. The ASF licenses this file to You Under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed Under the License is distributed on an "AS Is" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations Under the License. ==================================================================== */ namespace HH.WMS.Utils.NPOI.HSSF.Record { using System; using System.Text; using System.Collections; using HH.WMS.Utils.NPOI.DDF; using HH.WMS.Utils.NPOI.Util; using System.Collections.Generic; using HH.WMS.Utils.NPOI.HSSF.Util; /** * The escher container record is used to hold escher records. It is abstract and * must be subclassed for maximum benefit. * * @author Glen Stampoultzis (glens at apache.org) * @author Michael Zalewski (zalewski at optonline.net) */ public abstract class AbstractEscherHolderRecord : Record { private static bool DESERIALISE; static AbstractEscherHolderRecord() { DESERIALISE = false; //try //{ // DESERIALISE = (System.Configuration.ConfigurationManager.AppSettings["poi.deserialize.escher"] != null); //} //catch (Exception) //{ // DESERIALISE = false; //} } private List escherRecords; private LazilyConcatenatedByteArray rawDataContainer = new LazilyConcatenatedByteArray(); //private byte[] rawData; public AbstractEscherHolderRecord() { escherRecords = new List(); } /** * Constructs a Bar record and Sets its fields appropriately. * * @param in the RecordInputstream to Read the record from */ public AbstractEscherHolderRecord(RecordInputStream in1) { escherRecords = new List(); if (!DESERIALISE) { rawDataContainer.Concatenate(in1.ReadRemainder()); } else { byte[] data = in1.ReadAllContinuedRemainder(); ConvertToEscherRecords(0, data.Length, data); } } protected void ConvertRawBytesToEscherRecords() { byte[] rawData = RawData; ConvertToEscherRecords(0, rawData.Length, rawData); } private void ConvertToEscherRecords(int offset, int size, byte[] data) { escherRecords.Clear(); EscherRecordFactory recordFactory = new DefaultEscherRecordFactory(); int pos = offset; while (pos < offset + size) { EscherRecord r = recordFactory.CreateRecord(data, pos); int bytesRead = r.FillFields(data, pos, recordFactory); escherRecords.Add(r); pos += bytesRead; } } public override String ToString() { StringBuilder buffer = new StringBuilder(); String nl = Environment.NewLine; buffer.Append('[' + RecordName + ']' + nl); if (escherRecords.Count == 0) buffer.Append("No Escher Records Decoded" + nl); foreach (EscherRecord r in escherRecords) { buffer.Append(r.ToString()); } buffer.Append("[/" + RecordName + ']' + nl); return buffer.ToString(); } protected abstract String RecordName { get; } public override int Serialize(int offset, byte[] data) { LittleEndian.PutShort(data, 0 + offset, Sid); LittleEndian.PutShort(data, 2 + offset, (short)(RecordSize - 4)); byte[] rawData = RawData; if (escherRecords.Count == 0 && rawData != null) { LittleEndian.PutShort(data, 0 + offset, Sid); LittleEndian.PutShort(data, 2 + offset, (short)(RecordSize - 4)); Array.Copy(rawData, 0, data, 4 + offset, rawData.Length); return rawData.Length + 4; } LittleEndian.PutShort(data, 0 + offset, Sid); LittleEndian.PutShort(data, 2 + offset, (short)(RecordSize - 4)); int pos = offset + 4; foreach (EscherRecord r in escherRecords) { pos += r.Serialize(pos, data, new NullEscherSerializationListener()); } return RecordSize; } /** * Size of record (including 4 byte header) */ public override int RecordSize { get { byte[] rawData = RawData; if (escherRecords.Count == 0 && rawData != null) { return rawData.Length + 4; } else { int size = 4; foreach (EscherRecord r in escherRecords) { //EscherRecord r = (EscherRecord)iterator.Current; size += r.RecordSize; } return size; } } } public override object Clone() { return CloneViaReserialise(); } /** * Clone the current record, via a call to serialise * it, and another to Create a new record from the * bytes. * May only be used for classes which don't have * internal counts / ids in them. For those which * do, a full record-aware serialise is needed, which * allocates new ids / counts as needed. */ //public override Record CloneViaReserialise() //{ // // Do it via a re-serialise // // It's a cheat, but it works... // byte[] b = this.Serialize(); // using (var ms = new System.IO.MemoryStream(b)) // { // RecordInputStream rinp = new RecordInputStream(ms); // rinp.NextRecord(); // Record[] r = RecordFactory.CreateRecord(rinp); // if (r.Length != 1) // { // throw new InvalidOperationException("Re-serialised a record to Clone it, but got " + r.Length + " records back!"); // } // return r[0]; // } //} public void AddEscherRecord(int index, EscherRecord element) { escherRecords.Insert(index, element); } public bool AddEscherRecord(EscherRecord element) { escherRecords.Add(element); return true; } public List EscherRecords { get { return escherRecords; } } public void ClearEscherRecords() { escherRecords.Clear(); } /** * If we have a EscherContainerRecord as one of our * children (and most top level escher holders do), * then return that. */ public EscherContainerRecord GetEscherContainer() { for (IEnumerator it = escherRecords.GetEnumerator(); it.MoveNext(); ) { Object er = it.Current; if (er is EscherContainerRecord) { return (EscherContainerRecord)er; } } return null; } /** * Descends into all our children, returning the * first EscherRecord with the given id, or null * if none found */ public EscherRecord FindFirstWithId(short id) { return FindFirstWithId(id, EscherRecords); } private EscherRecord FindFirstWithId(short id, List records) { // Check at our level for (IEnumerator it = records.GetEnumerator(); it.MoveNext(); ) { EscherRecord r = (EscherRecord)it.Current; if (r.RecordId == id) { return r; } } // Then Check our children in turn for (IEnumerator it = records.GetEnumerator(); it.MoveNext(); ) { EscherRecord r = (EscherRecord)it.Current; if (r.IsContainerRecord) { EscherRecord found = FindFirstWithId(id, r.ChildRecords); if (found != null) { return found; } } } // Not found in this lot return null; } public EscherRecord GetEscherRecord(int index) { return (EscherRecord)escherRecords[index]; } /** * Big drawing Group records are split but it's easier to deal with them * as a whole Group so we need to join them toGether. */ public void Join(AbstractEscherHolderRecord record) { rawDataContainer.Concatenate(record.RawData); } public void ProcessContinueRecord(byte[] record) { rawDataContainer.Concatenate(record); } public byte[] RawData { get { return rawDataContainer.ToArray(); } set { rawDataContainer.Clear(); rawDataContainer.Concatenate(value); } } /** * Convert raw data to escher records. */ public void Decode() { byte[] rawData = RawData; ConvertToEscherRecords(0, rawData.Length, rawData); } } }