001: /*
002: * Copyright (c) 2004-2005, Hewlett-Packard Company and Massachusetts
003: * Institute of Technology. All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are
007: * met:
008: *
009: * - Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * - Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in the
014: * documentation and/or other materials provided with the distribution.
015: *
016: * - Neither the name of the Hewlett-Packard Company nor the name of the
017: * Massachusetts Institute of Technology nor the names of their
018: * contributors may be used to endorse or promote products derived from
019: * this software without specific prior written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
022: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
023: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
024: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
025: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
026: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
027: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
028: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
029: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
030: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
031: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
032: * DAMAGE.
033: */
034: package org.dspace.app.didl;
035:
036: import java.io.Serializable;
037:
038: /**
039: * This class implements UUID version 4. The values for the various fields are
040: * crypto random values set by the factory class UUIDFactory
041: *
042: * Development of this code was part of the aDORe repository project by the
043: * Research Library of the Los Alamos National Laboratory.
044: *
045: * This code is based on the implementation of UUID version 4 (the one that
046: * uses random/pseudo-random numbers by Ashraf Amrou of the Old Dominion University
047: * (Aug 14, 2003)
048: **/
049: public final class UUID implements Serializable {
050: private long hi;
051: private long lo;
052:
053: /**
054: * Construct a Version 4 UUID object from another UUID object
055: *
056: * @param uuid
057: * the UUID to use as a base for the new UUID
058: **/
059: public UUID(UUID uuid) {
060: this .hi = uuid.hi;
061: this .lo = uuid.lo;
062: }
063:
064: /**
065: * Construct a Version 4 UUID object form the two given long values.
066: * These values are (pseudo)random numbers (best if crypto quality)
067: *
068: * @param _hi
069: * first long value
070: *
071: * @param _lo
072: * second long value
073: *
074: **/
075: public UUID(long _hi, long _lo) {
076: this .hi = _hi;
077: this .lo = _lo;
078: // IETF variant (10)b
079: lo &= 0x3FFFFFFFFFFFFFFFL;
080: lo |= 0x8000000000000000L;
081: // set multicast bit (so that it there is no chance it will clash
082: // with other UUIDs generated based on real IEEE 802 addresses)
083: lo |= 0x0000800000000000L;
084: // version 4 (100)b: the one based on random/pseudo-random numbers
085: hi &= 0xFFFFFFFFFFFF0FFFL;
086: hi |= 0x0000000000004000L;
087: }
088:
089: /**
090: * Compare UUID objects
091: *
092: * @param obj
093: * the object to compare this UUID against
094: *
095: * @return true or false
096: **/
097: public boolean equals(Object obj) {
098: if (this == obj) // comparing to myself
099: return true;
100: if (obj instanceof UUID)
101: return equals((UUID) obj);
102: return false;
103: }
104:
105: /**
106: * Compare UUIDs
107: *
108: * @param uuid
109: * the UUID to compare this UUID against
110: *
111: * @return true or false
112: **/
113: public boolean equals(UUID uuid) {
114: return (hi == uuid.hi && lo == uuid.lo);
115: }
116:
117: /**
118: * Generate a hash for the UUID
119: *
120: * @return hash code for the UUID
121: *
122: **/
123: public int hashCode() {
124: return new Long(hi ^ lo).hashCode();
125: }
126:
127: /**
128: * Obtain a string representation of the UUID object
129: *
130: * @return the string representation of this UUID
131: *
132: **/
133: public String toString() {
134: return (/**"urn:uuid:" + **/
135: hexDigits(hi >> 32, 4) // time_low: 4 hexOctet (8 hex digits)
136: + "-" + hexDigits(hi >> 16, 2) // time_mid: 2 hexOctet (4 hex digits)
137: + "-" + hexDigits(hi, 2) // time_high_and_version: 2 hexOctet (4 hex digits)
138: + "-" + hexDigits(lo >> 48, 2) // clock_seq_and_reserved: 1 hexOctet (2 hex digits) & clock_seq_low: 1 hexOctet (2 hex digits)
139: + "-" + hexDigits(lo, 6)); // node: 6 hexOctet (12 hex digits)
140: }
141:
142: /**
143: * Obtain the Hex value of a given number of least significant octets
144: * from a long value as a String
145: *
146: * @param lVal
147: * the long value to retrieve octets from
148: *
149: * @param nHexOctets
150: * number of hex octets to return
151: *
152: * @return hex value of least significant octets as a string
153: *
154: **/
155: private static String hexDigits(long lVal, int nHexOctets) {
156: long tmp = 1L << (nHexOctets * 2 * 4); // e.g., if nHexOctets is 2, tmp = (1 0000 0000 0000 0000)b & tmp - 1 = (1111 1111 1111 1111)b
157: long result = lVal & (tmp - 1); // get ride of the uneeded most significant bits
158: result = tmp | result; // make sure the digit at position (nDigits + 1) equals 1 (to preserve leading zeroes)
159: return Long.toHexString(result).substring(1); // getride ot the digit at position nDigits + 1
160: }
161: }
|