1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
package org.apache.johnzon.mapper.access; |
20 | |
|
21 | |
import org.apache.johnzon.mapper.JohnzonProperty; |
22 | |
import org.apache.johnzon.mapper.MapperException; |
23 | |
|
24 | |
import java.beans.IntrospectionException; |
25 | |
import java.beans.Introspector; |
26 | |
import java.beans.PropertyDescriptor; |
27 | |
import java.lang.annotation.Annotation; |
28 | |
import java.lang.reflect.Method; |
29 | |
import java.lang.reflect.Type; |
30 | |
import java.util.Collection; |
31 | |
import java.util.HashMap; |
32 | |
import java.util.Map; |
33 | |
|
34 | |
public class MethodAccessMode implements AccessMode { |
35 | |
private final boolean supportGetterAsWritter; |
36 | |
|
37 | 64 | public MethodAccessMode(final boolean supportGetterAsWritter) { |
38 | 64 | this.supportGetterAsWritter = supportGetterAsWritter; |
39 | 64 | } |
40 | |
|
41 | |
@Override |
42 | |
public Map<String, Reader> findReaders(final Class<?> clazz) { |
43 | 47 | final Map<String, Reader> readers = new HashMap<String, Reader>(); |
44 | 47 | final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz); |
45 | 275 | for (final PropertyDescriptor descriptor : propertyDescriptors) { |
46 | 228 | final Method readMethod = descriptor.getReadMethod(); |
47 | 228 | if (readMethod != null && readMethod.getDeclaringClass() != Object.class) { |
48 | 180 | if (isIgnored(descriptor.getName())) { |
49 | 0 | continue; |
50 | |
} |
51 | 180 | readers.put(extractKey(descriptor), new MethodReader(readMethod)); |
52 | |
} |
53 | |
} |
54 | 47 | return readers; |
55 | |
} |
56 | |
|
57 | |
@Override |
58 | |
public Map<String, Writer> findWriters(final Class<?> clazz) { |
59 | 47 | final Map<String, Writer> writers = new HashMap<String, Writer>(); |
60 | 47 | final PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz); |
61 | 275 | for (final PropertyDescriptor descriptor : propertyDescriptors) { |
62 | 228 | if (descriptor.getPropertyType() == Class.class || isIgnored(descriptor.getName())) { |
63 | 0 | continue; |
64 | |
} |
65 | 181 | final Method writeMethod = descriptor.getWriteMethod(); |
66 | 181 | if (writeMethod != null) { |
67 | 173 | writers.put(extractKey(descriptor), new MethodWriter(writeMethod)); |
68 | 8 | } else if (supportGetterAsWritter |
69 | |
&& Collection.class.isAssignableFrom(descriptor.getPropertyType()) |
70 | |
&& descriptor.getReadMethod() != null) { |
71 | 1 | writers.put(extractKey(descriptor), new MethodGetterAsWriter(descriptor.getReadMethod())); |
72 | |
} |
73 | |
} |
74 | 47 | return writers; |
75 | |
} |
76 | |
|
77 | |
private String extractKey(final PropertyDescriptor f) { |
78 | 354 | final JohnzonProperty property = f.getReadMethod() == null ? null : f.getReadMethod().getAnnotation(JohnzonProperty.class); |
79 | 354 | return property != null ? property.value() : f.getName(); |
80 | |
} |
81 | |
|
82 | |
protected boolean isIgnored(final String name) { |
83 | 361 | return name.equals("metaClass") || name.contains("$"); |
84 | |
} |
85 | |
|
86 | |
private PropertyDescriptor[] getPropertyDescriptors(final Class<?> clazz) { |
87 | |
final PropertyDescriptor[] propertyDescriptors; |
88 | |
try { |
89 | 94 | propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); |
90 | 0 | } catch (final IntrospectionException e) { |
91 | 0 | throw new IllegalStateException(e); |
92 | 94 | } |
93 | 94 | return propertyDescriptors; |
94 | |
} |
95 | |
|
96 | |
protected static abstract class MethodDecoratedType implements DecoratedType { |
97 | |
protected final Method method; |
98 | |
|
99 | 354 | public MethodDecoratedType(final Method method) { |
100 | 354 | this.method = method; |
101 | 354 | if (!method.isAccessible()) { |
102 | 101 | method.setAccessible(true); |
103 | |
} |
104 | 354 | } |
105 | |
|
106 | |
@Override |
107 | |
public <T extends Annotation> T getAnnotation(final Class<T> clazz) { |
108 | 712 | return method.getAnnotation(clazz); |
109 | |
} |
110 | |
} |
111 | |
|
112 | 348 | public static class MethodWriter extends MethodDecoratedType implements Writer { |
113 | |
public MethodWriter(final Method method) { |
114 | 173 | super(method); |
115 | 173 | } |
116 | |
|
117 | |
@Override |
118 | |
public Type getType() { |
119 | 173 | return method.getGenericParameterTypes()[0]; |
120 | |
} |
121 | |
|
122 | |
@Override |
123 | |
public void write(final Object instance, final Object value) { |
124 | |
try { |
125 | 129 | method.invoke(instance, value); |
126 | 0 | } catch (final Exception e) { |
127 | 0 | throw new MapperException(e); |
128 | 129 | } |
129 | 129 | } |
130 | |
} |
131 | |
|
132 | 364 | public static class MethodReader extends MethodDecoratedType implements Reader { |
133 | |
public MethodReader(final Method method) { |
134 | 181 | super(method); |
135 | 181 | } |
136 | |
|
137 | |
@Override |
138 | |
public Type getType() { |
139 | 541 | return method.getGenericReturnType(); |
140 | |
} |
141 | |
|
142 | |
@Override |
143 | |
public Object read(final Object instance) { |
144 | |
try { |
145 | 157 | return method.invoke(instance); |
146 | 0 | } catch (final Exception e) { |
147 | 0 | throw new MapperException(e); |
148 | |
} |
149 | |
} |
150 | |
} |
151 | |
|
152 | |
private class MethodGetterAsWriter extends MethodReader implements Writer { |
153 | 1 | public MethodGetterAsWriter(final Method readMethod) { |
154 | 1 | super(readMethod); |
155 | 1 | } |
156 | |
|
157 | |
@Override |
158 | |
public void write(final Object instance, final Object value) { |
159 | 1 | if (value != null) { |
160 | |
try { |
161 | 1 | final Collection<?> collection = Collection.class.cast(method.invoke(instance)); |
162 | 1 | if (collection != null) { |
163 | 1 | collection.addAll(Collection.class.cast(value)); |
164 | |
} |
165 | 0 | } catch (final Exception e) { |
166 | 0 | throw new MapperException(e); |
167 | 1 | } |
168 | |
} |
169 | 1 | } |
170 | |
} |
171 | |
} |