blob: 7d674445d3dc0ad3a156a3ab3bc0b87c716fd095 [file] [log] [blame]
package org.codehaus.groovy.runtimemetaclassactionssupport;
import groovy.lang.GString;
import java.lang.reflect.Method;
/*
* Copyright 2005 John G. Wilson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/**
* @author John Wilson
*
*/
public abstract class MethodGenerator {
protected final static String DEFAULT_GROOVY_METHODS = "org.codehaus.groovy.runtime.DefaultGroovyMethods";
protected final static String DEFAULT_STATIC_GROOVY_METHODS = "org.codehaus.groovy.runtime.DefaultGroovyStaticMethods";
protected final Method method;
/**
* @param method
*/
public MethodGenerator(Method method) {
this.method = method;
}
public String getName() {
return this.method.getName();
}
public int getNumberOfParameters() {
return this.method.getParameterTypes().length;
}
public Class[] getParameterTypes() {
return this.method.getParameterTypes();
}
public boolean isOverloaded(final MethodGenerator other) {
return getName().equals(other.getName()) && getNumberOfParameters() == other.getNumberOfParameters();
}
public MethodGenerator processOverloaded(final Class claz, final MethodGenerator other) {
final Class[] p1 = getParameterTypes();
final Class[] p2 = other.getParameterTypes();
for (int i = 0; i != p1.length; i++) {
if (p1[i] != p2[i]) {
return new OverloadedMethodsGenerator(this, other); // We have an overloaded method
}
}
// We have a duplicate - return the one which has its declaring class as the current class
if (this.method.getDeclaringClass() == claz) {
return this;
} else {
return other;
}
}
public String generateDeclaration(int methodIndex) {
return "";
}
public String generateCall(final Class claz) {
final StringBuffer code = new StringBuffer();
final Class returnType = method.getReturnType();
if (returnType.isPrimitive()) {
if (returnType == void.class) {
makeCall(code).append(";\nreturn null;\n");
} else if (returnType == int.class) {
code.append("return new Integer(");
makeCall(code).append(");\n");
} else if (returnType == long.class) {
code.append("return new Long(");
makeCall(code).append(");\n");
} else if (returnType == short.class) {
code.append("return new Short(");
makeCall(code).append(");\n");
} else if (returnType == char.class) {
code.append("return new Char(");
makeCall(code).append(");\n");
} else if (returnType == byte.class) {
code.append("return new Byte(");
makeCall(code).append(");\n");
} else if (returnType == boolean.class) {
code.append("return new Boolean(");
makeCall(code).append(");\n");
} else if (returnType == float.class) {
code.append("return new Float(");
makeCall(code).append(");\n");
} else if (returnType == double.class) {
code.append("return new Double(");
makeCall(code).append(");\n");
} else {
code.append("**** ERROR ***** found primitive return type: " + returnType.getName());
}
} else {
code.append("return ");
makeCall(code).append(";\n");
}
return code.toString();
}
private StringBuffer makeCall(final StringBuffer code) {
startCall(code);
addParameters(code, this.method.getParameterTypes()).append(')');
return code;
}
protected abstract void startCall(StringBuffer code);
protected StringBuffer addParameters(final StringBuffer code, final Class[] parameterTypes) {
if (parameterTypes.length != 0) {
for (int i = 0; i != parameterTypes.length; i++) {
final Class parameterType = parameterTypes[i];
if (parameterType.isPrimitive()) {
if (parameterType == int.class) {
code.append("((Number)").append("args[");
code.append(i).append("]).intValue(), ");
} else if (parameterType == long.class) {
code.append("((Number)").append("args[");
code.append(i).append("]).longValue(), ");
} else if (parameterType == short.class) {
code.append("((Number)").append("args[");
code.append(i).append("]).shortValue(), ");
} else if (parameterType == char.class) {
code.append("((Character)").append("args[");
code.append(i).append("]).charValue(), ");
} else if (parameterType == byte.class) {
code.append("((Number)").append("args[");
code.append(i).append("]).byteValue(), ");
} else if (parameterType == boolean.class) {
code.append("((Boolean)").append("args[");
code.append(i).append("]).booleanValue(), ");
} else if (parameterType == float.class) {
code.append("((Number)").append("args[");
code.append(i).append("]).floatValue(), ");
} else if (parameterType == double.class) {
code.append("((Number)").append("args[");
code.append(i).append("]).doubleValue(), ");
} else {
code.append("**** ERROR ***** found primative parameter type: " + parameterType.getName());
}
} else if (parameterType == String.class) {
code.append("args[").append(i).append("].toString(), ");
} else if (parameterType == GString.class) {
code.append("(groovy.lang.GString)((args[").append(i).append("] instanceof groovy.lang.GString) ? ");
code.append("args[").append(i).append("] : ");
code.append("new groovy.lang.GString(args[").append(i).append("].toString()){public String[] getStrings() {return (String [])this.getValues();}}), ");
} else {
code.append('(');
getFullName(parameterType, code);
code.append(")args[").append(i).append("], ");
}
}
code.setLength(code.length() - 2); // trim the last "' " off
}
return code;
}
protected StringBuffer getFullName(final Class claz, final StringBuffer code) {
final Package classPackage = (claz.isArray()) ? claz.getComponentType().getPackage() : claz.getPackage();
if (classPackage != null) {
code.append(classPackage.getName()).append('.') ;
}
return code.append(claz.getSimpleName());
}
}