TabularType class is the  open type class
 * whose instances describe the types of {@link TabularData TabularData} values.
 *
 * @since 1.5
 */
public class TabularType extends OpenTypeTabularType instance, checking for the validity of the given parameters.
     * The validity constraints are described below for each parameter.
     * 
     * The Java class name of tabular data values this tabular type represents
     * (ie the class name returned by the {@link OpenType#getClassName() getClassName} method)
     * is set to the string value returned by TabularData.class.getName().
     * 
     * @param  typeName  The name given to the tabular type this instance represents; cannot be a null or empty string.
     *  Returns, in the same order as was given to this instance's
     * constructor, an unmodifiable List of the names of the items the
     * values of which are used to uniquely index each row element of
     * tabular data values described by this  If obj is null or is not an instance of
     *  If obj is an instance of
     *  
     * Two  
     * The hash code of a  
     * As  
     * The string representation consists of the name of this class (ie  
     * As 
 
     * @param  description  The human readable description of the tabular type this instance represents;
     *                      cannot be a null or empty string.
     * 
 
     * @param  rowType  The type of the row elements of tabular data values described by this tabular type instance;
     *                  cannot be null.
     * 
 
     * @param  indexNames  The names of the items the values of which are used to uniquely index each row element in the
     *                     tabular data values described by this tabular type instance;
     *                     cannot be null or empty. Each element should be an item name defined in rowType
     *                     (no null or empty string allowed).
     *                     It is important to note that the order of the item names in indexNames
     *                     is used by the methods {@link TabularData#get(java.lang.Object[]) get} and
     *                     {@link TabularData#remove(java.lang.Object[]) remove} of class
     *                     TabularData to match their array of values parameter to items.
     * 
 
     * @throws IllegalArgumentException  if rowType is null,
     *                                   or indexNames is a null or empty array,
     *                                   or an element in indexNames is a null or empty string,
     *                                   or typeName or description is a null or empty string.
     * 
 
     * @throws OpenDataException  if an element's value of indexNames
     *                            is not an item name defined in rowType.
     */
    public TabularType(String         typeName,
                       String         description,
                       CompositeType  rowType,
                       String[]       indexNames) throws OpenDataException {
        // Check and initialize state defined by parent.
        //
        super(TabularData.class.getName(), typeName, description, false);
        // Check rowType is not null
        //
        if (rowType == null) {
            throw new IllegalArgumentException("Argument rowType cannot be null.");
        }
        // Check indexNames is neither null nor empty and does not contain any null element or empty string
        //
        checkForNullElement(indexNames, "indexNames");
        checkForEmptyString(indexNames, "indexNames");
        // Check all indexNames values are valid item names for rowType
        //
        for (int i=0; iTabularType
     * instance.TabularType instance.
     *
     * javax.management.openmbean.TabularData,
     * isValue returns false.javax.management.openmbean.TabularData, say {@code
     * td}, the result is true if this {@code TabularType} is
     * assignable from {@link TabularData#getTabularType()
     * td.getTabularType()}, as defined in {@link
     * CompositeType#isValue CompositeType.isValue}.TabularType instance.
     *
     * @return true if obj is a value for this
     * tabular type, false otherwise.
     */
    public boolean isValue(Object obj) {
        // if obj is null or not a TabularData, return false
        //
        if (!(obj instanceof TabularData))
            return false;
        // if obj is not a TabularData, return false
        //
        TabularData value = (TabularData) obj;
        TabularType valueType = value.getTabularType();
        return isAssignableFrom(valueType);
    }
    @Override
    boolean isAssignableFrom(OpenType> ot) {
        if (!(ot instanceof TabularType))
            return false;
        TabularType tt = (TabularType) ot;
        if (!getTypeName().equals(tt.getTypeName()) ||
                !getIndexNames().equals(tt.getIndexNames()))
            return false;
        return getRowType().isAssignableFrom(tt.getRowType());
    }
    /* *** Methods overriden from class Object *** */
    /**
     * Compares the specified obj parameter with this TabularType instance for equality.
     * TabularType instances are equal if and only if all of the following statements are true:
     * 
     * 
     * 
 
     * @param  obj  the object to be compared for equality with this TabularType instance;
     *              if obj is null, equals returns false.
     *
     * @return  true if the specified object is equal to this TabularType instance.
     */
    public boolean equals(Object obj) {
        // if obj is null, return false
        //
        if (obj == null) {
            return false;
        }
        // if obj is not a TabularType, return false
        //
        TabularType other;
        try {
            other = (TabularType) obj;
        } catch (ClassCastException e) {
            return false;
        }
        // Now, really test for equality between this TabularType instance and the other:
        //
        // their names should be equal
        if ( ! this.getTypeName().equals(other.getTypeName()) ) {
            return false;
        }
        // their row types should be equal
        if ( ! this.rowType.equals(other.rowType) ) {
            return false;
        }
        // their index names should be equal and in the same order (ensured by List.equals())
        if ( ! this.indexNames.equals(other.indexNames) ) {
            return false;
        }
        // All tests for equality were successfull
        //
        return true;
    }
    /**
     * Returns the hash code value for this TabularType instance.
     * TabularType instance is the sum of the hash codes
     * of all elements of information used in equals comparisons
     * (ie: name, row type, index names).
     * This ensures that  t1.equals(t2)  implies that  t1.hashCode()==t2.hashCode() 
     * for any two TabularType instances t1 and t2,
     * as required by the general contract of the method
     * {@link Object#hashCode() Object.hashCode()}.
     * TabularType instances are immutable, the hash code for this instance is calculated once,
     * on the first call to hashCode, and then the same value is returned for subsequent calls.
     *
     * @return  the hash code value for this TabularType instance
     */
    public int hashCode() {
        // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
        //
        if (myHashCode == null) {
            int value = 0;
            value += this.getTypeName().hashCode();
            value += this.rowType.hashCode();
            for (String index : indexNames)
                value += index.hashCode();
            myHashCode = Integer.valueOf(value);
        }
        // return always the same hash code for this instance (immutable)
        //
        return myHashCode.intValue();
    }
    /**
     * Returns a string representation of this TabularType instance.
     * javax.management.openmbean.TabularType),
     * the type name for this instance, the row type string representation of this instance,
     * and the index names of this instance.
     * TabularType instances are immutable, the string representation for this instance is calculated once,
     * on the first call to toString, and then the same value is returned for subsequent calls.
     *
     * @return  a string representation of this TabularType instance
     */
    public String toString() {
        // Calculate the string representation if it has not yet been done (ie 1st call to toString())
        //
        if (myToString == null) {
            final StringBuilder result = new StringBuilder()
                .append(this.getClass().getName())
                .append("(name=")
                .append(getTypeName())
                .append(",rowType=")
                .append(rowType.toString())
                .append(",indexNames=(");
            String sep = "";
            for (String index : indexNames) {
                result.append(sep).append(index);
                sep = ",";
            }
            result.append("))");
            myToString = result.toString();
        }
        // return always the same string representation for this instance (immutable)
        //
        return myToString;
    }
}