Source Code Cross Referenced for ArrayType.java in  » 6.0-JDK-Core » management » javax » management » openmbean » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » management » javax.management.openmbean 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package javax.management.openmbean;
0027
0028        import java.io.ObjectStreamException;
0029        import java.lang.reflect.Array;
0030
0031        /**
0032         * The <code>ArrayType</code> class is the <i>open type</i> class whose instances describe 
0033         * all <i>open data</i> values which are n-dimensional arrays of <i>open data</i> values.
0034         * <p>
0035         * Examples of valid {@code ArrayType} instances are:
0036         * <pre>
0037         * // 2-dimension array of java.lang.String
0038         * ArrayType<String[][]> a1 = new ArrayType<String[][]>(2, SimpleType.STRING);
0039         *
0040         * // 1-dimension array of int
0041         * ArrayType<int[]> a2 = new ArrayType<int[]>(SimpleType.INTEGER, true);
0042         *
0043         * // 1-dimension array of java.lang.Integer
0044         * ArrayType<Integer[]> a3 = new ArrayType<Integer[]>(SimpleType.INTEGER, false);
0045         *
0046         * // 4-dimension array of int
0047         * ArrayType<int[][][][]> a4 = new ArrayType<int[][][][]>(3, a2);
0048         *
0049         * // 4-dimension array of java.lang.Integer
0050         * ArrayType<Integer[][][][]> a5 = new ArrayType<Integer[][][][]>(3, a3);
0051         *
0052         * // 1-dimension array of java.lang.String
0053         * ArrayType<String[]> a6 = new ArrayType<String[]>(SimpleType.STRING, false);
0054         *
0055         * // 1-dimension array of long
0056         * ArrayType<long[]> a7 = new ArrayType<long[]>(SimpleType.LONG, true);
0057         *
0058         * // 1-dimension array of java.lang.Integer
0059         * ArrayType<Integer[]> a8 = ArrayType.getArrayType(SimpleType.INTEGER);
0060         *
0061         * // 2-dimension array of java.lang.Integer
0062         * ArrayType<Integer[][]> a9 = ArrayType.getArrayType(a8);
0063         *
0064         * // 2-dimension array of int
0065         * ArrayType<int[][]> a10 = ArrayType.getPrimitiveArrayType(int[][].class);
0066         *
0067         * // 3-dimension array of int
0068         * ArrayType<int[][][]> a11 = ArrayType.getArrayType(a10);
0069         *
0070         * // 1-dimension array of float
0071         * ArrayType<float[]> a12 = ArrayType.getPrimitiveArrayType(float[].class);
0072         *
0073         * // 2-dimension array of float
0074         * ArrayType<float[][]> a13 = ArrayType.getArrayType(a12);
0075         *
0076         * // 1-dimension array of javax.management.ObjectName
0077         * ArrayType<ObjectName[]> a14 = ArrayType.getArrayType(SimpleType.OBJECTNAME);
0078         *
0079         * // 2-dimension array of javax.management.ObjectName
0080         * ArrayType<ObjectName[][]> a15 = ArrayType.getArrayType(a14);
0081         *
0082         * // 3-dimension array of java.lang.String
0083         * ArrayType<String[][][]> a16 = new ArrayType<String[][][]>(3, SimpleType.STRING);
0084         *
0085         * // 1-dimension array of java.lang.String
0086         * ArrayType<String[]> a17 = new ArrayType<String[]>(1, SimpleType.STRING);
0087         *
0088         * // 2-dimension array of java.lang.String
0089         * ArrayType<String[][]> a18 = new ArrayType<String[][]>(1, a17);
0090         *
0091         * // 3-dimension array of java.lang.String
0092         * ArrayType<String[][][]> a19 = new ArrayType<String[][][]>(1, a18);
0093         * </pre>
0094         *
0095         *
0096         * @since 1.5
0097         */
0098        /*
0099         Generification note: we could have defined a type parameter that is the
0100         element type, with class ArrayType<E> extends OpenType<E[]>.  However,
0101         that doesn't buy us all that much.  We can't say
0102         public OpenType<E> getElementOpenType()
0103         because this ArrayType could be a multi-dimensional array.
0104         For example, if we had
0105         ArrayType(2, SimpleType.INTEGER)
0106         then E would have to be Integer[], while getElementOpenType() would
0107         return SimpleType.INTEGER, which is an OpenType<Integer>.
0108
0109         Furthermore, we would like to support int[] (as well as Integer[]) as
0110         an Open Type (RFE 5045358).  We would want this to be an OpenType<int[]>
0111         which can't be expressed as <E[]> because E can't be a primitive type
0112         like int.
0113         */
0114        public class ArrayType<T> extends OpenType<T> {
0115
0116            /* Serial version */
0117            static final long serialVersionUID = 720504429830309770L;
0118
0119            /**
0120             * @serial The dimension of arrays described by this {@link ArrayType}
0121             *         instance.
0122             */
0123            private int dimension;
0124
0125            /**
0126             * @serial The <i>open type</i> of element values contained in the arrays
0127             *         described by this {@link ArrayType} instance.
0128             */
0129            private OpenType<?> elementType;
0130
0131            /**
0132             * @serial This flag indicates whether this {@link ArrayType}
0133             *         describes a primitive array.
0134             *
0135             * @since 1.6
0136             */
0137            private boolean primitiveArray;
0138
0139            private transient Integer myHashCode = null; // As this instance is immutable, these two values
0140            private transient String myToString = null; // need only be calculated once.
0141
0142            // indexes refering to columns in the PRIMITIVE_ARRAY_TYPES table.
0143            private static final int PRIMITIVE_WRAPPER_NAME_INDEX = 0;
0144            private static final int PRIMITIVE_TYPE_NAME_INDEX = 1;
0145            private static final int PRIMITIVE_TYPE_KEY_INDEX = 2;
0146            private static final int PRIMITIVE_OPEN_TYPE_INDEX = 3;
0147
0148            private static final Object[][] PRIMITIVE_ARRAY_TYPES = {
0149                    { Boolean.class.getName(), boolean.class.getName(), "Z",
0150                            SimpleType.BOOLEAN },
0151                    { Character.class.getName(), char.class.getName(), "C",
0152                            SimpleType.CHARACTER },
0153                    { Byte.class.getName(), byte.class.getName(), "B",
0154                            SimpleType.BYTE },
0155                    { Short.class.getName(), short.class.getName(), "S",
0156                            SimpleType.SHORT },
0157                    { Integer.class.getName(), int.class.getName(), "I",
0158                            SimpleType.INTEGER },
0159                    { Long.class.getName(), long.class.getName(), "J",
0160                            SimpleType.LONG },
0161                    { Float.class.getName(), float.class.getName(), "F",
0162                            SimpleType.FLOAT },
0163                    { Double.class.getName(), double.class.getName(), "D",
0164                            SimpleType.DOUBLE } };
0165
0166            static boolean isPrimitiveContentType(final String primitiveKey) {
0167                for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
0168                    if (typeDescr[PRIMITIVE_TYPE_KEY_INDEX]
0169                            .equals(primitiveKey)) {
0170                        return true;
0171                    }
0172                }
0173                return false;
0174            }
0175
0176            /**
0177             * Return the key used to identify the element type in 
0178             * arrays - e.g. "Z" for boolean, "C" for char etc...
0179             * @param elementClassName the wrapper class name of the array 
0180             *        element ("Boolean",  "Character", etc...)
0181             * @return the key corresponding to the given type ("Z", "C", etc...)
0182             *         return null if the given elementClassName is not a primitive
0183             *         wrapper class name.
0184             **/
0185            static String getPrimitiveTypeKey(String elementClassName) {
0186                for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
0187                    if (elementClassName
0188                            .equals(typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]))
0189                        return (String) typeDescr[PRIMITIVE_TYPE_KEY_INDEX];
0190                }
0191                return null;
0192            }
0193
0194            /**
0195             * Return the primitive type name corresponding to the given wrapper class.
0196             * e.g. "boolean" for "Boolean", "char" for "Character" etc...
0197             * @param elementClassName the type of the array element ("Boolean", 
0198             *        "Character", etc...)
0199             * @return the primitive type name corresponding to the given wrapper class 
0200             *         ("boolean", "char", etc...)
0201             *         return null if the given elementClassName is not a primitive
0202             *         wrapper type name.
0203             **/
0204            static String getPrimitiveTypeName(String elementClassName) {
0205                for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
0206                    if (elementClassName
0207                            .equals(typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]))
0208                        return (String) typeDescr[PRIMITIVE_TYPE_NAME_INDEX];
0209                }
0210                return null;
0211            }
0212
0213            /**
0214             * Return the primitive open type corresponding to the given primitive type.
0215             * e.g. SimpleType.BOOLEAN for "boolean", SimpleType.CHARACTER for 
0216             * "char", etc...
0217             * @param primitiveTypeName the primitive type of the array element ("boolean", 
0218             *        "char", etc...)
0219             * @return the OpenType corresponding to the given primitive type name
0220             *         (SimpleType.BOOLEAN, SimpleType.CHARACTER, etc...)
0221             *         return null if the given elementClassName is not a primitive
0222             *         type name.
0223             **/
0224            static SimpleType<?> getPrimitiveOpenType(String primitiveTypeName) {
0225                for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
0226                    if (primitiveTypeName
0227                            .equals(typeDescr[PRIMITIVE_TYPE_NAME_INDEX]))
0228                        return (SimpleType<?>) typeDescr[PRIMITIVE_OPEN_TYPE_INDEX];
0229                }
0230                return null;
0231            }
0232
0233            /* *** Constructor *** */
0234
0235            /**
0236             * Constructs an <tt>ArrayType</tt> instance describing <i>open data</i> values which are 
0237             * arrays with dimension <var>dimension</var> of elements whose <i>open type</i> is <var>elementType</var>.
0238             * <p>
0239             * When invoked on an <tt>ArrayType</tt> instance, the {@link OpenType#getClassName() getClassName} method
0240             * returns the class name of the array instances it describes (following the rules defined by the 
0241             * {@link Class#getName() getName} method of <code>java.lang.Class</code>), not the class name of the array elements
0242             * (which is returned by a call to <tt>getElementOpenType().getClassName()</tt>).
0243             * <p>
0244             * The internal field corresponding to the type name of this <code>ArrayType</code> instance is also set to
0245             * the class name of the array instances it describes. 
0246             * In other words, the methods <code>getClassName</code> and <code>getTypeName</code> return the same string value.
0247             * The internal field corresponding to the description of this <code>ArrayType</code> instance is set to a string value
0248             * which follows the following template:
0249             * <ul>
0250             * <li>if non-primitive array: <tt><i>&lt;dimension&gt;</i>-dimension array of <i>&lt;element_class_name&gt;</i></tt></li>
0251             * <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>
0252             * </ul>
0253             * <p>
0254             * As an example, the following piece of code:
0255             * <pre>
0256             * ArrayType<String[][][]> t = new ArrayType<String[][][]>(3, SimpleType.STRING);
0257             * System.out.println("array class name       = " + t.getClassName());
0258             * System.out.println("element class name     = " + t.getElementOpenType().getClassName());
0259             * System.out.println("array type name        = " + t.getTypeName());
0260             * System.out.println("array type description = " + t.getDescription());
0261             * </pre>
0262             * would produce the following output:
0263             * <pre>
0264             * array class name       = [[[Ljava.lang.String;
0265             * element class name     = java.lang.String
0266             * array type name        = [[[Ljava.lang.String;
0267             * array type description = 3-dimension array of java.lang.String
0268             * </pre>
0269             * And the following piece of code which is equivalent to the one listed
0270             * above would also produce the same output:
0271             * <pre>
0272             * ArrayType<String[]> t1 = new ArrayType<String[]>(1, SimpleType.STRING);
0273             * ArrayType<String[][]> t2 = new ArrayType<String[][]>(1, t1);
0274             * ArrayType<String[][][]> t3 = new ArrayType<String[][][]>(1, t2);
0275             * System.out.println("array class name       = " + t3.getClassName());
0276             * System.out.println("element class name     = " + t3.getElementOpenType().getClassName());
0277             * System.out.println("array type name        = " + t3.getTypeName());
0278             * System.out.println("array type description = " + t3.getDescription());
0279             * </pre>
0280             *
0281             * @param  dimension  the dimension of arrays described by this <tt>ArrayType</tt> instance;
0282             *			  must be greater than or equal to 1.
0283             *
0284             * @param  elementType  the <i>open type</i> of element values contained
0285             *                      in the arrays described by this <tt>ArrayType</tt>
0286             *                      instance; must be an instance of either
0287             *                      <tt>SimpleType</tt>, <tt>CompositeType</tt>,
0288             *                      <tt>TabularType</tt> or another <tt>ArrayType</tt>
0289             *                      with a <tt>SimpleType</tt>, <tt>CompositeType</tt>
0290             *                      or <tt>TabularType</tt> as its <tt>elementType</tt>.
0291             *
0292             * @throws IllegalArgumentException if {@code dimension} is not a positive
0293             *                                  integer.
0294             * @throws OpenDataException  if <var>elementType's className</var> is not
0295             *                            one of the allowed Java class names for open
0296             *                            data.
0297             */
0298            public ArrayType(int dimension, OpenType<?> elementType)
0299                    throws OpenDataException {
0300                // Check and construct state defined by parent.
0301                // We can't use the package-private OpenType constructor because
0302                // we don't know if the elementType parameter is sane.
0303                super (buildArrayClassName(dimension, elementType),
0304                        buildArrayClassName(dimension, elementType),
0305                        buildArrayDescription(dimension, elementType));
0306
0307                // Check and construct state specific to ArrayType
0308                //
0309                if (elementType.isArray()) {
0310                    ArrayType at = (ArrayType) elementType;
0311                    this .dimension = at.getDimension() + dimension;
0312                    this .elementType = at.getElementOpenType();
0313                    this .primitiveArray = at.isPrimitiveArray();
0314                } else {
0315                    this .dimension = dimension;
0316                    this .elementType = elementType;
0317                    this .primitiveArray = false;
0318                }
0319            }
0320
0321            /**
0322             * Constructs a unidimensional {@code ArrayType} instance for the
0323             * supplied {@code SimpleType}.
0324             * <p>
0325             * This constructor supports the creation of arrays of primitive
0326             * types when {@code primitiveArray} is {@code true}.
0327             * <p>
0328             * For primitive arrays the {@link #getElementOpenType()} method
0329             * returns the {@link SimpleType} corresponding to the wrapper
0330             * type of the primitive type of the array.
0331             * <p>
0332             * When invoked on an <tt>ArrayType</tt> instance, the {@link OpenType#getClassName() getClassName} method
0333             * returns the class name of the array instances it describes (following the rules defined by the 
0334             * {@link Class#getName() getName} method of <code>java.lang.Class</code>), not the class name of the array elements
0335             * (which is returned by a call to <tt>getElementOpenType().getClassName()</tt>).
0336             * <p>
0337             * The internal field corresponding to the type name of this <code>ArrayType</code> instance is also set to
0338             * the class name of the array instances it describes. 
0339             * In other words, the methods <code>getClassName</code> and <code>getTypeName</code> return the same string value.
0340             * The internal field corresponding to the description of this <code>ArrayType</code> instance is set to a string value
0341             * which follows the following template:
0342             * <ul>
0343             * <li>if non-primitive array: <tt>1-dimension array of <i>&lt;element_class_name&gt;</i></tt></li>
0344             * <li>if primitive array: <tt>1-dimension array of <i>&lt;primitive_type_of_the_element_class_name&gt;</i></tt></li>
0345             * </ul>
0346             * <p>
0347             * As an example, the following piece of code:
0348             * <pre>
0349             * ArrayType<int[]> t = new ArrayType<int[]>(SimpleType.INTEGER, true);
0350             * System.out.println("array class name       = " + t.getClassName());
0351             * System.out.println("element class name     = " + t.getElementOpenType().getClassName());
0352             * System.out.println("array type name        = " + t.getTypeName());
0353             * System.out.println("array type description = " + t.getDescription());
0354             * </pre>
0355             * would produce the following output:
0356             * <pre>
0357             * array class name       = [I
0358             * element class name     = java.lang.Integer
0359             * array type name        = [I
0360             * array type description = 1-dimension array of int
0361             * </pre>
0362             *
0363             * @param elementType the {@code SimpleType} of the element values
0364             *                    contained in the arrays described by this
0365             *                    {@code ArrayType} instance.
0366             *
0367             * @param primitiveArray {@code true} when this array describes
0368             *                       primitive arrays.
0369             *
0370             * @throws IllegalArgumentException if {@code dimension} is not a positive
0371             * integer.
0372             * @throws OpenDataException if {@code primitiveArray} is {@code true} and
0373             * {@code elementType} is not a valid {@code SimpleType} for a primitive
0374             * type.
0375             *
0376             * @since 1.6
0377             */
0378            public ArrayType(SimpleType<?> elementType, boolean primitiveArray)
0379                    throws OpenDataException {
0380
0381                // Check and construct state defined by parent.
0382                // We can call the package-private OpenType constructor because the
0383                // set of SimpleTypes is fixed and SimpleType can't be subclassed.
0384                super (buildArrayClassName(1, elementType, primitiveArray),
0385                        buildArrayClassName(1, elementType, primitiveArray),
0386                        buildArrayDescription(1, elementType, primitiveArray),
0387                        true);
0388
0389                // Check and construct state specific to ArrayType
0390                //
0391                this .dimension = 1;
0392                this .elementType = elementType;
0393                this .primitiveArray = primitiveArray;
0394            }
0395
0396            /* Package-private constructor for callers we trust to get it right. */
0397            ArrayType(String className, String typeName, String description,
0398                    int dimension, OpenType elementType, boolean primitiveArray) {
0399                super (className, typeName, description, true);
0400                this .dimension = dimension;
0401                this .elementType = elementType;
0402                this .primitiveArray = primitiveArray;
0403            }
0404
0405            private static String buildArrayClassName(int dimension,
0406                    OpenType<?> elementType) throws OpenDataException {
0407                boolean isPrimitiveArray = false;
0408                if (elementType.isArray()) {
0409                    isPrimitiveArray = ((ArrayType) elementType)
0410                            .isPrimitiveArray();
0411                }
0412                return buildArrayClassName(dimension, elementType,
0413                        isPrimitiveArray);
0414            }
0415
0416            private static String buildArrayClassName(int dimension,
0417                    OpenType<?> elementType, boolean isPrimitiveArray)
0418                    throws OpenDataException {
0419                if (dimension < 1) {
0420                    throw new IllegalArgumentException(
0421                            "Value of argument dimension must be greater than 0");
0422                }
0423                StringBuilder result = new StringBuilder();
0424                String elementClassName = elementType.getClassName();
0425                // Add N (= dimension) additional '[' characters to the existing array
0426                for (int i = 1; i <= dimension; i++) {
0427                    result.append('[');
0428                }
0429                if (elementType.isArray()) {
0430                    result.append(elementClassName);
0431                } else {
0432                    if (isPrimitiveArray) {
0433                        final String key = getPrimitiveTypeKey(elementClassName);
0434                        // Ideally we should throw an IllegalArgumentException here,
0435                        // but for compatibility reasons we throw an OpenDataException.
0436                        // (used to be thrown by OpenType() constructor).
0437                        //
0438                        if (key == null)
0439                            throw new OpenDataException(
0440                                    "Element type is not primitive: "
0441                                            + elementClassName);
0442                        result.append(key);
0443                    } else {
0444                        result.append("L");
0445                        result.append(elementClassName);
0446                        result.append(';');
0447                    }
0448                }
0449                return result.toString();
0450            }
0451
0452            private static String buildArrayDescription(int dimension,
0453                    OpenType<?> elementType) throws OpenDataException {
0454                boolean isPrimitiveArray = false;
0455                if (elementType.isArray()) {
0456                    isPrimitiveArray = ((ArrayType) elementType)
0457                            .isPrimitiveArray();
0458                }
0459                return buildArrayDescription(dimension, elementType,
0460                        isPrimitiveArray);
0461            }
0462
0463            private static String buildArrayDescription(int dimension,
0464                    OpenType<?> elementType, boolean isPrimitiveArray)
0465                    throws OpenDataException {
0466                if (elementType.isArray()) {
0467                    ArrayType at = (ArrayType) elementType;
0468                    dimension += at.getDimension();
0469                    elementType = at.getElementOpenType();
0470                    isPrimitiveArray = at.isPrimitiveArray();
0471                }
0472                StringBuilder result = new StringBuilder(dimension
0473                        + "-dimension array of ");
0474                final String elementClassName = elementType.getClassName();
0475                if (isPrimitiveArray) {
0476                    // Convert from wrapper type to primitive type
0477                    final String primitiveType = getPrimitiveTypeName(elementClassName);
0478
0479                    // Ideally we should throw an IllegalArgumentException here,
0480                    // but for compatibility reasons we throw an OpenDataException.
0481                    // (used to be thrown by OpenType() constructor).
0482                    //
0483                    if (primitiveType == null)
0484                        throw new OpenDataException(
0485                                "Element is not a primitive type: "
0486                                        + elementClassName);
0487                    result.append(primitiveType);
0488                } else {
0489                    result.append(elementClassName);
0490                }
0491                return result.toString();
0492            }
0493
0494            /* *** ArrayType specific information methods *** */
0495
0496            /**
0497             * Returns the dimension of arrays described by this <tt>ArrayType</tt> instance.
0498             *
0499             * @return the dimension.
0500             */
0501            public int getDimension() {
0502
0503                return dimension;
0504            }
0505
0506            /**
0507             * Returns the <i>open type</i> of element values contained in the arrays described by this <tt>ArrayType</tt> instance.
0508             *
0509             * @return the element type.
0510             */
0511            public OpenType<?> getElementOpenType() {
0512
0513                return elementType;
0514            }
0515
0516            /**
0517             * Returns <code>true</code> if the open data values this open
0518             * type describes are primitive arrays, <code>false</code> otherwise.
0519             *
0520             * @return true if this is a primitive array type.
0521             *
0522             * @since 1.6
0523             */
0524            public boolean isPrimitiveArray() {
0525
0526                return primitiveArray;
0527            }
0528
0529            /**
0530             * Tests whether <var>obj</var> is a value for this <code>ArrayType</code>
0531             * instance.
0532             * <p>
0533             * This method returns <code>true</code> if and only if <var>obj</var>
0534             * is not null, <var>obj</var> is an array and any one of the following
0535             * is <tt>true</tt>:
0536             *
0537             * <ul>
0538             * <li>if this <code>ArrayType</code> instance describes an array of
0539             * <tt>SimpleType</tt> elements or their corresponding primitive types,
0540             * <var>obj</var>'s class name is the same as the className field defined
0541             * for this <code>ArrayType</code> instance (i.e. the class name returned
0542             * by the {@link OpenType#getClassName() getClassName} method, which
0543             * includes the dimension information),<br>&nbsp;</li>
0544             * <li>if this <code>ArrayType</code> instance describes an array of
0545             * classes implementing the {@code TabularData} interface or the
0546             * {@code CompositeData} interface, <var>obj</var> is assignable to
0547             * such a declared array, and each element contained in <var>obj</var>
0548             * is either null or a valid value for the element's open type specified
0549             * by this <code>ArrayType</code> instance.</li>
0550             * </ul>
0551             *
0552             * @param obj the object to be tested.
0553             *
0554             * @return <code>true</code> if <var>obj</var> is a value for this
0555             * <code>ArrayType</code> instance.
0556             */
0557            public boolean isValue(Object obj) {
0558
0559                // if obj is null, return false
0560                //
0561                if (obj == null) {
0562                    return false;
0563                }
0564
0565                Class objClass = obj.getClass();
0566                String objClassName = objClass.getName();
0567
0568                // if obj is not an array, return false
0569                //
0570                if (!objClass.isArray()) {
0571                    return false;
0572                }
0573
0574                // Test if obj's class name is the same as for the array values that this instance describes
0575                // (this is fine if elements are of simple types, which are final classes)
0576                //
0577                if (this .getClassName().equals(objClassName)) {
0578                    return true;
0579                }
0580
0581                // In case this ArrayType instance describes an array of classes implementing the TabularData or CompositeData interface,
0582                // we first check for the assignability of obj to such an array of TabularData or CompositeData, 
0583                // which ensures that:
0584                //  . obj is of the the same dimension as this ArrayType instance, 
0585                //  . it is declared as an array of elements which are either all TabularData or all CompositeData.
0586                //
0587                // If the assignment check is positive, 
0588                // then we have to check that each element in obj is of the same TabularType or CompositeType 
0589                // as the one described by this ArrayType instance.
0590                //
0591                // [About assignment check, note that the call below returns true: ]
0592                // [Class.forName("[Lpackage.CompositeData;").isAssignableFrom(Class.forName("[Lpackage.CompositeDataImpl;)")); ]
0593                //
0594                if ((this .elementType.getClassName().equals(TabularData.class
0595                        .getName()))
0596                        || (this .elementType.getClassName()
0597                                .equals(CompositeData.class.getName()))) {
0598
0599                    boolean isTabular = (elementType.getClassName()
0600                            .equals(TabularData.class.getName()));
0601                    int[] dims = new int[getDimension()];
0602                    Class<?> elementClass = isTabular ? TabularData.class
0603                            : CompositeData.class;
0604                    Class<?> targetClass = Array
0605                            .newInstance(elementClass, dims).getClass();
0606
0607                    // assignment check: return false if negative
0608                    if (!targetClass.isAssignableFrom(objClass)) {
0609                        return false;
0610                    }
0611
0612                    // check that all elements in obj are valid values for this ArrayType
0613                    if (!checkElementsType((Object[]) obj, this .dimension)) { // we know obj's dimension is this.dimension
0614                        return false;
0615                    }
0616
0617                    return true;
0618                }
0619
0620                // if previous tests did not return, then obj is not a value for this ArrayType instance
0621                return false;
0622            }
0623
0624            /**
0625             * Returns true if and only if all elements contained in the array argument x_dim_Array of dimension dim
0626             * are valid values (ie either null or of the right openType) 
0627             * for the element open type specified by this ArrayType instance.
0628             * 
0629             * This method's implementation uses recursion to go down the dimensions of the array argument.
0630             */
0631            private boolean checkElementsType(Object[] x_dim_Array, int dim) {
0632
0633                // if the elements of x_dim_Array are themselves array: go down recursively....
0634                if (dim > 1) {
0635                    for (int i = 0; i < x_dim_Array.length; i++) {
0636                        if (!checkElementsType((Object[]) x_dim_Array[i],
0637                                dim - 1)) {
0638                            return false;
0639                        }
0640                    }
0641                    return true;
0642                }
0643                // ...else, for a non-empty array, each element must be a valid value: either null or of the right openType
0644                else {
0645                    for (int i = 0; i < x_dim_Array.length; i++) {
0646                        if ((x_dim_Array[i] != null)
0647                                && (!this .getElementOpenType().isValue(
0648                                        x_dim_Array[i]))) {
0649                            return false;
0650                        }
0651                    }
0652                    return true;
0653                }
0654            }
0655
0656            @Override
0657            boolean isAssignableFrom(OpenType ot) {
0658                if (!(ot instanceof  ArrayType))
0659                    return false;
0660                ArrayType<?> at = (ArrayType<?>) ot;
0661                return (at.getDimension() == getDimension()
0662                        && at.isPrimitiveArray() == isPrimitiveArray() && at
0663                        .getElementOpenType().isAssignableFrom(
0664                                getElementOpenType()));
0665            }
0666
0667            /* *** Methods overriden from class Object *** */
0668
0669            /**
0670             * Compares the specified <code>obj</code> parameter with this
0671             * <code>ArrayType</code> instance for equality.
0672             * <p>
0673             * Two <code>ArrayType</code> instances are equal if and only if they
0674             * describe array instances which have the same dimension, elements'
0675             * open type and primitive array flag.
0676             *
0677             * @param obj the object to be compared for equality with this
0678             *            <code>ArrayType</code> instance; if <var>obj</var>
0679             *            is <code>null</code> or is not an instance of the
0680             *            class <code>ArrayType</code> this method returns
0681             *            <code>false</code>.
0682             *
0683             * @return <code>true</code> if the specified object is equal to
0684             *         this <code>ArrayType</code> instance.
0685             */
0686            public boolean equals(Object obj) {
0687
0688                // if obj is null, return false
0689                //
0690                if (obj == null) {
0691                    return false;
0692                }
0693
0694                // if obj is not an ArrayType, return false
0695                //
0696                if (!(obj instanceof  ArrayType))
0697                    return false;
0698                ArrayType other = (ArrayType) obj;
0699
0700                // if other's dimension is different than this instance's, return false
0701                //
0702                if (this .dimension != other.dimension) {
0703                    return false;
0704                }
0705
0706                // Test if other's elementType field is the same as for this instance
0707                //
0708                if (!this .elementType.equals(other.elementType)) {
0709                    return false;
0710                }
0711
0712                // Test if other's primitiveArray flag is the same as for this instance
0713                //
0714                return this .primitiveArray == other.primitiveArray;
0715            }
0716
0717            /**
0718             * Returns the hash code value for this <code>ArrayType</code> instance.
0719             * <p>
0720             * The hash code of an <code>ArrayType</code> instance is the sum of the
0721             * hash codes of all the elements of information used in <code>equals</code>
0722             * comparisons (i.e. dimension, elements' open type and primitive array flag).
0723             * The hashcode for a primitive value is the hashcode of the corresponding boxed
0724             * object (e.g. the hashcode for <tt>true</tt> is <tt>Boolean.TRUE.hashCode()</tt>).
0725             * This ensures that <code> t1.equals(t2) </code> implies that
0726             * <code> t1.hashCode()==t2.hashCode() </code> for any two
0727             * <code>ArrayType</code> instances <code>t1</code> and <code>t2</code>,
0728             * as required by the general contract of the method
0729             * {@link Object#hashCode() Object.hashCode()}.
0730             * <p>
0731             * As <code>ArrayType</code> instances are immutable, the hash
0732             * code for this instance is calculated once, on the first call
0733             * to <code>hashCode</code>, and then the same value is returned
0734             * for subsequent calls.
0735             *
0736             * @return  the hash code value for this <code>ArrayType</code> instance
0737             */
0738            public int hashCode() {
0739
0740                // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
0741                //
0742                if (myHashCode == null) {
0743                    int value = 0;
0744                    value += dimension;
0745                    value += elementType.hashCode();
0746                    value += Boolean.valueOf(primitiveArray).hashCode();
0747                    myHashCode = new Integer(value);
0748                }
0749
0750                // return always the same hash code for this instance (immutable)
0751                //
0752                return myHashCode.intValue();
0753            }
0754
0755            /**
0756             * Returns a string representation of this <code>ArrayType</code> instance.
0757             * <p>
0758             * The string representation consists of the name of this class (i.e.
0759             * <code>javax.management.openmbean.ArrayType</code>), the type name,
0760             * the dimension, the elements' open type and the primitive array flag
0761             * defined for this instance.
0762             * <p>
0763             * As <code>ArrayType</code> instances are immutable, the
0764             * string representation for this instance is calculated
0765             * once, on the first call to <code>toString</code>, and
0766             * then the same value is returned for subsequent calls.
0767             *
0768             * @return a string representation of this <code>ArrayType</code> instance
0769             */
0770            public String toString() {
0771
0772                // Calculate the string representation if it has not yet been done (ie 1st call to toString())
0773                //
0774                if (myToString == null) {
0775                    myToString = getClass().getName() + "(name="
0776                            + getTypeName() + ",dimension=" + dimension
0777                            + ",elementType=" + elementType
0778                            + ",primitiveArray=" + primitiveArray + ")";
0779                }
0780
0781                // return always the same string representation for this instance (immutable)
0782                //
0783                return myToString;
0784            }
0785
0786            /**
0787             * Create an {@code ArrayType} instance in a type-safe manner.
0788             * <p>
0789             * Multidimensional arrays can be built up by calling this method as many
0790             * times as necessary.
0791             * <p>
0792             * Calling this method twice with the same parameters may return the same
0793             * object or two equal but not identical objects.
0794             * <p>
0795             * As an example, the following piece of code:
0796             * <pre>
0797             * ArrayType<String[]> t1 = ArrayType.getArrayType(SimpleType.STRING);
0798             * ArrayType<String[][]> t2 = ArrayType.getArrayType(t1);
0799             * ArrayType<String[][][]> t3 = ArrayType.getArrayType(t2);
0800             * System.out.println("array class name       = " + t3.getClassName());
0801             * System.out.println("element class name     = " + t3.getElementOpenType().getClassName());
0802             * System.out.println("array type name        = " + t3.getTypeName());
0803             * System.out.println("array type description = " + t3.getDescription());
0804             * </pre>
0805             * would produce the following output:
0806             * <pre>
0807             * array class name       = [[[Ljava.lang.String;
0808             * element class name     = java.lang.String
0809             * array type name        = [[[Ljava.lang.String;
0810             * array type description = 3-dimension array of java.lang.String
0811             * </pre>
0812             *
0813             * @param  elementType  the <i>open type</i> of element values contained
0814             *                      in the arrays described by this <tt>ArrayType</tt>
0815             *                      instance; must be an instance of either
0816             *                      <tt>SimpleType</tt>, <tt>CompositeType</tt>,
0817             *                      <tt>TabularType</tt> or another <tt>ArrayType</tt>
0818             *                      with a <tt>SimpleType</tt>, <tt>CompositeType</tt>
0819             *                      or <tt>TabularType</tt> as its <tt>elementType</tt>.
0820             *
0821             * @throws OpenDataException if <var>elementType's className</var> is not
0822             *                           one of the allowed Java class names for open
0823             *                           data.
0824             *
0825             * @since 1.6
0826             */
0827            public static <E> ArrayType<E[]> getArrayType(
0828                    OpenType<E> elementType) throws OpenDataException {
0829                return new ArrayType<E[]>(1, elementType);
0830            }
0831
0832            /**
0833             * Create an {@code ArrayType} instance in a type-safe manner.
0834             * <p>
0835             * Calling this method twice with the same parameters may return the
0836             * same object or two equal but not identical objects.
0837             * <p>
0838             * As an example, the following piece of code:
0839             * <pre>
0840             * ArrayType<int[][][]> t = ArrayType.getPrimitiveArrayType(int[][][].class);
0841             * System.out.println("array class name       = " + t.getClassName());
0842             * System.out.println("element class name     = " + t.getElementOpenType().getClassName());
0843             * System.out.println("array type name        = " + t.getTypeName());
0844             * System.out.println("array type description = " + t.getDescription());
0845             * </pre>
0846             * would produce the following output:
0847             * <pre>
0848             * array class name       = [[[I
0849             * element class name     = java.lang.Integer
0850             * array type name        = [[[I
0851             * array type description = 3-dimension array of int
0852             * </pre>
0853             *
0854             * @param arrayClass a primitive array class such as {@code int[].class},
0855             *                   {@code boolean[][].class}, etc. The {@link
0856             *                   #getElementOpenType()} method of the returned
0857             *                   {@code ArrayType} returns the {@link SimpleType}
0858             *                   corresponding to the wrapper type of the primitive
0859             *                   type of the array.
0860             *
0861             * @throws IllegalArgumentException if <var>arrayClass</var> is not
0862             *                                  a primitive array.
0863             *
0864             * @since 1.6
0865             */
0866            @SuppressWarnings("unchecked")
0867            // can't get appropriate T for primitive array
0868            public static <T> ArrayType<T> getPrimitiveArrayType(
0869                    Class<T> arrayClass) {
0870                // Check if the supplied parameter is an array
0871                //
0872                if (!arrayClass.isArray()) {
0873                    throw new IllegalArgumentException(
0874                            "arrayClass must be an array");
0875                }
0876
0877                // Calculate array dimension and component type name
0878                //
0879                int n = 1;
0880                Class<?> componentType = arrayClass.getComponentType();
0881                while (componentType.isArray()) {
0882                    n++;
0883                    componentType = componentType.getComponentType();
0884                }
0885                String componentTypeName = componentType.getName();
0886
0887                // Check if the array's component type is a primitive type
0888                //
0889                if (!componentType.isPrimitive()) {
0890                    throw new IllegalArgumentException(
0891                            "component type of the array must be a primitive type");
0892                }
0893
0894                // Map component type name to corresponding SimpleType
0895                //
0896                final SimpleType<?> simpleType = getPrimitiveOpenType(componentTypeName);
0897
0898                // Build primitive array
0899                //
0900                try {
0901                    ArrayType at = new ArrayType(simpleType, true);
0902                    if (n > 1)
0903                        at = new ArrayType<T>(n - 1, at);
0904                    return at;
0905                } catch (OpenDataException e) {
0906                    throw new IllegalArgumentException(e); // should not happen
0907                }
0908            }
0909
0910            /**
0911             * Replace/resolve the object read from the stream before it is returned
0912             * to the caller.
0913             *
0914             * @serialData The new serial form of this class defines a new serializable
0915             * {@code boolean} field {@code primitiveArray}. In order to guarantee the
0916             * interoperability with previous versions of this class the new serial
0917             * form must continue to refer to primitive wrapper types even when the
0918             * {@code ArrayType} instance describes a primitive type array. So when
0919             * {@code primitiveArray} is {@code true} the {@code className},
0920             * {@code typeName} and {@code description} serializable fields
0921             * are converted into primitive types before the deserialized
0922             * {@code ArrayType} instance is return to the caller. The
0923             * {@code elementType} field always returns the {@code SimpleType}
0924             * corresponding to the primitive wrapper type of the array's
0925             * primitive type.
0926             * <p>
0927             * Therefore the following serializable fields are deserialized as follows:
0928             * <ul>
0929             *   <li>if {@code primitiveArray} is {@code true} the {@code className}
0930             *       field is deserialized by replacing the array's component primitive
0931             *       wrapper type by the corresponding array's component primitive type,
0932             *       e.g. {@code "[[Ljava.lang.Integer;"} will be deserialized as
0933             *       {@code "[[I"}.</li>
0934             *   <li>if {@code primitiveArray} is {@code true} the {@code typeName}
0935             *       field is deserialized by replacing the array's component primitive
0936             *       wrapper type by the corresponding array's component primitive type,
0937             *       e.g. {@code "[[Ljava.lang.Integer;"} will be deserialized as
0938             *       {@code "[[I"}.</li>
0939             *   <li>if {@code primitiveArray} is {@code true} the {@code description}
0940             *       field is deserialized by replacing the array's component primitive
0941             *       wrapper type by the corresponding array's component primitive type,
0942             *       e.g. {@code "2-dimension array of java.lang.Integer"} will be
0943             *       deserialized as {@code "2-dimension array of int"}.</li>
0944             * </ul>
0945             *
0946             * @since 1.6
0947             */
0948            private Object readResolve() throws ObjectStreamException {
0949                if (primitiveArray) {
0950                    return convertFromWrapperToPrimitiveTypes();
0951                } else {
0952                    return this ;
0953                }
0954            }
0955
0956            private ArrayType convertFromWrapperToPrimitiveTypes() {
0957                String cn = getClassName();
0958                String tn = getTypeName();
0959                String d = getDescription();
0960                for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
0961                    if (cn
0962                            .indexOf((String) typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]) != -1) {
0963                        cn = cn.replaceFirst(
0964                                "L" + typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]
0965                                        + ";",
0966                                (String) typeDescr[PRIMITIVE_TYPE_KEY_INDEX]);
0967                        tn = tn.replaceFirst(
0968                                "L" + typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]
0969                                        + ";",
0970                                (String) typeDescr[PRIMITIVE_TYPE_KEY_INDEX]);
0971                        d = d
0972                                .replaceFirst(
0973                                        (String) typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX],
0974                                        (String) typeDescr[PRIMITIVE_TYPE_NAME_INDEX]);
0975                        break;
0976                    }
0977                }
0978                return new ArrayType(cn, tn, d, dimension, elementType,
0979                        primitiveArray);
0980            }
0981
0982            /**
0983             * Nominate a replacement for this object in the stream before the object
0984             * is written.
0985             *
0986             * @serialData The new serial form of this class defines a new serializable
0987             * {@code boolean} field {@code primitiveArray}. In order to guarantee the
0988             * interoperability with previous versions of this class the new serial
0989             * form must continue to refer to primitive wrapper types even when the
0990             * {@code ArrayType} instance describes a primitive type array. So when
0991             * {@code primitiveArray} is {@code true} the {@code className},
0992             * {@code typeName} and {@code description} serializable fields
0993             * are converted into wrapper types before the serialized
0994             * {@code ArrayType} instance is written to the stream. The
0995             * {@code elementType} field always returns the {@code SimpleType}
0996             * corresponding to the primitive wrapper type of the array's
0997             * primitive type.
0998             * <p>
0999             * Therefore the following serializable fields are serialized as follows:
1000             * <ul>
1001             *   <li>if {@code primitiveArray} is {@code true} the {@code className}
1002             *       field is serialized by replacing the array's component primitive
1003             *       type by the corresponding array's component primitive wrapper type,
1004             *       e.g. {@code "[[I"} will be serialized as
1005             *       {@code "[[Ljava.lang.Integer;"}.</li>
1006             *   <li>if {@code primitiveArray} is {@code true} the {@code typeName}
1007             *       field is serialized by replacing the array's component primitive
1008             *       type by the corresponding array's component primitive wrapper type,
1009             *       e.g. {@code "[[I"} will be serialized as
1010             *       {@code "[[Ljava.lang.Integer;"}.</li>
1011             *   <li>if {@code primitiveArray} is {@code true} the {@code description}
1012             *       field is serialized by replacing the array's component primitive
1013             *       type by the corresponding array's component primitive wrapper type,
1014             *       e.g. {@code "2-dimension array of int"} will be serialized as
1015             *       {@code "2-dimension array of java.lang.Integer"}.</li>
1016             * </ul>
1017             *
1018             * @since 1.6
1019             */
1020            private Object writeReplace() throws ObjectStreamException {
1021                if (primitiveArray) {
1022                    return convertFromPrimitiveToWrapperTypes();
1023                } else {
1024                    return this ;
1025                }
1026            }
1027
1028            private ArrayType convertFromPrimitiveToWrapperTypes() {
1029                String cn = getClassName();
1030                String tn = getTypeName();
1031                String d = getDescription();
1032                for (Object[] typeDescr : PRIMITIVE_ARRAY_TYPES) {
1033                    if (cn
1034                            .indexOf((String) typeDescr[PRIMITIVE_TYPE_KEY_INDEX]) != -1) {
1035                        cn = cn.replaceFirst(
1036                                (String) typeDescr[PRIMITIVE_TYPE_KEY_INDEX],
1037                                "L" + typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]
1038                                        + ";");
1039                        tn = tn.replaceFirst(
1040                                (String) typeDescr[PRIMITIVE_TYPE_KEY_INDEX],
1041                                "L" + typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]
1042                                        + ";");
1043                        d = d
1044                                .replaceFirst(
1045                                        (String) typeDescr[PRIMITIVE_TYPE_NAME_INDEX],
1046                                        (String) typeDescr[PRIMITIVE_WRAPPER_NAME_INDEX]);
1047                        break;
1048                    }
1049                }
1050                return new ArrayType(cn, tn, d, dimension, elementType,
1051                        primitiveArray);
1052            }
1053        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.