task4/solution04/test/org/apidesign/apifest08/test/Task4Test.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 17 Oct 2008 17:40:14 +0200
changeset 69 420baec87dc5
parent 62 f711ecd374f3
permissions -rw-r--r--
solution 4, task4
jaroslav@60
     1
package org.apidesign.apifest08.test;
jaroslav@60
     2
jaroslav@69
     3
import java.math.BigDecimal;
jaroslav@69
     4
import java.util.Calendar;
jaroslav@60
     5
import java.util.Date;
jaroslav@69
     6
import java.util.TimeZone;
jaroslav@60
     7
import junit.framework.TestCase;
jaroslav@60
     8
import org.apidesign.apifest08.currency.Convertor;
jaroslav@69
     9
import org.apidesign.apifest08.currency.ConvertorFactory;
jaroslav@69
    10
import org.apidesign.apifest08.currency.ExchangeRate;
jaroslav@69
    11
import org.apidesign.apifest08.currency.InvalidConversionException;
jaroslav@69
    12
import org.apidesign.apifest08.currency.TimedConvertor;
jaroslav@60
    13
jaroslav@60
    14
/** The exchange rates are not always the same. They are changing. However
jaroslav@60
    15
 * as in order to predict the future, one needs to understand own past. That is
jaroslav@60
    16
 * why it is important to know the exchange rate as it was at any time during
jaroslav@60
    17
 * the past.
jaroslav@60
    18
 * <p>
jaroslav@60
    19
 * Today's quest is to enhance the convertor API to deal with dates.
jaroslav@60
    20
 * One shall be able to convert a currency at any date. Each currencies rate shall
jaroslav@60
    21
 * be associated with a range between two Date objects. In order
jaroslav@60
    22
 * to keep compatibility with old API that knew nothing about dates, the
jaroslav@60
    23
 * rates associated then are applicable "for eternity". Any use of existing
jaroslav@60
    24
 * convert methods that do not accept a Date argument, uses the current
jaroslav@60
    25
 * System.currentTimeMillis() as default date.
jaroslav@60
    26
 */
jaroslav@60
    27
public class Task4Test extends TestCase {
jaroslav@60
    28
    public Task4Test(String testName) {
jaroslav@60
    29
        super(testName);
jaroslav@60
    30
    }
jaroslav@60
    31
jaroslav@69
    32
    private Calendar gmtCalendar;
jaroslav@69
    33
    
jaroslav@60
    34
    @Override
jaroslav@60
    35
    protected void setUp() throws Exception {
jaroslav@69
    36
        gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
jaroslav@60
    37
    }
jaroslav@60
    38
jaroslav@60
    39
    @Override
jaroslav@60
    40
    protected void tearDown() throws Exception {
jaroslav@60
    41
    }
jaroslav@60
    42
jaroslav@60
    43
    // Backward compatibly enhance your existing API to support following
jaroslav@60
    44
    // usecases:
jaroslav@60
    45
    //
jaroslav@60
    46
jaroslav@60
    47
    /** Takes a convertor with any rates associated and creates new convertor
jaroslav@60
    48
     * that returns the same values as the old one for time between from to till.
jaroslav@60
    49
     * Otherwise it returns no results. This is just a helper method that
jaroslav@60
    50
     * shall call some real one in the API.
jaroslav@60
    51
     * 
jaroslav@60
    52
     * @param old existing convertor
jaroslav@60
    53
     * @param from initial date (inclusive)
jaroslav@60
    54
     * @param till final date (exclusive)
jaroslav@60
    55
     * @return new convertor
jaroslav@60
    56
     */
jaroslav@60
    57
    public static Convertor limitTo(Convertor old, Date from, Date till) {
jaroslav@69
    58
        final Convertor convertor;
jaroslav@69
    59
jaroslav@69
    60
        convertor = ConvertorFactory.getConvertor(from, till, old);
jaroslav@69
    61
        
jaroslav@69
    62
        return convertor;
jaroslav@60
    63
    }
jaroslav@60
    64
jaroslav@60
    65
jaroslav@60
    66
    public void testCompositionOfLimitedConvertors() throws Exception {
jaroslav@60
    67
jaroslav@69
    68
        gmtCalendar.set(2008, Calendar.OCTOBER, 1, 0, 0, 0);
jaroslav@69
    69
        Date d1 = gmtCalendar.getTime(); // 2008-10-01 0:00 GMT
jaroslav@69
    70
        gmtCalendar.set(2008, Calendar.OCTOBER, 2, 0, 0, 0);
jaroslav@69
    71
        Date d2 = gmtCalendar.getTime(); // 2008-10-02 0:00 GMT
jaroslav@69
    72
        gmtCalendar.set(2008, Calendar.OCTOBER, 3, 0, 0, 0);
jaroslav@69
    73
        Date d3 = gmtCalendar.getTime(); // 2008-10-03 0:00 GMT
jaroslav@60
    74
        
jaroslav@60
    75
        Convertor c = Task2Test.merge(
jaroslav@60
    76
            limitTo(Task1Test.createCZKtoUSD(), d1, d2),
jaroslav@60
    77
            limitTo(Task1Test.createSKKtoCZK(), d2, d3)
jaroslav@60
    78
        );
jaroslav@60
    79
jaroslav@69
    80
        Date date;
jaroslav@69
    81
        BigDecimal amount;
jaroslav@69
    82
jaroslav@60
    83
        // convert $5 to CZK using c:
jaroslav@60
    84
        // cannot convert as no rate is applicable to current date
jaroslav@69
    85
        try
jaroslav@69
    86
        {
jaroslav@69
    87
            c.convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("5.00"));
jaroslav@69
    88
            fail("test A");
jaroslav@69
    89
        }
jaroslav@69
    90
        catch(final InvalidConversionException ex)
jaroslav@69
    91
        {
jaroslav@69
    92
        }
jaroslav@60
    93
jaroslav@60
    94
        // convert $8 to CZK using c:
jaroslav@60
    95
        // cannot convert as no rate is applicable to current date
jaroslav@69
    96
        try
jaroslav@69
    97
        {
jaroslav@69
    98
            c.convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("8.00"));
jaroslav@69
    99
            fail("test B");
jaroslav@69
   100
        }
