001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package javax.management.openmbean;
023:
024: import java.io.Serializable;
025:
026: /**
027: * Array types.<p>
028: *
029: * @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>
030: * @version $Revision: 57200 $
031: */
032: public class ArrayType extends OpenType implements Serializable {
033: // Attributes ----------------------------------------------------
034:
035: /**
036: * The number of dimensions in the array
037: */
038: private int dimension = 0;
039:
040: /**
041: * The element type for the array
042: */
043: private OpenType elementType = null;
044:
045: /**
046: * Cached hash code
047: */
048: private transient int cachedHashCode = 0;
049:
050: /**
051: * Cached string representation
052: */
053: private transient String cachedToString = null;
054:
055: // Static --------------------------------------------------------
056:
057: private static final long serialVersionUID = 720504429830309770L;
058:
059: // Constructors --------------------------------------------------
060:
061: /**
062: * Construct an ArrayType.
063: *
064: * @param dimension the number of dimensions in the array
065: * @param elementType the open type of the array elements
066: * @exception OpenDataException when open type is an ArrayType
067: * @exception IllegalArgumentException for a null argument or
068: * non-negative dimension
069: */
070: public ArrayType(int dimension, OpenType elementType)
071: throws OpenDataException {
072: super (genName(dimension, elementType), genName(dimension,
073: elementType), genDesc(dimension, elementType));
074: this .dimension = dimension;
075: this .elementType = elementType;
076: }
077:
078: // Public --------------------------------------------------------
079:
080: /**
081: * Get the dimension of the array
082: *
083: * @return the dimension
084: */
085: public int getDimension() {
086: return dimension;
087: }
088:
089: /**
090: * Get the open type of the array elements
091: *
092: * @return the element type
093: */
094: public OpenType getElementOpenType() {
095: return elementType;
096: }
097:
098: // OpenType Overrides --------------------------------------------
099:
100: public boolean isValue(Object obj) {
101: if (obj == null)
102: return false;
103: Class clazz = obj.getClass();
104: if (clazz.isArray() == false)
105: return false;
106: if (elementType instanceof SimpleType)
107: return (getClassName().equals(clazz.getName()));
108: if (elementType instanceof TabularType
109: || elementType instanceof CompositeType) {
110: Class this Class = null;
111: try {
112: this Class = Thread.currentThread()
113: .getContextClassLoader().loadClass(
114: getClassName());
115: } catch (ClassNotFoundException e) {
116: return false;
117: }
118: if (this Class.isAssignableFrom(clazz) == false)
119: return false;
120: return recursiveCheck((Object[]) obj, dimension);
121: }
122: return false;
123: }
124:
125: // Object Overrides ----------------------------------------------
126:
127: public boolean equals(Object obj) {
128: if (this == obj)
129: return true;
130: if (obj == null || !(obj instanceof ArrayType))
131: return false;
132: ArrayType other = (ArrayType) obj;
133: return (this .getDimension() == other.getDimension() && this
134: .getElementOpenType()
135: .equals(other.getElementOpenType()));
136: }
137:
138: public int hashCode() {
139: if (cachedHashCode != 0)
140: return cachedHashCode;
141: cachedHashCode = getDimension()
142: + getElementOpenType().hashCode();
143: return cachedHashCode;
144: }
145:
146: public String toString() {
147: if (cachedToString != null)
148: return cachedToString;
149: StringBuffer buffer = new StringBuffer(ArrayType.class
150: .getName());
151: buffer.append("\n");
152: buffer.append(getTypeName());
153: buffer.append("\n");
154: buffer.append(new Integer(dimension));
155: buffer.append("-dimensional array of\n");
156: buffer.append(elementType);
157: cachedToString = buffer.toString();
158: return cachedToString;
159: }
160:
161: // Private -------------------------------------------------------
162:
163: /**
164: * Generate the class and type name<p>
165: *
166: * NOTE: The spec's javadoc is wrong, it misses the L
167: */
168: private static String genName(int dimension, OpenType elementType)
169: throws OpenDataException {
170: if (dimension < 1)
171: throw new IllegalArgumentException("negative dimension");
172: if (elementType == null)
173: throw new IllegalArgumentException("null element type");
174: if (elementType instanceof ArrayType)
175: throw new OpenDataException("array type cannot be an"
176: + " element of an array type");
177: StringBuffer buffer = new StringBuffer();
178: for (int i = 0; i < dimension; i++)
179: buffer.append('[');
180: buffer.append('L');
181: buffer.append(elementType.getClassName());
182: buffer.append(';');
183: return buffer.toString();
184: }
185:
186: /**
187: * Generate the description
188: */
189: private static String genDesc(int dimension, OpenType elementType) {
190: StringBuffer buffer = new StringBuffer();
191: buffer.append(new Integer(dimension));
192: buffer.append("-dimension array of ");
193: buffer.append(elementType.getClassName());
194: return buffer.toString();
195: }
196:
197: /**
198: * Recursively check array elements
199: */
200: private boolean recursiveCheck(Object[] elements, int dimension) {
201: // Reached the end
202: if (dimension == 1) {
203: // Check each element is the correct type
204: for (int i = 0; i < elements.length; i++)
205: if (elements[i] != null
206: && elementType.isValue(elements[i]) == false)
207: return false;
208: } else {
209: // Check the array element in this array element
210: for (int i = 0; i < elements.length; i++)
211: if (recursiveCheck((Object[]) elements[i],
212: dimension - 1) == false)
213: return false;
214: }
215: return true;
216: }
217: }
|