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