1 /* 2 * Copyright (c) 1997, 2015, 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 * {@code @XmlCollectionItem(type=Integer.class);} 297 * </pre> 298 * For adding a value of {@code Class<? extends Annotation>} 299 * {@link #annotationParam(java.lang.String, java.lang.Class)} 300 * @param name 301 * The simple name for this annotation param 302 * 303 * @param value 304 * The class type of the param 305 * @return 306 * The JAnnotationUse. More member value pairs can 307 * be added to it using the same or the overloaded methods. 308 * 309 * 310 * 311 */ 312 public JAnnotationUse param(String name, final Class<?> value){ 313 addValue(name, new JAnnotationStringValue( 314 new JExpressionImpl() { 315 public void generate(JFormatter f) { 316 f.p(value.getName().replace('$', '.')); 317 f.p(".class"); 318 } 319 })); 320 return this; 321 } 322 323 /** 324 * Adds a member value pair to this annotation based on the 325 * type represented by the given JType 326 * 327 * @param name The simple name for this annotation param 328 * @param type the JType representing the actual type 329 * @return The JAnnotationUse. More member value pairs can 330 * be added to it using the same or the overloaded methods. 331 */ 332 public JAnnotationUse param(String name, JType type){ 333 JClass c = type.boxify(); 334 addValue(name, new JAnnotationStringValue ( c.dotclass() )); 335 return this; 336 } 337 338 /** 339 * Adds a member value pair to this annotation. 340 * @param name 341 * The simple name for this annotation 342 * 343 * @param value 344 * The JExpression which provides the contant value for this annotation 345 * @return 346 * The JAnnotationUse. More member value pairs can 347 * be added to it using the same or the overloaded methods. 348 * 349 */ 350 public JAnnotationUse param(String name, JExpression value){ 351 addValue(name, new JAnnotationStringValue(value)); 352 return this; 353 } 354 355 /** 356 * Adds a member value pair which is of type array to this annotation 357 * @param name 358 * The simple name for this annotation 359 * 360 * @return 361 * The JAnnotationArrayMember. For adding array values 362 * @see JAnnotationArrayMember 363 * 364 */ 365 public JAnnotationArrayMember paramArray(String name){ 366 JAnnotationArrayMember arrayMember = new JAnnotationArrayMember(owner()); 367 addValue(name, arrayMember); 368 return arrayMember; 369 } 370 371 372 // /** 373 // * This can be used to add annotations inside annotations 374 // * for e.g @XmlCollection(values= @XmlCollectionItem(type=Foo.class)) 375 // * @param className 376 // * The classname of the annotation to be included 377 // * @return 378 // * The JAnnotationUse that can be used as a member within this JAnnotationUse 379 // * @deprecated 380 // * use {@link JAnnotationArrayMember#annotate} 381 // */ 382 // public JAnnotationUse annotate(String className) { 383 // JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(className)); 384 // return annotationUse; 385 // } 386 387 /** 388 * This can be used to add annotations inside annotations 389 * for e.g @XmlCollection(values= @XmlCollectionItem(type=Foo.class)) 390 * @param clazz 391 * The annotation class to be included 392 * @return 393 * The JAnnotationUse that can be used as a member within this JAnnotationUse 394 * @deprecated 395 * use {@link JAnnotationArrayMember#annotate} 396 */ 397 public JAnnotationUse annotate(Class <? extends Annotation> clazz) { 398 JAnnotationUse annotationUse = new JAnnotationUse(owner().ref(clazz)); 399 return annotationUse; 400 } 401 402 public void generate(JFormatter f) { 403 f.p('@').g(clazz); 404 if(memberValues!=null) { 405 f.p('('); 406 boolean first = true; 407 408 if(isOptimizable()) { 409 // short form 410 f.g(memberValues.get("value")); 411 } else { 412 for (Map.Entry<String, JAnnotationValue> mapEntry : memberValues.entrySet()) { 413 if (!first) f.p(','); 414 f.p(mapEntry.getKey()).p('=').g(mapEntry.getValue()); 415 first = false; 416 } 417 } 418 f.p(')'); 419 } 420 } 421 422 private boolean isOptimizable() { 423 return memberValues.size()==1 && memberValues.containsKey("value"); 424 } 425 }