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.palm;
25 
26 import java.io.OutputStream;
27 import java.io.InputStream;
28 import java.io.DataOutputStream;
29 import java.io.DataInputStream;
30 import java.io.IOException;
31 
32 /**
33  *  <p>Contains the raw bytes for a <code>Record</code> in a PDB.</p>
34  *
35  *  <p>Note that it is not associated with a <code>Record</code> number
36  *  or ID.</p>
37  *
38  *  @author  Akhil Arora, Herbie Ong
39  *  @see     PalmDocument
40  *  @see     PalmDB
41  */
42 public final class Record {
43 
44     /**  <code>Record</code> <code>byte</code> array. */
45     private byte[] data;
46 
47     /**  <code>Record</code> attributes. */
48     private byte attributes = 0;
49 
50 
51     /**
52      *  Default constructor.
53      */
Record()54     public Record() {
55 
56         data = new byte[0];
57     }
58 
59 
60     /**
61      *  <p>Constructor to create a <code>Record</code> filled with
62      *  bytes.</p>
63      *
64      *  <p>Note that this does not check for 64k <code>Record</code>
65      *  sizes.  User of this class must check for that.</p>
66      *
67      *  @param  d  <code>byte</code> array contents for this object.
68      */
Record(byte[] d)69     public Record(byte[] d) {
70 
71         this(d, (byte) 0);
72     }
73 
74 
75     /**
76      *  <p>Constructor to create a <code>Record</code> filled with
77      *  bytes and assign <code>Record</code> attributes.</p>
78      *
79      *  <p>Note that this does not check for 64k <code>Record</code>
80      *  sizes.  User of this class must check for that.</p>
81      *
82      *  @param  d      <code>byte</code> array contents for this object.
83      *  @param  attrs  <code>Record</code> attributes.
84      */
Record(byte[] d, byte attrs)85     public Record(byte[] d, byte attrs) {
86 
87         data = new byte[d.length];
88         attributes = attrs;
89         System.arraycopy(d, 0, data, 0, d.length);
90     }
91 
92 
93     /**
94      *  This method returns the number of bytes in this object.
95      *
96      *  @return  Number of bytes in this object.
97      */
getSize()98     public int getSize() {
99 
100         return data.length;
101     }
102 
103 
104     /**
105      *  This method returns the contents of this <code>Object</code>.
106      *
107      *  @return  Contents in <code>byte</code> array
108      */
getBytes()109     public byte[] getBytes() {
110 
111         return data;
112     }
113 
114 
115     /**
116      *  <p>This method returns the <code>Record</code> attributes.</p>
117      *
118      *  <blockquote><pre>
119      *  <code>Record</code> attributes consists of (from high to low bit)
120      *
121      *  delete (1) - dirty (1) - busy (1) - secret (1) - category (4)
122      *  </pre></blockquote>
123      *
124      *  @return   <code>Record</code> attribute.
125      */
getAttributes()126     public byte getAttributes() {
127 
128         return attributes;
129     }
130 
131 
132     /**
133      *  Write out the <code>Record</code> attributes and
134      *  <code>Record</code> length followed by the data in this
135      *  <code>Record</code> object.
136      *
137      *  @param  outs  The <code>OutputStream</code> to write the object.
138      *
139      *  @throws  IOException  If any I/O error occurs.
140      */
write(OutputStream outs)141     public void write(OutputStream outs) throws IOException {
142 
143         DataOutputStream out = new DataOutputStream(outs);
144         out.writeByte(attributes);
145         out.writeShort(data.length);
146         out.write(data);
147     }
148 
149 
150     /**
151      *  Read the necessary data to create a PDB from
152      *  the <code>InputStream</code>.
153      *
154      *  @param  ins  The <code>InputStream</code> to read data from
155      *              in order to restore the <code>object</code>.
156      *
157      *  @throws  IOException  If any I/O error occurs.
158      */
read(InputStream ins)159     public void read(InputStream ins) throws IOException {
160 
161         DataInputStream in = new DataInputStream(ins);
162         attributes = in.readByte();
163         int len = in.readUnsignedShort();
164         data = new byte[len];
165         in.readFully(data);
166     }
167 
168 
169     /**
170      *  <p>Override equals method of <code>Object</code>.</p>
171      *
172      *  <p>Two <code>Record</code> objects are equal if they contain
173      *  the same bytes in the array and the same attributes.</p>
174      *
175      *  <p>This is used primarily for testing purposes only for now.</p>
176      *
177      *  @param  obj  A <code>Record</code> object to compare with
178      *
179      *  @return  true if obj is equal, otherwise false.
180      */
equals(Object obj)181     public boolean equals(Object obj) {
182 
183         boolean bool = false;
184 
185         if (obj instanceof Record) {
186 
187             Record rec = (Record) obj;
188 
189             checkLabel: {
190 
191                 if (rec.getAttributes() != attributes) {
192 
193                     break checkLabel;
194                 }
195 
196                 if (rec.getSize() == data.length) {
197 
198                     for (int i = 0; i < data.length; i++) {
199 
200                         if (data[i] != rec.data[i]) {
201                             break checkLabel;
202                         }
203                     }
204 
205                     bool = true;
206                 }
207             }
208         }
209         return bool;
210     }
211 }
212 
213