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