blob: 177e57d492b2fc7bfa495a6c383785b6a2876dd5 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* 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.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 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) {
if (jmn == null) return null;
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());
}
}
*/
}