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.hwpf.model;
019:
020: import org.apache.poi.hwpf.model.io.HWPFOutputStream;
021: import org.apache.poi.poifs.common.POIFSConstants;
022:
023: import java.io.IOException;
024: import java.io.UnsupportedEncodingException;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: /**
029: * @author Ryan Ackley
030: */
031: public class TextPieceTable {
032: protected ArrayList _textPieces = new ArrayList();
033: //int _multiple;
034: int _cpMin;
035:
036: public TextPieceTable() {
037: }
038:
039: public TextPieceTable(byte[] documentStream, byte[] tableStream,
040: int offset, int size, int fcMin)
041: throws UnsupportedEncodingException {
042: // get our plex of PieceDescriptors
043: PlexOfCps pieceTable = new PlexOfCps(tableStream, offset, size,
044: PieceDescriptor.getSizeInBytes());
045:
046: //_multiple = 2;
047: int length = pieceTable.length();
048: PieceDescriptor[] pieces = new PieceDescriptor[length];
049:
050: // iterate through piece descriptors raw bytes and create
051: // PieceDescriptor objects
052: for (int x = 0; x < length; x++) {
053: GenericPropertyNode node = pieceTable.getProperty(x);
054: pieces[x] = new PieceDescriptor(node.getBytes(), 0);
055:
056: // if (!pieces[x].isUnicode())
057: // {
058: // _multiple = 1;
059: // }
060: }
061:
062: int firstPieceFilePosition = pieces[0].getFilePosition();
063: _cpMin = firstPieceFilePosition - fcMin;
064:
065: // using the PieceDescriptors, build our list of TextPieces.
066: for (int x = 0; x < pieces.length; x++) {
067: int start = pieces[x].getFilePosition();
068: PropertyNode node = pieceTable.getProperty(x);
069: int nodeStart = node.getStart();
070:
071: // multiple will be 2 if there is only one piece and its unicode. Some
072: // type of optimization.
073: boolean unicode = pieces[x].isUnicode();
074:
075: int multiple = 1;
076: if (unicode) {
077: multiple = 2;
078: }
079: int nodeEnd = ((node.getEnd() - nodeStart) * multiple)
080: + nodeStart;
081: int textSize = nodeEnd - nodeStart;
082:
083: byte[] buf = new byte[textSize];
084: System.arraycopy(documentStream, start, buf, 0, textSize);
085:
086: int startFilePosition = start - firstPieceFilePosition;
087: _textPieces.add(new TextPiece(startFilePosition,
088: startFilePosition + textSize, buf, pieces[x], node
089: .getStart()));
090: }
091: }
092:
093: public int getCpMin() {
094: return _cpMin;
095: }
096:
097: public List getTextPieces() {
098: return _textPieces;
099: }
100:
101: public byte[] writeTo(HWPFOutputStream docStream)
102: throws IOException {
103:
104: PlexOfCps textPlex = new PlexOfCps(PieceDescriptor
105: .getSizeInBytes());
106: //int fcMin = docStream.getOffset();
107:
108: int size = _textPieces.size();
109: int bumpDown = 0;
110: for (int x = 0; x < size; x++) {
111: TextPiece next = (TextPiece) _textPieces.get(x);
112: PieceDescriptor pd = next.getPieceDescriptor();
113:
114: int offset = docStream.getOffset();
115: int mod = (offset % POIFSConstants.BIG_BLOCK_SIZE);
116: if (mod != 0) {
117: mod = POIFSConstants.BIG_BLOCK_SIZE - mod;
118: byte[] buf = new byte[mod];
119: docStream.write(buf);
120: }
121:
122: // set the text piece position to the current docStream offset.
123: pd.setFilePosition(docStream.getOffset());
124:
125: // write the text to the docstream and save the piece descriptor to the
126: // plex which will be written later to the tableStream.
127: //if (_multiple == 1 && pd.isUnicode() &&
128: docStream.write(next.getRawBytes());
129:
130: int nodeStart = next.getStart();
131: int multiple = 1;
132: if (pd.isUnicode()) {
133: multiple = 2;
134: }
135: textPlex
136: .addProperty(new GenericPropertyNode(nodeStart
137: - bumpDown, ((next.getEnd() - nodeStart)
138: / multiple + nodeStart)
139: - bumpDown, pd.toByteArray()));
140:
141: if (pd.isUnicode()) {
142: bumpDown += ((next.getEnd() - nodeStart) / multiple);
143: }
144:
145: }
146:
147: return textPlex.toByteArray();
148:
149: }
150:
151: public int adjustForInsert(int listIndex, int length) {
152: int size = _textPieces.size();
153:
154: TextPiece tp = (TextPiece) _textPieces.get(listIndex);
155:
156: //The text piece stores the length on file.
157: length = length * (tp.usesUnicode() ? 2 : 1);
158: tp.setEnd(tp.getEnd() + length);
159: for (int x = listIndex + 1; x < size; x++) {
160: tp = (TextPiece) _textPieces.get(x);
161: tp.setStart(tp.getStart() + length);
162: tp.setEnd(tp.getEnd() + length);
163: }
164: return length;
165: }
166:
167: public boolean equals(Object o) {
168: TextPieceTable tpt = (TextPieceTable) o;
169:
170: int size = tpt._textPieces.size();
171: if (size == _textPieces.size()) {
172: for (int x = 0; x < size; x++) {
173: if (!tpt._textPieces.get(x).equals(_textPieces.get(x))) {
174: return false;
175: }
176: }
177: return true;
178: }
179: return false;
180: }
181: }
|