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