/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.parser.expressions;
import gw.internal.gosu.parser.Expression;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import gw.lang.parser.StandardCoercionManager;
import gw.lang.parser.expressions.ICollectionInitializerExpression;
import gw.lang.parser.IExpression;
import gw.lang.reflect.IType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.java.IJavaType;
import gw.lang.reflect.java.JavaTypes;
/**
*/
public class CollectionInitializerExpression extends Expression implements ICollectionInitializerExpression
{
private ArrayList<IExpression> _values;
public boolean isCompileTimeConstant()
{
for( IExpression expr : getValues() )
{
if( !expr.isCompileTimeConstant() )
{
return false;
}
}
return true;
}
public Object evaluate()
{
if( !isCompileTimeConstant() )
{
return super.evaluate();
}
// Convert to an array for compile-time constant e.g., {a,b,c} is legal array expr for Annotation args
Class<?> arrayClass = getArrayClass( getType() );
List<IExpression> values = getValues();
Object instance = Array.newInstance( arrayClass.getComponentType(), values.size() );
for( int i = 0; i < Array.getLength( instance ); i++ )
{
IExpression expr = values.get( i );
Array.set( instance, i, expr.evaluate() );
}
return instance;
}
public static Class<?> getArrayClass( IType type )
{
if( JavaTypes.COLLECTION().isAssignableFrom( type ) )
{
return Array.newInstance(getArrayClass(type.getTypeParameters()[0]), 0).getClass();
}
if( StandardCoercionManager.isBoxed(type) )
{
type = TypeSystem.getPrimitiveType( type );
}
else if( type.isEnum() )
{
// An enum evaluates as the name of the enum constant field (for compile-time constant evaluation)
type = JavaTypes.STRING();
}
if( !type.isPrimitive() && type != JavaTypes.STRING() )
{
throw new IllegalStateException( "A compile-time constant expression must be either primitive, String, or Enum" );
}
return ((IJavaType)type).getBackingClass();
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( "{" );
if( _values != null )
{
for( int i = 0; i < _values.size(); i++ )
{
IExpression expression = _values.get( i );
sb.append( expression.toString() );
if( i < _values.size() - 1 )
{
sb.append( ", " );
}
}
}
sb.append( "}" );
return sb.toString();
}
public void initialize( Object newObject )
{
if( _values != null )
{
Collection collection = (Collection)newObject;
for( int i = 0; i < _values.size(); i++ )
{
IExpression expression = _values.get( i );
Object val = expression.evaluate();
collection.add( val );
}
}
}
public void add( Expression expression )
{
if( _values == null )
{
_values = new ArrayList<IExpression>();
}
_values.add( expression );
}
public void addFirst( Expression expression )
{
if( _values == null )
{
_values = new ArrayList<IExpression>();
}
_values.add( 0, expression );
}
public List<IExpression> getValues()
{
return _values == null ? Collections.<IExpression>emptyList() : _values;
}
}