task4/solution07/test/org/apidesign/apifest08/test/Task2Test.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 11 Oct 2008 23:38:46 +0200
changeset 61 58ec6da75f6f
parent 45 task3/solution07/test/org/apidesign/apifest08/test/Task2Test.java@251d0ed461fb
permissions -rw-r--r--
Copying structure for task4
japod@36
     1
package org.apidesign.apifest08.test;
japod@36
     2
japod@36
     3
import java.util.Currency;
japod@36
     4
import junit.framework.TestCase;
japod@36
     5
import org.apidesign.apifest08.currency.ConversionRate;
japod@36
     6
import org.apidesign.apifest08.currency.Convertor;
japod@36
     7
import org.apidesign.apifest08.currency.IllegalRequestSubtypeException;
japod@36
     8
import org.apidesign.apifest08.currency.MonetaryAmount;
japod@36
     9
import org.apidesign.apifest08.currency.TableConvertor;
japod@36
    10
japod@36
    11
/** There are many currencies around the world and many banks manipulate
japod@36
    12
 * with more than one or two at the same time. As banks are usually the
japod@36
    13
 * best paying clients, which is true even in case of your Convertor API,
japod@36
    14
 * it is reasonable to listen to their requests.
japod@36
    15
 * <p>
japod@36
    16
 * The quest for today is to enhance your existing convertor API to hold
japod@36
    17
 * information about many currencies and allow conversions between any of them.
japod@36
    18
 * Also, as conversion rates for diferent currencies usually arise from various
japod@36
    19
 * bank departments, there is another important need. There is a need to
japod@36
    20
 * compose two convertors into one by merging all the information about
japod@36
    21
 * currencies they know about.
japod@36
    22
 */
japod@36
    23
public class Task2Test extends TestCase {
japod@36
    24
    public Task2Test(String testName) {
japod@36
    25
        super(testName);
japod@36
    26
    }
japod@36
    27
japod@36
    28
    @Override
japod@36
    29
    protected void setUp() throws Exception {
japod@36
    30
    }
japod@36
    31
japod@36
    32
    @Override
japod@36
    33
    protected void tearDown() throws Exception {
japod@36
    34
    }
japod@36
    35
japod@36
    36
    protected static final Currency CZK = Currency.getInstance( "CZK" );
japod@36
    37
    protected static final Currency SKK = Currency.getInstance( "SKK" );
japod@36
    38
    protected static final Currency USD = Currency.getInstance( "USD" );
japod@36
    39
japod@36
    40
    // As in Task1Test, keep in mind, that there are three parts
japod@36
    41
    // of the whole system:
japod@36
    42
    // 1. there is someone who knows the current exchange rate
japod@36
    43
    // 2. there is someone who wants to do the conversion
japod@36
    44
    // 3. there is the API between 1. and 2. which allows them to communicate
japod@36
    45
    // 
japod@36
    46
    // Please backward compatibly enhance your existing API to support following
japod@36
    47
    // usecases:
japod@36
    48
    //
japod@36
    49
    
japod@36
    50
    /** Create convertor that understands two currencies, CZK and
japod@36
    51
     *  SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
japod@36
    52
     *  knows the exchange rate, and needs to use the API to create objects
japod@36
    53
     *  with the exchange rate. Anyone shall be ready to call this method without
japod@36
    54
     *  any other method being called previously. The API itself shall know
japod@36
    55
     *  nothing about any rates, before this method is called.
japod@36
    56
     */
japod@36
    57
    public static Convertor createTripleConvertor() {
japod@36
    58
        // Rates: 1USD = 15CZK
japod@36
    59
        // Rates: 1USD = 20SKK
japod@36
    60
        // Rates: 75CZK = 100SKK
japod@36
    61
        final TableConvertor convertor = new TableConvertor();
japod@36
    62
        final MonetaryAmount amountInUSD = new MonetaryAmount( 1, USD );
japod@36
    63
        final MonetaryAmount amountInCZK = new MonetaryAmount( 15, CZK );
japod@36
    64
        final MonetaryAmount amountInSKK = new MonetaryAmount( 20, SKK );
japod@36
    65
        convertor.putIntoTable( new ConversionRate( amountInCZK, amountInUSD ) );
japod@36
    66
        convertor.putIntoTable( new ConversionRate( amountInUSD, amountInCZK ) );
japod@36
    67
        convertor.putIntoTable( new ConversionRate( amountInSKK, amountInUSD ) );
japod@36
    68
        convertor.putIntoTable( new ConversionRate( amountInUSD, amountInSKK ) );
japod@36
    69
        convertor.putIntoTable( new ConversionRate( amountInSKK, amountInCZK ) );
japod@36
    70
        convertor.putIntoTable( new ConversionRate( amountInCZK, amountInSKK ) );
japod@36
    71
        return new ContractImposingDelegatingConvertor( convertor ).test();
japod@36
    72
    }
japod@36
    73
japod@36
    74
    /** Define convertor that understands three currencies. Use it.
japod@36
    75
     */
japod@36
    76
    public void testConvertorForUSDandCZKandSKK() throws Exception {
japod@36
    77
        final Convertor c = createTripleConvertor();
japod@36
    78
japod@36
    79
        // convert $5 to CZK using c:
japod@36
    80
        final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), CZK ) );
