/************************************************************************ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ 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; /** *

This class contains data for a single Palm database for use during * a conversion process.

* *

It contains zero or more Record objects stored in an * array. The index of the Record object in the array is * the Record id or number for that specific Record object. * Note that this class does not check for maximum number of Records * allowable in an actual PDB.

* *

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).

* *

The non default constructors take in a name parameter which may not * be the exact PDB name to be used. The name parameter in * String or byte array are converted to an exact * NAME_LENGTH byte array. If the length of the name is less * than NAME_LENGTH, 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 * bName, and a corresponding String object sName * that contains characters without the '\0' characters.

* *

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 OutputStream * object.

* *

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 InputStream * object.

* * @author Akhil Arora, Herbie Ong * @see PalmDocument * @see Record */ public final class PalmDB { /* Backup attribute for a PDB. This corresponds to dmHdrAttrBackup. */ public final static short PDB_HEADER_ATTR_BACKUP = 0x0008; /** Number of bytes for the name field in the PDB. */ public final static int NAME_LENGTH = 32; /** List of Record 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 PalmDB object with * Record objects. recs.length * can be zero for an empty PDB. * * @param name Suggested PDB name in a String. * @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 Record objects. * * @throws UnsupportedEncodingException If name is * not properly encoded. * @throws NullPointerException If recs 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 Record * objects. recs.length can be zero for an * empty PDB. * * @param name Suggested PDB name in a byte * 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 Record objects. * * @throws UnsupportedEncodingException If name 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 PalmDB 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. */ public 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 String * representation. and also by the read method. * * TODO: Note that this method assumes that the byte * array parameter contains one character per byte, * else it would truncate improperly. * * @param bytes PDB name in byte 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 PalmDB object. * * @return Number of Record objects. */ public int getRecordCount() { return records.length; } /** * Return the specific Record object associated * with the Record number. * * @param index Record index number. * * @return The Record 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 Record objects. * * @return The array of Record 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 * byte array of exact length of 32 bytes. * * @return The PDB name in byte array of * length 32. */ public byte[] getPDBNameBytes() { return bName; } /** * Write out the number of Records followed by what * will be written out by each Record object. * * @param os The OutputStream 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 (int i = 0; i < records.length; i++) records[i].write(out); } /** * Read the necessary data to create a PDB from * the InputStream. * * @param is The InputStream 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 Object. * * Two PalmDB 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 PalmDB Object to * compare. * * @return true if obj is equal to this, otherwise * false. */ 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; } }