summaryrefslogtreecommitdiff
path: root/xmerge/source/xmerge/java/org/openoffice/xmerge/converter/palm/PalmDB.java
blob: 5e34469f9a49cbe4a4a8da27a5b2c4179d051198 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */

package org.openoffice.xmerge.converter.palm;

import java.io.OutputStream;
import java.io.InputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 *  <p>This class contains data for a single Palm database for use during
 *  a conversion process.</p>
 *
 *  <p>It contains zero or more <code>Record</code> objects stored in an
 *  array.  The index of the <code>Record</code> object in the array is
 *  the <code>Record</code> id or number for that specific <code>Record</code> object.
 *  Note that this class does not check for maximum number of Records
 *  allowable in an actual PDB.</p>
 *
 *  <p>This class also contains the PDB name associated with the Palm
 *  database it represents.  A PDB name consists of 32 bytes of a
 *  certain encoding (extended ASCII in this case).</p>
 *
 *  <p>The non default constructors take in a name parameter which may not
 *  be the exact PDB name to be used.  The name parameter in
 *  <code>String</code> or <code>byte</code> array are converted to an exact
 *  <code>NAME_LENGTH</code> byte array.  If the length of the name is less
 *  than <code>NAME_LENGTH</code>, it is padded with '\0' characters.  If it
 *  is more, it gets truncated.  The last character in the resulting byte
 *  array is always a '\0' character.  The resulting byte array is stored in
 *  <code>bName</code>, and a corresponding String object <code>sName</code>
 *  that contains characters without the '\0' characters.</p>
 *
 *  <p>The {@link #write write} method is called within the
 *  {@link org.openoffice.xmerge.converter.palm.PalmDocument#write
 *  PalmDocument.write} method for writing out its data to the <code>OutputStream</code>
 *  object.</p>
 *
 *  <p>The {@link #read read} method is called within the
 *  {@link org.openoffice.xmerge.converter.palm.PalmDocument#read
 *  PalmDocument.read} method for reading in its data from the <code>InputStream</code>
 *  object.</p>
 *
 *  @see     PalmDocument
 *  @see     Record
 */

public final class PalmDB {



    /**  Number of bytes for the name field in the PDB. */
    public final static int NAME_LENGTH = 32;

    /**  List of <code>Record</code> objects. */
    private Record[] records;

    /**  PDB name in bytes. */
    private byte[] bName = null;

    /**  PDB name in String. */
    private String sName = null;

    /**  Creator ID. */
    private int creatorID = 0;

    /**  Type ID */
    private int typeID = 0;

    /**
     *  PDB version. Palm UInt16.
     *  It is treated as a number here, since there is no unsigned 16 bit
     *  in Java, int is used instead, but only 2 bytes are written out or
     *  read in.
     */
    private int version = 0;

    /**
     *  PDB attribute - flags for the database.
     *  Palm UInt16. Unsignedness should be irrelevant.
     */
    private short attribute = 0;


    /**
     *  Default constructor.
     *
     *  @param  creatorID  The PDB Creator ID.
     *  @param  typeID     The PDB Type ID.
     *  @param  version    The PDB header version.
     *  @param  attribute  The PDB header attribute.
     */
    public PalmDB(int creatorID, int typeID, int version, short attribute) {

        records = new Record[0];
        setAttributes(creatorID, typeID, version, attribute);
    }


    /**
     *  Constructor to create <code>PalmDB</code> object with
     *  <code>Record</code> objects.  <code>recs.length</code>
     * can be zero for an empty PDB.
     *
     *  @param  name       Suggested PDB name in a <code>String</code>.
     *  @param  creatorID  The PDB Creator ID.
     *  @param  typeID     The PDB Type ID.
     *  @param  version    The PDB header version.
     *  @param  attribute  The PDB header attribute.
     *  @param  recs       Array of <code>Record</code> objects.
     *
     *  @throws  UnsupportedEncodingException  If <code>name</code> is
     *                                         not properly encoded.
     *  @throws  NullPointerException          If <code>recs</code> is null.
     */
    public PalmDB(String name, int creatorID, int typeID, int version,
        short attribute, Record[] recs)
        throws UnsupportedEncodingException {

        this(name.getBytes(PdbUtil.ENCODING), creatorID, typeID, version,
            attribute, recs);
    }


    /**
     *  Constructor to create object with <code>Record</code>
     *  objects.  <code>recs.length</code> can be zero for an
     *  empty PDB.
     *
     *  @param   name      Suggested PDB name in a <code>byte</code>
     *                     array.
     *  @param  creatorID  The PDB Creator ID.
     *  @param  typeID     The PDB Type ID.
     *  @param  version    The PDB header version.
     *  @param  attribute  The PDB header attribute.
     *  @param   recs      Array of <code>Record</code> objects.
     *
     *  @throws  UnsupportedEncodingException  If <code>name</code> is
     *                                         not properly encoded.
     *  @throws  NullPointerException          If recs is null.
     */
    public PalmDB(byte[] name, int creatorID, int typeID, int version,
        short attribute, Record[] recs) throws UnsupportedEncodingException {

        store(name);

        records = new Record[recs.length];
        System.arraycopy(recs, 0, records, 0, recs.length);
        setAttributes(creatorID, typeID, version, attribute);
    }


    /**
     *  Set the attributes for the <code>PalmDB</code> object.
     *
     *  @param  creatorID  The PDB Creator ID.
     *  @param  typeID     The PDB Type ID.
     *  @param  version    The PDB header version.
     *  @param  attribute  The PDB header attribute.
     */
    private void setAttributes (int creatorID, int typeID, int version, short attribute) {
        this.creatorID = creatorID;
        this.typeID = typeID;
        this.version = version;
        this.attribute = attribute;
    }


    /**
     *  This private method is mainly used by the constructors above.
     *  to store bytes into name and also create a <code>String</code>
     *  representation. and also by the <code>read</code> method.
     *
     *  TODO: Note that this method assumes that the <code>byte</code>
     *  array parameter contains one character per <code>byte</code>,
     *  else it would truncate improperly.
     *
     *  @param  bytes  PDB name in <code>byte</code> array.
     *
     *  @throws  UnsupportedEncodingException  If ENCODING is
     *           not supported.
     */
    private void store(byte[] bytes) throws UnsupportedEncodingException {

        // note that this will initialize all bytes in name to 0.
        bName = new byte[NAME_LENGTH];

        // determine minimum length to copy over from bytes to bName.
        // Note that the last byte in bName has to be '\0'.

        int lastIndex = NAME_LENGTH - 1;

        int len = (bytes.length < lastIndex)? bytes.length: lastIndex;

        int i;

        for (i = 0; i < len; i++) {

            if (bytes[i] == 0) {
                break;
            }

            bName[i] = bytes[i];
        }

        // set sName, no need to include the '\0' character.
        sName = new String(bName, 0, i, PdbUtil.ENCODING);
    }


    /**
     *  Returns creator ID.
     *
     *  @return  The creator ID.
     */
    public int getCreatorID() {

        return creatorID;
    }


    /**
     *  Returns type ID.
     *
     *  @return  The type ID.
     */
    public int getTypeID() {

        return typeID;
    }


    /**
     *  Returns attribute flag.
     *
     *  @return  The attribute flag.
     */
    public short getAttribute() {

        return attribute;
    }


    /**
     *  Returns version.
     *
     *  @return  The version.
     */
    public int getVersion() {

        return version;
    }


    /**
     *  Return the number of Records contained in this
     *  PDB <code>PalmDB</code> object.
     *
     *  @return  Number of <code>Record</code> objects.
     */
    public int getRecordCount() {

        return records.length;
    }


    /**
     *  Return the specific <code>Record</code> object associated
     *  with the <code>Record</code> number.
     *
     *  @param  index  <code>Record</code> index number.
     *
     *  @return  The <code>Record</code> object in the specified index
     *
     *  @throws  ArrayIndexOutOfBoundsException  If index is out of bounds.
     */
    public Record getRecord(int index) {

        return records[index];
    }


    /**
     *  Return the list of <code>Record</code> objects.
     *
     *  @return  The array of <code>Record</code> objects.
     */
    public Record[] getRecords() {

        return records;
    }

    /**
     *  Return the PDB name associated with this object.
     *
     *  @return  The PDB name.
     */
    public String getPDBNameString() {

        return sName;
    }


    /**
     *  Return the PDB name associated with this object in
     *  <code>byte</code> array of exact length of 32 bytes.
     *
     *  @return  The PDB name in <code>byte</code> array of
     *           length 32.
     */
    public byte[] getPDBNameBytes() {

        return bName;
    }


    /**
     *  Write out the number of Records followed by what
     *  will be written out by each <code>Record</code> object.
     *
     *  @param  os  The <code>OutputStream</code> to write the
     *              object.
     *
     *  @throws  IOException  If any I/O error occurs.
     */
    public void write(OutputStream os) throws IOException {

        DataOutputStream out = new DataOutputStream(os);

        // write out PDB name
        out.write(bName);

        // write out 2 bytes for number of records
        out.writeShort(records.length);

        // let each Record object write out its own info.
        for (Record record : records) {
            record.write(out);
        }
    }

    /**
     *  Read the necessary data to create a PDB from
     *  the <code>InputStream</code>.
     *
     *  @param  is  The <code>InputStream</code> to read data
     *              in order to restore the object.
     *
     *  @throws  IOException  If any I/O error occurs.
     */
    public void read(InputStream is) throws IOException {

        DataInputStream in = new DataInputStream(is);

        // read in the PDB name.
        byte[] bytes = new byte[NAME_LENGTH];
        in.readFully(bytes);
        store(bytes);

        // read in number of records
        int nrec = in.readUnsignedShort();
        records = new Record[nrec];

        // read in the Record infos
        for (int i = 0; i < nrec; i++) {

            records[i] = new Record();
            records[i].read(in);
        }
    }

    /**
     *  Override equals method of <code>Object</code>.
     *
     *  Two <code>PalmDB</code> objects are equal if they contain
     *  the same information, i.e. PDB name and Records.
     *
     *  This is used primarily for testing purposes only for now.
     *
     *  @param  obj  A <code>PalmDB</code> <code>Object</code> to
     *               compare.
     *
     *  @return  true if <code>obj</code> is equal to this, otherwise
     *           false.
     */
    @Override
    public boolean equals(Object obj) {

        boolean bool = false;

        if (obj instanceof PalmDB) {

            PalmDB pdb = (PalmDB) obj;

            checkLabel: {

                // compare sName

                if (!sName.equals(pdb.sName)) {

                    break checkLabel;
                }

                // compare bName

                if (bName.length != pdb.bName.length) {

                    break checkLabel;
                }

                for (int i = 0; i < bName.length; i++) {

                    if (bName[i] != pdb.bName[i]) {

                        break checkLabel;
                    }
                }

                // compare each Record

                if (records.length != pdb.records.length) {

                    break checkLabel;
                }

                for (int i = 0; i < records.length; i++) {

                    if (!records[i].equals(pdb.records[i])) {

                        break checkLabel;
                    }
                }

                // all checks done
                bool = true;
            }
        }

        return bool;
    }
}