javax.bluetooth.DataElement Maven / Gradle / Ivy
/**
* BlueCove - Java library for Bluetooth
* Copyright (C) 2004 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Java docs licensed under the Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
* (c) Copyright 2001, 2002 Motorola, Inc. ALL RIGHTS RESERVED.
*
*
* @version $Id: DataElement.java 933 2007-08-20 14:09:54Z skarzhevskyy $
*/
package javax.bluetooth;
import java.util.Enumeration;
import java.util.Vector;
import com.intel.bluetooth.Utils;
/**
* The DataElement
class defines the various data
* types that a Bluetooth service attribute value may have.
*
* The following table describes the data types and valid
* values that a DataElement
object can store.
*
*
* Data Type Valid Values
* NULL
represents a
* null
value
* U_INT_1
* long
value range [0, 255]
* U_INT_2
long
* value range [0, 216-1]
* U_INT_4
* long
value range [0, 232-1]
* U_INT_8
* byte[]
value range [0, 264-1]
* U_INT_16
* byte[]
value range [0, 2128-1]
* INT_1
long
* value range [-128, 127]
* INT_2
long
* value range [-215, 215-1]
* INT_4
long
* value range [-231, 231-1]
* INT_8
long
* value range [-263, 263-1]
* INT_16
byte[]
* value range [-2127, 2127-1]
* URL
* java.lang.String
* UUID
* javax.bluetooth.UUID
* BOOL
boolean
* STRING
* java.lang.String
* DATSEQ
* java.util.Enumeration
* DATALT
* java.util.Enumeration
*
*
* @version 1.0 February 11, 2002
*
*/
public class DataElement {
/*
* The following section defines public, static and instance
* member variables used in the implementation of the methods.
*/
/**
* Defines data of type NULL.
*
* The value for data type DataElement.NULL
is
* implicit, i.e., there is no representation of it.
* Accordingly there is no method to retrieve
* it, and attempts to retrieve the value will throw an exception.
*
* The value of NULL
is 0x00 (0).
*
*/
public static final int NULL = 0x0000;
/**
* Defines an unsigned integer of size one byte.
*
* The value of the constant U_INT_1
* is 0x08 (8).
*/
public static final int U_INT_1 = 0x0008;
/**
* Defines an unsigned integer of size two bytes.
*
* The value of the constant U_INT_2
is 0x09 (9).
*/
public static final int U_INT_2 = 0x0009;
/**
* Defines an unsigned integer of size four bytes.
*
* The value of the constant U_INT_4
is 0x0A (10).
*/
public static final int U_INT_4 = 0x000A;
/**
* Defines an unsigned integer of size eight bytes.
*
* The value of the constant U_INT_8
is 0x0B (11).
*/
public static final int U_INT_8 = 0x000B;
/**
* Defines an unsigned integer of size sixteen bytes.
*
* The value of the constant U_INT_16
is 0x0C (12).
*/
public static final int U_INT_16 = 0x000C;
/**
* Defines a signed integer of size one byte.
*
* The value of the constant INT_1
is 0x10 (16).
*/
public static final int INT_1 = 0x0010;
/**
* Defines a signed integer of size two bytes.
*
* The value of the constant INT_2
is 0x11 (17).
*/
public static final int INT_2 = 0x0011;
/**
* Defines a signed integer of size four bytes.
*
* The value of the constant INT_4
is 0x12 (18).
*/
public static final int INT_4 = 0x0012;
/**
* Defines a signed integer of size eight bytes.
*
* The value of the constant INT_8
is 0x13 (19).
*/
public static final int INT_8 = 0x0013;
/**
* Defines a signed integer of size sixteen bytes.
*
* The value of the constant INT_16
is 0x14 (20).
*/
public static final int INT_16 = 0x0014;
/**
* Defines data of type URL.
*
* The value of the constant URL
is 0x40 (64).
*/
public static final int URL = 0x0040;
/**
* Defines data of type UUID.
*
* The value of the constant UUID
is 0x18 (24).
*/
public static final int UUID = 0x0018;
/**
* Defines data of type BOOL.
*
* The value of the constant BOOL
is 0x28 (40).
*/
public static final int BOOL = 0x0028;
/**
* Defines data of type STRING.
*
* The value of the constant STRING
is 0x20 (32).
*/
public static final int STRING = 0x0020;
/**
* Defines data of type DATSEQ. The service attribute value whose
* data has this type must consider all the elements of the list,
* i.e. the value is the whole set and not a subset. The elements
* of the set can be of any type defined in this class, including
* DATSEQ.
*
* The value of the constant DATSEQ
is 0x30 (48).
*/
public static final int DATSEQ = 0x0030;
/**
* Defines data of type DATALT. The service attribute value whose
* data has this type must consider only one of the elements of the
* set, i.e., the value is the not the whole set but only one
* element of the set. The user is free to choose any one element.
* The elements of the set can be of any type defined in this class,
* including DATALT.
*
* The value of the constant DATALT
is 0x38 (56).
*/
public static final int DATALT = 0x0038;
private Object value;
private int valueType;
/**
* Creates a DataElement
of type NULL
,
* DATALT
, or DATSEQ
.
*
* @see #NULL
* @see #DATALT
* @see #DATSEQ
*
* @param valueType the type of DataElement to create:
* NULL
, DATALT
, or DATSEQ
*
* @exception IllegalArgumentException if valueType
* is not NULL
, DATALT
, or
* DATSEQ
*/
public DataElement(int valueType) {
switch (valueType) {
case NULL:
value = null;
break;
case DATALT:
case DATSEQ:
value = new Vector();
break;
default:
throw new IllegalArgumentException();
}
this.valueType = valueType;
}
/**
* Creates a DataElement
whose data type is
* BOOL
and whose value is equal to bool
*
* @see #BOOL
*
* @param bool the value of the DataElement
of type
* BOOL.
*/
public DataElement(boolean bool) {
value = bool?Boolean.TRUE:Boolean.FALSE;
valueType = BOOL;
}
/**
* Creates a DataElement
that encapsulates an integer
* value of size U_INT_1
, U_INT_2
,
* U_INT_4
, INT_1
, INT_2
,
* INT_4
, and INT_8
.
* The legal values for the valueType
and the corresponding
* attribute values are:
*
* Value Type Value Range
* U_INT_1
* [0, 28-1]
* U_INT_2
* [0, 216-1]
* U_INT_4
* [0, 232-1]
* INT_1
* [-27, 27-1]
* INT_2
* [-215, 215-1]
* INT_4
* [-231, 231-1]
* INT_8
* [-263, 263-1]
*
* All other pairings are illegal and will cause an
* IllegalArgumentException
to be thrown.
*
* @see #U_INT_1
* @see #U_INT_2
* @see #U_INT_4
* @see #INT_1
* @see #INT_2
* @see #INT_4
* @see #INT_8
*
* @param valueType the data type of the object that is being
* created; must be one of the following:
* U_INT_1
,
* U_INT_2
,
* U_INT_4
,
* INT_1
,
* INT_2
,
* INT_4
, or
* INT_8
*
* @param value the value of the object being created; must be
* in the range specified for the given valueType
*
* @exception IllegalArgumentException if the valueType
* is not valid or the value
for the given legal
* valueType
is outside the valid range
*
*/
public DataElement(int valueType, long value) {
switch (valueType) {
case U_INT_1:
if (value < 0 || value > 0xff)
throw new IllegalArgumentException(value + " not U_INT_1");
break;
case U_INT_2:
if (value < 0 || value > 0xffff)
throw new IllegalArgumentException(value + " not U_INT_2");
break;
case U_INT_4:
if (value < 0 || value > 0xffffffffl)
throw new IllegalArgumentException(value + " not U_INT_4");
break;
case INT_1:
if (value < -0x80 || value > 0x7f)
throw new IllegalArgumentException(value + " not INT_1");
break;
case INT_2:
if (value < -0x8000 || value > 0x7fff)
throw new IllegalArgumentException(value + " not INT_2");
break;
case INT_4:
if (value < -0x80000000 || value > 0x7fffffff)
throw new IllegalArgumentException(value + " not INT_4");
break;
case INT_8:
break;
default:
throw new IllegalArgumentException();
}
this.value = new Long(value);
this.valueType = valueType;
}
/**
* Creates a DataElement
whose data type is given by
* valueType
and whose value is specified by the argument
* value
. The legal values for the valueType
* and the corresponding attribute values are:
*
* Value Type Java Type / Value Range
* URL
java.lang.String
*
* UUID
* javax.bluetooth.UUID
* STRING
* java.lang.String
* INT_16
* [-2127, 2127-1] as a byte array
* whose length must be 16
* U_INT_8
* [0, 264-1] as a byte array whose length must
* be 8
* U_INT_16
* [0, 2128-1] as a byte array whose length must
* be 16
*
* All other pairings are illegal and would cause an
* IllegalArgumentException
exception.
*
* @see #URL
* @see #UUID
* @see #STRING
* @see #U_INT_8
* @see #INT_16
* @see #U_INT_16
*
* @param valueType the data type of the object that is being
* created; must be one of the following: URL
,
* UUID
,
* STRING
,
* INT_16
,
* U_INT_8
, or
* U_INT_16
*
* @param value the value for the DataElement
being created
* of type valueType
*
* @exception IllegalArgumentException if the value
* is not of the valueType
type or is not in the range
* specified or is null
*
*/
public DataElement(int valueType, Object value) {
if (value == null)
throw new IllegalArgumentException();
switch (valueType) {
case URL:
case STRING:
if (!(value instanceof String))
throw new IllegalArgumentException();
break;
case UUID:
if (!(value instanceof UUID))
throw new IllegalArgumentException();
break;
case U_INT_8:
if (!(value instanceof byte[]) || ((byte[]) value).length != 8)
throw new IllegalArgumentException();
break;
case U_INT_16:
case INT_16:
if (!(value instanceof byte[]) || ((byte[]) value).length != 16)
throw new IllegalArgumentException();
break;
default:
throw new IllegalArgumentException();
}
this.value = value;
this.valueType = valueType;
}
/**
* Adds a DataElement
to this DATALT
* or DATSEQ
DataElement
object.
* The elem
will be added at the end of the list.
* The elem
can be of any
* DataElement
type, i.e., URL
,
* NULL
, BOOL
, UUID
,
* STRING
, DATSEQ
, DATALT
,
* and the various signed and unsigned integer types.
* The same object may be added twice. If the object is
* successfully added the size of the DataElement
is
* increased by one.
*
* @param elem the DataElement
object to add
*
* @exception ClassCastException if the method is invoked on a
* DataElement
whose type is not DATALT
* or DATSEQ
*
* @exception NullPointerException if elem
is
* null
*
*/
public void addElement(DataElement elem) {
if (elem == null)
throw new NullPointerException();
switch (valueType) {
case DATALT:
case DATSEQ:
((Vector) value).addElement(elem);
break;
default:
throw new ClassCastException();
}
}
/**
* Inserts a DataElement
at the specified location.
* This method can be invoked only on a DATALT
or
* DATSEQ
DataElement
.
* elem
can be of any DataElement
* type, i.e., URL
, NULL
,
* BOOL
,
* UUID
, STRING
, DATSEQ
,
* DATALT
, and the various signed and unsigned
* integers. The same object may be added twice. If the object is
* successfully added the size will be increased by one.
* Each element with an index greater than or equal to the specified
* index is shifted upward to have an index one
* greater than the value it had previously.
*
* The index
must be greater than or equal to 0 and
* less than or equal to the current size. Therefore,
* DATALT
and
* DATSEQ
are zero-based objects.
*
* @param elem the DataElement
object to add
*
* @param index the location at which to add the
* DataElement
*
* @throws ClassCastException if the method is invoked on an
* instance of DataElement
whose type is not
* DATALT
or DATSEQ
*
* @throws IndexOutOfBoundsException if index
* is negative or greater than
* the size of the DATALT
or DATSEQ
*
* @throws NullPointerException if elem
is
* null
*
*/
public void insertElementAt(DataElement elem, int index) {
if (elem == null)
throw new NullPointerException();
switch (valueType) {
case DATALT:
case DATSEQ:
((Vector) value).insertElementAt(elem, index);
break;
default:
throw new ClassCastException();
}
}
/**
* Returns the number of DataElements
that are present
* in this DATALT
or DATSEQ
object.
* It is possible that the number of elements is equal to zero.
*
* @return the number of elements in this DATALT
* or DATSEQ
*
* @throws ClassCastException if this object is not of type
* DATALT
or DATSEQ
*/
public int getSize() {
switch (valueType) {
case DATALT:
case DATSEQ:
return ((Vector) value).size();
default:
throw new ClassCastException();
}
}
/**
* Removes the first occurrence of the DataElement
* from this object. elem
may be of any type, i.e.,
* URL
, NULL
, BOOL
,
* UUID
, STRING
, DATSEQ
,
* DATALT
, or the variously sized signed and unsigned
* integers.
* Only the first object in the list that is equal to
* elem
will be removed. Other objects, if present,
* are not removed. Since this class doesn?t override the
* equals()
method of the Object
class,
* the remove method compares only the
* references of objects. If elem
is
* successfully removed the size of this DataElement
* is decreased by one. Each DataElement
in the
* DATALT
or DATSEQ
with an index greater
* than the index of elem
is shifted downward to have
* an index one smaller than the value it had previously.
*
* @param elem the DataElement
to be removed
*
* @return true
if the input value was found and
* removed; else false
*
* @throws ClassCastException if this object is not of
* type DATALT
or DATSEQ
*
* @throws NullPointerException if elem
is
* null
*/
public boolean removeElement(DataElement elem) {
if (elem == null)
throw new NullPointerException();
switch (valueType) {
case DATALT:
case DATSEQ:
return ((Vector) value).removeElement(elem);
default:
throw new ClassCastException();
}
}
/**
* Returns the data type of the object this DataElement
* represents.
*
* @return the data type of this DataElement object; the legal
* return values are:
* URL
,
* NULL
,
* BOOL
,
* UUID
,
* STRING
,
* DATSEQ
,
* DATALT
,
* U_INT_1
,
* U_INT_2
,
* U_INT_4
,
* U_INT_8
,
* U_INT_16
,
* INT_1
,
* INT_2
,
* INT_4
,
* INT_8
, or
* INT_16
*
*/
public int getDataType() {
return valueType;
}
/**
* Returns the value of the DataElement
if it can be
* represented as a long
. The data type of the object must be
* U_INT_1
,
* U_INT_2
,
* U_INT_4
,
* INT_1
,
* INT_2
,
* INT_4
, or
* INT_8
.
*
*
* @return the value of the DataElement
as a long
*
* @throws ClassCastException if the data type of the object is not
* U_INT_1
,
* U_INT_2
,
* U_INT_4
, INT_1
,
* INT_2
, INT_4
,
* or INT_8
*/
public long getLong() {
switch (valueType) {
case U_INT_1:
case U_INT_2:
case U_INT_4:
case INT_1:
case INT_2:
case INT_4:
case INT_8:
return ((Long) value).longValue();
default:
throw new ClassCastException();
}
}
/**
* Returns the value of the DataElement
if it is represented as
* a boolean
.
*
*
* @return the boolean
value of this DataElement
* object
*
* @throws ClassCastException if the data type of this object is
* not of type BOOL
*/
public boolean getBoolean() {
if (valueType == BOOL)
return ((Boolean) value).booleanValue();
else
throw new ClassCastException();
}
/**
* Returns the value of this DataElement
as an
* Object
. This method returns the appropriate Java
* object for the following data types:
* URL
,
* UUID
,
* STRING
,
* DATSEQ
,
* DATALT
,
* U_INT_8
,
* U_INT_16
, and
* INT_16
.
* Modifying the returned Object
will not change this
* DataElement
.
*
* The following are the legal pairs of data type
* and Java object type being returned.
*
* DataElement
Data Type
* Java Data Type
* URL
java.lang.String
*
* UUID
* javax.bluetooth.UUID
* STRING
java.lang.String
*
* DATSEQ
* java.util.Enumeration
* DATALT
* java.util.Enumeration
* U_INT_8
* byte[] of length 8
* U_INT_16
* byte[] of length 16
* INT_16
* byte[] of length 16
*
*
* @return the value of this object
*
* @throws ClassCastException if the object is not a
* URL
, UUID
,
* STRING
, DATSEQ
, DATALT
,
* U_INT_8
,
* U_INT_16
,
* or INT_16
*
*/
public Object getValue() {
switch (valueType) {
case URL:
case STRING:
case UUID:
return value;
case U_INT_8:
case U_INT_16:
case INT_16:
// Modifying the returned Object will not change this DataElemen
return Utils.clone((byte[])value);
case DATSEQ:
case DATALT:
return ((Vector) value).elements();
default:
throw new ClassCastException();
}
}
private static String typeToString(int type) {
switch (type) {
case DataElement.NULL: return "NULL";
case DataElement.U_INT_1: return "U_INT_1";
case DataElement.U_INT_2: return "U_INT_2";
case DataElement.U_INT_4: return "U_INT_4";
case DataElement.INT_1: return "INT_1";
case DataElement.INT_2: return "INT_2";
case DataElement.INT_4: return "INT_4";
case DataElement.INT_8: return "INT_8";
case DataElement.INT_16: return "INT_16";
case DataElement.URL: return "URL";
case DataElement.STRING: return "STRING";
case DataElement.UUID: return "UUID";
case DataElement.DATSEQ: return "DATSEQ";
case DataElement.BOOL: return "BOOL";
case DataElement.DATALT: return "DATALT";
default: return "Unknown" + type;
}
}
/**
* @deprecated Use ((Object)dataElement).toString() if you want your
* application to run in MDIP profile
*/
public String toString() {
switch (valueType) {
case U_INT_1:
case U_INT_2:
case U_INT_4:
case INT_1:
case INT_2:
case INT_4:
case INT_8:
return typeToString(valueType) + " 0x" + Utils.toHexString(((Long) value).longValue());
case BOOL:
case URL:
case STRING:
case UUID:
return typeToString(valueType) + " " + value.toString();
case U_INT_8:
case U_INT_16:
case INT_16: {
byte[] b = (byte[]) value;
StringBuffer buf = new StringBuffer();
buf.append(typeToString(valueType)).append(" ");
for (int i = 0; i < b.length; i++) {
buf.append(Integer.toHexString(b[i] >> 4 & 0xf));
buf.append(Integer.toHexString(b[i] & 0xf));
}
return buf.toString();
}
case DATSEQ: {
StringBuffer buf = new StringBuffer("DATSEQ {\n");
for (Enumeration e = ((Vector) value).elements(); e.hasMoreElements();) {
buf.append(e.nextElement());
buf.append("\n");
}
buf.append("}");
return buf.toString();
}
case DATALT: {
StringBuffer buf = new StringBuffer("DATALT {\n");
for (Enumeration e = ((Vector) value).elements(); e.hasMoreElements();) {
buf.append(e.nextElement());
buf.append("\n");
}
buf.append("}");
return buf.toString();
}
default:
return "???";
}
}
}