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