API Overview API Index Package Overview Direct link to this page
JDK 1.6
  javax.management.openmbean. CompositeType View Javadoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465

/*
 * @(#)CompositeType.java	3.32 06/05/03
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */


package javax.management.openmbean;


// java import
//
import java.util.Set;
import java.util.TreeMap;
import java.util.Collections;
import java.util.Iterator;

// jmx import
//


/**
 * The <code>CompositeType</code> class is the <i>open type</i> class 
 * whose instances describe the types of {@link CompositeData <code>CompositeData</code>} values.
 *
 * @version     3.32  06/05/03
 * @author      Sun Microsystems, Inc.
 *
 * @since 1.5
 * @since.unbundled JMX 1.1
 */
public class CompositeType extends OpenType<CompositeData> {

    /* Serial version */
    static final long serialVersionUID = -5366242454346948798L;

    /**
     * @serial Sorted mapping of the item names to their descriptions
     */
    private TreeMap<String,String> nameToDescription;
    
    /**
     * @serial Sorted mapping of the item names to their open types
     */
    private TreeMap<String,OpenType<?>> nameToType;	

    /* As this instance is immutable, following three values need only
     * be calculated once.  */
    private transient Integer myHashCode = null;
    private transient String  myToString = null;
    private transient Set<String> myNamesSet = null;


    /* *** Constructor *** */

    /**
     * Constructs a <code>CompositeType</code> instance, checking for the validity of the given parameters.
     * The validity constraints are described below for each parameter. 
     * <p>
     * Note that the contents of the three array parameters 
     * <var>itemNames</var>, <var>itemDescriptions</var> and <var>itemTypes</var>
     * are internally copied so that any subsequent modification of these arrays by the caller of this constructor
     * has no impact on the constructed <code>CompositeType</code> instance.
     * <p>
     * The Java class name of composite data values this composite type represents 
     * (ie the class name returned by the {@link OpenType#getClassName() getClassName} method) 
     * is set to the string value returned by <code>CompositeData.class.getName()</code>.
     * <p>
     * @param  typeName  The name given to the composite type this instance represents; cannot be a null or empty string.
     * <br>&nbsp;
     * @param  description  The human readable description of the composite type this instance represents; 
     *			    cannot be a null or empty string.
     * <br>&nbsp;
     * @param  itemNames  The names of the items contained in the 
     *			  composite data values described by this <code>CompositeType</code> instance; 
     *			  cannot be null and should contain at least one element; no element can be a null or empty string.
     *                    Note that the order in which the item names are given is not important to differentiate a
     *			  <code>CompositeType</code> instance from another;
     *			  the item names are internally stored sorted in ascending alphanumeric order.
     * <br>&nbsp;
     * @param  itemDescriptions  The descriptions, in the same order as <var>itemNames</var>, of the items contained in the 
     *			         composite data values described by this <code>CompositeType</code> instance; 
     *				 should be of the same size as <var>itemNames</var>;
     *				 no element can be a null or empty string.
     * <br>&nbsp;
     * @param  itemTypes  The open type instances, in the same order as <var>itemNames</var>, describing the items contained  
     *			  in the composite data values described by this <code>CompositeType</code> instance; 
     *			  should be of the same size as <var>itemNames</var>;
     *			  no element can be null.
     * <br>&nbsp;
     * @throws IllegalArgumentException  If <var>typeName</var> or <var>description</var> is a null or empty string,
     *					 or <var>itemNames</var> or <var>itemDescriptions</var> or <var>itemTypes</var> is null,
     *					 or any element of <var>itemNames</var> or <var>itemDescriptions</var> 
     *					 is a null or empty string,
     *					 or any element of <var>itemTypes</var> is null,
     *					 or <var>itemNames</var> or <var>itemDescriptions</var> or <var>itemTypes</var> 
     *					 are not of the same size.
     * <br>&nbsp;
     * @throws OpenDataException  If <var>itemNames</var> contains duplicate item names
     *				  (case sensitive, but leading and trailing whitespaces removed).
     */
    public CompositeType(String        typeName,
			 String        description, 
			 String[]      itemNames,
			 String[]      itemDescriptions,
			 OpenType<?>[] itemTypes) throws OpenDataException {

	// Check and construct state defined by parent
	//
	super(CompositeData.class.getName(), typeName, description, false);

	// Check the 3 arrays are not null or empty (ie length==0) and that there is no null element or empty string in them
	//
	checkForNullElement(itemNames, "itemNames");
	checkForNullElement(itemDescriptions, "itemDescriptions");
	checkForNullElement(itemTypes, "itemTypes");
	checkForEmptyString(itemNames, "itemNames");
	checkForEmptyString(itemDescriptions, "itemDescriptions");

	// Check the sizes of the 3 arrays are the same
	//
	if ( (itemNames.length != itemDescriptions.length) || (itemNames.length != itemTypes.length) ) {
	    throw new IllegalArgumentException("Array arguments itemNames[], itemDescriptions[] and itemTypes[] "+
					       "should be of same length (got "+ itemNames.length +", "+ 
					       itemDescriptions.length +" and "+ itemTypes.length +").");
	}
	
	// Initialize internal "names to descriptions" and "names to types" sorted maps,
	// and, by doing so, check there are no duplicate item names
	//
	nameToDescription = new TreeMap<String,String>();
	nameToType        = new TreeMap<String,OpenType<?>>();
	String key;
	for (int i=0; i<itemNames.length; i++) {
	    key = itemNames[i].trim();
	    if (nameToDescription.containsKey(key)) {
		throw new OpenDataException("Argument's element itemNames["+ i +"]=\""+ itemNames[i] +
					    "\" duplicates a previous item names.");
	    }	
	    nameToDescription.put(key, itemDescriptions[i].trim());
	    nameToType.put(key, itemTypes[i]);
	}
    }

