001package ch.qos.logback.core.joran.util.beans;
002
003import java.lang.reflect.Method;
004
005/**
006 * Encapsulates utility methods associated with standard java beans.
007 * 
008 * @author urechm
009 */
010public class BeanUtil {
011
012    // public static final BeanUtil SINGLETON = new BeanUtil();
013
014    public static final String PREFIX_GETTER_IS = "is";
015    public static final String PREFIX_GETTER_GET = "get";
016    public static final String PREFIX_SETTER = "set";
017    public static final String PREFIX_ADDER = "add";
018
019    /**
020     *
021     * @param method to check if it is an 'adder' method.
022     * @return true if the given method is an 'adder' method.
023     */
024    static public boolean isAdder(Method method) {
025        int parameterCount = getParameterCount(method);
026        if (parameterCount != 1) {
027            return false;
028        }
029        Class<?> returnType = method.getReturnType();
030        if (returnType != void.class) {
031            return false;
032        }
033        String methodName = method.getName();
034        return methodName.startsWith(PREFIX_ADDER);
035    }
036
037    /**
038     *
039     * @param method to check if it is a standard java beans getter.
040     * @return true if the given method is a standard java beans getter.
041     */
042    static public boolean isGetter(Method method) {
043        int parameterCount = getParameterCount(method);
044        if (parameterCount > 0) {
045            return false;
046        }
047        Class<?> returnType = method.getReturnType();
048        if (returnType == void.class) {
049            return false;
050        }
051        String methodName = method.getName();
052        if (!methodName.startsWith(PREFIX_GETTER_GET) && !methodName.startsWith(PREFIX_GETTER_IS)) {
053            return false;
054        }
055        if (methodName.startsWith(PREFIX_GETTER_IS)) {
056            if (!returnType.equals(boolean.class) && !returnType.equals(Boolean.class)) {
057                return false;
058            }
059        }
060        return true;
061    }
062
063    static private int getParameterCount(Method method) {
064        return method.getParameterTypes().length;
065    }
066
067    /**
068     *
069     * @param method to check if it is a standard java beans setter.
070     * @return true if the given method is a standard java beans setter.
071     */
072    static public boolean isSetter(Method method) {
073        int parameterCount = getParameterCount(method);
074        if (parameterCount != 1) {
075            return false;
076        }
077        Class<?> returnType = method.getReturnType();
078        if (returnType != void.class) {
079            return false;
080        }
081        String methodName = method.getName();
082        if (!methodName.startsWith(PREFIX_SETTER)) {
083            return false;
084        }
085        return true;
086    }
087
088    /**
089     * @param method to get the associated property name for.
090     * @return The property name of the associated property if the given method
091     *         matches a standard java beans getter or setter.
092     */
093    static public String getPropertyName(Method method) {
094        String methodName = method.getName();
095        String rawPropertyName = getSubstringIfPrefixMatches(methodName, PREFIX_GETTER_GET);
096        if (rawPropertyName == null) {
097            rawPropertyName = getSubstringIfPrefixMatches(methodName, PREFIX_SETTER);
098        }
099        if (rawPropertyName == null) {
100            rawPropertyName = getSubstringIfPrefixMatches(methodName, PREFIX_GETTER_IS);
101        }
102        if (rawPropertyName == null) {
103            rawPropertyName = getSubstringIfPrefixMatches(methodName, PREFIX_ADDER);
104        }
105        return toLowerCamelCase(rawPropertyName);
106    }
107
108    /**
109     * Converts the given String into lower camel case form.
110     * 
111     * @param string to decapitalize.
112     * @return null if the given String is null. Empty string if the given string is
113     *         empty. The given string if the first two consecutive letters are in
114     *         upper case. The given string with the first letter in lower case
115     *         otherwise, which might be the given string.
116     */
117    static public String toLowerCamelCase(String string) {
118        if (string == null) {
119            return null;
120        }
121        if (string.isEmpty()) {
122            return string;
123        }
124        if (string.length() > 1 && Character.isUpperCase(string.charAt(1)) && Character.isUpperCase(string.charAt(0))) {
125            return string;
126        }
127        char chars[] = string.toCharArray();
128        chars[0] = Character.toLowerCase(chars[0]);
129        return new String(chars);
130    }
131
132    static private String getSubstringIfPrefixMatches(String wholeString, String prefix) {
133        if (wholeString.startsWith(prefix)) {
134            return wholeString.substring(prefix.length());
135        }
136        return null;
137    }
138
139}