001 package net.sourceforge.pmd.util;
002
003 import java.lang.reflect.Method;
004 import java.math.BigDecimal;
005 import java.util.ArrayList;
006 import java.util.HashMap;
007 import java.util.List;
008 import java.util.Map;
009
010 /**
011 * Various class-related utility methods.
012 *
013 * @author Brian Remedios
014 */
015 public final class ClassUtil {
016
017 public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
018
019 private ClassUtil() {
020 };
021
022 @SuppressWarnings("PMD.AvoidUsingShortType")
023 private static final TypeMap PRIMITIVE_TYPE_NAMES = new TypeMap(new Class[] { int.class, byte.class, long.class,
024 short.class, float.class, double.class, char.class, boolean.class, });
025
026 private static final TypeMap TYPES_BY_NAME = new TypeMap(new Class[] { Integer.class, Byte.class, Long.class,
027 Short.class, Float.class, Double.class, Character.class, Boolean.class, BigDecimal.class, String.class,
028 Object.class, });
029
030 private static final Map<Class, String> SHORT_NAMES_BY_TYPE = computeClassShortNames();
031
032 /**
033 * Returns the type(class) for the name specified or null if not found.
034 *
035 * @param name String
036 * @return Class
037 */
038 public static Class<?> getPrimitiveTypeFor(String name) {
039 return PRIMITIVE_TYPE_NAMES.typeFor(name);
040 }
041
042 /**
043 * Return a map of all the short names of classes we maintain mappings for.
044 * The names are keyed by the classes themselves.
045 *
046 * @return Map<Class, String>
047 */
048 private static Map<Class, String> computeClassShortNames() {
049
050 Map<Class, String> map = new HashMap<Class, String>();
051 map.putAll(PRIMITIVE_TYPE_NAMES.asInverseWithShortName());
052 map.putAll(TYPES_BY_NAME.asInverseWithShortName());
053 return map;
054 }
055
056 public static Map<Class, String> getClassShortNames() {
057 return SHORT_NAMES_BY_TYPE;
058 }
059
060 /**
061 * Attempt to determine the actual class given the short name.
062 *
063 * @param shortName String
064 * @return Class
065 */
066 public static Class<?> getTypeFor(String shortName) {
067 Class<?> type = TYPES_BY_NAME.typeFor(shortName);
068 if (type != null) {
069 return type;
070 }
071
072 type = PRIMITIVE_TYPE_NAMES.typeFor(shortName);
073 if (type != null) {
074 return type;
075 }
076
077 return CollectionUtil.getCollectionTypeFor(shortName);
078 }
079
080 /**
081 * Return the name of the type in its short form if its known to us
082 * otherwise return its name fully packaged.
083 *
084 * @param type
085 * @return String
086 */
087 public static String asShortestName(Class<?> type) {
088
089 String name = SHORT_NAMES_BY_TYPE.get(type);
090 return name == null ? type.getName() : name;
091 }
092
093 /**
094 * Returns the abbreviated name of the type, without the package name
095 *
096 * @param fullTypeName
097 * @return String
098 */
099
100 public static String withoutPackageName(String fullTypeName) {
101 int dotPos = fullTypeName.lastIndexOf('.');
102 return dotPos > 0 ? fullTypeName.substring(dotPos + 1) : fullTypeName;
103 }
104
105 /**
106 * Attempts to return the specified method from the class provided but will
107 * walk up its superclasses until it finds a match. Returns null if it
108 * doesn't.
109 *
110 * @param clasz Class
111 * @param methodName String
112 * @param paramTypes Class[]
113 * @return Method
114 */
115 public static Method methodFor(Class<?> clasz, String methodName, Class<?>[] paramTypes) {
116 Method method = null;
117 Class<?> current = clasz;
118 while (current != Object.class) {
119 try {
120 method = current.getDeclaredMethod(methodName, paramTypes);
121 } catch (NoSuchMethodException ex) {
122 current = current.getSuperclass();
123 }
124 if (method != null) {
125 return method;
126 }
127 }
128 return null;
129 }
130
131 /**
132 * Return the methods as a map keyed by their common declaration types.
133 *
134 * @param methods
135 * @return Map<String, List<Method>>
136 */
137 public static Map<String, List<Method>> asMethodGroupsByTypeName(Method[] methods) {
138
139 Map<String, List<Method>> methodGroups = new HashMap<String, List<Method>>(methods.length);
140
141 for (int i=0; i<methods.length; i++) {
142 String clsName = ClassUtil.asShortestName(methods[i].getDeclaringClass());
143 if (!methodGroups.containsKey(clsName)) {
144 methodGroups.put(clsName, new ArrayList<Method>());
145 }
146 methodGroups.get(clsName).add(methods[i]);
147 }
148 return methodGroups;
149 }
150 }
|