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@codehaus.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.codehaus.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   * $Id$
44   *
45   * Contributors:
46   * --------------
47   * Keith Visco (kvisco@intalio.com) - Original Author
48   * Martin Skopp (skopp@riege.de)    - Moved some core code into JStructure
49   *                                    and revised to extend JStructure
50   *
51   */
52  
53  package org.codehaus.modello.plugin.java.javasource;
54  
55  /*
56   * Copyright (c) 2004, Codehaus.org
57   *
58   * Permission is hereby granted, free of charge, to any person obtaining a copy of
59   * this software and associated documentation files (the "Software"), to deal in
60   * the Software without restriction, including without limitation the rights to
61   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
62   * of the Software, and to permit persons to whom the Software is furnished to do
63   * so, subject to the following conditions:
64   *
65   * The above copyright notice and this permission notice shall be included in all
66   * copies or substantial portions of the Software.
67   *
68   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
69   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
70   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
72   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
73   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
74   * SOFTWARE.
75   */
76  
77  import java.util.ArrayList;
78  import java.util.Enumeration;
79  import java.util.List;
80  import java.util.Vector;
81  
82  /**
83   * A representation of the Java Source code for a Java Class. This is
84   * a useful utility when creating in memory source code.
85   * This package was modelled after the Java Reflection API
86   * as much as possible to reduce the learning curve.
87   *
88   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
89   * @author <a href="mailto:skopp@riege.de">Martin Skopp</a>
90   * @version $Revision$ $Date$
91   */
92  public class JClass extends JStructure
93  {
94  
95  
96      /**
97       * The list of constructors for this JClass
98       */
99      private Vector<JConstructor> _constructors = null;
100 
101 
102     /**
103      * The list of member variables (fields) of this JClass
104      */
105     private JNamedMap _fields = null;
106 
107 
108     private Vector<JClass> _innerClasses = null;
109 
110     /**
111      * The list of methods of this JClass
112      */
113     private Vector<JMethod> _methods = null;
114 
115     /**
116      * The superclass for this JClass
117      */
118     private String _superClass = null;
119 
120 
121     /**
122      * The source code for static initialization
123      **/
124     private JSourceCode _staticInitializer = new JSourceCode();
125 
126     /**
127      * Creates a new JClass with the given name
128      * @param name the name of the JClass to create
129      * @exception java.lang.IllegalArgumentException when the given name
130      * is not a valid Class name
131      **/
132     public JClass( String name )
133         throws IllegalArgumentException
134     {
135         super( name );
136         _constructors = new Vector<JConstructor>();
137         _fields = new JNamedMap();
138         _methods = new Vector<JMethod>();
139         _innerClasses = new Vector<JClass>();
140         //-- initialize default Java doc
141         getJDocComment().appendComment( "Class " + getLocalName() + "." );
142 
143     } //-- JClass
144 
145 
146     /**
147      * Adds the given Constructor to this classes list of constructors.
148      * The constructor must have been created with this JClass'
149      * createConstructor.
150      *
151      * @throws java.lang.IllegalArgumentException
152      */
153     public void addConstructor( JConstructor constructor )
154         throws IllegalArgumentException
155     {
156         if ( constructor == null )
157             throw new IllegalArgumentException( "Constructors cannot be null" );
158 
159         if ( constructor.getDeclaringClass() == this )
160         {
161 
162             /** check signatures (add later) **/
163             if ( !_constructors.contains( constructor ) )
164             {
165                 _constructors.addElement( constructor );
166             }
167         }
168         else
169         {
170             String err = "The given JConstructor was not created ";
171             err += "by this JClass";
172             throw new IllegalArgumentException( err );
173         }
174     }
175 
176     /**
177      * Adds the given JField to this JClass
178      *
179      * @param jField, the JField to add
180      * @exception java.lang.IllegalArgumentException when the given
181      * JField has a name of an existing JField
182      **/
183     public void addField( JField jField )
184         throws IllegalArgumentException
185     {
186         if ( jField == null )
187         {
188             throw new IllegalArgumentException( "Class members cannot be null" );
189         }
190 
191         String name = jField.getName();
192 
193         if ( _fields.get( name ) != null )
194         {
195             String err = "duplicate name found: " + name;
196             throw new IllegalArgumentException( err );
197         }
198         _fields.put( name, jField );
199 
200     } //-- addField
201 
202     /**
203      * Adds the given JMember to this JClass
204      *
205      * @param jMember, the JMember to add
206      * @exception java.lang.IllegalArgumentException when the given
207      * JMember has the same name of an existing JField
208      * or JMethod respectively, or if the JMember is of an
209      * unrecognized class.
210      **/
211     public void addMember( JMember jMember )
212         throws IllegalArgumentException
213     {
214         if ( jMember instanceof JField )
215             addField( (JField) jMember );
216         else if ( jMember instanceof JMethod )
217             addMethod( (JMethod) jMember );
218         else
219         {
220             String error = null;
221             if ( jMember == null )
222             {
223                 error = "the argument 'jMember' must not be null.";
224             }
225             else
226             {
227                 error = "Cannot add JMember '" + jMember.getClass().getName() +
228                     "' to JClass, unrecognized type.";
229             }
230             throw new IllegalArgumentException( error );
231         }
232 
233     } //-- addMember
234 
235     /**
236      * Adds the given JMethod to this JClass
237      *
238      * @param jMethod, the JMethod to add
239      * @param importReturnType true if we add the importReturnType to
240      * the class import lists. It could be useful to set it to false when
241      * all types are fully qualified.
242      * @exception java.lang.IllegalArgumentException when the given
243      * JMethod has the same name of an existing JMethod.
244      **/
245     public void addMethod( JMethod jMethod )
246     {
247         addMethod( jMethod, true );
248     }
249 
250     /**
251      * Adds the given JMethod to this JClass
252      *
253      * @param jMethod, the JMethod to add
254      * @param importReturnType true if we add the importReturnType to
255      * the class import lists. It could be useful to set it to false when
256      * all types are fully qualified.
257      * @exception java.lang.IllegalArgumentException when the given
258      * JMethod has the same name of an existing JMethod.
259      **/
260     public void addMethod( JMethod jMethod, boolean importReturnType )
261         throws IllegalArgumentException
262     {
263         if ( jMethod == null )
264         {
265             throw new IllegalArgumentException( "Class methods cannot be null" );
266         }
267 
268         //-- check method name and signatures *add later*
269 
270         //-- keep method list sorted for esthetics when printing
271         //-- START SORT :-)
272         boolean added = false;
273 //        short modifierVal = 0;
274         JModifiers modifiers = jMethod.getModifiers();
275 
276         if ( modifiers.isAbstract() )
277         {
278             getModifiers().setAbstract( true );
279         }
280 
281         for ( int i = 0; i < _methods.size(); i++ )
282         {
283             JMethod tmp = (JMethod) _methods.elementAt( i );
284             //-- first compare modifiers
285             if ( tmp.getModifiers().isPrivate() )
286             {
287                 if ( !modifiers.isPrivate() )
288                 {
289                     _methods.insertElementAt( jMethod, i );
290                     added = true;
291                     break;
292                 }
293             }
294             //-- compare names
295             if ( jMethod.getName().compareTo( tmp.getName() ) < 0 )
296             {
297                 _methods.insertElementAt( jMethod, i );
298                 added = true;
299                 break;
300             }
301         }
302         //-- END SORT
303         if ( !added ) _methods.addElement( jMethod );
304 
305     } //-- addMethod
306 
307     /**
308      * Adds the given array of JMethods to this JClass
309      *
310      * @param jMethods, the JMethod[] to add
311      * @exception java.lang.IllegalArgumentException when any of the given
312      * JMethods has the same name of an existing JMethod.
313      **/
314     public void addMethods( JMethod[] jMethods )
315         throws IllegalArgumentException
316     {
317         for ( JMethod jMethod : jMethods )
318         {
319             addMethod( jMethod );
320         }
321     } //-- addMethods
322 
323 
324     /**
325      * Creates a new JConstructor and adds it to this
326      * JClass.
327      *
328      * @return the newly created constructor
329      */
330     public JConstructor createConstructor()
331     {
332         return createConstructor( null );
333     } //-- createConstructor
334 
335     /**
336      * Creates a new JConstructor and adds it to this
337      * JClass.
338      *
339      * @return the newly created constructor
340      */
341     public JConstructor createConstructor( JParameter[] params )
342     {
343         JConstructor cons = new JConstructor( this );
344         if ( params != null )
345         {
346             for ( JParameter param : params )
347             {
348                 cons.addParameter( param );
349             }
350         }
351         addConstructor( cons );
352         return cons;
353     } //-- createConstructor
354 
355     /**
356      * Creates and returns an inner-class for this JClass
357      *
358      * @param localname the name of the class (no package name)
359      * @return the new JClass
360      */
361     public JClass createInnerClass( String localname )
362     {
363         if ( localname == null )
364         {
365             String err = "argument 'localname' must not be null.";
366             throw new IllegalArgumentException( err );
367         }
368         if ( localname.indexOf( '.' ) >= 0 )
369         {
370             String err = "The name of an inner-class must not contain a package name.";
371             throw new IllegalArgumentException( err );
372         }
373         String classname = getPackageName();
374         if ( classname != null )
375         {
376             classname = classname + "." + localname;
377         }
378         else
379         {
380             classname = localname;
381         }
382 
383         JClass innerClass = new JInnerClass( classname );
384         _innerClasses.addElement( innerClass );
385         return innerClass;
386 
387     } //-- createInnerClass
388 
389     /**
390      * Returns the constructor at the specified index.
391      *
392      * @param index the index of the constructor to return
393      * @return the JConstructor at the specified index.
394      */
395     public JConstructor getConstructor( int index )
396     {
397         return (JConstructor) _constructors.elementAt( index );
398     } //-- getConstructor
399 
400     /**
401      * Returns the an array of the JConstructors contained within this JClass
402      *
403      * @return an array of JConstructor
404      */
405     public JConstructor[] getConstructors()
406     {
407 
408         int size = _constructors.size();
409         JConstructor[] jcArray = new JConstructor[size];
410 
411         for ( int i = 0; i < _constructors.size(); i++ )
412         {
413             jcArray[i] = (JConstructor) _constructors.elementAt( i );
414         }
415         return jcArray;
416     } //-- getConstructors
417 
418 
419     /**
420      * Returns the member with the given name, or null if no member
421      * was found with the given name
422      * @param name the name of the member to return
423      * @return the member with the given name, or null if no member
424      * was found with the given name
425      **/
426     public JField getField( String name )
427     {
428         return (JField) _fields.get( name );
429     } //-- getField
430 
431     /**
432      * Returns an array of all the JFields of this JClass
433      * @return an array of all the JFields of this JClass
434      **/
435     public JField[] getFields()
436     {
437         int size = _fields.size();
438         JField[] farray = new JField[size];
439         for ( int i = 0; i < size; i++ )
440         {
441             farray[i] = (JField) _fields.get( i );
442         }
443         return farray;
444     } //-- getFields
445 
446     /**
447      * Returns an array of JClass (the inner classes)
448      * contained within this JClass.
449      *
450      * @return an array of JClass contained within this JClass
451      */
452     public JClass[] getInnerClasses()
453     {
454         int size = _innerClasses.size();
455         JClass[] carray = new JClass[size];
456         _innerClasses.copyInto( carray );
457         return carray;
458     } //-- getInnerClasses;
459 
460     /**
461      * Returns an array of all the JMethods of this JClass
462      *
463      * @return an array of all the JMethods of this JClass
464      */
465     public JMethod[] getMethods()
466     {
467         int size = _methods.size();
468         JMethod[] marray = new JMethod[size];
469 
470         for ( int i = 0; i < _methods.size(); i++ )
471         {
472             marray[i] = (JMethod) _methods.elementAt( i );
473         }
474         return marray;
475     } //-- getMethods
476 
477     /**
478      * Returns the first occurrence of the method with the
479      * given name, starting from the specified index.
480      *
481      * @param name the name of the method to look for
482      * @param startIndex the starting index to begin the search
483      * @return the method if found, otherwise null.
484      */
485     public JMethod getMethod( String name, int startIndex )
486     {
487         for ( int i = startIndex; i < _methods.size(); i++ )
488         {
489             JMethod jMethod = (JMethod) _methods.elementAt( i );
490             if ( jMethod.getName().equals( name ) ) return jMethod;
491         }
492         return null;
493     } //-- getMethod
494 
495     /**
496      * Returns the JMethod located at the specified index
497      *
498      * @param index the index of the JMethod to return.
499      * @return the JMethod
500      */
501     public JMethod getMethod( int index )
502     {
503         return (JMethod) _methods.elementAt( index );
504     } //-- getMethod
505 
506 
507     /**
508      * Returns the JSourceCode for the static initializer
509      * of this JClass
510      *
511      * @return the JSourceCode for the static initializer
512      * of this JClass
513      */
514     public JSourceCode getStaticInitializationCode()
515     {
516         return _staticInitializer;
517     } //-- getStaticInitializationCode
518 
519     /**
520      * Gets the super Class that this class extends
521      * @return superClass the super Class that this Class extends
522      */
523     public String getSuperClass()
524     {
525         return _superClass;
526     } //-- getSuperClass
527 
528     /**
529      * Prints the source code for this JClass to the given JSourceWriter
530      *
531      * @param jsw the JSourceWriter to print to. [May not be null]
532      */
533     public void print( JSourceWriter jsw )
534     {
535         print( jsw, false );
536     } //-- print
537 
538     /**
539      * Prints the source code for this JClass to the given JSourceWriter
540      *
541      * @param jsw the JSourceWriter to print to. [May not be null]
542      */
543     public void print( JSourceWriter jsw, boolean classOnly )
544     {
545 
546         if ( jsw == null )
547         {
548             throw new IllegalArgumentException( "argument 'jsw' should not be null." );
549         }
550 
551 
552         StringBuilder buffer = new StringBuilder();
553 
554 
555         if ( !classOnly )
556         {
557             printHeader( jsw );
558             printPackageDeclaration( jsw );
559 
560             //-- get imports from inner-classes
561             Vector<String> removeImports = null;
562             if ( _innerClasses.size() > 0 )
563             {
564                 removeImports = new Vector<String>();
565                 for ( int i = 0; i < _innerClasses.size(); i++ )
566                 {
567                     JClass iClass = (JClass) _innerClasses.elementAt( i );
568                     Enumeration<String> e = iClass.getImports();
569                     while ( e.hasMoreElements() )
570                     {
571                         String classname = e.nextElement();
572                         if ( !hasImport( classname ) )
573                         {
574                             addImport( classname );
575                             removeImports.addElement( classname );
576                         }
577                     }
578                 }
579             }
580             printImportDeclarations( jsw );
581 
582             //-- remove imports from inner-classes, if necessary
583             if ( removeImports != null )
584             {
585                 for ( int i = 0; i < removeImports.size(); i++ )
586                 {
587                     removeImport( (String) removeImports.elementAt( i ) );
588                 }
589             }
590 
591         }
592 
593         //------------/
594         //- Java Doc -/
595         //------------/
596 
597         getJDocComment().print( jsw );
598 
599         JAnnotations annotations = getAnnotations();
600         if ( annotations != null ) annotations.print( jsw );
601 
602         //-- print class information
603         //-- we need to add some JavaDoc API adding comments
604 
605         buffer.setLength( 0 );
606 
607         JModifiers modifiers = getModifiers();
608         if ( modifiers.isPrivate() )
609         {
610             buffer.append( "private " );
611         }
612         else if ( modifiers.isPublic() )
613         {
614             buffer.append( "public " );
615         }
616 
617         if ( modifiers.isAbstract() )
618         {
619             buffer.append( "abstract " );
620         }
621 
622         if ( this instanceof JInnerClass && modifiers.isStatic() )
623         {
624             buffer.append( "static " );
625         }
626 
627         if ( modifiers.isFinal() )
628         {
629             buffer.append( "final " );
630         }
631 
632         buffer.append( "class " );
633         buffer.append( getLocalName() );
634         jsw.writeln( buffer.toString() );
635         buffer.setLength( 0 );
636         jsw.indent();
637 
638         if ( _superClass != null )
639         {
640             buffer.append( "extends " );
641             buffer.append( _superClass );
642             jsw.writeln( buffer.toString() );
643             buffer.setLength( 0 );
644         }
645 
646         if ( getInterfaceCount() > 0 )
647         {
648             buffer.append( "implements " );
649 
650             Enumeration<String> e = getInterfaces();
651             while ( e.hasMoreElements() )
652             {
653                 buffer.append( e.nextElement() );
654                 if ( e.hasMoreElements() ) buffer.append( ", " );
655             }
656 
657             jsw.writeln( buffer.toString() );
658             buffer.setLength( 0 );
659         }
660 
661         jsw.unindent();
662 
663         jsw.writeln( '{' );
664 
665         jsw.indent();
666 
667         //-- declare members
668 
669         if ( _fields.size() > 0 )
670         {
671             jsw.writeln();
672             jsw.writeln( "  //--------------------------/" );
673             jsw.writeln( " //- Class/Member Variables -/" );
674             jsw.writeln( "//--------------------------/" );
675             jsw.writeln();
676         }
677 
678         for ( int i = 0; i < _fields.size(); i++ )
679         {
680 
681             JField jField = (JField) _fields.get( i );
682 
683             //-- print Java comment
684             JDocComment comment = jField.getComment();
685             if ( comment != null ) comment.print( jsw );
686 
687             JAnnotations fieldAnnotations = jField.getAnnotations();
688             if ( fieldAnnotations != null ) fieldAnnotations.print( jsw );
689 
690             // -- print member
691             jsw.write( jField.getModifiers().toString() );
692             jsw.write( ' ' );
693 
694             JType type = jField.getType();
695             String typeName = type.toString();
696             //-- for esthetics use short name in some cases
697             if ( typeName.equals( toString() ) )
698             {
699                 typeName = type.getLocalName();
700             }
701             jsw.write( typeName );
702             jsw.write( ' ' );
703             jsw.write( jField.getName() );
704 
705             String init = jField.getInitString();
706             if ( init != null )
707             {
708                 jsw.write( " = " );
709                 jsw.write( init );
710             }
711 
712             jsw.writeln( ';' );
713             jsw.writeln();
714         }
715 
716         //----------------------/
717         //- Static Initializer -/
718         //----------------------/
719 
720         if ( !_staticInitializer.isEmpty() )
721         {
722             jsw.writeln();
723             jsw.writeln( "static" );
724             jsw.writeln( "{" );
725             _staticInitializer.print( jsw );
726             jsw.writeln( "};" );
727             jsw.writeln();
728         }
729 
730         //-- print constructors
731         if ( _constructors.size() > 0 )
732         {
733             jsw.writeln();
734             jsw.writeln( "  //----------------/" );
735             jsw.writeln( " //- Constructors -/" );
736             jsw.writeln( "//----------------/" );
737             jsw.writeln();
738         }
739         for ( int i = 0; i < _constructors.size(); i++ )
740         {
741             JConstructor jConstructor = (JConstructor) _constructors.elementAt( i );
742             jConstructor.print( jsw );
743             jsw.writeln();
744         }
745 
746         //-- print methods
747         if ( _methods.size() > 0 )
748         {
749             jsw.writeln();
750             jsw.writeln( "  //-----------/" );
751             jsw.writeln( " //- Methods -/" );
752             jsw.writeln( "//-----------/" );
753             jsw.writeln();
754         }
755 
756         for ( int i = 0; i < _methods.size(); i++ )
757         {
758             JMethod jMethod = (JMethod) _methods.elementAt( i );
759             jMethod.print( jsw );
760             jsw.writeln();
761         }
762 
763         //-- print inner-classes
764         if ( _innerClasses.size() > 0 )
765         {
766             jsw.writeln();
767             jsw.writeln( "  //-----------------/" );
768             jsw.writeln( " //- Inner Classes -/" );
769             jsw.writeln( "//-----------------/" );
770             jsw.writeln();
771         }
772         for ( int i = 0; i < _innerClasses.size(); i++ )
773         {
774             JClass jClass = (JClass) _innerClasses.elementAt( i );
775             jClass.print( jsw, true );
776             jsw.writeln();
777         }
778 
779         for ( String sourceCodeEntry : sourceCodeEntries )
780         {
781             jsw.writeln( sourceCodeEntry );
782         }
783 
784         jsw.unindent();
785 
786         jsw.writeln( '}' );
787         jsw.flush();
788     } //-- printSource
789 
790     private List<String> sourceCodeEntries = new ArrayList<String>();
791 
792     public void addSourceCode( String sourceCode )
793     {
794         sourceCodeEntries.add( sourceCode );
795     }
796 
797     /**
798      * Removes the given constructor from this JClass
799      *
800      * @param constructor the JConstructor to remove
801      * @return true if the constructor was removed, otherwise false.
802      */
803     public boolean removeConstructor( JConstructor constructor )
804     {
805         return _constructors.removeElement( constructor );
806     } //-- removeConstructor
807 
808     /**
809      * Removes the field with the given name from this JClass
810      *
811      * @param name the name of the field to remove
812      **/
813     public JField removeField( String name )
814     {
815         if ( name == null ) return null;
816 
817         JField field = (JField) _fields.remove( name );
818 
819         //-- clean up imports
820         //-- NOT YET IMPLEMENTED
821         return field;
822     } //-- removeField
823 
824     /**
825      * Removes the given JField from this JClass
826      *
827      * @param jField, the JField to remove
828      **/
829     public boolean removeField( JField jField )
830     {
831         if ( jField == null ) return false;
832 
833         Object field = _fields.get( jField.getName() );
834         if ( field == jField )
835         {
836             _fields.remove( jField.getName() );
837             return true;
838         }
839         //-- clean up imports
840         //-- NOT YET IMPLEMENTED
841         return false;
842 
843     } //-- removeField
844 
845     /**
846      * Removes the given inner-class (JClass) from this JClass.
847      *
848      * @param jClass the JClass (inner-class) to remove.
849      * @return true if the JClass was removed, otherwise false.
850      */
851     public boolean removeInnerClass( JClass jClass )
852     {
853         return _innerClasses.removeElement( jClass );
854     } //-- removeInnerClass
855 
856     /**
857      * Sets the super Class that this class extends
858      * @param superClass the super Class that this Class extends
859      */
860     public void setSuperClass( String superClass )
861     {
862         _superClass = superClass;
863     } //-- setSuperClass
864 
865 
866     /**
867      * Test drive method...to be removed or commented out
868      **/
869     /*public static void main( String[] args )
870     {
871         JClass testClass = new JClass( "org.acme.Test" );
872 
873         testClass.addImport( "java.util.Vector" );
874         testClass.addMember( new JField( JType.INT, "x" ) );
875         JClass jcString = new JClass( "String" );
876 
877         JField field = null;
878         field = new JField( JType.INT, "_z" );
879         field.getModifiers().setStatic( true );
880         testClass.addField( field );
881 
882         testClass.getStaticInitializationCode().add( "_z = 75;" );
883 
884         field = new JField( jcString, "myString" );
885         field.getModifiers().makePrivate();
886         testClass.addMember( field );
887 
888         //-- create constructor
889         JConstructor cons = testClass.createConstructor();
890         cons.getSourceCode().add( "this.x = 6;" );
891 
892         JMethod jMethod = new JMethod( "getX", JType.INT, null );
893         jMethod.setSourceCode( "return this.x;" );
894         testClass.addMethod( jMethod );
895 
896         //-- create inner-class
897         JClass innerClass = testClass.createInnerClass( "Foo" );
898         innerClass.addImport( "java.util.Hashtable" );
899         innerClass.addMember( new JField( JType.INT, "_type" ) );
900 
901         field = new JField( jcString, "_name" );
902         field.getModifiers().makePrivate();
903         innerClass.addMember( field );
904 
905         //-- create constructor
906         cons = innerClass.createConstructor();
907         cons.getSourceCode().add( "_name = \"foo\";" );
908 
909         jMethod = new JMethod( "getName", jcString, null );
910         jMethod.setSourceCode( "return _name;" );
911         innerClass.addMethod( jMethod );
912 
913         testClass.print();
914     } //-- main
915     */
916 
917     final class JInnerClass extends JClass
918     {
919 
920         JInnerClass( String name )
921         {
922             super( name );
923         }
924 
925         /**
926          * Allows changing the package name of this JStructure
927          *
928          * @param packageName the package name to use
929          */
930         public void setPackageName( String packageName )
931         {
932             throw new IllegalStateException( "Cannot change the package of an inner-class" );
933         } //-- setPackageName
934     } //-- JInnerClass
935 
936 } //-- JClass