KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > spoon > support > reflect > declaration > CtAnnotationImpl


1 package spoon.support.reflect.declaration;
2
3 import java.lang.annotation.Annotation JavaDoc;
4 import java.lang.reflect.Array JavaDoc;
5 import java.lang.reflect.InvocationHandler JavaDoc;
6 import java.lang.reflect.Method JavaDoc;
7 import java.lang.reflect.Proxy JavaDoc;
8 import java.util.ArrayList JavaDoc;
9 import java.util.Arrays JavaDoc;
10 import java.util.Collection JavaDoc;
11 import java.util.List JavaDoc;
12 import java.util.Map JavaDoc;
13 import java.util.TreeMap JavaDoc;
14
15 import spoon.reflect.code.CtCodeElement;
16 import spoon.reflect.code.CtFieldAccess;
17 import spoon.reflect.code.CtLiteral;
18 import spoon.reflect.declaration.CtAnnotation;
19 import spoon.reflect.declaration.CtAnnotationType;
20 import spoon.reflect.declaration.CtField;
21 import spoon.reflect.declaration.CtSimpleType;
22 import spoon.reflect.eval.PartialEvaluator;
23 import spoon.reflect.reference.CtFieldReference;
24 import spoon.reflect.reference.CtTypeReference;
25 import spoon.reflect.visitor.CtVisitor;
26
27 /**
28  * The implementation for {@link spoon.reflect.declaration.CtAnnotation}.
29  *
30  * @author Renaud Pawlak
31  */

