src/share/classes/com/sun/codemodel/internal/JDefinedClass.java

Mon, 04 May 2009 21:10:41 -0700

author
tbell
date
Mon, 04 May 2009 21:10:41 -0700
changeset 50
42dfec6871f6
parent 45
31822b475baa
permissions
-rw-r--r--

6658158: Mutable statics in SAAJ (findbugs)
6658163: txw2.DatatypeWriter.BUILDIN is a mutable static (findbugs)
Reviewed-by: darcy

     1 /*
     2  * Copyright 2005-2006 Sun Microsystems, Inc.  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.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.codemodel.internal;
    28 import java.lang.annotation.Annotation;
    29 import java.util.ArrayList;
    30 import java.util.Collection;
    31 import java.util.Collections;
    32 import java.util.Iterator;
    33 import java.util.LinkedHashMap;
    34 import java.util.List;
    35 import java.util.Map;
    36 import java.util.Set;
    37 import java.util.TreeMap;
    38 import java.util.TreeSet;
    40 /**
    41  * A generated Java class/interface/enum/....
    42  *
    43  * <p>
    44  * This class models a declaration, and since a declaration can be always
    45  * used as a reference, it inherits {@link JClass}.
    46  *
    47  * <h2>Where to go from here?</h2>
    48  * <p>
    49  * You'd want to generate fields and methods on a class.
    50  * See {@link #method(int, JType, String)} and {@link #field(int, JType, String)}.
    51  */
    52 public class JDefinedClass
    53     extends JClass
    54     implements JDeclaration, JClassContainer, JGenerifiable, JAnnotatable {
    56     /** Name of this class. Null if anonymous. */
    57     private String name = null;
    60     /** Modifiers for the class declaration */
    61     private JMods mods;
    63     /** Name of the super class of this class. */
    64     private JClass superClass;
    66     /** List of interfaces that this class implements */
    67     private final Set<JClass> interfaces = new TreeSet<JClass>();
    69     /** Fields keyed by their names. */
    70     /*package*/ final Map<String,JFieldVar> fields = new LinkedHashMap<String,JFieldVar>();
    72     /** Static initializer, if this class has one */
    73     private JBlock init = null;
    75     /** class javadoc */
    76     private JDocComment jdoc = null;
    78     /** Set of constructors for this class, if any */
    79     private final List<JMethod> constructors = new ArrayList<JMethod>();
    81     /** Set of methods that are members of this class */
    82     private final List<JMethod> methods = new ArrayList<JMethod>();
    84     /**
    85      * Nested classes as a map from name to JDefinedClass.
    86      * The name is all capitalized in a case sensitive file system
    87      * ({@link JCodeModel#isCaseSensitiveFileSystem}) to avoid conflicts.
    88      *
    89      * Lazily created to save footprint.
    90      *
    91      * @see #getClasses()
    92      */
    93     private Map<String,JDefinedClass> classes;
    96     /**
    97      * Flag that controls whether this class should be really generated or not.
    98      *
    99      * Sometimes it is useful to generate code that refers to class X,
   100      * without actually generating the code of X.
   101      * This flag is used to surpress X.java file in the output.
   102      */
   103     private boolean hideFile = false;
   105     /**
   106      * Client-app spcific metadata associated with this user-created class.
   107      */
   108     public Object metadata;
   110     /**
   111      * String that will be put directly inside the generated code.
   112      * Can be null.
   113      */
   114     private String directBlock;
   116     /**
   117      * If this is a package-member class, this is {@link JPackage}.
   118      * If this is a nested class, this is {@link JDefinedClass}.
   119      * If this is an anonymous class, this constructor shouldn't be used.
   120      */
   121     private JClassContainer outer = null;
   124     /** Default value is class or interface
   125      *  or annotationTypeDeclaration
   126      *  or enum
   127      *
   128      */
   129     private final ClassType classType;
   131     /** List containing the enum value declarations
   132      *
   133      */
   134 //    private List enumValues = new ArrayList();
   136     /**
   137      * Set of enum constants that are keyed by names.
   138      * In Java, enum constant order is actually significant,
   139      * because of order ID they get. So let's preserve the order.
   140      */
   141     private final Map<String,JEnumConstant> enumConstantsByName = new LinkedHashMap<String,JEnumConstant>();
   143     /**
   144      * Annotations on this variable. Lazily created.
   145      */
   146     private List<JAnnotationUse> annotations = null;
   149     /**
   150      * Helper class to implement {@link JGenerifiable}.
   151      */
   152     private final JGenerifiableImpl generifiable = new JGenerifiableImpl() {
   153         protected JCodeModel owner() {
   154             return JDefinedClass.this.owner();
   155         }
   156     };
   158     JDefinedClass(JClassContainer parent, int mods, String name, ClassType classTypeval) {
   159         this(mods, name, parent, parent.owner(), classTypeval);
   160     }
   162     /**
   163      * Constructor for creating anonymous inner class.
   164      */
   165     JDefinedClass(
   166         JCodeModel owner,
   167         int mods,
   168         String name) {
   169         this(mods, name, null, owner);
   170     }
   172     private JDefinedClass(
   173             int mods,
   174             String name,
   175             JClassContainer parent,
   176             JCodeModel owner) {
   177         this (mods,name,parent,owner,ClassType.CLASS);
   178     }
   180     /**
   181      * JClass constructor
   182      *
   183      * @param mods
   184      *        Modifiers for this class declaration
   185      *
   186      * @param name
   187      *        Name of this class
   188      */
   189     private JDefinedClass(
   190         int mods,
   191         String name,
   192         JClassContainer parent,
   193         JCodeModel owner,
   194                 ClassType classTypeVal) {
   195         super(owner);
   197         if(name!=null) {
   198             if (name.trim().length() == 0)
   199                 throw new IllegalArgumentException("JClass name empty");
   201             if (!Character.isJavaIdentifierStart(name.charAt(0))) {
   202                 String msg =
   203                     "JClass name "
   204                         + name
   205                         + " contains illegal character"
   206                         + " for beginning of identifier: "
   207                         + name.charAt(0);
   208                 throw new IllegalArgumentException(msg);
   209             }
   210             for (int i = 1; i < name.length(); i++) {
   211                 if (!Character.isJavaIdentifierPart(name.charAt(i))) {
   212                     String msg =
   213                         "JClass name "
   214                             + name
   215                             + " contains illegal character "
   216                             + name.charAt(i);
   217                     throw new IllegalArgumentException(msg);
   218                 }
   219             }
   220         }
   222         this.classType = classTypeVal;
   223         if (isInterface())
   224             this.mods = JMods.forInterface(mods);
   225         else
   226             this.mods = JMods.forClass(mods);
   228         this.name = name;
   230         this.outer = parent;
   231     }
   233     /**
   234      * Returns true if this is an anonymous class.
   235      */
   236     public final boolean isAnonymous() {
   237         return name == null;
   238     }
   240     /**
   241      * This class extends the specifed class.
   242      *
   243      * @param superClass
   244      *        Superclass for this class
   245      *
   246      * @return This class
   247      */
   248     public JDefinedClass _extends(JClass superClass) {
   249         if (this.classType==ClassType.INTERFACE)
   250             throw new IllegalArgumentException("unable to set the super class for an interface");
   251         if (superClass == null)
   252             throw new NullPointerException();
   254         for( JClass o=superClass.outer(); o!=null; o=o.outer() ){
   255             if(this==o){
   256                 throw new IllegalArgumentException("Illegal class inheritance loop." +
   257                 "  Outer class " + this.name + " may not subclass from inner class: " + o.name());
   258             }
   259         }
   261         this.superClass = superClass;
   262         return this;
   263     }
   265     public JDefinedClass _extends(Class superClass) {
   266         return _extends(owner().ref(superClass));
   267     }
   269     /**
   270      * Returns the class extended by this class.
   271      */
   272     public JClass _extends() {
   273         if(superClass==null)
   274             superClass = owner().ref(Object.class);
   275         return superClass;
   276     }
   278     /**
   279      * This class implements the specifed interface.
   280      *
   281      * @param iface
   282      *        Interface that this class implements
   283      *
   284      * @return This class
   285      */
   286     public JDefinedClass _implements(JClass iface) {
   287         interfaces.add(iface);
   288         return this;
   289     }
   291     public JDefinedClass _implements(Class iface) {
   292         return _implements(owner().ref(iface));
   293     }
   295     /**
   296      * Returns an iterator that walks the nested classes defined in this
   297      * class.
   298      */
   299     public Iterator<JClass> _implements() {
   300         return interfaces.iterator();
   301     }
   303     /**
   304      * JClass name accessor.
   305      *
   306      * <p>
   307      * For example, for <code>java.util.List</code>, this method
   308      * returns <code>"List"</code>"
   309      *
   310      * @return Name of this class
   311      */
   312     public String name() {
   313         return name;
   314     }
   316     /**
   317      * If the named enum already exists, the reference to it is returned.
   318      * Otherwise this method generates a new enum reference with the given
   319      * name and returns it.
   320      *
   321      * @param name
   322      *          The name of the constant.
   323      * @return
   324      *      The generated type-safe enum constant.
   325      */
   326     public JEnumConstant enumConstant(String name){
   327         JEnumConstant ec = enumConstantsByName.get(name);
   328         if (null == ec) {
   329             ec = new JEnumConstant(this, name);
   330             enumConstantsByName.put(name, ec);
   331         }
   332         return ec;
   333     }
   335     /**
   336      * Gets the fully qualified name of this class.
   337      */
   338     public String fullName() {
   339         if (outer instanceof JDefinedClass)
   340             return ((JDefinedClass) outer).fullName() + '.' + name();
   342         JPackage p = _package();
   343         if (p.isUnnamed())
   344             return name();
   345         else
   346             return p.name() + '.' + name();
   347     }
   349     public String binaryName() {
   350         if (outer instanceof JDefinedClass)
   351             return ((JDefinedClass) outer).binaryName() + '$' + name();
   352         else
   353             return fullName();
   354     }
   356     public boolean isInterface() {
   357         return this.classType==ClassType.INTERFACE;
   358     }
   360     public boolean isAbstract() {
   361         return mods.isAbstract();
   362     }
   364     /**
   365      * Adds a field to the list of field members of this JDefinedClass.
   366      *
   367      * @param mods
   368      *        Modifiers for this field
   369      *
   370      * @param type
   371      *        JType of this field
   372      *
   373      * @param name
   374      *        Name of this field
   375      *
   376      * @return Newly generated field
   377      */
   378     public JFieldVar field(int mods, JType type, String name) {
   379         return field(mods, type, name, null);
   380     }
   382     public JFieldVar field(int mods, Class type, String name) {
   383         return field(mods, owner()._ref(type), name);
   384     }
   386     /**
   387      * Adds a field to the list of field members of this JDefinedClass.
   388      *
   389      * @param mods
   390      *        Modifiers for this field.
   391      * @param type
   392      *        JType of this field.
   393      * @param name
   394      *        Name of this field.
   395      * @param init
   396      *        Initial value of this field.
   397      *
   398      * @return Newly generated field
   399      */
   400     public JFieldVar field(
   401         int mods,
   402         JType type,
   403         String name,
   404         JExpression init) {
   405         JFieldVar f = new JFieldVar(this,JMods.forField(mods), type, name, init);
   407         if(fields.put(name, f)!=null)
   408             throw new IllegalArgumentException("trying to create the same field twice: "+name);
   410         return f;
   411     }
   413     /**  This method indicates if the interface
   414      *   is an annotationTypeDeclaration
   415      *
   416      */
   417     public boolean isAnnotationTypeDeclaration() {
   418         return this.classType==ClassType.ANNOTATION_TYPE_DECL;
   421     }
   423     /**
   424      * Add an annotationType Declaration to this package
   425      * @param name
   426      *      Name of the annotation Type declaration to be added to this package
   427      * @return
   428      *      newly created Annotation Type Declaration
   429      * @exception JClassAlreadyExistsException
   430      *      When the specified class/interface was already created.
   432      */
   433     public JDefinedClass _annotationTypeDeclaration(String name) throws JClassAlreadyExistsException {
   434         return _class (JMod.PUBLIC,name,ClassType.ANNOTATION_TYPE_DECL);
   435     }
   437     /**
   438      * Add a public enum to this package
   439      * @param name
   440      *      Name of the enum to be added to this package
   441      * @return
   442      *      newly created Enum
   443      * @exception JClassAlreadyExistsException
   444      *      When the specified class/interface was already created.
   446      */
   447     public JDefinedClass _enum (String name) throws JClassAlreadyExistsException {
   448         return _class (JMod.PUBLIC,name,ClassType.ENUM);
   449     }
   451     /**
   452      * Add a public enum to this package
   453      * @param name
   454      *      Name of the enum to be added to this package
   455      * @param mods
   456      *          Modifiers for this enum declaration
   457      * @return
   458      *      newly created Enum
   459      * @exception JClassAlreadyExistsException
   460      *      When the specified class/interface was already created.
   462      */
   463     public JDefinedClass _enum (int mods,String name) throws JClassAlreadyExistsException {
   464         return _class (mods,name,ClassType.ENUM);
   465     }
   471     public ClassType getClassType(){
   472         return this.classType;
   473     }
   475     public JFieldVar field(
   476         int mods,
   477         Class type,
   478         String name,
   479         JExpression init) {
   480         return field(mods, owner()._ref(type), name, init);
   481     }
   483     /**
   484      * Returns all the fields declred in this class.
   485      * The returned {@link Map} is a read-only live view.
   486      *
   487      * @return always non-null.
   488      */
   489     public Map<String,JFieldVar> fields() {
   490         return Collections.unmodifiableMap(fields);
   491     }
   493     /**
   494      * Removes a {@link JFieldVar} from this class.
   495      *
   496      * @throws IllegalArgumentException
   497      *      if the given field is not a field on this class.
   498      */
   499     public void removeField(JFieldVar field) {
   500         if(fields.remove(field.name())!=field)
   501             throw new IllegalArgumentException();
   502     }
   504     /**
   505      * Creates, if necessary, and returns the static initializer
   506      * for this class.
   507      *
   508      * @return JBlock containing initialization statements for this class
   509      */
   510     public JBlock init() {
   511         if (init == null)
   512             init = new JBlock();
   513         return init;
   514     }
   516     /**
   517      * Adds a constructor to this class.
   518      *
   519      * @param mods
   520      *        Modifiers for this constructor
   521      */
   522     public JMethod constructor(int mods) {
   523         JMethod c = new JMethod(mods, this);
   524         constructors.add(c);
   525         return c;
   526     }
   528     /**
   529      * Returns an iterator that walks the constructors defined in this class.
   530      */
   531     public Iterator constructors() {
   532         return constructors.iterator();
   533     }
   535     /**
   536      * Looks for a method that has the specified method signature
   537      * and return it.
   538      *
   539      * @return
   540      *      null if not found.
   541      */
   542     public JMethod getConstructor(JType[] argTypes) {
   543         for (JMethod m : constructors) {
   544             if (m.hasSignature(argTypes))
   545                 return m;
   546         }
   547         return null;
   548     }
   550     /**
   551      * Add a method to the list of method members of this JDefinedClass instance.
   552      *
   553      * @param mods
   554      *        Modifiers for this method
   555      *
   556      * @param type
   557      *        Return type for this method
   558      *
   559      * @param name
   560      *        Name of the method
   561      *
   562      * @return Newly generated JMethod
   563      */
   564     public JMethod method(int mods, JType type, String name) {
   565         // XXX problems caught in M constructor
   566         JMethod m = new JMethod(this, mods, type, name);
   567         methods.add(m);
   568         return m;
   569     }
   571     public JMethod method(int mods, Class type, String name) {
   572         return method(mods, owner()._ref(type), name);
   573     }
   575     /**
   576      * Returns the set of methods defined in this class.
   577      */
   578     public Collection<JMethod> methods() {
   579         return methods;
   580     }
   582     /**
   583      * Looks for a method that has the specified method signature
   584      * and return it.
   585      *
   586      * @return
   587      *      null if not found.
   588      */
   589     public JMethod getMethod(String name, JType[] argTypes) {
   590         for (JMethod m : methods) {
   591             if (!m.name().equals(name))
   592                 continue;
   594             if (m.hasSignature(argTypes))
   595                 return m;
   596         }
   597         return null;
   598     }
   600     public boolean isClass() {
   601         return true;
   602     }
   603     public boolean isPackage() {
   604         return false;
   605     }
   606     public JPackage getPackage() { return parentContainer().getPackage(); }
   608     /**
   609      * Add a new nested class to this class.
   610      *
   611      * @param mods
   612      *        Modifiers for this class declaration
   613      *
   614      * @param name
   615      *        Name of class to be added to this package
   616      *
   617      * @return Newly generated class
   618      */
   619     public JDefinedClass _class(int mods, String name)
   620         throws JClassAlreadyExistsException {
   621         return _class(mods, name, ClassType.CLASS);
   622     }
   624     /**
   625      * {@inheritDoc}
   626      *
   627      * @deprecated
   628      */
   629     public JDefinedClass _class(int mods, String name, boolean isInterface) throws JClassAlreadyExistsException {
   630         return _class(mods,name,isInterface?ClassType.INTERFACE:ClassType.CLASS);
   631     }
   633     public JDefinedClass _class(int mods, String name, ClassType classTypeVal)
   634         throws JClassAlreadyExistsException {
   636         String NAME;
   637         if (JCodeModel.isCaseSensitiveFileSystem)
   638             NAME = name.toUpperCase();
   639         else
   640             NAME = name;
   642         if (getClasses().containsKey(NAME))
   643             throw new JClassAlreadyExistsException(getClasses().get(NAME));
   644         else {
   645             // XXX problems caught in the NC constructor
   646             JDefinedClass c = new JDefinedClass(this, mods, name, classTypeVal);
   647             getClasses().put(NAME,c);
   648             return c;
   649         }
   650     }
   652     /**
   653      * Add a new public nested class to this class.
   654      */
   655     public JDefinedClass _class(String name)
   656         throws JClassAlreadyExistsException {
   657         return _class(JMod.PUBLIC, name);
   658     }
   660     /**
   661      * Add an interface to this package.
   662      *
   663      * @param mods
   664      *        Modifiers for this interface declaration
   665      *
   666      * @param name
   667      *        Name of interface to be added to this package
   668      *
   669      * @return Newly generated interface
   670      */
   671     public JDefinedClass _interface(int mods, String name)
   672         throws JClassAlreadyExistsException {
   673         return _class(mods, name, ClassType.INTERFACE);
   674     }
   676     /**
   677      * Adds a public interface to this package.
   678      */
   679     public JDefinedClass _interface(String name)
   680         throws JClassAlreadyExistsException {
   681         return _interface(JMod.PUBLIC, name);
   682     }
   684     /**
   685      * Creates, if necessary, and returns the class javadoc for this
   686      * JDefinedClass
   687      *
   688      * @return JDocComment containing javadocs for this class
   689      */
   690     public JDocComment javadoc() {
   691         if (jdoc == null)
   692             jdoc = new JDocComment(owner());
   693         return jdoc;
   694     }
   696     /**
   697      * Mark this file as hidden, so that this file won't be
   698      * generated.
   699      *
   700      * <p>
   701      * This feature could be used to generate code that refers
   702      * to class X, without actually generating X.java.
   703      */
   704     public void hide() {
   705         hideFile = true;
   706     }
   708     public boolean isHidden() {
   709         return hideFile;
   710     }
   712     /**
   713      * Returns an iterator that walks the nested classes defined in this
   714      * class.
   715      */
   716     public final Iterator<JDefinedClass> classes() {
   717         if(classes==null)
   718             return Collections.<JDefinedClass>emptyList().iterator();
   719         else
   720             return classes.values().iterator();
   721     }
   723     private Map<String,JDefinedClass> getClasses() {
   724         if(classes==null)
   725             classes = new TreeMap<String,JDefinedClass>();
   726         return classes;
   727     }
   730     /**
   731      * Returns all the nested classes defined in this class.
   732      */
   733     public final JClass[] listClasses() {
   734         if(classes==null)
   735             return new JClass[0];
   736         else
   737             return classes.values().toArray(new JClass[classes.values().size()]);
   738     }
   740     @Override
   741     public JClass outer() {
   742         if (outer.isClass())
   743             return (JClass) outer;
   744         else
   745             return null;
   746     }
   748     public void declare(JFormatter f) {
   749         if (jdoc != null)
   750             f.nl().g(jdoc);
   752         if (annotations != null){
   753             for (JAnnotationUse annotation : annotations)
   754                 f.g(annotation).nl();
   755         }
   757         f.g(mods).p(classType.declarationToken).id(name).d(generifiable);
   759         if (superClass != null && superClass != owner().ref(Object.class))
   760             f.nl().i().p("extends").g(superClass).nl().o();
   762         if (!interfaces.isEmpty()) {
   763             if (superClass == null)
   764                 f.nl();
   765             f.i().p(classType==ClassType.INTERFACE ? "extends" : "implements");
   766             f.g(interfaces);
   767             f.nl().o();
   768         }
   769         declareBody(f);
   770     }
   772     /**
   773      * prints the body of a class.
   774      */
   775     protected void declareBody(JFormatter f) {
   776         f.p('{').nl().nl().i();
   777         boolean first = true;
   779         if (!enumConstantsByName.isEmpty()) {
   780             for (JEnumConstant c : enumConstantsByName.values()) {
   781                 if (!first) f.p(',').nl();
   782                 f.d(c);
   783                 first = false;
   784             }
   785                 f.p(';').nl();
   786         }
   788         for( JFieldVar field : fields.values() )
   789             f.d(field);
   790         if (init != null)
   791             f.nl().p("static").s(init);
   792         for (JMethod m : constructors) {
   793             f.nl().d(m);
   794         }
   795         for (JMethod m : methods) {
   796             f.nl().d(m);
   797         }
   798         if(classes!=null)
   799             for (JDefinedClass dc : classes.values())
   800                 f.nl().d(dc);
   803         if (directBlock != null)
   804             f.p(directBlock);
   805         f.nl().o().p('}').nl();
   806     }
   808     /**
   809      * Places the given string directly inside the generated class.
   810      *
   811      * This method can be used to add methods/fields that are not
   812      * generated by CodeModel.
   813      * This method should be used only as the last resort.
   814      */
   815     public void direct(String string) {
   816         if (directBlock == null)
   817             directBlock = string;
   818         else
   819             directBlock += string;
   820     }
   822     public final JPackage _package() {
   823         JClassContainer p = outer;
   824         while (!(p instanceof JPackage))
   825             p = p.parentContainer();
   826         return (JPackage) p;
   827     }
   829     public final JClassContainer parentContainer() {
   830         return outer;
   831     }
   833     public JTypeVar generify(String name) {
   834         return generifiable.generify(name);
   835     }
   836     public JTypeVar generify(String name, Class bound) {
   837         return generifiable.generify(name, bound);
   838     }
   839     public JTypeVar generify(String name, JClass bound) {
   840         return generifiable.generify(name, bound);
   841     }
   842     @Override
   843     public JTypeVar[] typeParams() {
   844         return generifiable.typeParams();
   845     }
   847     protected JClass substituteParams(
   848         JTypeVar[] variables,
   849         List<JClass> bindings) {
   850         return this;
   851     }
   853     /** Adding ability to annotate a class
   854      * @param clazz
   855      *          The annotation class to annotate the class with
   856      */
   857     public JAnnotationUse annotate(Class <? extends Annotation> clazz){
   858         return annotate(owner().ref(clazz));
   859     }
   861     /** Adding ability to annotate a class
   862       * @param clazz
   863       *          The annotation class to annotate the class with
   864       */
   865      public JAnnotationUse annotate(JClass clazz){
   866         if(annotations==null)
   867            annotations = new ArrayList<JAnnotationUse>();
   868         JAnnotationUse a = new JAnnotationUse(clazz);
   869         annotations.add(a);
   870         return a;
   871     }
   873     public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) {
   874         return TypedAnnotationWriter.create(clazz,this);
   875     }
   876 }

mercurial