001package ball.beans; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: PropertyMethodEnum.java 5881 2020-05-06 04:14:12Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/beans/PropertyMethodEnum.java $ 007 * %% 008 * Copyright (C) 2008 - 2020 Allen D. Ball 009 * %% 010 * Licensed under the Apache License, Version 2.0 (the "License"); 011 * you may not use this file except in compliance with the License. 012 * You may obtain a copy of the License at 013 * 014 * http://www.apache.org/licenses/LICENSE-2.0 015 * 016 * Unless required by applicable law or agreed to in writing, software 017 * distributed under the License is distributed on an "AS IS" BASIS, 018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 019 * See the License for the specific language governing permissions and 020 * limitations under the License. 021 * ########################################################################## 022 */ 023import ball.annotation.ConstantValueMustConvertTo; 024import java.lang.reflect.Method; 025import java.util.Collections; 026import java.util.EnumMap; 027import java.util.Map; 028import java.util.regex.Matcher; 029import java.util.regex.Pattern; 030 031import static java.beans.Introspector.decapitalize; 032 033/** 034 * Bean property method {@link Enum} type. 035 * 036 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 037 * @version $Revision: 5881 $ 038 */ 039public enum PropertyMethodEnum { 040 GET, IS, SET; 041 042 private static final Map<PropertyMethodEnum,Method> MAP = 043 Collections.unmodifiableMap(new MethodPrototypeMap()); 044 045 @ConstantValueMustConvertTo(value = Pattern.class, method = "compile") 046 private static final String PROPERTY_REGEX = "([\\p{Upper}][\\p{Alnum}]*)"; 047 048 private Pattern pattern = null; 049 050 /** 051 * Method to get the prototype return type {@link Class} for this method 052 * type. 053 * 054 * @return The return type {@link Class}. 055 */ 056 public Class<?> getReturnType() { return MAP.get(this).getReturnType(); } 057 058 /** 059 * Method to get the prototype parameter types ({@link Class}es) for 060 * this method type. 061 * 062 * @return The parameter types array (of {@link Class}es). 063 */ 064 public Class<?>[] getParameterTypes() { 065 return MAP.get(this).getParameterTypes(); 066 } 067 068 /** 069 * Method to get the property name from the argument method name. 070 * 071 * @param method The candidate getter/setter method name. 072 * 073 * @return The property name if method name matches the pattern; 074 * {@code null} if the argument is {@code null} or doesn't 075 * match. 076 */ 077 public String getPropertyName(String method) { 078 String name = null; 079 080 if (method != null) { 081 Matcher matcher = pattern().matcher(method); 082 083 if (matcher.matches()) { 084 name = decapitalize(matcher.group(1)); 085 } 086 } 087 088 return name; 089 } 090 091 private Pattern pattern() { 092 if (pattern == null) { 093 pattern = 094 Pattern.compile(Pattern.quote(name().toLowerCase()) 095 + PROPERTY_REGEX); 096 } 097 098 return pattern; 099 } 100 101 /** 102 * Static method to get a property name from a {@link Method} name. 103 * (This method does not check return type or parameter types.) 104 * 105 * @param method The {@link Method}. 106 * 107 * @return The property name if method name matches the pattern; 108 * {@code null} if the argument is {@code null} or the name 109 * doesn't match. 110 */ 111 public static String getPropertyName(Method method) { 112 String name = null; 113 114 if (method != null) { 115 for (PropertyMethodEnum methodEnum : values()) { 116 name = methodEnum.getPropertyName(method.getName()); 117 118 if (name != null) { 119 break; 120 } 121 } 122 } 123 124 return name; 125 } 126 127 private static class MethodPrototypeMap 128 extends EnumMap<PropertyMethodEnum,Method> { 129 private static final long serialVersionUID = 6408568606272721794L; 130 131 public MethodPrototypeMap() { 132 super(PropertyMethodEnum.class); 133 134 for (Method method : Prototypes.class.getDeclaredMethods()) { 135 put(PropertyMethodEnum.valueOf(method.getName()), method); 136 } 137 } 138 139 public interface Prototypes<T> { 140 public T GET(); 141 public boolean IS(); 142 public void SET(T value); 143 } 144 } 145}