jaroslav@69
   101
        catch(final InvalidConversionException ex)
jaroslav@69
   102
        {
jaroslav@69
   103
        }
jaroslav@60
   104
jaroslav@60
   105
        // convert 1003CZK to USD using c:
jaroslav@60
   106
        // cannot convert as no rate is applicable to current date
jaroslav@69
   107
        try
jaroslav@69
   108
        {
jaroslav@69
   109
            c.convert(Task1Test.CZK, Task1Test.USD, new BigDecimal("1003.00"));
jaroslav@69
   110
            fail("test C");
jaroslav@69
   111
        }
jaroslav@69
   112
        catch(final InvalidConversionException ex)
jaroslav@69
   113
        {
jaroslav@69
   114
        }
jaroslav@60
   115
jaroslav@60
   116
        // convert 16CZK using c:
jaroslav@60
   117
        // cannot convert as no rate is applicable to current date
jaroslav@69
   118
        try
jaroslav@69
   119
        {
jaroslav@69
   120
            c.convert(Task1Test.CZK, Task1Test.USD, new BigDecimal("16.00"));
jaroslav@69
   121
            fail("test D");
jaroslav@69
   122
        }
jaroslav@69
   123
        catch(final InvalidConversionException ex)
jaroslav@69
   124
        {
jaroslav@69
   125
        }
jaroslav@60
   126
jaroslav@60
   127
        // convert 500SKK to CZK using c:
jaroslav@60
   128
        // cannot convert as no rate is applicable to current date
jaroslav@69
   129
        try
jaroslav@69
   130
        {
jaroslav@69
   131
            c.convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"));
jaroslav@69
   132
            fail("test C");
jaroslav@69
   133
        }
jaroslav@69
   134
        catch(final InvalidConversionException ex)
jaroslav@69
   135
        {
jaroslav@69
   136
        }
jaroslav@60
   137
jaroslav@60
   138
        // convert $5 to CZK using c at 2008-10-01 6:00 GMT:
jaroslav@60
   139
        // assertEquals("Result is 85 CZK");
jaroslav@69
   140
        gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
jaroslav@69
   141
        date = gmtCalendar.getTime();
jaroslav@69
   142
        amount = ((TimedConvertor)c).convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("5.00"), date);
jaroslav@69
   143
        assertEquals(new BigDecimal("85.00"), amount);
jaroslav@60
   144
jaroslav@60
   145
        // convert $8 to CZK using c at 2008-10-01 6:00 GMT:
jaroslav@60
   146
        // assertEquals("Result is 136 CZK");
jaroslav@69
   147
        gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
jaroslav@69
   148
        date = gmtCalendar.getTime();
jaroslav@69
   149
        amount = ((TimedConvertor)c).convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("8.00"), date);
jaroslav@69
   150
        assertEquals(new BigDecimal("136.00"), amount);
jaroslav@60
   151
jaroslav@60
   152
        // convert 1003CZK to USD using c at 2008-10-01 6:00 GMT:
jaroslav@60
   153
        // assertEquals("Result is 59 USD");
jaroslav@69
   154
        gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
jaroslav@69
   155
        date = gmtCalendar.getTime();
jaroslav@69
   156
        amount = ((TimedConvertor)c).convert(Task1Test.CZK, Task1Test.USD, new BigDecimal("1003.00"), date);
jaroslav@69
   157
        assertEquals(new BigDecimal("59.00"), amount);
jaroslav@60
   158
jaroslav@60
   159
        // convert 16CZK using c at 2008-10-02 9:00 GMT:
jaroslav@60
   160
        // assertEquals("Result is 20 SKK");
jaroslav@69
   161
        gmtCalendar.set(2008, Calendar.OCTOBER, 2, 9, 0, 0);
