com.thoughtworks.qdox.model.JavaMethod Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of qdox Show documentation
Show all versions of qdox Show documentation
QDox is a high speed, small footprint parser for extracting class/interface/method definitions from source files
complete with JavaDoc @tags. It is designed to be used by active code generators or documentation tools.
package com.thoughtworks.qdox.model;
import java.beans.Introspector;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class JavaMethod extends AbstractInheritableJavaEntity implements Member {
private TypeVariable[] typeParameters = TypeVariable.EMPTY_ARRAY;
private Type returns = Type.VOID;
private List parameters = new LinkedList();
private JavaParameter[] parametersArray = JavaParameter.EMPTY_ARRAY;
private Type[] exceptions = Type.EMPTY_ARRAY;
private boolean constructor;
private String sourceCode;
private boolean varArgs;
/**
* The default constructor
*/
public JavaMethod() {
}
/**
* Create new method without parameters and return type
*
* @param name the name of the method
*/
public JavaMethod(String name) {
setName(name);
}
/**
* Create a new method without parameters
*
* @param returns the return type
* @param name the name of this method
*/
public JavaMethod(Type returns, String name) {
setReturns(returns);
setName(name);
}
/**
*
* @return the return type
* @deprecated it is recommended to use getReturnType()
*/
public Type getReturns() {
return returns;
}
public JavaParameter[] getParameters() {
if(parametersArray == null) {
parametersArray = new JavaParameter[parameters.size()];
parameters.toArray( parametersArray );
}
return parametersArray;
}
public JavaParameter getParameterByName(String name) {
JavaParameter[] parameters = getParameters();
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].getName().equals(name)) {
return parameters[i];
}
}
return null;
}
public Type[] getExceptions() {
return exceptions;
}
/**
*
* @return true is this method is a constructor
*/
public boolean isConstructor() {
return constructor;
}
/**
*
* @return true is this method conains varArgs
*/
public boolean isVarArgs()
{
return varArgs;
}
protected void writeBody(IndentBuffer result) {
writeBody(result, true, true, true);
}
/**
* @since 1.3
*/
protected void writeBody(IndentBuffer result, boolean withModifiers, boolean isDeclaration, boolean isPrettyPrint) {
if (withModifiers) {
writeAccessibilityModifier(result);
writeNonAccessibilityModifiers(result);
}
if (!constructor) {
if(isDeclaration) {
result.write(returns.toString());
result.write(' ');
}
}
result.write(name);
result.write('(');
for (int i = 0; i < getParameters().length; i++) {
JavaParameter parameter = parametersArray[i];
if (i > 0) result.write(", ");
if (isDeclaration) {
result.write(parameter.getType().toString());
if (parameter.isVarArgs()) {
result.write("...");
}
result.write(' ');
}
result.write(parameter.getName());
}
result.write(')');
if (isDeclaration && exceptions.length > 0) {
result.write(" throws ");
for (int i = 0; i < exceptions.length; i++) {
if (i > 0) result.write(", ");
result.write(exceptions[i].getValue());
}
}
if (isPrettyPrint) {
if (sourceCode != null && sourceCode.length() > 0) {
result.write(" {");
result.newline();
result.write(sourceCode);
result.write("}");
result.newline();
} else {
result.write(';');
result.newline();
}
}
}
/**
* @since 1.3
*/
private String getSignature(boolean withModifiers, boolean isDeclaration) {
IndentBuffer result = new IndentBuffer();
writeBody(result, withModifiers, isDeclaration, false);
return result.toString();
}
/**
* @since 1.3
*/
public String getDeclarationSignature(boolean withModifiers) {
return getSignature(withModifiers, true);
}
/**
* @since 1.3
*/
public String getCallSignature() {
return getSignature(false, false);
}
/**
* Define the return type of this method
*
* @param returns the return type
*/
public void setReturns(Type returns) {
this.returns = returns;
}
public void addParameter(JavaParameter javaParameter) {
javaParameter.setParentMethod( this );
parameters.add( javaParameter );
parametersArray = null;
this.varArgs = javaParameter.isVarArgs();
}
public void setExceptions(Type[] exceptions) {
this.exceptions = exceptions;
}
public void setConstructor(boolean constructor) {
this.constructor = constructor;
}
public boolean equals(Object obj) {
if ( this == obj )
{
return true;
}
if ( !( obj instanceof JavaMethod ) )
{
return false;
}
JavaMethod m = (JavaMethod) obj;
if (m.isConstructor() != isConstructor())
{
return false;
}
if ( m.getName() != null && !m.getName().equals( this.getName() ) )
{
return false;
}
if ( this.getName() != null && !this.getName().equals( m.getName() ) )
{
return false;
}
if ( m.getReturns() != null && !m.getReturns().equals( this.getReturns() ) )
{
return false;
}
if ( this.getReturns() != null && !this.getReturns().equals( m.getReturns() ) )
{
return false;
}
JavaParameter[] myParams = getParameters();
JavaParameter[] otherParams = m.getParameters();
if (otherParams.length != myParams.length) return false;
for (int i = 0; i < myParams.length; i++) {
if (!otherParams[i].equals(myParams[i])) return false;
}
return this.varArgs == m.varArgs;
}
/**
* This method is NOT varArg aware. The overloaded method is.
*
* @param name
* @param parameterTypes
* @return
* @deprecated use overloaded method
*/
public boolean signatureMatches(String name, Type[] parameterTypes) {
return signatureMatches( name, parameterTypes, false );
}
/**
* @param name method name
* @param parameterTypes parameter types or null if there are no parameters.
* @return true if the signature and parameters match.
*/
public boolean signatureMatches(String name, Type[] parameterTypes, boolean varArg) {
if (!name.equals(this.name)) return false;
parameterTypes = (parameterTypes == null ? new Type[0] : parameterTypes);
if (parameterTypes.length != this.getParameters().length) return false;
for (int i = 0; i < parametersArray.length; i++) {
if (!parametersArray[i].getType().equals(parameterTypes[i])) {
return false;
}
}
return (this.varArgs == varArg);
}
public int hashCode() {
int hashCode = name.hashCode();
if (returns != null) hashCode *= returns.hashCode();
hashCode *= getParameters().length;
return hashCode;
}
public boolean isPublic() {
return super.isPublic() || (getParentClass() != null ? getParentClass().isInterface() : false);
}
/**
* @return true if this method is a Java Bean accessor
* @since 1.3
*/
public boolean isPropertyAccessor() {
if (isStatic()) return false;
if (getParameters().length != 0) return false;
if (getName().startsWith("is")) {
return (getName().length() > 2
&& Character.isUpperCase(getName().charAt(2)));
}
if (getName().startsWith("get")) {
return (getName().length() > 3
&& Character.isUpperCase(getName().charAt(3)));
}
return false;
}
/**
* @return true if this method is a Java Bean accessor
* @since 1.3
*/
public boolean isPropertyMutator() {
if (isStatic()) return false;
if (getParameters().length != 1) return false;
if (getName().startsWith("set")) {
return (getName().length() > 3
&& Character.isUpperCase(getName().charAt(3)));
}
return false;
}
/**
* @return the type of the property this method represents, or null if this method
* is not a property mutator or property accessor.
* @since 1.3
*/
public Type getPropertyType() {
if (isPropertyAccessor()) {
return getReturns();
}
if (isPropertyMutator()) {
return getParameters()[0].getType();
}
return null;
}
/**
* @return the name of the property this method represents, or null if this method
* is not a property mutator or property accessor.
* @since 1.3
*/
public String getPropertyName() {
int start = -1;
if (getName().startsWith("get") || getName().startsWith("set")) {
start = 3;
} else if (getName().startsWith("is")) {
start = 2;
} else {
return null;
}
return Introspector.decapitalize(getName().substring(start));
}
public DocletTag[] getTagsByName(String name, boolean inherited) {
JavaClass clazz = getParentClass();
JavaParameter[] params = getParameters();
Type[] types = new Type[params.length];
for (int i = 0; i < types.length; i++) {
types[i] = params[i].getType();
}
JavaMethod[] methods = clazz.getMethodsBySignature(getName(), types, true);
List result = new ArrayList();
for (int i = 0; i < methods.length; i++) {
JavaMethod method = methods[i];
DocletTag[] tags = method.getTagsByName(name);
for (int j = 0; j < tags.length; j++) {
DocletTag tag = tags[j];
if(!result.contains(tag)) {
result.add(tag);
}
}
}
return (DocletTag[]) result.toArray(new DocletTag[result.size()]);
}
public int compareTo(Object o) {
return getDeclarationSignature(false).compareTo(((JavaMethod)o).getDeclarationSignature(false));
}
/**
* Get the original source code of the body of this method.
*
* @return Code as string.
*/
public String getSourceCode(){
return sourceCode;
}
public void setSourceCode(String sourceCode){
this.sourceCode = sourceCode;
}
public void setTypeParameters(TypeVariable[] typeParameters) {
this.typeParameters = typeParameters;
}
public TypeVariable[] getTypeParameters() {
return typeParameters;
}
public String toString() {
StringBuffer result = new StringBuffer();
if(isPrivate()) {
result.append("private ");
}
else if(isProtected()) {
result.append("protected ");
}
else if(isPublic()) {
result.append("public ");
}
if(isAbstract()) {
result.append("abstract ");
}
if(isStatic()) {
result.append("static ");
}
if(isFinal()) {
result.append("final ");
}
if(isSynchronized()) {
result.append("synchronized ");
}
if(isNative()) {
result.append("native ");
}
if (!constructor) {
result.append(getReturns().getValue() + " ");
}
if(getParentClass() != null) {
result.append(getParentClass().getFullyQualifiedName());
if (!constructor) {
result.append(".");
}
}
if (!constructor) {
result.append(getName());
}
result.append("(");
for(int paramIndex=0;paramIndex0) {
result.append(",");
}
String typeValue = getParameters()[paramIndex].getType().getResolvedValue(getTypeParameters());
result.append(typeValue);
}
result.append(")");
for(int i = 0; i < exceptions.length; i++) {
result.append(i==0 ? " throws " : ",");
result.append(exceptions[i].getValue());
}
return result.toString();
}
/**
* Equivalent of java.lang.reflect.Method.getGenericReturnType()
*
* @return the generic returntype
* @since 1.12
*/
public Type getGenericReturnType()
{
return returns;
}
/**
* Equivalent of java.lang.reflect.Method.getReturnType()
*
* @return
* @since 1.12
*/
public Type getReturnType() {
return getReturnType( false );
}
/**
* If a class inherits this method from a generic class or interface, you can use this method to get the resolved return type
*
* @param resolve
* @return
* @since 1.12
*/
public Type getReturnType( boolean resolve )
{
return getReturnType( resolve, getParentClass() );
}
/**
*
* @param resolve
* @param callingClass
* @return
* @since 1.12
*/
protected Type getReturnType ( boolean resolve, JavaClass callingClass) {
Type result = null;
if (getReturns() != null) {
result = getReturns().resolve( this.getParentClass(), callingClass );
//According to java-specs, if it could be resolved the upper boundary, so Object, should be returned
if ( !resolve && !returns.getFullyQualifiedName().equals( result.getFullyQualifiedName() ) )
{
result = new Type( "java.lang.Object" );
}
}
return result;
}
/**
*
* @return the parameter types as array
* @since 1.12
*/
public Type[] getParameterTypes() {
return getParameterTypes( false );
}
/**
* If a class inherits this method from a generic class or interface, you can use this method to get the resolved parameter types
*
* @param resolve
* @return the parameter types as array
* @since 1.12
*/
public Type[] getParameterTypes( boolean resolve ) {
return getParameterTypes( resolve, getParentClass() );
}
protected Type[] getParameterTypes ( boolean resolve, JavaClass callingClass) {
Type[] result = new Type[getParameters().length];
for (int paramIndex = 0; paramIndex < getParameters().length; paramIndex++ )
{
Type curType = getParameters()[paramIndex].getType().resolve( this.getParentClass(), callingClass );
//According to java-specs, if it could be resolved the upper boundary, so Object, should be returned
if ( !resolve && returns != null && !returns.getFullyQualifiedName().equals( curType.getFullyQualifiedName() ) )
{
result[paramIndex] = new Type( "java.lang.Object" );
}
else {
result[paramIndex] = curType;
}
}
return result;
}
}