001    package org.springframework.richclient.widget.table;
002    
003    import java.lang.reflect.Method;
004    
005    import org.apache.commons.beanutils.MethodUtils;
006    
007    /**
008     * A number of helper classes to retrieve getter and setter methods.
009     * 
010     * @author Jan Hoskens
011     * @since 0.5.0
012     */
013    public class ClassUtils
014    {
015    
016        /**
017         * No instantiation possible.
018         */
019        private ClassUtils()
020        {
021        }
022    
023        /**
024         * Lookup the getter method for the given property. This can be a getXXX() or a isXXX() method.
025         * 
026         * @param clazz
027         *            type which contains the property.
028         * @param propertyName
029         *            name of the property.
030         * @return a Method with read-access for the property.
031         */
032        public static Method getReadMethod(Class<?> clazz, String propertyName) throws NoSuchMethodError
033        {
034            String propertyNameCapitalized = capitalize(propertyName);
035            try
036            {
037                return clazz.getMethod("get" + propertyNameCapitalized);
038            }
039            catch (Exception e)
040            {
041                try
042                {
043                    return clazz.getMethod("is" + propertyNameCapitalized);
044                }
045                catch (Exception e1)
046                {
047                    throw new NoSuchMethodError("Could not find getter (getXX or isXXX) for property: "
048                            + propertyName);
049                }
050            }
051        }
052    
053        /**
054         * Returns the type of the property checking if it actually does return something and wrapping primitives
055         * if needed.
056         * 
057         * @param getter
058         *            the method to access the property.
059         * @return the type of the property.
060         * @throws IllegalArgumentException
061         *             if the method has a {@link Void} return type.
062         */
063        public static Class<?> getTypeForProperty(Method getter)
064        {
065            Class<?> returnType = getter.getReturnType();
066            if (returnType.equals(Void.TYPE))
067                throw new IllegalArgumentException("Getter " + getter.toString() + " does not have a returntype.");
068            else if (returnType.isPrimitive())
069                return MethodUtils.getPrimitiveWrapper(returnType);
070            return returnType;
071        }
072    
073        /**
074         * Lookup the setter method for the given property.
075         * 
076         * @param clazz
077         *            type which contains the property.
078         * @param propertyName
079         *            name of the property.
080         * @param propertyType
081         *            type of the property.
082         * @return a Method with write-access for the property.
083         */
084        public static final Method getWriteMethod(Class<?> clazz, String propertyName, Class<?> propertyType)
085        {
086            String propertyNameCapitalized = capitalize(propertyName);
087            try
088            {
089                return clazz.getMethod("set" + propertyNameCapitalized, new Class[]{propertyType});
090            }
091            catch (Exception e)
092            {
093                return null;
094            }
095        }
096    
097        /**
098         * Small helper method to capitalize the first character of the given string.
099         * 
100         * @param s
101         *            string to capitalize
102         * @return a string starting with a capital character.
103         */
104        public static String capitalize(String s)
105        {
106            if (s == null || s.length() == 0)
107            {
108                return s;
109            }
110            char chars[] = s.toCharArray();
111            chars[0] = Character.toUpperCase(chars[0]);
112            return new String(chars);
113        }
114    
115        /**
116         * Create an {@link Accessor} for the given property. A property may be nested using the dot character.
117         * 
118         * @param clazz
119         *            the type containing the property.
120         * @param propertyName
121         *            the name of the property.
122         * @return an Accessor for the property.
123         */
124        public static Accessor getAccessorForProperty(final Class<?> clazz, final String propertyName)
125        {
126            int splitPoint = propertyName.indexOf('.');
127            if (splitPoint > 0)
128            {
129                String firstPart = propertyName.substring(0, splitPoint);
130                String secondPart = propertyName.substring(splitPoint + 1);
131                return new NestedAccessor(clazz, firstPart, secondPart);
132            }
133            return new SimpleAccessor(clazz, propertyName);
134        }
135    
136        /**
137         * Create a {@link Writer} for the given property. A property may be nested using the dot character.
138         * 
139         * @param clazz
140         *            the type containing the property.
141         * @param propertyName
142         *            the name of the property.
143         * @return a Writer for the property.
144         */
145        public static Writer getWriterForProperty(final Class<?> beanClass, final String propertyName)
146        {
147            int splitPoint = propertyName.indexOf('.');
148            if (splitPoint > 0)
149            {
150                String firstPart = propertyName.substring(0, splitPoint);
151                String secondPart = propertyName.substring(splitPoint + 1);
152                return new NestedWriter(beanClass, firstPart, secondPart);
153            }
154            return new SimpleWriter(beanClass, propertyName);
155        }
156    }