1 /* 2 * Copyright (c) 1997, 2012, 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 * @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 @XmlCollection(values= @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 @XmlCollection(values= @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 }