1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.asteriskjava.manager.internal;
18
19 import org.asteriskjava.AsteriskVersion;
20 import org.asteriskjava.manager.AsteriskMapping;
21 import org.asteriskjava.manager.action.ManagerAction;
22 import org.asteriskjava.manager.action.UserEventAction;
23 import org.asteriskjava.manager.event.UserEvent;
24 import org.asteriskjava.util.Log;
25 import org.asteriskjava.util.LogFactory;
26 import org.asteriskjava.util.ReflectionUtil;
27
28 import java.lang.reflect.Field;
29 import java.lang.reflect.Method;
30 import java.util.*;
31
32
33
34
35
36
37
38 class ActionBuilderImpl implements ActionBuilder
39 {
40 private static final String LINE_SEPARATOR = "\r\n";
41 private static final String ATTRIBUTES_PROPERTY_NAME = "attributes";
42
43
44
45
46 private final Log logger = LogFactory.getLog(getClass());
47 private AsteriskVersion targetVersion;
48
49
50
51
52 ActionBuilderImpl()
53 {
54 this.targetVersion = AsteriskVersion.ASTERISK_1_0;
55 }
56
57 public void setTargetVersion(AsteriskVersion targetVersion)
58 {
59 this.targetVersion = targetVersion;
60 }
61
62 public String buildAction(final ManagerAction action)
63 {
64 return buildAction(action, null);
65 }
66
67 @SuppressWarnings("unchecked")
68 public String buildAction(final ManagerAction action, final String internalActionId)
69 {
70 StringBuffer sb = new StringBuffer();
71
72 sb.append("action: ");
73 sb.append(action.getAction());
74 sb.append(LINE_SEPARATOR);
75 if (internalActionId != null)
76 {
77 sb.append("actionid: ");
78 sb.append(ManagerUtil.addInternalActionId(action.getActionId(), internalActionId));
79 sb.append(LINE_SEPARATOR);
80 }
81 else if (action.getActionId() != null)
82 {
83 sb.append("actionid: ");
84 sb.append(action.getActionId());
85 sb.append(LINE_SEPARATOR);
86 }
87
88
89
90
91
92 Set<String> ignore = new HashSet<String>();
93 ignore.add("class");
94 ignore.add("action");
95 ignore.add("actionid");
96 ignore.add(ATTRIBUTES_PROPERTY_NAME);
97
98
99
100 if (action instanceof UserEventAction)
101 {
102 UserEvent userEvent = ((UserEventAction) action).getUserEvent();
103 appendUserEvent(sb, userEvent);
104
105
106
107 appendGetters(sb, userEvent, ignore);
108 }
109 else
110 {
111 appendGetters(sb, action, ignore);
112 }
113
114
115
116 Map<String, Method> getters = ReflectionUtil.getGetters(action.getClass());
117
118 if(getters.containsKey(ATTRIBUTES_PROPERTY_NAME))
119 {
120 Method getter = getters.get(ATTRIBUTES_PROPERTY_NAME);
121 Object value = null;
122 try
123 {
124 value = getter.invoke(action);
125 }
126 catch (Exception ex)
127 {
128 logger.error("Unable to retrieve property '" + ATTRIBUTES_PROPERTY_NAME + "' of " + action.getClass(), ex);
129 }
130
131 if(value instanceof Map)
132 {
133 Map<Object,Object> attributes = (Map<Object, Object>)value;
134 for (Map.Entry<Object, Object> entry : attributes.entrySet())
135 {
136 appendString(sb, entry.getKey() == null ? "null" : entry.getKey().toString(),
137 entry.getValue() == null ? "null" : entry.getValue().toString());
138 }
139 }
140 }
141
142 sb.append(LINE_SEPARATOR);
143 return sb.toString();
144 }
145
146 private void appendMap(StringBuffer sb, String key, Map<String, String> values)
147 {
148 String singularKey;
149
150
151 if (key.endsWith("s"))
152 {
153 singularKey = key.substring(0, key.length() - 1);
154 }
155 else
156 {
157 singularKey = key;
158 }
159
160 if (targetVersion.isAtLeast(AsteriskVersion.ASTERISK_1_2))
161 {
162 appendMap12(sb, singularKey, values);
163 }
164 else
165 {
166 appendMap10(sb, singularKey, values);
167 }
168 }
169
170 private void appendMap10(StringBuffer sb, String singularKey, Map<String, String> values)
171 {
172 Iterator<Map.Entry<String, String>> entryIterator;
173
174 sb.append(singularKey);
175 sb.append(": ");
176 entryIterator = values.entrySet().iterator();
177 while (entryIterator.hasNext())
178 {
179 Map.Entry<String, String> entry;
180
181 entry = entryIterator.next();
182 sb.append(entry.getKey());
183 sb.append("=");
184 if (entry.getValue() != null)
185 {
186 sb.append(entry.getValue());
187 }
188
189 if (entryIterator.hasNext())
190 {
191 sb.append("|");
192 }
193 }
194 sb.append(LINE_SEPARATOR);
195 }
196
197 private void appendMap12(StringBuffer sb, String singularKey, Map<String, String> values)
198 {
199 for (Map.Entry<String, String> entry : values.entrySet())
200 {
201 sb.append(singularKey);
202 sb.append(": ");
203 sb.append(entry.getKey());
204 sb.append("=");
205 if (entry.getValue() != null)
206 {
207 sb.append(entry.getValue());
208 }
209
210 sb.append(LINE_SEPARATOR);
211 }
212 }
213
214 private void appendString(StringBuffer sb, String key, String value)
215 {
216 sb.append(key);
217 sb.append(": ");
218 sb.append(value);
219 sb.append(LINE_SEPARATOR);
220 }
221
222 private void appendUserEvent(StringBuffer sb, UserEvent event)
223 {
224 Class<?> clazz = event.getClass();
225
226 String className = clazz.getName();
227 String eventType = className.substring(className.lastIndexOf('.') + 1).toLowerCase(Locale.ENGLISH);
228
229 if (eventType.endsWith("event"))
230 {
231 eventType = eventType.substring(0, eventType.length() - "event".length());
232 }
233
234 appendString(sb, "UserEvent", eventType);
235 }
236
237 @SuppressWarnings("unchecked")
238 private void appendGetters(StringBuffer sb, Object action, Set<String> membersToIgnore)
239 {
240 Map<String, Method> getters = ReflectionUtil.getGetters(action.getClass());
241 for (Map.Entry<String, Method> entry : getters.entrySet())
242 {
243 final String name = entry.getKey();
244 final Method getter = entry.getValue();
245 final Object value;
246
247 if (membersToIgnore.contains(name))
248 {
249 continue;
250 }
251
252 try
253 {
254 value = getter.invoke(action);
255 }
256 catch (Exception ex)
257 {
258 logger.error("Unable to retrieve property '" + name + "' of " + action.getClass(), ex);
259 continue;
260 }
261
262 if (value == null || value instanceof Class)
263 {
264 continue;
265 }
266
267 final String mappedName = mapToAsterisk(getter);
268 if (value instanceof Map)
269 {
270 appendMap(sb, mappedName, (Map<String, String>) value);
271 }
272 else if (value instanceof String)
273 {
274 appendString(sb, mappedName, (String) value);
275 }
276 else
277 {
278 appendString(sb, mappedName, value.toString());
279 }
280 }
281 }
282
283 private String mapToAsterisk(Method getter)
284 {
285 AsteriskMapping annotation;
286
287
288 annotation = getter.getAnnotation(AsteriskMapping.class);
289 if (annotation != null)
290 {
291 return annotation.value();
292 }
293
294
295 String setterName = determineSetterName(getter.getName());
296 try
297 {
298 Method setter = getter.getDeclaringClass().getDeclaredMethod(setterName, getter.getReturnType());
299 annotation = setter.getAnnotation(AsteriskMapping.class);
300 if (annotation != null)
301 {
302 return annotation.value();
303 }
304 }
305 catch (NoSuchMethodException e)
306 {
307
308 }
309
310
311 String fieldName = determineFieldName(getter.getName());
312 try
313 {
314 Field field = getter.getDeclaringClass().getDeclaredField(fieldName);
315 annotation = field.getAnnotation(AsteriskMapping.class);
316 if (annotation != null)
317 {
318 return annotation.value();
319 }
320 }
321 catch (NoSuchFieldException e)
322 {
323
324 }
325
326 return fieldName.toLowerCase(Locale.US);
327 }
328
329 String determineSetterName(String getterName)
330 {
331 if (getterName.startsWith("get"))
332 {
333 return "set" + getterName.substring(3);
334 }
335 else if (getterName.startsWith("is"))
336 {
337 return "set" + getterName.substring(2);
338 }
339 else
340 {
341 throw new IllegalArgumentException("Getter '" + getterName + "' doesn't start with either 'get' or 'is'");
342 }
343 }
344
345 String determineFieldName(String accessorName)
346 {
347 if (accessorName.startsWith("get"))
348 {
349 return lcFirst(accessorName.substring(3));
350 }
351 else if (accessorName.startsWith("is"))
352 {
353 return lcFirst(accessorName.substring(2));
354 }
355 else if (accessorName.startsWith("set"))
356 {
357 return lcFirst(accessorName.substring(3));
358 }
359 else
360 {
361 throw new IllegalArgumentException("Accessor '" + accessorName + "' doesn't start with either 'get', 'is' or 'set'");
362 }
363 }
364
365
366
367
368
369
370
371 String lcFirst(String s)
372 {
373 if (s == null || s.length() < 1)
374 {
375 return s;
376 }
377
378 char first = s.charAt(0);
379 return Character.toLowerCase(first) + s.substring(1);
380 }
381 }