    private static void checkForNullElement(Object[] arg, String argName) {
	if ( (arg == null) || (arg.length == 0) ) {
	    throw new IllegalArgumentException("Argument "+ argName +"[] cannot be null or empty.");
	}
	for (int i=0; i<arg.length; i++) {
	    if (arg[i] == null) {
		throw new IllegalArgumentException("Argument's element "+ argName +"["+ i +"] cannot be null.");
	    }
	}
    }

    private static void checkForEmptyString(String[] arg, String argName) {
	for (int i=0; i<arg.length; i++) {
	    if (arg[i].trim().equals("")) {
		throw new IllegalArgumentException("Argument's element "+ argName +"["+ i +"] cannot be an empty string.");
	    }
	}
    }

    /* *** Composite type specific information methods *** */

    /**
     * Returns <code>true</code> if this <code>CompositeType</code> instance defines an item
     * whose name is <var>itemName</var>.
     *
     * @param itemName the name of the item.
     *
     * @return true if an item of this name is present.
     */
    public boolean containsKey(String itemName) {

	if (itemName == null) {
	    return false;
	}
	return nameToDescription.containsKey(itemName);
    }

    /**
     * Returns the description of the item whose name is <var>itemName</var>, 
     * or <code>null</code> if this <code>CompositeType</code> instance does not define any item
     * whose name is <var>itemName</var>.
     *
     * @param itemName the name of the item.
     *
     * @return the description.
     */
    public String getDescription(String itemName) {

	if (itemName == null) {
	    return null;
	}
	return (String) nameToDescription.get(itemName);
    }

    /**
     * Returns the <i>open type</i> of the item whose name is <var>itemName</var>, 
     * or <code>null</code> if this <code>CompositeType</code> instance does not define any item
     * whose name is <var>itemName</var>.
     *
     * @param itemName the name of the time.
     *
     * @return the type.
     */
    public OpenType<?> getType(String itemName) {

	if (itemName == null) {
	    return null;
	}
	return (OpenType<?>) nameToType.get(itemName);
    }