32 public class CtAnnotationImpl<A extends Annotation JavaDoc> extends CtElementImpl
33         implements CtAnnotation<A> {
34     class AnnotationInvocationHandler implements InvocationHandler JavaDoc {
35         CtAnnotation<? extends Annotation JavaDoc> annotation;
36
37         public AnnotationInvocationHandler(
38                 CtAnnotation<? extends Annotation JavaDoc> annotation) {
39             super();
40             this.annotation = annotation;
41         }
42
43         public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args)
44                 throws Throwable JavaDoc {
45             String JavaDoc fieldname = method.getName();
46             if (fieldname.equals("toString")) {
47                 return CtAnnotationImpl.this.toString();
48             } else if (fieldname.equals("annotationType")) {
49                 return annotation.getAnnotationType().getActualClass();
50             }
51             return getElementValue(fieldname);
52         }
53     }
54
55     private static final long serialVersionUID = 1L;
56
57     CtTypeReference<A> annotationType;
58
59     Map JavaDoc<String JavaDoc, Object JavaDoc> elementValues = new TreeMap JavaDoc<String JavaDoc, Object JavaDoc>();
60
61     public CtAnnotationImpl() {
62         super();
63     }
64
65     public void accept(CtVisitor visitor) {
66         visitor.visitCtAnnotation(this);
67     }
68
69     protected void appendValues(String JavaDoc elementName, Object JavaDoc... values) {
70         if (!elementValues.containsKey(elementName)) {
71             elementValues.put(elementName, values);
72         } else {
73             Object JavaDoc o = elementValues.get(elementName);
74             if (o.getClass().isArray()) {
75                 List JavaDoc<Object JavaDoc> tmp = new ArrayList JavaDoc<Object JavaDoc>();
76                 Object JavaDoc[] old = (Object JavaDoc[]) o;
77                 for (Object JavaDoc a : old) {
78                     tmp.add(a);
79                 }
80                 for (Object JavaDoc a : values) {
81                     tmp.add(a);
82                 }
83                 elementValues.put(elementName, tmp.toArray());
84             } else {
85                 // o is not a array
86
if (values.length > 1) {
87                     throw new RuntimeException JavaDoc(
88                             "Cannot add array to a non-array value");
89                 } else {
90                     elementValues.put(elementName, values[0]);
91                 }
92             }
93         }
94     }
95
96     @SuppressWarnings JavaDoc("unchecked")
97     public A getActualAnnotation() {
98         return (A) Proxy.newProxyInstance(annotationType.getActualClass()
99                 .getClassLoader(), new Class JavaDoc[] { annotationType
100                 .getActualClass() }, new AnnotationInvocationHandler(this));
101     }
102
103     @SuppressWarnings JavaDoc("unchecked")
104     private Object JavaDoc convertValue(Object JavaDoc value) {
105         if (value instanceof CtFieldReference) {
106             Class JavaDoc c = ((CtFieldReference) value).getDeclaringType()
107                     .getActualClass();
108             if (((CtFieldReference) value).getSimpleName().equals("class")) {
109                 return c;
110             }
111             CtField field = ((CtFieldReference) value).getDeclaration();
112             if (Enum JavaDoc.class.isAssignableFrom(c)) {
113                 // Value references a Enum field
114
return Enum.valueOf(c, ((CtFieldReference) value)
115                         .getSimpleName());
116             } else {
117                 // Value is a static final
118
return convertValue(field.getDefaultExpression());
119             }
120         } else if (value instanceof CtFieldAccess) {
121             // Get variable
122
return convertValue(((CtFieldAccess) value).getVariable());
123         } else if (value instanceof CtAnnotation) {
124             // Get proxy
125
return ((CtAnnotation) value).getActualAnnotation();
126         } else if (value instanceof CtLiteral) {
127             // Replace literal by his value
128
return ((CtLiteral) value).getValue();
129         } else if (value instanceof CtCodeElement) {
130             // Evaluate code elements
131
PartialEvaluator eval = getFactory().Eval()
132                     .createPartialEvaluator();
133             Object JavaDoc ret = eval.evaluate(((CtCodeElement) value).getParent(),
134                     (CtCodeElement) value);
135             if (!(ret instanceof CtCodeElement))
136                 return convertValue(ret);
137             else
138                 return ret;
139         } else if (value instanceof CtTypeReference) {
140             // Get RT class for References
141
return ((CtTypeReference) value).getActualClass();
142         }
143         return value;
144     }
145
146     private Class JavaDoc getElementType(String JavaDoc name) {
147         // Try by CT reflection
148
CtSimpleType t = getAnnotationType().getDeclaration();
149         if (t != null) {
150             CtField f = t.getField(name);
151             return f.getType().getActualClass();
152         }
153         // Try with RT reflection
154
Class JavaDoc c = getAnnotationType().getActualClass();
155         for (Method JavaDoc m : c.getMethods()) {
156             if (m.getName().equals(name)) {
157                 return m.getReturnType();
158             }
159         }
160         return null;
161     }
162
163     public CtTypeReference<A> getAnnotationType() {
164         return annotationType;
165     }
166
167     private Object JavaDoc getDefaultValue(String JavaDoc fieldName) {
168         Object JavaDoc ret = null;
169         CtAnnotationType<?> at = (CtAnnotationType<?>) getAnnotationType()
170                 .getDeclaration();
171         if (at != null) {
172             CtField<?> f = at.getField(fieldName);
173             ret = f.getDefaultExpression();
174         }
175         return ret;
176     }
177
178     public Object JavaDoc getElementValue(String JavaDoc key) {
179         Object JavaDoc ret = null;
180         ret = elementValues.get(key);
181         if (ret == null)
182             ret = getDefaultValue(key);
183         if (ret == null)
184             ret = getReflectValue(key);
185
186         Class JavaDoc type = getElementType(key);
187
188         if (type.isArray()) {
189             if (!(ret instanceof Collection JavaDoc)) {
190                 List JavaDoc<Object JavaDoc> lst = new ArrayList JavaDoc<Object JavaDoc>();
191                 Object JavaDoc[] temp = (Object JavaDoc[])ret;
192                 lst.addAll(Arrays.asList(temp));
193                 ret = lst;
194                 
195             }
196             Collection JavaDoc col = (Collection JavaDoc) ret;
197             Object JavaDoc[] array = (Object JavaDoc[]) Array.newInstance(type
198                     .getComponentType(), col.size());
199             int i = 0;
200             for (Object JavaDoc obj : col) {
201                 array[i++] = convertValue(obj);
202             }
203             ret = array;
204         } else {
205             ret = convertValue(ret);
206         }
207
208         if (type.isPrimitive()) {
209             if (type == boolean.class && ret.getClass() != boolean.class) {
210                 ret = Boolean.parseBoolean(ret.toString());
211             } else if (type == byte.class && ret.getClass() != byte.class) {
212                 ret = Byte.parseByte(ret.toString());
213             } else if (type == char.class && ret.getClass() != char.class) {
214                 ret = ret.toString().charAt(0);
215             } else if (type == double.class && ret.getClass() != double.class) {
216                 ret = Double.parseDouble(ret.toString());
217             } else if (type == float.class && ret.getClass() != float.class) {
218                 ret = Float.parseFloat(ret.toString());
219             } else if (type == int.class && ret.getClass() != int.class) {
220                 ret = Integer.parseInt(ret.toString());
221             } else if (type == long.class && ret.getClass() != long.class) {
222                 ret = Long.parseLong(ret.toString());
223             }
224         }
225         return ret;
226     }
227
228     public Map JavaDoc<String JavaDoc, Object JavaDoc> getElementValues() {
229         return elementValues;
230     }
231
232     private Object JavaDoc getReflectValue(String JavaDoc fieldname) {
233         try {
234             Class JavaDoc c = getAnnotationType().getActualClass();
235             Method JavaDoc m = c.getMethod(fieldname);
236             return m.getDefaultValue();
237         } catch (Exception JavaDoc e) {
238             return null;
239         }
240     }
241
242     @SuppressWarnings JavaDoc("unchecked")
243     public void setAnnotationType(
244             CtTypeReference<? extends Annotation JavaDoc> annotationType) {
245         this.annotationType = (CtTypeReference<A>) annotationType;
246     }
247
248     public void setElementValues(Map JavaDoc<String JavaDoc, Object JavaDoc> values) {
249         this.elementValues = values;
250     }
251 }
252
Popular Tags