1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 package org.openoffice.xmerge.converter.xml.sxw.aportisdoc; 25 26 import java.io.ByteArrayOutputStream; 27 import java.io.DataOutputStream; 28 import java.io.IOException; 29 import java.util.List; 30 import java.util.ArrayList; 31 32 import org.openoffice.xmerge.converter.palm.Record; 33 34 /** 35 * This class is used by {@link DocumentSerializerImpl} to encode the AportisDoc format. 36 * It does not deal with any XML tags. It only knows how to encode 37 * from <code>String</code>. 38 * 39 * @author Herbie Ong 40 */ 41 final class DocEncoder implements DocConstants { 42 43 /** Text buffer to contain text section. */ 44 private StringBuffer textBuffer = null; 45 46 /** Length of text section. */ 47 private int textLen = 0; 48 49 /** Number of text records. */ 50 private int textRecCount = 0; 51 52 53 /** 54 * Default constructor creates a header and 55 * a text buffer for holding all the text in 56 * the AportisDoc database. 57 */ DocEncoder()58 DocEncoder() { 59 60 textBuffer = new StringBuffer(TEXT_RECORD_SIZE); 61 } 62 63 64 /** 65 * This method appends text into the text section of 66 * the AportisDoc database. 67 * 68 * @param text <code>String</code> to append. 69 */ addText(String text)70 void addText(String text) { 71 72 textBuffer.append(text); 73 } 74 75 76 /** 77 * This method appends text into the text section of 78 * the AportisDoc database. 79 * 80 * @param text <code>char</code> array to append. 81 */ addText(char[] text)82 void addText(char[] text) { 83 84 textBuffer.append(text); 85 } 86 87 88 /** 89 * This method appends text character into the text 90 * section of the AportisDoc database. 91 * 92 * @param text <code>char</code> to append. 93 */ addText(char text)94 void addText(char text) { 95 96 textBuffer.append(text); 97 } 98 99 100 /** 101 * This method encodes the information given to a 102 * palm <code>Record</code> array in the AportisDoc 103 * database format. 104 * 105 * @return <code>Record</code> array holding AportisDoc 106 * contents. 107 * 108 * @throws IOException If any I/O error occurs. 109 */ getRecords()110 Record[] getRecords() throws IOException { 111 112 byte textBytes[] = processTextBuffer(); 113 textLen = textBytes.length; 114 textRecCount = (short) (textBytes.length / TEXT_RECORD_SIZE); 115 116 // recBytes to hold a record of bytes at a time 117 byte recBytes[] = new byte[TEXT_RECORD_SIZE]; 118 int pos = 0; 119 120 List textRecords = new ArrayList(textRecCount + 1); 121 122 // split textBytes into chunks of Record objects 123 // and store in textRecords object. 124 for (int i = 0; i < textRecCount; i++) { 125 126 System.arraycopy(textBytes, pos, recBytes, 0, recBytes.length); 127 pos += recBytes.length; 128 Record zRec = new Record(recBytes); 129 textRecords.add(zRec); 130 } 131 132 // there's more if ... 133 134 if (pos < textLen) { 135 136 textRecCount++; 137 138 recBytes = new byte[textLen - pos]; 139 System.arraycopy(textBytes, pos, recBytes, 0, recBytes.length); 140 Record rec = new Record(recBytes); 141 textRecords.add(rec); 142 } 143 144 // construct the Record array and copy 145 // references from textRecords. 146 147 Record[] allRecords = new Record[textRecords.size() + 1]; 148 149 allRecords[0] = new Record(getHeaderBytes()); 150 151 for (int i = 1; i < allRecords.length; i++) { 152 153 allRecords[i] = (Record) textRecords.get(i-1); 154 } 155 156 return allRecords; 157 } 158 159 160 /** 161 * This method converts the text buffer into a <code>byte</code> 162 * array with the proper encoding of the text section of the 163 * AportisDoc format. 164 * 165 * TODO: do compression. 166 * 167 * @return byte[] Converted <code>byte</code> array of text 168 * section. 169 * 170 * @throws IOException If any I/O error occurs. 171 */ processTextBuffer()172 private byte[] processTextBuffer() throws IOException 173 { 174 String str = textBuffer.toString(); 175 byte bytes[] = str.getBytes(ENCODING); 176 177 return bytes; 178 } 179 180 181 /** 182 * This method produces the <code>byte</code> array for the header. 183 * 184 * @return <code>byte</code> array containing header record data. 185 * 186 * @throws IOException If any I/O error occurs. 187 */ getHeaderBytes()188 private byte[] getHeaderBytes() throws IOException 189 { 190 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 191 DataOutputStream dos = new DataOutputStream(bos); 192 193 // TODO: for now, we shall use UNCOMPRESSED. 194 // later, we need to use COMPRESSED or a setting. 195 dos.writeShort(UNCOMPRESSED); 196 dos.writeShort(SPARE); 197 dos.writeInt(textLen); 198 dos.writeShort(textRecCount); 199 dos.writeShort(TEXT_RECORD_SIZE); 200 dos.writeInt(SPARE); 201 202 byte[] bytes = bos.toByteArray(); 203 204 return bytes; 205 } 206 } 207 208