View Javadoc

    1   /*
    2    * Copyright (c) 2001-2003 The XDoclet team
    3    * All rights reserved.
    4    */
    5   package xjavadoc;
    6
    7   import java.lang.reflect.Modifier;
    8   import java.util.ArrayList;
    9   import java.util.Iterator;
    10  import java.util.List;
    11  import java.beans.Introspector;
    12
    13  /***
    14   * Describe what this class does
    15   *
    16   * @author    Aslak Hellesøy
    17   * @created   25. februar 2003
    18   */
    19  final class MethodImpl extends AbstractExecutableMember implements XMethod
    20  {
    21  	public static int  instanceCount = 0;
    22
    23  	private String     methodNameWithSignatureAndModifiers = null;
    24  	private String     methodNameWithSignatureWithoutModifiers = null;
    25
    26  	private ReturnType _returnType = new ReturnType( this );
    27
    28  	public MethodImpl( AbstractClass containingClass, XTagFactory tagFactory )
    29  	{
    30  		super( containingClass, tagFactory );
    31
    32  		// if we're in an interface, add public modifier even if it isn't declared,
    33  		// since interface methods are always public.
    34  		if( containingClass.isInterface() )
    35  		{
    36  			addModifier( Modifier.PUBLIC );
    37  		}
    38  		instanceCount++;
    39  	}
    40
    41  	/***
    42  	 * Gets the Constructor attribute of the SourceMethod object
    43  	 *
    44  	 * @return   The Constructor value
    45  	 */
    46  	public final boolean isConstructor()
    47  	{
    48  		return false;
    49  	}
    50
    51  	public final Type getReturnType()
    52  	{
    53  		return _returnType;
    54  	}
    55
    56  	public XProgramElement getSuperElement()
    57  	{
    58  		return getSuperElement( true );
    59  	}
    60
    61  	public List getSuperInterfaceElements()
    62  	{
    63
    64  		Iterator interfaces = getContainingClass().getInterfaces().iterator();
    65
    66  		List result = new ArrayList();
    67
    68  		while ( interfaces.hasNext() )
    69  		{
    70
    71  			XClass superinterface = (XClass) interfaces.next();
    72
    73  			XExecutableMember superExecutableMember = superinterface.getMethod( getNameWithSignature( false ) );
    74  			if( superExecutableMember != null )
    75  			{
    76  				result.add( superExecutableMember );
    77  			}
    78
    79  			//TODO: do we need to keep searching upwards, to find superinterfaces?
    80
    81  		}
    82
    83  		return result;
    84  	}
    85
    86  	public XMethod getAccessor()
    87  	{
    88  		XMethod result = null;
    89
    90  		if( isPropertyMutator() )
    91  		{
    92  			Type requiredType = ( Type ) getParameters().iterator().next();
    93  			String getterNameWithSignature = "get" + getNameWithoutPrefix() + "()";
    94  			String isserNameWithSignature = "is" + getNameWithoutPrefix() + "()";
    95  			XMethod getter = getContainingClass().getMethod( getterNameWithSignature, true );
    96  			XMethod isser = getContainingClass().getMethod( isserNameWithSignature, true );
    97
    98  			// If only one is non null, return it. If both or none exist, return null.
    99  			if( getter == null && isser != null )
    100 			{
    101 				result = isser;
    102 			}
    103 			else if( getter != null && isser == null )
    104 			{
    105 				result = getter;
    106 			}
    107 			// Verify that the types are compatible
    108 			if( !requiredType.equals( result.getReturnType() ) )
    109 			{
    110 				result = null;
    111 			}
    112 		}
    113 		return result;
    114 	}
    115
    116 	public XMethod getMutator()
    117 	{
    118 		XMethod result = null;
    119
    120 		if( isPropertyAccessor() )
    121 		{
    122 			Type requiredType = getReturnType();
    123 			String argument = requiredType.getType().getQualifiedName() + requiredType.getDimensionAsString();
    124 			String setterNameWithSignature = "set" + getNameWithoutPrefix() + "(" + argument + ")";
    125
    126 			result = getContainingClass().getMethod( setterNameWithSignature, true );
    127 		}
    128 		return result;
    129 	}
    130
    131 	public boolean isPropertyAccessor()
    132 	{
    133 		boolean signatureOk = false;
    134 		boolean nameOk = false;
    135
    136 		if( getName().startsWith( "is" ) )
    137 		{
    138 			signatureOk = getReturnType().getType().getQualifiedName().equals( "boolean" ) || getReturnType().getType().getQualifiedName().equals( "java.lang.Boolean" );
    139 			signatureOk = signatureOk && getReturnType().getDimension() == 0;
    140 			if( getName().length() > 2 )
    141 			{
    142 				nameOk = Character.isUpperCase( getName().charAt( 2 ) );
    143 			}
    144 		}
    145 		if( getName().startsWith( "get" ) )
    146 		{
    147 			signatureOk = true;
    148 			if( getName().length() > 3 )
    149 			{
    150 				nameOk = Character.isUpperCase( getName().charAt( 3 ) );
    151 			}
    152 		}
    153
    154 		boolean noParams = getParameters().size() == 0;
    155
    156 		return signatureOk && nameOk && noParams;
    157 	}
    158
    159 	public boolean isPropertyMutator()
    160 	{
    161 		boolean nameOk = false;
    162
    163 		if( getName().startsWith( "set" ) )
    164 		{
    165 			if( getName().length() > 3 )
    166 			{
    167 				nameOk = Character.isUpperCase( getName().charAt( 3 ) );
    168 			}
    169 		}
    170
    171 		boolean oneParam = getParameters().size() == 1;
    172
    173 		return nameOk && oneParam;
    174 	}
    175
    176 	public String getPropertyName()
    177 	{
    178 		String result = null;
    179
    180 		if( getName().startsWith( "get" ) || getName().startsWith( "set" ) )
    181 		{
    182 			result = Introspector.decapitalize( getName().substring( 3 ) );
    183 		}
    184 		else if( getName().startsWith( "is" ) )
    185 		{
    186 			result = Introspector.decapitalize( getName().substring( 2 ) );
    187 		}
    188 		return result;
    189 	}
    190
    191 	public Type getPropertyType()
    192 	{
    193 		Type result = null;
    194
    195 		if( isPropertyMutator() )
    196 		{
    197 			XParameter parameter = ( XParameter ) getParameters().iterator().next();
    198
    199 			result = parameter;
    200 		}
    201 		else if( isPropertyAccessor() )
    202 		{
    203 			result = getReturnType();
    204 		}
    205 		return result;
    206 	}
    207
    208 	public String getNameWithoutPrefix()
    209 	{
    210 		for( int i = 0; i < getName().length(); i++ )
    211 		{
    212 			if( Character.isUpperCase( getName().charAt( i ) ) )
    213 			{
    214 				return getName().substring( i );
    215 			}
    216 		}
    217 		return null;
    218 	}
    219
    220 	/***
    221 	 * Sets the ReturnType attribute of the SourceMethod object
    222 	 *
    223 	 * @param returnType  The new ReturnType value
    224 	 */
    225 	public final void setReturnType( String returnType )
    226 	{
    227 		_returnType.setType( returnType );
    228 	}
    229
    230 	/***
    231 	 * Sets the ReturnDimension attribute of the SourceMethod object
    232 	 *
    233 	 * @param d  The new ReturnDimension value
    234 	 */
    235 	public final void setReturnDimension( int d )
    236 	{
    237 		_returnType.setDimension( d );
    238 	}
    239
    240 	/***
    241 	 * Two methods are equal if they have the same return type, name and signature,
    242 	 * regardless of the enclosing class and modifiers. Methods are compared for
    243 	 * equality when calling XClass.getMethods(true)
    244 	 *
    245 	 * @param o
    246 	 * @return
    247 	 */
    248 	public boolean equals( Object o )
    249 	{
    250 		MethodImpl other = ( MethodImpl ) o;
    251
    252 		return getMethodNameWithSignatureWithoutModifiers().equals( other.getMethodNameWithSignatureWithoutModifiers() );
    253 	}
    254
    255 	public int hashCode()
    256 	{
    257 		return toString( false ).hashCode();
    258 	}
    259
    260 	public String toString()
    261 	{
    262 		return getMethodNameWithSignatureAndModifiers() + " [" + getContainingClass().getQualifiedName() + "]";
    263 	}
    264
    265 	protected String buildStringId()
    266 	{
    267 		return getMethodNameWithSignatureWithoutModifiers();
    268 	}
    269
    270 	private String getMethodNameWithSignatureAndModifiers()
    271 	{
    272 		if( methodNameWithSignatureAndModifiers == null )
    273 		{
    274 			methodNameWithSignatureAndModifiers = toString( true );
    275 		}
    276 		return methodNameWithSignatureAndModifiers;
    277 	}
    278
    279 	private String getMethodNameWithSignatureWithoutModifiers()
    280 	{
    281 		if( methodNameWithSignatureWithoutModifiers == null )
    282 		{
    283 			methodNameWithSignatureWithoutModifiers = toString( false );
    284 		}
    285 		return methodNameWithSignatureWithoutModifiers;
    286 	}
    287
    288 	/***
    289 	 * Builds a String uniquely describing this method
    290 	 *
    291 	 * @param modifiers
    292 	 * @return           a String uniquely describing this method
    293 	 */
    294 	private String toString( boolean modifiers )
    295 	{
    296 		StringBuffer sb;
    297
    298 		if( modifiers )
    299 		{
    300 			sb = new StringBuffer( getModifiers() );
    301 			if( sb.length() > 0 )
    302 			{
    303 				sb.append( ' ' );
    304 			}
    305 		}
    306 		else
    307 		{
    308 			sb = new StringBuffer();
    309 		}
    310 		sb.append( getReturnType().getType().getQualifiedName() );
    311 		sb.append( getReturnType().getDimensionAsString() );
    312 		sb.append( ' ' );
    313 		sb.append( getNameWithSignature( false ) );
    314 		return sb.toString();
    315 	}
    316
    317 }