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      * @param constructor a constructor
152      * @throws java.lang.IllegalArgumentException if {@code constructor} is {@code null} or invalid.
153      */
154     public void addConstructor( JConstructor constructor )
155         throws IllegalArgumentException
156     {
157         if ( constructor == null )
158             throw new IllegalArgumentException( "Constructors cannot be null" );
159 
160         if ( constructor.getDeclaringClass() == this )
161         {
162 
163             /** check signatures (add later) **/
164             if ( !_constructors.contains( constructor ) )
165             {
166                 _constructors.addElement( constructor );
167             }
168         }
169         else
170         {
171             String err = "The given JConstructor was not created ";
172             err += "by this JClass";
173             throw new IllegalArgumentException( err );
174         }
175     }
176 
177     /**
178      * Adds the given JField to this JClass
179      *
180      * @param jField, the JField to add
181      * @exception java.lang.IllegalArgumentException when the given
182      * JField has a name of an existing JField
183      **/
184     public void addField( JField jField )
185         throws IllegalArgumentException
186     {
187         if ( jField == null )
188         {
189             throw new IllegalArgumentException( "Class members cannot be null" );
190         }
191 
192         String name = jField.getName();
193 
194         if ( _fields.get( name ) != null )
195         {
196             String err = "duplicate name found: " + name;
197             throw new IllegalArgumentException( err );
198         }
199         _fields.put( name, jField );
200 
201     } //-- addField
202 
203     /**
204      * Adds the given JMember to this JClass
205      *
206      * @param jMember, the JMember to add
207      * @exception java.lang.IllegalArgumentException when the given
208      * JMember has the same name of an existing JField
209      * or JMethod respectively, or if the JMember is of an
210      * unrecognized class.
211      **/
212     public void addMember( JMember jMember )
213         throws IllegalArgumentException
214     {
215         if ( jMember instanceof JField )
216             addField( (JField) jMember );
217         else if ( jMember instanceof JMethod )
218             addMethod( (JMethod) jMember );
219         else
220         {
221             String error = null;
222             if ( jMember == null )
223             {
224                 error = "the argument 'jMember' must not be null.";
225             }
226             else
227             {
228                 error = "Cannot add JMember '" + jMember.getClass().getName() +
229                     "' to JClass, unrecognized type.";
230             }
231             throw new IllegalArgumentException( error );
232         }
233 
234     } //-- addMember
235 
236     /**
237      * Adds the given JMethod to this JClass
238      *
239      * @param jMethod the JMethod to add
240      **/
241     public void addMethod( JMethod jMethod )
242     {
243         addMethod( jMethod, true );
244     }
245 
246     /**
247      * Adds the given JMethod to this JClass
248      *
249      * @param jMethod, the JMethod to add
250      * @param importReturnType true if we add the importReturnType to
251      * the class import lists. It could be useful to set it to false when
252      * all types are fully qualified.
253      * @throws java.lang.IllegalArgumentException when the given
254      * JMethod has the same name of an existing JMethod.
255      **/
256     public void addMethod( JMethod jMethod, boolean importReturnType )
257         throws IllegalArgumentException
258     {
259         if ( jMethod == null )
260         {
261             throw new IllegalArgumentException( "Class methods cannot be null" );
262         }
263 
264         //-- check method name and signatures *add later*
265 
266         //-- keep method list sorted for esthetics when printing
267         //-- START SORT :-)
268         boolean added = false;
269 //        short modifierVal = 0;
270         JModifiers modifiers = jMethod.getModifiers();
271 
272         if ( modifiers.isAbstract() )
273         {
274             getModifiers().setAbstract( true );
275         }
276 
277         for ( int i = 0; i < _methods.size(); i++ )
278         {
279             JMethod tmp = (JMethod) _methods.elementAt( i );
280             //-- first compare modifiers
281             if ( tmp.getModifiers().isPrivate() )
282             {
283                 if ( !modifiers.isPrivate() )
284                 {
285                     _methods.insertElementAt( jMethod, i );
286                     added = true;
287                     break;
288                 }
289             }
290             //-- compare names
291             if ( jMethod.getName().compareTo( tmp.getName() ) < 0 )
292             {
293                 _methods.insertElementAt( jMethod, i );
294                 added = true;
295                 break;
296             }
297         }
298         //-- END SORT
299         if ( !added ) _methods.addElement( jMethod );
300 
301     } //-- addMethod
302 
303     /**
304      * Adds the given array of JMethods to this JClass
305      *
306      * @param jMethods, the JMethod[] to add
307      * @exception java.lang.IllegalArgumentException when any of the given
308      * JMethods has the same name of an existing JMethod.
309      **/
310     public void addMethods( JMethod[] jMethods )
311         throws IllegalArgumentException
312     {
313         for ( JMethod jMethod : jMethods )
314         {
315             addMethod( jMethod );
316         }
317     } //-- addMethods
318 
319 
320     /**
321      * Creates a new JConstructor and adds it to this
322      * JClass.
323      *
324      * @return the newly created constructor
325      */
326     public JConstructor createConstructor()
327     {
328         return createConstructor( null );
329     } //-- createConstructor
330 
331     /**
332      * Creates a new JConstructor and adds it to this
333      * JClass.
334      *
335      * @param params the parameters
336      * @return the newly created constructor
337      */
338     public JConstructor createConstructor( JParameter[] params )
339     {
340         JConstructor cons = new JConstructor( this );
341         if ( params != null )
342         {
343             for ( JParameter param : params )
344             {
345                 cons.addParameter( param );
346             }
347         }
348         addConstructor( cons );
349         return cons;
350     } //-- createConstructor
351 
352     /**
353      * Creates and returns an inner-class for this JClass
354      *
355      * @param localname the name of the class (no package name)
356      * @return the new JClass
357      */
358     public JClass createInnerClass( String localname )
359     {
360         if ( localname == null )
361         {
362             String err = "argument 'localname' must not be null.";
363             throw new IllegalArgumentException( err );
364         }
365         if ( localname.indexOf( '.' ) >= 0 )
366         {
367             String err = "The name of an inner-class must not contain a package name.";
368             throw new IllegalArgumentException( err );
369         }
370         String classname = getPackageName();
371         if ( classname != null )
372         {
373             classname = classname + "." + localname;
374         }
375         else
376         {
377             classname = localname;
378         }
379 
380         JClass innerClass = new JInnerClass( classname );
381         _innerClasses.addElement( innerClass );
382         return innerClass;
383 
384     } //-- createInnerClass
385 
386     /**
387      * Returns the constructor at the specified index.
388      *
389      * @param index the index of the constructor to return
390      * @return the JConstructor at the specified index.
391      */
392     public JConstructor getConstructor( int index )
393     {
394         return (JConstructor) _constructors.elementAt( index );
395     } //-- getConstructor
396 
397     /**
398      * Returns the an array of the JConstructors contained within this JClass
399      *
400      * @return an array of JConstructor
401      */
402     public JConstructor[] getConstructors()
403     {
404 
405         int size = _constructors.size();
406         JConstructor[] jcArray = new JConstructor[size];
407 
408         for ( int i = 0; i < _constructors.size(); i++ )
409         {
410             jcArray[i] = (JConstructor) _constructors.elementAt( i );
411         }
412         return jcArray;
413     } //-- getConstructors
414 
415 
416     /**
417      * Returns the member with the given name, or null if no member
418      * was found with the given name
419      * @param name the name of the member to return
420      * @return the member with the given name, or null if no member
421      * was found with the given name
422      **/
423     public JField getField( String name )
424     {
425         return (JField) _fields.get( name );
426     } //-- getField
427 
428     /**
429      * Returns an array of all the JFields of this JClass
430      * @return an array of all the JFields of this JClass
431      **/
432     public JField[] getFields()
433     {
434         int size = _fields.size();
435         JField[] farray = new JField[size];
436         for ( int i = 0; i < size; i++ )
437         {
438             farray[i] = (JField) _fields.get( i );
439         }
440         return farray;
441     } //-- getFields
442 
443     /**
444      * Returns an array of JClass (the inner classes)
445      * contained within this JClass.
446      *
447      * @return an array of JClass contained within this JClass
448      */
449     public JClass[] getInnerClasses()
450     {
451         int size = _innerClasses.size();
452         JClass[] carray = new JClass[size];
453         _innerClasses.copyInto( carray );
454         return carray;
455     } //-- getInnerClasses;
456 
457     /**
458      * Returns an array of all the JMethods of this JClass
459      *
460      * @return an array of all the JMethods of this JClass
461      */
462     public JMethod[] getMethods()
463     {
464         int size = _methods.size();
465         JMethod[] marray = new JMethod[size];
466 
467         for ( int i = 0; i < _methods.size(); i++ )
468         {
469             marray[i] = (JMethod) _methods.elementAt( i );
470         }
471         return marray;
472     } //-- getMethods
473 
474     /**
475      * Returns the first occurrence of the method with the
476      * given name, starting from the specified index.
477      *
478      * @param name the name of the method to look for
479      * @param startIndex the starting index to begin the search
480      * @return the method if found, otherwise null.
481      */
482     public JMethod getMethod( String name, int startIndex )
483     {
484         for ( int i = startIndex; i < _methods.size(); i++ )
485         {
486             JMethod jMethod = (JMethod) _methods.elementAt( i );
487             if ( jMethod.getName().equals( name ) ) return jMethod;
488         }
489         return null;
490     } //-- getMethod
491 
492     /**
493      * Returns the JMethod located at the specified index
494      *
495      * @param index the index of the JMethod to return.
496      * @return the JMethod
497      */
498     public JMethod getMethod( int index )
499     {
500         return (JMethod) _methods.elementAt( index );
501     } //-- getMethod
502 
503 
504     /**
505      * Returns the JSourceCode for the static initializer
506      * of this JClass
507      *
508      * @return the JSourceCode for the static initializer
509      * of this JClass
510      */
511     public JSourceCode getStaticInitializationCode()
512     {
513         return _staticInitializer;
514     } //-- getStaticInitializationCode
515 
516     /**
517      * Gets the super Class that this class extends
518      * @return superClass the super Class that this Class extends
519      */
520     public String getSuperClass()
521     {
522         return _superClass;
523     } //-- getSuperClass
524 
525     /**
526      * Prints the source code for this JClass to the given JSourceWriter
527      *
528      * @param jsw the JSourceWriter to print to. [May not be null]
529      */
530     public void print( JSourceWriter jsw )
531     {
532         print( jsw, false );
533     } //-- print
534 
535     /**
536      * Prints the source code for this JClass to the given JSourceWriter
537      *
538      * @param jsw the JSourceWriter to print to. [May not be null]
539      * @param classOnly whether the header, package and imports should be printed too 
540      */
541     public void print( JSourceWriter jsw, boolean classOnly )
542     {
543 
544         if ( jsw == null )
545         {
546             throw new IllegalArgumentException( "argument 'jsw' should not be null." );
547         }
548 
549 
550         StringBuilder buffer = new StringBuilder();
551 
552 
553         if ( !classOnly )
554         {
555             printHeader( jsw );
556             printPackageDeclaration( jsw );
557 
558             //-- get imports from inner-classes
559             Vector<String> removeImports = null;
560             if ( _innerClasses.size() > 0 )
561             {
562                 removeImports = new Vector<String>();
563                 for ( int i = 0; i < _innerClasses.size(); i++ )
564                 {
565                     JClass iClass = (JClass) _innerClasses.elementAt( i );
566                     Enumeration<String> e = iClass.getImports();
567                     while ( e.hasMoreElements() )
568                     {
569                         String classname = e.nextElement();
570                         if ( !hasImport( classname ) )
571                         {
572                             addImport( classname );
573                             removeImports.addElement( classname );
574                         }
575                     }
576                 }
577             }
578             printImportDeclarations( jsw );
579 
580             //-- remove imports from inner-classes, if necessary
581             if ( removeImports != null )
582             {
583                 for ( int i = 0; i < removeImports.size(); i++ )
584                 {
585                     removeImport( (String) removeImports.elementAt( i ) );
586                 }
587             }
588 
589         }
590 
591         //------------/
592         //- Java Doc -/
593         //------------/
594 
595         getJDocComment().print( jsw );
596 
597         JAnnotations annotations = getAnnotations();
598         if ( annotations != null ) annotations.print( jsw );
599 
600         //-- print class information
601         //-- we need to add some JavaDoc API adding comments
602 
603         buffer.setLength( 0 );
604 
605         JModifiers modifiers = getModifiers();
606         if ( modifiers.isPrivate() )
607         {
608             buffer.append( "private " );
609         }
610         else if ( modifiers.isPublic() )
611         {
612             buffer.append( "public " );
613         }
614 
615         if ( modifiers.isAbstract() )
616         {
617             buffer.append( "abstract " );
618         }
619 
620         if ( this instanceof JInnerClass && modifiers.isStatic() )
621         {
622             buffer.append( "static " );
623         }
624 
625         if ( modifiers.isFinal() )
626         {
627             buffer.append( "final " );
628         }
629 
630         buffer.append( "class " );
631         buffer.append( getLocalName() );
632         jsw.writeln( buffer.toString() );
633         buffer.setLength( 0 );
634         jsw.indent();
635 
636         if ( _superClass != null )
637         {
638             buffer.append( "extends " );
639             buffer.append( _superClass );
640             jsw.writeln( buffer.toString() );
641             buffer.setLength( 0 );
642         }
643 
644         if ( getInterfaceCount() > 0 )
645         {
646             buffer.append( "implements " );
647 
648             Enumeration<String> e = getInterfaces();
649             while ( e.hasMoreElements() )
650             {
651                 buffer.append( e.nextElement() );
652                 if ( e.hasMoreElements() ) buffer.append( ", " );
653             }
654 
655             jsw.writeln( buffer.toString() );
656             buffer.setLength( 0 );
657         }
658 
659         jsw.unindent();
660 
661         jsw.writeln( '{' );
662 
663         jsw.indent();
664 
665         //-- declare members
666 
667         if ( _fields.size() > 0 )
668         {
669             jsw.writeln();
670             jsw.writeln( "  //--------------------------/" );
671             jsw.writeln( " //- Class/Member Variables -/" );
672             jsw.writeln( "//--------------------------/" );
673             jsw.writeln();
674         }
675 
676         for ( int i = 0; i < _fields.size(); i++ )
677         {
678 
679             JField jField = (JField) _fields.get( i );
680 
681             //-- print Java comment
682             JDocComment comment = jField.getComment();
683             if ( comment != null ) comment.print( jsw );
684 
685             JAnnotations fieldAnnotations = jField.getAnnotations();
686             if ( fieldAnnotations != null ) fieldAnnotations.print( jsw );
687 
688             // -- print member
689             jsw.write( jField.getModifiers().toString() );
690             jsw.write( ' ' );
691 
692             JType type = jField.getType();
693             String typeName = type.toString();
694             //-- for esthetics use short name in some cases
695             if ( typeName.equals( toString() ) )
696             {
697                 typeName = type.getLocalName();
698             }
699             jsw.write( typeName );
700             jsw.write( ' ' );
701             jsw.write( jField.getName() );
702 
703             String init = jField.getInitString();
704             if ( init != null )
705             {
706                 jsw.write( " = " );
707                 jsw.write( init );
708             }
709 
710             jsw.writeln( ';' );
711             jsw.writeln();
712         }
713 
714         //----------------------/
715         //- Static Initializer -/
716         //----------------------/
717 
718         if ( !_staticInitializer.isEmpty() )
719         {
720             jsw.writeln();
721             jsw.writeln( "static" );
722             jsw.writeln( "{" );
723             _staticInitializer.print( jsw );
724             jsw.writeln( "};" );
725             jsw.writeln();
726         }
727 
728         //-- print constructors
729         if ( _constructors.size() > 0 )
730         {
731             jsw.writeln();
732             jsw.writeln( "  //----------------/" );
733             jsw.writeln( " //- Constructors -/" );
734             jsw.writeln( "//----------------/" );
735             jsw.writeln();
736         }
737         for ( int i = 0; i < _constructors.size(); i++ )
738         {
739             JConstructor jConstructor = (JConstructor) _constructors.elementAt( i );
740             jConstructor.print( jsw );
741             jsw.writeln();
742         }
743 
744         //-- print methods
745         if ( _methods.size() > 0 )
746         {
747             jsw.writeln();
748             jsw.writeln( "  //-----------/" );
749             jsw.writeln( " //- Methods -/" );
750             jsw.writeln( "//-----------/" );
751             jsw.writeln();
752         }
753 
754         for ( int i = 0; i < _methods.size(); i++ )
755         {
756             JMethod jMethod = (JMethod) _methods.elementAt( i );
757             jMethod.print( jsw );
758             jsw.writeln();
759         }
760 
761         //-- print inner-classes
762         if ( _innerClasses.size() > 0 )
763         {
764             jsw.writeln();
765             jsw.writeln( "  //-----------------/" );
766             jsw.writeln( " //- Inner Classes -/" );
767             jsw.writeln( "//-----------------/" );
768             jsw.writeln();
769         }
770         for ( int i = 0; i < _innerClasses.size(); i++ )
771         {
772             JClass jClass = (JClass) _innerClasses.elementAt( i );
773             jClass.print( jsw, true );
774             jsw.writeln();
775         }
776 
777         for ( String sourceCodeEntry : sourceCodeEntries )
778         {
779             jsw.writeln( sourceCodeEntry );
780         }
781 
782         jsw.unindent();
783 
784         jsw.writeln( '}' );
785         jsw.flush();
786     } //-- printSource
787 
788     private List<String> sourceCodeEntries = new ArrayList<String>();
789 
790     public void addSourceCode( String sourceCode )
791     {
792         sourceCodeEntries.add( sourceCode );
793     }
794 
795     /**
796      * Removes the given constructor from this JClass
797      *
798      * @param constructor the JConstructor to remove
799      * @return true if the constructor was removed, otherwise false.
800      */
801     public boolean removeConstructor( JConstructor constructor )
802     {
803         return _constructors.removeElement( constructor );
804     } //-- removeConstructor
805 
806     /**
807      * Removes the field with the given name from this JClass
808      *
809      * @param name the name of the field to remove
810      * @return the removed field
811      **/
812     public JField removeField( String name )
813     {
814         if ( name == null ) return null;
815 
816         JField field = (JField) _fields.remove( name );
817 
818         //-- clean up imports
819         //-- NOT YET IMPLEMENTED
820         return field;
821     } //-- removeField
822 
823     /**
824      * Removes the given JField from this JClass
825      *
826      * @param jField, the JField to remove
827      * @return {{@code true} if and only if the field was successfully removed
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