/* * @(#)CompositeDataSupport.java 3.27 04/03/24 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package javax.management.openmbean; // java import // import java.io.Serializable; import java.util.Set; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Arrays; // jmx import // /** * The CompositeDataSupport class is the open data class which implements the CompositeData interface. * * @version 3.27 04/03/24 * @author Sun Microsystems, Inc. * * @since 1.5 * @since.unbundled JMX 1.1 */ public class CompositeDataSupport implements CompositeData, Serializable { /* Serial version */ static final long serialVersionUID = 8003518976613702244L; /** * @serial Internal representation of the mapping of item names to their respective values. * A {@link SortedMap} is used for faster retrieval of elements. */ private SortedMap contents = new TreeMap(); /** * @serial The composite type of this composite data instance. */ private CompositeType compositeType; /** *
* Constructs a CompositeDataSupport instance with the specified compositeType, whose item values * are specified by itemValues[], in the same order as in itemNames[]. * As a CompositeType does not specify any order on its items, the itemNames[] parameter is used * to specify the order in which the values are given in itemValues[]. * The items contained in this CompositeDataSupport instance are internally stored in a TreeMap, * thus sorted in ascending lexicographic order of their names, for faster retrieval of individual item values. *
* The constructor checks that all the constraints listed below for each parameter are satisfied, * and throws the appropriate exception if they are not. *
* @param compositeType the composite type of this composite data instance; * must not be null. *
* @param itemNames itemNames must list, in any order, all the item names defined in compositeType; * the order in which the names are listed, is used to match values in itemValues[]; * must not be null or empty. *
* @param itemValues the values of the items, listed in the same order as their respective names in itemNames; * each item value can be null, but if it is non-null it must be * a valid value for the open type defined in compositeType for the corresponding item; * must be of the same size as itemNames; must not be null or empty. *
* @throws IllegalArgumentException compositeType is null, or itemNames[] or itemValues[] is null or empty, * or one of the elements in itemNames[] is a null or empty string, * or itemNames[] and itemValues[] are not of the same size. *
* @throws OpenDataException itemNames[] or itemValues[]'s size differs from * the number of items defined in compositeType, * or one of the elements in itemNames[] does not exist as an item name defined in compositeType, * or one of the elements in itemValues[] is not a valid value for the corresponding item * as defined in compositeType. *
*/
public CompositeDataSupport(CompositeType compositeType, String[] itemNames, Object[] itemValues)
throws OpenDataException {
// Check compositeType is not null
//
if (compositeType == null) {
throw new IllegalArgumentException("Argument compositeType cannot be null.");
}
// item names defined in compositeType:
Set namesSet = compositeType.keySet();
// Check the array itemNames is not null or empty (length!=0) and
// that there is no null element or empty string in it
//
checkForNullElement(itemNames, "itemNames");
checkForEmptyString(itemNames, "itemNames");
// Check the array itemValues is not null or empty (length!=0)
// (NOTE: we allow null values as array elements)
//
if ( (itemValues == null) || (itemValues.length == 0) ) {
throw new IllegalArgumentException("Argument itemValues[] cannot be null or empty.");
}
// Check that the sizes of the 2 arrays itemNames and itemValues are the same
//
if (itemNames.length != itemValues.length) {
throw new IllegalArgumentException("Array arguments itemNames[] and itemValues[] "+
"should be of same length (got "+ itemNames.length +
" and "+ itemValues.length +").");
}
// Check the size of the 2 arrays is equal to the number of items defined in compositeType
//
if (itemNames.length != namesSet.size()) {
throw new OpenDataException("The size of array arguments itemNames[] and itemValues[] should be equal to the number of items defined"+
" in argument compositeType (found "+ itemNames.length +" elements in itemNames[] and itemValues[],"+
" expecting "+ namesSet.size() +" elements according to compositeType.");
}
// Check parameter itemNames[] contains all names defined in the compositeType of this instance
//
if ( ! Arrays.asList(itemNames).containsAll(namesSet) ) {
throw new OpenDataException("Argument itemNames[] does not contain all names defined in the compositeType of this instance.");
}
// Check each element of itemValues[], if not null, is of the open type defined for the corresponding item
//
OpenType itemType;
for (int i=0; i
* @param compositeType the composite type of this composite data instance;
* must not be null.
*
* @param items the mappings of all the item names to their values;
* items must contain all the item names defined in compositeType;
* must not be null or empty.
*
* @throws IllegalArgumentException compositeType is null, or items is null or empty,
* or one of the keys in items is a null or empty string,
* or one of the values in items is null.
*
* @throws OpenDataException items' size differs from the number of items defined in compositeType,
* or one of the keys in items does not exist as an item name defined in compositeType,
* or one of the values in items is not a valid value for the corresponding item
* as defined in compositeType.
*
* @throws ArrayStoreException one or more keys in items is not of the class java.lang.String.
*
*/
public CompositeDataSupport(CompositeType compositeType, Map items)
throws OpenDataException {
// Let the other constructor do the job, as the call to another constructor must be the first call
//
this( compositeType,
(items==null ? null : (String[]) items.keySet().toArray(new String[items.size()])), // may raise an ArrayStoreException
(items==null ? null : items.values().toArray()) );
}
/**
*
*/
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
* Returns true if and only if all of the following statements are true:
*
* The hash code of a
* This ensures that
* However, note that another instance of a class implementing the
* The string representation consists of the name of this class (ie CompositeDataSupport
instance for equality.
*
*
* This ensures that this equals method works properly for obj parameters which are
* different implementations of the CompositeData
interface,CompositeData
interface, with the restrictions mentioned in the
* {@link java.util.Collection#equals(Object) equals}
* method of the java.util.Collection interface.
*
* @param obj the object to be compared for equality with this CompositeDataSupport
instance;
*
* @return true
if the specified object is equal to this CompositeDataSupport
instance.
*/
public boolean equals(Object obj) {
// if obj is null, return false
//
if (obj == null) {
return false;
}
// if obj is not a CompositeData, return false
//
CompositeData other;
try {
other = (CompositeData) obj;
} catch (ClassCastException e) {
return false;
}
// their compositeType should be equal
if ( ! this.getCompositeType().equals(other.getCompositeType()) ) {
return false;
}
// Currently this test returns false if we have different Array instances with same contents.
// Array objects are equals only if their references are equal, ie they are the same object!
// CompositeData equals() method need to be modified to compare Array contents...
// their content, i.e. (name, value) pairs, should be equal
Map.Entry entry;
boolean ok;
for (Iterator iter = contents.entrySet().iterator(); iter.hasNext(); ) {
entry = (Map.Entry) iter.next();
ok = ( entry.getValue() == null ?
other.get((String)entry.getKey()) == null :
entry.getValue().equals(other.get((String)entry.getKey())) );
if ( ! ok ) {
return false;
}
}
// All tests for equality were successfull
//
return true;
}
/**
* Returns the hash code value for this CompositeDataSupport
instance.
* CompositeDataSupport
instance is the sum of the hash codes
* of all elements of information used in equals
comparisons
* (ie: its composite type and all the item values).
* t1.equals(t2)
implies that t1.hashCode()==t2.hashCode()
* for any two CompositeDataSupport
instances t1
and t2
,
* as required by the general contract of the method
* {@link Object#hashCode() Object.hashCode()}.
* CompositeData
interface
* may be equal to this CompositeDataSupport
instance as defined by {@link #equals},
* but may have a different hash code if it is calculated differently.
*
* @return the hash code value for this CompositeDataSupport
instance
*/
public int hashCode() {
int result = 0;
result += compositeType.hashCode();
Map.Entry entry;
for (Iterator iter = contents.entrySet().iterator(); iter.hasNext(); ) {
entry = (Map.Entry) iter.next();
result += ( entry.getValue() == null ? 0 : entry.getValue().hashCode() );
}
return result;
}
/**
* Returns a string representation of this CompositeDataSupport
instance.
* javax.management.openmbean.CompositeDataSupport
),
* the string representation of the composite type of this instance, and the string representation of the contents
* (ie list the itemName=itemValue mappings).
*
* @return a string representation of this CompositeDataSupport
instance
*/
public String toString() {
return new StringBuffer()
.append(this.getClass().getName())
.append("(compositeType=")
.append(compositeType.toString())
.append(",contents=")
.append(contents.toString())
.append(")")
.toString();
}
}