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