/* * file: Var2Data.java * author: Jon Iles * copyright: (c) Packwood Software 2002-2003 * date: 03/01/2003 */ /* * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * This library 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 for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ package net.sf.mpxj.mpp; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Date; import java.util.TreeMap; /** * This class represents a block of variable data. Each block of * data is represented by a 4 byte size, followed by the data itself. * Each Var2Data block should be associated with a MetaData block * which describes the layout of the data in the Var2Data block. */ final class Var2Data extends MPPComponent { /** * Constructor. Extracts the content of the data block, with reference * to the meta data held in the VarMeta block. * * @param meta meta data for this block * @param is InputStream from which data is read * @throws IOException on file read error */ Var2Data(VarMeta meta, InputStream is) throws IOException { m_meta = meta; byte[] data; int itemCount = m_meta.getItemCount(); int itemOffset; for (int loop = 0; loop < itemCount; loop++) { itemOffset = meta.getOffset(loop); is.reset(); is.skip(itemOffset); int size = readInt(is); data = readByteArray(is, size); m_map.put(Integer.valueOf(itemOffset), data); } } /** * This method retrieves a byte array containing the data at the * given offset in the block. If no data is found at the given offset * this method returns null. * * @param offset offset of required data * @return byte array containing required data */ public byte[] getByteArray(Integer offset) { byte[] result = null; if (offset != null) { result = m_map.get(offset); } return (result); } /** * This method retrieves a byte array of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return byte array containing required data */ public byte[] getByteArray(Integer id, Integer type) { return (getByteArray(m_meta.getOffset(id, type))); } /** * This method retrieves the data at the given offset and returns * it as a String, assuming the underlying data is composed of * two byte characters. * * @param offset offset of required data * @return string containing required data */ public String getUnicodeString(Integer offset) { String result = null; if (offset != null) { byte[] value = m_map.get(offset); if (value != null) { result = MPPUtility.getUnicodeString(value, 0); } } return (result); } /** * This method retrieves a String of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return string containing required data */ public String getUnicodeString(Integer id, Integer type) { return (getUnicodeString(m_meta.getOffset(id, type))); } /** * This method retrieves a timestamp of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return required timestamp data */ public Date getTimestamp(Integer id, Integer type) { Date result = null; Integer offset = m_meta.getOffset(id, type); if (offset != null) { byte[] value = m_map.get(offset); if (value != null && value.length >= 4) { result = MPPUtility.getTimestamp(value, 0); } } return (result); } /** * This method retrieves the data at the given offset and returns * it as a String, assuming the underlying data is composed of * single byte characters. * * @param offset offset of required data * @return string containing required data */ public String getString(Integer offset) { String result = null; if (offset != null) { byte[] value = m_map.get(offset); if (value != null) { result = MPPUtility.getString(value, 0); } } return (result); } /** * This method retrieves a string of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return required string data */ public String getString(Integer id, Integer type) { return (getString(m_meta.getOffset(id, type))); } /** * This method retrieves an integer of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return required integer data */ public int getShort(Integer id, Integer type) { int result = 0; Integer offset = m_meta.getOffset(id, type); if (offset != null) { byte[] value = m_map.get(offset); if (value != null && value.length >= 2) { result = MPPUtility.getShort(value, 0); } } return (result); } /** * This method retrieves an integer of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return required integer data */ public int getByte(Integer id, Integer type) { int result = 0; Integer offset = m_meta.getOffset(id, type); if (offset != null) { byte[] value = m_map.get(offset); if (value != null) { result = MPPUtility.getByte(value, 0); } } return (result); } /** * This method retrieves an integer of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return required integer data */ public int getInt(Integer id, Integer type) { int result = 0; Integer offset = m_meta.getOffset(id, type); if (offset != null) { byte[] value = m_map.get(offset); if (value != null && value.length >= 4) { result = MPPUtility.getInt(value, 0); } } return (result); } /** * This method retrieves an integer of the specified type, * belonging to the item with the specified unique ID. Note that * the integer value is read from an arbitrary offset within the * byte array of data. * * @param id unique ID of entity to which this data belongs * @param offset offset into the byte array fom which to read the integer * @param type data type identifier * @return required integer data */ public int getInt(Integer id, int offset, Integer type) { int result = 0; Integer metaOffset = m_meta.getOffset(id, type); if (metaOffset != null) { byte[] value = m_map.get(metaOffset); if (value != null && value.length >= offset + 4) { result = MPPUtility.getInt(value, offset); } } return (result); } /** * This method retrieves an integer of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return required integer data */ public long getLong(Integer id, Integer type) { long result = 0; Integer offset = m_meta.getOffset(id, type); if (offset != null) { byte[] value = m_map.get(offset); if (value != null && value.length >= 8) { result = MPPUtility.getLong(value, 0); } } return (result); } /** * This method retrieves a double of the specified type, * belonging to the item with the specified unique ID. * * @param id unique ID of entity to which this data belongs * @param type data type identifier * @return required double data */ public double getDouble(Integer id, Integer type) { double result = Double.longBitsToDouble(getLong(id, type)); if (Double.isNaN(result)) { result = 0; } return result; } /** * Retrieve the underlying meta data. This method is provided * mainly as a convenience for debugging. * * @return VarMeta instance */ public VarMeta getVarMeta() { return (m_meta); } /** * This method dumps the contents of this Var2Data block as a String. * Note that this facility is provided as a debugging aid. * * @return formatted contents of this block */ @Override public String toString() { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.println("BEGIN Var2Data"); for (Integer offset : m_map.keySet()) { byte[] data = m_map.get(offset); pw.println(" Data at offset: " + offset + " size: " + data.length); pw.println(MPPUtility.hexdump(data, true, 16, " ")); } pw.println("END Var2Data"); pw.println(); pw.close(); return (sw.toString()); } /** * This is a specialised version of the toString method which * outputs just the data in this structure for the given unique ID. * * @param id unique ID * @return string representation */ public String toString(Integer id) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.println("BEGIN Var2Data for " + id); for (Integer type : m_meta.getTypes(id)) { Integer offset = m_meta.getOffset(id, type); byte[] data = m_map.get(offset); pw.println(" Data at offset: " + offset + " size: " + data.length); pw.println(MPPUtility.hexdump(data, true, 16, " ")); } pw.println("END Var2Data for " + id); pw.println(); pw.close(); return (sw.toString()); } /** * Map containing data items indexed by offset. */ private TreeMap<Integer, byte[]> m_map = new TreeMap<Integer, byte[]>(); /** * Reference to the meta data associated with this block. */ private VarMeta m_meta; }