/* * Copyright 2013 Guidewire Software, Inc. */ package gw.lang.reflect; import gw.lang.parser.IExpression; import gw.lang.reflect.gs.IGenericTypeVariable; import gw.lang.parser.IScriptPartId; import gw.util.Pair; import gw.util.perf.objectsize.UnmodifiableSizeTwoSet; import java.io.ObjectStreamException; import java.util.Set; public class ParameterizedFunctionType extends AbstractType implements IFunctionType { private FunctionType _genericFuncType; private IType[] _typeParams; transient private FunctionTypeInfo _typeInfo; transient private IType _retType; transient private Set<IType> _allTypesInHierarchy; transient private IType[] _paramTypes; transient private String _signature; public ParameterizedFunctionType( FunctionType genericType, IType... typeParams ) { _genericFuncType = genericType; _typeParams = typeParams; } public IType getReturnType() { if( _retType != null ) { return _retType; } IGenericMethodInfo gmi = (IGenericMethodInfo)_genericFuncType.getMethodInfo(); gmi = gmi == null ? _genericFuncType : gmi; return _retType = gmi.getParameterizedReturnType( _typeParams ); } public IType[] getParameterTypes() { if( _paramTypes != null ) { return _paramTypes; } IGenericMethodInfo gmi = (gw.lang.reflect.IGenericMethodInfo)_genericFuncType.getMethodInfo(); gmi = gmi == null ? _genericFuncType : gmi; return _paramTypes = gmi.getParameterizedParameterTypes2( _genericFuncType.getOwningParameterizedType(), _typeParams ); } public IMethodInfo getMethodInfo() { return _genericFuncType.getMethodInfo(); } @Override public IFeatureInfo getMethodOrConstructorInfo() { return _genericFuncType.getMethodOrConstructorInfo(); } public String getParamSignature() { if( _signature == null ) { String strParams = _genericFuncType.getName() + "("; for( int i = 0; i < _paramTypes.length; i++ ) { strParams += (i == 0 ? "" : ", " ) + (_paramTypes[i] == null ? "" : _paramTypes[i].getName()); } strParams += ")"; _signature = strParams; } return _signature; } @Override public String getParamSignatureForCurrentModule() { if( _signature == null ) { String strParams = _genericFuncType.getName() + "("; for( int i = 0; i < _paramTypes.length; i++ ) { strParams += (i == 0 ? "" : ", " ) + (_paramTypes[i] == null ? "" : FunctionType.getParamTypeNameFromJavaBackedType(_paramTypes[i])); } strParams += ")"; _signature = strParams; } return _signature; } public String getName() { return _genericFuncType.getName(); } public String getDisplayName() { return getName(); } public String getRelativeName() { return getName(); } public String getNamespace() { return _genericFuncType.getNamespace(); } public ITypeLoader getTypeLoader() { return _genericFuncType.getTypeLoader(); } public boolean isInterface() { return _genericFuncType.isInterface(); } public IType[] getInterfaces() { return _genericFuncType.getInterfaces(); } public boolean isEnum() { return false; } public IType getSupertype() { return _genericFuncType.getSupertype(); } public IType getEnclosingType() { return _genericFuncType.getEnclosingType(); } public IType getGenericType() { return isGenericType() ? this : _genericFuncType; } public boolean isFinal() { return true; } public boolean isParameterizedType() { return true; } public boolean isGenericType() { return false; } public IGenericTypeVariable[] getGenericTypeVariables() { return null; } public IFunctionType inferParameterizedTypeFromArgTypesAndContextType(IType[] eArgs, IType ctxType) { throw new IllegalStateException( "Tried to infer parameterization on an already parameterized type." ); } public ParameterizedFunctionType getParameterizedType( IType... paramTypes ) { throw new IllegalStateException( "Tried to parameterize an already parameterized type." ); } public IType[] getTypeParameters() { return _typeParams; } public Set<IType> getAllTypesInHierarchy() { if( _allTypesInHierarchy == null ) { _allTypesInHierarchy = new UnmodifiableSizeTwoSet<IType>(this, _genericFuncType); } return _allTypesInHierarchy; } public boolean isArray() { return false; } public boolean isPrimitive() { return false; } public IType getArrayType() { return null; } public Object makeArrayInstance( int iLength ) { throw new UnsupportedOperationException( "Can't create an array of a parameterized function type." ); } public Object getArrayComponent( Object array, int iIndex ) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { return null; } public void setArrayComponent( Object array, int iIndex, Object value ) throws IllegalArgumentException, ArrayIndexOutOfBoundsException { throw new UnsupportedOperationException(); } public int getArrayLength( Object array ) throws IllegalArgumentException { return 0; } public IType getComponentType() { return null; } public boolean isAssignableFrom( IType type ) { return type.getAllTypesInHierarchy().contains( this ); } public boolean isMutable() { return false; } public ITypeInfo getTypeInfo() { return _typeInfo == null ? _typeInfo = new FunctionTypeInfo( this ) : _typeInfo; } public void unloadTypeInfo() { _typeInfo = null; } public Object readResolve() throws ObjectStreamException { return _genericFuncType.getParameterizedType( _typeParams ); } public boolean isValid() { return true; } public int getModifiers() { return _typeInfo != null ? Modifier.getModifiersFrom( _typeInfo ) : Modifier.PUBLIC; } public boolean isAbstract() { return false; } public IScriptPartId getContext() { return _genericFuncType.getScriptPart(); } public void setContext( IScriptPartId partId ) { _genericFuncType.setScriptPart( partId ); } public boolean equals( Object o ) { if( this == o ) { return true; } if( !(o instanceof ParameterizedFunctionType) ) { return false; } final ParameterizedFunctionType functionType = (ParameterizedFunctionType)o; return getParamSignature().equals( functionType.getParamSignature() ); } public int hashCode() { return getParamSignature().hashCode(); } public String toString() { return getParamSignature().toString(); } public boolean areParamsCompatible( IFunctionType rhsType ) { IType[] lhsParams = getParameterTypes(); IType[] rhsParams = rhsType.getParameterTypes(); if( lhsParams.length != rhsParams.length ) { return false; } for( int i = 0; i < rhsParams.length; i++ ) { IType myParamType = lhsParams[i]; IType otherParamType = rhsParams[i]; if( !(otherParamType.isAssignableFrom( myParamType ) || myParamType instanceof ITypeVariableType) ) { return false; } } return true; } public IScriptPartId getScriptPart() { return getContext(); } @Override public IType newInstance( IType[] paramTypes, IType returnType ) { return new ParameterizedFunctionType( (FunctionType)_genericFuncType.newInstance( paramTypes, returnType ), _typeParams ); } public boolean isDiscarded() { return false; } public void setDiscarded( boolean bDiscarded ) { } public boolean isCompoundType() { return false; } public Set<IType> getCompoundTypeComponents() { return null; } public Pair<Long, String> getRetainedMemory() { return null; } @Override public String[] getParameterNames() { if( _genericFuncType != null ) { return _genericFuncType.getParameterNames(); } return new String[0]; } @Override public IExpression[] getDefaultValueExpressions() { if( _genericFuncType != null ) { return _genericFuncType.getDefaultValueExpressions(); } return IExpression.EMPTY_ARRAY; } @Override public boolean hasOptionalParams() { if( _genericFuncType != null ) { return _genericFuncType.hasOptionalParams(); } return false; } }