jaroslav@69
   162
        date = gmtCalendar.getTime();
jaroslav@69
   163
        amount = ((TimedConvertor)c).convert(Task1Test.CZK, Task1Test.SKK, new BigDecimal("16.00"), date);
jaroslav@69
   164
        assertEquals(new BigDecimal("20.00"), amount);
jaroslav@60
   165
jaroslav@60
   166
        // convert 500SKK to CZK using c at 2008-10-02 9:00 GMT:
jaroslav@60
   167
        // assertEquals("Result is 400 CZK");
jaroslav@69
   168
        gmtCalendar.set(2008, Calendar.OCTOBER, 2, 9, 0, 0);
jaroslav@69
   169
        date = gmtCalendar.getTime();
jaroslav@69
   170
        amount = ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
jaroslav@69
   171
        assertEquals(new BigDecimal("400.00"), amount);
jaroslav@60
   172
jaroslav@60
   173
        // convert 500SKK to CZK using c at 2008-10-01 6:00 GMT:
jaroslav@60
   174
        // cannot convert as no rate is applicable to current date
jaroslav@69
   175
        try
jaroslav@69
   176
        {
jaroslav@69
   177
            gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
jaroslav@69
   178
            date = gmtCalendar.getTime();
jaroslav@69
   179
            ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
jaroslav@69
   180
            fail("test D");
jaroslav@69
   181
        }
jaroslav@69
   182
        catch(final InvalidConversionException ex)
jaroslav@69
   183
        {
jaroslav@69
   184
        }
jaroslav@60
   185
    }
jaroslav@60
   186
jaroslav@60
   187
    /** Create convertor that understands two currencies, CZK and
jaroslav@60
   188
     *  SKK. Make 100 SKK == 90 CZK.
jaroslav@60
   189
     *
jaroslav@60
   190
     * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
jaroslav@60
   191
     */
jaroslav@69
   192
    public static Convertor createSKKtoCZK2()
jaroslav@69
   193
    {
jaroslav@69
   194
        final ExchangeRate rate;
jaroslav@69
   195
        final Convertor    convertor;
jaroslav@69
   196
        
jaroslav@69
   197
        rate = ExchangeRate.getExchangeRate(Task1Test.SKK,
jaroslav@69
   198
                                            Task1Test.CZK,
jaroslav@69
   199
                                            new BigDecimal("100.00"),
jaroslav@69
   200
                                            new BigDecimal("90.00"));
jaroslav@69
   201
        convertor = ConvertorFactory.getConvertor(rate);
jaroslav@69
   202
jaroslav@69
   203
        return (convertor);
jaroslav@60
   204
    }
jaroslav@60
   205
jaroslav@60
   206
    public void testDateConvetorWithTwoDifferentRates() throws Exception {
jaroslav@69
   207
        gmtCalendar.set(2008, Calendar.OCTOBER, 1, 0, 0, 0);
jaroslav@69
   208
        Date d1 = gmtCalendar.getTime(); // 2008-10-01 0:00 GMT
jaroslav@69
   209
        gmtCalendar.set(2008, Calendar.OCTOBER, 2, 0, 0, 0);
jaroslav@69
   210
        Date d2 = gmtCalendar.getTime(); // 2008-10-02 0:00 GMT
jaroslav@69
   211
        gmtCalendar.set(2008, Calendar.OCTOBER, 3, 0, 0, 0);
jaroslav@69
   212
        Date d3 = gmtCalendar.getTime(); // 2008-10-03 0:00 GMT
jaroslav@60
   213
jaroslav@60
   214
        Convertor c = Task2Test.merge(
jaroslav@60
   215
            limitTo(createSKKtoCZK2(), d1, d2),
jaroslav@60
   216
            limitTo(Task1Test.createSKKtoCZK(), d2, d3)
jaroslav@60
   217
        );
jaroslav@60
   218
jaroslav@69
   219
        Date date;
jaroslav@69
   220
        BigDecimal amount;
jaroslav@69
   221
        
jaroslav@60
   222
        // convert 500SKK to CZK using c at 2008-10-02 9:00 GMT:
jaroslav@60
   223
        // assertEquals("Result is 400 CZK");
jaroslav@69
   224
        gmtCalendar.set(2008, Calendar.OCTOBER, 2, 6, 0, 0);
jaroslav@69
   225
        date = gmtCalendar.getTime();
jaroslav@69
   226
        amount = ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
jaroslav@69
   227
        assertEquals(new BigDecimal("400.00"), amount);
jaroslav@60
   228
jaroslav@60
   229
        // convert 500SKK to CZK using c at 2008-10-01 6:00 GMT:
jaroslav@60
   230
        // assertEquals("Result is 450 CZK");
jaroslav@69
   231
        gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
jaroslav@69
   232
        date = gmtCalendar.getTime();
jaroslav@69
   233
        amount = ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
jaroslav@69
   234
        assertEquals(new BigDecimal("450.00"), amount);
jaroslav@60
   235
    }
jaroslav@60
   236
jaroslav@60
   237
}