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.LittleEndian;
021: import org.apache.poi.util.StringUtil;
022:
023: /**
024: * Supports the STRING record structure.
025: *
026: * @author Glen Stampoultzis (glens at apache.org)
027: */
028: public class StringRecord extends Record {
029: public final static short sid = 0x207;
030: private int field_1_string_length;
031: private byte field_2_unicode_flag;
032: private String field_3_string;
033:
034: public StringRecord() {
035: }
036:
037: /**
038: * Constructs a String record and sets its fields appropriately.
039: *
040: * @param in the RecordInputstream to read the record from
041: */
042: public StringRecord(RecordInputStream in) {
043: super (in);
044: }
045:
046: /**
047: * Throw a runtime exception in the event of a
048: * record passed with a differing ID.
049: *
050: * @param id alleged id for this record
051: */
052: protected void validateSid(short id) {
053: if (id != sid) {
054: throw new RecordFormatException("Not a valid StringRecord");
055: }
056: }
057:
058: /**
059: * @param in the RecordInputstream to read the record from
060: */
061: protected void fillFields(RecordInputStream in) {
062: field_1_string_length = in.readShort();
063: field_2_unicode_flag = in.readByte();
064: byte[] data = in.readRemainder();
065: //Why isnt this using the in.readString methods???
066: if (isUnCompressedUnicode()) {
067: field_3_string = StringUtil.getFromUnicodeLE(data, 0,
068: field_1_string_length);
069: } else {
070: field_3_string = StringUtil.getFromCompressedUnicode(data,
071: 0, field_1_string_length);
072: }
073: }
074:
075: public void processContinueRecord(byte[] data) {
076: if (isUnCompressedUnicode()) {
077: field_3_string += StringUtil.getFromUnicodeLE(data, 0,
078: field_1_string_length - field_3_string.length());
079: } else {
080: field_3_string += StringUtil.getFromCompressedUnicode(data,
081: 0, field_1_string_length - field_3_string.length());
082: }
083: }
084:
085: public boolean isInValueSection() {
086: return true;
087: }
088:
089: private int getStringByteLength() {
090: return isUnCompressedUnicode() ? field_1_string_length * 2
091: : field_1_string_length;
092: }
093:
094: /**
095: * gives the current serialized size of the record. Should include the sid and reclength (4 bytes).
096: */
097: public int getRecordSize() {
098: return 4 + 2 + 1 + getStringByteLength();
099: }
100:
101: /**
102: * is this uncompressed unicode (16bit)? Or just 8-bit compressed?
103: * @return isUnicode - True for 16bit- false for 8bit
104: */
105: public boolean isUnCompressedUnicode() {
106: return (field_2_unicode_flag == 1);
107: }
108:
109: /**
110: * called by the class that is responsible for writing this sucker.
111: * Subclasses should implement this so that their data is passed back in a
112: * byte array.
113: *
114: * @param offset to begin writing at
115: * @param data byte array containing instance data
116: * @return number of bytes written
117: */
118: public int serialize(int offset, byte[] data) {
119: LittleEndian.putShort(data, 0 + offset, sid);
120: LittleEndian.putShort(data, 2 + offset,
121: (short) (3 + getStringByteLength()));
122: LittleEndian.putUShort(data, 4 + offset, field_1_string_length);
123: data[6 + offset] = field_2_unicode_flag;
124: if (isUnCompressedUnicode()) {
125: StringUtil.putUnicodeLE(field_3_string, data, 7 + offset);
126: } else {
127: StringUtil.putCompressedUnicode(field_3_string, data,
128: 7 + offset);
129: }
130: return getRecordSize();
131: }
132:
133: /**
134: * return the non static version of the id for this record.
135: */
136: public short getSid() {
137: return sid;
138: }
139:
140: /**
141: * @return The string represented by this record.
142: */
143: public String getString() {
144: return field_3_string;
145: }
146:
147: /**
148: * Sets whether the string is compressed or not
149: * @param unicode_flag 1 = uncompressed, 0 = compressed
150: */
151: public void setCompressedFlag(byte unicode_flag) {
152: this .field_2_unicode_flag = unicode_flag;
153: }
154:
155: /**
156: * Sets the string represented by this record.
157: */
158: public void setString(String string) {
159: this .field_1_string_length = string.length();
160: this .field_3_string = string;
161: setCompressedFlag(StringUtil.hasMultibyte(string) ? (byte) 1
162: : (byte) 0);
163: }
164:
165: public String toString() {
166: StringBuffer buffer = new StringBuffer();
167:
168: buffer.append("[STRING]\n");
169: buffer.append(" .string = ").append(
170: field_3_string).append("\n");
171: buffer.append("[/STRING]\n");
172: return buffer.toString();
173: }
174:
175: public Object clone() {
176: StringRecord rec = new StringRecord();
177: rec.field_1_string_length = this.field_1_string_length;
178: rec.field_2_unicode_flag = this.field_2_unicode_flag;
179: rec.field_3_string = this.field_3_string;
180: return rec;
181:
182: }
183:
184: }
|