FileDocCategorySizeDatePackage
DataElement.javaAPI DocphoneME MR2 API (J2ME)11259Wed May 02 18:00:30 BST 2007javax.bluetooth

DataElement.java

/*
 *
 *
 * Portions Copyright  2000-2007 Sun Microsystems, Inc. All Rights
 * Reserved.  Use is subject to license terms.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 only, as published by the Free Software Foundation.
 * 
 * This program 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
 * General Public License version 2 for more details (a copy is
 * included at /legal/license.txt).
 * 
 * You should have received a copy of the GNU General Public License
 * version 2 along with this work; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 * 
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 or visit www.sun.com if you need additional
 * information or have any questions.
 */

/*
 * (c) Copyright 2001, 2002 Motorola, Inc.  ALL RIGHTS RESERVED.
 */
package javax.bluetooth;
import java.util.Vector;

/**
 * This class is defined by the JSR-82 specification
 * <em>Java™ APIs for Bluetooth™ Wireless Technology,
 * Version 1.1.</em>
 */
// JAVADOC COMMENT ELIDED 
public class DataElement {

    // JAVADOC COMMENT ELIDED 
    public static final int NULL = 0x0000;

    // JAVADOC COMMENT ELIDED 
    public static final int U_INT_1 = 0x0008;

    // JAVADOC COMMENT ELIDED 
    public static final int U_INT_2 = 0x0009;

    // JAVADOC COMMENT ELIDED 
    public static final int U_INT_4 = 0x000A;

    // JAVADOC COMMENT ELIDED 
    public static final int U_INT_8 = 0x000B;

    // JAVADOC COMMENT ELIDED 
    public static final int U_INT_16 = 0x000C;

    // JAVADOC COMMENT ELIDED 
    public static final int INT_1 = 0x0010;

    // JAVADOC COMMENT ELIDED 
    public static final int INT_2 = 0x0011;

    // JAVADOC COMMENT ELIDED 
    public static final int INT_4 = 0x0012;

    // JAVADOC COMMENT ELIDED 
    public static final int INT_8 = 0x0013;

    // JAVADOC COMMENT ELIDED 
    public static final int INT_16 = 0x0014;

    // JAVADOC COMMENT ELIDED 
    public static final int URL = 0x0040;

    // JAVADOC COMMENT ELIDED 
    public static final int UUID = 0x0018;

    // JAVADOC COMMENT ELIDED 
    public static final int BOOL = 0x0028;

    // JAVADOC COMMENT ELIDED 
    public static final int STRING = 0x0020;

    // JAVADOC COMMENT ELIDED 
    public static final int DATSEQ = 0x0030;

    // JAVADOC COMMENT ELIDED 
    public static final int DATALT = 0x0038;

    /** Keeps the specified or derived type of the element. */
    private int valueType;

    /** Keeps the boolean value for the type BOOL. */
    private boolean booleanValue;

    /** Keeps the long value for the types *INT*. */
    private long longValue;

    /**
     * Keeps the misc type value for the rest of types.
     *
     * This field also keeps the value for the type DATALT and DATSEQ.
     * In this case it's a Vector. The access to the Vector elements
     * is synchronized in cldc (according the source code). But,
     * this is not documented, so we make a synchronize access
     * to this field to fit any cldc implementation.
     */
    private Object miscValue;

    // JAVADOC COMMENT ELIDED 
    public DataElement(int valueType) {
        switch (valueType) {
        case NULL: /* miscValue = null in this case. */
            break;
        case DATALT: /* falls through */
        case DATSEQ:
            this.miscValue = new Vector();
            break;
        default:
            throw new IllegalArgumentException(
                    "Invalid valueType for this constructor: " + valueType);
        }
        this.valueType = valueType;
    }

    // JAVADOC COMMENT ELIDED 
    public DataElement(boolean bool) {
        valueType = BOOL;
        booleanValue = bool;
    }

    // JAVADOC COMMENT ELIDED 
    public DataElement(int valueType, long value) {
        long min = 0;
        long max = 0;

        switch (valueType) {
        case U_INT_1:
            max = 0xffL;
            break;
        case U_INT_2:
            max = 0xffffL;
            break;
        case U_INT_4:
            max = 0xffffffffL;
            break;
        case INT_1:
            min = Byte.MIN_VALUE;
            max = Byte.MAX_VALUE;
            break;
        case INT_2:
            min = -0x8000L;
            max = 0x7fffL;
            break;
        case INT_4:
            min = Integer.MIN_VALUE;
            max = Integer.MAX_VALUE;
            break;
        case INT_8:
            min = Long.MIN_VALUE;
            max = Long.MAX_VALUE;
            break;
        default:
            throw new IllegalArgumentException(
                    "Invalid 'valueType' for this constructor: " + valueType);
        }

        // check if value in the valid rangle for this type
        if (value < min || value > max) {
            throw new IllegalArgumentException(
                    "Invalid 'value' for specified type: " + value);
        }
        this.valueType = valueType;
        this.longValue = value;
    }

