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 
25 import java.io.RandomAccessFile;
26 import java.io.IOException;
27 
28 
29 /**
30  *  <p>Provides functionality to decode a pdb formatted file into
31  *  a <code>PalmDB</code> object given a file input stream</p>
32  *
33  *  <p>Sample usage:</p>
34  *
35  *  <p><blockquote><pre>
36  *     PDBDecoder decoder = new PDBDecoder("sample.pdb");
37  *     PalmDB palmDB = decoder.parse();
38  *  </pre></blockquote></p>
39  *
40  *  <p>Refer to the
41  *  <a href="http://starlite.eng/zensync/eng/converters/palmfileformats.pdf">
42  *  Palm file format specification</a> for details on the pdb format.</p>
43  *
44  *  <p>This decoder has the following assumptions on the pdb file ...</p>
45  *  <ol>
46  *  <li><p>There is only one RecordList section in the pdb.</p></li>
47  *  <li><p>The record indices in the RecordList are sorted in order, i.e. the
48  *      first record index refers to record 0, and so forth.</p></li>
49  *  <li><p>The raw records in the record section are sorted as well in order,
50  *      i.e. first record comes ahead of second record, etc.</p></li>
51  *  </ol>
52  *
53  *  Other decoders assume these as well.
54  *
55  *  @author    Herbie Ong
56  *  @see    PalmDB
57  *  @see    PDBHeader
58  *
59  *  @author    Herbie Ong
60  */
61 
62 public final class PDBDecoder {
63 
64     /**
65      *  <p>This method decodes a pdb file into a PalmDB object.</p>
66      *
67      *  <p>First, read in the header data using <code>PDBHeader</code>'s
68      *  <code>read</code> method</p>.  Next, read in the record list
69      *  section.  Store the record offsets for use when parsing the records.
70      *  Based on these offsets, read in each record's bytes and store
71      *  each in a <code>Record</code> object.  Lastly, create a
72      *  <code>PalmDB</code> object with the read in <code>Record</code>s.
73      *
74      *  @param   fileName    pdb file name
75      *  @throws   IOException    if I/O error occurs
76      */
77 
parse(String fileName)78     public PalmDB parse(String fileName) throws IOException {
79 
80         RandomAccessFile file = new RandomAccessFile(fileName, "r");
81 
82         // read the pdb header
83         PDBHeader header = new PDBHeader();
84         header.read(file);
85 
86         Record recArray[] = new Record[header.numRecords];
87 
88         if (header.numRecords != 0) {
89 
90             // read in the record indices + offsets
91 
92             int recOffset[] = new int[header.numRecords];
93 
94             for (int i = 0; i < header.numRecords; i++) {
95 
96                 recOffset[i] = file.readInt();
97                 int attr = file.readInt();    // read in attribute.
98             }
99 
100             // read the records
101 
102             int len = 0;
103             byte[] bytes = null;
104 
105             int lastIndex = header.numRecords - 1;
106 
107             for (int i = 0; i < lastIndex; i++) {
108 
109                 file.seek(recOffset[i]);
110                 len = recOffset[i+1] - recOffset[i];
111                 bytes = new byte[len];
112                 file.readFully(bytes);
113                 recArray[i] = new Record(bytes);
114             }
115 
116             // last record
117             file.seek(recOffset[lastIndex]);
118             len = (int) file.length() - recOffset[lastIndex];
119             bytes = new byte[len];
120             file.readFully(bytes);
121             recArray[lastIndex] = new Record(bytes);
122         }
123 
124         file.close();
125 
126         // create PalmDB and return it
127         PalmDB pdb = new PalmDB(header.pdbName, recArray);
128         return pdb;
129     }
130 }
131 
132