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 * @XmlCollectionItem(type=Integer.class);
402 * </pre>
403 *
404 * For adding a value of Class<? extends Annotation>
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 }