KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > binding > model > ClassUtils


1 /*
2 Copyright (c) 2004-2005, Dennis M. Sosnoski
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.binding.model;
30
31 import java.util.HashMap JavaDoc;
32
33 /**
34  * Interface for field or method information. Provides the information needed
35  * for access to the item.
36  *
37  * @author Dennis M. Sosnoski
38  * @version 1.0
39  */

40
41 public class ClassUtils
42 {
43     /** Map for primitive type signature variants. */
44     private static HashMap JavaDoc s_variantMap = new HashMap JavaDoc();
45     
46     /** Map for signatures corresponding to class names. */
47     private static HashMap JavaDoc s_signatureMap = new HashMap JavaDoc();
48     
49     static {
50         
51         // initialize primitive type variants
52
s_variantMap.put("boolean", new String JavaDoc[] { "Z" });
53         s_variantMap.put("byte", new String JavaDoc[] { "B", "S", "I" });
54         s_variantMap.put("char", new String JavaDoc[] { "C", "I" });
55         s_variantMap.put("double", new String JavaDoc[] { "D" });
56         s_variantMap.put("float", new String JavaDoc[] { "F" });
57         s_variantMap.put("int", new String JavaDoc[] { "I" });
58         s_variantMap.put("long", new String JavaDoc[] { "J" });
59         s_variantMap.put("short", new String JavaDoc[] { "S", "I" });
60         s_variantMap.put("void", new String JavaDoc[] { "V" });
61         
62         // initialize signatures for primitive types
63
s_signatureMap.put("boolean", "Z");
64         s_signatureMap.put("byte", "B");
65         s_signatureMap.put("char", "C");
66         s_signatureMap.put("double", "D");
67         s_signatureMap.put("float", "F");
68         s_signatureMap.put("int", "I");
69         s_signatureMap.put("long", "J");
70         s_signatureMap.put("short", "S");
71         s_signatureMap.put("void", "V");
72     }
73
74     /**
75      * Check if type name is a primitive.
76      *
77      * @return <code>true</code> if a primitive, <code>false</code> if not
78      */

79     public static boolean isPrimitive(String JavaDoc type) {
80         return s_variantMap.get(type) != null;
81     }
82     
83     /**
84      * Get virtual method by fully qualified name. This splits the class
85      * name from the method name, finds the class, and then tries to find a
86      * matching method name in that class or a superclass.
87      *
88      * @param name fully qualified class and method name
89      * @param sigs possible method signatures
90      * @param vctx validation context (used for class lookup)
91      * @return information for the method, or <code>null</code> if not found
92      */

93     public static IClassItem findVirtualMethod(String JavaDoc name, String JavaDoc[] sigs,
94         ValidationContext vctx) {
95         
96         // get the class containing the method
97
int split = name.lastIndexOf('.');
98         String JavaDoc cname = name.substring(0, split);
99         String JavaDoc mname = name.substring(split+1);
100         IClass iclas = vctx.getRequiredClassInfo(cname);
101         
102         // find the method in class or superclass
103
for (int i = 0; i < sigs.length; i++) {
104             IClassItem method = iclas.getMethod(mname, sigs[i]);
105             if (method != null) {
106                 return method;
107             }
108         }
109         return null;
110     }
111     
112     /**
113      * Get static method by fully qualified name. This splits the class
114      * name from the method name, finds the class, and then tries to find a
115      * matching method name in that class.
116      *
117      * @param name fully qualified class and method name
118      * @param sigs possible method signatures
119      * @param vctx validation context (used for class lookup)
120      * @return information for the method, or <code>null</code> if not found
121      */

122     public static IClassItem findStaticMethod(String JavaDoc name, String JavaDoc[] sigs,
123         ValidationContext vctx) {
124         
125         // get the class containing the method
126
int split = name.lastIndexOf('.');
127         String JavaDoc cname = name.substring(0, split);
128         String JavaDoc mname = name.substring(split+1);
129         IClass iclas = vctx.getRequiredClassInfo(cname);
130         
131         // find the method in class or superclass
132
for (int i = 0; i < sigs.length; i++) {
133             IClassItem method = iclas.getStaticMethod(mname, sigs[i]);
134             if (method != null) {
135                 return method;
136             }
137         }
138         return null;
139     }
140     
141     /**
142      * Get all variant signatures for a fully qualified class name. The
143      * returned array gives all signatures (for interfaces or classes) which
144      * instances of the class can match.
145      *
146      * @param name fully qualified class name
147      * @param vctx validation context (used for class lookup)
148      * @return possible signature variations for instances of the class
149      */

150     public static String JavaDoc[] getSignatureVariants(String JavaDoc name,
151         ValidationContext vctx) {
152         Object JavaDoc obj = s_variantMap.get(name);
153         if (obj == null) {
154             IClass iclas = vctx.getRequiredClassInfo(name);
155             return iclas.getInstanceSigs();
156         } else {
157             return (String JavaDoc[])obj;
158         }
159     }
160     
161     /**
162      * Gets the signature string corresponding to a type. The base for the type
163      * may be a primitive or class name, and may include trailing array
164      * brackets.
165      *
166      * @param type type name
167      * @return signature string for type
168      */

169     public static String JavaDoc getSignature(String JavaDoc type) {
170         
171         //. check if already built signature for this type
172
String JavaDoc sig = (String JavaDoc)s_signatureMap.get(type);
173         if (sig == null) {
174             
175             // check if this is an array type
176
int dim = 0;
177             int split = type.indexOf('[');
178             if (split >= 0) {
179                 
180                 // count pairs of array brackets
181
int mark = split;
182                 while ((type.length()-mark) >= 2) {
183                     if (type.charAt(mark) == '[' ||
184                         type.charAt(mark+1) == ']') {
185                         dim++;
186                         mark += 2;
187                     } else {
188                         throw new IllegalArgumentException JavaDoc
189                             ("Invalid type name " + type);
190                     }
191                 }
192                 
193                 // make sure only bracket pairs at end
194
if (mark < type.length()) {
195                     throw new IllegalArgumentException JavaDoc("Invalid type name " +
196                         type);
197                 }
198                 
199                 // see if signature for base object type needs to be added
200
String JavaDoc cname = type.substring(0, split);
201                 String JavaDoc base = (String JavaDoc)s_signatureMap.get(cname);
202                 if (base == null) {
203                     
204                     // add base type signature to map
205
base = "L" + cname.replace('.', '/') + ';';
206                     s_signatureMap.put(cname, base);
207                     
208                 }
209                 
210                 // prepend appropriate number of
211
StringBuffer JavaDoc buff = new StringBuffer JavaDoc(dim + base.length());
212                 for (int i = 0; i < dim; i++) {
213                     buff.append('[');
214                 }
215                 buff.append(base);
216                 sig = buff.toString();
217                     
218             } else {
219                 
220                 // define signature for ordinary object type
221
sig = "L" + type.replace('.', '/') + ';';
222                 
223             }
224             
225             // add signature definition to map
226
s_signatureMap.put(type, sig);
227         }
228         
229         // return signature for type
230
return sig;
231     }
232     
233     /**
234      * Check if a value of one type can be directly assigned to another type.
235      * This is basically the equivalent of the instanceof operator, but with
236      * application to primitive types as well as object types.
237      *
238      * @param from fully qualified class name of initial type
239      * @param to fully qualified class name of assignment type
240      * @param vctx validation context (used for class lookup)
241      * @return <code>true</code> if assignable, <code>false</code> if not
242      */

243     public static boolean isAssignable(String JavaDoc from, String JavaDoc to,
244         ValidationContext vctx) {
245         
246         // always assignable if the two are the same
247
if (from.equals(to)) {
248             return true;
249         } else {
250             
251             // try direct lookup for primitive types
252
Object JavaDoc fobj = s_variantMap.get(from);
253             Object JavaDoc tobj = s_variantMap.get(to);
254             if (fobj == null && tobj == null) {
255                 
256                 // find the actual class information
257
IClass fclas = vctx.getRequiredClassInfo(from);
258                 IClass tclas = vctx.getRequiredClassInfo(to);
259                 
260                 // assignable if from type has to as a possible signature
261
String JavaDoc[] sigs = fclas.getInstanceSigs();
262                 String JavaDoc match = getSignature(to);
263                 for (int i = 0; i < sigs.length; i++) {
264                     if (match.equals(sigs[i])) {
265                         return true;
266                     }
267                 }
268                 return false;
269                 
270             } else if (fobj != null && tobj != null) {
271                 
272                 // assignable if from type has to as a possible signature
273
String JavaDoc[] fsigs = (String JavaDoc[])fobj;
274                 String JavaDoc[] tsigs = (String JavaDoc[])tobj;
275                 if (tsigs.length == 1) {
276                     for (int i = 0; i < fsigs.length; i++) {
277                         if (fsigs[i] == tsigs[0]) {
278                             return true;
279                         }
280                     }
281                 }
282                 return false;
283                 
284             } else {
285                 
286                 // primitive and object types never assignable
287
return false;
288                 
289             }
290         }
291     }
292
293     /**
294      * Try loading class from classpath.
295      *
296      * @param name fully qualified name of class to be loaded
297      * @return loaded class, or <code>null</code> if not found
298      */

299     public static Class JavaDoc loadClass(String JavaDoc name) {
300         try {
301             return ClassUtils.class.getClassLoader().loadClass(name);
302         } catch (ClassNotFoundException JavaDoc ex) {
303             return null;
304         }
305     }
306 }
Popular Tags