1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.ochafik.lang.reflect;
20
21
22
23
24 import java.lang.reflect.Field;
25 import java.lang.reflect.Method;
26 import java.lang.reflect.Type;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.regex.Pattern;
31
32 import com.ochafik.util.string.RegexUtils;
33 import com.ochafik.util.string.StringUtils;
34
35 public class GettersAndSettersHelper {
36 public static class GetterAndSetterInfo {
37 public Method getter;
38 public Method setter;
39
40 public String fieldName;
41 public boolean isFull() {
42 return getter != null && setter != null;
43 }
44 public Class<?> elementType;
45 public GetterAndSetterInfo(String fieldName, Class<?> elementType, Method getter, Method setter, Field field) {
46 this.elementType = elementType;
47 this.fieldName = fieldName;
48 this.getter = getter;
49 this.setter = setter;
50
51 }
52 public GetterAndSetterInfo() {}
53 public boolean isConsistent() {
54 if (getter == null || setter == null)
55 return true;
56
57 Class<?>[] pts = setter.getParameterTypes();
58 return pts.length == 1 && pts[0].isAssignableFrom(getter.getReturnType());
59 }
60 }
61
62 public final Map<String, GetterAndSetterInfo> gettersAndSetters = new HashMap<String, GetterAndSetterInfo>();
63
64 static Pattern getterSetterPattern = Pattern.compile("(is|get|set)([A-Z]\\w+)");
65
66 public GettersAndSettersHelper(Class<?> type, FieldGetter fieldGetter) {
67 this.fieldGetter = fieldGetter;
68 for (Method method : type.getMethods()) {
69 int nParams = method.getParameterTypes().length;
70 if (nParams > 1)
71 continue;
72
73 String name = method.getName();
74 String match[] = RegexUtils.match(name, getterSetterPattern);
75 if (match != null) {
76 Class<?> returnType = method.getReturnType();
77 String fieldName = StringUtils.uncapitalize(match[2]);
78 boolean isGetter = !match[1].equals("set");
79 if (isGetter) {
80 if (nParams == 0) {
81 GetterAndSetterInfo getterAndSetter = getOrCreatePair(fieldName);
82 if (getterAndSetter.getter != null) {
83 if (getterAndSetter.getter.getReturnType().isAssignableFrom(returnType)) {
84
85 getterAndSetter.getter = method;
86 }
87 } else {
88 getterAndSetter.getter = method;
89 }
90
91 if (!getterAndSetter.isConsistent())
92 getterAndSetter.setter = null;
93
94 }
95
96
97 } else if (nParams == 1) {
98 GetterAndSetterInfo getterAndSetter = getOrCreatePair(fieldName);
99
100
101 getterAndSetter.setter = method;
102 if (!getterAndSetter.isConsistent())
103 getterAndSetter.setter = null;
104 }
105 }
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 }
124 final FieldGetter fieldGetter;
125 public interface FieldGetter {
126 public Field getField(Class<?> c, String name) throws SecurityException, NoSuchFieldException;
127 }
128 public Set<String> getFieldNames() {
129 return gettersAndSetters.keySet();
130 }
131 public Method getGetter(String fieldName) {
132 GetterAndSetterInfo pair = gettersAndSetters.get(fieldName);
133 return pair == null ? null : pair.getter;
134 }
135 public Method getSetter(String fieldName) {
136 GetterAndSetterInfo pair = gettersAndSetters.get(fieldName);
137 return pair == null ? null : pair.setter;
138 }
139 public Type getFieldType(String fieldName) {
140 GetterAndSetterInfo pair = gettersAndSetters.get(fieldName);
141 if (pair == null)
142 return null;
143 if (pair.getter != null)
144 return pair.getter.getGenericReturnType();
145 if (pair.setter != null)
146 return pair.setter.getGenericParameterTypes()[0];
147 return null;
148 }
149 public void assertConsistentPair(GetterAndSetterInfo p) {
150 if (p.getter != null && p.setter != null) {
151 Class<?> getType = p.getter.getReturnType(),
152 setType = p.setter.getParameterTypes()[0];
153
154
155 assert setType.isAssignableFrom(getType);
156 }
157 }
158 protected GetterAndSetterInfo getOrCreatePair(String fieldName) {
159 GetterAndSetterInfo getterAndSetter = gettersAndSetters.get(fieldName);
160 if (getterAndSetter == null)
161 gettersAndSetters.put(fieldName, getterAndSetter = new GetterAndSetterInfo());
162
163 return getterAndSetter;
164 }
165 }