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: import java.util.Vector;
034:
035: /**
036: * This class is defined by the JSR-82 specification
037: * <em>Java™ APIs for Bluetooth™ Wireless Technology,
038: * Version 1.1.</em>
039: */
040: // JAVADOC COMMENT ELIDED
041: public class DataElement {
042:
043: // JAVADOC COMMENT ELIDED
044: public static final int NULL = 0x0000;
045:
046: // JAVADOC COMMENT ELIDED
047: public static final int U_INT_1 = 0x0008;
048:
049: // JAVADOC COMMENT ELIDED
050: public static final int U_INT_2 = 0x0009;
051:
052: // JAVADOC COMMENT ELIDED
053: public static final int U_INT_4 = 0x000A;
054:
055: // JAVADOC COMMENT ELIDED
056: public static final int U_INT_8 = 0x000B;
057:
058: // JAVADOC COMMENT ELIDED
059: public static final int U_INT_16 = 0x000C;
060:
061: // JAVADOC COMMENT ELIDED
062: public static final int INT_1 = 0x0010;
063:
064: // JAVADOC COMMENT ELIDED
065: public static final int INT_2 = 0x0011;
066:
067: // JAVADOC COMMENT ELIDED
068: public static final int INT_4 = 0x0012;
069:
070: // JAVADOC COMMENT ELIDED
071: public static final int INT_8 = 0x0013;
072:
073: // JAVADOC COMMENT ELIDED
074: public static final int INT_16 = 0x0014;
075:
076: // JAVADOC COMMENT ELIDED
077: public static final int URL = 0x0040;
078:
079: // JAVADOC COMMENT ELIDED
080: public static final int UUID = 0x0018;
081:
082: // JAVADOC COMMENT ELIDED
083: public static final int BOOL = 0x0028;
084:
085: // JAVADOC COMMENT ELIDED
086: public static final int STRING = 0x0020;
087:
088: // JAVADOC COMMENT ELIDED
089: public static final int DATSEQ = 0x0030;
090:
091: // JAVADOC COMMENT ELIDED
092: public static final int DATALT = 0x0038;
093:
094: /** Keeps the specified or derived type of the element. */
095: private int valueType;
096:
097: /** Keeps the boolean value for the type BOOL. */
098: private boolean booleanValue;
099:
100: /** Keeps the long value for the types *INT*. */
101: private long longValue;
102:
103: /**
104: * Keeps the misc type value for the rest of types.
105: *
106: * This field also keeps the value for the type DATALT and DATSEQ.
107: * In this case it's a Vector. The access to the Vector elements
108: * is synchronized in cldc (according the source code). But,
109: * this is not documented, so we make a synchronize access
110: * to this field to fit any cldc implementation.
111: */
112: private Object miscValue;
113:
114: // JAVADOC COMMENT ELIDED
115: public DataElement(int valueType) {
116: switch (valueType) {
117: case NULL: /* miscValue = null in this case. */
118: break;
119: case DATALT: /* falls through */
120: case DATSEQ:
121: this .miscValue = new Vector();
122: break;
123: default:
124: throw new IllegalArgumentException(
125: "Invalid valueType for this constructor: "
126: + valueType);
127: }
128: this .valueType = valueType;
129: }
130:
131: // JAVADOC COMMENT ELIDED
132: public DataElement(boolean bool) {
133: valueType = BOOL;
134: booleanValue = bool;
135: }
136:
137: // JAVADOC COMMENT ELIDED
138: public DataElement(int valueType, long value) {
139: long min = 0;
140: long max = 0;
141:
142: switch (valueType) {
143: case U_INT_1:
144: max = 0xffL;
145: break;
146: case U_INT_2:
147: max = 0xffffL;
148: break;
149: case U_INT_4:
150: max = 0xffffffffL;
151: break;
152: case INT_1:
153: min = Byte.MIN_VALUE;
154: max = Byte.MAX_VALUE;
155: break;
156: case INT_2:
157: min = -0x8000L;
158: max = 0x7fffL;
159: break;
160: case INT_4:
161: min = Integer.MIN_VALUE;
162: max = Integer.MAX_VALUE;
163: break;
164: case INT_8:
165: min = Long.MIN_VALUE;
166: max = Long.MAX_VALUE;
167: break;
168: default:
169: throw new IllegalArgumentException(
170: "Invalid 'valueType' for this constructor: "
171: + valueType);
172: }
173:
174: // check if value in the valid rangle for this type
175: if (value < min || value > max) {
176: throw new IllegalArgumentException(
177: "Invalid 'value' for specified type: " + value);
178: }
179: this .valueType = valueType;
180: this .longValue = value;
181: }
182:
183: // JAVADOC COMMENT ELIDED
184: public DataElement(int valueType, Object value) {
185: boolean isCorrectValue = true;
186:
187: switch (valueType) {
188: case URL: /* falls through */
189: case STRING:
190: isCorrectValue = value instanceof String;
191: break;
192: case UUID:
193: isCorrectValue = value instanceof UUID;
194: break;
195: case INT_16: /* falls through */
196: case U_INT_16:
197: isCorrectValue = value instanceof byte[]
198: && ((byte[]) value).length == 16;
199: break;
200: case U_INT_8:
201: isCorrectValue = value instanceof byte[]
202: && ((byte[]) value).length == 8;
203: break;
204: default:
205: throw new IllegalArgumentException(
206: "Invalid 'valueType' for this constructor: "
207: + valueType);
208: }
209:
210: // check if value in the valid rangle for this type
211: if (!isCorrectValue) {
212: throw new IllegalArgumentException(
213: "Invalid 'value' for specified type: " + value);
214: }
215: this .valueType = valueType;
216: this .miscValue = value;
217: }
218:
219: // JAVADOC COMMENT ELIDED
220: public synchronized void addElement(DataElement elem) {
221:
222: /*
223: * We can't optimize this by invoking the
224: * this.insertElementAt(elem, getSize()), because
225: * the ClassCastException may be thrown from getSize()
226: * which gives us improper stack trace.
227: */
228: if (valueType != DATSEQ && valueType != DATALT) {
229: throw new ClassCastException(
230: "Invalid element type for this method: "
231: + valueType);
232: }
233:
234: if (elem == null) {
235: throw new NullPointerException("Specified element is null");
236: }
237: ((Vector) miscValue).addElement(elem);
238: }
239:
240: // JAVADOC COMMENT ELIDED
241: public synchronized void insertElementAt(DataElement elem, int index) {
242: if (valueType != DATSEQ && valueType != DATALT) {
243: throw new ClassCastException(
244: "Invalid element type for this method: "
245: + valueType);
246: }
247:
248: if (elem == null) {
249: throw new NullPointerException("Specified element is null");
250: }
251:
252: /*
253: * We can't use the Vector.insertElementAt check for out of
254: * bounds, because Vector throws ArrayIndexOutOfBoundsException
255: * in this case.
256: */
257: if (index < 0 || index > ((Vector) miscValue).size()) {
258: throw new IndexOutOfBoundsException(
259: "Specified index is out of range");
260: }
261: ((Vector) miscValue).insertElementAt(elem, index);
262: }
263:
264: // JAVADOC COMMENT ELIDED
265: public synchronized int getSize() {
266: if (valueType != DATSEQ && valueType != DATALT) {
267: throw new ClassCastException(
268: "Invalid element type for this method: "
269: + valueType);
270: }
271: return ((Vector) miscValue).size();
272: }
273:
274: // JAVADOC COMMENT ELIDED
275: public boolean removeElement(DataElement elem) {
276: if (valueType != DATSEQ && valueType != DATALT) {
277: throw new ClassCastException(
278: "Invalid element type for this method: "
279: + valueType);
280: }
281:
282: if (elem == null) {
283: throw new NullPointerException("Specified element is null");
284: }
285:
286: /*
287: * The Bluetooth spec says the two DataElement equals if their
288: * references are equal. According to cldc1.1 ref impl sources,
289: * the Vector uses 'equals' call, and the Object.equls uses
290: * a references compare, so we may not care about doing this here.
291: */
292: return ((Vector) miscValue).removeElement(elem);
293: }
294:
295: // JAVADOC COMMENT ELIDED
296: public int getDataType() {
297: return valueType;
298: }
299:
300: // JAVADOC COMMENT ELIDED
301: public long getLong() {
302: switch (valueType) {
303: case U_INT_1: /* falls through */
304: case U_INT_2: /* falls through */
305: case U_INT_4: /* falls through */
306: case INT_1: /* falls through */
307: case INT_2: /* falls through */
308: case INT_4: /* falls through */
309: case INT_8:
310: break;
311: default:
312: throw new ClassCastException(
313: "Invalid element type for this method: "
314: + valueType);
315: }
316: return longValue;
317: }
318:
319: // JAVADOC COMMENT ELIDED
320: public boolean getBoolean() {
321: if (valueType != BOOL) {
322: throw new ClassCastException(
323: "Invalid element type for this method: "
324: + valueType);
325: }
326: return booleanValue;
327: }
328:
329: // JAVADOC COMMENT ELIDED
330: public synchronized Object getValue() {
331: Object retValue = miscValue;
332:
333: /*
334: * According to cldc & bluetooth specifications, the String and UUID
335: * are immutable, so we may not return a clone object to safe
336: * the stored one.
337: *
338: * The Vector.elements() returns an Enumeration, which does not allow
339: * to break the Vector either.
340: *
341: * The array may be modified by reference, so we have to return
342: * a clone.
343: */
344: switch (valueType) {
345: case URL: /* falls through */
346: case STRING: /* falls through */
347: case UUID:
348: break;
349: case DATALT: /* falls through */
350: case DATSEQ:
351: retValue = ((Vector) miscValue).elements();
352: break;
353: case U_INT_8: /* falls through */
354: case U_INT_16: /* falls through */
355: case INT_16:
356: int length = ((byte[]) miscValue).length;
357: retValue = new byte[length];
358: System.arraycopy(miscValue, 0, retValue, 0, length);
359: break;
360: default:
361: throw new ClassCastException(
362: "Invalid element type for this method: "
363: + valueType);
364: }
365: return retValue;
366: }
367: } // end of class 'DataElement' definition
|