View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 1999-2002 (C) Intalio, Inc. All Rights Reserved.
32   */
33  package org.exolab.javasource;
34  
35  import java.util.Enumeration;
36  
37  import org.exolab.castor.builder.SourceGenerator;
38  
39  /**
40   * A representation of the Java Source code for a Java Class. This is a useful utility when creating
41   * in memory source code. This package was modelled after the Java Reflection API as much as
42   * possible to reduce the learning curve.
43   *
44   * @author <a href="mailto:keith AT kvisco DOT com">Keith Visco</a>
45   * @author <a href="mailto:skopp AT riege DOT de">Martin Skopp</a>
46   * @version $Revision$ $Date: 2005-05-08 12:32:06 -0600 (Sun, 08 May 2005) $
47   */
48  public class JClass extends AbstractJClass {
49  
50    /** The superclass for this JClass. */
51    private JTypeName _superClass;
52  
53    /**
54     * Creates a new JClass with the given name.
55     *
56     * @param name The name of the JClass to create.
57     */
58    public JClass(final String name) {
59      super(name);
60  
61      _superClass = null;
62    }
63  
64    /**
65     * Creates a new JClass with the given name.
66     *
67     * @param name The name of the JClass to create.
68     * @param useOldFieldNaming Whether to use old field naming conventions
69     */
70    public JClass(final String name, boolean useOldFieldNaming) {
71      super(name, useOldFieldNaming);
72  
73      _superClass = null;
74    }
75  
76    /**
77     * {@inheritDoc}
78     */
79    public final void addImport(final String className) {
80      if ((className == null) || (className.length() == 0)) {
81        return;
82      }
83  
84      JTypeName jtName = new JTypeName(className);
85  
86      String cls = jtName.getLocalName();
87      String pkg = jtName.getPackageName();
88  
89      // If we are extending a class from the default package which conflicts
90      // with this import then we cannot import this class
91      if (_superClass != null && _superClass.getLocalName().equals(cls)) {
92        if (_superClass.getPackageName() == null && pkg != null) {
93          return;
94        }
95      }
96  
97      addImportInternal(className);
98    }
99  
100   /**
101    * {@inheritDoc}
102    */
103   public void addMember(final JMember jMember) {
104     if (jMember instanceof JField) {
105       addField((JField) jMember);
106     } else if (jMember instanceof JConstant) {
107       addConstant(((JConstant) jMember));
108     } else if (jMember instanceof JMethod) {
109       addMethod((JMethod) jMember);
110     } else {
111       String error = null;
112       if (jMember == null) {
113         error = "the argument 'jMember' must not be null.";
114       } else {
115         error = "Cannot add JMember '" + jMember.getClass().getName()
116             + "' to JClass, unrecognized type.";
117       }
118       throw new IllegalArgumentException(error);
119     }
120   }
121 
122   /**
123    * Returns the super class that this class extends.
124    *
125    * @return superClass The super class that this class extends.
126    */
127   public final JTypeName getSuperClass() {
128     return _superClass;
129   }
130 
131   /**
132    * Returns the qualified name of the super class that this class extends.
133    *
134    * @return superClass The qualified name of the super class that this class extends.
135    */
136   public final String getSuperClassQualifiedName() {
137     if (_superClass == null) {
138       return null;
139     }
140     return _superClass.getQualifiedName();
141   }
142 
143   /**
144    * Sets the super Class that this class extends.
145    *
146    * @param superClass The super Class that this Class extends.
147    */
148   public final void setSuperClass(final String superClass) {
149     if (superClass == null) {
150       _superClass = null;
151     } else {
152       _superClass = new JTypeName(superClass);
153     }
154   }
155 
156   /**
157    * {@inheritDoc}
158    * 
159    * @deprecated Please use the Velocity-template based approach instead.
160    * @see SourceGenerator#setJClassPrinterType(String)
161    */
162   public void print(final JSourceWriter jsw, final boolean classOnly) {
163     if (jsw == null) {
164       throw new IllegalArgumentException("argument 'jsw' should not be null.");
165     }
166 
167     // -- print class headers (comment header, package, imports) if desired
168     if (!classOnly) {
169       printClassHeaders(jsw);
170     }
171 
172     getJDocComment().print(jsw);
173 
174     printClassDefinitionLine(jsw); // includes the opening '{'
175 
176     jsw.writeln();
177     jsw.indent();
178 
179     printConstantDefinitions(jsw);
180     printMemberVariables(jsw);
181     printStaticInitializers(jsw);
182     printConstructors(jsw);
183     printMethods(jsw);
184     printInnerClasses(jsw);
185     printSourceCodeFragments(jsw);
186 
187     jsw.unindent();
188     jsw.writeln('}');
189     jsw.flush();
190   }
191 
192   /**
193    * Writes to the JSourceWriter the line that defines this class. This line includes the class
194    * name, extends and implements entries, and any modifiers such as "private".
195    * 
196    * @param jsw The JSourceWriter to be used.
197    */
198   private void printClassDefinitionLine(final JSourceWriter jsw) {
199     StringBuilder buffer = new StringBuilder(32);
200 
201     // -- first print our annotations
202     getAnnotatedElementHelper().printAnnotations(jsw);
203 
204     // -- next our modifiers
205     JModifiers modifiers = getModifiers();
206     if (modifiers.isPrivate()) {
207       buffer.append("private ");
208     } else if (modifiers.isPublic()) {
209       buffer.append("public ");
210     }
211 
212     if (modifiers.isFinal()) {
213       buffer.append("final ");
214     }
215 
216     if (modifiers.isAbstract()) {
217       buffer.append("abstract ");
218     }
219 
220     // -- next our class name plus extends and implements entries
221     buffer.append("class ");
222     buffer.append(getLocalName());
223     buffer.append(' ');
224     if (_superClass != null) {
225       buffer.append("extends ");
226       buffer.append(_superClass);
227       buffer.append(' ');
228     }
229     if (getInterfaceCount() > 0) {
230       boolean endl = false;
231       if ((getInterfaceCount() > 1) || (_superClass != null)) {
232         jsw.writeln(buffer.toString());
233         buffer.setLength(0);
234         endl = true;
235       }
236       buffer.append("implements ");
237 
238       Enumeration<String> enumeration = getInterfaces();
239       while (enumeration.hasMoreElements()) {
240         buffer.append(enumeration.nextElement());
241         if (enumeration.hasMoreElements()) {
242           buffer.append(", ");
243         }
244       }
245       if (endl) {
246         jsw.writeln(buffer.toString());
247         buffer.setLength(0);
248       } else {
249         buffer.append(' ');
250       }
251     }
252 
253     // -- and we're done
254     buffer.append('{');
255     jsw.writeln(buffer.toString());
256     buffer.setLength(0);
257   }
258 
259 
260   /**
261    * Changes the local name of this class type.
262    * 
263    * @param localName The new local name to be used.
264    */
265   public void changeLocalName(final String localName) {
266     String packageName = getPackageName();
267     if (packageName != null) {
268       setName(packageName + "." + localName);
269     } else {
270       setName(localName);
271     }
272   }
273 
274 }