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 }