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 }