1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package com.salesforce.aptspring.processor;
28
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Map.Entry;
32
33 import javax.lang.model.element.AnnotationMirror;
34 import javax.lang.model.element.AnnotationValue;
35 import javax.lang.model.element.Element;
36 import javax.lang.model.element.ExecutableElement;
37 import javax.lang.model.element.TypeElement;
38 import javax.lang.model.element.VariableElement;
39 import javax.lang.model.util.SimpleAnnotationValueVisitor8;
40
41 public class AnnotationValueExtractor {
42
43 private static final String ALIAS_TYPE = "org.springframework.core.annotation.AliasFor";
44
45 private static final String ALIAS_TARGET_TYPE = "annotation";
46
47 private static final String ALIAS_TARGET_FIELD = "attribute";
48
49 private static final String DEFAULT_ANNOTATION_VALUE = "value";
50
51
52 private static class AliasData {
53 private String targetAnnotation = null;
54 private String targetField = null;
55 }
56
57
58
59
60
61
62
63
64
65
66
67
68 public static String[] getAnnotationValue(Element e, String annotationTypeName, String methodName) {
69 if (e instanceof TypeElement) {
70
71 ((TypeElement) e).getSuperclass();
72 ((TypeElement) e).getInterfaces();
73 }
74 for (AnnotationMirror a : e.getAnnotationMirrors()) {
75 String[] returned = getAnnotationValue(a, annotationTypeName, methodName);
76 if (returned != null) {
77 return returned;
78 }
79 }
80 return null;
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96 private static String[] getAnnotationValue(AnnotationMirror am, String annotationTypeName, String methodName) {
97 String currentType = am.getAnnotationType().toString();
98 for (Entry<? extends ExecutableElement, ? extends AnnotationValue> ev : am.getElementValues().entrySet()) {
99 boolean aliasMatch = aliasMatch(getAlias(ev.getKey()), annotationTypeName, methodName, currentType);
100 boolean foundField = ev.getKey().getSimpleName().toString().equals(methodName);
101 if (aliasMatch || (foundField && currentType.equals(annotationTypeName))) {
102 AnnotationValueExtractorVisitor ex = new AnnotationValueExtractorVisitor();
103 List<String> values = new ArrayList<>();
104 ex.visit(ev.getValue(), values);
105 return values.toArray(new String[values.size()]);
106 }
107 }
108 if (currentType.equals(annotationTypeName)) {
109
110 return new String[]{};
111 }
112
113 for (AnnotationMirror a : am.getAnnotationType().getAnnotationMirrors()) {
114
115 if (!a.getAnnotationType().asElement().toString().startsWith("java.lang.annotation")) {
116 String[] output = getAnnotationValue(a, annotationTypeName, methodName);
117 if (output != null) {
118 return output;
119 }
120 }
121 }
122 return null;
123 }
124
125
126
127
128
129
130
131
132
133
134 private static AliasData getAlias(ExecutableElement annotationParameter) {
135 AliasData output = null;
136 for (AnnotationMirror am : annotationParameter.getAnnotationMirrors()) {
137 if (ALIAS_TYPE.equals(am.getAnnotationType().asElement().toString())) {
138 output = new AliasData();
139 for (Entry<? extends ExecutableElement, ? extends AnnotationValue> ev : am.getElementValues().entrySet()) {
140 String fieldName = ev.getKey().getSimpleName().toString();
141 AnnotationValue av = ev.getValue();
142 if (ALIAS_TARGET_TYPE.equals(fieldName)) {
143 output.targetAnnotation = getAttributeValueFromAnnotationFieldAsString(av, false);
144 }
145
146
147
148
149 if (ALIAS_TARGET_FIELD.equals(fieldName)) {
150 output.targetField = getAttributeValueFromAnnotationFieldAsString(av, true);
151 }
152 if (DEFAULT_ANNOTATION_VALUE.equals(fieldName) && output.targetField == null) {
153 output.targetField = getAttributeValueFromAnnotationFieldAsString(av, true);
154 }
155 }
156
157
158
159 if (output.targetAnnotation != null && output.targetField == null) {
160 output.targetField = annotationParameter.getSimpleName().toString();
161 }
162 }
163 }
164 return output;
165 }
166
167
168
169
170
171
172
173
174
175 private static String getAttributeValueFromAnnotationFieldAsString(AnnotationValue av, boolean emptyStringAsNull) {
176 if (av != null && av.getValue() != null) {
177 return av.getValue().toString().isEmpty() && emptyStringAsNull ? null : av.getValue().toString();
178 } else {
179 return null;
180 }
181 }
182
183
184
185
186
187
188 private static boolean aliasMatch(AliasData aliasData, String targetType, String targetField, String currentAnnotation) {
189 if (aliasData == null) {
190 return false;
191 }
192 return (
193 (targetType.equals(aliasData.targetAnnotation)
194 || (aliasData.targetAnnotation == null && targetType.equals(currentAnnotation)))
195 &&
196 targetField.equals(aliasData.targetField));
197 }
198
199 private static class AnnotationValueExtractorVisitor extends SimpleAnnotationValueVisitor8<Void, List<String>> {
200
201 @Override
202 protected Void defaultAction(Object o, List<String> values) {
203 values.add(o.toString());
204 return null;
205 }
206
207 public Void visitEnumConstant(VariableElement c, List<String> values) {
208 values.add(c.getSimpleName().toString());
209 return null;
210 }
211
212 public Void visitAnnotation(AnnotationMirror a, List<String> values) {
213
214 return defaultAction(a, values);
215 }
216
217 public Void visitArray(List<? extends AnnotationValue> vals, List<String> values) {
218 for (AnnotationValue val : vals) {
219 visit(val, values);
220 }
221 return null;
222 }
223 }
224 }