1*04ea5bd4SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*04ea5bd4SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*04ea5bd4SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*04ea5bd4SAndrew Rist * distributed with this work for additional information 6*04ea5bd4SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*04ea5bd4SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*04ea5bd4SAndrew Rist * "License"); you may not use this file except in compliance 9*04ea5bd4SAndrew Rist * with the License. You may obtain a copy of the License at 10*04ea5bd4SAndrew Rist * 11*04ea5bd4SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12*04ea5bd4SAndrew Rist * 13*04ea5bd4SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*04ea5bd4SAndrew Rist * software distributed under the License is distributed on an 15*04ea5bd4SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*04ea5bd4SAndrew Rist * KIND, either express or implied. See the License for the 17*04ea5bd4SAndrew Rist * specific language governing permissions and limitations 18*04ea5bd4SAndrew Rist * under the License. 19*04ea5bd4SAndrew Rist * 20*04ea5bd4SAndrew Rist *************************************************************/ 21*04ea5bd4SAndrew Rist 22*04ea5bd4SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir import java.io.OutputStream; 25cdf0e10cSrcweir import java.io.InputStream; 26cdf0e10cSrcweir import java.io.DataOutputStream; 27cdf0e10cSrcweir import java.io.DataInputStream; 28cdf0e10cSrcweir import java.io.IOException; 29cdf0e10cSrcweir import java.io.UnsupportedEncodingException; 30cdf0e10cSrcweir 31cdf0e10cSrcweir /** 32cdf0e10cSrcweir * <p>This class contains data for a single Palm database for use during 33cdf0e10cSrcweir * a conversion process.</p> 34cdf0e10cSrcweir * 35cdf0e10cSrcweir * <p>It contains zero or more <code>Record</code> objects stored in an 36cdf0e10cSrcweir * array. The index of the <code>Record</code> object in the array is 37cdf0e10cSrcweir * the record id or number for that specific <code>Record</code> object. 38cdf0e10cSrcweir * Note that this class does not check for maximum number of records 39cdf0e10cSrcweir * allowable in an actual pdb.</p> 40cdf0e10cSrcweir * 41cdf0e10cSrcweir * <p>This class also contains the pdb name associated with the Palm database 42cdf0e10cSrcweir * it represents. A pdb name consists of 32 bytes of a certain encoding 43cdf0e10cSrcweir * (extended ASCII in this case).</p> 44cdf0e10cSrcweir * 45cdf0e10cSrcweir * <p>The non default constructors take in a name parameter which may not 46cdf0e10cSrcweir * be the exact pdb name to be used. The name parameter in 47cdf0e10cSrcweir * <code>String</code> or <code>byte[]</code> are converted to an exact 48cdf0e10cSrcweir * <code>NAME_LENGTH</code> byte array. If the length of the name is less 49cdf0e10cSrcweir * than <code>NAME_LENGTH</code>, it is padded with '\0' characters. If it 50cdf0e10cSrcweir * is more, it gets truncated. The last character in the resulting byte 51cdf0e10cSrcweir * array is always a '\0' character. The resulting byte array is stored in 52cdf0e10cSrcweir * <code>bName</code>, and a corresponding String object <code>sName</code> 53cdf0e10cSrcweir * that contains characters without the '\0' characters.</p> 54cdf0e10cSrcweir * 55cdf0e10cSrcweir * <p>The {@link #write write} method is called within the 56cdf0e10cSrcweir * {@link zensync.util.palm.PalmDBSet#write PalmDBSet.write} method 57cdf0e10cSrcweir * for writing out its data to the <code>OutputStream</code> object.</p> 58cdf0e10cSrcweir * 59cdf0e10cSrcweir * <p>The {@link #read read} method is called within the 60cdf0e10cSrcweir * {@link zensync.util.palm.PalmDBSet#read PalmDBSet.read} method 61cdf0e10cSrcweir * for reading in its data from the <code>InputStream</code> object.</p> 62cdf0e10cSrcweir * 63cdf0e10cSrcweir * @author Akhil Arora, Herbie Ong 64cdf0e10cSrcweir * @see PalmDBSet 65cdf0e10cSrcweir * @see Record 66cdf0e10cSrcweir */ 67cdf0e10cSrcweir 68cdf0e10cSrcweir public final class PalmDB { 69cdf0e10cSrcweir 70cdf0e10cSrcweir /** number of bytes for the name field in the pdb */ 71cdf0e10cSrcweir public final static int NAME_LENGTH = 32; 72cdf0e10cSrcweir 73cdf0e10cSrcweir /** list of Record objects */ 74cdf0e10cSrcweir private Record[] records; 75cdf0e10cSrcweir 76cdf0e10cSrcweir /** pdb name in bytes */ 77cdf0e10cSrcweir private byte[] bName = null; 78cdf0e10cSrcweir 79cdf0e10cSrcweir /** pdb name in String */ 80cdf0e10cSrcweir private String sName = null; 81cdf0e10cSrcweir 82cdf0e10cSrcweir 83cdf0e10cSrcweir /** 84cdf0e10cSrcweir * Default constructor for use after a read(). 85cdf0e10cSrcweir */ 86cdf0e10cSrcweir PalmDB()87cdf0e10cSrcweir public PalmDB() { 88cdf0e10cSrcweir 89cdf0e10cSrcweir records = new Record[0]; 90cdf0e10cSrcweir } 91cdf0e10cSrcweir 92cdf0e10cSrcweir /** 93cdf0e10cSrcweir * Constructor to create object with Record objects. 94cdf0e10cSrcweir * recs.length can be zero for an empty pdb. 95cdf0e10cSrcweir * 96cdf0e10cSrcweir * @param name suggested pdb name in String 97cdf0e10cSrcweir * @param recs array of Record objects 98cdf0e10cSrcweir * @throws NullPointerException if recs is null 99cdf0e10cSrcweir */ 100cdf0e10cSrcweir PalmDB(String name, Record[] recs)101cdf0e10cSrcweir public PalmDB(String name, Record[] recs) 102cdf0e10cSrcweir throws UnsupportedEncodingException { 103cdf0e10cSrcweir 104cdf0e10cSrcweir this(name.getBytes(PDBUtil.ENCODING), recs); 105cdf0e10cSrcweir } 106cdf0e10cSrcweir 107cdf0e10cSrcweir /** 108cdf0e10cSrcweir * Constructor to create object with Record objects. 109cdf0e10cSrcweir * recs.length can be zero for an empty pdb. 110cdf0e10cSrcweir * 111cdf0e10cSrcweir * @param name suggested pdb name in byte array 112cdf0e10cSrcweir * @param recs array of Record objects 113cdf0e10cSrcweir * @throws NullPointerException if recs is null 114cdf0e10cSrcweir */ 115cdf0e10cSrcweir PalmDB(byte[] name, Record[] recs)116cdf0e10cSrcweir public PalmDB(byte[] name, Record[] recs) 117cdf0e10cSrcweir throws UnsupportedEncodingException { 118cdf0e10cSrcweir 119cdf0e10cSrcweir store(name); 120cdf0e10cSrcweir 121cdf0e10cSrcweir records = new Record[recs.length]; 122cdf0e10cSrcweir System.arraycopy(recs, 0, records, 0, recs.length); 123cdf0e10cSrcweir } 124cdf0e10cSrcweir 125cdf0e10cSrcweir /** 126cdf0e10cSrcweir * This private method is mainly used by the constructors above. 127cdf0e10cSrcweir * to store bytes into name and also create a String representation. 128cdf0e10cSrcweir * and also by the read method. 129cdf0e10cSrcweir * 130cdf0e10cSrcweir * TODO: Note that this method assumes that the byte array parameter 131cdf0e10cSrcweir * contains one character per byte, else it would truncate 132cdf0e10cSrcweir * improperly. 133cdf0e10cSrcweir * 134cdf0e10cSrcweir * @param bytes pdb name in byte array 135cdf0e10cSrcweir * @throws UnsupportedEncodingException if ENCODING is not supported 136cdf0e10cSrcweir */ 137cdf0e10cSrcweir store(byte[] bytes)138cdf0e10cSrcweir private void store(byte[] bytes) throws UnsupportedEncodingException { 139cdf0e10cSrcweir 140cdf0e10cSrcweir // note that this will initialize all bytes in name to 0. 141cdf0e10cSrcweir bName = new byte[NAME_LENGTH]; 142cdf0e10cSrcweir 143cdf0e10cSrcweir // determine minimum length to copy over from bytes to bName. 144cdf0e10cSrcweir // Note that the last byte in bName has to be '\0'. 145cdf0e10cSrcweir 146cdf0e10cSrcweir int lastIndex = NAME_LENGTH - 1; 147cdf0e10cSrcweir 148cdf0e10cSrcweir int len = (bytes.length < lastIndex)? bytes.length: lastIndex; 149cdf0e10cSrcweir 150cdf0e10cSrcweir int i; 151cdf0e10cSrcweir 152cdf0e10cSrcweir for (i = 0; i < len; i++) { 153cdf0e10cSrcweir 154cdf0e10cSrcweir if (bytes[i] == 0) { 155cdf0e10cSrcweir break; 156cdf0e10cSrcweir } 157cdf0e10cSrcweir 158cdf0e10cSrcweir bName[i] = bytes[i]; 159cdf0e10cSrcweir } 160cdf0e10cSrcweir 161cdf0e10cSrcweir // set sName, no need to include the '\0' character. 162cdf0e10cSrcweir sName = new String(bName, 0, i, PDBUtil.ENCODING); 163cdf0e10cSrcweir } 164cdf0e10cSrcweir 165cdf0e10cSrcweir /** 166cdf0e10cSrcweir * Return the number of records contained in this 167cdf0e10cSrcweir * pdb PalmDB object. 168cdf0e10cSrcweir * 169cdf0e10cSrcweir * @return int number of Record objects 170cdf0e10cSrcweir */ 171cdf0e10cSrcweir getRecordCount()172cdf0e10cSrcweir public int getRecordCount() { 173cdf0e10cSrcweir 174cdf0e10cSrcweir return records.length; 175cdf0e10cSrcweir } 176cdf0e10cSrcweir 177cdf0e10cSrcweir /** 178cdf0e10cSrcweir * Return the specific Record object associated 179cdf0e10cSrcweir * with the record number. 180cdf0e10cSrcweir * 181cdf0e10cSrcweir * @param index record index number 182cdf0e10cSrcweir * @return Record the Record object in the specified index 183cdf0e10cSrcweir * @throws ArrayIndexOutOfBoundsException if index is out of bounds 184cdf0e10cSrcweir */ 185cdf0e10cSrcweir getRecord(int index)186cdf0e10cSrcweir public Record getRecord(int index) { 187cdf0e10cSrcweir 188cdf0e10cSrcweir return records[index]; 189cdf0e10cSrcweir } 190cdf0e10cSrcweir 191cdf0e10cSrcweir /** 192cdf0e10cSrcweir * Return the list of Record objects 193cdf0e10cSrcweir * 194cdf0e10cSrcweir * @return Record[] the list of Record objects 195cdf0e10cSrcweir */ 196cdf0e10cSrcweir getRecords()197cdf0e10cSrcweir public Record[] getRecords() { 198cdf0e10cSrcweir 199cdf0e10cSrcweir return records; 200cdf0e10cSrcweir } 201cdf0e10cSrcweir 202cdf0e10cSrcweir /** 203cdf0e10cSrcweir * Return the PDBName associated with this object in String 204cdf0e10cSrcweir * 205cdf0e10cSrcweir * @return String pdb name in String 206cdf0e10cSrcweir */ 207cdf0e10cSrcweir getPDBNameString()208cdf0e10cSrcweir public String getPDBNameString() { 209cdf0e10cSrcweir 210cdf0e10cSrcweir return sName; 211cdf0e10cSrcweir } 212cdf0e10cSrcweir 213cdf0e10cSrcweir /** 214cdf0e10cSrcweir * Return the PDBName associated with this object 215cdf0e10cSrcweir * in byte array of exact length of 32 bytes. 216cdf0e10cSrcweir * 217cdf0e10cSrcweir * @return byte[] pdb name in byte[] of length 32. 218cdf0e10cSrcweir */ 219cdf0e10cSrcweir getPDBNameBytes()220cdf0e10cSrcweir public byte[] getPDBNameBytes() { 221cdf0e10cSrcweir 222cdf0e10cSrcweir return bName; 223cdf0e10cSrcweir } 224cdf0e10cSrcweir 225cdf0e10cSrcweir /** 226cdf0e10cSrcweir * Write out the number of records followed by what 227cdf0e10cSrcweir * will be written out by each Record object. 228cdf0e10cSrcweir * 229cdf0e10cSrcweir * @param os the stream to write the object to 230cdf0e10cSrcweir * @throws IOException if any I/O error occurs 231cdf0e10cSrcweir */ 232cdf0e10cSrcweir write(OutputStream os)233cdf0e10cSrcweir public void write(OutputStream os) throws IOException { 234cdf0e10cSrcweir 235cdf0e10cSrcweir DataOutputStream out = new DataOutputStream(os); 236cdf0e10cSrcweir 237cdf0e10cSrcweir // write out pdb name 238cdf0e10cSrcweir out.write(bName); 239cdf0e10cSrcweir 240cdf0e10cSrcweir // write out 2 bytes for number of records 241cdf0e10cSrcweir out.writeShort(records.length); 242cdf0e10cSrcweir 243cdf0e10cSrcweir // let each Record object write out its own info. 244cdf0e10cSrcweir for (int i = 0; i < records.length; i++) 245cdf0e10cSrcweir records[i].write(out); 246cdf0e10cSrcweir } 247cdf0e10cSrcweir 248cdf0e10cSrcweir /** 249cdf0e10cSrcweir * Read the necessary data to create a pdb from 250cdf0e10cSrcweir * the input stream. 251cdf0e10cSrcweir * 252cdf0e10cSrcweir * @param is the stream to read data from in order 253cdf0e10cSrcweir * to restore the object 254cdf0e10cSrcweir * @throws IOException if any I/O error occurs 255cdf0e10cSrcweir */ 256cdf0e10cSrcweir read(InputStream is)257cdf0e10cSrcweir public void read(InputStream is) throws IOException { 258cdf0e10cSrcweir 259cdf0e10cSrcweir DataInputStream in = new DataInputStream(is); 260cdf0e10cSrcweir 261cdf0e10cSrcweir // read in the pdb name. 262cdf0e10cSrcweir byte[] bytes = new byte[NAME_LENGTH]; 263cdf0e10cSrcweir in.readFully(bytes); 264cdf0e10cSrcweir store(bytes); 265cdf0e10cSrcweir 266cdf0e10cSrcweir // read in number of records 267cdf0e10cSrcweir int nrec = in.readUnsignedShort(); 268cdf0e10cSrcweir records = new Record[nrec]; 269cdf0e10cSrcweir 270cdf0e10cSrcweir // read in the Record infos 271cdf0e10cSrcweir for (int i = 0; i < nrec; i++) { 272cdf0e10cSrcweir 273cdf0e10cSrcweir records[i] = new Record(); 274cdf0e10cSrcweir records[i].read(in); 275cdf0e10cSrcweir } 276cdf0e10cSrcweir } 277cdf0e10cSrcweir 278cdf0e10cSrcweir /** 279cdf0e10cSrcweir * Override equals method of Object. 280cdf0e10cSrcweir * 281cdf0e10cSrcweir * 2 PalmDB objects are equal if they contain the same information, 282cdf0e10cSrcweir * i.e. pdb name and records. 283cdf0e10cSrcweir * 284cdf0e10cSrcweir * This is used primarily for testing purposes only for now. 285cdf0e10cSrcweir * 286cdf0e10cSrcweir * @param obj a PalmDB object to compare with 287cdf0e10cSrcweir * @return boolean true if obj is equal to this, else false. 288cdf0e10cSrcweir */ 289cdf0e10cSrcweir equals(Object obj)290cdf0e10cSrcweir public boolean equals(Object obj) { 291cdf0e10cSrcweir 292cdf0e10cSrcweir boolean bool = false; 293cdf0e10cSrcweir 294cdf0e10cSrcweir if (obj instanceof PalmDB) { 295cdf0e10cSrcweir 296cdf0e10cSrcweir PalmDB pdb = (PalmDB) obj; 297cdf0e10cSrcweir 298cdf0e10cSrcweir checkLabel: { 299cdf0e10cSrcweir 300cdf0e10cSrcweir // compare sName 301cdf0e10cSrcweir 302cdf0e10cSrcweir if (!sName.equals(pdb.sName)) { 303cdf0e10cSrcweir 304cdf0e10cSrcweir break checkLabel; 305cdf0e10cSrcweir } 306cdf0e10cSrcweir 307cdf0e10cSrcweir // compare bName 308cdf0e10cSrcweir 309cdf0e10cSrcweir if (bName.length != pdb.bName.length) { 310cdf0e10cSrcweir 311cdf0e10cSrcweir break checkLabel; 312cdf0e10cSrcweir } 313cdf0e10cSrcweir 314cdf0e10cSrcweir for (int i = 0; i < bName.length; i++) { 315cdf0e10cSrcweir 316cdf0e10cSrcweir if (bName[i] != pdb.bName[i]) { 317cdf0e10cSrcweir 318cdf0e10cSrcweir break checkLabel; 319cdf0e10cSrcweir } 320cdf0e10cSrcweir } 321cdf0e10cSrcweir 322cdf0e10cSrcweir // compare each Record 323cdf0e10cSrcweir 324cdf0e10cSrcweir if (records.length != pdb.records.length) { 325cdf0e10cSrcweir 326cdf0e10cSrcweir break checkLabel; 327cdf0e10cSrcweir } 328cdf0e10cSrcweir 329cdf0e10cSrcweir for (int i = 0; i < records.length; i++) { 330cdf0e10cSrcweir 331cdf0e10cSrcweir if (!records[i].equals(pdb.records[i])) { 332cdf0e10cSrcweir 333cdf0e10cSrcweir break checkLabel; 334cdf0e10cSrcweir } 335cdf0e10cSrcweir } 336cdf0e10cSrcweir 337cdf0e10cSrcweir // all checks done 338cdf0e10cSrcweir bool = true; 339cdf0e10cSrcweir } 340cdf0e10cSrcweir } 341cdf0e10cSrcweir 342cdf0e10cSrcweir return bool; 343cdf0e10cSrcweir } 344cdf0e10cSrcweir } 345