KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)CompositeDataSupport.java 3.27 04/03/24
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 import java.util.Set JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.SortedMap JavaDoc;
18 import java.util.TreeMap JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Arrays JavaDoc;
23
24
25 // jmx import
26
//
27

28
29 /**
30  * The <tt>CompositeDataSupport</tt> class is the <i>open data</i> class which implements the <tt>CompositeData</tt> interface.
31  *
32  * @version 3.27 04/03/24
33  * @author Sun Microsystems, Inc.
34  *
35  * @since 1.5
36  * @since.unbundled JMX 1.1
37  */

38 public class CompositeDataSupport
39     implements CompositeData JavaDoc, Serializable JavaDoc {
40
41     /* Serial version */
42     static final long serialVersionUID = 8003518976613702244L;
43
44     /**
45      * @serial Internal representation of the mapping of item names to their respective values.
46      * A {@link SortedMap} is used for faster retrieval of elements.
47      */

48     private SortedMap JavaDoc contents = new TreeMap JavaDoc();
49
50     /**
51      * @serial The <i>composite type </i> of this <i>composite data</i> instance.
52      */

53     private CompositeType JavaDoc compositeType;
54     
55
56
57     /**
58      * <p>
59      * Constructs a <tt>CompositeDataSupport</tt> instance with the specified <tt>compositeType</tt>, whose item values
60      * are specified by <tt>itemValues[]</tt>, in the same order as in <tt>itemNames[]</tt>.
61      * As a <tt>CompositeType</tt> does not specify any order on its items, the <tt>itemNames[]</tt> parameter is used
62      * to specify the order in which the values are given in <tt>itemValues[]</tt>.
63      * The items contained in this <tt>CompositeDataSupport</tt> instance are internally stored in a <tt>TreeMap</tt>,
64      * thus sorted in ascending lexicographic order of their names, for faster retrieval of individual item values.
65      * <p>
66      * The constructor checks that all the constraints listed below for each parameter are satisfied,
67      * and throws the appropriate exception if they are not.
68      * <p>
69      * @param compositeType the <i>composite type </i> of this <i>composite data</i> instance;
70      * must not be null.
71      * <p>
72      * @param itemNames <tt>itemNames</tt> must list, in any order, all the item names defined in <tt>compositeType</tt>;
73      * the order in which the names are listed, is used to match values in <tt>itemValues[]</tt>;
74      * must not be null or empty.
75      * <p>
76      * @param itemValues the values of the items, listed in the same order as their respective names in <tt>itemNames</tt>;
77      * each item value can be null, but if it is non-null it must be
78      * a valid value for the open type defined in <tt>compositeType</tt> for the corresponding item;
79      * must be of the same size as <tt>itemNames</tt>; must not be null or empty.
80      * <p>
81      * @throws IllegalArgumentException <tt>compositeType</tt> is null, or <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty,
82      * or one of the elements in <tt>itemNames[]</tt> is a null or empty string,
83      * or <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
84      * <p>
85      * @throws OpenDataException <tt>itemNames[]</tt> or <tt>itemValues[]</tt>'s size differs from
86      * the number of items defined in <tt>compositeType</tt>,
87      * or one of the elements in <tt>itemNames[]</tt> does not exist as an item name defined in <tt>compositeType</tt>,
88      * or one of the elements in <tt>itemValues[]</tt> is not a valid value for the corresponding item
89      * as defined in <tt>compositeType</tt>.
90      * <p>
91      */

92     public CompositeDataSupport(CompositeType JavaDoc compositeType, String JavaDoc[] itemNames, Object JavaDoc[] itemValues)
93     throws OpenDataException JavaDoc {
94
95     // Check compositeType is not null
96
//
97
if (compositeType == null) {
98         throw new IllegalArgumentException JavaDoc("Argument compositeType cannot be null.");
99     }
100
101     // item names defined in compositeType:
102
Set JavaDoc namesSet = compositeType.keySet();
103
104     // Check the array itemNames is not null or empty (length!=0) and
105
// that there is no null element or empty string in it
106
//
107
checkForNullElement(itemNames, "itemNames");
108     checkForEmptyString(itemNames, "itemNames");
109
110     // Check the array itemValues is not null or empty (length!=0)
111
// (NOTE: we allow null values as array elements)
112
//
113
if ( (itemValues == null) || (itemValues.length == 0) ) {
114         throw new IllegalArgumentException JavaDoc("Argument itemValues[] cannot be null or empty.");
115     }
116
117     // Check that the sizes of the 2 arrays itemNames and itemValues are the same
118
//
119
if (itemNames.length != itemValues.length) {
120         throw new IllegalArgumentException JavaDoc("Array arguments itemNames[] and itemValues[] "+
121                            "should be of same length (got "+ itemNames.length +
122                            " and "+ itemValues.length +").");
123     }
124     
125     // Check the size of the 2 arrays is equal to the number of items defined in compositeType
126
//
127
if (itemNames.length != namesSet.size()) {
128         throw new OpenDataException JavaDoc("The size of array arguments itemNames[] and itemValues[] should be equal to the number of items defined"+
129                     " in argument compositeType (found "+ itemNames.length +" elements in itemNames[] and itemValues[],"+
130                     " expecting "+ namesSet.size() +" elements according to compositeType.");
131     }
132
133     // Check parameter itemNames[] contains all names defined in the compositeType of this instance
134
//
135
if ( ! Arrays.asList(itemNames).containsAll(namesSet) ) {
136         throw new OpenDataException JavaDoc("Argument itemNames[] does not contain all names defined in the compositeType of this instance.");
137     }
138     
139     // Check each element of itemValues[], if not null, is of the open type defined for the corresponding item
140
//
141
OpenType JavaDoc itemType;
142     for (int i=0; i<itemValues.length; i++) {
143         itemType = compositeType.getType(itemNames[i]);
144         if ( (itemValues[i] != null) && (! itemType.isValue(itemValues[i])) ) {
145         throw new OpenDataException JavaDoc("Argument's element itemValues["+ i +"]=\""+ itemValues[i] +"\" is not a valid value for"+
146                         " this item (itemName="+ itemNames[i] +",itemType="+ itemType +").");
147         }
148     }
149     
150     // Initialize internal fields: compositeType and contents
151
//
152
this.compositeType = compositeType;
153     for (int i=0; i<itemNames.length; i++) {
154         this.contents.put(itemNames[i], itemValues[i]);
155     }
156     }
157
158     /**
159      * <p>
160      * Constructs a <tt>CompositeDataSupport</tt> instance with the specified <tt>compositeType</tt>, whose item names and corresponding values
161      * are given by the mappings in the map <tt>items</tt>.
162      * This constructor converts the keys to a string array and the values to an object array and calls
163      * <tt>CompositeDataSupport(javax.management.openmbean.CompositeType, java.lang.String[], java.lang.Object[])</tt>.
164      * <p>
165      * @param compositeType the <i>composite type </i> of this <i>composite data</i> instance;
166      * must not be null.
167      * <p>
168      * @param items the mappings of all the item names to their values;
169      * <tt>items</tt> must contain all the item names defined in <tt>compositeType</tt>;
170      * must not be null or empty.
171      * <p>
172      * @throws IllegalArgumentException <tt>compositeType</tt> is null, or <tt>items</tt> is null or empty,
173      * or one of the keys in <tt>items</tt> is a null or empty string,
174      * or one of the values in <tt>items</tt> is null.
175      * <p>
176      * @throws OpenDataException <tt>items</tt>' size differs from the number of items defined in <tt>compositeType</tt>,
177      * or one of the keys in <tt>items</tt> does not exist as an item name defined in <tt>compositeType</tt>,
178      * or one of the values in <tt>items</tt> is not a valid value for the corresponding item
179      * as defined in <tt>compositeType</tt>.
180      * <p>
181      * @throws ArrayStoreException one or more keys in <tt>items</tt> is not of the class <tt>java.lang.String</tt>.
182      * <p>
183      */

184     public CompositeDataSupport(CompositeType JavaDoc compositeType, Map JavaDoc items)
185     throws OpenDataException JavaDoc {
186
187
188     // Let the other constructor do the job, as the call to another constructor must be the first call
189
//
190
this( compositeType,
191           (items==null ? null : (String JavaDoc[]) items.keySet().toArray(new String JavaDoc[items.size()])), // may raise an ArrayStoreException
192
(items==null ? null : items.values().toArray()) );
193     }
194
195     /**
196      *
197      */

198     private static void checkForNullElement(Object JavaDoc[] arg, String JavaDoc argName) {
199     if ( (arg == null) || (arg.length == 0) ) {
200         throw new IllegalArgumentException JavaDoc("Argument "+ argName +"[] cannot be null or empty.");
201     }
202     for (int i=0; i<arg.length; i++) {
203         if (arg[i] == null) {
204         throw new IllegalArgumentException JavaDoc("Argument's element "+ argName +"["+ i +"] cannot be null.");
205         }
206     }
207     }
208
209     /**
210      *
211      */

212     private static void checkForEmptyString(String JavaDoc[] arg, String JavaDoc argName) {
213     for (int i=0; i<arg.length; i++) {
214         if (arg[i].trim().equals("")) {
215         throw new IllegalArgumentException JavaDoc("Argument's element "+ argName +"["+ i +"] cannot be an empty string.");
216         }
217     }
218     }
219
220     /**
221      * Returns the <i>composite type </i> of this <i>composite data</i> instance.
222      */

223     public CompositeType JavaDoc getCompositeType() {
224
225     return compositeType;
226     }
227
228     /**
229      * Returns the value of the item whose name is <tt>key</tt>.
230      *
231      * @throws IllegalArgumentException if <tt>key</tt> is a null or empty String.
232      *
233      * @throws InvalidKeyException if <tt>key</tt> is not an existing item name for this <tt>CompositeData</tt> instance.
234      */

235     public Object JavaDoc get(String JavaDoc key) {
236
237     if ( (key == null) || (key.trim().equals("")) ) {
238         throw new IllegalArgumentException JavaDoc("Argument key cannot be a null or empty String.");
239     }
240     if ( ! contents.containsKey(key.trim())) {
241         throw new InvalidKeyException JavaDoc("Argument key=\""+ key.trim() +"\" is not an existing item name for this CompositeData instance.");
242     }
243     return contents.get(key.trim());
244     }
245
246     /**
247      * Returns an array of the values of the items whose names are specified by <tt>keys</tt>, in the same order as <tt>keys</tt>.
248      *
249      * @throws IllegalArgumentException if an element in <tt>keys</tt> is a null or empty String.
250      *
251      * @throws InvalidKeyException if an element in <tt>keys</tt> is not an existing item name for this <tt>CompositeData</tt> instance.
252      */

253     public Object JavaDoc[] getAll(String JavaDoc[] keys) {
254
255     if ( (keys == null) || (keys.length == 0) ) {
256         return new Object JavaDoc[0];
257     }
258     Object JavaDoc[] results = new Object JavaDoc[keys.length];
259     for (int i=0; i<keys.length; i++) {
260         results[i] = this.get(keys[i]);
261     }
262     return results;
263     }
264
265     /**
266      * Returns <tt>true</tt> if and only if this <tt>CompositeData</tt> instance contains
267      * an item whose name is <tt>key</tt>.
268      * If <tt>key</tt> is a null or empty String, this method simply returns false.
269      */

270     public boolean containsKey(String JavaDoc key) {
271
272     if ( (key == null) || (key.trim().equals("")) ) {
273         return false;
274     }
275     return contents.containsKey(key);
276     }
277
278     /**
279      * Returns <tt>true</tt> if and only if this <tt>CompositeData</tt> instance contains an item
280      * whose value is <tt>value</tt>.
281      */

282     public boolean containsValue(Object JavaDoc value) {
283
284     return contents.containsValue(value);
285     }
286
287     /**
288      * Returns an unmodifiable Collection view of the item values contained in this <tt>CompositeData</tt> instance.
289      * The returned collection's iterator will return the values in the ascending lexicographic order of the corresponding
290      * item names.
291      */

292     public Collection JavaDoc values() {
293
294     return Collections.unmodifiableCollection(contents.values());
295     }
296
297     /**
298      * Compares the specified <var>obj</var> parameter with this <code>CompositeDataSupport</code> instance for equality.
299      * <p>
300      * Returns <tt>true</tt> if and only if all of the following statements are true:
301      * <ul>
302      * <li><var>obj</var> is non null,</li>
303      * <li><var>obj</var> also implements the <code>CompositeData</code> interface,</li>
304      * <li>their composite types are equal</li>
305      * <li>their contents, i.e. (name, value) pairs are equal. </li>
306      * </ul>
307      * This ensures that this <tt>equals</tt> method works properly for <var>obj</var> parameters which are
308      * different implementations of the <code>CompositeData</code> interface, with the restrictions mentioned in the
309      * {@link java.util.Collection#equals(Object) equals}
310      * method of the <tt>java.util.Collection</tt> interface.
311      * <br>&nbsp;
312      * @param obj the object to be compared for equality with this <code>CompositeDataSupport</code> instance;
313      *
314      * @return <code>true</code> if the specified object is equal to this <code>CompositeDataSupport</code> instance.
315      */

316     public boolean equals(Object JavaDoc obj) {
317
318     // if obj is null, return false
319
//
320
if (obj == null) {
321         return false;
322     }
323
324     // if obj is not a CompositeData, return false
325
//
326
CompositeData JavaDoc other;
327     try {
328         other = (CompositeData JavaDoc) obj;
329     } catch (ClassCastException JavaDoc e) {
330         return false;
331     }
332
333     // their compositeType should be equal
334
if ( ! this.getCompositeType().equals(other.getCompositeType()) ) {
335         return false;
336     }
337     
338     
339         // Currently this test returns false if we have different Array instances with same contents.
340
// Array objects are equals only if their references are equal, ie they are the same object!
341
// CompositeData equals() method need to be modified to compare Array contents...
342

343     // their content, i.e. (name, value) pairs, should be equal
344
Map.Entry JavaDoc entry;
345     boolean ok;
346     for (Iterator JavaDoc iter = contents.entrySet().iterator(); iter.hasNext(); ) {
347         entry = (Map.Entry JavaDoc) iter.next();
348         ok = ( entry.getValue() == null ?
349            other.get((String JavaDoc)entry.getKey()) == null :
350            entry.getValue().equals(other.get((String JavaDoc)entry.getKey())) );
351         if ( ! ok ) {
352         return false;
353         }
354     }
355        
356     // All tests for equality were successfull
357
//
358
return true;
359     }
360
361     /**
362      * Returns the hash code value for this <code>CompositeDataSupport</code> instance.
363      * <p>
364      * The hash code of a <code>CompositeDataSupport</code> instance is the sum of the hash codes
365      * of all elements of information used in <code>equals</code> comparisons
366      * (ie: its <i>composite type</i> and all the item values).
367      * <p>
368      * This ensures that <code> t1.equals(t2) </code> implies that <code> t1.hashCode()==t2.hashCode() </code>
369      * for any two <code>CompositeDataSupport</code> instances <code>t1</code> and <code>t2</code>,
370      * as required by the general contract of the method
371      * {@link Object#hashCode() Object.hashCode()}.
372      * <p>
373      * However, note that another instance of a class implementing the <code>CompositeData</code> interface
374      * may be equal to this <code>CompositeDataSupport</code> instance as defined by {@link #equals},
375      * but may have a different hash code if it is calculated differently.
376      *
377      * @return the hash code value for this <code>CompositeDataSupport</code> instance
378      */

379     public int hashCode() {
380
381     int result = 0;
382     result += compositeType.hashCode();
383     Map.Entry JavaDoc entry;
384     for (Iterator JavaDoc iter = contents.entrySet().iterator(); iter.hasNext(); ) {
385         entry = (Map.Entry JavaDoc) iter.next();
386         result += ( entry.getValue() == null ? 0 : entry.getValue().hashCode() );
387     }
388     return result;
389     }
390
391     /**
392      * Returns a string representation of this <code>CompositeDataSupport</code> instance.
393      * <p>
394      * The string representation consists of the name of this class (ie <code>javax.management.openmbean.CompositeDataSupport</code>),
395      * the string representation of the composite type of this instance, and the string representation of the contents
396      * (ie list the itemName=itemValue mappings).
397      *
398      * @return a string representation of this <code>CompositeDataSupport</code> instance
399      */

400     public String JavaDoc toString() {
401
402     return new StringBuffer JavaDoc()
403         .append(this.getClass().getName())
404         .append("(compositeType=")
405         .append(compositeType.toString())
406         .append(",contents=")
407         .append(contents.toString())
408         .append(")")
409         .toString();
410     }
411
412 }
413
Popular Tags