1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jadira.bindings.core.general.unmarshaller;
17
18 import java.lang.invoke.MethodHandle;
19 import java.lang.invoke.MethodHandles;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Modifier;
22
23 import org.jadira.bindings.core.api.BindingException;
24 import org.jadira.bindings.core.api.FromUnmarshaller;
25
26
27
28
29
30
31
32
33
34
35
36 public final class MethodFromUnmarshaller<S, T> implements FromUnmarshaller<S, T> {
37
38 private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
39
40 private final MethodHandle unmarshalHandle;
41
42 private final Class<S> boundClass;
43
44 private final Class<T> targetClass;
45
46
47
48
49
50
51 public MethodFromUnmarshaller(Class<S> boundClass, Method unmarshal) {
52
53 this.boundClass = boundClass;
54
55 if (unmarshal.getParameterTypes().length != 1) {
56 throw new IllegalStateException("unmarshal method must define a single parameter");
57 }
58 if (!Modifier.isStatic(unmarshal.getModifiers())) {
59 throw new IllegalStateException("unmarshal method must be defined as static");
60 }
61 if (!boundClass.isAssignableFrom(unmarshal.getReturnType())) {
62 throw new IllegalStateException("unmarshal method must return " + boundClass.getSimpleName());
63 }
64
65 try {
66 this.unmarshalHandle = LOOKUP.unreflect(unmarshal);
67 } catch (IllegalAccessException e) {
68 throw new IllegalStateException("Method is not accessible" + unmarshal);
69 }
70
71 @SuppressWarnings("unchecked")
72 Class<T> myTarget = (Class<T>)unmarshal.getParameterTypes()[0];
73 this.targetClass = myTarget;
74 }
75
76
77
78
79
80 public S unmarshal(T object) {
81
82 if (object != null && !targetClass.isAssignableFrom(object.getClass())) {
83 throw new IllegalArgumentException("Supplied object was not instance of target class");
84 }
85
86 try {
87 return getBoundClass().cast(unmarshalHandle.invoke(object));
88 } catch (Throwable ex) {
89 if (ex.getCause() instanceof RuntimeException) {
90 throw (RuntimeException) ex.getCause();
91 }
92 throw new BindingException(ex.getMessage(), ex.getCause());
93 }
94 }
95
96
97
98
99
100 public Class<S> getBoundClass() {
101 return boundClass;
102 }
103
104
105
106
107
108 public Class<T> getTargetClass() {
109 return targetClass;
110 }
111 }