KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > classfile > TypeDescriptor


1 /* ====================================================================
2  * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.trove.classfile;
54
55 /******************************************************************************
56  * This class is used to build field and return type descriptor strings as
57  * defined in <i>The Java Virtual Machine Specification</i>, section 4.3.2.
58  *
59  * @author Brian S O'Neill
60  * @version
61  * <!--$$Revision:--> 28 <!-- $-->, <!--$$JustDate:--> 9/07/00 <!-- $-->
62  * @see ClassFile
63  */

64 public class TypeDescriptor extends Descriptor {
65     private String JavaDoc mStr;
66     private String JavaDoc mClassName;
67     private Class JavaDoc mClass;
68     private int mDim;
69     private TypeDescriptor mComponentType;
70     private int mSpecifiedDim;
71     
72     public TypeDescriptor(String JavaDoc className) {
73         mClassName = className;
74         mStr = generate(className);
75     }
76
77     /**
78      * Used to construct any kind of type descriptor including objects and
79      * primitive types.
80      */

81     public TypeDescriptor(Class JavaDoc clazz) {
82         int dim = 0;
83
84         // Adjust dimension count.
85
while (clazz.isArray()) {
86             dim++;
87             clazz = clazz.getComponentType();
88         }
89
90         mClassName = clazz.getName();
91         mClass = clazz;
92         mDim = dim;
93
94         mStr = generate(clazz, dim);
95     }
96
97     /**
98      * Used to construct an array TypeDescriptor.
99      *
100      * @param componentType the component type
101      * @param dim the number of dimensions, which must be greater than zero.
102      *
103      * @exception IllegalArgumentException when the dimensions is not greater
104      * than zero.
105      */

106     public TypeDescriptor(TypeDescriptor componentType, int dim)
107         throws IllegalArgumentException JavaDoc {
108
109         if (dim <= 0) {
110             throw new IllegalArgumentException JavaDoc
111                 ("Array dimensions must be greater than zero: " + dim);
112         }
113
114         mClassName = componentType.getClassName();
115         mClass = componentType.getClassArg();
116         mDim = componentType.getDimensions() + dim;
117
118         if (mClass != null) {
119             mStr = generate(mClass, mDim);
120         }
121         else {
122             mStr = generate(mClassName, mDim);
123         }
124
125         mComponentType = componentType;
126         mSpecifiedDim = dim;
127     }
128
129     public String JavaDoc getClassName() {
130         return mClassName;
131     }
132
133     /**
134      * If this TypeDescriptor was constructed with a Class argument, then
135      * this method retrieves that argument. If the Class argument represented
136      * an array, the component type is returned. i.e. for
137      * <tt>TypeDescriptor(Object[][].class)</tt>, Object is returned.
138      *
139      * <p>If this TypeDescriptor was constructed with a String argument,
140      * null is returned. Call getClassName instead in this case.
141      *
142      * @return A Class that never represents an array.
143      */

144     public Class JavaDoc getClassArg() {
145         return mClass;
146     }
147
148     /**
149      * If this TypeDescriptor represents an array, the component type is
150      * returned. Otherwise, null is returned. i.e. for
151      * <tt>TypeDescriptor(Object[].class, 1)</tt>, Object[] is returned,
152      * and for <tt>TypeDescriptor(Object[].class)</tt>, Object is returned.
153      */

154     public TypeDescriptor getComponentType() {
155         if (mComponentType == null && mDim > 0) {
156             if (mClass != null) {
157                 mComponentType = new TypeDescriptor(mClass);
158             }
159             else {
160                 mComponentType = new TypeDescriptor(mClassName);
161             }
162         }
163
164         return mComponentType;
165     }
166
167     /**
168      * Returns the dimensions after being adjusted. i.e.
169      * <tt>TypeDescriptor(Object[][].class)</tt> has two dimensions and
170      * <tt>TypeDescriptor(TypeDescriptor(Object[].class), 2)</tt> has three
171      * dimensions.
172      */

173     public int getDimensions() {
174         return mDim;
175     }
176
177     /**
178      * Returns the dimensions as originally specified in the constructor. i.e.
179      * <tt>new TypeDescriptor(new TypeDescriptor(Object[].class), 2)</tt>
180      * has two specified dimensions. If no dimensions were specified, the
181      * results of getDimensions are returned.
182      */

183     public int getSpecifiedDimensions() {
184         return (mSpecifiedDim != 0) ? mSpecifiedDim : mDim;
185     }
186
187     public int hashCode() {
188         return mStr.hashCode();
189     }
190
191     public boolean equals(Object JavaDoc other) {
192         if (other instanceof TypeDescriptor) {
193             return ((TypeDescriptor)other).mStr.equals(mStr);
194         }
195         else {
196             return false;
197         }
198     }
199
200     /**
201      * Returns the TypeDescriptor code.
202      */

203     public String JavaDoc toString() {
204         return mStr;
205     }
206     
207     static String JavaDoc generate(String JavaDoc className) {
208         return generate(className, 0);
209     }
210     
211     /**
212      * Used to generate an array type descriptor.
213      */

214     static String JavaDoc generate(String JavaDoc className, int dim) {
215         StringBuffer JavaDoc desc = new StringBuffer JavaDoc(className.length() + dim + 2);
216         
217         while (dim-- > 0) {
218             desc.append('[');
219         }
220         
221         desc.append('L');
222         desc.append(className.replace('.', '/'));
223         desc.append(';');
224         
225         return desc.toString();
226     }
227     
228     /**
229      * Used to generate any kind of type descriptor including arrays and
230      * primitive types.
231      */

232     static String JavaDoc generate(Class JavaDoc clazz) {
233         return generate(clazz, 0);
234     }
235
236     static String JavaDoc generate(Class JavaDoc clazz, int dim) {
237         // Get component type and dimensions if an array.
238
while (clazz.isArray()) {
239             dim++;
240             clazz = clazz.getComponentType();
241         }
242
243         if (!clazz.isPrimitive()) {
244             return generate(clazz.getName(), dim);
245         }
246         
247         StringBuffer JavaDoc desc = new StringBuffer JavaDoc(dim + 1);
248         
249         while (dim-- > 0) {
250             desc.append('[');
251         }
252         
253         char type = 'V';
254         
255         if (clazz == int.class)
256             type = 'I';
257         else if (clazz == char.class)
258             type = 'C';
259         else if (clazz == boolean.class)
260             type = 'Z';
261         else if (clazz == double.class)
262             type = 'D';
263         else if (clazz == float.class)
264             type = 'F';
265         else if (clazz == long.class)
266             type = 'J';
267         else if (clazz == byte.class)
268             type = 'B';
269         else if (clazz == short.class)
270             type = 'S';
271         
272         desc.append(type);
273         
274         return desc.toString();
275     }
276
277     public static TypeDescriptor parseTypeDesc(String JavaDoc desc)
278         throws IllegalArgumentException JavaDoc {
279
280         TypeDescriptor td = null;
281         int cursor = 0;
282         try {
283             int dim = 0;
284             char c;
285             while ((c = desc.charAt(cursor++)) == '[') {
286                 dim++;
287             }
288
289             Class JavaDoc primitiveClass = null;
290
291             switch (c) {
292             case 'V':
293                 primitiveClass = void.class;
294                 break;
295             case 'I':
296                 primitiveClass = int.class;
297                 break;
298             case 'C':
299                 primitiveClass = char.class;
300                 break;
301             case 'Z':
302                 primitiveClass = boolean.class;
303                 break;
304             case 'D':
305                 primitiveClass = double.class;
306                 break;
307             case 'F':
308                 primitiveClass = float.class;
309                 break;
310             case 'J':
311                 primitiveClass = long.class;
312                 break;
313             case 'B':
314                 primitiveClass = byte.class;
315                 break;
316             case 'S':
317                 primitiveClass = short.class;
318                 break;
319             case 'L':
320                 StringBuffer JavaDoc name = new StringBuffer JavaDoc(desc.length());
321                 while ((c = desc.charAt(cursor++)) != ';') {
322                     if (c == '/') {
323                         c = '.';
324                     }
325                     name.append(c);
326                 }
327
328                 td = new TypeDescriptor(name.toString());
329
330                 if (dim > 0) {
331                     td = new TypeDescriptor(td, dim);
332                 }
333
334                 break;
335             }
336
337             if (primitiveClass != null) {
338                 td = new TypeDescriptor(primitiveClass);
339
340                 if (dim > 0) {
341                     td = new TypeDescriptor(td, dim);
342                 }
343             }
344         }
345         catch (NullPointerException JavaDoc e) {
346             throw new IllegalArgumentException JavaDoc("Invalid descriptor: " + desc);
347         }
348         catch (IndexOutOfBoundsException JavaDoc e) {
349             throw new IllegalArgumentException JavaDoc("Invalid descriptor: " + desc);
350         }
351
352         if (td == null || cursor != desc.length()) {
353             throw new IllegalArgumentException JavaDoc("Invalid descriptor: " + desc);
354         }
355
356         return td;
357     }
358 }
359
Popular Tags