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 }