1 package com.github.mygreen.supercsv.builder;
2
3 import java.lang.annotation.Annotation;
4 import java.lang.reflect.Field;
5 import java.util.ArrayList;
6 import java.util.Comparator;
7 import java.util.List;
8 import java.util.Objects;
9 import java.util.Optional;
10 import java.util.stream.Collectors;
11
12 import org.supercsv.exception.SuperCsvReflectionException;
13
14 import com.github.mygreen.supercsv.annotation.DefaultGroup;
15 import com.github.mygreen.supercsv.util.Utils;
16
17
18
19
20
21
22
23
24 public class FieldAccessor {
25
26
27
28
29 private final Field field;
30
31
32
33
34 private final String name;
35
36
37
38
39 private final Class<?> type;
40
41
42
43
44 private final List<ExpandedAnnotation> expandedAnnos = new ArrayList<>();
45
46
47
48
49
50
51
52 public FieldAccessor(final Field field, final Comparator<Annotation> comparator) {
53 Objects.requireNonNull(field);
54 Objects.requireNonNull(comparator);
55
56 field.setAccessible(true);
57
58 this.field = field;
59 this.type = field.getType();
60 this.name = field.getName();
61
62 final AnnotationExpanderotationExpander.html#AnnotationExpander">AnnotationExpander expander = new AnnotationExpander(comparator);
63 this.expandedAnnos.addAll(expander.expand(field.getAnnotations()));
64 }
65
66
67
68
69
70
71
72
73
74
75 public <A extends Annotation> Optional<A> getAnnotation(final Class<A> annoClass) {
76 Objects.requireNonNull(annoClass, "annoClass should not be null.");
77
78 return getAnnotationsByType(expandedAnnos, annoClass).stream()
79 .findFirst();
80
81 }
82
83
84
85
86
87
88
89
90
91
92 public <A extends Annotation> List<A> getAnnotations(final Class<A> annoClass) {
93 Objects.requireNonNull(annoClass, "annoClass should not be null.");
94
95 return getAnnotationsByType(expandedAnnos, annoClass);
96 }
97
98 @SuppressWarnings({"unchecked"})
99 private static <A extends Annotation> List<A> getAnnotationsByType(
100 final List<ExpandedAnnotation> expanedAnnos, final Class<A> annoClass) {
101
102 final List<A> list = new ArrayList<>();
103
104 for(ExpandedAnnotation anno : expanedAnnos) {
105
106 if(anno.isAnnotationType(annoClass)) {
107 list.add((A)anno.getOriginal());
108
109 } else if(anno.isComposed()) {
110
111 list.addAll(getAnnotationsByType(anno.getChilds(), annoClass));
112
113 }
114
115
116 }
117
118 return list;
119
120 }
121
122
123
124
125
126
127
128
129
130
131 public <A extends Annotation> boolean hasAnnotation(final Class<A> annoClass) {
132 return getAnnotation(annoClass).isPresent();
133 }
134
135
136
137
138
139
140
141
142
143
144 public <A extends Annotation> List<A> getAnnotationsByGroup(final Class<A> annoClass, final Class<?>... groups) {
145 Objects.requireNonNull(annoClass, "annoClass should not be null.");
146
147 return getAnnotations(annoClass).stream()
148 .filter(anno -> hasGroups(anno, groups))
149 .collect(Collectors.toList());
150
151 }
152
153
154
155
156
157
158
159
160
161 public <A extends Annotation> boolean hasAnnotationByGroup(final Class<A> annoClass, final Class<?>... groups) {
162
163 return getAnnotationsByGroup(annoClass, groups).size() > 0;
164
165 }
166
167
168
169
170
171
172
173
174 public List<Annotation> getAnnotationsByGroup(final Class<?>... groups) {
175
176 return getAnnotations(expandedAnnos).stream()
177 .filter(anno -> hasGroups(anno, groups))
178 .collect(Collectors.toList());
179
180 }
181
182 @SuppressWarnings({"unchecked"})
183 private static <A extends Annotation> List<A> getAnnotations(final List<ExpandedAnnotation> expanedAnnos) {
184
185 final List<A> list = new ArrayList<>();
186
187 for(ExpandedAnnotation anno : expanedAnnos) {
188 if(anno.isComposed()) {
189 list.addAll(getAnnotations(anno.getChilds()));
190
191 } else {
192 list.add((A)anno.getOriginal());
193
194 }
195 }
196
197 return list;
198
199 }
200
201
202
203
204
205
206
207
208 @SuppressWarnings("rawtypes")
209 private boolean hasGroups(final Annotation anno, final Class<?>... groups) {
210
211 final Optional<Class[]> targetGroups = Utils.getAnnotationAttribute(anno, "groups", Class[].class);
212
213 if(!targetGroups.isPresent()) {
214
215 return false;
216
217 }
218
219 if(groups.length == 0) {
220 if(targetGroups.get().length == 0) {
221
222 return true;
223
224 } else {
225 for(Class<?> targetGroup : targetGroups.get()) {
226 if(targetGroup.equals(DefaultGroup.class)) {
227
228 return true;
229 }
230 }
231 }
232
233 } else {
234
235 for(Class<?> group : groups) {
236
237 if(group.equals(DefaultGroup.class) && targetGroups.get().length == 0) {
238
239 return true;
240 }
241
242 for(Class<?> targetGroup : targetGroups.get()) {
243
244 if(targetGroup.equals(group)) {
245 return true;
246 }
247 }
248
249 }
250
251 }
252
253 return false;
254
255 }
256
257
258
259
260
261 public String getName() {
262 return name;
263 }
264
265
266
267
268
269 public String getNameWithClass() {
270 return getDeclaredClass().getName() + "#" + getName();
271 }
272
273
274
275
276
277 public Class<?> getType() {
278 return type;
279 }
280
281
282
283
284
285 public String getTypeName() {
286 return getType().getName();
287 }
288
289
290
291
292
293
294
295 public Class<?> getDeclaredClass() {
296 return field.getDeclaringClass();
297 }
298
299
300
301
302
303
304
305 public boolean isTypeOf(final Class<?> clazz) {
306 return clazz.isAssignableFrom(getType());
307 }
308
309
310
311
312
313
314
315
316 public Object getValue(final Object record) {
317 Objects.requireNonNull(record);
318
319 if(!getDeclaredClass().equals(record.getClass())) {
320 throw new IllegalArgumentException(String.format("not match record class type. expected=%s. actual=%s, ",
321 type.getName(), record.getClass().getName()));
322 }
323
324 try {
325 return field.get(record);
326 } catch (IllegalArgumentException | IllegalAccessException e) {
327 throw new SuperCsvReflectionException("fail get field value.", e);
328 }
329
330 }
331 }