Frames | No Frames |
1: /* ArrayType.java -- Open type descriptor for an array. 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: package javax.management.openmbean; 39: 40: import java.lang.reflect.Array; 41: 42: import java.util.Arrays; 43: 44: /** 45: * The open type descriptor for arrays of open data values. 46: * 47: * @author Andrew John Hughes (gnu_andrew@member.fsf.org) 48: * @since 1.5 49: */ 50: public class ArrayType 51: extends OpenType 52: { 53: 54: /** 55: * Compatible with JDK 1.5 56: */ 57: private static final long serialVersionUID = 720504429830309770L; 58: 59: /** 60: * The number of dimensions arrays of this type has. 61: */ 62: private int dimension; 63: 64: /** 65: * The element type of arrays of this type. 66: */ 67: private OpenType elementType; 68: 69: /** 70: * The hash code of this instance. 71: */ 72: private transient Integer hashCode; 73: 74: /** 75: * The <code>toString()</code> result of this instance. 76: */ 77: private transient String string; 78: 79: /** 80: * Returns the class name of the array, given the element 81: * class name and its dimensions. 82: * 83: * @param className the name of the class used by the 84: * array's elements. 85: * @param dim the dimensions of the array. 86: * @return the array's class name. 87: */ 88: private static String getArrayClassName(String className, int dim) 89: { 90: char[] brackets = new char[dim]; 91: Arrays.fill(brackets, '['); 92: return String.valueOf(brackets) + "L" + className; 93: } 94: 95: /** 96: * <p> 97: * Constructs a new {@link ArrayType} instance for an array of the 98: * specified type with the supplied number of dimensions. The attributes 99: * used by the superclass, {@link OpenType}, are automatically defined, 100: * based on these values. Both the class name and type name are set 101: * to the value returned by the {@link java.lang.Class#getName()} of 102: * the array's class (i.e. the element type, preceded by n instances of 103: * '[' and an 'L', where n is the number of dimensions the array has). 104: * The description is based upon the template <code>n-dimension array 105: * of e</code>, where n is the number of dimensions of the array, and 106: * e is the element type. The class name of the actual elements is 107: * obtainable by calling {@link OpenType#getClassName()} on the result 108: * of {@link #getElementOpenType()}. 109: * </p> 110: * <p> 111: * As an example, the array type returned by 112: * <code>new ArrayType(6, SimpleType.INTEGER)</code> has the following 113: * values: 114: * </p> 115: * <table> 116: * <th><td>Attribute</td><td>Value</td></th> 117: * <tr><td>Class Name</td><td><code>[[[[[[Ljava.lang.Integer;</code> 118: * </td></tr> 119: * <tr><td>Type Name</td><td><code>[[[[[[Ljava.lang.Integer;</code> 120: * </td></tr> 121: * <tr><td>Description</td><td><code>6-dimension array of 122: * java.lang.Integer</code></td></tr> 123: * <tr><td>Element Type Class Name</td><td><code>java.lang.Integer</code> 124: * </td></tr> 125: * </table> 126: * <p> 127: * The dimensions of the array must be equal to or greater than 1. The 128: * element type must be an instance of {@link SimpleType}, 129: * {@link CompositeType} or {@link TabularType}. 130: * </p> 131: * 132: * @param dim the dimensions of the array. 133: * @param elementType the type of the elements of the array. 134: * @throws IllegalArgumentException if <code>dim</code> is less than 1. 135: * @throws OpenDataException if the element type is not an instance of either 136: * {@link SimpleType}, {@link CompositeType} 137: * or {@link TabularType}. 138: */ 139: public ArrayType(int dim, OpenType elementType) 140: throws OpenDataException 141: { 142: super(getArrayClassName(elementType.getClassName(), dim), 143: getArrayClassName(elementType.getClassName(), dim), 144: dim + "-dimension array of " + elementType.getClassName()); 145: if (dim < 1) 146: throw new IllegalArgumentException("Dimensions must be greater " + 147: "than or equal to 1."); 148: if (!(elementType instanceof SimpleType || 149: elementType instanceof CompositeType || 150: elementType instanceof TabularType)) 151: throw new OpenDataException("The element type must be a simple " + 152: "type, a composite type or a tabular " + 153: "type."); 154: dimension = dim; 155: this.elementType = elementType; 156: } 157: 158: /** 159: * <p> 160: * Compares this array type with another object 161: * for equality. The objects are judged to be equal if: 162: * </p> 163: * <ul> 164: * <li><code>obj</code> is not null.</li> 165: * <li><code>obj</code> is an instance of 166: * {@link ArrayType}.</li> 167: * <li>The dimensions are equal.</li> 168: * <li>The element types are equal.</li> 169: * </ul> 170: * 171: * @param obj the object to compare with. 172: * @return true if the conditions above hold. 173: */ 174: public boolean equals(Object obj) 175: { 176: if (!(obj instanceof ArrayType)) 177: return false; 178: ArrayType atype = (ArrayType) obj; 179: return (atype.getDimension() == dimension && 180: atype.getElementOpenType().equals(elementType)); 181: } 182: 183: /** 184: * Returns the number of dimensions used by arrays 185: * of this type. 186: * 187: * @return the number of dimensions. 188: */ 189: public int getDimension() 190: { 191: return dimension; 192: } 193: 194: /** 195: * Returns the open type descriptor which describes 196: * the type of the elements of this array type. 197: * 198: * @return the type of the elements. 199: */ 200: public OpenType getElementOpenType() 201: { 202: return elementType; 203: } 204: 205: /** 206: * <p> 207: * Returns the hash code of the array type. 208: * This is computed as the sum of the hash code of the 209: * element type together with the number of dimensions 210: * the array has. These are the same elements 211: * of the type that are compared as part of the 212: * {@link #equals(java.lang.Object)} method, thus ensuring 213: * that the hashcode is compatible with the equality 214: * test. 215: * </p> 216: * <p> 217: * As instances of this class are immutable, the hash code 218: * is computed just once for each instance and reused 219: * throughout its life. 220: * </p> 221: * 222: * @return the hash code of this instance. 223: */ 224: public int hashCode() 225: { 226: if (hashCode == null) 227: hashCode = Integer.valueOf(dimension + elementType.hashCode()); 228: return hashCode.intValue(); 229: } 230: 231: /** 232: * <p> 233: * Returns true if the specified object is a member of this 234: * array type. The object is judged to be so if it is 235: * non-null, an array and one of the following two conditions 236: * holds: 237: * </p> 238: * <ul> 239: * <li>This {@link ArrayType} instance has a {@link SimpleType} 240: * as its element type. Thus, the object must have the same 241: * class name as that returned by {@link SimpleType#getClassName()} 242: * for this class.</li> 243: * <li>This {@link ArrayType} instance has a {@link CompositeType} 244: * or a {@link TabularType} as its element type. Thus, the object 245: * must be assignable to such an array, and have elements which 246: * are either null or valid values for the element type.</li> 247: * </ul> 248: * 249: * @param obj the object to test for membership. 250: * @return true if the object is a member of this type. 251: */ 252: public boolean isValue(Object obj) 253: { 254: if (obj == null) 255: return false; 256: Class objClass = obj.getClass(); 257: if (!(objClass.isArray())) 258: return false; 259: if (elementType instanceof SimpleType) 260: return getClassName().equals(objClass.getName()); 261: Class elementClass = null; 262: try 263: { 264: elementClass = Class.forName(getClassName()); 265: } 266: catch (ClassNotFoundException e) 267: { 268: throw new IllegalStateException("The array type's element " + 269: "class could not be found.", e); 270: } 271: if (!(elementClass.isAssignableFrom(objClass))) 272: return false; 273: for (int a = 0; a < Array.getLength(obj); ++a) 274: { 275: Object elem = Array.get(obj, a); 276: if (elem != null && 277: (!(elementType.isValue(elem)))) 278: return false; 279: } 280: return true; 281: } 282: 283: /** 284: * <p> 285: * Returns a textual representation of this instance. This 286: * is constructed using the class name 287: * (<code>javax.management.openmbean.ArrayType</code>) 288: * and each element of the instance which is relevant to 289: * the definition of {@link equals(java.lang.Object)} and 290: * {@link hashCode()} (i.e. the type name, the number of 291: * dimensions and the element type). 292: * </p> 293: * <p> 294: * As instances of this class are immutable, the return value 295: * is computed just once for each instance and reused 296: * throughout its life. 297: * </p> 298: * 299: * @return a @link{java.lang.String} instance representing 300: * the instance in textual form. 301: */ 302: public String toString() 303: { 304: if (string == null) 305: string = getClass().getName() 306: + "[name=" + getTypeName() 307: + ", dimension=" + dimension 308: + ", elementType=" + elementType 309: + "]"; 310: return string; 311: } 312: 313: }