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