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 }
--- EOF ---