View Javadoc
1   /*
2    * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.codemodel.internal;
27  
28  
29  import java.lang.annotation.Annotation;
30  import java.util.Collections;
31  import java.util.LinkedHashMap;
32  import java.util.Map;
33  
34  /**
35   * Represents an annotation on a program element.
36   *
37   * TODO
38   *    How to add enums to the annotations
39   * @author
40   *     Bhakti Mehta (bhakti.mehta@sun.com)
41   */
42  public final class JAnnotationUse extends JAnnotationValue {
43  
44      /**
45       * The {@link Annotation} class
46       */
47      private final JClass clazz;
48  
49      /**
50       * Map of member values.
51       */
52      private Map<String,JAnnotationValue> memberValues;
53  
54      JAnnotationUse(JClass clazz){
55          this.clazz = clazz;
56      }
57  
58      public JClass getAnnotationClass() {
59          return clazz;
60      }
61  
62      public Map<String, JAnnotationValue> getAnnotationMembers() {
63          return Collections.unmodifiableMap(memberValues);
64      }
65  
66      private JCodeModel owner() {
67          return clazz.owner();
68      }
69  
70      private void addValue(String name, JAnnotationValue annotationValue) {
71          // Use ordered map to keep the code generation the same on any JVM.
72          // Lazily created.
73          if(memberValues==null)
74              memberValues = new LinkedHashMap<String, JAnnotationValue>();
75          memberValues.put(name,annotationValue);
76      }
77  
78      /**
79       * Adds a member value pair to this annotation
80       *
81       * @param name
82       *        The simple name for this annotation
83       *
84       * @param value
85       *        The boolean value for this annotation
86       * @return
87       *         The JAnnotationUse. More member value pairs can
88       *         be added to it using the same or the overloaded methods.
89       *
90       */
91      public JAnnotationUse param(String name, boolean value){
92          addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
93          return this;
94      }
95  
96      /**
97       * Adds a member value pair to this annotation
98       * @param name
99       *        The simple name for this annotation
100      *
101      * @param value
102      *        The byte member value for this annotation
103      * @return
104      *         The JAnnotationUse. More member value pairs can
105      *         be added to it using the same or the overloaded methods.
106      *
107      */
108     public JAnnotationUse param(String name, byte value){
109         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
110         return this;
111     }
112 
113     /**
114      * Adds a member value pair to this annotation
115      * @param name
116      *        The simple name for this annotation
117      *
118      * @param value
119      *        The char member value for this annotation
120      * @return
121      *         The JAnnotationUse. More member value pairs can
122      *         be added to it using the same or the overloaded methods.
123      *
124      */
125     public JAnnotationUse param(String name, char value){
126         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
127         return this;
128     }
129 
130     /**
131      * Adds a member value pair to this annotation
132      * @param name
133      *        The simple name for this annotation
134      *
135      * @param value
136      *        The double member value for this annotation
137      * @return
138      *         The JAnnotationUse. More member value pairs can
139      *         be added to it using the same or the overloaded methods.
140      *
141      */
142     public JAnnotationUse param(String name, double value){
143         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
144         return this;
145     }
146 
147     /**
148      * Adds a member value pair to this annotation
149      * @param name
150      *        The simple name for this annotation
151      *
152      * @param value
153      *        The float member value for this annotation
154      * @return
155      *         The JAnnotationUse. More member value pairs can
156      *         be added to it using the same or the overloaded methods.
157      *
158      */
159     public JAnnotationUse param(String name, float value){
160         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
161         return this;
162     }
163 
164     /**
165      * Adds a member value pair to this annotation
166      * @param name
167      *        The simple name for this annotation
168      *
169      * @param value
170      *        The long member value for this annotation
171      * @return
172      *         The JAnnotationUse. More member value pairs can
173      *         be added to it using the same or the overloaded methods.
174      *
175      */
176     public JAnnotationUse param(String name, long value){
177         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
178         return this;
179     }
180 
181     /**
182      * Adds a member value pair to this annotation
183      * @param name
184      *        The simple name for this annotation
185      *
186      * @param value
187      *        The short member value for this annotation
188      * @return
189      *         The JAnnotationUse. More member value pairs can
190      *         be added to it using the same or the overloaded methods.
191      *
192      */
193     public JAnnotationUse param(String name, short value){
194         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
195         return this;
196     }
197 
198     /**
199      * Adds a member value pair to this annotation
200      * @param name
201      *        The simple name for this annotation
202      *
203      * @param value
204      *        The int member value for this annotation
205      * @return
206      *         The JAnnotationUse. More member value pairs can
207      *         be added to it using the same or the overloaded methods.
208      *
209      */
210     public JAnnotationUse param(String name, int value){
211         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
212         return this;
213     }
214 
215     /**
216      * Adds a member value pair to this annotation
217      * @param name
218      *        The simple name for this annotation
219      *
220      * @param value
221      *        The String member value for this annotation
222      * @return
223      *         The JAnnotationUse. More member value pairs can
224      *         be added to it using the same or the overloaded methods.
225      *
226      */
227     public JAnnotationUse param(String name, String value){
228         //Escape string values with quotes so that they can
229         //be generated accordingly
230         addValue(name, new JAnnotationStringValue(JExpr.lit(value)));
231         return this;
232     }
233 
234     /**
235      * Adds a member value pair to this annotation
236      * For adding class values as param
237      * @see #param(String, Class)
238      * @param name
239      *        The simple name for this annotation
240      *
241      * @param value
242      *        The annotation class which is member value for this annotation
243      * @return
244      *         The JAnnotationUse. More member value pairs can
245      *         be added to it using the same or the overloaded methods.
246      *
247      */
248     public JAnnotationUse annotationParam(String name, Class<? extends Annotation> value) {
249         JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(value));
250         addValue(name, annotationUse);
251         return annotationUse;
252     }
253 
254     /**
255      * Adds a member value pair to this annotation
256      * @param name
257      *        The simple name for this annotation
258      *
259      * @param value
260      *        The enum class which is member value for this annotation
261      * @return
262      *         The JAnnotationUse. More member value pairs can
263      *         be added to it using the same or the overloaded methods.
264      *
265      */
266     public JAnnotationUse param(String name, final Enum<?> value) {
267         addValue(name, new JAnnotationValue() {
268                     public void generate(JFormatter f) {
269                         f.t(owner().ref(value.getDeclaringClass())).p('.').p(value.name());
270                     }
271                 });
272         return this;
273     }
274 
275     /**
276      * Adds a member value pair to this annotation
277      * @param name
278      *        The simple name for this annotation
279      *
280      * @param value
281      *        The JEnumConstant which is member value for this annotation
282      * @return
283      *         The JAnnotationUse. More member value pairs can
284      *         be added to it using the same or the overloaded methods.
285      *
286      */
287     public JAnnotationUse param(String name, JEnumConstant value){
288         addValue(name, new JAnnotationStringValue(value));
289         return this;
290     }
291 
292      /**
293       * Adds a member value pair to this annotation
294       *  This can be used for e.g to specify
295       * <pre>
296       *        &#64;XmlCollectionItem(type=Integer.class);
297       * <pre>
298       * For adding a value of Class<? extends Annotation>
299       * @link
300       * #annotationParam(java.lang.String, java.lang.Class<? extends java.lang.annotation.Annotation>)
301       * @param name
302       *        The simple name for this annotation param
303       *
304       * @param value
305       *        The class type of the param
306       * @return
307       *         The JAnnotationUse. More member value pairs can
308       *         be added to it using the same or the overloaded methods.
309       *
310       *
311       *
312       */
313      public JAnnotationUse param(String name, final Class<?> value){
314          addValue(name, new JAnnotationStringValue(
315                          new JExpressionImpl() {
316                                  public void generate(JFormatter f) {
317                                          f.p(value.getName().replace('$', '.'));
318                                          f.p(".class");
319                                 }
320                          }));
321          return this;
322     }
323 
324     /**
325      * Adds a member value pair to this annotation based on the
326      * type represented by the given JType
327      *
328      * @param name The simple name for this annotation param
329      * @param type the JType representing the actual type
330      * @return The JAnnotationUse. More member value pairs can
331      *         be added to it using the same or the overloaded methods.
332      */
333     public JAnnotationUse param(String name, JType type){
334         JClass c = type.boxify();
335         addValue(name, new JAnnotationStringValue ( c.dotclass() ));
336         return this;
337     }
338 
339     /**
340      * Adds a member value pair to this annotation.
341      * @param name
342      *        The simple name for this annotation
343      *
344      * @param value
345      *        The JExpression which provides the contant value for this annotation
346      * @return
347      *         The JAnnotationUse. More member value pairs can
348      *         be added to it using the same or the overloaded methods.
349      *
350      */
351     public JAnnotationUse param(String name, JExpression value){
352         addValue(name, new JAnnotationStringValue(value));
353         return this;
354     }
355 
356     /**
357      * Adds a member value pair which is of type array to this annotation
358      * @param name
359      *        The simple name for this annotation
360      *
361      * @return
362      *         The JAnnotationArrayMember. For adding array values
363      *         @see JAnnotationArrayMember
364      *
365      */
366     public JAnnotationArrayMember paramArray(String name){
367         JAnnotationArrayMember arrayMember = new JAnnotationArrayMember(owner());
368         addValue(name, arrayMember);
369         return arrayMember;
370     }
371 
372 
373 //    /**
374 //     * This can be used to add annotations inside annotations
375 //     * for e.g  &#64;XmlCollection(values= &#64;XmlCollectionItem(type=Foo.class))
376 //     * @param className
377 //     *         The classname of the annotation to be included
378 //     * @return
379 //     *         The JAnnotationUse that can be used as a member within this JAnnotationUse
380 //     * @deprecated
381 //     *      use {@link JAnnotationArrayMember#annotate}
382 //     */
383 //    public JAnnotationUse annotate(String className) {
384 //        JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(className));
385 //        return annotationUse;
386 //    }
387 
388     /**
389      * This can be used to add annotations inside annotations
390      * for e.g  &#64;XmlCollection(values= &#64;XmlCollectionItem(type=Foo.class))
391      * @param clazz
392      *         The annotation class to be included
393      * @return
394      *     The JAnnotationUse that can be used as a member within this JAnnotationUse
395      * @deprecated
396      *      use {@link JAnnotationArrayMember#annotate}
397      */
398     public JAnnotationUse annotate(Class <? extends Annotation> clazz) {
399          JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(clazz));
400          return annotationUse;
401     }
402 
403     public void generate(JFormatter f) {
404         f.p('@').g(clazz);
405         if(memberValues!=null) {
406             f.p('(');
407             boolean first = true;
408 
409             if(isOptimizable()) {
410                 // short form
411                 f.g(memberValues.get("value"));
412             } else {
413                 for (Map.Entry<String, JAnnotationValue> mapEntry : memberValues.entrySet()) {
414                     if (!first) f.p(',');
415                     f.p(mapEntry.getKey()).p('=').g(mapEntry.getValue());
416                     first = false;
417                 }
418             }
419             f.p(')');
420         }
421     }
422 
423     private boolean isOptimizable() {
424         return memberValues.size()==1 && memberValues.containsKey("value");
425     }
426 }