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