japod@36
    81
        final MonetaryAmount a1 = r1.getNetAmount();
japod@36
    82
        // assertEquals("Result is 75 CZK");
japod@36
    83
        assertNotNull( a1 );
japod@36
    84
        assertEquals( 75.0, a1.getAmount().doubleValue() );
japod@36
    85
        assertEquals( CZK, a1.getCurrency() );
japod@36
    86
japod@36
    87
        // convert $5 to SKK using c:
japod@36
    88
        final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), SKK ) );
japod@36
    89
        final MonetaryAmount a2 = r2.getNetAmount();
japod@36
    90
        // assertEquals("Result is 100 SKK");
japod@36
    91
        assertNotNull( a2 );
japod@36
    92
        assertEquals( 100.0, a2.getAmount().doubleValue() );
japod@36
    93
        assertEquals( SKK, a2.getCurrency() );
japod@36
    94
japod@36
    95
        // convert 200SKK to CZK using c:
japod@36
    96
        final Convertor.ConversionResult r3 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 200, SKK ), CZK ) );
japod@36
    97
        final MonetaryAmount a3 = r3.getNetAmount();
japod@36
    98
        // assertEquals("Result is 150 CZK");
japod@36
    99
        assertNotNull( a3 );
japod@36
   100
        assertEquals( 150.0, a3.getAmount().doubleValue() );
japod@36
   101
        assertEquals( CZK, a3.getCurrency() );
japod@36
   102
japod@36
   103
        // convert 200SKK to USK using c:
japod@36
   104
        final Convertor.ConversionResult r4 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 200, SKK ), USD ) );
japod@36
   105
        final MonetaryAmount a4 = r4.getNetAmount();
japod@36
   106
        // assertEquals("Result is 10 USD");
japod@36
   107
        assertNotNull( a4 );
japod@36
   108
        assertEquals( 10.0, a4.getAmount().doubleValue() );
japod@36
   109
        assertEquals( USD, a4.getCurrency() );
japod@36
   110
    }
japod@36
   111
japod@36
   112
    /** Merge all currency rates of convertor 1 with convertor 2.
japod@36
   113
     * Implement this using your API, preferably this method just delegates
japod@36
   114
     * into some API method which does the actual work, without requiring
japod@36
   115
     * API clients to code anything complex.
japod@36
   116
     */
