package com.codiform.moo;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import com.codiform.moo.annotation.MapProperty;
import com.codiform.moo.curry.Update;
import com.codiform.moo.domain.PortfolioValue;
import com.codiform.moo.domain.Security;
import com.codiform.moo.domain.SimplifiedPortfolioValue;
public class MapPropertyUpdateTest {
public static class Value {
private Integer id;
private String name;
@SuppressWarnings( "unused" )
private Value() {
// for translation only
}
public Value( int id, String name ) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
public static class ValueDto {
private Integer id;
private String name;
@SuppressWarnings( "unused" )
private ValueDto() {
// for translation only
}
public ValueDto( int id, String name ) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
public static class ValueDtoMap {
private Map<String, ValueDto> values;
public ValueDtoMap() {
values = new HashMap<String, ValueDto>();
}
public ValueDto get( String index ) {
return values.get( index );
}
public Map<String, ValueDto> getValues() {
return values;
}
public void put( String index, ValueDto dto ) {
values.put( index, dto );
}
}
public static class ValueMap {
@MapProperty( valueClass = Value.class, update = true )
private Map<String, Value> values;
public ValueMap() {
values = new HashMap<String, Value>();
}
public boolean containsKey( String key ) {
return values.containsKey( key );
}
public Value get( String index ) {
return values.get( index );
}
public void put( String index, Value value ) {
values.put( index, value );
}
public int size() {
return values.size();
}
}
public static class RetainValueMap {
@MapProperty( valueClass = Value.class, update = true, removeOrphans = false )
private Map<String, Value> values;
public RetainValueMap() {
values = new HashMap<String, Value>();
}
public boolean containsKey( String key ) {
return values.containsKey( key );
}
public Value get( String index ) {
return values.get( index );
}
public void put( String index, Value value ) {
values.put( index, value );
}
public int size() {
return values.size();
}
}
private void assertEqualValues( ValueDto expectedValues, Value actual ) {
assertEquals( expectedValues.getId(), actual.getId() );
assertEquals( expectedValues.getName(), actual.getName() );
}
private void assertIdentityAndValues( Value expectedIdentity, ValueDto expectedValues, Value actual ) {
assertSame( expectedIdentity, actual );
assertEqualValues( expectedValues, actual );
}
@Test
public void testUpdateMapPropertyUpdatesObjectsInMapByKey() {
ValueDto flaDto = new ValueDto( 242, "Front Line Assembly" );
ValueDto tkkDto = new ValueDto( 38, "My Life with the Thrill Kill Kult" );
ValueDtoMap dtoMap = new ValueDtoMap();
dtoMap.put( "FLA", flaDto );
dtoMap.put( "TKK", tkkDto );
Value fla = new Value( 1, "Front Line" );
Value tkk = new Value( 2, "Thrill Kill" );
ValueMap valueMap = new ValueMap();
valueMap.put( "TKK", tkk );
valueMap.put( "FLA", fla );
Update.from( dtoMap ).to( valueMap );
assertIdentityAndValues( tkk, tkkDto, valueMap.get( "TKK" ) );
assertIdentityAndValues( fla, flaDto, valueMap.get( "FLA" ) );
}
@Test
public void testUpdateMapWillInsertItemWhoseKeyIsNotPresentInDestinationMap() {
ValueDto tardisDto = new ValueDto( 1, "Time and Relative Dimension in Space" );
ValueDto ssDto = new ValueDto( 2, "Sonic Screwdriver" );
ValueDtoMap dtoMap = new ValueDtoMap();
dtoMap.put( "TARDIS", tardisDto );
dtoMap.put( "SS", ssDto );
ValueMap valueMap = new ValueMap();
Value tardis = new Value( 1, "Dr. Who's Ship" );
valueMap.put( "TARDIS", tardis );
Update.from( dtoMap ).to( valueMap );
assertEquals( 2, valueMap.size() );
assertIdentityAndValues( tardis, tardisDto, valueMap.get( "TARDIS" ) );
assertEqualValues( ssDto, valueMap.get( "SS" ) );
}
@Test
public void testUpdateMapWillNullifyItemWhoseKeyHasNullValueInSourceMap() {
ValueDto iphone4sDto = new ValueDto( 1, "HSPA+" );
ValueDto nexusDto = new ValueDto( 3, "LTE" );
ValueDtoMap dtoMap = new ValueDtoMap();
dtoMap.put( "iPhone 4S", iphone4sDto );
dtoMap.put( "Galaxy Nexus", nexusDto );
dtoMap.put( "iPhone 4", null );
Value iphone4s = new Value( 1, "4G" );
Value nexus = new Value( 3, "4G" );
ValueMap valueMap = new ValueMap();
valueMap.put( "iPhone 4S", iphone4s );
valueMap.put( "iPhone 4", new Value( 2, "3G" ) );
valueMap.put( "Galaxy Nexus", nexus );
Update.from( dtoMap ).to( valueMap );
assertEquals( 3, valueMap.size() );
assertIdentityAndValues( iphone4s, iphone4sDto, valueMap.get( "iPhone 4S" ) );
assertIdentityAndValues( nexus, nexusDto, valueMap.get( "Galaxy Nexus" ) );
assertTrue( "Value Map should have retained key, but set to null after update.", valueMap.containsKey( "iPhone 4" ) );
assertNull( valueMap.get( "iPhone 4" ) );
}
@Test
public void testUpdateMapWillRemoveItemWhoseKeyIsNotPresentInSourceMap() {
ValueDto iphone4sDto = new ValueDto( 1, "HSPA+" );
ValueDto nexusDto = new ValueDto( 3, "LTE" );
ValueDtoMap dtoMap = new ValueDtoMap();
dtoMap.put( "iPhone 4S", iphone4sDto );
dtoMap.put( "Galaxy Nexus", nexusDto );
Value iphone4s = new Value( 1, "4G" );
Value nexus = new Value( 3, "4G" );
ValueMap valueMap = new ValueMap();
valueMap.put( "iPhone 4S", iphone4s );
valueMap.put( "iPhone 4", new Value( 2, "3G" ) );
valueMap.put( "Galaxy Nexus", nexus );
Update.from( dtoMap ).to( valueMap );
assertEquals( 2, valueMap.size() );
assertIdentityAndValues( iphone4s, iphone4sDto, valueMap.get( "iPhone 4S" ) );
assertIdentityAndValues( nexus, nexusDto, valueMap.get( "Galaxy Nexus" ) );
assertFalse( valueMap.containsKey( "iPhone 4" ) );
}
@Test
public void testUpdateMapWillNotRemoveItemWhoseKeyIsNotPresentInSourceMapIfRemoveOrphansIsFalse() {
ValueDtoMap dtoMap = new ValueDtoMap();
dtoMap.put( "iPhone 4S", new ValueDto( 1, "HSPA+" ) );
dtoMap.put( "Galaxy Nexus", new ValueDto( 3, "LTE" ) );
RetainValueMap valueMap = new RetainValueMap();
valueMap.put( "iPhone 4S", new Value( 1, "4G" ) );
valueMap.put( "iPhone 4", new Value( 2, "3G" ) );
valueMap.put( "Galaxy Nexus", new Value( 3, "4G" ) );
Update.from( dtoMap ).to( valueMap );
assertEquals( 3, valueMap.size() );
}
@Test
public void testUpdateMapWithKeyTranslation() {
// Given
SimplifiedPortfolioValue spv = new SimplifiedPortfolioValue();
spv.putValue( "K", 6109d ); // 1000 shares of kellogg at 61.09
spv.putValue( "HBC", 199.9d ); // 10 shares of HBC at 19.99
assertThat( spv.size(), is( equalTo( 2 ) ) );
assertThat( spv.getValue( "K" ), is( closeTo( 6109d, 0.1d ) ) );
assertThat( spv.getValue( "HBC" ), is( closeTo( 199.9d, 0.1d ) ) );
// When
PortfolioValue pv = new PortfolioValue();
pv.putValue( new Security( "K", "NYSE" ), 6109d ); // no change
pv.putValue( new Security( "HBC", "TSE" ), 300d ); // price drop to $15/share, bought 10 more shares, for 20 total
Update.from( pv ).to( spv );
// Then
assertThat( spv.size(), is( equalTo( 2 ) ) );
assertThat( spv.getValue( "K" ), is( closeTo( 6109d, 0.1d ) ) );
assertThat( spv.getValue( "HBC" ), is( closeTo( 300d, 0.1d ) ) );
}
}