blob: a7c0a60ca3cc3356d608c4c576e2072d2508f462 [file] [log] [blame]
/*
* 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.
*
*/
package org.codehaus.groovy.runtimemetaclassactionssupport;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* @author John Wilson
*
*/
public class OverloadedMethodsGenerator extends MethodGenerator {
private final MethodGenerator firstMethod;
private final List generatorList = new LinkedList();
private int methodIndex = 0;
public OverloadedMethodsGenerator(final MethodGenerator firstMethod, final MethodGenerator secondMethod) {
super(null);
this.firstMethod = firstMethod;
this.generatorList.add(firstMethod);
this.generatorList.add(secondMethod);
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#generateCall(java.lang.Class)
*/
public String generateCall(final Class claz) {
final StringBuffer code = new StringBuffer();
final Iterator iter = this.generatorList.iterator();
int i = 0;
code.append("switch(chooseMethod(possible").append(getName()).append("Parameters").append(this.methodIndex).append(", args)) {\n");
while (iter.hasNext()) {
final MethodGenerator generator = (MethodGenerator)iter.next();
code.append("case ").append(i++).append(": \n");
code.append(generator.generateCall(claz));
}
code.append("default:\n");
code.append("return groovy.lang.MetaClass.NO_METHOD_FOUND;\n");
code.append("}\n");
return code.toString();
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#startCall(java.lang.StringBuffer)
*/
protected void startCall(final StringBuffer code) {
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#generateDeclaration(int)
*/
public String generateDeclaration(final int methodIndex) {
final StringBuffer code = new StringBuffer();
final Iterator iter = this.generatorList.iterator();
int i = 1;
this.methodIndex = methodIndex;
while (iter.hasNext()) {
final MethodGenerator generator = (MethodGenerator)iter.next();
code.append(generator.generateDeclaration((methodIndex << 16) | i )); // TODO: find a better way of getting unique indexes
}
code.append("private final Class[][] possible").append(getName()).append("Parameters").append(methodIndex).append(" = new Class[][]{\n");
final Iterator iter1 = this.generatorList.iterator();
while (iter1.hasNext()) {
final MethodGenerator generator = (MethodGenerator)iter1.next();
final Class[] parameterTypes = generator.getParameterTypes();
code.append("new Class[] {");
for (int j = 0; j != parameterTypes.length; j++) {
final Class parameterType = parameterTypes[j];
if (parameterType.isPrimitive()) {
if (parameterType == int.class) {
code.append("int");
} else if (parameterType == long.class) {
code.append("long");
} else if (parameterType == short.class) {
code.append("short");
} else if (parameterType == char.class) {
code.append("char");
} else if (parameterType == byte.class) {
code.append("byte");
} else if (parameterType == boolean.class) {
code.append("boolean");
} else if (parameterType == float.class) {
code.append("float");
} else if (parameterType == double.class) {
code.append("double");
} else {
code.append("**** ERROR ***** found primative parameter type: " + parameterType.getName());
}
} else {
getFullName(parameterType, code);
}
code.append(".class, ");
}
code.setLength(code.length() - 2); // Trim the trailing ", "
code.append("},\n ");
}
code.setLength(code.length() - 3); // Trim the trailing ",\n "
code.append("\n};\n");
return code.toString();
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#getName()
*/
public String getName() {
return firstMethod.getName();
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#getNumberOfParameters()
*/
public int getNumberOfParameters() {
return firstMethod.getNumberOfParameters();
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#getParameterTypes()
*/
public Class[] getParameterTypes() {
return firstMethod.getParameterTypes();
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#isOverloaded(org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator)
*/
public boolean isOverloaded(final MethodGenerator other) {
return firstMethod.isOverloaded(other);
}
/* (non-Javadoc)
* @see org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator#processOverloaded(java.lang.Class, org.codehaus.groovy.runtimemetaclassactionssupport.MethodGenerator)
*/
public MethodGenerator processOverloaded(final Class claz, final MethodGenerator other) {
if (other instanceof OverloadedMethodsGenerator) {
final Iterator iter = ((OverloadedMethodsGenerator)other).generatorList.iterator();
while (iter.hasNext()) {
processOverloaded(claz, (MethodGenerator)iter.next());
}
} else {
final Class[] p1 = other.getParameterTypes();
for (int i = 0; i != this.generatorList.size(); i++) {
final MethodGenerator generator = (MethodGenerator)this.generatorList.get(i);
final Class[] p2 = generator.getParameterTypes();
int j = 0;
while (p1[j] == p2[j] && ++j != p1.length);
if (j == p1.length) {
// other is a duplicate of this method
if (other.method.getDeclaringClass() == claz) {
this.generatorList.add(i, other);
}
return this;
}
}
this.generatorList.add(other);
}
return this;
}
}