blob: 636d610d263416e93397dca5b11270eb89740522 [file] [log] [blame]
/**************************************************************
*
* 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.
*
*************************************************************/
package org.openoffice.xmerge.converter.xml.sxw.wordsmith;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.*;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
import org.openoffice.xmerge.converter.palm.*;
/**
* This class is used by {@link
* org.openoffice.xmerge.converter.xml.sxw.wordsmith.DocumentDeserializerImpl
* DocumentDeserializerImpl} to encode the WordSmith format.
*
* @author David Proulx
*/
// DJP: replace 4096 w/ a defined constant
final class WSEncoder {
/* DJP: These should probably go somewhere else! */
/** Constant for uncompressed version. */
public static final short UNCOMPRESSED = 1;
/** Constant for compressed version. */
public static final short COMPRESSED = 2;
/** Constant used for spare fields. */
public static final int SPARE = 0;
/* WordSmith Header information. */
private short version;
private int textLen;
private short maxRecSize;
private int textRecCount = 0;
/* WordSmith document elements. */
WseHeader header = null;
WseFontTable ft = null;
WseColorTable ct = null;
private Vector elements; // paragraphs & text runs
/* Totals for the WordSmith document. */
int nrParagraphs = 0;
int nrAtoms = 0;
int nrChars = 0;
/**
* Default constructor creates a header and
* a text buffer for holding all the text in
* the WordSmith database.
*/
WSEncoder() {
version = 1;
textLen = 0;
maxRecSize = 4096;
elements = new Vector();
}
/**
* This method adds a new element to the WordSmith document.
*
* @param elem WordSmith document element to add
*/
void addElement(Wse elem) {
if (elem.getClass() == WseHeader.class)
header = (WseHeader)elem;
else if (elem.getClass() == WseFontTable.class)
ft = (WseFontTable)elem;
else if (elem.getClass() == WseColorTable.class)
ct = (WseColorTable)elem;
else
elements.addElement(elem);
}
/**
* This method encodes the information given to
* an array of palm Records in the WordSmith database format.
*
* @return <code>Record</code> array holding WordSmith contents.
*
* @throws IOException If any I/O error occurs.
*/
Record[] getRecords() throws IOException {
Vector allRecs = new Vector();
int nElements = elements.size();
// Count up the number of paragraphs, atoms, and characters.
int currElement = 0;
while (currElement < nElements) {
Wse e = (Wse)elements.elementAt(currElement++);
if (e.getClass() == WsePara.class)
nrParagraphs++;
if (e.getClass() == WseTextRun.class) {
nrAtoms++;
nrChars += ((WseTextRun)e).getText().length();
}
}
byte[] currRec = new byte[4096];
int currRecLen = 0;
// This code assumes that the WordSmith header, font table,
// and color table total less than 4096 bytes.
header = new WseHeader(nrParagraphs, nrAtoms, nrChars, ft, ct);
System.arraycopy(header.getBytes(), 0,
currRec, currRecLen, header.getByteCount());
currRecLen += header.getByteCount();
if (ft != null) {
System.arraycopy(ft.getBytes(), 0, currRec, currRecLen,
ft.getByteCount());
currRecLen += ft.getByteCount();
}
if (ct != null) {
System.arraycopy(ct.getBytes(), 0, currRec, currRecLen,
ct.getByteCount());
currRecLen += ct.getByteCount();
}
currElement = 0;
while (currElement < nElements) {
Wse e = (Wse)elements.elementAt(currElement++);
int length = e.getByteCount();
if ((length + currRecLen) <= 4096) {
System.arraycopy(e.getBytes(), 0, currRec, currRecLen, length);
currRecLen += length;
} else {
// Copy in enough to get to full size, then create a
// new Record and add it to the Vector.
int firstPartLen = 4096 - currRecLen;
System.arraycopy(e.getBytes(), 0, currRec, currRecLen,
firstPartLen);
Record r = new Record(currRec);
allRecs.addElement(r);
// Put the remainder at the beginning of the next record
currRecLen = 0;
System.arraycopy(e.getBytes(), firstPartLen, currRec,
currRecLen, length - firstPartLen);
currRecLen += length - firstPartLen;
}
}
// Processed all the elements. Write out any remaining partial record.
if (currRecLen > 0) {
byte[] partial = new byte[currRecLen];
System.arraycopy(currRec, 0, partial, 0, currRecLen);
Record rr = new Record(partial);
allRecs.addElement(rr);
}
// Record 0 is the WordSmith header. Do it last since it
// contains totals for the entire document. It goes
// before everything else.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeShort(version);
dos.writeShort(0);
dos.writeInt(textLen);
dos.writeShort(allRecs.size());
dos.writeShort(maxRecSize);
dos.writeInt(0);
allRecs.insertElementAt(new Record(bos.toByteArray()), 0);
// Convert Vector of Records to an array and return it.
int nRecs = allRecs.size();
Record recs[] = new Record[nRecs];
for (int i = 0; i < nRecs; i++)
recs[i] = (Record)allRecs.elementAt(i);
return recs;
}
}