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 }