View Javadoc

1   package net.sourceforge.pmd.util;
2   
3   import java.lang.reflect.Method;
4   import java.math.BigDecimal;
5   import java.util.ArrayList;
6   import java.util.HashMap;
7   import java.util.List;
8   import java.util.Map;
9   
10  /**
11   * Various class-related utility methods intended for mapping common java.lang types to their short 
12   * short forms allowing end users to enter these names in UIs without the package prefixes.
13   *
14   * @author Brian Remedios
15   */
16  public final class ClassUtil {
17  
18      public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
19  
20      private ClassUtil() {
21      };
22  
23      @SuppressWarnings("PMD.AvoidUsingShortType")
24      private static final TypeMap PRIMITIVE_TYPE_NAMES = new TypeMap(new Class[] { int.class, byte.class, long.class,
25              short.class, float.class, double.class, char.class, boolean.class, });
26  
27      private static final TypeMap TYPES_BY_NAME = new TypeMap(new Class[] { Integer.class, Byte.class, Long.class,
28              Short.class, Float.class, Double.class, Character.class, Boolean.class, BigDecimal.class, String.class,
29              Object.class, Class.class});
30  
31      private static final Map<Class<?>, String> SHORT_NAMES_BY_TYPE = computeClassShortNames();
32      
33      /**
34       * Returns the type(class) for the name specified or null if not found.
35       *
36       * @param name String
37       * @return Class
38       */
39      public static Class<?> getPrimitiveTypeFor(String name) {
40          return PRIMITIVE_TYPE_NAMES.typeFor(name);
41      }
42  
43      /**
44       * Return a map of all the short names of classes we maintain mappings for.
45       * The names are keyed by the classes themselves.
46       *
47       * @return Map<Class, String>
48       */
49      private static Map<Class<?>, String> computeClassShortNames() {
50          
51          Map<Class<?>, String> map = new HashMap<Class<?>, String>();
52          map.putAll(PRIMITIVE_TYPE_NAMES.asInverseWithShortName());
53          map.putAll(TYPES_BY_NAME.asInverseWithShortName());
54          return map;
55      }
56  
57      public static Map<Class<?>, String> getClassShortNames() {
58          return SHORT_NAMES_BY_TYPE;
59      }
60      
61      /**
62       * Attempt to determine the actual class given the short name.
63       *
64       * @param shortName String
65       * @return Class
66       */
67      public static Class<?> getTypeFor(String shortName) {
68          Class<?> type = TYPES_BY_NAME.typeFor(shortName);
69          if (type != null) {
70              return type;
71          }
72  
73          type = PRIMITIVE_TYPE_NAMES.typeFor(shortName);
74          if (type != null) {
75              return type;
76          }
77  
78          return CollectionUtil.getCollectionTypeFor(shortName);
79      }
80  
81      /**
82       * Return the name of the type in its short form if its known to us
83       * otherwise return its name fully packaged.
84       * 
85       * @param type
86       * @return String
87       */
88      public static String asShortestName(Class<?> type) {
89          
90          String name = SHORT_NAMES_BY_TYPE.get(type);
91          return name == null ? type.getName() : name;
92      }
93      
94      /**
95       * Returns the abbreviated name of the type, without the package name
96       *
97       * @param fullTypeName
98       * @return String
99       */
100 
101     public static String withoutPackageName(String fullTypeName) {
102         int dotPos = fullTypeName.lastIndexOf('.');
103         return dotPos > 0 ? fullTypeName.substring(dotPos + 1) : fullTypeName;
104     }
105 
106     /**
107      * Attempts to return the specified method from the class provided but will
108      * walk up its superclasses until it finds a match. Returns null if it
109      * doesn't.
110      *
111      * @param clasz		 Class
112      * @param methodName String
113      * @param paramTypes Class[]
114      * @return Method
115      */
116     public static Method methodFor(Class<?> clasz, String methodName, Class<?>[] paramTypes) {
117         Method method = null;
118         Class<?> current = clasz;
119         while (current != Object.class) {
120             try {
121                 method = current.getDeclaredMethod(methodName, paramTypes);
122             } catch (NoSuchMethodException ex) {
123                 current = current.getSuperclass();
124             }
125             if (method != null) {
126                 return method;
127             }
128         }
129         return null;
130     }
131     
132     /**
133      * Return the methods as a map keyed by their common declaration types.
134      * 
135      * @param methods
136      * @return Map<String, List<Method>>
137      */
138     public static Map<String, List<Method>> asMethodGroupsByTypeName(Method[] methods) {
139         
140         Map<String, List<Method>> methodGroups = new HashMap<String, List<Method>>(methods.length);
141         
142         for (int i=0; i<methods.length; i++) {
143             String clsName = asShortestName(methods[i].getDeclaringClass());
144             if (!methodGroups.containsKey(clsName)) {
145                 methodGroups.put(clsName, new ArrayList<Method>());
146             }
147             methodGroups.get(clsName).add(methods[i]);
148         }
149         return methodGroups;
150     }
151 }