1
2
3
4 package net.sourceforge.pmd.lang.rule.properties;
5
6 import java.lang.reflect.Array;
7 import java.lang.reflect.Method;
8 import java.util.Map;
9
10 import net.sourceforge.pmd.PropertyDescriptorFactory;
11 import net.sourceforge.pmd.lang.rule.properties.factories.BasicPropertyDescriptorFactory;
12 import net.sourceforge.pmd.util.ClassUtil;
13 import net.sourceforge.pmd.util.StringUtil;
14
15
16
17
18
19
20
21
22
23
24
25 public class MethodProperty extends AbstractPackagedProperty<Method> {
26
27 public static final char CLASS_METHOD_DELIMITER = '#';
28 public static final char METHOD_ARG_DELIMITER = ',';
29 public static final char[] METHOD_GROUP_DELIMITERS = new char[] { '(', ')' };
30
31 private static final String ARRAY_FLAG = "[]";
32 private static final Map<Class<?>, String> TYPE_SHORTCUTS = ClassUtil.getClassShortNames();
33
34 public static final PropertyDescriptorFactory FACTORY = new BasicPropertyDescriptorFactory<MethodProperty>(
35 Method.class, PACKAGED_FIELD_TYPES_BY_KEY) {
36
37 public MethodProperty createWith(Map<String, String> valuesById) {
38 char delimiter = delimiterIn(valuesById);
39 return new MethodProperty(nameIn(valuesById), descriptionIn(valuesById), defaultValueIn(valuesById),
40 legalPackageNamesIn(valuesById, delimiter), 0f);
41 }
42 };
43
44
45
46
47
48 private static String shortestNameFor(Class<?> cls) {
49 String compactName = TYPE_SHORTCUTS.get(cls);
50 return compactName == null ? cls.getName() : compactName;
51 }
52
53
54
55
56
57
58
59
60 public static String asStringFor(Method method) {
61 StringBuilder sb = new StringBuilder();
62 asStringOn(method, sb);
63 return sb.toString();
64 }
65
66
67
68
69 protected String defaultAsString() {
70 return asStringFor(defaultValue());
71 }
72
73
74
75
76
77 private static void serializedTypeIdOn(Class<?> type, StringBuilder sb) {
78
79 Class<?> arrayType = type.getComponentType();
80 if (arrayType == null) {
81 sb.append(shortestNameFor(type));
82 return;
83 }
84 sb.append(shortestNameFor(arrayType)).append(ARRAY_FLAG);
85 }
86
87
88
89
90
91
92
93 public static void asStringOn(Method method, StringBuilder sb) {
94
95 Class<?> clazz = method.getDeclaringClass();
96
97 sb.append(shortestNameFor(clazz));
98 sb.append(CLASS_METHOD_DELIMITER);
99 sb.append(method.getName());
100
101 sb.append(METHOD_GROUP_DELIMITERS[0]);
102
103 Class<?>[] argTypes = method.getParameterTypes();
104 if (argTypes.length == 0) {
105 sb.append(METHOD_GROUP_DELIMITERS[1]);
106 return;
107 }
108
109 serializedTypeIdOn(argTypes[0], sb);
110 for (int i = 1; i < argTypes.length; i++) {
111 sb.append(METHOD_ARG_DELIMITER);
112 serializedTypeIdOn(argTypes[i], sb);
113 }
114 sb.append(METHOD_GROUP_DELIMITERS[1]);
115 }
116
117
118
119
120
121 private static Class<?> typeFor(String typeName) {
122
123 Class<?> type = null;
124
125 if (typeName.endsWith(ARRAY_FLAG)) {
126 String arrayTypeName = typeName.substring(0, typeName.length() - ARRAY_FLAG.length());
127 type = typeFor(arrayTypeName);
128 return Array.newInstance(type, 0).getClass();
129
130
131 }
132
133 type = ClassUtil.getTypeFor(typeName);
134 if (type != null) {
135 return type;
136 }
137
138 try {
139 return Class.forName(typeName);
140 } catch (Exception ex) {
141 return null;
142 }
143 }
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166 public static Method methodFrom(String methodNameAndArgTypes, char classMethodDelimiter, char methodArgDelimiter) {
167
168
169
170
171 int delimPos0 = -1;
172 if (methodNameAndArgTypes != null) {
173 delimPos0 = methodNameAndArgTypes.indexOf(classMethodDelimiter);
174 } else {
175 return null;
176 }
177
178 if (delimPos0 < 0) {
179 return null;
180 }
181
182 String className = methodNameAndArgTypes.substring(0, delimPos0);
183 Class<?> type = ClassUtil.getTypeFor(className);
184 if (type == null) {
185 return null;
186 }
187
188 int delimPos1 = methodNameAndArgTypes.indexOf(METHOD_GROUP_DELIMITERS[0]);
189 if (delimPos1 < 0) {
190 String methodName = methodNameAndArgTypes.substring(delimPos0 + 1);
191 return ClassUtil.methodFor(type, methodName, ClassUtil.EMPTY_CLASS_ARRAY);
192 }
193
194 String methodName = methodNameAndArgTypes.substring(delimPos0 + 1, delimPos1);
195 if (StringUtil.isEmpty(methodName)) {
196 return null;
197 }
198
199 int delimPos2 = methodNameAndArgTypes.indexOf(METHOD_GROUP_DELIMITERS[1]);
200 if (delimPos2 < 0) {
201 return null;
202 }
203
204 String argTypesStr = methodNameAndArgTypes.substring(delimPos1 + 1, delimPos2);
205 if (StringUtil.isEmpty(argTypesStr)) {
206 return ClassUtil.methodFor(type, methodName, ClassUtil.EMPTY_CLASS_ARRAY);
207 }
208
209 String[] argTypeNames = StringUtil.substringsOf(argTypesStr, methodArgDelimiter);
210 Class<?>[] argTypes = new Class[argTypeNames.length];
211 for (int i = 0; i < argTypes.length; i++) {
212 argTypes[i] = typeFor(argTypeNames[i]);
213 }
214
215 return ClassUtil.methodFor(type, methodName, argTypes);
216 }
217
218
219
220
221
222 public static Method methodFrom(String methodStr) {
223 return methodFrom(methodStr, CLASS_METHOD_DELIMITER, METHOD_ARG_DELIMITER);
224 }
225
226
227
228
229
230
231
232
233
234
235
236 public MethodProperty(String theName, String theDescription, Method theDefault, String[] legalPackageNames,
237 float theUIOrder) {
238 super(theName, theDescription, theDefault, legalPackageNames, theUIOrder);
239 }
240
241
242
243
244
245
246
247
248
249
250
251 public MethodProperty(String theName, String theDescription, String defaultMethodStr, String[] legalPackageNames,
252 float theUIOrder) {
253 super(theName, theDescription, methodFrom(defaultMethodStr), legalPackageNames, theUIOrder);
254 }
255
256
257
258
259
260
261
262
263
264
265
266 public MethodProperty(String theName, String theDescription, String defaultMethodStr,
267 Map<String, String> otherParams, float theUIOrder) {
268 this(theName, theDescription, methodFrom(defaultMethodStr), packageNamesIn(otherParams), theUIOrder);
269 }
270
271
272
273
274
275
276
277
278 @Override
279 protected String asString(Object value) {
280 return value == null ? "" : asStringFor((Method) value);
281 }
282
283
284
285
286
287 @Override
288 protected String packageNameOf(Object item) {
289
290 final Method method = (Method) item;
291 return method.getDeclaringClass().getName() + '.' + method.getName();
292 }
293
294
295
296
297 @Override
298 protected String itemTypeName() {
299 return "method";
300 }
301
302
303
304
305
306 public Class<Method> type() {
307 return Method.class;
308 }
309
310
311
312
313
314
315
316 public Method valueFrom(String valueString) throws IllegalArgumentException {
317 return methodFrom(valueString);
318 }
319 }