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