    // JAVADOC COMMENT ELIDED 
    public DataElement(int valueType, Object value) {
        boolean isCorrectValue = true;

        switch (valueType) {
        case URL: /* falls through */
        case STRING:
            isCorrectValue = value instanceof String;
            break;
        case UUID:
            isCorrectValue = value instanceof UUID;
            break;
        case INT_16: /* falls through */
        case U_INT_16:
            isCorrectValue = value instanceof byte[]
                    && ((byte[]) value).length == 16;
            break;
        case U_INT_8:
            isCorrectValue = value instanceof byte[]
                    && ((byte[]) value).length == 8;
            break;
        default:
            throw new IllegalArgumentException(
                    "Invalid 'valueType' for this constructor: " + valueType);
        }

        // check if value in the valid rangle for this type
        if (!isCorrectValue) {
            throw new IllegalArgumentException(
                    "Invalid 'value' for specified type: " + value);
        }
        this.valueType = valueType;
        this.miscValue = value;
    }

    // JAVADOC COMMENT ELIDED 
    public synchronized void addElement(DataElement elem) {

        /*
         * We can't optimize this by invoking the
         * this.insertElementAt(elem, getSize()), because
         * the ClassCastException may be thrown from getSize()
         * which gives us improper stack trace.
         */
        if (valueType != DATSEQ && valueType != DATALT) {
            throw new ClassCastException(
                    "Invalid element type for this method: " + valueType);
        }

        if (elem == null) {
            throw new NullPointerException("Specified element is null");
        }
        ((Vector) miscValue).addElement(elem);
    }

    // JAVADOC COMMENT ELIDED 
    public synchronized void insertElementAt(DataElement elem, int index) {
        if (valueType != DATSEQ && valueType != DATALT) {
            throw new ClassCastException(
                    "Invalid element type for this method: " + valueType);
        }

        if (elem == null) {
            throw new NullPointerException("Specified element is null");
        }

        /*
         * We can't use the Vector.insertElementAt check for out of
         * bounds, because Vector throws ArrayIndexOutOfBoundsException
         * in this case.
         */
        if (index < 0 || index > ((Vector) miscValue).size()) {
            throw new IndexOutOfBoundsException(
                    "Specified index is out of range");
        }
        ((Vector) miscValue).insertElementAt(elem, index);
    }

    // JAVADOC COMMENT ELIDED 
    public synchronized int getSize() {
        if (valueType != DATSEQ && valueType != DATALT) {
            throw new ClassCastException(
                    "Invalid element type for this method: " + valueType);
        }
        return ((Vector) miscValue).size();
    }

    // JAVADOC COMMENT ELIDED 
    public boolean removeElement(DataElement elem) {
        if (valueType != DATSEQ && valueType != DATALT) {
            throw new ClassCastException(
                    "Invalid element type for this method: " + valueType);
        }

        if (elem == null) {
            throw new NullPointerException("Specified element is null");
        }

        /*
         * The Bluetooth spec says the two DataElement equals if their
         * references are equal. According to cldc1.1 ref impl sources,
         * the Vector uses 'equals' call, and the Object.equls uses
         * a references compare, so we may not care about doing this here.
         */
        return ((Vector) miscValue).removeElement(elem);
    }

    // JAVADOC COMMENT ELIDED 
    public int getDataType() {
        return valueType;
    }

    // JAVADOC COMMENT ELIDED 
    public long getLong() {
        switch (valueType) {
        case U_INT_1: /* falls through */
        case U_INT_2: /* falls through */
        case U_INT_4: /* falls through */
        case INT_1: /* falls through */
        case INT_2: /* falls through */
        case INT_4: /* falls through */
        case INT_8:
            break;
        default:
            throw new ClassCastException(
                    "Invalid element type for this method: " + valueType);
        }
        return longValue;
    }

    // JAVADOC COMMENT ELIDED 
    public boolean getBoolean() {
        if (valueType != BOOL) {
            throw new ClassCastException(
                    "Invalid element type for this method: " + valueType);
        }
        return booleanValue;
    }

    // JAVADOC COMMENT ELIDED 
    public synchronized Object getValue() {
        Object retValue = miscValue;

        /*
         * According to cldc & bluetooth specifications, the String and UUID
         * are immutable, so we may not return a clone object to safe
         * the stored one.
         *
         * The Vector.elements() returns an Enumeration, which does not allow
         * to break the Vector either.
         *
         * The array may be modified by reference, so we have to return
         * a clone.
         */
        switch (valueType) {
        case URL: /* falls through */
        case STRING: /* falls through */
        case UUID:
            break;
        case DATALT: /* falls through */
        case DATSEQ:
            retValue = ((Vector) miscValue).elements();
            break;
        case U_INT_8: /* falls through */
        case U_INT_16: /* falls through */
        case INT_16:
            int length = ((byte[]) miscValue).length;
            retValue = new byte[length];
            System.arraycopy(miscValue, 0, retValue, 0, length);
            break;
        default:
            throw new ClassCastException(
                    "Invalid element type for this method: " + valueType);
        }
        return retValue;
    }
} // end of class 'DataElement' definition