2004-04-09 09:05:39 -04:00
|
|
|
/* ====================================================================
|
2006-12-22 14:18:16 -05:00
|
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
|
|
this work for additional information regarding copyright ownership.
|
|
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
|
|
(the "License"); you may not use this file except in compliance with
|
|
|
|
the License. You may obtain a copy of the License at
|
2004-04-09 09:05:39 -04:00
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
==================================================================== */
|
2009-06-01 17:07:20 -04:00
|
|
|
|
2002-02-13 23:00:59 -05:00
|
|
|
package org.apache.poi.hpsf;
|
|
|
|
|
2003-12-02 12:46:01 -05:00
|
|
|
import java.io.UnsupportedEncodingException;
|
2011-10-02 04:58:11 -04:00
|
|
|
import java.util.LinkedHashMap;
|
2003-08-02 15:02:28 -04:00
|
|
|
import java.util.Map;
|
2003-08-23 11:12:22 -04:00
|
|
|
|
2003-12-02 12:46:01 -05:00
|
|
|
import org.apache.poi.util.HexDump;
|
2002-05-26 18:18:40 -04:00
|
|
|
import org.apache.poi.util.LittleEndian;
|
2008-02-08 06:55:43 -05:00
|
|
|
import org.apache.poi.util.POILogFactory;
|
|
|
|
import org.apache.poi.util.POILogger;
|
2002-02-13 23:00:59 -05:00
|
|
|
|
|
|
|
/**
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>A property in a {@link Section} of a {@link PropertySet}.</p>
|
2002-02-13 23:00:59 -05:00
|
|
|
*
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>The property's <strong>ID</strong> gives the property a meaning
|
|
|
|
* in the context of its {@link Section}. Each {@link Section} spans
|
|
|
|
* its own name space of property IDs.</p>
|
2002-02-13 23:00:59 -05:00
|
|
|
*
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>The property's <strong>type</strong> determines how its
|
|
|
|
* <strong>value </strong> is interpreted. For example, if the type is
|
|
|
|
* {@link Variant#VT_LPSTR} (byte string), the value consists of a
|
2002-07-22 04:25:19 -04:00
|
|
|
* DWord telling how many bytes the string contains. The bytes follow
|
|
|
|
* immediately, including any null bytes that terminate the
|
2002-07-18 11:51:39 -04:00
|
|
|
* string. The type {@link Variant#VT_I4} denotes a four-byte integer
|
|
|
|
* value, {@link Variant#VT_FILETIME} some date and time (of a
|
|
|
|
* file).</p>
|
2002-02-13 23:00:59 -05:00
|
|
|
*
|
2003-08-30 05:13:53 -04:00
|
|
|
* <p>Please note that not all {@link Variant} types yet. This might change
|
|
|
|
* over time but largely depends on your feedback so that the POI team knows
|
|
|
|
* which variant types are really needed. So please feel free to submit error
|
|
|
|
* reports or patches for the types you need.</p>
|
2009-08-18 12:50:24 -04:00
|
|
|
*
|
2005-04-01 11:58:00 -05:00
|
|
|
* <p>Microsoft documentation: <a
|
|
|
|
* href="http://msdn.microsoft.com/library/en-us/stg/stg/property_set_display_name_dictionary.asp?frame=true">
|
|
|
|
* Property Set Display Name Dictionary</a>.
|
2002-02-13 23:00:59 -05:00
|
|
|
*
|
2003-08-30 05:13:53 -04:00
|
|
|
* @author Rainer Klute <a
|
|
|
|
* href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
|
2002-07-18 11:51:39 -04:00
|
|
|
* @author Drew Varner (Drew.Varner InAndAround sc.edu)
|
|
|
|
* @see Section
|
|
|
|
* @see Variant
|
2002-02-13 23:00:59 -05:00
|
|
|
*/
|
2002-07-18 11:51:39 -04:00
|
|
|
public class Property
|
|
|
|
{
|
2002-02-13 23:00:59 -05:00
|
|
|
|
2003-08-02 15:02:28 -04:00
|
|
|
/** <p>The property's ID.</p> */
|
2003-08-30 05:13:53 -04:00
|
|
|
protected long id;
|
2002-02-13 23:00:59 -05:00
|
|
|
|
2002-05-11 10:47:24 -04:00
|
|
|
|
2002-02-13 23:00:59 -05:00
|
|
|
/**
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>Returns the property's ID.</p>
|
2002-05-11 10:47:24 -04:00
|
|
|
*
|
2002-07-18 11:51:39 -04:00
|
|
|
* @return The ID value
|
2002-02-13 23:00:59 -05:00
|
|
|
*/
|
2003-08-30 05:13:53 -04:00
|
|
|
public long getID()
|
2002-07-18 11:51:39 -04:00
|
|
|
{
|
2002-02-13 23:00:59 -05:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-08-02 15:02:28 -04:00
|
|
|
/** <p>The property's type.</p> */
|
2003-08-03 16:16:46 -04:00
|
|
|
protected long type;
|
2002-05-11 10:47:24 -04:00
|
|
|
|
2002-02-13 23:00:59 -05:00
|
|
|
|
|
|
|
/**
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>Returns the property's type.</p>
|
2002-05-11 10:47:24 -04:00
|
|
|
*
|
2002-07-18 11:51:39 -04:00
|
|
|
* @return The type value
|
2002-02-13 23:00:59 -05:00
|
|
|
*/
|
2002-07-18 11:51:39 -04:00
|
|
|
public long getType()
|
|
|
|
{
|
2002-02-13 23:00:59 -05:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-08-02 15:02:28 -04:00
|
|
|
/** <p>The property's value.</p> */
|
2003-08-03 16:16:46 -04:00
|
|
|
protected Object value;
|
2002-02-13 23:00:59 -05:00
|
|
|
|
2002-05-11 10:47:24 -04:00
|
|
|
|
2002-02-13 23:00:59 -05:00
|
|
|
/**
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>Returns the property's value.</p>
|
2002-05-11 10:47:24 -04:00
|
|
|
*
|
2002-07-18 11:51:39 -04:00
|
|
|
* @return The property's value
|
2002-02-13 23:00:59 -05:00
|
|
|
*/
|
2002-07-18 11:51:39 -04:00
|
|
|
public Object getValue()
|
|
|
|
{
|
2002-02-13 23:00:59 -05:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-03-03 11:57:55 -05:00
|
|
|
/**
|
|
|
|
* <p>Creates a property.</p>
|
2009-08-18 12:50:24 -04:00
|
|
|
*
|
2006-03-03 11:57:55 -05:00
|
|
|
* @param id the property's ID.
|
|
|
|
* @param type the property's type, see {@link Variant}.
|
2008-02-08 06:55:43 -05:00
|
|
|
* @param value the property's value. Only certain types are allowed, see
|
|
|
|
* {@link Variant}.
|
2006-03-03 11:57:55 -05:00
|
|
|
*/
|
|
|
|
public Property(final long id, final long type, final Object value)
|
|
|
|
{
|
|
|
|
this.id = id;
|
|
|
|
this.type = type;
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-02-13 23:00:59 -05:00
|
|
|
/**
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>Creates a {@link Property} instance by reading its bytes
|
|
|
|
* from the property set stream.</p>
|
2002-02-13 23:00:59 -05:00
|
|
|
*
|
2002-07-18 11:51:39 -04:00
|
|
|
* @param id The property's ID.
|
|
|
|
* @param src The bytes the property set stream consists of.
|
|
|
|
* @param offset The property's type/value pair's offset in the
|
|
|
|
* section.
|
|
|
|
* @param length The property's type/value pair's length in bytes.
|
2002-12-10 01:15:20 -05:00
|
|
|
* @param codepage The section's and thus the property's
|
|
|
|
* codepage. It is needed only when reading string values.
|
2003-12-02 12:46:01 -05:00
|
|
|
* @exception UnsupportedEncodingException if the specified codepage is not
|
2004-06-22 12:11:39 -04:00
|
|
|
* supported.
|
2002-02-13 23:00:59 -05:00
|
|
|
*/
|
2003-08-30 05:13:53 -04:00
|
|
|
public Property(final long id, final byte[] src, final long offset,
|
2003-08-02 15:02:28 -04:00
|
|
|
final int length, final int codepage)
|
2003-12-02 12:46:01 -05:00
|
|
|
throws UnsupportedEncodingException
|
2002-07-18 11:51:39 -04:00
|
|
|
{
|
2002-02-13 23:00:59 -05:00
|
|
|
this.id = id;
|
|
|
|
|
2002-05-11 10:47:24 -04:00
|
|
|
/*
|
2002-12-10 01:15:20 -05:00
|
|
|
* ID 0 is a special case since it specifies a dictionary of
|
|
|
|
* property IDs and property names.
|
2002-05-11 10:47:24 -04:00
|
|
|
*/
|
2002-07-18 11:51:39 -04:00
|
|
|
if (id == 0)
|
2003-08-02 15:02:28 -04:00
|
|
|
{
|
2002-12-10 01:15:20 -05:00
|
|
|
value = readDictionary(src, offset, length, codepage);
|
2002-02-13 23:00:59 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-05-11 10:47:24 -04:00
|
|
|
int o = (int) offset;
|
|
|
|
type = LittleEndian.getUInt(src, o);
|
|
|
|
o += LittleEndian.INT_SIZE;
|
2002-02-13 23:00:59 -05:00
|
|
|
|
2003-08-02 15:02:28 -04:00
|
|
|
try
|
|
|
|
{
|
2003-12-02 12:46:01 -05:00
|
|
|
value = VariantSupport.read(src, o, length, (int) type, codepage);
|
2003-08-02 15:02:28 -04:00
|
|
|
}
|
2003-08-23 11:12:22 -04:00
|
|
|
catch (UnsupportedVariantTypeException ex)
|
2003-08-02 15:02:28 -04:00
|
|
|
{
|
2003-08-30 05:13:53 -04:00
|
|
|
VariantSupport.writeUnsupportedTypeMessage(ex);
|
2003-08-23 11:12:22 -04:00
|
|
|
value = ex.getValue();
|
2003-08-02 15:02:28 -04:00
|
|
|
}
|
2002-02-13 23:00:59 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-08-03 16:16:46 -04:00
|
|
|
/**
|
|
|
|
* <p>Creates an empty property. It must be filled using the set method to
|
|
|
|
* be usable.</p>
|
|
|
|
*/
|
|
|
|
protected Property()
|
2003-08-23 11:12:22 -04:00
|
|
|
{ }
|
2003-08-03 16:16:46 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2002-02-13 23:00:59 -05:00
|
|
|
/**
|
2002-07-18 11:51:39 -04:00
|
|
|
* <p>Reads a dictionary.</p>
|
2009-08-18 12:50:24 -04:00
|
|
|
*
|
2005-04-01 11:58:00 -05:00
|
|
|
* @param src The byte array containing the bytes making out the dictionary.
|
|
|
|
* @param offset At this offset within <var>src </var> the dictionary
|
|
|
|
* starts.
|
2002-07-18 11:51:39 -04:00
|
|
|
* @param length The dictionary contains at most this many bytes.
|
2002-12-10 01:15:20 -05:00
|
|
|
* @param codepage The codepage of the string values.
|
2002-07-18 11:51:39 -04:00
|
|
|
* @return The dictonary
|
2005-04-01 11:58:00 -05:00
|
|
|
* @throws UnsupportedEncodingException if the dictionary's codepage is not
|
|
|
|
* (yet) supported.
|
2002-02-13 23:00:59 -05:00
|
|
|
*/
|
2011-10-02 04:58:11 -04:00
|
|
|
protected Map<?, ?> readDictionary(final byte[] src, final long offset,
|
2003-08-02 15:02:28 -04:00
|
|
|
final int length, final int codepage)
|
2005-04-01 11:58:00 -05:00
|
|
|
throws UnsupportedEncodingException
|
2002-07-18 11:51:39 -04:00
|
|
|
{
|
2003-08-02 15:02:28 -04:00
|
|
|
/* Check whether "offset" points into the "src" array". */
|
|
|
|
if (offset < 0 || offset > src.length)
|
|
|
|
throw new HPSFRuntimeException
|
|
|
|
("Illegal offset " + offset + " while HPSF stream contains " +
|
|
|
|
length + " bytes.");
|
2002-12-10 01:15:20 -05:00
|
|
|
int o = (int) offset;
|
2002-05-11 10:47:24 -04:00
|
|
|
|
|
|
|
/*
|
2002-12-10 01:15:20 -05:00
|
|
|
* Read the number of dictionary entries.
|
2002-05-11 10:47:24 -04:00
|
|
|
*/
|
|
|
|
final long nrEntries = LittleEndian.getUInt(src, o);
|
|
|
|
o += LittleEndian.INT_SIZE;
|
|
|
|
|
2011-10-02 04:58:11 -04:00
|
|
|
final Map<Object, Object> m = new LinkedHashMap<Object, Object>(
|
|
|
|
(int) nrEntries, (float) 1.0 );
|
2008-02-08 06:55:43 -05:00
|
|
|
|
|
|
|
try
|
2003-08-02 15:02:28 -04:00
|
|
|
{
|
2008-02-08 06:55:43 -05:00
|
|
|
for (int i = 0; i < nrEntries; i++)
|
2005-04-01 11:58:00 -05:00
|
|
|
{
|
2008-02-08 06:55:43 -05:00
|
|
|
/* The key. */
|
2009-10-08 18:29:41 -04:00
|
|
|
final Long id = Long.valueOf(LittleEndian.getUInt(src, o));
|
2008-02-08 06:55:43 -05:00
|
|
|
o += LittleEndian.INT_SIZE;
|
|
|
|
|
|
|
|
/* The value (a string). The length is the either the
|
|
|
|
* number of (two-byte) characters if the character set is Unicode
|
|
|
|
* or the number of bytes if the character set is not Unicode.
|
|
|
|
* The length includes terminating 0x00 bytes which we have to strip
|
|
|
|
* off to create a Java string. */
|
|
|
|
long sLength = LittleEndian.getUInt(src, o);
|
|
|
|
o += LittleEndian.INT_SIZE;
|
|
|
|
|
|
|
|
/* Read the string. */
|
|
|
|
final StringBuffer b = new StringBuffer();
|
|
|
|
switch (codepage)
|
2005-04-01 11:58:00 -05:00
|
|
|
{
|
2008-02-08 06:55:43 -05:00
|
|
|
case -1:
|
|
|
|
{
|
|
|
|
/* Without a codepage the length is equal to the number of
|
|
|
|
* bytes. */
|
|
|
|
b.append(new String(src, o, (int) sLength));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Constants.CP_UNICODE:
|
|
|
|
{
|
|
|
|
/* The length is the number of characters, i.e. the number
|
|
|
|
* of bytes is twice the number of the characters. */
|
|
|
|
final int nrBytes = (int) (sLength * 2);
|
|
|
|
final byte[] h = new byte[nrBytes];
|
|
|
|
for (int i2 = 0; i2 < nrBytes; i2 += 2)
|
|
|
|
{
|
|
|
|
h[i2] = src[o + i2 + 1];
|
|
|
|
h[i2 + 1] = src[o + i2];
|
|
|
|
}
|
|
|
|
b.append(new String(h, 0, nrBytes,
|
|
|
|
VariantSupport.codepageToEncoding(codepage)));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2005-04-01 11:58:00 -05:00
|
|
|
{
|
2008-02-08 06:55:43 -05:00
|
|
|
/* For encodings other than Unicode the length is the number
|
|
|
|
* of bytes. */
|
|
|
|
b.append(new String(src, o, (int) sLength,
|
|
|
|
VariantSupport.codepageToEncoding(codepage)));
|
|
|
|
break;
|
2005-04-01 11:58:00 -05:00
|
|
|
}
|
|
|
|
}
|
2008-02-08 06:55:43 -05:00
|
|
|
|
|
|
|
/* Strip 0x00 characters from the end of the string: */
|
|
|
|
while (b.length() > 0 && b.charAt(b.length() - 1) == 0x00)
|
|
|
|
b.setLength(b.length() - 1);
|
|
|
|
if (codepage == Constants.CP_UNICODE)
|
2005-04-01 11:58:00 -05:00
|
|
|
{
|
2008-02-08 06:55:43 -05:00
|
|
|
if (sLength % 2 == 1)
|
|
|
|
sLength++;
|
|
|
|
o += (sLength + sLength);
|
2005-04-01 11:58:00 -05:00
|
|
|
}
|
2008-02-08 06:55:43 -05:00
|
|
|
else
|
|
|
|
o += sLength;
|
|
|
|
m.put(id, b.toString());
|
2005-04-01 11:58:00 -05:00
|
|
|
}
|
2008-02-08 06:55:43 -05:00
|
|
|
}
|
|
|
|
catch (RuntimeException ex)
|
|
|
|
{
|
|
|
|
final POILogger l = POILogFactory.getLogger(getClass());
|
|
|
|
l.log(POILogger.WARN,
|
|
|
|
"The property set's dictionary contains bogus data. "
|
|
|
|
+ "All dictionary entries starting with the one with ID "
|
|
|
|
+ id + " will be ignored.", ex);
|
2002-02-13 23:00:59 -05:00
|
|
|
}
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2003-08-02 15:02:28 -04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* <p>Returns the property's size in bytes. This is always a multiple of
|
|
|
|
* 4.</p>
|
|
|
|
*
|
|
|
|
* @return the property's size in bytes
|
2009-08-18 12:50:24 -04:00
|
|
|
*
|
2003-08-30 05:13:53 -04:00
|
|
|
* @exception WritingNotSupportedException if HPSF does not yet support the
|
|
|
|
* property's variant type.
|
2003-08-02 15:02:28 -04:00
|
|
|
*/
|
2003-08-30 05:13:53 -04:00
|
|
|
protected int getSize() throws WritingNotSupportedException
|
2003-08-02 15:02:28 -04:00
|
|
|
{
|
2003-08-30 05:13:53 -04:00
|
|
|
int length = VariantSupport.getVariantLength(type);
|
|
|
|
if (length >= 0)
|
|
|
|
return length; /* Fixed length */
|
|
|
|
if (length == -2)
|
|
|
|
/* Unknown length */
|
|
|
|
throw new WritingNotSupportedException(type, null);
|
|
|
|
|
|
|
|
/* Variable length: */
|
2003-08-23 11:12:22 -04:00
|
|
|
final int PADDING = 4; /* Pad to multiples of 4. */
|
|
|
|
switch ((int) type)
|
|
|
|
{
|
|
|
|
case Variant.VT_LPSTR:
|
|
|
|
{
|
|
|
|
int l = ((String) value).length() + 1;
|
|
|
|
int r = l % PADDING;
|
|
|
|
if (r > 0)
|
|
|
|
l += PADDING - r;
|
|
|
|
length += l;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Variant.VT_EMPTY:
|
|
|
|
break;
|
|
|
|
default:
|
2003-08-30 05:13:53 -04:00
|
|
|
throw new WritingNotSupportedException(type, value);
|
2003-08-23 11:12:22 -04:00
|
|
|
}
|
|
|
|
return length;
|
2003-08-02 15:02:28 -04:00
|
|
|
}
|
|
|
|
|
2003-08-03 16:16:46 -04:00
|
|
|
|
|
|
|
|
2003-08-23 11:12:22 -04:00
|
|
|
/**
|
2008-02-08 06:55:43 -05:00
|
|
|
* <p>Compares two properties.</p> <p>Please beware that a property with
|
|
|
|
* ID == 0 is a special case: It does not have a type, and its value is the
|
|
|
|
* section's dictionary. Another special case are strings: Two properties
|
|
|
|
* may have the different types Variant.VT_LPSTR and Variant.VT_LPWSTR;</p>
|
2009-08-18 12:50:24 -04:00
|
|
|
*
|
2003-08-23 11:12:22 -04:00
|
|
|
* @see Object#equals(java.lang.Object)
|
|
|
|
*/
|
|
|
|
public boolean equals(final Object o)
|
2003-08-03 16:16:46 -04:00
|
|
|
{
|
2009-08-18 12:50:24 -04:00
|
|
|
if (!(o instanceof Property)) {
|
2003-08-30 05:13:53 -04:00
|
|
|
return false;
|
2009-08-18 12:50:24 -04:00
|
|
|
}
|
2003-08-30 05:13:53 -04:00
|
|
|
final Property p = (Property) o;
|
|
|
|
final Object pValue = p.getValue();
|
2003-09-18 14:56:35 -04:00
|
|
|
final long pId = p.getID();
|
2004-08-31 16:45:00 -04:00
|
|
|
if (id != pId || (id != 0 && !typesAreEqual(type, p.getType())))
|
2003-08-30 05:13:53 -04:00
|
|
|
return false;
|
|
|
|
if (value == null && pValue == null)
|
|
|
|
return true;
|
|
|
|
if (value == null || pValue == null)
|
|
|
|
return false;
|
2003-09-18 14:56:35 -04:00
|
|
|
|
2003-08-30 05:13:53 -04:00
|
|
|
/* It's clear now that both values are non-null. */
|
2009-08-18 12:50:24 -04:00
|
|
|
final Class<?> valueClass = value.getClass();
|
|
|
|
final Class<?> pValueClass = pValue.getClass();
|
2003-08-30 05:13:53 -04:00
|
|
|
if (!(valueClass.isAssignableFrom(pValueClass)) &&
|
|
|
|
!(pValueClass.isAssignableFrom(valueClass)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (value instanceof byte[])
|
|
|
|
return Util.equal((byte[]) value, (byte[]) pValue);
|
|
|
|
|
|
|
|
return value.equals(pValue);
|
2003-08-03 16:16:46 -04:00
|
|
|
}
|
|
|
|
|
2003-08-23 11:12:22 -04:00
|
|
|
|
|
|
|
|
2004-08-31 16:45:00 -04:00
|
|
|
private boolean typesAreEqual(final long t1, final long t2)
|
|
|
|
{
|
|
|
|
if (t1 == t2 ||
|
|
|
|
(t1 == Variant.VT_LPSTR && t2 == Variant.VT_LPWSTR) ||
|
2009-08-18 12:50:24 -04:00
|
|
|
(t2 == Variant.VT_LPSTR && t1 == Variant.VT_LPWSTR)) {
|
2004-08-31 16:45:00 -04:00
|
|
|
return true;
|
2009-08-18 12:50:24 -04:00
|
|
|
}
|
|
|
|
return false;
|
2004-08-31 16:45:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-08-23 11:12:22 -04:00
|
|
|
/**
|
2003-08-30 05:13:53 -04:00
|
|
|
* @see Object#hashCode()
|
2003-08-23 11:12:22 -04:00
|
|
|
*/
|
2003-08-30 05:13:53 -04:00
|
|
|
public int hashCode()
|
|
|
|
{
|
|
|
|
long hashCode = 0;
|
|
|
|
hashCode += id;
|
|
|
|
hashCode += type;
|
|
|
|
if (value != null)
|
|
|
|
hashCode += value.hashCode();
|
|
|
|
final int returnHashCode = (int) (hashCode & 0x0ffffffffL );
|
|
|
|
return returnHashCode;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-08-23 11:12:22 -04:00
|
|
|
|
2003-08-30 05:13:53 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @see Object#toString()
|
|
|
|
*/
|
|
|
|
public String toString()
|
2003-08-23 11:12:22 -04:00
|
|
|
{
|
2003-08-30 05:13:53 -04:00
|
|
|
final StringBuffer b = new StringBuffer();
|
|
|
|
b.append(getClass().getName());
|
|
|
|
b.append('[');
|
|
|
|
b.append("id: ");
|
|
|
|
b.append(getID());
|
|
|
|
b.append(", type: ");
|
|
|
|
b.append(getType());
|
2003-12-02 12:46:01 -05:00
|
|
|
final Object value = getValue();
|
2003-08-30 05:13:53 -04:00
|
|
|
b.append(", value: ");
|
2003-12-02 12:46:01 -05:00
|
|
|
b.append(value.toString());
|
|
|
|
if (value instanceof String)
|
|
|
|
{
|
|
|
|
final String s = (String) value;
|
|
|
|
final int l = s.length();
|
|
|
|
final byte[] bytes = new byte[l * 2];
|
|
|
|
for (int i = 0; i < l; i++)
|
|
|
|
{
|
|
|
|
final char c = s.charAt(i);
|
|
|
|
final byte high = (byte) ((c & 0x00ff00) >> 8);
|
|
|
|
final byte low = (byte) ((c & 0x0000ff) >> 0);
|
|
|
|
bytes[i * 2] = high;
|
|
|
|
bytes[i * 2 + 1] = low;
|
|
|
|
}
|
|
|
|
final String hex = HexDump.dump(bytes, 0L, 0);
|
|
|
|
b.append(" [");
|
|
|
|
b.append(hex);
|
|
|
|
b.append("]");
|
|
|
|
}
|
2003-08-30 05:13:53 -04:00
|
|
|
b.append(']');
|
|
|
|
return b.toString();
|
2003-08-23 11:12:22 -04:00
|
|
|
}
|
|
|
|
|
2002-02-13 23:00:59 -05:00
|
|
|
}
|