001 package com.mockrunner.util.common; 002 003 import java.util.ArrayList; 004 import java.util.Arrays; 005 import java.util.Collections; 006 import java.util.HashSet; 007 import java.util.List; 008 import java.util.Set; 009 010 public class ClassUtil 011 { 012 private final static String[] KEYWORDS = new String[] 013 { 014 "abstract", "assert", "boolean", "break", "byte", 015 "case", "catch", "char", "class", "const", 016 "continue", "default", "do", "double", "else", "enum", 017 "extends", "final", "finally", "float", "for", 018 "goto", "if", "implements", "import", "instanceof", 019 "int", "interface", "long", "native", "new", 020 "package", "private", "protected", "public", "return", 021 "short", "static", "strictFP", "super", "switch", 022 "synchronized", "this", "throw", "throws", "transient", 023 "try", "void", "volatile", "while" 024 }; 025 026 /** 027 * Returns the name of the package of the specified class. 028 * If the class has no package, an empty String will be 029 * returned. 030 * @param clazz the Class 031 * @return the package name 032 */ 033 public static String getPackageName(Class clazz) 034 { 035 Package classPackage = clazz.getPackage(); 036 if(null == classPackage) return ""; 037 return classPackage.getName(); 038 } 039 040 /** 041 * Returns the name of the specified class. This method 042 * only returns the class name without package information. 043 * If the specified class represents a primitive type, the 044 * name of the primitive type will be returned. If the 045 * specified class is an array, <code>[]</code> will be 046 * appended to the name (once for each dimension). 047 * @param clazz the Class 048 * @return the class name 049 */ 050 public static String getClassName(Class clazz) 051 { 052 String dimensions = ""; 053 while(clazz.isArray()) 054 { 055 clazz = clazz.getComponentType(); 056 dimensions += "[]"; 057 } 058 String classPackage = getPackageName(clazz); 059 if(classPackage.length() == 0) 060 { 061 return clazz.getName() + dimensions; 062 } 063 else 064 { 065 return clazz.getName().substring(classPackage.length() + 1) + dimensions; 066 } 067 } 068 069 /** 070 * Returns all interfaces implemented by the specified class 071 * including all interfaces implemented by super classes. 072 * If the specified class is itself an interfaces or the 073 * specified class does not implement any interfaces, this 074 * method returns an empty array. 075 * @param clazz the Class 076 * @return all interfaces implemented by the specified class 077 */ 078 public static Class[] getImplementedInterfaces(Class clazz) 079 { 080 if(clazz.isInterface()) return new Class[0]; 081 Class[] classes = getInheritanceHierarchy(clazz); 082 Set interfaceSet = new HashSet(); 083 for(int ii = 0; ii < classes.length; ii++) 084 { 085 interfaceSet.addAll(Arrays.asList(classes[ii].getInterfaces())); 086 } 087 return (Class[])interfaceSet.toArray(new Class[interfaceSet.size()]); 088 } 089 090 /** 091 * Returns the inheritance hierarchy of the specified class. 092 * The returned array includes all superclasses of the specified class 093 * starting with the most general superclass, which is 094 * <code>java.lang.Object</code>. The returned array also 095 * includes the class itself as the last element. Implemented 096 * interfaces are not included. 097 * @param clazz the Class 098 * @return all superclasses, most general superclass first 099 */ 100 public static Class[] getInheritanceHierarchy(Class clazz) 101 { 102 List classes = new ArrayList(); 103 Class currentClass = clazz; 104 while(null != currentClass) 105 { 106 classes.add(currentClass); 107 currentClass = currentClass.getSuperclass(); 108 } 109 Collections.reverse(classes); 110 return (Class[])classes.toArray(new Class[classes.size()]); 111 } 112 113 /** 114 * Returns if the specified string is a Java language 115 * keyword. 116 * @param name the string 117 * @return <code>true</code> if it is a keyword, 118 * <code>false</code> otherwise 119 */ 120 public static boolean isKeyword(String name) 121 { 122 for(int ii = 0; ii < KEYWORDS.length; ii++) 123 { 124 if(KEYWORDS[ii].equals(name)) return true; 125 } 126 return false; 127 } 128 129 /** 130 * Returns a suitable argument name for arguments 131 * of type <code>argumentType</code>. Simply takes 132 * the class name and converts the starting characters 133 * to lower case (by preserving one upper case character). 134 * E.g. the result of <code>JMSTestModule</code> is 135 * <code>jmsTestModule</code>. 136 * If the specified <code>argumentType</code> is an array, 137 * an <code>"s"</code> is appended to the string. 138 * If the resulting string is a Java keyword, <code>"Value"</code> 139 * is appended to the string (which is always the case with 140 * primitive types). 141 * @param argumentType the argument type 142 * @return a suitable mixed case argument name 143 */ 144 public static String getArgumentName(Class argumentType) 145 { 146 String dimensions = ""; 147 while(argumentType.isArray()) 148 { 149 argumentType = argumentType.getComponentType(); 150 dimensions = "s"; 151 } 152 String name = getClassName(argumentType); 153 int index = 0; 154 while(index < name.length() - 1 && Character.isUpperCase(name.charAt(index)) && Character.isUpperCase(name.charAt(index + 1))) 155 { 156 index++; 157 } 158 if(index == name.length() - 1) 159 { 160 index++; 161 } 162 name = StringUtil.lowerCase(name, 0, index); 163 if(isKeyword(name)) 164 { 165 name += "Value"; 166 } 167 name += dimensions; 168 return name; 169 } 170 }