View Javadoc

1   /*
2    * Copyright (c) 2001-2003 The XDoclet team
3    * All rights reserved.
4    */
5   package xjavadoc;
6   
7   import org.apache.commons.collections.Predicate;
8   import org.apache.commons.collections.CollectionUtils;
9   
10  import java.util.*;
11  import java.io.IOException;
12  import java.io.File;
13  
14  /***
15   * Base implementation of XClass.
16   *
17   * @author    Ara Abrahamian
18   * @author    Aslak Hellesøy
19   * @created   18. oktober 2002
20   */
21  public abstract class AbstractClass extends AbstractProgramElement implements XClass
22  {
23  	/***
24  	 * The implemented interfaces according to the source
25  	 */
26  	private List       _declaredInterfaces;
27  	/***
28  	 * The implemented interfaces according to the hierarchy
29  	 */
30  	private List       _allInterfaces;
31  
32  	private List       _importedClasses;
33  	private List       _importedClassNames;
34  	private List       _importedPackages;
35  	private List       _constructors;
36  	private Map        _namedConstructors;
37  	private List       _methods;
38  	private HashMap    _namedMethods;
39  	private List       _fields;
40  	private List       _innerClasses;
41  	private XPackage   _containingPackage;
42  	private boolean    _isInterface;
43  	private boolean    _isAnonymous = false;
44  	private XClass     _superclass;
45  	private int        _hash = Integer.MIN_VALUE;
46  	private List       _directSubclasses;
47  	private List       _allSubclasses;
48  	private List       _implementingClasses;
49  	private List       _extendingInterfaces;
50  	private String     _name;
51  	private String     _transformedName;
52  	private String     _qualifiedName;
53  	private String     _transformedQualifiedName;
54  
55      protected AbstractClass( AbstractClass containingClass, XTagFactory tagFactory )
56      {
57          super( containingClass, tagFactory );
58      }
59  
60      protected AbstractClass( XJavaDoc xJavaDoc, XTagFactory tagFactory )
61      {
62          super( xJavaDoc, tagFactory );
63      }
64  
65  	/***
66  	 * Gets the Interface attribute of the SourceClass object
67  	 *
68  	 * @return   The Interface value
69  	 */
70  	public final boolean isInterface()
71  	{
72  		return _isInterface;
73  	}
74  
75  	public final boolean isA( String full_qualified_type_name )
76  	{
77  		return isA( full_qualified_type_name, true );
78  	}
79  
80  	public final boolean isA( final String full_qualified_type_name, final boolean superclasses )
81  	{
82  		final boolean sameClass = getQualifiedName().equals( full_qualified_type_name );
83  		final boolean subClass = isSubclassOf( full_qualified_type_name, superclasses );
84  		final boolean implementz = isImplementingInterface( full_qualified_type_name, superclasses );
85  
86  		return sameClass || subClass || implementz;
87  	}
88  
89  	public final XMethod getMethod( String methodNameWithSignature )
90  	{
91  		return getMethod( methodNameWithSignature, false );
92  	}
93  
94  	public final XMethod getMethod( String methodNameWithSignature, boolean superclasses )
95  	{
96  		XMethod result = null;
97  
98  		initializeNamedMethodsHashMap();
99  
100 		if( _namedMethods != null )
101 		{
102 			result = ( XMethod ) _namedMethods.get( methodNameWithSignature );
103 		}
104 		if( result == null && superclasses )
105 		{
106 			XClass superclass = getSuperclass();
107 
108 			if( superclass != null )
109 			{
110 				result = superclass.getMethod( methodNameWithSignature, true );
111 			}
112 		}
113 		return result;
114 	}
115 
116 	/***
117 	 * Gets the Constructor attribute of the AbstractClass object
118 	 *
119 	 * @param constructorNameWithSignature  Describe what the parameter does
120 	 * @return                              The Constructor value
121 	 */
122 	public final XConstructor getConstructor( String constructorNameWithSignature )
123 	{
124 		initializeNamedConstructorsHashMap();
125 
126 		if( _namedConstructors != null )
127 			return ( XConstructor ) _namedConstructors.get( constructorNameWithSignature );
128 		else
129 			return null;
130 	}
131 
132 	/***
133 	 * Returns an XField with the given name. Example: getField("id");
134 	 *
135 	 * @param fieldName  Describe what the parameter does
136 	 * @return           The Field value
137 	 */
138 	public final XField getField( String fieldName )
139 	{
140 		if( _fields == null )
141 		{
142 			return null;
143 		}
144 		for( int i = 0; i < _fields.size(); i++ )
145 		{
146 			XField field = ( XField ) _fields.get( i );
147 
148 			if( field.getName().equals( fieldName ) )
149 			{
150 				return field;
151 			}
152 		}
153 		return null;
154 	}
155 
156 	/***
157 	 * Describe what the method does
158 	 *
159 	 * @return   Describe the return value for method for return value
160 	 */
161 	public final List getImportedClasses()
162 	{
163 		return _importedClasses == null ? EMPTY_LIST : Collections.unmodifiableList( _importedClasses );
164 	}
165 
166 	/***
167 	 * Describe what the method does
168 	 *
169 	 * @return   Describe the return value for method for return value
170 	 */
171 	public final List getImportedPackages()
172 	{
173 		return _importedPackages == null ? EMPTY_LIST : Collections.unmodifiableList( _importedPackages );
174 	}
175 
176 	public final List getMethods()
177 	{
178 		return getMethods( false );
179 	}
180 
181 	public final List getMethods( Predicate predicate, boolean superclasses )
182 	{
183 		return Collections.unmodifiableList( new ArrayList( CollectionUtils.select( getMethods( superclasses ), predicate ) ) );
184 	}
185 
186 	public final List getFields( Predicate predicate, boolean superclasses )
187 	{
188 		return Collections.unmodifiableList( new ArrayList( CollectionUtils.select( getFields( superclasses ), predicate ) ) );
189 	}
190 
191 	public final List getMethods( boolean superclasses )
192 	{
193 		return getMembers( superclasses, false );
194 	}
195 
196 	public final List getFields( boolean superclasses )
197 	{
198 		return getMembers( superclasses, true );
199 	}
200 
201 	/***
202 	 * Describe what the method does
203 	 *
204 	 * @return   Describe the return value for method for return value
205 	 */
206 	public final List getFields()
207 	{
208 		return _fields == null ? EMPTY_LIST : Collections.unmodifiableList( _fields );
209 	}
210 
211 	/***
212 	 * Gets the constructors.
213 	 *
214 	 * @return   the constructors.
215 	 */
216 	public final List getConstructors()
217 	{
218 		return _constructors == null ? EMPTY_LIST : Collections.unmodifiableList( _constructors );
219 	}
220 
221 	public final boolean isSubclassOf( String full_qualified_type_name )
222 	{
223 		return isSubclassOf( full_qualified_type_name, true );
224 	}
225 
226 	public final boolean isImplementingInterface( String full_qualified_type_name )
227 	{
228 		return isImplementingInterface( full_qualified_type_name, true );
229 	}
230 
231 	public String getType()
232 	{
233 		return getQualifiedName() + ".class";
234 	}
235 
236 	public boolean isInner()
237 	{
238 		boolean hasContainingClass = getContainingClass() != null;
239 		return hasContainingClass;
240 	}
241 
242 	public boolean isSubclassOf( String full_qualified_type_name, boolean superclasses )
243 	{
244 		XClass superclass = this.getSuperclass();
245 
246 		if( superclass == null )
247 			return false;
248 		do
249 		{
250 			if( superclass.getQualifiedName().equals( full_qualified_type_name ) )
251 				return true;
252 
253 			superclass = superclass.getSuperclass();
254 		}while ( superclasses == true && superclass != null );
255 
256 		return false;
257 	}
258 
259 	public boolean isImplementingInterface( String full_qualified_type_name, boolean superclasses )
260 	{
261 		XClass cur_class = this;
262 
263 		do
264 		{
265 			for( Iterator iterator = cur_class.getInterfaces().iterator(); iterator.hasNext();  )
266 			{
267 				XClass intf = ( XClass ) iterator.next();
268 
269 				//if intf is full_qualified_type_name directly or it extends from another interface which extends full_qualified_type_name
270 				if( intf.getQualifiedName().equals( full_qualified_type_name ) || intf.isImplementingInterface( full_qualified_type_name, superclasses ) )
271 					return true;
272 			}
273 
274 			cur_class = cur_class.getSuperclass();
275 		}while ( superclasses == true && cur_class != null );
276 
277 		return false;
278 	}
279 
280 	public String getName()
281 	{
282 		return _name;
283 	}
284 
285 	/***
286 	 * Describe what the method does
287 	 *
288 	 * @return   Describe the return value for method for return value
289 	 */
290 	public String getQualifiedName()
291 	{
292 		return _qualifiedName;
293 	}
294 
295 	/***
296 	 * Gets the transformed class name, for example: <code>Character$Subset</code>
297 	 *
298 	 * @return   the transformed class name.
299 	 */
300 	public String getTransformedName()
301 	{
302 		return _transformedName;
303 	}
304 
305 	/***
306 	 * Gets the transformed qualified class name, for example: <code>java.lang.Character$Subset</code>
307 	 *
308 	 * @return   the transformed qualified class name.
309 	 */
310 	public String getTransformedQualifiedName()
311 	{
312 		return _transformedQualifiedName;
313 	}
314 
315 	/***
316 	 * Returns all the implemented interfaces (if this is a class) or all the
317 	 * extended interfaces (if this is an interface)
318 	 *
319 	 * @return   Describe the return value for method for return value
320 	 */
321 	public List getInterfaces()
322 	{
323 		// IMPORTANT: This method should not be called before all classes have been parsed.
324 		if( _allInterfaces == null )
325 		{
326 			// Temporarily use a Set
327 			Set allInterfaces = new HashSet();
328 
329 			if( _declaredInterfaces != null )
330 			{
331 				allInterfaces.addAll( _declaredInterfaces );
332 
333 				// Add all the declared interfaces' superinterfaces
334 				for( Iterator i = _declaredInterfaces.iterator(); i.hasNext();  )
335 				{
336 					XClass intf = ( XClass ) i.next();
337 
338 					allInterfaces.addAll( intf.getInterfaces() );
339 				}
340 			}
341 
342 			// Add all the superclasses' interfaces
343 			XClass superclass = getSuperclass();
344 
345 			while( superclass != null )
346 			{
347 				allInterfaces.addAll( superclass.getInterfaces() );
348 				superclass = superclass.getSuperclass();
349 			}
350 
351 			_allInterfaces = Arrays.asList( allInterfaces.toArray() );
352 		}
353 		return _allInterfaces;
354 	}
355 
356 	/***
357 	 * Returns the interfaces that are declared in the source code. This excludes
358 	 * any interfaces that might be implicitly implemented. This method is only
359 	 * useful for CodeUnit, which compares source codes, and should normally not be
360 	 * called.
361 	 *
362 	 * @return   A Collection of XClass
363 	 */
364 	public Collection getDeclaredInterfaces()
365 	{
366 		return _declaredInterfaces != null ? _declaredInterfaces : EMPTY_LIST;
367 	}
368 
369 	/***
370 	 * Describe what the method does
371 	 *
372 	 * @return   Describe the return value for method for return value
373 	 */
374 	public XClass getSuperclass()
375 	{
376 		return _superclass;
377 	}
378 
379 	public List getDirectSubclasses()
380 	{
381 		if( isInterface() )
382 		{
383 			throw new UnsupportedOperationException( "Should never ask for directSubclasses of interfaces. Ask for implementingClasses or extendingInterfaces instead" );
384 		}
385 		if( _directSubclasses == null )
386 		{
387 			_directSubclasses = new LinkedList();
388 
389 			for( Iterator classes = getXJavaDoc().getSourceClasses().iterator(); classes.hasNext();  )
390 			{
391 				XClass clazz = (XClass) classes.next();
392 
393 				if( clazz.getSuperclass() == this )
394 				{
395 					_directSubclasses.add( clazz );
396 				}
397 			}
398 		}
399 		return Collections.unmodifiableList( _directSubclasses );
400 	}
401 
402 	public List getAllSubclasses()
403 	{
404 		if( isInterface() )
405 		{
406 			throw new UnsupportedOperationException( "Should never ask for allSubclasses of interfaces. Ask for implementingClasses or extendingInterfaces instead" );
407 		}
408 		if( _allSubclasses == null )
409 		{
410 			_allSubclasses = new LinkedList();
411 
412 			for( Iterator classes = getXJavaDoc().getSourceClasses().iterator(); classes.hasNext();  )
413 			{
414 				XClass clazz = (XClass) classes.next();
415 
416 				while( clazz != null )
417 				{
418 					if( clazz.getSuperclass() == this )
419 					{
420 						_allSubclasses.add( clazz );
421 						break;
422 					}
423 					clazz = clazz.getSuperclass();
424 				}
425 			}
426 		}
427 		return Collections.unmodifiableList( _allSubclasses );
428 	}
429 
430 	public List getImplementingClasses()
431 	{
432 		if( !isInterface() )
433 		{
434 			throw new UnsupportedOperationException( "Should never ask for implementingClasses of classes. Ask for directSubclasses or allSubclasses instead" );
435 		}
436 		if( _implementingClasses == null )
437 		{
438 			_implementingClasses = new LinkedList();
439 
440 			for( Iterator classes = getXJavaDoc().getSourceClasses().iterator(); classes.hasNext();  )
441 			{
442 				XClass clazz = (XClass) classes.next();
443 
444 				if( !clazz.isInterface() )
445 				{
446 					Collection interfaces = clazz.getInterfaces();
447 
448 					if( interfaces.contains( this ) )
449 					{
450 						_implementingClasses.add( clazz );
451 					}
452 				}
453 			}
454 		}
455 		return Collections.unmodifiableList( _implementingClasses );
456 	}
457 
458 	public List getExtendingInterfaces()
459 	{
460 		if( !isInterface() )
461 		{
462 			throw new UnsupportedOperationException( "Should never ask for extendingInterfaces of classes. Ask for directSubclasses or allSubclasses instead" );
463 		}
464 		if( _extendingInterfaces == null )
465 		{
466 			_extendingInterfaces = new LinkedList();
467 
468             for( Iterator classes = getXJavaDoc().getSourceClasses().iterator(); classes.hasNext();  )
469             {
470                 XClass clazz = (XClass) classes.next();
471 
472 				if( clazz.isInterface() )
473 				{
474 					Collection interfaces = clazz.getInterfaces();
475 
476 					if( interfaces.contains( this ) )
477 					{
478 						_extendingInterfaces.add( clazz );
479 					}
480 				}
481 			}
482 		}
483 		return Collections.unmodifiableList( _extendingInterfaces );
484 	}
485 
486 	/***
487 	 * Describe what the method does
488 	 *
489 	 * @return   Describe the return value
490 	 */
491 	public XPackage getContainingPackage()
492 	{
493 		if( _containingPackage == null )
494 		{
495 			_containingPackage = getXJavaDoc().addPackageMaybe( "" );
496 		}
497 		return _containingPackage;
498 	}
499 
500 	/***
501 	 * Describe what the method does
502 	 *
503 	 * @return   Describe the return value
504 	 */
505 	public List getInnerClasses()
506 	{
507 		return _innerClasses == null ? EMPTY_LIST : Collections.unmodifiableList( _innerClasses );
508 	}
509 	/***
510 	 * Describe what the method does
511 	 *
512 	 * @return   Describe the return value
513 	 */
514 	public XProgramElement getSuperElement()
515 	{
516 		return getSuperclass();
517 	}
518 
519 	public List getSuperInterfaceElements()
520 	{
521 		return getInterfaces();
522 	}
523 
524 	public boolean isAnonymous()
525 	{
526 		return _isAnonymous;
527 	}
528 
529 	public List getMethodTags( String tagName, boolean superclasses )
530 	{
531 		Set result = new HashSet();
532 
533 		for( Iterator methods = getMethods( superclasses ).iterator(); methods.hasNext();  )
534 		{
535 			XMethod method = (XMethod) methods.next();
536 
537 			result.addAll( method.getDoc().getTags( tagName, superclasses ) );
538 		}
539 		return new ArrayList( result );
540 	}
541 
542 	public final int compareTo( Object o )
543 	{
544 		XClass other = ( XClass ) o;
545 
546 		return getQualifiedName().compareTo( other.getQualifiedName() );
547 	}
548 
549 	public final String toString()
550 	{
551 		return getQualifiedName();
552 	}
553 
554 	public String save( File rootDir ) throws IOException
555 	{
556 		throw new UnsupportedOperationException( getClass().getName() );
557 	}
558 
559 	public boolean equals( Object obj )
560 	{
561 		if( !( obj instanceof XClass ) )
562 		{
563 			return false;
564 		}
565 
566 		XClass other_clazz = ( XClass ) obj;
567 
568 		return getQualifiedName().equals( other_clazz.getQualifiedName() );
569 	}
570 
571 	public int hashCode()
572 	{
573 		if( _hash == Integer.MIN_VALUE )
574 		{
575 			_hash += getQualifiedName().hashCode();
576 		}
577 		return _hash;
578 	}
579 
580 	public XClass qualify( String unqualifiedClassName )
581 	{
582 		return getXJavaDoc().getXClass( unqualifiedClassName );
583 	}
584 
585 	public long lastModified()
586 	{
587 		return Long.MIN_VALUE;
588 	}
589 
590 	/***
591 	 * update javadoc
592 	 */
593 	public void updateDoc()
594 	{
595 		super.updateDoc();
596 
597 		// update docs on fields, methods and constructors
598 		for( Iterator i = getFields().iterator(); i.hasNext();  )
599 		{
600 			( ( XField ) i.next() ).updateDoc();
601 		}
602 		for( Iterator i = getMethods().iterator(); i.hasNext();  )
603 		{
604 			( ( XMethod ) i.next() ).updateDoc();
605 		}
606 		for( Iterator i = getConstructors().iterator(); i.hasNext();  )
607 		{
608 			( ( XConstructor ) i.next() ).updateDoc();
609 		}
610 
611 		for( Iterator i = getInnerClasses().iterator(); i.hasNext();  )
612 		{
613 			( ( XClass ) i.next() ).updateDoc();
614 		}
615 	}
616 
617 	protected final boolean hasImportedClasses()
618 	{
619 		return _importedClasses != null;
620 	}
621 
622 	protected final boolean hasInnerClasses()
623 	{
624 		return _innerClasses != null;
625 	}
626 
627 	protected final boolean hasImportedPackages()
628 	{
629 		return _importedPackages != null;
630 	}
631 
632 	protected void addInnerClass( XClass clazz )
633 	{
634 		if( _innerClasses == null )
635 		{
636 			_innerClasses = new LinkedList();
637 		}
638 		_innerClasses.add( clazz );
639 	}
640 
641 	/***
642 	 * Sets the qualified name of the class. Should only be called on objects that
643 	 * represent outer classes.
644 	 *
645 	 * @param qualifiedName  The new QualifiedName value
646 	 */
647 	final void setQualifiedName( String qualifiedName )
648 	{
649 		if( qualifiedName == null )
650 		{
651 			throw new IllegalArgumentException( "qualifiedName can't be null!" );
652 		}
653 		if( qualifiedName.startsWith( "." ) )
654 		{
655 			throw new IllegalArgumentException( "qualifiedName can't start with a dot! " + qualifiedName );
656 		}
657 		if( _qualifiedName != null )
658 		{
659 			throw new IllegalStateException( "Setting qualified name " + qualifiedName + " from " + _qualifiedName + " 2nd time!" );
660 		}
661 		if( isInner() )
662 		{
663 			throw new IllegalStateException( "Don't call setQualifiedName for inner classes. Call setName instead. (" + qualifiedName + ")" );
664 		}
665 		_qualifiedName = qualifiedName;
666 		_transformedQualifiedName = qualifiedName;
667 		_name = Util.classNameFromQualifiedClassName( _qualifiedName );
668 		_transformedName = _name;
669 	}
670 
671 	/***
672 	 * Sets the ContainingPackage attribute of the AbstractProgramElement object
673 	 * Use package name specified in class, and do not complain about directory
674 	 * struct.
675 	 *
676 	 * @param containingPackage  The new ContainingPackage value
677 	 */
678 	final void setContainingPackage( String containingPackage )
679 	{
680 		_containingPackage = getXJavaDoc().addPackageMaybe( containingPackage );
681 	}
682 
683 	/***
684 	 * Sets the Interface attribute of the SourceClass object
685 	 *
686 	 * @param flag  The new Interface value
687 	 */
688 	final void setInterface( boolean flag )
689 	{
690 		_isInterface = flag;
691 		_superclass = null;
692 	}
693 
694 	/***
695 	 * Sets the SuperClass attribute of the SourceClass object
696 	 *
697 	 * @param superclass  The new Superclass value
698 	 */
699 	final void setSuperclass( String superclass )
700 	{
701 		_superclass = qualify( superclass );
702 		// Now tell the superclass and all its superclasses
703 		// that we're a subclass (Except java.lang.Object)
704 		/*
705 		 * XClass superclass = _superclass;
706 		 * while(superclass.getQualifiedName().equals("java.lang.Object")) {
707 		 * if(superclass._subclasses == null) {
708 		 * superclass._subclasses=new TreeSet();
709 		 * }
710 		 * superclass._subclasses.add(this);
711 		 * }
712 		 */
713 	}
714 
715 	/***
716 	 * This method is called for anonymous classes only. Anon classes come in 2
717 	 * flavours. They either realise a class or an interface.
718 	 *
719 	 * @param clazz
720 	 */
721 	final void setRealised( String clazz )
722 	{
723 		_isAnonymous = true;
724 
725 		XClass realised = qualify( clazz );
726 
727 		if( realised.isInterface() )
728 		{
729 			// We're realising an interface
730 			addInterface( clazz );
731 			setSuperclass( "java.lang.Object" );
732 		}
733 		else
734 		{
735 			// We're realising a class
736 			setSuperclass( clazz );
737 		}
738 	}
739 
740 	/***
741 	 * Sets the unqualified name of the class. Should only be called on objects
742 	 * that represent inner classes.
743 	 *
744 	 * @param name  The new Name value
745 	 */
746 	void setName( String name )
747 	{
748 		if( !isInner() )
749 		{
750 			throw new IllegalStateException( "Don't call setName for outer classes. Call setQualifiedName instead. (" + name + ")" );
751 		}
752 		if( name == null )
753 		{
754 			throw new IllegalStateException( "name can't be null!" );
755 		}
756 
757 		// The *real* name is the containing class' name + '.' + the name
758 
759 		String realName = getContainingClass().getName() + '.' + name;
760 
761 		// The *transformed* name is the containing class' transformed name + '$' + the name
762 
763 		String transformedName = getContainingClass().getTransformedName() + '$' + name;
764 
765 		if( _name != null && !_name.equals( realName ) )
766 		{
767 			throw new IllegalStateException( "Setting name 2nd time with a different value! 1st time: '" + _name + "', 2nd time: '" + name + "'" );
768 		}
769 		_name = realName;
770 		_transformedName = transformedName;
771 
772 		if( getContainingPackage().getName().equals( "" ) )
773 		{
774 			_qualifiedName = _name;
775 			_transformedQualifiedName = _transformedName;
776 		}
777 		else
778 		{
779 			_qualifiedName = getContainingPackage().getName() + '.' + _name;
780 			_transformedQualifiedName = getContainingPackage().getName() + '.' + _transformedName;
781 		}
782 		if( _qualifiedName.startsWith( "." ) )
783 		{
784 			throw new IllegalStateException( "qualifiedName can't start with a dot! " + _qualifiedName );
785 		}
786 	}
787 
788 	/***
789 	 * Adds an interface that this class implements (if this is a class) or an
790 	 * interface that this interface extends (if this is an interface)
791 	 *
792 	 * @param interfaceName  Describe the method parameter
793 	 */
794 	final void addInterface( String interfaceName )
795 	{
796 		if( _declaredInterfaces == null )
797 		{
798 			_declaredInterfaces = new LinkedList();
799 		}
800 
801 		XClass qualifiedInterface = qualify( interfaceName );
802 
803 		_declaredInterfaces.add( qualifiedInterface );
804 	}
805 
806 	void resolveImportedClasses()
807 	{
808 		if( _importedClassNames == null )
809 		{
810 			// No imported classes
811 			return;
812 		}
813 
814 		// The first time we're called, none of the imported classes are resolved.
815 		if( _importedClasses == null )
816 		{
817 			_importedClasses = new ArrayList( _importedClassNames.size() );
818 			for( Iterator i = _importedClassNames.iterator(); i.hasNext();  )
819 			{
820 				String importedClassName = ( String ) i.next();
821 
822 				_importedClasses.add( qualify( importedClassName ) );
823 			}
824 		}
825 	}
826 	/***
827 	 * Sets the ImportedClasses attribute of the AbstractClass object
828 	 *
829 	 * @param importedClass  Describe the method parameter
830 	 */
831 	void addImportedClass( String importedClass )
832 	{
833 		if( _importedClassNames == null )
834 		{
835 			_importedClassNames = new LinkedList();
836 		}
837 		_importedClassNames.add( importedClass );
838 	}
839 	/***
840 	 * Sets the ImportedPackages attribute of the AbstractClass object
841 	 *
842 	 * @param importedPackage  Describe the method parameter
843 	 */
844 	void addImportedPackage( String importedPackage )
845 	{
846 		if( _importedPackages == null )
847 		{
848 			_importedPackages = new LinkedList();
849 		}
850 
851 		XPackage pakkage = getXJavaDoc().addPackageMaybe( importedPackage );
852 
853 		_importedPackages.add( pakkage );
854 	}
855 
856 	/***
857 	 * Gets the Constructors attribute of the AbstractClass object
858 	 *
859 	 * @param constructor  Describe the method parameter
860 	 */
861 	void addConstructor( XConstructor constructor )
862 	{
863 		validate( constructor );
864 		if( _constructors == null )
865 		{
866 			_constructors = new LinkedList();
867 		}
868 		_constructors.add( constructor );
869 	}
870 
871 	/***
872 	 * Gets the Fields attribute of the AbstractClass object
873 	 *
874 	 * @param field  Describe the method parameter
875 	 */
876 	void addField( XField field )
877 	{
878 		validate( field );
879 		if( _fields == null )
880 		{
881 			_fields = new LinkedList();
882 		}
883 		_fields.add( field );
884 	}
885 	/***
886 	 * Gets the Methods attribute of the AbstractClass object
887 	 *
888 	 * @param method  Describe the method parameter
889 	 */
890 	void addMethod( XMethod method )
891 	{
892 		validate( method );
893 		if( _methods == null )
894 		{
895 			_methods = new LinkedList();
896 		}
897 
898 		_methods.add( method );
899 	}
900 
901 	void reset()
902 	{
903 		super.reset();
904 
905 		_declaredInterfaces = null;
906 		_allInterfaces = null;
907 		_importedClasses = null;
908 		_importedClassNames = null;
909 		_importedPackages = null;
910 		_constructors = null;
911 		_namedConstructors = null;
912 		_methods = null;
913 		_namedMethods = null;
914 		_fields = null;
915 		_innerClasses = null;
916 	}
917 
918 	/***
919 	 * Returns all the fields or methods.
920 	 *
921 	 * @param forFields     true if you want the fields, false if you want methods
922 	 * @param superclasses
923 	 * @return   A List of XMember
924 	 */
925 	private final List getMembers( boolean superclasses, boolean forFields )
926 	{
927 		if( !superclasses )
928 		{
929 			if( forFields )
930 			{
931 				return _fields == null ? EMPTY_LIST : Collections.unmodifiableList( _fields );
932 			}
933 			else
934 			{
935 				return _methods == null ? EMPTY_LIST : Collections.unmodifiableList( _methods );
936 			}
937 		}
938 		else
939 		{
940 			// Make a new Collection where we append all methods from this and super
941 			LinkedList members = new LinkedList();
942 
943 			// Add methods from this class if any.
944 			if( forFields )
945 			{
946 				if( _fields != null )
947 				{
948 					members.addAll( _fields );
949 				}
950 			}
951 			else
952 			{
953 				if( _methods != null )
954 				{
955 					members.addAll( _methods );
956 				}
957 			}
958 
959 			// Now add members from super
960 			AbstractClass superclass = ( AbstractClass ) getSuperclass();
961 
962 			if( superclass != null )
963 			{
964 				Collection superMembers = superclass.getMembers( true, forFields );
965 
966 				// Iterate over the superclass methods. Don't add methods that exist in subclasses
967 				// (overridden methods)
968 				for( Iterator m = superMembers.iterator(); m.hasNext();  )
969 				{
970 					XMember superMember = ( XMember ) m.next();
971 
972 					if( !superMember.isPrivate() && !members.contains( superMember ) )
973 					{
974 						members.add( superMember );
975 					}
976 				}
977 			}
978 
979 			// Add members from interfaces too.
980 			Collection interfaces = getInterfaces();
981 
982 			for( Iterator i = interfaces.iterator(); i.hasNext();  )
983 			{
984 				AbstractClass interfaze = ( AbstractClass ) i.next();
985 
986 				// We're iterating over every interface, so we *don't* ask for the super members
987 				Collection interfaceMembers = interfaze.getMembers( false, forFields );
988 
989 				// Iterate over the interface methods. Don't add methods that exist in the base class
990 				// or any of the immediate superclasses. Interface methods in the back of the line!!
991 				// (overridden methods)
992 				for( Iterator m = interfaceMembers.iterator(); m.hasNext();  )
993 				{
994 					XMember interfaceMember = ( XMember ) m.next();
995 
996 					if( !members.contains( interfaceMember ) )
997 					{
998 						members.add( interfaceMember );
999 					}
1000 				}
1001 			}
1002 
1003 			return Collections.unmodifiableList( members );
1004 		}
1005 	}
1006 
1007 	private final void validate( XMember member ) throws IllegalStateException
1008 	{
1009 		if( member.getName() == null )
1010 		{
1011 			throw new IllegalStateException( "Trying to add a member with no name:" + member.getClass().getName() + ":" + hashCode() );
1012 		}
1013 	}
1014 
1015 	private void initializeNamedMethodsHashMap()
1016 	{
1017 		if( _namedMethods != null || _methods == null )
1018 			return;
1019 
1020 		_namedMethods = new HashMap();
1021 
1022 		for( int i = 0; i < _methods.size(); i++ )
1023 		{
1024 			XMethod method = ( XMethod ) _methods.get( i );
1025 
1026 			_namedMethods.put( method.getNameWithSignature( false ), method );
1027 		}
1028 	}
1029 
1030 	private void initializeNamedConstructorsHashMap()
1031 	{
1032 		if( _namedConstructors != null || _constructors == null )
1033 			return;
1034 
1035 		_namedConstructors = new HashMap();
1036 
1037 		for( int i = 0; i < _constructors.size(); i++ )
1038 		{
1039 			XConstructor constructor = ( XConstructor ) _constructors.get( i );
1040 
1041 			_namedConstructors.put( constructor.getNameWithSignature( false ), constructor );
1042 		}
1043 	}
1044 }
1045