KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > lang > ClassUtils


1 /*
2  * Copyright 2002-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.lang;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23
24 /**
25  * <p>Operates on classes without using reflection.</p>
26  *
27  * <p>This class handles invalid <code>null</code> inputs as best it can.
28  * Each method documents its behaviour in more detail.</p>
29  *
30  * @author Stephen Colebourne
31  * @author Gary Gregory
32  * @author Norm Deane
33  * @since 2.0
34  * @version $Id: ClassUtils.java 161243 2005-04-14 04:30:28Z ggregory $
35  */

36 public class ClassUtils {
37
38     /**
39      * <p>The package separator character: <code>'&#x2e;' == {@value}</code>.</p>
40      */

41     public static final char PACKAGE_SEPARATOR_CHAR = '.';
42     
43     /**
44      * <p>The package separator String: <code>"&#x2e;"</code>.</p>
45      */

46     public static final String JavaDoc PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
47     
48     /**
49      * <p>The inner class separator character: <code>'$' == {@value}</code>.</p>
50      */

51     public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
52     
53     /**
54      * <p>The inner class separator String: <code>"$"</code>.</p>
55      */

56     public static final String JavaDoc INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
57     
58     /**
59      * Maps primitive <code>Class</code>es to their corresponding wrapper <code>Class</code>.
60      */

61     private static Map JavaDoc primitiveWrapperMap = new HashMap JavaDoc();
62     static {
63          primitiveWrapperMap.put(Boolean.TYPE, Boolean JavaDoc.class);
64          primitiveWrapperMap.put(Byte.TYPE, Byte JavaDoc.class);
65          primitiveWrapperMap.put(Character.TYPE, Character JavaDoc.class);
66          primitiveWrapperMap.put(Short.TYPE, Short JavaDoc.class);
67          primitiveWrapperMap.put(Integer.TYPE, Integer JavaDoc.class);
68          primitiveWrapperMap.put(Long.TYPE, Long JavaDoc.class);
69          primitiveWrapperMap.put(Double.TYPE, Double JavaDoc.class);
70          primitiveWrapperMap.put(Float.TYPE, Float JavaDoc.class);
71     }
72     
73     /**
74      * <p>ClassUtils instances should NOT be constructed in standard programming.
75      * Instead, the class should be used as
76      * <code>ClassUtils.getShortClassName(cls)</code>.</p>
77      *
78      * <p>This constructor is public to permit tools that require a JavaBean
79      * instance to operate.</p>
80      */

81     public ClassUtils() {
82     }
83
84     // Short class name
85
// ----------------------------------------------------------------------
86
/**
87      * <p>Gets the class name minus the package name for an <code>Object</code>.</p>
88      *
89      * @param object the class to get the short name for, may be null
90      * @param valueIfNull the value to return if null
91      * @return the class name of the object without the package name, or the null value
92      */

93     public static String JavaDoc getShortClassName(Object JavaDoc object, String JavaDoc valueIfNull) {
94         if (object == null) {
95             return valueIfNull;
96         }
97         return getShortClassName(object.getClass().getName());
98     }
99     
100     /**
101      * <p>Gets the class name minus the package name from a <code>Class</code>.</p>
102      *
103      * @param cls the class to get the short name for.
104      * @return the class name without the package name or an empty string
105      */

106     public static String JavaDoc getShortClassName(Class JavaDoc cls) {
107         if (cls == null) {
108             return StringUtils.EMPTY;
109         }
110         return getShortClassName(cls.getName());
111     }
112     
113     /**
114      * <p>Gets the class name minus the package name from a String.</p>
115      *
116      * <p>The string passed in is assumed to be a class name - it is not checked.</p>
117      *
118      * @param className the className to get the short name for
119      * @return the class name of the class without the package name or an empty string
120      */

121     public static String JavaDoc getShortClassName(String JavaDoc className) {
122         if (className == null) {
123             return StringUtils.EMPTY;
124         }
125         if (className.length() == 0) {
126             return StringUtils.EMPTY;
127         }
128         char[] chars = className.toCharArray();
129         int lastDot = 0;
130         for (int i = 0; i < chars.length; i++) {
131             if (chars[i] == PACKAGE_SEPARATOR_CHAR) {
132                 lastDot = i + 1;
133             } else if (chars[i] == INNER_CLASS_SEPARATOR_CHAR) { // handle inner classes
134
chars[i] = PACKAGE_SEPARATOR_CHAR;
135             }
136         }
137         return new String JavaDoc(chars, lastDot, chars.length - lastDot);
138     }
139     
140     // Package name
141
// ----------------------------------------------------------------------
142
/**
143      * <p>Gets the package name of an <code>Object</code>.</p>
144      *
145      * @param object the class to get the package name for, may be null
146      * @param valueIfNull the value to return if null
147      * @return the package name of the object, or the null value
148      */

149     public static String JavaDoc getPackageName(Object JavaDoc object, String JavaDoc valueIfNull) {
150         if (object == null) {
151             return valueIfNull;
152         }
153         return getPackageName(object.getClass().getName());
154     }
155     
156     /**
157      * <p>Gets the package name of a <code>Class</code>.</p>
158      *
159      * @param cls the class to get the package name for, may be <code>null</code>.
160      * @return the package name or an empty string
161      */

162     public static String JavaDoc getPackageName(Class JavaDoc cls) {
163         if (cls == null) {
164             return StringUtils.EMPTY;
165         }
166         return getPackageName(cls.getName());
167     }
168     
169     /**
170      * <p>Gets the package name from a <code>String</code>.</p>
171      *
172      * <p>The string passed in is assumed to be a class name - it is not checked.</p>
173      * <p>If the class is unpackaged, return an empty string.</p>
174      *
175      * @param className the className to get the package name for, may be <code>null</code>
176      * @return the package name or an empty string
177      */

178     public static String JavaDoc getPackageName(String JavaDoc className) {
179         if (className == null) {
180             return StringUtils.EMPTY;
181         }
182         int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
183         if (i == -1) {
184             return StringUtils.EMPTY;
185         }
186         return className.substring(0, i);
187     }
188     
189     // Superclasses/Superinterfaces
190
// ----------------------------------------------------------------------
191
/**
192      * <p>Gets a <code>List</code> of superclasses for the given class.</p>
193      *
194      * @param cls the class to look up, may be <code>null</code>
195      * @return the <code>List</code> of superclasses in order going up from this one
196      * <code>null</code> if null input
197      */

198     public static List JavaDoc getAllSuperclasses(Class JavaDoc cls) {
199         if (cls == null) {
200             return null;
201         }
202         List JavaDoc classes = new ArrayList JavaDoc();
203         Class JavaDoc superclass = cls.getSuperclass();
204         while (superclass != null) {
205             classes.add(superclass);
206             superclass = superclass.getSuperclass();
207         }
208         return classes;
209     }
210     
211     /**
212      * <p>Gets a <code>List</code> of all interfaces implemented by the given
213      * class and its superclasses.</p>
214      *
215      * <p>The order is determined by looking through each interface in turn as
216      * declared in the source file and following its hierarchy up. Then each
217      * superclass is considered in the same way. Later duplicates are ignored,
218      * so the order is maintained.</p>
219      *
220      * @param cls the class to look up, may be <code>null</code>
221      * @return the <code>List</code> of interfaces in order,
222      * <code>null</code> if null input
223      */

224     public static List JavaDoc getAllInterfaces(Class JavaDoc cls) {
225         if (cls == null) {
226             return null;
227         }
228         List JavaDoc list = new ArrayList JavaDoc();
229         while (cls != null) {
230             Class JavaDoc[] interfaces = cls.getInterfaces();
231             for (int i = 0; i < interfaces.length; i++) {
232                 if (list.contains(interfaces[i]) == false) {
233                     list.add(interfaces[i]);
234                 }
235                 List JavaDoc superInterfaces = getAllInterfaces(interfaces[i]);
236                 for (Iterator JavaDoc it = superInterfaces.iterator(); it.hasNext();) {
237                     Class JavaDoc intface = (Class JavaDoc) it.next();
238                     if (list.contains(intface) == false) {
239                         list.add(intface);
240                     }
241                 }
242             }
243             cls = cls.getSuperclass();
244         }
245         return list;
246     }
247     
248     // Convert list
249
// ----------------------------------------------------------------------
250
/**
251      * <p>Given a <code>List</code> of class names, this method converts them into classes.</p>
252      *
253      * <p>A new <code>List</code> is returned. If the class name cannot be found, <code>null</code>
254      * is stored in the <code>List</code>. If the class name in the <code>List</code> is
255      * <code>null</code>, <code>null</code> is stored in the output <code>List</code>.</p>
256      *
257      * @param classNames the classNames to change
258      * @return a <code>List</code> of Class objects corresponding to the class names,
259      * <code>null</code> if null input
260      * @throws ClassCastException if classNames contains a non String entry
261      */

262     public static List JavaDoc convertClassNamesToClasses(List JavaDoc classNames) {
263         if (classNames == null) {
264             return null;
265         }
266         List JavaDoc classes = new ArrayList JavaDoc(classNames.size());
267         for (Iterator JavaDoc it = classNames.iterator(); it.hasNext();) {
268             String JavaDoc className = (String JavaDoc) it.next();
269             try {
270                 classes.add(Class.forName(className));
271             } catch (Exception JavaDoc ex) {
272                 classes.add(null);
273             }
274         }
275         return classes;
276     }
277     
278     /**
279      * <p>Given a <code>List</code> of <code>Class</code> objects, this method converts
280      * them into class names.</p>
281      *
282      * <p>A new <code>List</code> is returned. <code>null</code> objects will be copied into
283      * the returned list as <code>null</code>.</p>
284      *
285      * @param classes the classes to change
286      * @return a <code>List</code> of class names corresponding to the Class objects,
287      * <code>null</code> if null input
288      * @throws ClassCastException if <code>classes</code> contains a non-<code>Class</code> entry
289      */

290     public static List JavaDoc convertClassesToClassNames(List JavaDoc classes) {
291         if (classes == null) {
292             return null;
293         }
294         List JavaDoc classNames = new ArrayList JavaDoc(classes.size());
295         for (Iterator JavaDoc it = classes.iterator(); it.hasNext();) {
296             Class JavaDoc cls = (Class JavaDoc) it.next();
297             if (cls == null) {
298                 classNames.add(null);
299             } else {
300                 classNames.add(cls.getName());
301             }
302         }
303         return classNames;
304     }
305     
306     // Is assignable
307
// ----------------------------------------------------------------------
308
/**
309      * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
310      *
311      * <p>This method calls {@link #isAssignable(Class, Class) isAssignable} for each
312      * Class pair in the input arrays. It can be used to check if a set of arguments
313      * (the first parameter) are suitably compatible with a set of method parameter types
314      * (the second parameter).</p>
315      *
316      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
317      * method takes into account widenings of primitive classes and
318      * <code>null</code>s.</p>
319      *
320      * <p>Primitive widenings allow an int to be assigned to a <code>long</code>,
321      * <code>float</code> or <code>double</code>. This method returns the correct
322      * result for these cases.</p>
323      *
324      * <p><code>Null</code> may be assigned to any reference type. This method will
325      * return <code>true</code> if <code>null</code> is passed in and the toClass is
326      * non-primitive.</p>
327      *
328      * <p>Specifically, this method tests whether the type represented by the
329      * specified <code>Class</code> parameter can be converted to the type
330      * represented by this <code>Class</code> object via an identity conversion
331      * widening primitive or widening reference conversion. See
332      * <em><a HREF="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
333      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
334      *
335      * @param classArray the array of Classes to check, may be <code>null</code>
336      * @param toClassArray the array of Classes to try to assign into, may be <code>null</code>
337      * @return <code>true</code> if assignment possible
338      */

339     public static boolean isAssignable(Class JavaDoc[] classArray, Class JavaDoc[] toClassArray) {
340         if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
341             return false;
342         }
343         if (classArray == null) {
344             classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
345         }
346         if (toClassArray == null) {
347             toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
348         }
349         for (int i = 0; i < classArray.length; i++) {
350             if (isAssignable(classArray[i], toClassArray[i]) == false) {
351                 return false;
352             }
353         }
354         return true;
355     }
356     
357     /**
358      * <p>Checks if one <code>Class</code> can be assigned to a variable of
359      * another <code>Class</code>.</p>
360      *
361      * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
362      * this method takes into account widenings of primitive classes and
363      * <code>null</code>s.</p>
364      *
365      * <p>Primitive widenings allow an int to be assigned to a long, float or
366      * double. This method returns the correct result for these cases.</p>
367      *
368      * <p><code>Null</code> may be assigned to any reference type. This method
369      * will return <code>true</code> if <code>null</code> is passed in and the
370      * toClass is non-primitive.</p>
371      *
372      * <p>Specifically, this method tests whether the type represented by the
373      * specified <code>Class</code> parameter can be converted to the type
374      * represented by this <code>Class</code> object via an identity conversion
375      * widening primitive or widening reference conversion. See
376      * <em><a HREF="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
377      * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
378      *
379      * @param cls the Class to check, may be null
380      * @param toClass the Class to try to assign into, returns false if null
381      * @return <code>true</code> if assignment possible
382      */

