/* * Copyright 2013. Guidewire Software, Inc. */ package gw.internal.gosu.parser.java.classinfo; import gw.lang.reflect.IAnnotationInfo; import gw.lang.reflect.IType; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.java.IJavaAnnotatedElement; import gw.lang.reflect.java.IJavaClassInfo; import gw.lang.reflect.java.IJavaClassMethod; import gw.lang.reflect.java.IJavaClassType; import gw.lang.reflect.java.asm.AsmAnnotation; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.util.HashMap; import java.util.List; import java.util.Map; public class AsmClassAnnotationInfo implements IAnnotationInfo { private AsmAnnotation _annotation; private IJavaAnnotatedElement _owner; public AsmClassAnnotationInfo( AsmAnnotation annotation, IJavaAnnotatedElement owner ) { _annotation = annotation; _owner = owner; } public String getName() { return _annotation.getType().getName(); } public IType getOwnersType() { return _owner.getEnclosingClass().getJavaType(); } public String getDisplayName() { return getName(); } public String getDescription() { return getName(); } public Annotation getInstance() { throw new RuntimeException( "Not supported for source types" ); } @Override public Object getFieldValue( String fieldName ) { return normalizeValue( fieldName, _annotation.getFieldValues().get( fieldName ) ); } private Object normalizeValue( String fieldName, Object value ) { if( value instanceof List ) { value = makeArray( fieldName, (List)value ); } else if( value instanceof AsmAnnotation ) { value = new AsmClassAnnotationInfo( (AsmAnnotation)value, _owner ); } return value; } private Object makeArray( String fieldName, List l ) { IJavaClassInfo classInfo = TypeSystem.getJavaClassInfo( _annotation.getType().getName(), ((IJavaClassType)_owner).getModule() ); try { IJavaClassMethod method = classInfo.getDeclaredMethod( fieldName ); IJavaClassInfo ci = method.getReturnClassInfo(); return makeArray( ci, l, _owner ); } catch( Exception e ) { throw new RuntimeException( e ); } } public IType getType() { return TypeSystem.getByFullName( getName() ); } public String toString() { return getName(); } private static final Map<String, Class> SUPPORTED_TYPES = new HashMap<String, Class>(); static { SUPPORTED_TYPES.put( byte.class.getName(), byte.class ); SUPPORTED_TYPES.put( boolean.class.getName(), boolean.class ); SUPPORTED_TYPES.put( char.class.getName(), char.class ); SUPPORTED_TYPES.put( short.class.getName(), short.class ); SUPPORTED_TYPES.put( int.class.getName(), int.class ); SUPPORTED_TYPES.put( long.class.getName(), long.class ); SUPPORTED_TYPES.put( float.class.getName(), float.class ); SUPPORTED_TYPES.put( double.class.getName(), double.class ); SUPPORTED_TYPES.put( void.class.getName(), void.class ); SUPPORTED_TYPES.put( String.class.getName(), String.class ); SUPPORTED_TYPES.put( AsmAnnotation.class.getName(), IAnnotationInfo.class ); } public static Object makeArray( IJavaClassInfo ci, List l, IJavaAnnotatedElement owner ) throws ClassNotFoundException { Object array; IJavaClassInfo componentType = ci.getComponentType(); if( !componentType.isArray() ) { Class compClass; if( componentType.isEnum() ) { compClass = String.class; } else { compClass = getClass( componentType ); } if( compClass == null ) { throw new IllegalStateException(); } array = Array.newInstance( compClass, l.size() ); for( int i = 0; i < l.size(); i++ ) { Object elem = l.get( i ); if( compClass == IAnnotationInfo.class ) { elem = new AsmClassAnnotationInfo( (AsmAnnotation)elem, owner ); } try { Array.set( array, i, elem ); } catch( RuntimeException e ) { throw e; } } } else { array = Array.newInstance( getClass( componentType ), l.size() ); for( int i = 0; i < l.size(); i++ ) { Object elem = makeArray( componentType, (List)l.get( i ), owner ); Array.set( array, i, elem ); } } return array; } private static Class<?> getClass( IJavaClassInfo ci ) { if( ci.isArray() ) { return Array.newInstance( getClass( ci.getComponentType() ), 0 ).getClass(); } if( ci.isAnnotation() ) { return IAnnotationInfo.class; } else if( ci.isEnum() ) { return String.class; } else { String componentName = ci.getName(); Class cls = SUPPORTED_TYPES.get( componentName ); return cls == null ? String.class : cls; } } }