adding solution07 for task 2
authorjapod@localhost
Tue, 07 Oct 2008 00:24:22 +0200
changeset 366102a569c7fa
parent 35 8898c620fe96
child 37 d333e45f6df1
adding solution07 for task 2
task2/solution07/test/org/apidesign/apifest08/test/Task2Test.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/task2/solution07/test/org/apidesign/apifest08/test/Task2Test.java	Tue Oct 07 00:24:22 2008 +0200
     1.3 @@ -0,0 +1,192 @@
     1.4 +package org.apidesign.apifest08.test;
     1.5 +
     1.6 +import java.util.Currency;
     1.7 +import junit.framework.TestCase;
     1.8 +import org.apidesign.apifest08.currency.ConversionRate;
     1.9 +import org.apidesign.apifest08.currency.Convertor;
    1.10 +import org.apidesign.apifest08.currency.IllegalRequestSubtypeException;
    1.11 +import org.apidesign.apifest08.currency.MonetaryAmount;
    1.12 +import org.apidesign.apifest08.currency.TableConvertor;
    1.13 +
    1.14 +/** There are many currencies around the world and many banks manipulate
    1.15 + * with more than one or two at the same time. As banks are usually the
    1.16 + * best paying clients, which is true even in case of your Convertor API,
    1.17 + * it is reasonable to listen to their requests.
    1.18 + * <p>
    1.19 + * The quest for today is to enhance your existing convertor API to hold
    1.20 + * information about many currencies and allow conversions between any of them.
    1.21 + * Also, as conversion rates for diferent currencies usually arise from various
    1.22 + * bank departments, there is another important need. There is a need to
    1.23 + * compose two convertors into one by merging all the information about
    1.24 + * currencies they know about.
    1.25 + */
    1.26 +public class Task2Test extends TestCase {
    1.27 +    public Task2Test(String testName) {
    1.28 +        super(testName);
    1.29 +    }
    1.30 +
    1.31 +    @Override
    1.32 +    protected void setUp() throws Exception {
    1.33 +    }
    1.34 +
    1.35 +    @Override
    1.36 +    protected void tearDown() throws Exception {
    1.37 +    }
    1.38 +
    1.39 +    protected static final Currency CZK = Currency.getInstance( "CZK" );
    1.40 +    protected static final Currency SKK = Currency.getInstance( "SKK" );
    1.41 +    protected static final Currency USD = Currency.getInstance( "USD" );
    1.42 +
    1.43 +    // As in Task1Test, keep in mind, that there are three parts
    1.44 +    // of the whole system:
    1.45 +    // 1. there is someone who knows the current exchange rate
    1.46 +    // 2. there is someone who wants to do the conversion
    1.47 +    // 3. there is the API between 1. and 2. which allows them to communicate
    1.48 +    // 
    1.49 +    // Please backward compatibly enhance your existing API to support following
    1.50 +    // usecases:
    1.51 +    //
    1.52 +    
    1.53 +    /** Create convertor that understands two currencies, CZK and
    1.54 +     *  SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
    1.55 +     *  knows the exchange rate, and needs to use the API to create objects
    1.56 +     *  with the exchange rate. Anyone shall be ready to call this method without
    1.57 +     *  any other method being called previously. The API itself shall know
    1.58 +     *  nothing about any rates, before this method is called.
    1.59 +     */
    1.60 +    public static Convertor createTripleConvertor() {
    1.61 +        // Rates: 1USD = 15CZK
    1.62 +        // Rates: 1USD = 20SKK
    1.63 +        // Rates: 75CZK = 100SKK
    1.64 +        final TableConvertor convertor = new TableConvertor();
    1.65 +        final MonetaryAmount amountInUSD = new MonetaryAmount( 1, USD );
    1.66 +        final MonetaryAmount amountInCZK = new MonetaryAmount( 15, CZK );
    1.67 +        final MonetaryAmount amountInSKK = new MonetaryAmount( 20, SKK );
    1.68 +        convertor.putIntoTable( new ConversionRate( amountInCZK, amountInUSD ) );
    1.69 +        convertor.putIntoTable( new ConversionRate( amountInUSD, amountInCZK ) );
    1.70 +        convertor.putIntoTable( new ConversionRate( amountInSKK, amountInUSD ) );
    1.71 +        convertor.putIntoTable( new ConversionRate( amountInUSD, amountInSKK ) );
    1.72 +        convertor.putIntoTable( new ConversionRate( amountInSKK, amountInCZK ) );
    1.73 +        convertor.putIntoTable( new ConversionRate( amountInCZK, amountInSKK ) );
    1.74 +        return new ContractImposingDelegatingConvertor( convertor ).test();
    1.75 +    }
    1.76 +
    1.77 +    /** Define convertor that understands three currencies. Use it.
    1.78 +     */
    1.79 +    public void testConvertorForUSDandCZKandSKK() throws Exception {
    1.80 +        final Convertor c = createTripleConvertor();
    1.81 +
    1.82 +        // convert $5 to CZK using c:
    1.83 +        final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), CZK ) );
    1.84 +        final MonetaryAmount a1 = r1.getNetAmount();
    1.85 +        // assertEquals("Result is 75 CZK");
    1.86 +        assertNotNull( a1 );
    1.87 +        assertEquals( 75.0, a1.getAmount().doubleValue() );
    1.88 +        assertEquals( CZK, a1.getCurrency() );
    1.89 +
    1.90 +        // convert $5 to SKK using c:
    1.91 +        final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), SKK ) );
    1.92 +        final MonetaryAmount a2 = r2.getNetAmount();
    1.93 +        // assertEquals("Result is 100 SKK");
    1.94 +        assertNotNull( a2 );
    1.95 +        assertEquals( 100.0, a2.getAmount().doubleValue() );
    1.96 +        assertEquals( SKK, a2.getCurrency() );
    1.97 +
    1.98 +        // convert 200SKK to CZK using c:
    1.99 +        final Convertor.ConversionResult r3 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 200, SKK ), CZK ) );
   1.100 +        final MonetaryAmount a3 = r3.getNetAmount();
   1.101 +        // assertEquals("Result is 150 CZK");
   1.102 +        assertNotNull( a3 );
   1.103 +        assertEquals( 150.0, a3.getAmount().doubleValue() );
   1.104 +        assertEquals( CZK, a3.getCurrency() );
   1.105 +
   1.106 +        // convert 200SKK to USK using c:
   1.107 +        final Convertor.ConversionResult r4 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 200, SKK ), USD ) );
   1.108 +        final MonetaryAmount a4 = r4.getNetAmount();
   1.109 +        // assertEquals("Result is 10 USD");
   1.110 +        assertNotNull( a4 );
   1.111 +        assertEquals( 10.0, a4.getAmount().doubleValue() );
   1.112 +        assertEquals( USD, a4.getCurrency() );
   1.113 +    }
   1.114 +
   1.115 +    /** Merge all currency rates of convertor 1 with convertor 2.
   1.116 +     * Implement this using your API, preferably this method just delegates
   1.117 +     * into some API method which does the actual work, without requiring
   1.118 +     * API clients to code anything complex.
   1.119 +     */
   1.120 +    public static Convertor merge( final Convertor one, final Convertor two ) {
   1.121 +        return new Convertor() {
   1.122 +
   1.123 +            public ConversionResult convert( ConversionRequest req ) throws IllegalRequestSubtypeException {
   1.124 +                final ConversionResult res1 = one.convert( req );
   1.125 +                final ConversionResult res2 = two.convert( req );
   1.126 +                if ( res1.getNetAmount() != null ) {
   1.127 +                    if ( res2.getNetAmount() != null ) {
   1.128 +                        // TODO check if they arrive at the same thing
   1.129 +                        return res1;
   1.130 +                    } else {
   1.131 +                        return res1;
   1.132 +                    }
   1.133 +                } else {
   1.134 +                    if ( res2.getNetAmount() != null ) {
   1.135 +                        return res2;
   1.136 +                    } else {
   1.137 +                        // neither converts
   1.138 +                        return new ConversionResult( null );
   1.139 +                    }                    
   1.140 +                }
   1.141 +            }
   1.142 +            
   1.143 +        };
   1.144 +    }
   1.145 +
   1.146 +    /** Join the convertors from previous task, Task1Test and show that it
   1.147 +     * can be used to do reasonable conversions.
   1.148 +     */
   1.149 +    public void testConvertorComposition() throws Exception {
   1.150 +        final Convertor c = merge(
   1.151 +            Task1Test.createCZKtoUSD(),
   1.152 +            Task1Test.createSKKtoCZK()
   1.153 +        );
   1.154 +
   1.155 +        // convert $5 to CZK using c:
   1.156 +        final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), CZK ) );
   1.157 +        final MonetaryAmount a1 = r1.getNetAmount();
   1.158 +        // assertEquals("Result is 85 CZK");
   1.159 +        assertNotNull( a1 );
   1.160 +        assertEquals( 85.0, a1.getAmount().doubleValue() );
   1.161 +        assertEquals( CZK, a1.getCurrency() );
   1.162 +
   1.163 +        // convert $8 to CZK
   1.164 +        final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 8, USD ), CZK ) );
   1.165 +        final MonetaryAmount a2 = r2.getNetAmount();
   1.166 +        // assertEquals("Result is 136 CZK");
   1.167 +        assertNotNull( a2 );
   1.168 +        assertEquals( 136.0, a2.getAmount().doubleValue() );
   1.169 +        assertEquals( CZK, a2.getCurrency() );
   1.170 +
   1.171 +        // convert 1003CZK to USD
   1.172 +        final Convertor.ConversionResult r3 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 1003, CZK ), USD ) );
   1.173 +        final MonetaryAmount a3 = r3.getNetAmount();
   1.174 +        // assertEquals("Result is 59 USD");
   1.175 +        assertNotNull( a3 );
   1.176 +        assertEquals( 59.0, a3.getAmount().doubleValue() );
   1.177 +        assertEquals( USD, a3.getCurrency() );
   1.178 +
   1.179 +        // convert 16CZK using c:
   1.180 +        final Convertor.ConversionResult r4 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 16, CZK ), SKK ) );
   1.181 +        final MonetaryAmount a4 = r4.getNetAmount();
   1.182 +        // assertEquals("Result is 20 SKK");
   1.183 +        assertNotNull( a4 );
   1.184 +        assertEquals( 20.0, a4.getAmount().doubleValue() );
   1.185 +        assertEquals( SKK, a4.getCurrency() );
   1.186 +
   1.187 +        // convert 500SKK to CZK using c:
   1.188 +        final Convertor.ConversionResult r5 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 500, SKK ), CZK ) );
   1.189 +        final MonetaryAmount a5 = r5.getNetAmount();
   1.190 +        // assertEquals("Result is 400 CZK");
   1.191 +        assertNotNull( a5 );
   1.192 +        assertEquals( 400.0, a5.getAmount().doubleValue() );
   1.193 +        assertEquals( CZK, a5.getCurrency() );
   1.194 +    }
   1.195 +}