japod@36
   117
    public static Convertor merge( final Convertor one, final Convertor two ) {
japod@36
   118
        return new Convertor() {
japod@36
   119
japod@36
   120
            public ConversionResult convert( ConversionRequest req ) throws IllegalRequestSubtypeException {
japod@36
   121
                final ConversionResult res1 = one.convert( req );
japod@36
   122
                final ConversionResult res2 = two.convert( req );
japod@36
   123
                if ( res1.getNetAmount() != null ) {
japod@36
   124
                    if ( res2.getNetAmount() != null ) {
japod@36
   125
                        // TODO check if they arrive at the same thing
japod@36
   126
                        return res1;
japod@36
   127
                    } else {
japod@36
   128
                        return res1;
japod@36
   129
                    }
japod@36
   130
                } else {
japod@36
   131
                    if ( res2.getNetAmount() != null ) {
japod@36
   132
                        return res2;
japod@36
   133
                    } else {
japod@36
   134
                        // neither converts
japod@36
   135
                        return new ConversionResult( null );
japod@36
   136
                    }                    
japod@36
   137
                }
japod@36
   138
            }
japod@36
   139
            
japod@36
   140
        };
japod@36
   141
    }
japod@36
   142
japod@36
   143
    /** Join the convertors from previous task, Task1Test and show that it
japod@36
   144
     * can be used to do reasonable conversions.
japod@36
   145
     */
japod@36
   146
    public void testConvertorComposition() throws Exception {
japod@36
   147
        final Convertor c = merge(
japod@36
   148
            Task1Test.createCZKtoUSD(),
japod@36
   149
            Task1Test.createSKKtoCZK()
japod@36
   150
        );
japod@36
   151
japod@36
   152
        // convert $5 to CZK using c:
japod@36
   153
        final Convertor.ConversionResult r1 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 5, USD ), CZK ) );
japod@36
   154
        final MonetaryAmount a1 = r1.getNetAmount();
japod@36
   155
        // assertEquals("Result is 85 CZK");
japod@36
   156
        assertNotNull( a1 );
japod@36
   157
        assertEquals( 85.0, a1.getAmount().doubleValue() );
japod@36
   158
        assertEquals( CZK, a1.getCurrency() );
japod@36
   159
japod@36
   160
        // convert $8 to CZK
japod@36
   161
        final Convertor.ConversionResult r2 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 8, USD ), CZK ) );
japod@36
   162
        final MonetaryAmount a2 = r2.getNetAmount();
japod@36
   163
        // assertEquals("Result is 136 CZK");
japod@36
   164
        assertNotNull( a2 );
japod@36
   165
        assertEquals( 136.0, a2.getAmount().doubleValue() );
japod@36
   166
        assertEquals( CZK, a2.getCurrency() );
japod@36
   167
japod@36
   168
        // convert 1003CZK to USD
japod@36
   169
        final Convertor.ConversionResult r3 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 1003, CZK ), USD ) );
japod@36
   170
        final MonetaryAmount a3 = r3.getNetAmount();
japod@36
   171
        // assertEquals("Result is 59 USD");
japod@36
   172
        assertNotNull( a3 );
japod@36
   173
        assertEquals( 59.0, a3.getAmount().doubleValue() );
japod@36
   174
        assertEquals( USD, a3.getCurrency() );
japod@36
   175
japod@36
   176
        // convert 16CZK using c:
japod@36
   177
        final Convertor.ConversionResult r4 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 16, CZK ), SKK ) );
japod@36
   178
        final MonetaryAmount a4 = r4.getNetAmount();
japod@36
   179
        // assertEquals("Result is 20 SKK");
japod@36
   180
        assertNotNull( a4 );
japod@36
   181
        assertEquals( 20.0, a4.getAmount().doubleValue() );
japod@36
   182
        assertEquals( SKK, a4.getCurrency() );
japod@36
   183
japod@36
   184
        // convert 500SKK to CZK using c:
japod@36
   185
        final Convertor.ConversionResult r5 = c.convert( new Convertor.ConversionRequest( new MonetaryAmount( 500, SKK ), CZK ) );
japod@36
   186
        final MonetaryAmount a5 = r5.getNetAmount();
japod@36
   187
        // assertEquals("Result is 400 CZK");
japod@36
   188
        assertNotNull( a5 );
japod@36
   189
        assertEquals( 400.0, a5.getAmount().doubleValue() );
japod@36
   190
        assertEquals( CZK, a5.getCurrency() );
japod@36
   191
    }
japod@36
   192
}