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 }