KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > openmbean > ArrayType


1 /*
2  * @(#)ArrayType.java 3.24 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8
9 package javax.management.openmbean;
10
11
12 // java import
13
//
14
import java.io.Serializable JavaDoc;
15
16 // jmx import
17
//
18

19
20 /**
21  * The <code>ArrayType</code> class is the <i>open type</i> class whose instances describe
22  * all <i>open data</i> values which are n-dimensional arrays of <i>open data</i> values.
23  *
24  * @version 3.24 03/12/19
25  * @author Sun Microsystems, Inc.
26  *
27  * @since 1.5
28  * @since.unbundled JMX 1.1
29  */

30 public class ArrayType
31     extends OpenType JavaDoc
32     implements Serializable JavaDoc {
33
34     /* Serial version */
35     static final long serialVersionUID = 720504429830309770L;
36     
37     /**
38      * @serial The dimension of arrays described by this {@link ArrayType} instance
39      */

40     private int dimension;
41     
42     /**
43      * @serial The <i>open type</i> of element values contained in the arrays described by
44      * this {@link ArrayType} instance
45      */

46     private OpenType JavaDoc elementType;
47
48     private transient Integer JavaDoc myHashCode = null; // As this instance is immutable, these two values
49
private transient String JavaDoc myToString = null; // need only be calculated once.
50

51
52     /* *** Constructor *** */
53
54     /**
55      * Constructs an <tt>ArrayType</tt> instance describing <i>open data</i> values which are
56      * arrays with dimension <var>dimension</var> of elements whose <i>open type</i> is <var>elementType</var>.
57      * <p>
58      * When invoked on an <tt>ArrayType</tt> instance, the {@link OpenType#getClassName() getClassName} method
59      * returns the class name of the array instances it describes (following the rules defined by the
60      * {@link Class#getName() getName} method of <code>java.lang.Class</code>), not the class name of the array elements
61      * (which is returned by a call to <tt>getElementOpenType().getClassName()</tt>).
62      * <p>
63      * The internal field corresponding to the type name of this <code>ArrayType</code> instance is also set to
64      * the class name of the array instances it describes.
65      * In other words, the methods <code>getClassName</code> and <code>getTypeName</code> return the same string value.
66      * The internal field corresponding to the description of this <code>ArrayType</code> instance is set to a string value
67      * which follows the following template:<br>
68      * <tt><i>&lt;dimension&gt;</i>-dimension array of <i>&lt;element_class_name&gt;</i></tt>
69      * <p>
70      * As an example, the following piece of code:
71      * <pre>
72      * ArrayType t = new ArrayType(3, SimpleType.STRING);
73      * System.out.println("array class name = "+ t.getClassName());
74      * System.out.println("element class name = "+ t.getElementOpenType().getClassName());
75      * System.out.println("array type name = "+ t.getTypeName());
76      * System.out.println("array type description = "+ t.getDescription());
77      * </pre>
78      * would produce the following output:
79      * <pre>
80      * array class name = [[[java.lang.String;
81      * element class name = java.lang.String
82      * array type name = [[[java.lang.String;
83      * array type description = 3-dimension array of java.lang.String
84      * </pre>
85      *
86      * @param dimension the dimension of arrays described by this <tt>ArrayType</tt> instance;
87      * must be greater than or equal to 1.
88      *
89      * @param elementType the <i>open type</i> of element values contained in the arrays described by
90      * this <tt>ArrayType</tt> instance; must be an instance of either
91      * <tt>SimpleType</tt>, <tt>CompositeType</tt> or <tt>TabularType</tt>.
92      *
93      * @throws IllegalArgumentException if <var>dimension</var> is not a positive integer
94      *
95      * @throws OpenDataException if <var>elementType</var> is an instance of <tt>ArrayType</tt>
96      */

97     public ArrayType(int dimension,
98              OpenType JavaDoc elementType) throws OpenDataException JavaDoc {
99     
100     // Check and construct state defined by parent.
101
//
102
super(buildArrayClassName(dimension, elementType.getClassName()),
103           buildArrayClassName(dimension, elementType.getClassName()),
104           String.valueOf(dimension) +"-dimension array of "+ elementType.getClassName());
105     
106     // Check and construct state specific to ArrayType
107
//
108
this.dimension = dimension; // already checked >=1 in buildArrayClassName
109
this.elementType = elementType; // cannot be ArrayType: super() would throw exception on the built classname
110
}
111
112     /**
113      *
114      */

115     private static String JavaDoc buildArrayClassName(int dimension, String JavaDoc elementClassName) throws OpenDataException JavaDoc {
116
117     if (dimension < 1) {
118         throw new IllegalArgumentException JavaDoc("Value of argument dimension must be greater than 0");
119     }
120
121     StringBuffer JavaDoc result = new StringBuffer JavaDoc();
122
123     for (int i=1; i<dimension; i++) { // add (dimension - 1) '[' characters
124
result.append('[');
125     }
126     result.append("[L");
127     result.append(elementClassName);
128     result.append(';');
129
130     return result.toString();
131     }
132
133
134     /* *** ArrayType specific information methods *** */
135
136     /**
137      * Returns the dimension of arrays described by this <tt>ArrayType</tt> instance.
138      *
139      * @return the dimension.
140      */

141     public int getDimension() {
142
143     return dimension;
144     }
145
146     /**
147      * Returns the <i>open type</i> of element values contained in the arrays described by this <tt>ArrayType</tt> instance.
148      *
149      * @return the element type.
150      */

151     public OpenType JavaDoc getElementOpenType() {
152
153     return elementType;
154     }
155
156     /**
157      * Tests whether <var>obj</var> is a value for this <code>ArrayType</code> instance.
158      * <p>
159      * This method returns <code>true</code> if and only if <var>obj</var> is not null, <var>obj</var> is an array
160      * and any one of the following is <tt>true</tt>:
161      * <p><ul>
162      * <li>if this <code>ArrayType</code> instance describes an array of <tt>SimpleType</tt> elements,
163      * <var>obj</var>'s class name is the same as the className field defined for this <code>ArrayType</code> instance
164      * (ie the class name returned by the {@link OpenType#getClassName() getClassName} method,
165      * which includes the dimension information),<br>&nbsp;
166      * </li>
167      * <li>if this <code>ArrayType</code> instance describes an array
168      * of classes implementing the TabularData interface or the CompositeData interface,
169      * <var>obj</var> is assignable to such a declared array,
170      * and each element contained in <var>obj</var> is either null or a valid value for the element's open type
171      * specified by this <code>ArrayType</code> instance.
172      * </li></ul>
173      * <p>
174      *
175      * @param obj the object to be tested.
176      *
177      * @return <code>true</code> if <var>obj</var> is a value for this <code>ArrayType</code> instance.
178      */

179     public boolean isValue(Object JavaDoc obj) {
180
181     // if obj is null, return false
182
//
183
if (obj == null) {
184         return false;
185     }
186
187     Class JavaDoc objClass = obj.getClass();
188     String JavaDoc objClassName = objClass.getName();
189
190     // if obj is not an array, return false
191
//
192
if ( ! objClass.isArray() ) {
193         return false;
194     }
195
196     // Test if obj's class name is the same as for the array values that this instance describes
197
// (this is fine if elements are of simple types, which are final classes)
198
//
199
if ( this.getClassName().equals(objClassName) ) {
200         return true;
201     }
202
203     // In case this ArrayType instance describes an array of classes implementing the TabularData or CompositeData interface,
204
// we first check for the assignability of obj to such an array of TabularData or CompositeData,
205
// which ensures that:
206
// . obj is of the the same dimension as this ArrayType instance,
207
// . it is declared as an array of elements which are either all TabularData or all CompositeData.
208
//
209
// If the assignment check is positive,
210
// then we have to check that each element in obj is of the same TabularType or CompositeType
211
// as the one described by this ArrayType instance.
212
//
213
// [About assignment check, note that the call below returns true: ]
214
// [Class.forName("[Lpackage.CompositeData;").isAssignableFrom(Class.forName("[Lpackage.CompositeDataImpl;)")); ]
215
//
216
if ( (this.elementType.getClassName().equals(TabularData JavaDoc.class.getName())) ||
217          (this.elementType.getClassName().equals(CompositeData JavaDoc.class.getName())) ) {
218
219         /* this.getClassName() is
220          * "[Ljavax.management.openmbean.TabularData;" or the same
221          * thing for CompositeData, either one optionally preceded
222          * by n '[' characters. So the class is necessarily known
223          * to the ClassLoader of ArrayType, and Class.forName is
224          * safe. */

225         Class JavaDoc targetClass;
226         try {
227         targetClass = Class.forName(this.getClassName());
228         } catch (ClassNotFoundException JavaDoc e) { // should not happen
229
return false;
230         }
231         // assignment check: return false if negative
232
if ( ! targetClass.isAssignableFrom(objClass) ) {
233         return false;
234         }
235
236         // check that all elements in obj are valid values for this ArrayType
237
if ( ! checkElementsType( (Object JavaDoc[]) obj, this.dimension) ) { // we know obj's dimension is this.dimension
238
return false;
239         }
240
241         return true;
242     }
243
244     // if previous tests did not return, then obj is not a value for this ArrayType instance
245
return false;
246     }
247
248     /**
249      * Returns true if and only if all elements contained in the array argument x_dim_Array of dimension dim
250      * are valid values (ie either null or of the right openType)
251      * for the element open type specified by this ArrayType instance.
252      *
253      * This method's implementation uses recursion to go down the dimensions of the array argument.
254      */

255     private boolean checkElementsType(Object JavaDoc[] x_dim_Array, int dim) {
256
257     // if the elements of x_dim_Array are themselves array: go down recursively....
258
if ( dim > 1 ) {
259         for (int i=0; i<x_dim_Array.length; i++) {
260         if ( ! checkElementsType((Object JavaDoc[])x_dim_Array[i], dim-1) ) {
261             return false;
262         }
263         }
264         return true;
265     }
266     // ...else, for a non-empty array, each element must be a valid value: either null or of the right openType
267
else {
268         for (int i=0; i<x_dim_Array.length; i++) {
269         if ( (x_dim_Array[i] != null) && (! this.getElementOpenType().isValue(x_dim_Array[i])) ) {
270             return false;
271         }
272         }
273         return true;
274     }
275     }
276
277
278
279     /* *** Methods overriden from class Object *** */
280
281     /**
282      * Compares the specified <code>obj</code> parameter with this <code>ArrayType</code> instance for equality.
283      * <p>
284      * Two <code>ArrayType</code> instances are equal if and only if they describes array instances
285      * which have the same dimension and elements' open type.
286      *
287      * @param obj the object to be compared for equality with this <code>ArrayType</code> instance;
288      * if <var>obj</var> is <code>null</code> or is not an instance of the class <code>ArrayType</code>,
289      * <code>equals</code> returns <code>false</code>.
290      *
291      * @return <code>true</code> if the specified object is equal to this <code>ArrayType</code> instance.
292      */

293     public boolean equals(Object JavaDoc obj) {
294
295     // if obj is null, return false
296
//
297
if (obj == null) {
298         return false;
299     }
300
301     // if obj is not an ArrayType, return false
302
//
303
ArrayType JavaDoc other;
304     try {
305         other = (ArrayType JavaDoc) obj;
306     } catch (ClassCastException JavaDoc e) {
307         return false;
308     }
309
310     // if other's dimension is different than this instance's, return false
311
//
312
if (other.dimension != this.dimension) {
313         return false;
314     }
315
316     // Test if other's elementType field is the same as for this instance
317
//
318
return this.elementType.equals(other.elementType);
319     }
320
321     /**
322      * Returns the hash code value for this <code>ArrayType</code> instance.
323      * <p>
324      * The hash code of a <code>ArrayType</code> instance is the sum of the hash codes
325      * of all elements of information used in <code>equals</code> comparisons
326      * (ie: dimension and elements' type).
327      * This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
328      * for any two <code>ArrayType</code> instances <code>t1</code> and <code>t2</code>,
329      * as required by the general contract of the method
330      * {@link Object#hashCode() Object.hashCode()}.
331      * <p>
332      * As <code>ArrayType</code> instances are immutable, the hash code for this instance is calculated once,
333      * on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
334      *
335      * @return the hash code value for this <code>ArrayType</code> instance
336      */

337     public int hashCode() {
338
339     // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
340
//
341
if (myHashCode == null) {
342         int value = 0;
343         value += this.dimension;
344         value += this.elementType.hashCode();
345         myHashCode = new Integer JavaDoc(value);
346     }
347     
348     // return always the same hash code for this instance (immutable)
349
//
350
return myHashCode.intValue();
351     }
352
353     /**
354      * Returns a string representation of this <code>ArrayType</code> instance.
355      * <p>
356      * The string representation consists of
357      * the name of this class (ie <code>javax.management.openmbean.ArrayType</code>), the type name,
358      * the dimension and elements' type defined for this instance,
359      * <p>
360      * As <code>ArrayType</code> instances are immutable, the string representation for this instance is calculated once,
361      * on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
362      *
363      * @return a string representation of this <code>ArrayType</code> instance
364      */

365     public String JavaDoc toString() {
366
367     // Calculate the string representation if it has not yet been done (ie 1st call to toString())
368
//
369
if (myToString == null) {
370         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
371         result.append(this.getClass().getName());
372         result.append("(name=");
373         result.append(getTypeName());
374         result.append(",dimension=");
375         result.append(String.valueOf(this.dimension));
376         result.append(",elementType=");
377         result.append(this.elementType.toString());
378         result.append(")");
379         myToString = result.toString();
380     }
381
382     // return always the same string representation for this instance (immutable)
383
//
384
return myToString;
385     }
386
387 }
388
Popular Tags