/*
* Copyright 2013. Guidewire Software, Inc.
*/
package gw.lang.reflect;
import gw.internal.ext.org.apache.commons.collections.map.ListOrderedMap;
import gw.lang.function.IBlock;
import gw.util.GosuEscapeUtil;
import java.util.List;
import java.util.Map;
/**
*/
public class Expando implements IExpando {
private Map<String, Object> _map = new ListOrderedMap();
@Override
public Object getFieldValue( String field ) {
return _map.get( field );
}
@Override
public void setFieldValue( String field, Object value ) {
_map.put( field, value );
}
@Override
public Object invoke( String methodName, Object... args ) {
Object f = _map.get( methodName );
if( f instanceof IBlock ) {
return ((IBlock)f).invokeWithArgs( args );
}
return IPlaceholder.UNHANDLED;
}
@Override
public void setDefaultFieldValue( String name ) {
setFieldValue( name, new Expando() );
}
@Override
public Map getMap() {
return _map;
}
public String toGosu() {
StringBuilder sb = new StringBuilder();
toGosu( true, sb, 0 );
return sb.toString();
}
public void toGosu( boolean bWithDynamic, StringBuilder sb, int indent ) {
int iKey = 0;
indent( sb, indent );
sb.append( "new" ).append( bWithDynamic ? " dynamic.Dynamic()" : "()" );
if( _map.size() > 0 ) {
sb.append( " {\n" );
for( String key : _map.keySet() ) {
indent( sb, indent + 2 );
sb.append( ":" ).append( key ).append( " = " );
Object value = _map.get( key );
if( value instanceof Expando ) {
((Expando)value).toGosu( false, sb, indent+2 );
}
else if( value instanceof List )
{
int length = ((List)value).size();
sb.append( '{' );
if( length > 0 ) {
sb.append( "\n" );
int iSize = ((List)value).size();
for( int i = 0; i < iSize; i++ ) {
Object comp = ((List)value).get( i );
if( comp instanceof Expando ) {
((Expando)comp).toGosu( false, sb, indent+4 );
}
else {
indent( sb, indent+4 );
appendGosuValue( sb, comp );
}
appendCommaNewLine( sb, i < iSize - 1 );
}
}
indent( sb, indent + 2 );
sb.append( "}" );
}
else {
appendGosuValue( sb, value );
}
appendCommaNewLine( sb, iKey++ < _map.size() - 1 );
}
}
indent( sb, indent );
sb.append( "}" );
}
private void appendCommaNewLine( StringBuilder sb, boolean bComma ) {
if( bComma ) {
sb.append( ',' );
}
sb.append( "\n" );
}
private StringBuilder appendGosuValue( StringBuilder sb, Object comp ) {
if( comp instanceof String ) {
sb.append( '"' );
sb.append( GosuEscapeUtil.escapeForGosuStringLiteral( (String)comp ) );
sb.append( '"' );
}
else if( comp instanceof Integer ||
comp instanceof Long ||
comp instanceof Double ||
comp instanceof Float ||
comp instanceof Short ||
comp instanceof Character ||
comp instanceof Byte ) {
sb.append( comp );
}
else if( comp == null ) {
sb.append( "null" );
}
else {
throw new IllegalStateException( "Unsupported expando type: " + comp.getClass() );
}
return sb;
}
public String toXml( String name ) {
StringBuilder sb = new StringBuilder();
toXml( name, sb, 0 );
return sb.toString();
}
public void toXml( String name, StringBuilder sb, int indent ) {
indent( sb, indent );
sb.append( '<' ).append( name );
if( _map.size() > 0 ) {
sb.append( ">\n" );
for( String key : _map.keySet() ) {
Object value = _map.get( key );
if( value instanceof Expando ) {
((Expando)value).toXml( key, sb, indent+2 );
}
else if( value instanceof List )
{
int length = ((List)value).size();
indent( sb, indent+2 );
sb.append( "<" ).append( key );
if( length > 0 ) {
sb.append( ">\n" );
for( Object comp : ((List)value) ) {
if( comp instanceof Expando ) {
((Expando)comp).toXml( "li", sb, indent+4 );
}
else {
indent( sb, indent+4 );
sb.append( "<li>" ).append( comp ).append( "</li>\n" );
}
}
indent( sb, indent+2 );
sb.append( "</" ).append( key ).append( ">\n" );
}
else {
sb.append( "/>\n");
}
}
else {
indent( sb, indent+2 );
sb.append( '<' ).append( key ).append( ">" );
sb.append( value );
sb.append( "</" ).append( key ).append( ">\n" );
}
}
indent( sb, indent );
sb.append( "</").append( name ).append( ">\n" );
}
else {
sb.append( "/>\n" );
}
}
private void indent( StringBuilder sb, int indent ) {
for( int i = 0; i < indent; i++ ) {
sb.append( ' ' );
}
}
@Override
public boolean equals( Object o ) {
if( this == o ) {
return true;
}
if( !(o instanceof Expando) ) {
return false;
}
Expando expando = (Expando)o;
if( !_map.equals( expando._map ) ) {
return false;
}
return true;
}
@Override
public int hashCode() {
return _map.hashCode();
}
@Override
public String toString() {
return "Expando{" +
"_map=" + _map +
'}';
}
}