001: /*
002: *
003: *
004: * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights
005: * Reserved. Use is subject to license terms.
006: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License version
010: * 2 only, as published by the Free Software Foundation.
011: *
012: * This program is distributed in the hope that it will be useful, but
013: * WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * General Public License version 2 for more details (a copy is
016: * included at /legal/license.txt).
017: *
018: * You should have received a copy of the GNU General Public License
019: * version 2 along with this work; if not, write to the Free Software
020: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
021: * 02110-1301 USA
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
024: * Clara, CA 95054 or visit www.sun.com if you need additional
025: * information or have any questions.
026: */
027:
028: /*
029: * (c) Copyright 2001, 2002 Motorola, Inc. ALL RIGHTS RESERVED.
030: */
031: package javax.bluetooth;
032:
033: /**
034: * This class is defined by the JSR-82 specification
035: * <em>Java™ APIs for Bluetooth™ Wireless Technology,
036: * Version 1.1.</em>
037: */
038: // JAVADOC COMMENT ELIDED
039: public class UUID {
040:
041: // JAVADOC COMMENT ELIDED
042: private long highBits;
043:
044: // JAVADOC COMMENT ELIDED
045: private long lowBits;
046:
047: // JAVADOC COMMENT ELIDED
048: private static final long BASE_UUID_HIGHT = 0x1000L;
049:
050: // JAVADOC COMMENT ELIDED
051: private static final long BASE_UUID_LOW = 0x800000805F9B34FBL;
052:
053: // JAVADOC COMMENT ELIDED
054: private static final char[] digits = { '0', '1', '2', '3', '4',
055: '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
056:
057: // JAVADOC COMMENT ELIDED
058: public UUID(long uuidValue) {
059:
060: // check the specified value is out of range
061: if (uuidValue < 0 || uuidValue > 0xffffffffL) {
062: throw new IllegalArgumentException(
063: "The 'uuidValue' is out of [0, 2^32 - 1] range: "
064: + uuidValue);
065: }
066:
067: /*
068: * Create a UUID from 16/32 bits value.
069: *
070: * 128_bit_value = 16_bit_value * 2^96 + Bluetooth_Base_UUID
071: * 128_bit_value = 32_bit_value * 2^96 + Bluetooth_Base_UUID
072: *
073: * No need to check the "overflow/negative", because
074: * uuidValue is 32 bits & BASE_UUID_HIGHT is 16 bits.
075: */
076: highBits = (uuidValue << 32) | BASE_UUID_HIGHT;
077: lowBits = BASE_UUID_LOW;
078: }
079:
080: // JAVADOC COMMENT ELIDED
081: public UUID(String uuidValue, boolean shortUUID) {
082: if (uuidValue == null) {
083: throw new NullPointerException(
084: "Specified 'uuidValue' is null");
085: }
086:
087: /*
088: * The zero length is double checked by the parsing operation,
089: * but the NumberFormatException is thrown in that case -
090: * we need IllegalArgumentException according to spec.
091: */
092: if (uuidValue.length() == 0
093: || (shortUUID && uuidValue.length() > 8)
094: || uuidValue.length() > 32) {
095: throw new IllegalArgumentException(
096: "Invalid length of specified 'uuidValue': "
097: + uuidValue.length());
098: }
099:
100: // check if sign character presents
101: if (uuidValue.indexOf('-') != -1) {
102: throw new NumberFormatException(
103: "The '-' character is not allowed: " + uuidValue);
104: }
105:
106: /*
107: * 16-bit or 32-bit UUID case.
108: */
109: if (shortUUID) {
110:
111: // this checks the format and may throw a NumberFormatException
112: long val = Long.parseLong(uuidValue, 16);
113:
114: /*
115: * create a UUID from 16/32 bits value.
116: *
117: * No need to check the "overflow/negative", because
118: * lVal is 32 bits & BASE_UUID_HIGHT is 16 bits.
119: */
120: highBits = (val << 32) | BASE_UUID_HIGHT;
121: lowBits = BASE_UUID_LOW;
122: return;
123: }
124:
125: /*
126: * 128-bit UUID case.
127: */
128: highBits = 0x0L;
129:
130: // simple case (optimization)
131: if (uuidValue.length() < 16) {
132: lowBits = Long.parseLong(uuidValue, 16);
133: return;
134: }
135:
136: /*
137: * We have to do a 32 bits parsing, because the
138: * Long.parseLong("ffff ffff ffff ffff") does not
139: * parse such an unsigned number.
140: */
141: int l = uuidValue.length();
142: lowBits = Long.parseLong(uuidValue.substring(l - 8), 16);
143: lowBits |= (Long.parseLong(uuidValue.substring(l - 16, l - 8),
144: 16) << 32);
145:
146: if (l == 16) {
147: return;
148: }
149:
150: if (l <= 24) {
151: highBits = Long.parseLong(uuidValue.substring(0, l - 16),
152: 16);
153: } else {
154: highBits = Long.parseLong(uuidValue.substring(l - 24,
155: l - 16), 16);
156: highBits |= (Long.parseLong(uuidValue.substring(0, l - 24),
157: 16) << 32);
158: }
159: }
160:
161: // JAVADOC COMMENT ELIDED
162: public String toString() {
163:
164: /*
165: * This implementation is taken from cldc1.1 Integer#toUnsignedString
166: * one. The implementation which uses Integer#toHexString() is
167: * 2-3 times slower, so such a code duplication is required here.
168: */
169: int[] ints = new int[] { (int) (lowBits & 0xffffffffL),
170: (int) (lowBits >>> 32 & 0xffffffffL),
171: (int) (highBits & 0xffffffffL),
172: (int) (highBits >>> 32 & 0xffffffffL) };
173: int charPos = 32;
174: char[] buf = new char[charPos];
175: int shift = 4;
176: int mask = 0xf;
177: int needZerosIndex = -1;
178:
179: /*
180: * check with part of value requires the zero characters.
181: *
182: * I.e. the original algorithm gives as an 1 character
183: * for the value '1', but we may want 00000001.
184: */
185: for (int i = 3; i >= 0; i--) {
186: if (ints[i] != 0) {
187: needZerosIndex = i - 1;
188: break;
189: }
190: }
191:
192: /*
193: * Process parts of UUID from low parts to high ones.
194: */
195: for (int i = 0; i < ints.length; i++) {
196:
197: /*
198: * The 16 bits are zero & no need to fill with 0,
199: * and it's not a UUID with value '0' (i != 0).
200: */
201: if (ints[i] == 0 && needZerosIndex < i && i != 0) {
202: continue;
203: }
204:
205: if (needZerosIndex >= i) {
206:
207: // fill all 8 characters (even if allof them are '0')
208: for (int j = 0; j < 8; j++) {
209: buf[--charPos] = digits[ints[i] & mask];
210: ints[i] >>>= shift;
211: }
212: } else {
213:
214: // fill until the highest valuable character
215: do {
216: buf[--charPos] = digits[ints[i] & mask];
217: ints[i] >>>= shift;
218: } while (ints[i] != 0);
219: }
220: }
221: return new String(buf, charPos, (32 - charPos));
222: }
223:
224: // JAVADOC COMMENT ELIDED
225: public boolean equals(Object value) {
226: return value instanceof UUID
227: && lowBits == ((UUID) value).lowBits
228: && highBits == ((UUID) value).highBits;
229: }
230:
231: // JAVADOC COMMENT ELIDED
232: public int hashCode() {
233: return (int) (highBits ^ highBits >> 32 ^ lowBits ^ lowBits >> 32);
234: }
235: } // end of class 'UUID' definition
|