/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser.types; import gw.lang.reflect.IAnnotationInfo; import gw.lang.reflect.IConstructorInfo; import gw.lang.reflect.IHasParameterInfos; import gw.lang.reflect.IMethodInfo; import gw.lang.reflect.INonLoadableType; import gw.lang.reflect.IParameterInfo; import gw.lang.reflect.IPropertyAccessor; import gw.lang.reflect.IPropertyInfo; import gw.lang.reflect.IType; import gw.lang.reflect.ITypeInfo; import gw.lang.reflect.ITypeLoader; import gw.lang.reflect.MethodList; import gw.lang.reflect.PropertyInfoBase; import gw.lang.reflect.TypeBase; import gw.lang.reflect.TypeInfoBase; import gw.lang.reflect.java.JavaTypes; import gw.util.concurrent.LockingLazyVar; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; public class FunctionLiteralType extends TypeBase implements IType, INonLoadableType { private LockingLazyVar<ITypeInfo> _typeInfo = new LockingLazyVar<ITypeInfo>() { @Override protected ITypeInfo init() { return makeTypeInfo(); } }; private IHasParameterInfos _feature; private IType _superType; private Class _clazz; public static FunctionLiteralType resolve( Class clazz, IType superType, IType referenceType, CharSequence name, IType[] parameters ) { IHasParameterInfos feature; if( name == null ) { feature = referenceType.getTypeInfo().getConstructor( parameters ); } else { feature = referenceType.getTypeInfo().getMethod( name, parameters ); } return new FunctionLiteralType( clazz, superType, feature ); } public Class getSerializationClass() { return _clazz; } public IType getSerializationSuperType() { return _superType; } public IType getSerializationReferenceType() { return _feature.getOwnersType(); } public String getSerializationName() { if( _feature instanceof IMethodInfo ) { return _feature.getDisplayName(); } else { return null; } } public IType[] getSerializationParameters() { List<IType> paramTypes = new ArrayList<IType>(); for( IParameterInfo pi : _feature.getParameters() ) { paramTypes.add( pi.getFeatureType() ); } return paramTypes.toArray( new IType[paramTypes.size()] ); } public FunctionLiteralType( Class clazz, IType rawType, IHasParameterInfos feature ) { super( clazz ); _clazz = clazz; _feature = feature; _superType = rawType; } @Override public String getName() { return _feature.getName(); } @Override public String getRelativeName() { return _feature.getName(); } @Override public String getNamespace() { return null; } @Override public ITypeLoader getTypeLoader() { return _superType.getTypeLoader(); } @Override public IType getSupertype() { return _superType; } @Override public IType[] getInterfaces() { return _superType.getInterfaces(); } @Override public ITypeInfo getTypeInfo() { return _typeInfo.get(); } protected Set<? extends IType> loadAllTypesInHierarchy() { return getAllClassesInClassHierarchyAsIntrinsicTypes( this ); } public boolean isAssignableFrom(IType type) { return type.getAllTypesInHierarchy().contains( this ); } private ITypeInfo makeTypeInfo() { return new FunctionLiteralTypeInfo(); } private class FunctionLiteralTypeInfo extends TypeInfoBase implements ITypeInfo { private LockingLazyVar<List<? extends IPropertyInfo>> _properties = new LockingLazyVar<List<? extends IPropertyInfo>>() { @Override protected List<? extends IPropertyInfo> init() { List<IPropertyInfo> properties = new ArrayList( _superType.getTypeInfo().getProperties() ); IParameterInfo[] parameters = _feature.getParameters(); for( IParameterInfo parameter : parameters ) { properties.add( new FunctionLiteralParameterProperty( FunctionLiteralTypeInfo.this, parameter ) ); } return properties; } }; @Override public List<? extends IPropertyInfo> getProperties() { return _properties.get(); } @Override public IPropertyInfo getProperty( CharSequence propName ) { for( IPropertyInfo propertyInfo : getProperties() ) { if( propertyInfo.getName().substring( 0 ).equals( propName ) ) { return propertyInfo; } } return null; } @Override public MethodList getMethods() { return _superType.getTypeInfo().getMethods(); } @Override public List<? extends IConstructorInfo> getConstructors() { return _superType.getTypeInfo().getConstructors(); } @Override public List<IAnnotationInfo> getDeclaredAnnotations() { return Collections.emptyList(); } @Override public IType getOwnersType() { return FunctionLiteralType.this; } } private class FunctionLiteralParameterProperty extends PropertyInfoBase implements IPropertyInfo { private String _name; private IParameterInfo _parameter; public FunctionLiteralParameterProperty( ITypeInfo container, IParameterInfo parameter ) { super( container ); _name = "$" + parameter.getName(); _parameter = parameter; } @Override public boolean isReadable() { return true; } @Override public boolean isWritable( IType whosAskin ) { return false; } @Override public IPropertyAccessor getAccessor() { return new IPropertyAccessor() { @Override public Object getValue( Object ctx ) { return _parameter; } @Override public void setValue( Object ctx, Object value ) { throw new UnsupportedOperationException( "Can't set property value!" ); } }; } @Override public List<IAnnotationInfo> getDeclaredAnnotations() { return Collections.emptyList(); } @Override public String getName() { return _name; } @Override public IType getFeatureType() { return JavaTypes.getGosuType(IParameterInfo.class); } } }