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