/* * Copyright 2013 Guidewire Software, Inc. */ package gw.internal.gosu.parser.expressions; import gw.config.CommonServices; import gw.internal.gosu.parser.BeanAccess; import gw.internal.gosu.parser.Expression; import gw.internal.gosu.parser.Statement; import gw.lang.parser.EvaluationException; import gw.lang.parser.exceptions.ParseException; import gw.lang.parser.statements.ITerminalStatement; import gw.lang.parser.expressions.IInitializerAssignment; import gw.lang.reflect.IPropertyInfo; import gw.lang.reflect.IType; import gw.lang.reflect.ITypeInfo; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.java.JavaTypes; import gw.util.GosuExceptionUtil; import java.util.Collection; import java.util.Map; final public class InitializerAssignment extends Statement implements IInitializerAssignment { private IType _ownerType; private String _propertyName; private Expression _rhs; private IPropertyInfo _pi; public InitializerAssignment( IType ownerType, String propertyName ) { _ownerType = ownerType; _propertyName = propertyName; } public IType getOwnerType() { return _ownerType; } public String getPropertyName() { return _propertyName; } public String toString() { return _propertyName; } public Expression getRhs() { return _rhs; } public void setRhs( Expression rhs ) { _rhs = rhs; } protected ITerminalStatement getLeastSignificantTerminalStatement_internal( boolean[] bAbsolute ) { bAbsolute[0] = false; return null; } public Object execute() { return null; } public void execute( Object contextValue ) { ITypeInfo typeInfo = getOwnerType().getTypeInfo(); if( typeInfo == null ) { throw new EvaluationException( "No type info found for, " + getOwnerType().getName() ); } IPropertyInfo pi = getPropertyInfo(); if( pi != null && !BeanAccess.isDescriptorHidden( pi ) ) { if( !pi.isWritable() ) { //## todo: this is dicey if( JavaTypes.COLLECTION().isAssignableFrom(pi.getFeatureType()) ) { addAll( contextValue, pi ); } else if( JavaTypes.MAP().isAssignableFrom(pi.getFeatureType()) ) { putAll( contextValue, pi ); } } else { Object value = getValue( pi ); pi.getAccessor().setValue( contextValue, value ); } } else { throw new EvaluationException( "No writable property descriptor found for property, " + getPropertyName() + ", on class, " + TypeSystem.getUnqualifiedClassName( getOwnerType() ) ); } } public IPropertyInfo getPropertyInfo() { try { return _pi != null ? _pi : BeanAccess.getPropertyInfo( getOwnerType(), getPropertyName(), null, null, null ); } catch (ParseException e) { return null; } } private void putAll( Object contextValue, IPropertyInfo pi ) { Map value = (Map)getValue( pi ); Map existingMap = (Map)pi.getAccessor().getValue( contextValue ); if( existingMap != null ) { //noinspection unchecked existingMap.putAll( value ); } else { throw new EvaluationException( getPropertyName() + ", on class, " + TypeSystem.getUnqualifiedClassName( getOwnerType() ) + "is not writable and does not have a current Map value to add values to." ); } } private void addAll( Object contextValue, IPropertyInfo pi ) { Collection value = (Collection)getValue( pi ); Collection existingCollection = null; if( pi.isReadable() ) { existingCollection = (Collection)pi.getAccessor().getValue( contextValue ); } if( existingCollection != null ) { //noinspection unchecked existingCollection.addAll( value ); } else { throw new EvaluationException( getPropertyName() + ", on class, " + TypeSystem.getUnqualifiedClassName( getOwnerType() ) + "is not writable and does not have a current Collection value to add values to." ); } } private Object getValue( IPropertyInfo pi ) { Object value; try { value = _rhs.evaluate(); } catch( Exception e ) { throw GosuExceptionUtil.forceThrow( e ); } value = CommonServices.getCoercionManager().convertValue( value, pi.getFeatureType() ); return value; } public void setPropertyInfo( IPropertyInfo propertyInfo ) { _pi = propertyInfo; } }