1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v2.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  
15  package ch.qos.logback.core.joran.util.beans;
16  
17  import java.lang.reflect.Method;
18  
19  /**
20   * Encapsulates utility methods associated with standard java beans.
21   * 
22   * @author urechm
23   */
24  public class BeanUtil {
25  
26      // public static final BeanUtil SINGLETON = new BeanUtil();
27  
28      public static final String PREFIX_GETTER_IS = "is";
29      public static final String PREFIX_GETTER_GET = "get";
30      public static final String PREFIX_SETTER = "set";
31      public static final String PREFIX_ADDER = "add";
32  
33      /**
34       *
35       * @param method to check if it is an 'adder' method.
36       * @return true if the given method is an 'adder' method.
37       */
38      static public boolean isAdder(Method method) {
39          int parameterCount = getParameterCount(method);
40          if (parameterCount != 1) {
41              return false;
42          }
43          Class<?> returnType = method.getReturnType();
44          if (returnType != void.class) {
45              return false;
46          }
47          String methodName = method.getName();
48          return methodName.startsWith(PREFIX_ADDER);
49      }
50  
51      /**
52       *
53       * @param method to check if it is a standard java beans getter.
54       * @return true if the given method is a standard java beans getter.
55       */
56      static public boolean isGetter(Method method) {
57          int parameterCount = getParameterCount(method);
58          if (parameterCount > 0) {
59              return false;
60          }
61          Class<?> returnType = method.getReturnType();
62          if (returnType == void.class) {
63              return false;
64          }
65          String methodName = method.getName();
66          if (!methodName.startsWith(PREFIX_GETTER_GET) && !methodName.startsWith(PREFIX_GETTER_IS)) {
67              return false;
68          }
69          if (methodName.startsWith(PREFIX_GETTER_IS)) {
70              if (!returnType.equals(boolean.class) && !returnType.equals(Boolean.class)) {
71                  return false;
72              }
73          }
74          return true;
75      }
76  
77      static private int getParameterCount(Method method) {
78          return method.getParameterTypes().length;
79      }
80  
81      /**
82       *
83       * @param method to check if it is a standard java beans setter.
84       * @return true if the given method is a standard java beans setter.
85       */
86      static public boolean isSetter(Method method) {
87          int parameterCount = getParameterCount(method);
88          if (parameterCount != 1) {
89              return false;
90          }
91          Class<?> returnType = method.getReturnType();
92          if (returnType != void.class) {
93              return false;
94          }
95          String methodName = method.getName();
96          if (!methodName.startsWith(PREFIX_SETTER)) {
97              return false;
98          }
99          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 }