< prev index next >

src/java.management/share/classes/javax/management/openmbean/ArrayType.java

Print this page




  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.management.openmbean;
  27 
  28 import java.io.ObjectStreamException;
  29 import java.lang.reflect.Array;
  30 
  31 /**
  32  * The <code>ArrayType</code> class is the <i>open type</i> class whose instances describe
  33  * all <i>open data</i> values which are n-dimensional arrays of <i>open data</i> values.
  34  * <p>
  35  * Examples of valid {@code ArrayType} instances are:
  36  * <pre>{@code
  37  * // 2-dimension array of java.lang.String
  38  * ArrayType<String[][]> a1 = new ArrayType<String[][]>(2, SimpleType.STRING);
  39  *
  40  * // 1-dimension array of int
  41  * ArrayType<int[]> a2 = new ArrayType<int[]>(SimpleType.INTEGER, true);
  42  *
  43  * // 1-dimension array of java.lang.Integer
  44  * ArrayType<Integer[]> a3 = new ArrayType<Integer[]>(SimpleType.INTEGER, false);
  45  *
  46  * // 4-dimension array of int
  47  * ArrayType<int[][][][]> a4 = new ArrayType<int[][][][]>(3, a2);
  48  *
  49  * // 4-dimension array of java.lang.Integer
  50  * ArrayType<Integer[][][][]> a5 = new ArrayType<Integer[][][][]>(3, a3);
  51  *
  52  * // 1-dimension array of java.lang.String


 205      * e.g. SimpleType.BOOLEAN for "boolean", SimpleType.CHARACTER for
 206      * "char", etc...
 207      * @param primitiveTypeName the primitive type of the array element ("boolean",
 208      *        "char", etc...)
 209      * @return the OpenType corresponding to the given primitive type name
 210      *         (SimpleType.BOOLEAN, SimpleType.CHARACTER, etc...)
 211      *         return null if the given elementClassName is not a primitive
 212      *         type name.
 213      **/
 214     static SimpleType<?> getPrimitiveOpenType(String primitiveTypeName) {
 215         for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
 216             if (primitiveTypeName.equals(typeDescr[PRIMITIVE_TYPE_NAME_INDEX]))
 217                 return (SimpleType<?>)typeDescr[PRIMITIVE_OPEN_TYPE_INDEX];
 218         }
 219         return null;
 220     }
 221 
 222     /* *** Constructor *** */
 223 
 224     /**
 225      * Constructs an <tt>ArrayType</tt> instance describing <i>open data</i> values which are
 226      * arrays with dimension <var>dimension</var> of elements whose <i>open type</i> is <var>elementType</var>.









 227      * <p>
 228      * When invoked on an <tt>ArrayType</tt> instance, the {@link OpenType#getClassName() getClassName} method
 229      * returns the class name of the array instances it describes (following the rules defined by the
 230      * {@link Class#getName() getName} method of <code>java.lang.Class</code>), not the class name of the array elements
 231      * (which is returned by a call to <tt>getElementOpenType().getClassName()</tt>).
 232      * <p>
 233      * The internal field corresponding to the type name of this <code>ArrayType</code> instance is also set to
 234      * the class name of the array instances it describes.
 235      * In other words, the methods <code>getClassName</code> and <code>getTypeName</code> return the same string value.
 236      * The internal field corresponding to the description of this <code>ArrayType</code> instance is set to a string value


 237      * which follows the following template:
 238      * <ul>
 239      * <li>if non-primitive array: <tt><i>&lt;dimension&gt;</i>-dimension array of <i>&lt;element_class_name&gt;</i></tt></li>
 240      * <li>if primitive array: <tt><i>&lt;dimension&gt;</i>-dimension array of <i>&lt;primitive_type_of_the_element_class_name&gt;</i></tt></li>


 241      * </ul>
 242      * <p>
 243      * As an example, the following piece of code:
 244      * <pre>{@code
 245      * ArrayType<String[][][]> t = new ArrayType<String[][][]>(3, SimpleType.STRING);
 246      * System.out.println("array class name       = " + t.getClassName());
 247      * System.out.println("element class name     = " + t.getElementOpenType().getClassName());
 248      * System.out.println("array type name        = " + t.getTypeName());
 249      * System.out.println("array type description = " + t.getDescription());
 250      * }</pre>
 251      * would produce the following output:
 252      * <pre>{@code
 253      * array class name       = [[[Ljava.lang.String;
 254      * element class name     = java.lang.String
 255      * array type name        = [[[Ljava.lang.String;
 256      * array type description = 3-dimension array of java.lang.String
 257      * }</pre>
 258      * And the following piece of code which is equivalent to the one listed
 259      * above would also produce the same output:
 260      * <pre>{@code
 261      * ArrayType<String[]> t1 = new ArrayType<String[]>(1, SimpleType.STRING);
 262      * ArrayType<String[][]> t2 = new ArrayType<String[][]>(1, t1);
 263      * ArrayType<String[][][]> t3 = new ArrayType<String[][][]>(1, t2);
 264      * System.out.println("array class name       = " + t3.getClassName());
 265      * System.out.println("element class name     = " + t3.getElementOpenType().getClassName());
 266      * System.out.println("array type name        = " + t3.getTypeName());
 267      * System.out.println("array type description = " + t3.getDescription());
 268      * }</pre>
 269      *
 270      * @param  dimension  the dimension of arrays described by this <tt>ArrayType</tt> instance;
 271      *                    must be greater than or equal to 1.
 272      *
 273      * @param  elementType  the <i>open type</i> of element values contained
 274      *                      in the arrays described by this <tt>ArrayType</tt>
 275      *                      instance; must be an instance of either
 276      *                      <tt>SimpleType</tt>, <tt>CompositeType</tt>,
 277      *                      <tt>TabularType</tt> or another <tt>ArrayType</tt>
 278      *                      with a <tt>SimpleType</tt>, <tt>CompositeType</tt>
 279      *                      or <tt>TabularType</tt> as its <tt>elementType</tt>.
 280      *
 281      * @throws IllegalArgumentException if {@code dimension} is not a positive
 282      *                                  integer.
 283      * @throws OpenDataException  if <var>elementType's className</var> is not
 284      *                            one of the allowed Java class names for open
 285      *                            data.
 286      */
 287     public ArrayType(int dimension,
 288                      OpenType<?> elementType) throws OpenDataException {
 289         // Check and construct state defined by parent.
 290         // We can't use the package-private OpenType constructor because
 291         // we don't know if the elementType parameter is sane.
 292         super(buildArrayClassName(dimension, elementType),
 293               buildArrayClassName(dimension, elementType),
 294               buildArrayDescription(dimension, elementType));
 295 
 296         // Check and construct state specific to ArrayType
 297         //
 298         if (elementType.isArray()) {
 299             ArrayType<?> at = (ArrayType<?>) elementType;


 301             this.elementType = at.getElementOpenType();
 302             this.primitiveArray = at.isPrimitiveArray();
 303         } else {
 304             this.dimension = dimension;
 305             this.elementType = elementType;
 306             this.primitiveArray = false;
 307         }
 308     }
 309 
 310     /**
 311      * Constructs a unidimensional {@code ArrayType} instance for the
 312      * supplied {@code SimpleType}.
 313      * <p>
 314      * This constructor supports the creation of arrays of primitive
 315      * types when {@code primitiveArray} is {@code true}.
 316      * <p>
 317      * For primitive arrays the {@link #getElementOpenType()} method
 318      * returns the {@link SimpleType} corresponding to the wrapper
 319      * type of the primitive type of the array.
 320      * <p>
 321      * When invoked on an <tt>ArrayType</tt> instance, the {@link OpenType#getClassName() getClassName} method
 322      * returns the class name of the array instances it describes (following the rules defined by the
 323      * {@link Class#getName() getName} method of <code>java.lang.Class</code>), not the class name of the array elements
 324      * (which is returned by a call to <tt>getElementOpenType().getClassName()</tt>).



 325      * <p>
 326      * The internal field corresponding to the type name of this <code>ArrayType</code> instance is also set to

 327      * the class name of the array instances it describes.
 328      * In other words, the methods <code>getClassName</code> and <code>getTypeName</code> return the same string value.
 329      * The internal field corresponding to the description of this <code>ArrayType</code> instance is set to a string value


 330      * which follows the following template:
 331      * <ul>
 332      * <li>if non-primitive array: <tt>1-dimension array of <i>&lt;element_class_name&gt;</i></tt></li>
 333      * <li>if primitive array: <tt>1-dimension array of <i>&lt;primitive_type_of_the_element_class_name&gt;</i></tt></li>


 334      * </ul>
 335      * <p>
 336      * As an example, the following piece of code:
 337      * <pre>{@code
 338      * ArrayType<int[]> t = new ArrayType<int[]>(SimpleType.INTEGER, true);
 339      * System.out.println("array class name       = " + t.getClassName());
 340      * System.out.println("element class name     = " + t.getElementOpenType().getClassName());
 341      * System.out.println("array type name        = " + t.getTypeName());
 342      * System.out.println("array type description = " + t.getDescription());
 343      * }</pre>
 344      * would produce the following output:
 345      * <pre>{@code
 346      * array class name       = [I
 347      * element class name     = java.lang.Integer
 348      * array type name        = [I
 349      * array type description = 1-dimension array of int
 350      * }</pre>
 351      *
 352      * @param elementType the {@code SimpleType} of the element values
 353      *                    contained in the arrays described by this


 466             final String primitiveType =
 467                     getPrimitiveTypeName(elementClassName);
 468 
 469             // Ideally we should throw an IllegalArgumentException here,
 470             // but for compatibility reasons we throw an OpenDataException.
 471             // (used to be thrown by OpenType() constructor).
 472             //
 473             if (primitiveType == null)
 474                 throw new OpenDataException("Element is not a primitive type: "+
 475                         elementClassName);
 476             result.append(primitiveType);
 477         } else {
 478             result.append(elementClassName);
 479         }
 480         return result.toString();
 481     }
 482 
 483     /* *** ArrayType specific information methods *** */
 484 
 485     /**
 486      * Returns the dimension of arrays described by this <tt>ArrayType</tt> instance.
 487      *
 488      * @return the dimension.
 489      */
 490     public int getDimension() {
 491 
 492         return dimension;
 493     }
 494 
 495     /**
 496      * Returns the <i>open type</i> of element values contained in the arrays described by this <tt>ArrayType</tt> instance.

 497      *
 498      * @return the element type.
 499      */
 500     public OpenType<?> getElementOpenType() {
 501 
 502         return elementType;
 503     }
 504 
 505     /**
 506      * Returns <code>true</code> if the open data values this open
 507      * type describes are primitive arrays, <code>false</code> otherwise.
 508      *
 509      * @return true if this is a primitive array type.
 510      *
 511      * @since 1.6
 512      */
 513     public boolean isPrimitiveArray() {
 514 
 515         return primitiveArray;
 516     }
 517 
 518     /**
 519      * Tests whether <var>obj</var> is a value for this <code>ArrayType</code>
 520      * instance.
 521      * <p>
 522      * This method returns <code>true</code> if and only if <var>obj</var>
 523      * is not null, <var>obj</var> is an array and any one of the following
 524      * is <tt>true</tt>:
 525      *
 526      * <ul>
 527      * <li>if this <code>ArrayType</code> instance describes an array of
 528      * <tt>SimpleType</tt> elements or their corresponding primitive types,
 529      * <var>obj</var>'s class name is the same as the className field defined
 530      * for this <code>ArrayType</code> instance (i.e. the class name returned
 531      * by the {@link OpenType#getClassName() getClassName} method, which
 532      * includes the dimension information),<br>&nbsp;</li>
 533      * <li>if this <code>ArrayType</code> instance describes an array of
 534      * classes implementing the {@code TabularData} interface or the
 535      * {@code CompositeData} interface, <var>obj</var> is assignable to
 536      * such a declared array, and each element contained in {<var>obj</var>
 537      * is either null or a valid value for the element's open type specified
 538      * by this <code>ArrayType</code> instance.</li>
 539      * </ul>
 540      *
 541      * @param obj the object to be tested.
 542      *
 543      * @return <code>true</code> if <var>obj</var> is a value for this
 544      * <code>ArrayType</code> instance.
 545      */
 546     public boolean isValue(Object obj) {
 547 
 548         // if obj is null, return false
 549         //
 550         if (obj == null) {
 551             return false;
 552         }
 553 
 554         Class<?> objClass = obj.getClass();
 555         String objClassName = objClass.getName();
 556 
 557         // if obj is not an array, return false
 558         //
 559         if ( ! objClass.isArray() ) {
 560             return false;
 561         }
 562 
 563         // Test if obj's class name is the same as for the array values that this instance describes
 564         // (this is fine if elements are of simple types, which are final classes)


 632                 }
 633             }
 634             return true;
 635         }
 636     }
 637 
 638     @Override
 639     boolean isAssignableFrom(OpenType<?> ot) {
 640         if (!(ot instanceof ArrayType<?>))
 641             return false;
 642         ArrayType<?> at = (ArrayType<?>) ot;
 643         return (at.getDimension() == getDimension() &&
 644                 at.isPrimitiveArray() == isPrimitiveArray() &&
 645                 at.getElementOpenType().isAssignableFrom(getElementOpenType()));
 646     }
 647 
 648 
 649     /* *** Methods overriden from class Object *** */
 650 
 651     /**
 652      * Compares the specified <code>obj</code> parameter with this
 653      * <code>ArrayType</code> instance for equality.
 654      * <p>
 655      * Two <code>ArrayType</code> instances are equal if and only if they
 656      * describe array instances which have the same dimension, elements'
 657      * open type and primitive array flag.
 658      *
 659      * @param obj the object to be compared for equality with this
 660      *            <code>ArrayType</code> instance; if <var>obj</var>
 661      *            is <code>null</code> or is not an instance of the
 662      *            class <code>ArrayType</code> this method returns
 663      *            <code>false</code>.
 664      *
 665      * @return <code>true</code> if the specified object is equal to
 666      *         this <code>ArrayType</code> instance.
 667      */
 668     public boolean equals(Object obj) {
 669 
 670         // if obj is null, return false
 671         //
 672         if (obj == null) {
 673             return false;
 674         }
 675 
 676         // if obj is not an ArrayType, return false
 677         //
 678         if (!(obj instanceof ArrayType<?>))
 679             return false;
 680         ArrayType<?> other = (ArrayType<?>) obj;
 681 
 682         // if other's dimension is different than this instance's, return false
 683         //
 684         if (this.dimension != other.dimension) {
 685             return false;
 686         }
 687 
 688         // Test if other's elementType field is the same as for this instance
 689         //
 690         if (!this.elementType.equals(other.elementType)) {
 691             return false;
 692         }
 693 
 694         // Test if other's primitiveArray flag is the same as for this instance
 695         //
 696         return this.primitiveArray == other.primitiveArray;
 697     }
 698 
 699     /**
 700      * Returns the hash code value for this <code>ArrayType</code> instance.
 701      * <p>
 702      * The hash code of an <code>ArrayType</code> instance is the sum of the
 703      * hash codes of all the elements of information used in <code>equals</code>
 704      * comparisons (i.e. dimension, elements' open type and primitive array flag).
 705      * The hashcode for a primitive value is the hashcode of the corresponding boxed
 706      * object (e.g. the hashcode for <tt>true</tt> is <tt>Boolean.TRUE.hashCode()</tt>).
 707      * This ensures that <code> t1.equals(t2) </code> implies that
 708      * <code> t1.hashCode()==t2.hashCode() </code> for any two
 709      * <code>ArrayType</code> instances <code>t1</code> and <code>t2</code>,
 710      * as required by the general contract of the method
 711      * {@link Object#hashCode() Object.hashCode()}.
 712      * <p>
 713      * As <code>ArrayType</code> instances are immutable, the hash
 714      * code for this instance is calculated once, on the first call
 715      * to <code>hashCode</code>, and then the same value is returned
 716      * for subsequent calls.
 717      *
 718      * @return  the hash code value for this <code>ArrayType</code> instance
 719      */
 720     public int hashCode() {
 721 
 722         // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
 723         //
 724         if (myHashCode == null) {
 725             int value = 0;
 726             value += dimension;
 727             value += elementType.hashCode();
 728             value += Boolean.valueOf(primitiveArray).hashCode();
 729             myHashCode = Integer.valueOf(value);
 730         }
 731 
 732         // return always the same hash code for this instance (immutable)
 733         //
 734         return myHashCode.intValue();
 735     }
 736 
 737     /**
 738      * Returns a string representation of this <code>ArrayType</code> instance.
 739      * <p>
 740      * The string representation consists of the name of this class (i.e.
 741      * <code>javax.management.openmbean.ArrayType</code>), the type name,
 742      * the dimension, the elements' open type and the primitive array flag
 743      * defined for this instance.
 744      * <p>
 745      * As <code>ArrayType</code> instances are immutable, the
 746      * string representation for this instance is calculated
 747      * once, on the first call to <code>toString</code>, and
 748      * then the same value is returned for subsequent calls.
 749      *
 750      * @return a string representation of this <code>ArrayType</code> instance
 751      */
 752     public String toString() {
 753 
 754         // Calculate the string representation if it has not yet been done (ie 1st call to toString())
 755         //
 756         if (myToString == null) {
 757             myToString = getClass().getName() +
 758                          "(name=" + getTypeName() +
 759                          ",dimension=" + dimension +
 760                          ",elementType=" + elementType +
 761                          ",primitiveArray=" + primitiveArray + ")";
 762         }
 763 
 764         // return always the same string representation for this instance (immutable)
 765         //
 766         return myToString;
 767     }
 768 
 769     /**
 770      * Create an {@code ArrayType} instance in a type-safe manner.


 778      * As an example, the following piece of code:
 779      * <pre>{@code
 780      * ArrayType<String[]> t1 = ArrayType.getArrayType(SimpleType.STRING);
 781      * ArrayType<String[][]> t2 = ArrayType.getArrayType(t1);
 782      * ArrayType<String[][][]> t3 = ArrayType.getArrayType(t2);
 783      * System.out.println("array class name       = " + t3.getClassName());
 784      * System.out.println("element class name     = " + t3.getElementOpenType().getClassName());
 785      * System.out.println("array type name        = " + t3.getTypeName());
 786      * System.out.println("array type description = " + t3.getDescription());
 787      * }</pre>
 788      * would produce the following output:
 789      * <pre>{@code
 790      * array class name       = [[[Ljava.lang.String;
 791      * element class name     = java.lang.String
 792      * array type name        = [[[Ljava.lang.String;
 793      * array type description = 3-dimension array of java.lang.String
 794      * }</pre>
 795      *
 796      * @param <E> the Java type that described instances must have
 797      * @param  elementType  the <i>open type</i> of element values contained
 798      *                      in the arrays described by this <tt>ArrayType</tt>
 799      *                      instance; must be an instance of either
 800      *                      <tt>SimpleType</tt>, <tt>CompositeType</tt>,
 801      *                      <tt>TabularType</tt> or another <tt>ArrayType</tt>
 802      *                      with a <tt>SimpleType</tt>, <tt>CompositeType</tt>
 803      *                      or <tt>TabularType</tt> as its <tt>elementType</tt>.
 804      * @return an {@code ArrayType} instance
 805      * @throws OpenDataException if <var>elementType's className</var> is not
 806      *                           one of the allowed Java class names for open
 807      *                           data.
 808      *
 809      * @since 1.6
 810      */
 811     public static <E> ArrayType<E[]> getArrayType(OpenType<E> elementType)
 812         throws OpenDataException {
 813         return new ArrayType<E[]>(1, elementType);
 814     }
 815 
 816     /**
 817      * Create an {@code ArrayType} instance in a type-safe manner.
 818      * <p>
 819      * Calling this method twice with the same parameters may return the
 820      * same object or two equal but not identical objects.
 821      * <p>
 822      * As an example, the following piece of code:
 823      * <pre>{@code




  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.management.openmbean;
  27 
  28 import java.io.ObjectStreamException;
  29 import java.lang.reflect.Array;
  30 
  31 /**
  32  * The {@code ArrayType} class is the <i>open type</i> class whose instances describe
  33  * all <i>open data</i> values which are n-dimensional arrays of <i>open data</i> values.
  34  * <p>
  35  * Examples of valid {@code ArrayType} instances are:
  36  * <pre>{@code
  37  * // 2-dimension array of java.lang.String
  38  * ArrayType<String[][]> a1 = new ArrayType<String[][]>(2, SimpleType.STRING);
  39  *
  40  * // 1-dimension array of int
  41  * ArrayType<int[]> a2 = new ArrayType<int[]>(SimpleType.INTEGER, true);
  42  *
  43  * // 1-dimension array of java.lang.Integer
  44  * ArrayType<Integer[]> a3 = new ArrayType<Integer[]>(SimpleType.INTEGER, false);
  45  *
  46  * // 4-dimension array of int
  47  * ArrayType<int[][][][]> a4 = new ArrayType<int[][][][]>(3, a2);
  48  *
  49  * // 4-dimension array of java.lang.Integer
  50  * ArrayType<Integer[][][][]> a5 = new ArrayType<Integer[][][][]>(3, a3);
  51  *
  52  * // 1-dimension array of java.lang.String


 205      * e.g. SimpleType.BOOLEAN for "boolean", SimpleType.CHARACTER for
 206      * "char", etc...
 207      * @param primitiveTypeName the primitive type of the array element ("boolean",
 208      *        "char", etc...)
 209      * @return the OpenType corresponding to the given primitive type name
 210      *         (SimpleType.BOOLEAN, SimpleType.CHARACTER, etc...)
 211      *         return null if the given elementClassName is not a primitive
 212      *         type name.
 213      **/
 214     static SimpleType<?> getPrimitiveOpenType(String primitiveTypeName) {
 215         for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
 216             if (primitiveTypeName.equals(typeDescr[PRIMITIVE_TYPE_NAME_INDEX]))
 217                 return (SimpleType<?>)typeDescr[PRIMITIVE_OPEN_TYPE_INDEX];
 218         }
 219         return null;
 220     }
 221 
 222     /* *** Constructor *** */
 223 
 224     /**
 225      * Constructs an {@code ArrayType} instance describing <i>open data</i> values which are
 226      * arrays with dimension <var>dimension</var> of elements
 227      * whose <i>open type</i> is <var>elementType</var>.
 228      * <p>
 229      * When invoked on an {@code ArrayType} instance,
 230      * the {@link OpenType#getClassName() getClassName} method
 231      * returns the class name of the array instances it describes
 232      * (following the rules defined by the
 233      * {@link Class#getName() getName} method of {@code java.lang.Class}),
 234      * not the class name of the array elements
 235      * (which is returned by a call to {@code getElementOpenType().getClassName()}).
 236      * <p>
 237      * The internal field corresponding to the type name of this
 238      * {@code ArrayType} instance is also set to




 239      * the class name of the array instances it describes.
 240      * In other words, the methods {@code getClassName} and
 241      * {@code getTypeName} return the same string value.
 242      * The internal field corresponding to the description of this
 243      * {@code ArrayType} instance is set to a string value
 244      * which follows the following template:
 245      * <ul>
 246      * <li>if non-primitive array: <code><i>&lt;dimension&gt;</i>-dimension array
 247      *     of <i>&lt;element_class_name&gt;</i></code></li>
 248      * <li>if primitive array: <code><i>&lt;dimension&gt;</i>-dimension array
 249      *     of <i>&lt;primitive_type_of_the_element_class_name&gt;</i></code></li>
 250      * </ul>
 251      * <p>
 252      * As an example, the following piece of code:
 253      * <pre>{@code
 254      * ArrayType<String[][][]> t = new ArrayType<String[][][]>(3, SimpleType.STRING);
 255      * System.out.println("array class name       = " + t.getClassName());
 256      * System.out.println("element class name     = " + t.getElementOpenType().getClassName());
 257      * System.out.println("array type name        = " + t.getTypeName());
 258      * System.out.println("array type description = " + t.getDescription());
 259      * }</pre>
 260      * would produce the following output:
 261      * <pre>{@code
 262      * array class name       = [[[Ljava.lang.String;
 263      * element class name     = java.lang.String
 264      * array type name        = [[[Ljava.lang.String;
 265      * array type description = 3-dimension array of java.lang.String
 266      * }</pre>
 267      * And the following piece of code which is equivalent to the one listed
 268      * above would also produce the same output:
 269      * <pre>{@code
 270      * ArrayType<String[]> t1 = new ArrayType<String[]>(1, SimpleType.STRING);
 271      * ArrayType<String[][]> t2 = new ArrayType<String[][]>(1, t1);
 272      * ArrayType<String[][][]> t3 = new ArrayType<String[][][]>(1, t2);
 273      * System.out.println("array class name       = " + t3.getClassName());
 274      * System.out.println("element class name     = " + t3.getElementOpenType().getClassName());
 275      * System.out.println("array type name        = " + t3.getTypeName());
 276      * System.out.println("array type description = " + t3.getDescription());
 277      * }</pre>
 278      *
 279      * @param  dimension  the dimension of arrays described by this {@code ArrayType} instance;
 280      *                    must be greater than or equal to 1.
 281      *
 282      * @param  elementType  the <i>open type</i> of element values contained
 283      *                      in the arrays described by this {@code ArrayType}
 284      *                      instance; must be an instance of either
 285      *                      {@code SimpleType}, {@code CompositeType},
 286      *                      {@code TabularType} or another {@code ArrayType}
 287      *                      with a {@code SimpleType}, {@code CompositeType}
 288      *                      or {@code TabularType} as its {@code elementType}.
 289      *
 290      * @throws IllegalArgumentException if {@code dimension} is not a positive
 291      *                                  integer.
 292      * @throws OpenDataException  if <var>elementType's className</var> is not
 293      *                            one of the allowed Java class names for open
 294      *                            data.
 295      */
 296     public ArrayType(int dimension,
 297                      OpenType<?> elementType) throws OpenDataException {
 298         // Check and construct state defined by parent.
 299         // We can't use the package-private OpenType constructor because
 300         // we don't know if the elementType parameter is sane.
 301         super(buildArrayClassName(dimension, elementType),
 302               buildArrayClassName(dimension, elementType),
 303               buildArrayDescription(dimension, elementType));
 304 
 305         // Check and construct state specific to ArrayType
 306         //
 307         if (elementType.isArray()) {
 308             ArrayType<?> at = (ArrayType<?>) elementType;


 310             this.elementType = at.getElementOpenType();
 311             this.primitiveArray = at.isPrimitiveArray();
 312         } else {
 313             this.dimension = dimension;
 314             this.elementType = elementType;
 315             this.primitiveArray = false;
 316         }
 317     }
 318 
 319     /**
 320      * Constructs a unidimensional {@code ArrayType} instance for the
 321      * supplied {@code SimpleType}.
 322      * <p>
 323      * This constructor supports the creation of arrays of primitive
 324      * types when {@code primitiveArray} is {@code true}.
 325      * <p>
 326      * For primitive arrays the {@link #getElementOpenType()} method
 327      * returns the {@link SimpleType} corresponding to the wrapper
 328      * type of the primitive type of the array.
 329      * <p>
 330      * When invoked on an {@code ArrayType} instance,
 331      * the {@link OpenType#getClassName() getClassName} method
 332      * returns the class name of the array instances it describes
 333      * (following the rules defined by the
 334      * {@link Class#getName() getName} method of {@code java.lang.Class}),
 335      * not the class name of the array elements
 336      * (which is returned by a call to {@code getElementOpenType().getClassName()}).
 337      * <p>
 338      * The internal field corresponding to the type name of this
 339      * {@code ArrayType} instance is also set to
 340      * the class name of the array instances it describes.
 341      * In other words, the methods {@code getClassName} and
 342      * {@code getTypeName} return the same string value.
 343      * The internal field corresponding to the description
 344      * of this {@code ArrayType} instance is set to a string value
 345      * which follows the following template:
 346      * <ul>
 347      * <li>if non-primitive array: <code>1-dimension array
 348      *     of <i>&lt;element_class_name&gt;</i></code></li>
 349      * <li>if primitive array: <code>1-dimension array
 350      *     of <i>&lt;primitive_type_of_the_element_class_name&gt;</i></code></li>
 351      * </ul>
 352      * <p>
 353      * As an example, the following piece of code:
 354      * <pre>{@code
 355      * ArrayType<int[]> t = new ArrayType<int[]>(SimpleType.INTEGER, true);
 356      * System.out.println("array class name       = " + t.getClassName());
 357      * System.out.println("element class name     = " + t.getElementOpenType().getClassName());
 358      * System.out.println("array type name        = " + t.getTypeName());
 359      * System.out.println("array type description = " + t.getDescription());
 360      * }</pre>
 361      * would produce the following output:
 362      * <pre>{@code
 363      * array class name       = [I
 364      * element class name     = java.lang.Integer
 365      * array type name        = [I
 366      * array type description = 1-dimension array of int
 367      * }</pre>
 368      *
 369      * @param elementType the {@code SimpleType} of the element values
 370      *                    contained in the arrays described by this


 483             final String primitiveType =
 484                     getPrimitiveTypeName(elementClassName);
 485 
 486             // Ideally we should throw an IllegalArgumentException here,
 487             // but for compatibility reasons we throw an OpenDataException.
 488             // (used to be thrown by OpenType() constructor).
 489             //
 490             if (primitiveType == null)
 491                 throw new OpenDataException("Element is not a primitive type: "+
 492                         elementClassName);
 493             result.append(primitiveType);
 494         } else {
 495             result.append(elementClassName);
 496         }
 497         return result.toString();
 498     }
 499 
 500     /* *** ArrayType specific information methods *** */
 501 
 502     /**
 503      * Returns the dimension of arrays described by this {@code ArrayType} instance.
 504      *
 505      * @return the dimension.
 506      */
 507     public int getDimension() {
 508 
 509         return dimension;
 510     }
 511 
 512     /**
 513      * Returns the <i>open type</i> of element values contained
 514      * in the arrays described by this {@code ArrayType} instance.
 515      *
 516      * @return the element type.
 517      */
 518     public OpenType<?> getElementOpenType() {
 519 
 520         return elementType;
 521     }
 522 
 523     /**
 524      * Returns {@code true} if the open data values this open
 525      * type describes are primitive arrays, {@code false} otherwise.
 526      *
 527      * @return true if this is a primitive array type.
 528      *
 529      * @since 1.6
 530      */
 531     public boolean isPrimitiveArray() {
 532 
 533         return primitiveArray;
 534     }
 535 
 536     /**
 537      * Tests whether <var>obj</var> is a value for this {@code ArrayType}
 538      * instance.
 539      * <p>
 540      * This method returns {@code true} if and only if <var>obj</var>
 541      * is not null, <var>obj</var> is an array and any one of the following
 542      * is {@code true}:
 543      *
 544      * <ul>
 545      * <li>if this {@code ArrayType} instance describes an array of
 546      * {@code SimpleType} elements or their corresponding primitive types,
 547      * <var>obj</var>'s class name is the same as the className field defined
 548      * for this {@code ArrayType} instance (i.e. the class name returned
 549      * by the {@link OpenType#getClassName() getClassName} method, which
 550      * includes the dimension information),<br>&nbsp;</li>
 551      * <li>if this {@code ArrayType} instance describes an array of
 552      * classes implementing the {@code TabularData} interface or the
 553      * {@code CompositeData} interface, <var>obj</var> is assignable to
 554      * such a declared array, and each element contained in {<var>obj</var>
 555      * is either null or a valid value for the element's open type specified
 556      * by this {@code ArrayType} instance.</li>
 557      * </ul>
 558      *
 559      * @param obj the object to be tested.
 560      *
 561      * @return {@code true} if <var>obj</var> is a value for this
 562      * {@code ArrayType} instance.
 563      */
 564     public boolean isValue(Object obj) {
 565 
 566         // if obj is null, return false
 567         //
 568         if (obj == null) {
 569             return false;
 570         }
 571 
 572         Class<?> objClass = obj.getClass();
 573         String objClassName = objClass.getName();
 574 
 575         // if obj is not an array, return false
 576         //
 577         if ( ! objClass.isArray() ) {
 578             return false;
 579         }
 580 
 581         // Test if obj's class name is the same as for the array values that this instance describes
 582         // (this is fine if elements are of simple types, which are final classes)


 650                 }
 651             }
 652             return true;
 653         }
 654     }
 655 
 656     @Override
 657     boolean isAssignableFrom(OpenType<?> ot) {
 658         if (!(ot instanceof ArrayType<?>))
 659             return false;
 660         ArrayType<?> at = (ArrayType<?>) ot;
 661         return (at.getDimension() == getDimension() &&
 662                 at.isPrimitiveArray() == isPrimitiveArray() &&
 663                 at.getElementOpenType().isAssignableFrom(getElementOpenType()));
 664     }
 665 
 666 
 667     /* *** Methods overriden from class Object *** */
 668 
 669     /**
 670      * Compares the specified {@code obj} parameter with this
 671      * {@code ArrayType} instance for equality.
 672      * <p>
 673      * Two {@code ArrayType} instances are equal if and only if they
 674      * describe array instances which have the same dimension, elements'
 675      * open type and primitive array flag.
 676      *
 677      * @param obj the object to be compared for equality with this
 678      *            {@code ArrayType} instance; if <var>obj</var>
 679      *            is {@code null} or is not an instance of the
 680      *            class {@code ArrayType} this method returns
 681      *            {@code false}.
 682      *
 683      * @return {@code true} if the specified object is equal to
 684      *         this {@code ArrayType} instance.
 685      */
 686     public boolean equals(Object obj) {
 687 
 688         // if obj is null, return false
 689         //
 690         if (obj == null) {
 691             return false;
 692         }
 693 
 694         // if obj is not an ArrayType, return false
 695         //
 696         if (!(obj instanceof ArrayType<?>))
 697             return false;
 698         ArrayType<?> other = (ArrayType<?>) obj;
 699 
 700         // if other's dimension is different than this instance's, return false
 701         //
 702         if (this.dimension != other.dimension) {
 703             return false;
 704         }
 705 
 706         // Test if other's elementType field is the same as for this instance
 707         //
 708         if (!this.elementType.equals(other.elementType)) {
 709             return false;
 710         }
 711 
 712         // Test if other's primitiveArray flag is the same as for this instance
 713         //
 714         return this.primitiveArray == other.primitiveArray;
 715     }
 716 
 717     /**
 718      * Returns the hash code value for this {@code ArrayType} instance.
 719      * <p>
 720      * The hash code of an {@code ArrayType} instance is the sum of the
 721      * hash codes of all the elements of information used in {@code equals}
 722      * comparisons (i.e. dimension, elements' open type and primitive array flag).
 723      * The hashcode for a primitive value is the hashcode of the corresponding boxed
 724      * object (e.g. the hashcode for {@code true} is {@code Boolean.TRUE.hashCode()}).
 725      * This ensures that {@code t1.equals(t2)} implies that
 726      * {@code t1.hashCode()==t2.hashCode()} for any two
 727      * {@code ArrayType} instances {@code t1} and {@code t2},
 728      * as required by the general contract of the method
 729      * {@link Object#hashCode() Object.hashCode()}.
 730      * <p>
 731      * As {@code ArrayType} instances are immutable, the hash
 732      * code for this instance is calculated once, on the first call
 733      * to {@code hashCode}, and then the same value is returned
 734      * for subsequent calls.
 735      *
 736      * @return  the hash code value for this {@code ArrayType} instance
 737      */
 738     public int hashCode() {
 739 
 740         // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
 741         //
 742         if (myHashCode == null) {
 743             int value = 0;
 744             value += dimension;
 745             value += elementType.hashCode();
 746             value += Boolean.valueOf(primitiveArray).hashCode();
 747             myHashCode = Integer.valueOf(value);
 748         }
 749 
 750         // return always the same hash code for this instance (immutable)
 751         //
 752         return myHashCode.intValue();
 753     }
 754 
 755     /**
 756      * Returns a string representation of this {@code ArrayType} instance.
 757      * <p>
 758      * The string representation consists of the name of this class (i.e.
 759      * {@code javax.management.openmbean.ArrayType}), the type name,
 760      * the dimension, the elements' open type and the primitive array flag
 761      * defined for this instance.
 762      * <p>
 763      * As {@code ArrayType} instances are immutable, the
 764      * string representation for this instance is calculated
 765      * once, on the first call to {@code toString}, and
 766      * then the same value is returned for subsequent calls.
 767      *
 768      * @return a string representation of this {@code ArrayType} instance
 769      */
 770     public String toString() {
 771 
 772         // Calculate the string representation if it has not yet been done (ie 1st call to toString())
 773         //
 774         if (myToString == null) {
 775             myToString = getClass().getName() +
 776                          "(name=" + getTypeName() +
 777                          ",dimension=" + dimension +
 778                          ",elementType=" + elementType +
 779                          ",primitiveArray=" + primitiveArray + ")";
 780         }
 781 
 782         // return always the same string representation for this instance (immutable)
 783         //
 784         return myToString;
 785     }
 786 
 787     /**
 788      * Create an {@code ArrayType} instance in a type-safe manner.


 796      * As an example, the following piece of code:
 797      * <pre>{@code
 798      * ArrayType<String[]> t1 = ArrayType.getArrayType(SimpleType.STRING);
 799      * ArrayType<String[][]> t2 = ArrayType.getArrayType(t1);
 800      * ArrayType<String[][][]> t3 = ArrayType.getArrayType(t2);
 801      * System.out.println("array class name       = " + t3.getClassName());
 802      * System.out.println("element class name     = " + t3.getElementOpenType().getClassName());
 803      * System.out.println("array type name        = " + t3.getTypeName());
 804      * System.out.println("array type description = " + t3.getDescription());
 805      * }</pre>
 806      * would produce the following output:
 807      * <pre>{@code
 808      * array class name       = [[[Ljava.lang.String;
 809      * element class name     = java.lang.String
 810      * array type name        = [[[Ljava.lang.String;
 811      * array type description = 3-dimension array of java.lang.String
 812      * }</pre>
 813      *
 814      * @param <E> the Java type that described instances must have
 815      * @param  elementType  the <i>open type</i> of element values contained
 816      *                      in the arrays described by this {@code ArrayType}
 817      *                      instance; must be an instance of either
 818      *                      {@code SimpleType}, {@code CompositeType},
 819      *                      {@code TabularType} or another {@code ArrayType}
 820      *                      with a {@code SimpleType}, {@code CompositeType}
 821      *                      or {@code TabularType} as its {@code elementType}.
 822      * @return an {@code ArrayType} instance
 823      * @throws OpenDataException if <var>elementType's className</var> is not
 824      *                           one of the allowed Java class names for open
 825      *                           data.
 826      *
 827      * @since 1.6
 828      */
 829     public static <E> ArrayType<E[]> getArrayType(OpenType<E> elementType)
 830         throws OpenDataException {
 831         return new ArrayType<E[]>(1, elementType);
 832     }
 833 
 834     /**
 835      * Create an {@code ArrayType} instance in a type-safe manner.
 836      * <p>
 837      * Calling this method twice with the same parameters may return the
 838      * same object or two equal but not identical objects.
 839      * <p>
 840      * As an example, the following piece of code:
 841      * <pre>{@code


< prev index next >