/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.internal.gosu.ir.transform.statement;
import gw.internal.gosu.parser.expressions.InitializerAssignment;
import gw.internal.gosu.parser.BeanAccess;
import gw.lang.ir.IRStatement;
import gw.lang.ir.IRExpression;
import gw.internal.gosu.ir.nodes.IRProperty;
import gw.internal.gosu.ir.nodes.IRPropertyFactory;
import gw.internal.gosu.ir.transform.ExpressionTransformer;
import gw.internal.gosu.ir.transform.TopLevelTransformationContext;
import gw.lang.reflect.java.IJavaType;
import gw.lang.reflect.java.JavaTypes;
import gw.lang.reflect.IPropertyInfo;
import gw.lang.reflect.IType;
import gw.lang.reflect.ITypeInfo;
import gw.lang.reflect.IPropertyAccessor;
import gw.lang.parser.exceptions.ParseException;
import gw.lang.reflect.java.JavaTypes;
import java.util.Collection;
import java.util.Map;
import java.util.Collections;
/**
*/
public class InitializerAssignmentTransformer extends AbstractStatementTransformer<InitializerAssignment>
{
public static IRStatement compile( TopLevelTransformationContext cc, InitializerAssignment stmt, IRExpression root )
{
InitializerAssignmentTransformer gen = new InitializerAssignmentTransformer( cc, stmt, root );
return gen.compile( );
}
private IRExpression _root;
private InitializerAssignmentTransformer( TopLevelTransformationContext cc, InitializerAssignment stmt, IRExpression root )
{
super( cc, stmt );
_root = root;
}
protected IRStatement compile_impl( )
{
IPropertyInfo pi = getPropertyInfo();
IRProperty irProperty = IRPropertyFactory.createIRProperty(pi);
IRExpression value = ExpressionTransformer.compile( _stmt().getRhs(), _cc() );
if( !pi.isWritable( getGosuClass() ) )
{
IRExpression property = callMethod( irProperty.getGetterMethod(), _root, Collections.EMPTY_LIST );
if( JavaTypes.COLLECTION().isAssignableFrom( pi.getFeatureType() ) )
{
return buildMethodCall( callMethod( Collection.class, "addAll", new Class[]{Collection.class},
property,
exprList( value ) ) );
}
else if( JavaTypes.MAP().isAssignableFrom( pi.getFeatureType() ) )
{
return buildMethodCall( callMethod( Map.class, "putAll", new Class[]{Map.class},
property,
exprList( value ) ) );
}
else
{
throw new IllegalStateException( "Cannot initialize read-only property " + pi.getName() + " that's not a Collection or a Map " );
}
}
else
{
if( irProperty.isBytecodeProperty() )
{
if ( irProperty.isField() ) {
return setField( irProperty, _root, value );
} else {
return buildMethodCall( callMethod( irProperty.getSetterMethod(), _root, exprList( value ) ) );
}
}
else
{
IRExpression typeInfo = callMethod( IType.class, "getTypeInfo", new Class[0], pushType( _stmt().getOwnerType() ), exprList() );
pushConstant( _stmt().getPropertyName() );
IRExpression property = callMethod( ITypeInfo.class, "getProperty", new Class[]{CharSequence.class},
typeInfo,
exprList( pushConstant( _stmt().getPropertyName() ) ) );
IRExpression accessor = callMethod( IPropertyInfo.class, "getAccessor", new Class[0], property, exprList() );
IRExpression setterCall = callMethod( IPropertyAccessor.class, "setValue", new Class[]{Object.class, Object.class},
accessor,
exprList( _root, boxValue( value.getType(), value) ) );
return buildMethodCall( setterCall );
}
}
}
private IPropertyInfo getPropertyInfo()
{
IPropertyInfo pi;
try
{
pi = BeanAccess.getPropertyInfo( _stmt().getOwnerType(), _stmt().getPropertyName(), null, null, null );
}
catch( ParseException e )
{
throw new RuntimeException( e );
}
return pi;
}
}