/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser;
import gw.config.CommonServices;
import gw.internal.gosu.parser.statements.LoopStatement;
import gw.lang.reflect.IAnnotationInfo;
import gw.lang.reflect.IExceptionInfo;
import gw.lang.reflect.IFeatureInfo;
import gw.lang.reflect.IMethodCallHandler;
import gw.lang.reflect.IMethodInfo;
import gw.lang.reflect.IParameterInfo;
import gw.lang.reflect.IScriptabilityModifier;
import gw.lang.reflect.IType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.java.JavaTypes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
*/
public class ArrayExpansionMethodInfo implements IMethodInfo
{
private IMethodInfo _delegate;
private IMethodCallHandler _callHandler;
public ArrayExpansionMethodInfo( IMethodInfo delegate )
{
_delegate = delegate;
}
public IMethodCallHandler getCallHandler()
{
return _callHandler == null
? _callHandler = new ArrayExpansionCallHandler()
: _callHandler;
}
public List<IExceptionInfo> getExceptions()
{
return _delegate.getExceptions();
}
public IParameterInfo[] getParameters()
{
return _delegate.getParameters();
}
public String getReturnDescription()
{
return _delegate.getReturnDescription();
}
public IType getReturnType()
{
IType type = _delegate.getReturnType();
if( type.isArray() || type == JavaTypes.pVOID() )
{
return type;
}
return type.getArrayType();
}
public boolean isScriptable()
{
return _delegate.isScriptable();
}
public boolean isDeprecated()
{
return _delegate.isDeprecated();
}
public String getDeprecatedReason() {
return _delegate.getDeprecatedReason();
}
public boolean isVisible( IScriptabilityModifier constraint )
{
return _delegate.isVisible( constraint );
}
public boolean isHidden()
{
return _delegate.isHidden();
}
public boolean isStatic()
{
return _delegate.isStatic();
}
public boolean isPrivate()
{
return _delegate.isPrivate();
}
public boolean isInternal()
{
return _delegate.isInternal();
}
public boolean isProtected()
{
return _delegate.isProtected();
}
public boolean isPublic()
{
return _delegate.isPublic();
}
public boolean isAbstract()
{
return _delegate.isAbstract();
}
public boolean isFinal()
{
return _delegate.isFinal();
}
public List<IAnnotationInfo> getAnnotations()
{
return Collections.emptyList();
}
public List<IAnnotationInfo> getDeclaredAnnotations()
{
return Collections.emptyList();
}
@Override
public IAnnotationInfo getAnnotation( IType type )
{
return null;
}
public List<IAnnotationInfo> getAnnotationsOfType( IType type )
{
return Collections.emptyList();
}
public boolean hasAnnotation( IType type )
{
return false;
}
@Override
public boolean hasDeclaredAnnotation( IType type )
{
return false;
}
public IFeatureInfo getContainer()
{
return _delegate.getContainer();
}
public IType getOwnersType()
{
return _delegate.getOwnersType();
}
public String getName()
{
return _delegate.getName();
}
public String getDisplayName()
{
return _delegate.getDisplayName();
}
public String getDescription()
{
return _delegate.getDescription();
}
public IMethodInfo getDelegate()
{
return _delegate;
}
class ArrayExpansionCallHandler implements IMethodCallHandler
{
public Object handleCall( Object ctx, Object... args )
{
IMethodCallHandler callHandler = _delegate.getCallHandler();
if( ctx == null )
{
return null;
}
IType type = _delegate.getReturnType();
IType objArrayType = TypeSystem.getFromObject( ctx );
boolean bArray = type.isArray();
List<Object> results = new ArrayList<Object>();
for( Iterator iter = LoopStatement.makeIterator( ctx, objArrayType ); iter.hasNext(); )
{
Object elem = iter.next();
Object value = elem == null ? null : callHandler.handleCall( elem, args );
if( type != JavaTypes.pVOID() )
{
if( value != null && bArray )
{
//noinspection unchecked
results.addAll( (Collection)CommonServices.getCoercionManager().convertValue( value, JavaTypes.ARRAY_LIST() ) );
}
else
{
results.add( value );
}
}
}
return type != JavaTypes.pVOID() ? coerceValue( getReturnType(), results ) : null;
}
public Object coerceValue( IType typeToCoerceTo, List<Object> list )
{
if( list == null )
{
return null;
}
Object returnArray = typeToCoerceTo.getComponentType().makeArrayInstance( list.size() );
int i = 0;
for( Object val : list )
{
typeToCoerceTo.setArrayComponent( returnArray, i++, CommonServices.getCoercionManager().convertValue( val, typeToCoerceTo.getComponentType() ) );
}
return returnArray;
}
}
}