    /**
     * Returns an unmodifiable Set view of all the item names defined by this <code>CompositeType</code> instance.
     * The set's iterator will return the item names in ascending order. 
     *
     * @return a {@link Set} of {@link String}.
     */
    public Set<String> keySet() {

	// Initializes myNamesSet on first call
	if (myNamesSet == null) {
	    myNamesSet = Collections.unmodifiableSet(nameToDescription.keySet());
	}

	return myNamesSet; // always return the same value
    }


    /**
     * Tests whether <var>obj</var> is a value which could be
     * described by this <code>CompositeType</code> instance.
     *
     * <p>If <var>obj</var> is null or is not an instance of
     * <code>javax.management.openmbean.CompositeData</code>,
     * <code>isValue</code> returns <code>false</code>.</p>
     *
     * <p>If <var>obj</var> is an instance of
     * <code>javax.management.openmbean.CompositeData</code>, then let
     * {@code ct} be its {@code CompositeType} as returned by {@link
     * CompositeData#getCompositeType()}.  The result is true if
     * {@code this} is <em>assignable from</em> {@code ct}.  This
     * means that:</p>
     *
     * <ul>
     * <li>{@link #getTypeName() this.getTypeName()} equals
     * {@code ct.getTypeName()}, and
     * <li>there are no item names present in {@code this} that are
     * not also present in {@code ct}, and
     * <li>for every item in {@code this}, its type is assignable from
     * the type of the corresponding item in {@code ct}.
     * </ul>
     *
     * <p>A {@code TabularType} is assignable from another {@code
     * TabularType} if they have the same {@linkplain
     * TabularType#getTypeName() typeName} and {@linkplain
     * TabularType#getIndexNames() index name list}, and the
     * {@linkplain TabularType#getRowType() row type} of the first is
     * assignable from the row type of the second.
     *
     * <p>An {@code ArrayType} is assignable from another {@code
     * ArrayType} if they have the same {@linkplain
     * ArrayType#getDimension() dimension}; and both are {@linkplain
     * ArrayType#isPrimitiveArray() primitive arrays} or neither is;
     * and the {@linkplain ArrayType#getElementOpenType() element
     * type} of the first is assignable from the element type of the
     * second.
     *
     * <p>In every other case, an {@code OpenType} is assignable from
     * another {@code OpenType} only if they are equal.</p>
     *
     * <p>These rules mean that extra items can be added to a {@code
     * CompositeData} without making it invalid for a {@code CompositeType}
     * that does not have those items.</p>
     *
     * @param  obj  the value whose open type is to be tested for compatibility
     * with this <code>CompositeType</code> instance.
     *
     * @return <code>true</code> if <var>obj</var> is a value for this
     * composite type, <code>false</code> otherwise.
     */
    public boolean isValue(Object obj) {

	// if obj is null or not CompositeData, return false
	//
	if (!(obj instanceof CompositeData)) {
	    return false;
	}

	// if obj is not a CompositeData, return false
	//
	CompositeData value = (CompositeData) obj;

	// test value's CompositeType is assignable to this CompositeType instance
	//
	CompositeType valueType = value.getCompositeType();
        return this.isAssignableFrom(valueType);
    }
    
    /**
     * Tests whether values of the given type can be assigned to this
     * open type.  The result is true if the given type is also a
     * CompositeType with the same name ({@link #getTypeName()}), and
     * every item in this type is also present in the given type with
     * the same name and assignable type.  There can be additional
     * items in the given type, which are ignored.
     *
     * @param ot the type to be tested.
     *
     * @return true if {@code ot} is assignable to this open type.
     */
@Override
    boolean isAssignableFrom(OpenType ot) {
        if (!(ot instanceof CompositeType))
            return false;
        CompositeType ct = (CompositeType) ot;
        if (!ct.getTypeName().equals(getTypeName()))
            return false;
        for (String key : keySet()) {
            OpenType<?> otItemType = ct.getType(key);
            OpenType<?> thisItemType = getType(key);
            if (otItemType == null ||
                    !thisItemType.isAssignableFrom(otItemType))
                return false;
        }
        return true;
    }


    /* *** Methods overriden from class Object *** */

