blob: 803622016cc39aafbe628768a8b869434965308d [file] [log] [blame]
//Copyright 2004, 2005 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.tapestry.enhance;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
/**
* Implementation of {@link MethodSignature} that supports jdk 1.5 generic typing support.
*
*/
public class GenericsMethodSignatureImpl extends MethodSignatureImpl implements MethodSignature
{
boolean _isGeneric;
public GenericsMethodSignatureImpl(Class type, Method m)
{
super(findReturnType(type, m), m.getName(), findParameterTypes(type, m), m.getExceptionTypes());
_isGeneric = type.getGenericSuperclass() != null && ParameterizedType.class.isInstance(type.getGenericSuperclass());
}
public boolean isGeneric()
{
return _isGeneric;
}
static Class findReturnType(Class type, Method m)
{
Type ret = m.getGenericReturnType();
if (TypeVariable.class.isInstance(ret)
&& type.getGenericSuperclass() != null
&& ParameterizedType.class.isInstance(type.getGenericSuperclass())) {
TypeVariable tvar = (TypeVariable)ret;
ParameterizedType param = (ParameterizedType)type.getGenericSuperclass();
Class resolvedType = resolveType(param, tvar);
if (resolvedType != null)
return resolvedType;
}
return m.getReturnType();
}
static Class resolveType(ParameterizedType param, TypeVariable var)
{
if (param.getActualTypeArguments().length < 1)
return null;
for (int i=0; i < var.getBounds().length; i++) {
Type t = var.getBounds()[i];
Class resolvedType = null;
if (ParameterizedType.class.isInstance(t)) {
ParameterizedType pparam = (ParameterizedType)t;
for (int e=0; e < pparam.getActualTypeArguments().length; e++) {
if (!TypeVariable.class.isInstance(pparam.getActualTypeArguments()[e]))
continue;
resolvedType = resolveType(pparam, (TypeVariable)pparam.getActualTypeArguments()[e]);
}
} else {
resolvedType = findType(param.getActualTypeArguments(), (Class)t);
}
if (resolvedType != null)
return resolvedType;
}
return null;
}
static Class findType(Type[] types, Class type)
{
for (int i = 0; i < types.length; i++) {
if (Class.class.isInstance(types[i]) && type.isAssignableFrom((Class)types[i]))
return (Class)types[i];
}
return null;
}
static Class[] findParameterTypes(Class type, Method m)
{
if (type.getGenericSuperclass() == null
|| !ParameterizedType.class.isInstance(type.getGenericSuperclass()))
return m.getParameterTypes();
ParameterizedType param = (ParameterizedType)type.getGenericSuperclass();
Type[] genTypes = m.getGenericParameterTypes();
Class[] types = new Class[genTypes.length];
typeSearch:
for (int i=0; i < genTypes.length; i++) {
if (TypeVariable.class.isInstance(genTypes[i])) {
Class resolved = resolveType(param, (TypeVariable)genTypes[i]);
if (resolved != null) {
types[i] = resolved;
continue;
}
}
types[i] = m.getParameterTypes()[i];
}
return types;
}
}