/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser;
import gw.lang.reflect.DefaultArrayType;
import gw.lang.reflect.gs.IGosuArrayClass;
import gw.lang.reflect.gs.IGosuClass;
import gw.lang.reflect.IType;
import gw.lang.reflect.ITypeLoader;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.java.IJavaClassInfo;
import gw.util.Pair;
import gw.util.concurrent.LockingLazyVar;
import java.lang.reflect.Array;
/**
*/
public class GosuArrayClass extends DefaultArrayType implements IGosuArrayClass
{
// lazy to break circular reference issues
private LockingLazyVar<IJavaClassInfo> _lazyConcreteClass;
public GosuArrayClass( final IType componentType, ITypeLoader typeLoader )
{
super( componentType, null, typeLoader );
_lazyConcreteClass =
new LockingLazyVar<IJavaClassInfo>()
{
@Override
protected IJavaClassInfo init()
{
Class componentClass;
if( componentType instanceof IGosuClass )
{
componentClass = ((IGosuClass)componentType).getBackingClass();
}
else
{
componentClass = ((GosuArrayClass) componentType).getConcreteClass().getBackingClass();
}
componentClass = Array.newInstance( componentClass, 0 ).getClass();
return TypeSystem.getJavaClassInfo( componentClass );
}
};
}
@Override
protected IGosuArrayClass makeArrayType()
{
return (IGosuArrayClass)TypeSystem.getOrCreateTypeReference(
new GosuArrayClass( TypeSystem.getOrCreateTypeReference( this ), getTypeLoader() ) );
}
@Override
public Object makeArrayInstance( int iLength )
{
Pair<Integer, Class> gosuClassDepthPair = getGosuClassDepthPair( getComponentType(), 2 );
Integer first = gosuClassDepthPair.getFirst();
return Array.newInstance( gosuClassDepthPair.getSecond(), getDims( first, iLength ) );
}
private int[] getDims( Integer depth, int iLength )
{
int[] ints = new int[depth];
for( int i = 0; i < depth; i++ )
{
if( i == 0 )
{
ints[i] = iLength;
}
else
{
ints[i] = 0;
}
}
return ints;
}
@Override
public Object getArrayComponent( Object array, int iIndex ) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
{
return Array.get( array, iIndex );
}
@Override
public void setArrayComponent( Object array, int iIndex, Object value ) throws IllegalArgumentException, ArrayIndexOutOfBoundsException
{
Array.set( array, iIndex, value );
}
@Override
public int getArrayLength( Object array ) throws IllegalArgumentException
{
return Array.getLength( array );
}
public boolean hasGosuClassAtRoot( IType component )
{
return getGosuClassDepthPair( component, 2 ) != null;
}
@Override
public IJavaClassInfo getConcreteClass()
{
return _lazyConcreteClass.get();
}
private Pair<Integer, Class> getGosuClassDepthPair( IType component, int depth )
{
if( component == null )
{
return null;
}
else if( component instanceof IGosuClass )
{
return new Pair<Integer, Class>( depth, ((IGosuClassInternal) component).getBackingClass() );
}
else
{
return getGosuClassDepthPair( component.getComponentType(), depth + 1 );
}
}
}