    /**
     * Compares the specified <code>obj</code> parameter with this <code>CompositeType</code> instance for equality. 
     * <p>
     * Two <code>CompositeType</code> instances are equal if and only if all of the following statements are true:
     * <ul>
     * <li>their type names are equal</li>
     * <li>their items' names and types are equal</li>
     * </ul>
     * <br>&nbsp;
     * @param  obj  the object to be compared for equality with this <code>CompositeType</code> instance;
     *		    if <var>obj</var> is <code>null</code>, <code>equals</code> returns <code>false</code>.
     * 
     * @return  <code>true</code> if the specified object is equal to this <code>CompositeType</code> instance.
     */
    public boolean equals(Object obj) {

	// if obj is null, return false
	//
	if (obj == null) {
	    return false;
	}

	// if obj is not a CompositeType, return false
	//
	CompositeType other;
	try {
	    other = (CompositeType) obj;
	} catch (ClassCastException e) {
	    return false;
	}

	// Now, really test for equality between this CompositeType instance and the other
	//
	
	// their names should be equal
	if ( ! this.getTypeName().equals(other.getTypeName()) ) {
	    return false;
	}

	// their items names and types should be equal
	if ( ! this.nameToType.equals(other.nameToType) ) {
	    return false;
	}

	// All tests for equality were successfull
	//
	return true;
    }

    /**
     * Returns the hash code value for this <code>CompositeType</code> instance. 
     * <p>
     * The hash code of a <code>CompositeType</code> instance is the sum of the hash codes
     * of all elements of information used in <code>equals</code> comparisons 
     * (ie: name, items names, items types). 
     * This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code> 
     * for any two <code>CompositeType</code> instances <code>t1</code> and <code>t2</code>, 
     * as required by the general contract of the method
     * {@link Object#hashCode() Object.hashCode()}.
     * <p>
     * As <code>CompositeType</code> instances are immutable, the hash code for this instance is calculated once,
     * on the first call to <code>hashCode</code>, and then the same value is returned for subsequent calls.
     *
     * @return  the hash code value for this <code>CompositeType</code> instance
     */
    public int hashCode() {

	// Calculate the hash code value if it has not yet been done (ie 1st call to hashCode())
	//
	if (myHashCode == null) {
	    int value = 0;
	    value += this.getTypeName().hashCode();
	    String key;
	    for (Iterator k = nameToDescription.keySet().iterator(); k.hasNext();  ) {
		key = (String) k.next();
		value += key.hashCode();
		value += this.nameToType.get(key).hashCode();
	    }
	    myHashCode = new Integer(value);
	}
	
	// return always the same hash code for this instance (immutable)
	//
	return myHashCode.intValue();
    }

    /**
     * Returns a string representation of this <code>CompositeType</code> instance. 
     * <p>
     * The string representation consists of 
     * the name of this class (ie <code>javax.management.openmbean.CompositeType</code>), the type name for this instance, 
     * and the list of the items names and types string representation of this instance.
     * <p>
     * As <code>CompositeType</code> instances are immutable, the string representation for this instance is calculated once,
     * on the first call to <code>toString</code>, and then the same value is returned for subsequent calls.
     * 
     * @return  a string representation of this <code>CompositeType</code> instance
     */
    public String toString() {

	// Calculate the string representation if it has not yet been done (ie 1st call to toString())
	//
	if (myToString == null) {
	    StringBuffer result = new StringBuffer();
	    result.append(this.getClass().getName());
	    result.append("(name=");
	    result.append(getTypeName());
	    result.append(",items=(");
	    int i=0; 
	    Iterator k=nameToType.keySet().iterator();
	    String key;
	    while (k.hasNext()) {
		key = (String) k.next();
		if (i > 0) result.append(",");
		result.append("(itemName=");
		result.append(key);
		result.append(",itemType=");
		result.append(nameToType.get(key).toString() +")");
		i++;
	    }
	    result.append("))");
	    myToString = result.toString();
	}

	// return always the same string representation for this instance (immutable)
	//
	return myToString;
    }

}

Generated By: JavaOnTracks Doclet 0.1.4     ©Thibaut Colar