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    }