blob: 44748b26fb22ff88d8029a964f4fc009c689d301 [file] [log] [blame]
package org.apache.xmlbeans.impl.binding.bts;
import org.apache.xmlbeans.impl.jam.JMethod;
import org.apache.xmlbeans.impl.jam.JParameter;
import org.apache.xml.xmlbeans.bindingConfig.JavaMethodName;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* Abstraction which uniquely identifies a particular method on some class.
* This requires both a method name and some information about the method
* signature - this class just provides a structured representation of
* that information, as well a service (getMethodOn) for reflecting
* on a given class to find the java.lang.Method named by the MethodName.
*
* The basic motivation for adding this class is to remove guesswork from the
* runtime about how to map a 'getterName' string plus some notion of
* property type to an actual java.lang.Method. With MethodName, the
* binding file is able to make make it completely unambiguous.
*
* @author Patrick Calahan <pcal@bea.com>
*/
public class MethodName {
// ========================================================================
// Variables
private String mMethodName;
private JavaTypeName[] mParamTypes;
// ========================================================================
// Factory methods
/**
* Creates a MethodName which names the given JMethod.
*/
public static MethodName create(JMethod m) {
JParameter[] params = m.getParameters();
if (params == null || params.length == 0) {
return new MethodName(m.getSimpleName());
} else {
JavaTypeName[] types = new JavaTypeName[params.length];
for(int i=0; i<types.length; i++) {
types[i] = JavaTypeName.forJClass(params[i].getType());
}
return new MethodName(m.getSimpleName(),types);
}
}
/**
* Creates a MethodName for a method with the given name and no parameters
* (e.g., a getter).
*/
public static MethodName create(String methodName) {
return new MethodName(methodName);
}
/**
* Creates a MethodName for a method with the given name and a single
* parameter of the given type (e.g., a setter).
*/
public static MethodName create(String methodName, JavaTypeName paramType) {
return create(methodName,new JavaTypeName[] {paramType});
}
/**
* Creates a MethodName for a method with the given name and a set
* of parameters of the given types.
*/
public static MethodName create(String methodName, JavaTypeName[] paramTypes) {
if (paramTypes == null || paramTypes.length == 0) {
return new MethodName(methodName);
} else {
return new MethodName(methodName,paramTypes);
}
}
/**
* Creates a MethodName from the given XmlObject.
*/
/*package*/ static MethodName create(JavaMethodName jmn) {
return create(jmn.getMethodName(),
namesForStrings(jmn.getParamTypeArray()));
}
private static JavaTypeName[] namesForStrings(String[] names) {
JavaTypeName[] out = new JavaTypeName[names.length];
for(int i=0; i<out.length; i++) out[i] = JavaTypeName.forString(names[i]);
return out;
}
// ========================================================================
// Constructors
private MethodName(String methodName, JavaTypeName[] types) {
mMethodName = methodName;
mParamTypes = types;
}
private MethodName(String methodName) {
mMethodName = methodName;
mParamTypes = new JavaTypeName[0];
}
// ========================================================================
// Public methods
public String getSimpleName() { return mMethodName; }
/**
* Returns the java.lang.Method which is named by this MethodName
* on the given class.
*
* @param containingClass Class to be searched for the method.
* @return
* @throws ClassNotFoundException if one of the paramType classes specified
* for this MethodName cannot be loaded from the given class' classloader.
* @throws NoSuchMethodException If the named method does not exist on
* this class.
* @throws IllegalArgumentException if containingClass is null.
*/
public Method getMethodOn(Class containingClass)
throws ClassNotFoundException, NoSuchMethodException
{
if (containingClass == null) {
throw new IllegalArgumentException("null class");
}
Class[] types = null;
if (mParamTypes != null && mParamTypes.length > 0) {
types = new Class[mParamTypes.length];
for(int i=0; i<types.length; i++) {
types[i] = mParamTypes[i].loadClassIn(containingClass.getClassLoader());
}
}
return containingClass.getMethod(mMethodName,types);
}
// ========================================================================
// Object implementation
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MethodName)) return false;
final MethodName methodName = (MethodName) o;
if (mMethodName != null ? !mMethodName.equals(methodName.mMethodName) :
methodName.mMethodName != null) return false;
if (!Arrays.equals(mParamTypes, methodName.mParamTypes)) return false;
return true;
}
public int hashCode() {
return (mMethodName != null ? mMethodName.hashCode() : 0);
}
// ========================================================================
// Package methods
/**
* Populates the given xmlobject with our contents.
*/
/*package*/ void write(JavaMethodName name) {
name.setMethodName(mMethodName);
if (mParamTypes != null && mParamTypes.length > 0) {
String[] types = new String[mParamTypes.length];
for(int i=0; i<types.length; i++) types[i] = mParamTypes[i].toString();
name.setParamTypeArray(types);
}
}
/* should make this a test
public static void main(String[] args) throws Exception {
test("java.lang.String",String.class);
test("java.lang.String[]",String[].class);
test("int",int.class);
test("int[]",int[].class);
test("double[][][]",double[][][].class);
}
public static void test(String jtn, Class c) throws Exception {
JavaTypeName name = JavaTypeName.forString(jtn);
if (!name.loadClassIn(ClassLoader.getSystemClassLoader()).equals(c)) {
System.out.println(jtn+" failed "+c.getName());
} else {
System.out.println(jtn+" passed "+c.getName());
}
}
*/
}