1 package org.apache.velocity.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.reflect.Array;
23 import java.lang.reflect.Method;
24 import java.lang.reflect.Modifier;
25 import java.math.BigDecimal;
26 import java.util.Map;
27 import java.util.HashMap;
28
29
30
31
32
33
34
35
36 public class DuckType
37 {
38 protected enum Types
39 {
40 STRING("getAsString"),
41 NUMBER("getAsNumber"),
42 BOOLEAN("getAsBoolean"),
43 EMPTY("isEmpty");
44
45 final String name;
46 final Map<Class,Object> cache = new HashMap();
47
48 Types(String name)
49 {
50 this.name = name;
51 }
52
53 void set(Class c, Object o)
54 {
55 cache.put(c, o);
56 }
57
58 Object get(Class c)
59 {
60 return cache.get(c);
61 }
62 }
63
64 protected static final Object NO_METHOD = new Object();
65
66 public static String asString(Object value)
67 {
68 return asString(value, true);
69 }
70
71 public static String asString(Object value, boolean coerceType)
72 {
73 if (value == null)
74 {
75 return null;
76 }
77 if (value instanceof String)
78 {
79 return (String)value;
80 }
81 Object got = get(value, Types.STRING);
82 if (got == NO_METHOD)
83 {
84 return coerceType ? value.toString() : null;
85 }
86 return (String)got;
87 }
88
89 public static boolean asNull(Object value)
90 {
91 if (value == null ||
92 get(value, Types.STRING) == null ||
93 get(value, Types.NUMBER) == null)
94 {
95 return true;
96 }
97 return false;
98 }
99
100 public static boolean asBoolean(Object value)
101 {
102 return asBoolean(value, true);
103 }
104
105 public static boolean asBoolean(Object value, boolean coerceType)
106 {
107 if (value == null)
108 {
109 return false;
110 }
111 if (value instanceof Boolean)
112 {
113 return ((Boolean)value).booleanValue();
114 }
115 Object got = get(value, Types.BOOLEAN);
116 if (got != NO_METHOD)
117 {
118 return ((Boolean)got).booleanValue();
119 }
120 if (coerceType)
121 {
122 return !asEmpty(value);
123 }
124 return true;
125 }
126
127
128 public static boolean asEmpty(Object value)
129 {
130
131 if (value == null)
132 {
133 return true;
134 }
135
136
137 if (value instanceof CharSequence)
138 {
139 return ((CharSequence)value).length() == 0;
140 }
141
142
143 Object isEmpty = get(value, Types.EMPTY);
144 if (isEmpty != NO_METHOD)
145 {
146 return (Boolean)isEmpty;
147 }
148
149
150 if (value.getClass().isArray())
151 {
152 return Array.getLength(value) == 0;
153 }
154
155
156 Object asString = get(value, Types.STRING);
157 if (asString == null)
158 {
159 return true;
160 }
161
162 else if (asString != NO_METHOD)
163 {
164 return ((String)asString).length() == 0;
165 }
166
167
168 Object asNumber = get(value, Types.NUMBER);
169 if (asNumber == null)
170 {
171 return true;
172 }
173
174
175 String string = value.toString();
176 return string == null || string.length() == 0;
177 }
178
179 public static Number asNumber(Object value)
180 {
181 return asNumber(value, true);
182 }
183
184 public static Number asNumber(Object value, boolean coerceType)
185 {
186 if (value == null)
187 {
188 return null;
189 }
190 if (value instanceof Number)
191 {
192 return (Number)value;
193 }
194 Object got = get(value, Types.NUMBER);
195 if (got != NO_METHOD)
196 {
197 return (Number)got;
198 }
199 if (coerceType)
200 {
201 String string = asString(value);
202 if (string != null)
203 {
204 return new BigDecimal(string);
205 }
206 }
207 return null;
208 }
209
210 protected static Object get(Object value, Types type)
211 {
212 try
213 {
214
215 Class c = value.getClass();
216 Object cached = type.get(c);
217 if (cached == NO_METHOD)
218 {
219 return cached;
220 }
221 if (cached != null)
222 {
223 return ((Method)cached).invoke(value);
224 }
225
226 Method method = findMethod(c, type);
227 if (method == null)
228 {
229 type.set(c, NO_METHOD);
230 return NO_METHOD;
231 }
232 type.set(c, method);
233 return method.invoke(value);
234 }
235 catch (RuntimeException re)
236 {
237 throw re;
238 }
239 catch (Exception e)
240 {
241 throw new RuntimeException(e);
242 }
243 }
244
245 protected static Method findMethod(Class c, Types type)
246 {
247 if (c == null || c == Object.class)
248 {
249 return null;
250 }
251 Method m = getMethod(c, type.name);
252 if (m != null)
253 {
254 return m;
255 }
256 for (Class i : c.getInterfaces())
257 {
258 m = findMethod(i, type);
259 if (m != null)
260 {
261 return m;
262 }
263 }
264 m = findMethod(c.getSuperclass(), type);
265 if (m != null)
266 {
267 return m;
268 }
269 return null;
270 }
271
272 private static Method getMethod(Class c, String name)
273 {
274 if (Modifier.isPublic(c.getModifiers()))
275 {
276 try
277 {
278 Method m = c.getDeclaredMethod(name);
279 if (Modifier.isPublic(m.getModifiers()))
280 {
281 return m;
282 }
283 }
284 catch (NoSuchMethodException nsme) {}
285 }
286 return null;
287 }
288
289 }