/*
* Copyright 2013. Guidewire Software, Inc.
*/
package gw.internal.gosu.parser;
import gw.internal.gosu.parser.java.classinfo.AsmClassAnnotationInfo;
import gw.internal.gosu.parser.java.classinfo.JavaSourceUtil;
import gw.lang.parser.TypeVarToTypeMap;
import gw.lang.reflect.FunctionType;
import gw.lang.reflect.IAnnotationInfo;
import gw.lang.reflect.IType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.gs.IGenericTypeVariable;
import gw.lang.reflect.java.IJavaClassBytecodeMethod;
import gw.lang.reflect.java.IJavaClassInfo;
import gw.lang.reflect.java.IJavaClassMethod;
import gw.lang.reflect.java.IJavaClassType;
import gw.lang.reflect.java.IJavaClassTypeVariable;
import gw.lang.reflect.java.IJavaMethodInfo;
import gw.lang.reflect.java.asm.AsmAnnotation;
import gw.lang.reflect.java.asm.AsmMethod;
import gw.lang.reflect.java.asm.AsmType;
import gw.lang.reflect.module.IModule;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
public class AsmMethodJavaClassMethod implements IJavaClassMethod, IJavaClassBytecodeMethod {
private AsmMethod _method;
private IModule _module;
public AsmMethodJavaClassMethod( AsmMethod method, IModule module ) {
_method = method;
_module = module;
}
@Override
public IType getReturnType() {
return TypeSystem.getByFullNameIfValid( _method.getReturnType().getNameWithArrayBrackets() );
}
@Override
public IJavaClassInfo getReturnClassInfo() {
return JavaSourceUtil.getClassInfo( _method.getReturnType().getNameWithArrayBrackets(), _module );
}
@Override
public String getName() {
return _method.getName();
}
@Override
public IJavaClassInfo getEnclosingClass() {
return JavaSourceUtil.getClassInfo( _method.getDeclaringClass(), _module );
}
@Override
public IJavaClassInfo[] getParameterTypes() {
List<AsmType> rawTypes = _method.getParameters();
IJavaClassInfo[] types = new IJavaClassInfo[rawTypes.size()];
for( int i = 0; i < rawTypes.size(); i++ ) {
types[i] = JavaSourceUtil.getClassInfo( rawTypes.get( i ).getNameWithArrayBrackets(), _module );
}
return types;
}
@Override
public int getModifiers() {
return _method.getModifiers();
}
@Override
public boolean isSynthetic() {
return _method.isSynthetic();
}
@Override
public boolean isBridge() {
return _method.isBridge();
}
@Override
public IJavaClassInfo[] getExceptionTypes() {
List<AsmType> rawTypes = _method.getExceptions();
IJavaClassInfo[] types = new IJavaClassInfo[rawTypes.size()];
for( int i = 0; i < rawTypes.size(); i++ ) {
types[i] = JavaSourceUtil.getClassInfo( rawTypes.get( i ).getNameWithArrayBrackets(), _module );
}
return types;
}
@Override
public Object getDefaultValue() {
return normalizeValue( _method.getAnnotationDefaultValue() );
}
private Object normalizeValue( Object value ) {
if( value instanceof List ) {
value = makeArray( (List)value );
}
return value;
}
private Object makeArray( List l ) {
try {
IJavaClassInfo ci = getReturnClassInfo();
return AsmClassAnnotationInfo.makeArray( ci, l, this );
}
catch( Exception e ) {
throw new RuntimeException( e );
}
}
@Override
public String getReturnTypeName() {
return _method.getReturnType().getNameWithArrayBrackets();
}
@Override
public boolean isAnnotationPresent( Class<? extends Annotation> annotationClass ) {
return _method.isAnnotationPresent( annotationClass );
}
@Override
public IAnnotationInfo getAnnotation( Class annotationClass ) {
AsmAnnotation annotation = _method.getAnnotation( annotationClass );
return annotation != null ? new AsmClassAnnotationInfo( annotation, this ) : null;
}
@Override
public IAnnotationInfo[] getDeclaredAnnotations() {
List<AsmAnnotation> annotations = _method.getAnnotations();
IAnnotationInfo[] declaredAnnotations = new IAnnotationInfo[annotations.size()];
for( int i = 0; i < declaredAnnotations.length; i++ ) {
declaredAnnotations[i] = new AsmClassAnnotationInfo( annotations.get( i ), this );
}
return declaredAnnotations;
}
public void setAccessible( boolean accessible ) {
throw new UnsupportedOperationException();
}
@Override
public Object invoke( Object ctx, Object[] args ) throws InvocationTargetException, IllegalAccessException {
throw new UnsupportedOperationException();
}
@Override
public IGenericTypeVariable[] getTypeVariables( IJavaMethodInfo javaMethodInfo ) {
List<AsmType> typeVars = _method.getMethodType().getTypeParameters();
IType declClass = TypeSystem.getByFullNameIfValid( _method.getDeclaringClass().getName(), _module );
TypeVarToTypeMap actualParamByVarName = TypeLord.mapTypeByVarName( declClass, declClass );
FunctionType functionType = new FunctionType( javaMethodInfo, true );
IJavaClassTypeVariable[] javaTypeVars = new IJavaClassTypeVariable[typeVars.size()];
for( int i = 0; i < typeVars.size(); i++ ) {
javaTypeVars[i] = (IJavaClassTypeVariable)AsmTypeJavaClassType.createType( typeVars.get( i ), _module );
}
return GenericTypeVariable.convertTypeVars( functionType, javaTypeVars, actualParamByVarName );
}
@Override
public IJavaClassType[] getGenericParameterTypes() {
List<AsmType> getParam = _method.getGenericParameters();
IJavaClassType[] types = new IJavaClassType[getParam.size()];
for( int i = 0; i < getParam.size(); i++ ) {
AsmType rawType = getParam.get( i );
IJavaClassType type = AsmTypeJavaClassType.createType( rawType, _module );
types[i] = type;
}
return types;
}
@Override
public IJavaClassType getGenericReturnType() {
return AsmTypeJavaClassType.createType( _method.getGenericReturnType(), _module );
}
@Override
public int hashCode() {
int result = Arrays.hashCode( getParameterTypes() );
result = 31 * result + getReturnType().hashCode();
result = 31 * result + getName().hashCode();
return result;
}
public boolean equals( Object o ) {
if( !(o instanceof IJavaClassMethod) ) {
return false;
}
IJavaClassMethod jcm = (IJavaClassMethod)o;
return getName().equals( jcm.getName() ) &&
getReturnType() == jcm.getReturnType() &&
Arrays.equals( getParameterTypes(), jcm.getParameterTypes() );
}
@Override
public int compareTo( IJavaClassMethod o ) {
return getName().compareTo( o.getName() );
}
public String toString() {
return _method.toString();
}
}