383     public static boolean isAssignable(Class JavaDoc cls, Class JavaDoc toClass) {
384         if (toClass == null) {
385             return false;
386         }
387         // have to check for null, as isAssignableFrom doesn't
388
if (cls == null) {
389             return !(toClass.isPrimitive());
390         }
391         if (cls.equals(toClass)) {
392             return true;
393         }
394         if (cls.isPrimitive()) {
395             if (toClass.isPrimitive() == false) {
396                 return false;
397             }
398             if (Integer.TYPE.equals(cls)) {
399                 return Long.TYPE.equals(toClass)
400                     || Float.TYPE.equals(toClass)
401                     || Double.TYPE.equals(toClass);
402             }
403             if (Long.TYPE.equals(cls)) {
404                 return Float.TYPE.equals(toClass)
405                     || Double.TYPE.equals(toClass);
406             }
407             if (Boolean.TYPE.equals(cls)) {
408                 return false;
409             }
410             if (Double.TYPE.equals(cls)) {
411                 return false;
412             }
413             if (Float.TYPE.equals(cls)) {
414                 return Double.TYPE.equals(toClass);
415             }
416             if (Character.TYPE.equals(cls)) {
417                 return Integer.TYPE.equals(toClass)
418                     || Long.TYPE.equals(toClass)
419                     || Float.TYPE.equals(toClass)
420                     || Double.TYPE.equals(toClass);
421             }
422             if (Short.TYPE.equals(cls)) {
423                 return Integer.TYPE.equals(toClass)
424                     || Long.TYPE.equals(toClass)
425                     || Float.TYPE.equals(toClass)
426                     || Double.TYPE.equals(toClass);
427             }
428             if (Byte.TYPE.equals(cls)) {
429                 return Short.TYPE.equals(toClass)
430                     || Integer.TYPE.equals(toClass)
431                     || Long.TYPE.equals(toClass)
432                     || Float.TYPE.equals(toClass)
433                     || Double.TYPE.equals(toClass);
434             }
435             // should never get here
436
return false;
437         }
438         return toClass.isAssignableFrom(cls);
439     }
440     
441     /**
442      * <p>Converts the specified primitive Class object to its corresponding
443      * wrapper Class object.</p>
444      *
445      * @param cls the class to convert, may be null
446      * @return the wrapper class for <code>cls</code> or <code>cls</code> if
447      * <code>cls</code> is not a primitive. <code>null</code> if null input.
448      * @since 2.1
449      */

