|
2 | 2 |
|
3 | 3 | import java.lang.annotation.Annotation; |
4 | 4 | import java.lang.reflect.Array; |
| 5 | +import java.lang.reflect.Constructor; |
5 | 6 | import java.lang.reflect.Field; |
| 7 | +import java.lang.reflect.InvocationTargetException; |
| 8 | +import java.lang.reflect.ParameterizedType; |
6 | 9 | import java.math.BigDecimal; |
7 | 10 | import java.text.SimpleDateFormat; |
8 | 11 | import java.util.*; |
9 | 12 |
|
| 13 | +import play.Logger; |
10 | 14 | import play.Play; |
| 15 | +import play.exceptions.UnexpectedException; |
11 | 16 | import play.libs.I18N; |
12 | 17 |
|
13 | 18 | /** |
@@ -149,7 +154,24 @@ private static void unBind(Map<String, Object> result, Object src, Class<?> srcC |
149 | 154 | result.putAll(r); |
150 | 155 | return; |
151 | 156 | } |
152 | | - |
| 157 | + |
| 158 | + // application custom types have higher priority. If unable to bind proceed with the next one |
| 159 | + for (Class<TypeUnbinder<?>> c : Play.classloader.getAssignableClasses(TypeUnbinder.class)) { |
| 160 | + if (c.isAnnotationPresent(Global.class)) { |
| 161 | + Class<?> forType = (Class<?>) ((ParameterizedType) c.getGenericInterfaces()[0]).getActualTypeArguments()[0]; |
| 162 | + if (forType.isAssignableFrom(srcClazz)) { |
| 163 | + try { |
| 164 | + boolean _r = createNewInstance(c).unBind(result, src, srcClazz, name, annotations); |
| 165 | + if (_r) { |
| 166 | + return; |
| 167 | + } |
| 168 | + } catch (Exception e) { |
| 169 | + // ... |
| 170 | + } |
| 171 | + } |
| 172 | + } |
| 173 | + } |
| 174 | + |
153 | 175 | if (isDirect(srcClazz) || src == null) { |
154 | 176 | directUnbind(result, src, srcClazz, name, annotations); |
155 | 177 | }else if (src.getClass().isArray()) { |
@@ -198,4 +220,18 @@ private static void unBind(Map<String, Object> result, Object src, Class<?> srcC |
198 | 220 | public static boolean isDirect(Class<?> clazz) { |
199 | 221 | return clazz.equals(String.class) || clazz.equals(Integer.class) || Enum.class.isAssignableFrom(clazz) || clazz.equals(Boolean.class) || clazz.equals(Long.class) || clazz.equals(Double.class) || clazz.equals(Float.class) || clazz.equals(Short.class) || clazz.equals(BigDecimal.class) || clazz.isPrimitive() || clazz.equals(Class.class); |
200 | 222 | } |
| 223 | + |
| 224 | + private static <T> T createNewInstance(Class<T> clazz) { |
| 225 | + try { |
| 226 | + Constructor<T> constructor = clazz.getDeclaredConstructor(); |
| 227 | + constructor.setAccessible(true); |
| 228 | + return constructor.newInstance(); |
| 229 | + } catch (InstantiationException | IllegalAccessException e) { |
| 230 | + Logger.warn("Failed to create instance of %s: %s", clazz.getName(), e); |
| 231 | + throw new UnexpectedException(e); |
| 232 | + } catch (NoSuchMethodException | InvocationTargetException e) { |
| 233 | + Logger.error("Failed to create instance of %s: %s", clazz.getName(), e); |
| 234 | + throw new UnexpectedException(e); |
| 235 | + } |
| 236 | + } |
201 | 237 | } |
0 commit comments