japod@49: package org.apidesign.apifest08.test; japod@49: japod@49: import junit.framework.TestCase; japod@49: import org.apidesign.apifest08.currency.Convertor; japod@49: import org.apidesign.apifest08.currency.ConvertorFactory; japod@49: import org.apidesign.apifest08.currency.CurrencyRate; japod@49: import org.apidesign.apifest08.currency.CurrencyRateFactory; japod@49: japod@49: /** There are many currencies around the world and many banks manipulate japod@49: * with more than one or two at the same time. As banks are usually the japod@49: * best paying clients, which is true even in case of your Convertor API, japod@49: * it is reasonable to listen to their requests. japod@49: *

japod@49: * The quest for today is to enhance your existing convertor API to hold japod@49: * information about many currencies and allow conversions between any of them. japod@49: * Also, as conversion rates for diferent currencies usually arise from various japod@49: * bank departments, there is another important need. There is a need to japod@49: * compose two convertors into one by merging all the information about japod@49: * currencies they know about. japod@49: */ japod@49: public class Task2Test extends TestCase { japod@49: public Task2Test(String testName) { japod@49: super(testName); japod@49: } japod@49: japod@49: @Override japod@49: protected void setUp() throws Exception { japod@49: } japod@49: japod@49: @Override japod@49: protected void tearDown() throws Exception { japod@49: } japod@49: japod@49: // As in Task1Test, keep in mind, that there are three parts japod@49: // of the whole system: japod@49: // 1. there is someone who knows the current exchange rate japod@49: // 2. there is someone who wants to do the conversion japod@49: // 3. there is the API between 1. and 2. which allows them to communicate japod@49: // japod@49: // Please backward compatibly enhance your existing API to support following japod@49: // usecases: japod@49: // japod@49: japod@49: /** Create convertor that understands two currencies, CZK and japod@49: * SKK. Make 100 SKK == 75 CZK. This is method for the group of users that japod@49: * knows the exchange rate, and needs to use the API to create objects japod@49: * with the exchange rate. Anyone shall be ready to call this method without japod@49: * any other method being called previously. The API itself shall know japod@49: * nothing about any rates, before this method is called. japod@49: */ japod@49: public static Convertor createTripleConvertor() { japod@49: // Rates: 1USD = 15CZK japod@49: // Rates: 1USD = 20SKK japod@49: // Rates: 75CZK = 100SKK japod@49: CurrencyRate usdCzk = CurrencyRateFactory.getInstance().createCurrencyRate("USD", "CZK", 1, 15); japod@49: CurrencyRate usdSkk = CurrencyRateFactory.getInstance().createCurrencyRate("USD", "SKK", 1, 20); japod@49: CurrencyRate czkSkk = CurrencyRateFactory.getInstance().createCurrencyRate("CZK", "SKK", 75, 100); japod@49: return ConvertorFactory.newInstance().createConvertor(usdCzk, usdSkk, czkSkk); japod@49: } japod@49: japod@49: /** Define convertor that understands three currencies. Use it. japod@49: */ japod@49: public void testConvertorForUSDandCZKandSKK() throws Exception { japod@49: Convertor c = createTripleConvertor(); japod@49: japod@49: // convert $5 to CZK using c: japod@49: // assertEquals("Result is 75 CZK"); japod@49: assertEquals("Result is 75 CZK", 75.0, c.convert("USD", "CZK", 5)); japod@49: japod@49: // convert $5 to SKK using c: japod@49: // assertEquals("Result is 100 SKK"); japod@49: assertEquals("Result is 100 SKK", 100.0, c.convert("USD", "SKK", 5)); japod@49: japod@49: // convert 200SKK to CZK using c: japod@49: // assertEquals("Result is 150 CZK"); japod@49: assertEquals("Result is 150 CZK", 150.0, c.convert("SKK", "CZK", 200)); japod@49: japod@49: // convert 200SKK to USD using c: japod@49: // assertEquals("Result is 10 USD"); japod@49: assertEquals("Result is 10 USD", 10.0, c.convert("SKK", "USD", 200)); japod@49: } japod@49: japod@49: /** Merge all currency rates of convertor 1 with convertor 2. japod@49: * Implement this using your API, preferably this method just delegates japod@49: * into some API method which does the actual work, without requiring japod@49: * API clients to code anything complex. japod@49: */ japod@49: public static Convertor merge(Convertor one, Convertor two) { japod@49: return ConvertorFactory.newInstance().mergeConvertors(one,two); japod@49: } japod@49: japod@49: /** Join the convertors from previous task, Task1Test and show that it japod@49: * can be used to do reasonable conversions. japod@49: */ japod@49: public void testConvertorComposition() throws Exception { japod@49: Convertor c = merge( japod@49: Task1Test.createCZKtoUSD(), japod@49: Task1Test.createSKKtoCZK() japod@49: ); japod@49: japod@49: // convert $5 to CZK using c: japod@49: // assertEquals("Result is 85 CZK"); japod@49: assertEquals("Result is 85 CZK", 85.0, c.convert("USD", "CZK", 5)); japod@49: japod@49: // convert $8 to CZK using c: japod@49: // assertEquals("Result is 136 CZK"); japod@49: assertEquals("Result is 136 CZK", 136.0, c.convert("USD", "CZK", 8)); japod@49: japod@49: // convert 1003CZK to USD using c: japod@49: // assertEquals("Result is 59 USD"); japod@49: assertEquals("Result is 59 USD", 59.0, c.convert("CZK", "USD", 1003)); japod@49: japod@49: // convert 16CZK using c: japod@49: // assertEquals("Result is 20 SKK"); japod@49: assertEquals("Result is 20 SKK", 20.0, c.convert("CZK", "SKK", 16)); japod@49: japod@49: // convert 500SKK to CZK using c: japod@49: // assertEquals("Result is 400 CZK"); japod@49: assertEquals("Result is 400 CZK", 400.0, c.convert("SKK", "CZK", 500)); japod@49: japod@49: //test exceptions japod@49: Convertor one = Task1Test.createCZKtoUSD(); japod@49: Convertor two = Task1Test.createSKKtoCZK(); japod@49: Convertor three = Task1Test.createSKKtoCZK(); japod@49: try { japod@49: ConvertorFactory.newInstance().mergeConvertors(one,two,three); japod@49: fail(); japod@49: } catch (IllegalArgumentException e) { japod@49: //ok japod@49: } japod@49: japod@49: //test exceptions japod@49: try { japod@49: ConvertorFactory.newInstance().mergeConvertors(c, two); japod@49: fail(); japod@49: } catch (IllegalArgumentException e) { japod@49: //ok japod@49: } japod@49: japod@49: //try convertors from version 1 japod@49: Convertor v1one = ConvertorFactory.newInstance().createConvertor("CZE", "CZE", 1, 2); japod@49: assertEquals("CZE->CZE 1:2 10 expects 20", 20.0, v1one.convert("CZE", "CZE", 10)); japod@49: try { japod@49: ConvertorFactory.newInstance().mergeConvertors(v1one, two); japod@49: fail(); japod@49: } catch (IllegalArgumentException e) { japod@49: //ok japod@49: } japod@49: japod@49: Convertor v1two = ConvertorFactory.newInstance().createConvertor("EUR", "", 1, 2); japod@49: assertEquals("EUR->'' 1:2 10 expects 20", 20.0, v1two.convert("EUR", "", 10)); japod@49: try { japod@49: ConvertorFactory.newInstance().mergeConvertors(v1two, two); japod@49: fail(); japod@49: } catch (IllegalArgumentException e) { japod@49: //ok japod@49: } japod@49: japod@49: Convertor v1three = ConvertorFactory.newInstance().createConvertor("EUR", "", 1, 2); japod@49: assertEquals("''->EUR 1:2 10 expects 5", 5.0, v1three.convert("", "EUR", 10)); japod@49: try { japod@49: ConvertorFactory.newInstance().mergeConvertors(v1three, two); japod@49: fail(); japod@49: } catch (IllegalArgumentException e) { japod@49: //ok japod@49: } japod@49: japod@49: } japod@49: }