001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hpsf;
019:
020: import org.apache.poi.util.HexDump;
021:
022: /**
023: * <p>Represents a class ID (16 bytes). Unlike other little-endian
024: * type the {@link ClassID} is not just 16 bytes stored in the wrong
025: * order. Instead, it is a double word (4 bytes) followed by two
026: * words (2 bytes each) followed by 8 bytes.</p>
027: *
028: * @author Rainer Klute <a
029: * href="mailto:klute@rainer-klute.de"><klute@rainer-klute.de></a>
030: * @version $Id: ClassID.java 489730 2006-12-22 19:18:16Z bayard $
031: * @since 2002-02-09
032: */
033: public class ClassID {
034:
035: /**
036: * <p>The bytes making out the class ID in correct order,
037: * i.e. big-endian.</p>
038: */
039: protected byte[] bytes;
040:
041: /**
042: * <p>Creates a {@link ClassID} and reads its value from a byte
043: * array.</p>
044: *
045: * @param src The byte array to read from.
046: * @param offset The offset of the first byte to read.
047: */
048: public ClassID(final byte[] src, final int offset) {
049: read(src, offset);
050: }
051:
052: /**
053: * <p>Creates a {@link ClassID} and initializes its value with
054: * 0x00 bytes.</p>
055: */
056: public ClassID() {
057: bytes = new byte[LENGTH];
058: for (int i = 0; i < LENGTH; i++)
059: bytes[i] = 0x00;
060: }
061:
062: /** <p>The number of bytes occupied by this object in the byte
063: * stream.</p> */
064: public static final int LENGTH = 16;
065:
066: /**
067: * @return The number of bytes occupied by this object in the byte
068: * stream.
069: */
070: public int length() {
071: return LENGTH;
072: }
073:
074: /**
075: * <p>Gets the bytes making out the class ID. They are returned in
076: * correct order, i.e. big-endian.</p>
077: *
078: * @return the bytes making out the class ID.
079: */
080: public byte[] getBytes() {
081: return bytes;
082: }
083:
084: /**
085: * <p>Sets the bytes making out the class ID.</p>
086: *
087: * @param bytes The bytes making out the class ID in big-endian format. They
088: * are copied without their order being changed.
089: */
090: public void setBytes(final byte[] bytes) {
091: for (int i = 0; i < this .bytes.length; i++)
092: this .bytes[i] = bytes[i];
093: }
094:
095: /**
096: * <p>Reads the class ID's value from a byte array by turning
097: * little-endian into big-endian.</p>
098: *
099: * @param src The byte array to read from
100: *
101: * @param offset The offset within the <var>src</var> byte array
102: *
103: * @return A byte array containing the class ID.
104: */
105: public byte[] read(final byte[] src, final int offset) {
106: bytes = new byte[16];
107:
108: /* Read double word. */
109: bytes[0] = src[3 + offset];
110: bytes[1] = src[2 + offset];
111: bytes[2] = src[1 + offset];
112: bytes[3] = src[0 + offset];
113:
114: /* Read first word. */
115: bytes[4] = src[5 + offset];
116: bytes[5] = src[4 + offset];
117:
118: /* Read second word. */
119: bytes[6] = src[7 + offset];
120: bytes[7] = src[6 + offset];
121:
122: /* Read 8 bytes. */
123: for (int i = 8; i < 16; i++)
124: bytes[i] = src[i + offset];
125:
126: return bytes;
127: }
128:
129: /**
130: * <p>Writes the class ID to a byte array in the
131: * little-endian format.</p>
132: *
133: * @param dst The byte array to write to.
134: *
135: * @param offset The offset within the <var>dst</var> byte array.
136: *
137: * @exception ArrayStoreException if there is not enough room for the class
138: * ID 16 bytes in the byte array after the <var>offset</var> position.
139: */
140: public void write(final byte[] dst, final int offset)
141: throws ArrayStoreException {
142: /* Check array size: */
143: if (dst.length < 16)
144: throw new ArrayStoreException(
145: "Destination byte[] must have room for at least 16 bytes, "
146: + "but has a length of only " + dst.length
147: + ".");
148: /* Write double word. */
149: dst[0 + offset] = bytes[3];
150: dst[1 + offset] = bytes[2];
151: dst[2 + offset] = bytes[1];
152: dst[3 + offset] = bytes[0];
153:
154: /* Write first word. */
155: dst[4 + offset] = bytes[5];
156: dst[5 + offset] = bytes[4];
157:
158: /* Write second word. */
159: dst[6 + offset] = bytes[7];
160: dst[7 + offset] = bytes[6];
161:
162: /* Write 8 bytes. */
163: for (int i = 8; i < 16; i++)
164: dst[i + offset] = bytes[i];
165: }
166:
167: /**
168: * <p>Checks whether this <code>ClassID</code> is equal to another
169: * object.</p>
170: *
171: * @param o the object to compare this <code>PropertySet</code> with
172: * @return <code>true</code> if the objects are equal, else
173: * <code>false</code>.</p>
174: */
175: public boolean equals(final Object o) {
176: if (o == null || !(o instanceof ClassID))
177: return false;
178: final ClassID cid = (ClassID) o;
179: if (bytes.length != cid.bytes.length)
180: return false;
181: for (int i = 0; i < bytes.length; i++)
182: if (bytes[i] != cid.bytes[i])
183: return false;
184: return true;
185: }
186:
187: /**
188: * @see Object#hashCode()
189: */
190: public int hashCode() {
191: return new String(bytes).hashCode();
192: }
193:
194: /**
195: * <p>Returns a human-readable representation of the Class ID in standard
196: * format <code>"{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"</code>.</p>
197: *
198: * @return String representation of the Class ID represented by this object.
199: */
200: public String toString() {
201: StringBuffer sbClassId = new StringBuffer(38);
202: sbClassId.append('{');
203: for (int i = 0; i < 16; i++) {
204: sbClassId.append(HexDump.toHex(bytes[i]));
205: if (i == 3 || i == 5 || i == 7 || i == 9)
206: sbClassId.append('-');
207: }
208: sbClassId.append('}');
209: return sbClassId.toString();
210: }
211:
212: }
|