450     public static Class JavaDoc primitiveToWrapper(Class JavaDoc cls) {
451         Class JavaDoc convertedClass = cls;
452         if (cls != null && cls.isPrimitive()) {
453             convertedClass = (Class JavaDoc) primitiveWrapperMap.get(cls);
454         }
455         return convertedClass;
456     }
457
458     /**
459      * <p>Converts the specified array of primitive Class objects to an array of
460      * its corresponding wrapper Class objects.</p>
461      *
462      * @param classes the class array to convert, may be null or empty
463      * @return an array which contains for each given class, the wrapper class or
464      * the original class if class is not a primitive. <code>null</code> if null input.
465      * Empty array if an empty array passed in.
466      * @since 2.1
467      */

468     public static Class JavaDoc[] primitivesToWrappers(Class JavaDoc[] classes) {
469         if (classes == null) {
470             return null;
471         }
472         
473         if (classes.length == 0) {
474             return classes;
475         }
476         
477         Class JavaDoc[] convertedClasses = new Class JavaDoc[classes.length];
478         for (int i=0; i < classes.length; i++) {
479             convertedClasses[i] = primitiveToWrapper( classes[i] );
480         }
481         return convertedClasses;
482     }
483
484     // Inner class
485
// ----------------------------------------------------------------------
486
/**
487      * <p>Is the specified class an inner class or static nested class.</p>
488      *
489      * @param cls the class to check, may be null
490      * @return <code>true</code> if the class is an inner or static nested class,
491      * false if not or <code>null</code>
492      */

493     public static boolean isInnerClass(Class JavaDoc cls) {
494         if (cls == null) {
495             return false;
496         }
497         return cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0;
498     }
499
500 }
501
Popular Tags