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.util.*;
021:
022: import java.io.ByteArrayInputStream;
023: import java.util.List;
024: import java.util.Iterator;
025: import java.util.ArrayList;
026:
027: /**
028: * The obj record is used to hold various graphic objects and controls.
029: *
030: * @author Glen Stampoultzis (glens at apache.org)
031: */
032: public class ObjRecord extends Record {
033: public final static short sid = 0x5D;
034: private List subrecords;
035:
036: //00000000 15 00 12 00 01 00 01 00 11 60 00 00 00 00 00 0D .........`......
037: //00000010 26 01 00 00 00 00 00 00 00 00 &.........
038:
039: public ObjRecord() {
040: subrecords = new ArrayList(2);
041: }
042:
043: /**
044: * Constructs a OBJ record and sets its fields appropriately.
045: *
046: * @param in the RecordInputstream to read the record from
047: */
048:
049: public ObjRecord(RecordInputStream in) {
050: super (in);
051: }
052:
053: /**
054: * Checks the sid matches the expected side for this record
055: *
056: * @param id the expected sid.
057: */
058: protected void validateSid(short id) {
059: if (id != sid) {
060: throw new RecordFormatException("Not an OBJ record");
061: }
062: }
063:
064: protected void fillFields(RecordInputStream in) {
065: subrecords = new ArrayList();
066: //Check if this can be continued, if so then the
067: //following wont work properly
068: int subSize = 0;
069: byte[] subRecordData = in.readRemainder();
070: RecordInputStream subRecStream = new RecordInputStream(
071: new ByteArrayInputStream(subRecordData));
072: while (subRecStream.hasNextRecord()) {
073: subRecStream.nextRecord();
074: Record subRecord = SubRecord.createSubRecord(subRecStream);
075: subSize += subRecord.getRecordSize();
076: subrecords.add(subRecord);
077: }
078:
079: /**
080: * Check if the RecordInputStream skipped EndSubRecord,
081: * if it did then append it explicitly.
082: * See Bug 41242 for details.
083: */
084: if (subRecordData.length - subSize == 4) {
085: subrecords.add(new EndSubRecord());
086: }
087:
088: /* JMH the size present/not present in the code below
089: needs to be considered in the RecordInputStream??
090: int pos = offset;
091: while (pos - offset <= size-2) // atleast one "short" must be present
092: {
093: short subRecordSid = LittleEndian.getShort(data, pos);
094: short subRecordSize = -1; // set default to "< 0"
095: if (pos-offset <= size-4) { // see if size info is present, else default to -1
096: subRecordSize = LittleEndian.getShort(data, pos + 2);
097: }
098: Record subRecord = SubRecord.createSubRecord(subRecordSid, subRecordSize, data, pos + 4);
099: subrecords.add(subRecord);
100: pos += subRecord.getRecordSize();
101: }*/
102: }
103:
104: public String toString() {
105: StringBuffer buffer = new StringBuffer();
106:
107: buffer.append("[OBJ]\n");
108: for (Iterator iterator = subrecords.iterator(); iterator
109: .hasNext();) {
110: Record record = (Record) iterator.next();
111: buffer.append("SUBRECORD: " + record.toString());
112: }
113: buffer.append("[/OBJ]\n");
114: return buffer.toString();
115: }
116:
117: public int serialize(int offset, byte[] data) {
118: int pos = 0;
119:
120: LittleEndian.putShort(data, 0 + offset, sid);
121: LittleEndian.putShort(data, 2 + offset,
122: (short) (getRecordSize() - 4));
123:
124: pos = offset + 4;
125: for (Iterator iterator = subrecords.iterator(); iterator
126: .hasNext();) {
127: Record record = (Record) iterator.next();
128: pos += record.serialize(pos, data);
129: }
130:
131: return getRecordSize();
132: }
133:
134: /**
135: * Size of record (excluding 4 byte header)
136: */
137: public int getRecordSize() {
138: int size = 0;
139: for (Iterator iterator = subrecords.iterator(); iterator
140: .hasNext();) {
141: Record record = (Record) iterator.next();
142: size += record.getRecordSize();
143: }
144: return 4 + size;
145: }
146:
147: public short getSid() {
148: return sid;
149: }
150:
151: public List getSubRecords() {
152: return subrecords;
153: }
154:
155: public void clearSubRecords() {
156: subrecords.clear();
157: }
158:
159: public void addSubRecord(int index, Object element) {
160: subrecords.add(index, element);
161: }
162:
163: public boolean addSubRecord(Object o) {
164: return subrecords.add(o);
165: }
166:
167: public Object clone() {
168: ObjRecord rec = new ObjRecord();
169:
170: for (Iterator iterator = subrecords.iterator(); iterator
171: .hasNext();)
172: rec.addSubRecord(((Record) iterator.next()).clone());
173:
174: return rec;
175: }
176:
177: } // END OF CLASS
|