| /* CompositeType.java -- Type descriptor for CompositeData instances. |
| Copyright (C) 2006 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| package javax.management.openmbean; |
| |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.TreeMap; |
| |
| /** |
| * The open type descriptor for instances of the |
| * {@link CompositeData} class. |
| * |
| * @author Andrew John Hughes (gnu_andrew@member.fsf.org) |
| * @since 1.5 |
| */ |
| public class CompositeType |
| extends OpenType |
| { |
| |
| /** |
| * Compatible with JDK 1.5 |
| */ |
| private static final long serialVersionUID = -5366242454346948798L; |
| |
| /** |
| * A map of item names to their descriptions. |
| */ |
| private TreeMap nameToDescription; |
| |
| /** |
| * A map of item names to their types. |
| */ |
| private TreeMap nameToType; |
| |
| /** |
| * The hash code of this instance. |
| */ |
| private transient Integer hashCode; |
| |
| /** |
| * The <code>toString()</code> result of this instance. |
| */ |
| private transient String string; |
| |
| /** |
| * <p> |
| * Constructs a new {@link CompositeType} instance for the given |
| * type name with the specified field names, descriptions and types. |
| * All parameters, and the elements of the array parameters, must be |
| * non-null and {@link java.lang.String} values must be something other |
| * than the empty string. The arrays must be non-empty, and be of |
| * equal size. |
| * </p> |
| * <p> |
| * The result of <code>CompositeData.class.getName()</code> is adopted |
| * as the class name (see {@link OpenType}) and changes to the array |
| * elements following construction of the {@link CompositeType} instance |
| * will <strong>not</strong> affect the values used by the instance. |
| * The field names are sorted in to ascending alphanumeric order internally, |
| * and so ordering can not be used to differentiate between two instances. |
| * </p> |
| * |
| * @param name the name of this composite type. |
| * @param desc a description of this composite type. |
| * @param names the names of each field within the composite type. |
| * @param descs the descriptions of each field within the composite type. |
| * @param types the types of each field within the composite type. |
| * @throws IllegalArgumentException if any validity constraint listed above |
| * is broken. |
| * @throws OpenDataException if duplicate item names are provided. Item names |
| * are case-sensitive, but whitespace is removed |
| * before comparison. |
| */ |
| public CompositeType(String name, String desc, String[] names, |
| String[] descs, OpenType[] types) |
| throws OpenDataException |
| { |
| super(CompositeData.class.getName(), name, desc); |
| if (names.length == 0 |
| || names.length != descs.length |
| || names.length != types.length) |
| throw new IllegalArgumentException("Arrays must be non-empty " + |
| "and of equal size."); |
| nameToDescription = new TreeMap(); |
| for (int a = 0; a < names.length; ++a) |
| { |
| if (names[a] == null) |
| throw new IllegalArgumentException("Name " + a + " is null."); |
| if (descs[a] == null) |
| throw new IllegalArgumentException("Description " + a + |
| " is null."); |
| String fieldName = names[a].trim(); |
| if (fieldName.length() == 0) |
| throw new IllegalArgumentException("Name " + a + " is " + |
| "the empty string."); |
| if (descs[a].length() == 0) |
| throw new IllegalArgumentException("Description " + a + " is " + |
| "the empty string."); |
| if (nameToDescription.containsKey(fieldName)) |
| throw new OpenDataException(fieldName + " appears more " + |
| "than once."); |
| nameToDescription.put(fieldName, descs[a]); |
| } |
| nameToType = new TreeMap(); |
| for (int a = 0; a < names.length; ++a) |
| nameToType.put(names[a].trim(), types[a]); |
| } |
| |
| /** |
| * Returns true if this composite data type has a field |
| * with the given name. |
| * |
| * @param name the name of the field to check for. |
| * @return true if a field of that name exists. |
| */ |
| public boolean containsKey(String name) |
| { |
| return nameToDescription.containsKey(name); |
| } |
| |
| /** |
| * <p> |
| * Compares this composite data type with another object |
| * for equality. The objects are judged to be equal if: |
| * </p> |
| * <ul> |
| * <li><code>obj</code> is not null.</li> |
| * <li><code>obj</code> is an instance of |
| * {@link CompositeType}.</li> |
| * <li>The type names are equal.</li> |
| * <li>The fields and their types match.</li> |
| * </ul> |
| * |
| * @param obj the object to compare with. |
| * @return true if the conditions above hold. |
| */ |
| public boolean equals(Object obj) |
| { |
| if (!(obj instanceof CompositeType)) |
| return false; |
| CompositeType ctype = (CompositeType) obj; |
| if (!(ctype.getTypeName().equals(getTypeName()))) |
| return false; |
| Set keys = keySet(); |
| if (!(ctype.keySet().equals(keys))) |
| return false; |
| Iterator it = keys.iterator(); |
| while (it.hasNext()) |
| { |
| String key = (String) it.next(); |
| if (!(ctype.getType(key).equals(getType(key)))) |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Returns the description for the given field name, |
| * or <code>null</code> if the field name does not |
| * exist within this composite data type. |
| * |
| * @param name the name of the field whose description |
| * should be returned. |
| * @return the description, or <code>null</code> if the |
| * field doesn't exist. |
| */ |
| public String getDescription(String name) |
| { |
| return (String) nameToDescription.get(name); |
| } |
| |
| /** |
| * Returns the type for the given field name, |
| * or <code>null</code> if the field name does not |
| * exist within this composite data type. |
| * |
| * @param name the name of the field whose type |
| * should be returned. |
| * @return the type, or <code>null</code> if the |
| * field doesn't exist. |
| */ |
| public OpenType getType(String name) |
| { |
| return (OpenType) nameToType.get(name); |
| } |
| |
| /** |
| * <p> |
| * Returns the hash code of the composite data type. |
| * This is computed as the sum of the hash codes of |
| * each field name and its type, together with the hash |
| * code of the type name. These are the same elements |
| * of the type that are compared as part of the |
| * {@link #equals(java.lang.Object)} method, thus ensuring |
| * that the hashcode is compatible with the equality |
| * test. |
| * </p> |
| * <p> |
| * As instances of this class are immutable, the hash code |
| * is computed just once for each instance and reused |
| * throughout its life. |
| * </p> |
| * |
| * @return the hash code of this instance. |
| */ |
| public int hashCode() |
| { |
| if (hashCode == null) |
| { |
| int elementTotal = 0; |
| Iterator it = nameToType.entrySet().iterator(); |
| while (it.hasNext()) |
| { |
| Map.Entry entry = (Map.Entry) it.next(); |
| elementTotal += (entry.getKey().hashCode() + |
| entry.getValue().hashCode()); |
| } |
| hashCode = Integer.valueOf(elementTotal |
| + getTypeName().hashCode()); |
| } |
| return hashCode.intValue(); |
| } |
| |
| /** |
| * Returns true if the specified object is a member of this |
| * composite type. The object is judged to be so if it is |
| * an instance of {@link CompositeData} with an equivalent |
| * type, according to the definition of |
| * {@link #equals(java.lang.Object)} for {@link CompositeType}. |
| * |
| * @param obj the object to test for membership. |
| * @return true if the object is a member of this type. |
| */ |
| public boolean isValue(Object obj) |
| { |
| if (obj instanceof CompositeData) |
| { |
| CompositeData data = (CompositeData) obj; |
| return equals(data.getCompositeType()); |
| } |
| return false; |
| } |
| |
| /** |
| * Returns an unmodifiable {@link java.util.Set}-based |
| * view of the field names that form part of this |
| * {@link CompositeType} instance. The names are stored |
| * in ascending alphanumeric order. |
| * |
| * @return a unmodifiable set containing the field |
| * name {@link java.lang.String}s. |
| */ |
| public Set keySet() |
| { |
| return Collections.unmodifiableSet(nameToDescription.keySet()); |
| } |
| |
| /** |
| * <p> |
| * Returns a textual representation of this instance. This |
| * is constructed using the class name |
| * (<code>javax.management.openmbean.CompositeType</code>) |
| * and each element of the instance which is relevant to |
| * the definition of {@link equals(java.lang.Object)} and |
| * {@link hashCode()} (i.e. the type name, and the name |
| * and type of each field). |
| * </p> |
| * <p> |
| * As instances of this class are immutable, the return value |
| * is computed just once for each instance and reused |
| * throughout its life. |
| * </p> |
| * |
| * @return a @link{java.lang.String} instance representing |
| * the instance in textual form. |
| */ |
| public String toString() |
| { |
| if (string == null) |
| string = getClass().getName() |
| + "[name=" + getTypeName() |
| + ", fields=" + nameToType |
| + "]"; |
| return string; |
| } |
| |
| } |