View Javadoc
1   /**
2    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3    *
4    * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
5    * Portions Copyright 2013-2015 Philip Helger
6    *
7    * The contents of this file are subject to the terms of either the GNU
8    * General Public License Version 2 only ("GPL") or the Common Development
9    * and Distribution License("CDDL") (collectively, the "License").  You
10   * may not use this file except in compliance with the License.  You can
11   * obtain a copy of the License at
12   * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
13   * or packager/legal/LICENSE.txt.  See the License for the specific
14   * language governing permissions and limitations under the License.
15   *
16   * When distributing the software, include this License Header Notice in each
17   * file and include the License file at packager/legal/LICENSE.txt.
18   *
19   * GPL Classpath Exception:
20   * Oracle designates this particular file as subject to the "Classpath"
21   * exception as provided by Oracle in the GPL Version 2 section of the License
22   * file that accompanied this code.
23   *
24   * Modifications:
25   * If applicable, add the following below the License Header, with the fields
26   * enclosed by brackets [] replaced by your own identifying information:
27   * "Portions Copyright [year] [name of copyright owner]"
28   *
29   * Contributor(s):
30   * If you wish your version of this file to be governed by only the CDDL or
31   * only the GPL Version 2, indicate your decision by adding "[Contributor]
32   * elects to include this software in this distribution under the [CDDL or GPL
33   * Version 2] license."  If you don't indicate a single choice of license, a
34   * recipient has the option to distribute your version of this file under
35   * either the CDDL, the GPL Version 2 or to extend the choice of license to
36   * its licensees as provided above.  However, if you add GPL Version 2 code
37   * and therefore, elected the GPL Version 2 license, then the option applies
38   * only if the new code is made subject to such option by the copyright
39   * holder.
40   */
41  package com.helger.jcodemodel;
42  
43  import java.lang.annotation.Annotation;
44  import java.util.Collections;
45  import java.util.HashMap;
46  import java.util.LinkedHashMap;
47  import java.util.Map;
48  
49  import javax.annotation.Nonnegative;
50  import javax.annotation.Nonnull;
51  import javax.annotation.Nullable;
52  
53  import com.helger.jcodemodel.util.JCValueEnforcer;
54  
55  /**
56   * Represents an annotation on a program element.
57   *
58   * @author Bhakti Mehta (bhakti.mehta@sun.com)
59   */
60  public class JAnnotationUse extends AbstractJAnnotationValueOwned
61  {
62    /**
63     * The special parameter name that can be optimized away if used without any
64     * other parameter
65     */
66    public static final String SPECIAL_KEY_VALUE = "value";
67  
68    /**
69     * The {@link Annotation} class
70     */
71    private final AbstractJClass m_aAnnotationClass;
72  
73    /**
74     * Map of member values.
75     */
76    private Map <String, AbstractJAnnotationValue> m_aMemberValues;
77  
78    public JAnnotationUse (@Nonnull final AbstractJClass aAnnotationClass)
79    {
80      m_aAnnotationClass = JCValueEnforcer.notNull (aAnnotationClass, "AnnotationClass");
81    }
82  
83    @Nonnull
84    public AbstractJClass getAnnotationClass ()
85    {
86      return m_aAnnotationClass;
87    }
88  
89    @Nonnull
90    public JCodeModel owner ()
91    {
92      return m_aAnnotationClass.owner ();
93    }
94  
95    @Nonnull
96    public Map <String, AbstractJAnnotationValue> getAnnotationMembers ()
97    {
98      return m_aMemberValues == null ? new HashMap <String, AbstractJAnnotationValue> ()
99                                     : Collections.unmodifiableMap (m_aMemberValues);
100   }
101 
102   public boolean hasAnnotationMembers ()
103   {
104     return m_aMemberValues != null && !m_aMemberValues.isEmpty ();
105   }
106 
107   @Nullable
108   public AbstractJAnnotationValue getParam (@Nullable final String sName)
109   {
110     return m_aMemberValues == null ? null : m_aMemberValues.get (sName);
111   }
112 
113   @Nullable
114   public JAnnotationStringValue getConstantParam (@Nullable final String sName)
115   {
116     final AbstractJAnnotationValue aParam = getParam (sName);
117     return aParam instanceof JAnnotationStringValue ? (JAnnotationStringValue) aParam : null;
118   }
119 
120   @Nullable
121   public IJExpression getConstantParamValue (@Nullable final String sName)
122   {
123     final JAnnotationStringValue aParam = getConstantParam (sName);
124     return aParam != null ? aParam.value () : null;
125   }
126 
127   @Nonnull
128   private JAnnotationUse _addValue (@Nonnull final String sName,
129                                     @Nonnull final AbstractJAnnotationValue aAnnotationValue)
130   {
131     JCValueEnforcer.notEmpty (sName, "Name");
132     JCValueEnforcer.notNull (aAnnotationValue, "AnnotationValue");
133 
134     // Use ordered map to keep the code generation the same on any JVM.
135     // Lazily created.
136     if (m_aMemberValues == null)
137       m_aMemberValues = new LinkedHashMap <String, AbstractJAnnotationValue> ();
138     m_aMemberValues.put (sName, aAnnotationValue);
139 
140     return this;
141   }
142 
143   /**
144    * Adds a member value pair to this annotation
145    *
146    * @param sName
147    *        The simple name for this annotation
148    * @param value
149    *        The boolean value for this annotation
150    * @return The {@link JAnnotationUse}. More member value pairs can be added to
151    *         it using the same or the overloaded methods.
152    */
153   @Nonnull
154   public JAnnotationUse param (@Nonnull final String sName, final boolean value)
155   {
156     return _addValue (sName, wrap (value));
157   }
158 
159   @Nonnull
160   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final boolean... values)
161   {
162     paramArray (name).params (values);
163     return this;
164   }
165 
166   /**
167    * Adds a member value pair to this annotation
168    *
169    * @param name
170    *        The simple name for this annotation
171    * @param value
172    *        The byte member value for this annotation
173    * @return The {@link JAnnotationUse}. More member value pairs can be added to
174    *         it using the same or the overloaded methods.
175    */
176   @Nonnull
177   public JAnnotationUse param (@Nonnull final String name, final byte value)
178   {
179     return _addValue (name, wrap (value));
180   }
181 
182   @Nonnull
183   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final byte... values)
184   {
185     paramArray (name).params (values);
186     return this;
187   }
188 
189   /**
190    * Adds a member value pair to this annotation
191    *
192    * @param name
193    *        The simple name for this annotation
194    * @param value
195    *        The char member value for this annotation
196    * @return The {@link JAnnotationUse}. More member value pairs can be added to
197    *         it using the same or the overloaded methods.
198    */
199   @Nonnull
200   public JAnnotationUse param (@Nonnull final String name, final char value)
201   {
202     return _addValue (name, wrap (value));
203   }
204 
205   @Nonnull
206   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final char... values)
207   {
208     paramArray (name).params (values);
209     return this;
210   }
211 
212   /**
213    * Adds a member value pair to this annotation
214    *
215    * @param name
216    *        The simple name for this annotation
217    * @param value
218    *        The double member value for this annotation
219    * @return The {@link JAnnotationUse}. More member value pairs can be added to
220    *         it using the same or the overloaded methods.
221    */
222   @Nonnull
223   public JAnnotationUse param (@Nonnull final String name, final double value)
224   {
225     return _addValue (name, wrap (value));
226   }
227 
228   @Nonnull
229   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final double... values)
230   {
231     paramArray (name).params (values);
232     return this;
233   }
234 
235   /**
236    * Adds a member value pair to this annotation
237    *
238    * @param name
239    *        The simple name for this annotation
240    * @param value
241    *        The float member value for this annotation
242    * @return The {@link JAnnotationUse}. More member value pairs can be added to
243    *         it using the same or the overloaded methods.
244    */
245   @Nonnull
246   public JAnnotationUse param (@Nonnull final String name, final float value)
247   {
248     return _addValue (name, wrap (value));
249   }
250 
251   @Nonnull
252   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final float... values)
253   {
254     paramArray (name).params (values);
255     return this;
256   }
257 
258   /**
259    * Adds a member value pair to this annotation
260    *
261    * @param name
262    *        The simple name for this annotation
263    * @param value
264    *        The long member value for this annotation
265    * @return The {@link JAnnotationUse}. More member value pairs can be added to
266    *         it using the same or the overloaded methods.
267    */
268   @Nonnull
269   public JAnnotationUse param (@Nonnull final String name, final long value)
270   {
271     return _addValue (name, wrap (value));
272   }
273 
274   @Nonnull
275   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final long... values)
276   {
277     paramArray (name).params (values);
278     return this;
279   }
280 
281   /**
282    * Adds a member value pair to this annotation
283    *
284    * @param name
285    *        The simple name for this annotation
286    * @param value
287    *        The short member value for this annotation
288    * @return The {@link JAnnotationUse}. More member value pairs can be added to
289    *         it using the same or the overloaded methods.
290    */
291   @Nonnull
292   public JAnnotationUse param (@Nonnull final String name, final short value)
293   {
294     return _addValue (name, wrap (value));
295   }
296 
297   @Nonnull
298   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final short... values)
299   {
300     paramArray (name).params (values);
301     return this;
302   }
303 
304   /**
305    * Adds a member value pair to this annotation
306    *
307    * @param name
308    *        The simple name for this annotation
309    * @param value
310    *        The int member value for this annotation
311    * @return The {@link JAnnotationUse}. More member value pairs can be added to
312    *         it using the same or the overloaded methods.
313    */
314   @Nonnull
315   public JAnnotationUse param (@Nonnull final String name, final int value)
316   {
317     return _addValue (name, wrap (value));
318   }
319 
320   @Nonnull
321   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final int... values)
322   {
323     paramArray (name).params (values);
324     return this;
325   }
326 
327   /**
328    * Adds a member value pair to this annotation
329    *
330    * @param name
331    *        The simple name for this annotation
332    * @param value
333    *        The String member value for this annotation
334    * @return The {@link JAnnotationUse}. More member value pairs can be added to
335    *         it using the same or the overloaded methods.
336    */
337   @Nonnull
338   public JAnnotationUse param (@Nonnull final String name, final String value)
339   {
340     return _addValue (name, wrap (value));
341   }
342 
343   @Nonnull
344   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final String... values)
345   {
346     paramArray (name).params (values);
347     return this;
348   }
349 
350   /**
351    * Adds a member value pair to this annotation
352    *
353    * @param name
354    *        The simple name for this annotation
355    * @param value
356    *        The enum class which is member value for this annotation
357    * @return The {@link JAnnotationUse}. More member value pairs can be added to
358    *         it using the same or the overloaded methods.
359    */
360   @Nonnull
361   public JAnnotationUse param (@Nonnull final String name, @Nonnull final Enum <?> value)
362   {
363     return _addValue (name, wrap (value));
364   }
365 
366   @Nonnull
367   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final Enum <?>... values)
368   {
369     paramArray (name).params (values);
370     return this;
371   }
372 
373   /**
374    * Adds a member value pair to this annotation
375    *
376    * @param name
377    *        The simple name for this annotation
378    * @param value
379    *        The {@link JEnumConstant} which is member value for this annotation
380    * @return The {@link JAnnotationUse}. More member value pairs can be added to
381    *         it using the same or the overloaded methods.
382    */
383   @Nonnull
384   public JAnnotationUse param (@Nonnull final String name, @Nonnull final JEnumConstant value)
385   {
386     return _addValue (name, wrap (value));
387   }
388 
389   @Nonnull
390   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final JEnumConstant... values)
391   {
392     paramArray (name).params (values);
393     return this;
394   }
395 
396   /**
397    * Adds a member value pair to this annotation This can be used for e.g to
398    * specify
399    *
400    * <pre>
401    * &#64;XmlCollectionItem(type=Integer.class);
402    * </pre>
403    *
404    * For adding a value of Class&lt;? extends Annotation&gt;
405    * {@link #annotationParam(String, Class)}
406    *
407    * @param name
408    *        The simple name for this annotation param
409    * @param value
410    *        The class type of the param
411    * @return The {@link JAnnotationUse}. More member value pairs can be added to
412    *         it using the same or the overloaded methods.
413    */
414   @Nonnull
415   public JAnnotationUse param (@Nonnull final String name, @Nonnull final Class <?> value)
416   {
417     return _addValue (name, wrap (value));
418   }
419 
420   @Nonnull
421   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final Class <?>... values)
422   {
423     paramArray (name).params (values);
424     return this;
425   }
426 
427   /**
428    * Adds a member value pair to this annotation based on the type represented
429    * by the given {@link AbstractJType}
430    *
431    * @param name
432    *        The simple name for this annotation param
433    * @param type
434    *        the {@link AbstractJType} representing the actual type
435    * @return The {@link JAnnotationUse}. More member value pairs can be added to
436    *         it using the same or the overloaded methods.
437    */
438   @Nonnull
439   public JAnnotationUse param (@Nonnull final String name, @Nonnull final AbstractJType type)
440   {
441     return _addValue (name, wrap (type));
442   }
443 
444   @Nonnull
445   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final AbstractJType... values)
446   {
447     paramArray (name).params (values);
448     return this;
449   }
450 
451   /**
452    * Adds a member value pair to this annotation.
453    *
454    * @param name
455    *        The simple name for this annotation
456    * @param value
457    *        The {@link IJExpression} which provides the content value for this
458    *        annotation
459    * @return The {@link JAnnotationUse}. More member value pairs can be added to
460    *         it using the same or the overloaded methods.
461    */
462   @Nonnull
463   public JAnnotationUse param (@Nonnull final String name, @Nonnull final IJExpression value)
464   {
465     return _addValue (name, wrap (value));
466   }
467 
468   @Nonnull
469   public JAnnotationUse paramArray (@Nonnull final String name, @Nonnull final IJExpression... values)
470   {
471     paramArray (name).params (values);
472     return this;
473   }
474 
475   /**
476    * Adds a member value pair which is of type array to this annotation
477    *
478    * @param sName
479    *        The simple name for this annotation
480    * @return The {@link JAnnotationArrayMember}. For adding array values
481    * @see JAnnotationArrayMember
482    */
483   @Nonnull
484   public JAnnotationArrayMember paramArray (@Nonnull final String sName)
485   {
486     final JAnnotationArrayMember aArrayMember = new JAnnotationArrayMember (owner ());
487     _addValue (sName, aArrayMember);
488     return aArrayMember;
489   }
490 
491   /**
492    * Adds a member value pair to this annotation For adding class values as
493    * param
494    *
495    * @see #param(String, Class)
496    * @param name
497    *        The simple name for this annotation
498    * @param value
499    *        The annotation class which is member value for this annotation
500    * @return The {@link JAnnotationUse}. More member value pairs can be added to
501    *         it using the same or the overloaded methods.
502    */
503   @Nonnull
504   public JAnnotationUse annotationParam (@Nonnull final String name, @Nonnull final Class <? extends Annotation> value)
505   {
506     return annotationParam (name, owner ().ref (value));
507   }
508 
509   /**
510    * Adds a member value pair to this annotation For adding class values as
511    * param
512    *
513    * @see #param(String, Class)
514    * @param name
515    *        The simple name for this annotation
516    * @param value
517    *        The annotation class which is member value for this annotation
518    * @return The {@link JAnnotationUse}. More member value pairs can be added to
519    *         it using the same or the overloaded methods.
520    */
521   @Nonnull
522   public JAnnotationUse annotationParam (@Nonnull final String name, @Nonnull final AbstractJClass value)
523   {
524     final JAnnotationUse annotationUse = new JAnnotationUse (value);
525     _addValue (name, annotationUse);
526     return annotationUse;
527   }
528 
529   @Nonnegative
530   public int size ()
531   {
532     return m_aMemberValues.size ();
533   }
534 
535   private boolean _isOptimizable ()
536   {
537     return m_aMemberValues.size () == 1 && m_aMemberValues.containsKey (SPECIAL_KEY_VALUE);
538   }
539 
540   public void generate (final JFormatter f)
541   {
542     f.print ('@').generable (m_aAnnotationClass);
543     if (m_aMemberValues != null && !m_aMemberValues.isEmpty ())
544     {
545       f.print ('(');
546       if (_isOptimizable ())
547       {
548         // short form
549         f.generable (m_aMemberValues.get (SPECIAL_KEY_VALUE));
550       }
551       else
552       {
553         boolean bFirst = true;
554         for (final Map.Entry <String, AbstractJAnnotationValue> mapEntry : m_aMemberValues.entrySet ())
555         {
556           if (!bFirst)
557             f.print (',');
558           f.print (mapEntry.getKey ()).print ('=').generable (mapEntry.getValue ());
559           bFirst = false;
560         }
561       }
562       f.print (')');
563     }
564   }
565 }