adding solution12 for task 2
authorjapod@localhost
Tue, 07 Oct 2008 00:17:07 +0200
changeset 3380f2d8751f35
parent 32 2198184978d5
child 34 3a18aae85c9e
adding solution12 for task 2
task2/solution12/src/org/apidesign/apifest08/currency/Convertor.java
task2/solution12/test/org/apidesign/apifest08/test/Task2Test.java
     1.1 --- a/task2/solution12/src/org/apidesign/apifest08/currency/Convertor.java	Wed Oct 01 11:23:11 2008 +0200
     1.2 +++ b/task2/solution12/src/org/apidesign/apifest08/currency/Convertor.java	Tue Oct 07 00:17:07 2008 +0200
     1.3 @@ -1,7 +1,9 @@
     1.4  package org.apidesign.apifest08.currency;
     1.5  
     1.6 +import java.util.ArrayList;
     1.7  import java.util.Currency;
     1.8  import java.util.Hashtable;
     1.9 +import java.util.List;
    1.10  
    1.11  import org.apidesign.apifest08.currency.exceptions.ConvertorException;
    1.12  import org.apidesign.apifest08.currency.exceptions.InvalidCurrencyException;
    1.13 @@ -18,20 +20,19 @@
    1.14  
    1.15    private static Hashtable<String, ExchangeRate> exchangeRates;
    1.16  
    1.17 -  private ExchangeRate exchangeRate12;
    1.18 -  private ExchangeRate exchangeRate21;
    1.19 +  private Hashtable<String, ExchangeRate> convertorInstanceExchangeRates; 
    1.20  
    1.21 -  private Convertor(Currency currency1, Currency currency2) throws UnknownConvertorException {
    1.22 -    String key12 = currency1.getCurrencyCode() + currency2.getCurrencyCode();
    1.23 -    String key21 = currency2.getCurrencyCode() + currency1.getCurrencyCode();
    1.24 -
    1.25 -    if (!(exchangeRates.containsKey(key12) && exchangeRates.containsKey(key21))) {
    1.26 -      throw new UnknownConvertorException("Selected convertor (" + currency1.getCurrencyCode() + "->"
    1.27 -          + currency2.getCurrencyCode() + ") has not defined any rates!!!");
    1.28 -    }
    1.29 -
    1.30 -    this.exchangeRate12 = exchangeRates.get(key12);
    1.31 -    this.exchangeRate21 = exchangeRates.get(key21);
    1.32 +  private Convertor(List<Currency> currencies) throws UnknownConvertorException {
    1.33 +	  convertorInstanceExchangeRates = new Hashtable<String, ExchangeRate>();
    1.34 +	  for (Currency currency1 : currencies) {
    1.35 +		for (Currency currency2 : currencies) {
    1.36 +			if(!currency1.getCurrencyCode().equals(currency2.getCurrencyCode())) {
    1.37 +				String key = currency1.getCurrencyCode() + currency2.getCurrencyCode();
    1.38 +				ExchangeRate exchangeRate = exchangeRates.get(key);
    1.39 +				convertorInstanceExchangeRates.put(key, exchangeRate);
    1.40 +			}
    1.41 +		}
    1.42 +	}
    1.43    }
    1.44  
    1.45    /**
    1.46 @@ -67,6 +68,18 @@
    1.47      exchangeRates.put(key21, new ExchangeRate(currency2, currency1, recountedRate, unit));
    1.48  
    1.49    }
    1.50 +  
    1.51 +  /**
    1.52 +   * Merge exchange rates of actual convertor with exchange rates from selected 
    1.53 +   * convertor. If there are same currencies in both convertors, these from selected
    1.54 +   * convertor rewrites these in actual convertor.
    1.55 +   * @param convertor convertor to merge with actual one
    1.56 +   * @return convertor with merged exchange rates 
    1.57 +   */
    1.58 +  public Convertor merge(Convertor convertor) {
    1.59 +	  convertorInstanceExchangeRates.putAll(convertor.getInstanceExchangeRates());
    1.60 +	  return this;
    1.61 +  }
    1.62  
    1.63    /**
    1.64     * Creates new instance of convertor.
    1.65 @@ -78,11 +91,33 @@
    1.66     * @throws UnknownConvertorException
    1.67     *           thrown if convertor for selected currencies has not been defined
    1.68     */
    1.69 -  public static Convertor getConvertorInstance(Currency currency1, Currency currency2) throws UnknownConvertorException {
    1.70 -    if (currency1 == null || currency2 == null) {
    1.71 -      throw new ConvertorException("None of the currencies should be null!!!");
    1.72 -    }
    1.73 -    return new Convertor(currency1, currency2);
    1.74 +  public static Convertor getConvertorInstance(Currency... currencies) throws UnknownConvertorException {
    1.75 +   	List<Currency> currencyList = new ArrayList<Currency>();
    1.76 +   	
    1.77 +   	if(currencies.length < 2) {
    1.78 +   		throw new ConvertorException("To get convertor instance, you have to select at least two currencies!!!");
    1.79 +   	}
    1.80 +
    1.81 +   	for (Currency currency1 : currencies) {
    1.82 +   		for (Currency currency2 : currencies) {
    1.83 +   	   		if(currency1 == null || currency2 == null) {
    1.84 +   	   			throw new ConvertorException("None of the currencies should be null!!!");
    1.85 +   	   		}
    1.86 +   	   		
    1.87 +   			if(!currency1.getCurrencyCode().equals(currency2.getCurrencyCode())) {
    1.88 +   				String key12 = currency1.getCurrencyCode() + currency2.getCurrencyCode();
    1.89 +   				String key21 = currency2.getCurrencyCode() + currency1.getCurrencyCode();
    1.90 +   				if (!(exchangeRates.containsKey(key12) && exchangeRates.containsKey(key21))) {
    1.91 +   					throw new UnknownConvertorException("Selected convertor (" + currency1.getCurrencyCode() + "<->"
    1.92 +   		    			+ currency2.getCurrencyCode() + ") has not defined exchange rates!!!");
    1.93 +   				}
    1.94 +   			}
    1.95 +		}
    1.96 +   		
    1.97 +   		currencyList.add(currency1);
    1.98 +	}
    1.99 +    
   1.100 +    return new Convertor(currencyList);
   1.101    }
   1.102  
   1.103    /**
   1.104 @@ -125,25 +160,25 @@
   1.105     */
   1.106    private ExchangeRate getExchangeRate(Currency originalCurrency, Currency newCurrency) throws InvalidCurrencyException {
   1.107      ExchangeRate actualyUsedExchangeRate = null;
   1.108 +    
   1.109 +    String key = originalCurrency.getCurrencyCode() + newCurrency.getCurrencyCode();
   1.110  
   1.111 -    if (originalCurrency.getCurrencyCode().equals(exchangeRate12.getOriginalCurrency().getCurrencyCode())
   1.112 -        && newCurrency.getCurrencyCode().equals(exchangeRate12.getNewCurrency().getCurrencyCode())) {
   1.113 -      actualyUsedExchangeRate = exchangeRate12;
   1.114 -    } else if (originalCurrency.getCurrencyCode().equals(exchangeRate21.getOriginalCurrency().getCurrencyCode())
   1.115 -        && newCurrency.getCurrencyCode().equals(exchangeRate21.getNewCurrency().getCurrencyCode())) {
   1.116 -      actualyUsedExchangeRate = exchangeRate21;
   1.117 +    if(convertorInstanceExchangeRates.containsKey(key)) {
   1.118 +      actualyUsedExchangeRate = convertorInstanceExchangeRates.get(key);
   1.119      } else {
   1.120 -      throw new InvalidCurrencyException("This convertor " + this
   1.121 -          + " could not be used for converting selected currencies (" + originalCurrency.getCurrencyCode() + "->"
   1.122 +      throw new InvalidCurrencyException("This convertor could not be used for converting selected currencies (" + originalCurrency.getCurrencyCode() + "->"
   1.123            + newCurrency.getCurrencyCode() + ") !!!");
   1.124      }
   1.125  
   1.126      return actualyUsedExchangeRate;
   1.127    }
   1.128 -
   1.129 -  public String toString() {
   1.130 -    String currency1Code = exchangeRate12.getOriginalCurrency().getCurrencyCode();
   1.131 -    String currency2Code = exchangeRate12.getNewCurrency().getCurrencyCode();
   1.132 -    return "Converter [" + currency1Code + "->" + currency2Code + ", " + currency2Code + "->" + currency1Code + "]";
   1.133 +  
   1.134 +  /**
   1.135 +   * Returns exchange rates for actual instance of convertor.
   1.136 +   * @return exchange rates for actual instance of convertor
   1.137 +   */
   1.138 +  Hashtable<String, ExchangeRate> getInstanceExchangeRates() {
   1.139 +	  return convertorInstanceExchangeRates;
   1.140    }
   1.141 +  
   1.142  }
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/task2/solution12/test/org/apidesign/apifest08/test/Task2Test.java	Tue Oct 07 00:17:07 2008 +0200
     2.3 @@ -0,0 +1,132 @@
     2.4 +package org.apidesign.apifest08.test;
     2.5 +
     2.6 +import java.util.Currency;
     2.7 +
     2.8 +import junit.framework.TestCase;
     2.9 +
    2.10 +import org.apidesign.apifest08.currency.Convertor;
    2.11 +import org.apidesign.apifest08.currency.exceptions.UnknownConvertorException;
    2.12 +
    2.13 +/** There are many currencies around the world and many banks manipulate
    2.14 + * with more than one or two at the same time. As banks are usually the
    2.15 + * best paying clients, which is true even in case of your Convertor API,
    2.16 + * it is reasonable to listen to their requests.
    2.17 + * <p>
    2.18 + * The quest for today is to enhance your existing convertor API to hold
    2.19 + * information about many currencies and allow conversions between any of them.
    2.20 + * Also, as conversion rates for diferent currencies usually arise from various
    2.21 + * bank departments, there is another important need. There is a need to
    2.22 + * compose two convertors into one by merging all the information about
    2.23 + * currencies they know about.
    2.24 + */
    2.25 +public class Task2Test extends TestCase {
    2.26 +    public Task2Test(String testName) {
    2.27 +        super(testName);
    2.28 +    }
    2.29 +
    2.30 +    @Override
    2.31 +    protected void setUp() throws Exception {
    2.32 +    }
    2.33 +
    2.34 +    @Override
    2.35 +    protected void tearDown() throws Exception {
    2.36 +    }
    2.37 +
    2.38 +    // As in Task1Test, keep in mind, that there are three parts
    2.39 +    // of the whole system:
    2.40 +    // 1. there is someone who knows the current exchange rate
    2.41 +    // 2. there is someone who wants to do the conversion
    2.42 +    // 3. there is the API between 1. and 2. which allows them to communicate
    2.43 +    // 
    2.44 +    // Please backward compatibly enhance your existing API to support following
    2.45 +    // usecases:
    2.46 +    //
    2.47 +    
    2.48 +    /** Create convertor that understands two currencies, CZK and
    2.49 +     *  SKK. Make 100 SKK == 75 CZK. This is method for the group of users that
    2.50 +     *  knows the exchange rate, and needs to use the API to create objects
    2.51 +     *  with the exchange rate. Anyone shall be ready to call this method without
    2.52 +     *  any other method being called previously. The API itself shall know
    2.53 +     *  nothing about any rates, before this method is called.
    2.54 +     */
    2.55 +    public static Convertor createTripleConvertor() {
    2.56 +        // Rates: 1USD = 15CZK
    2.57 +        // Rates: 1USD = 20SKK
    2.58 +        // Rates: 75CZK = 100SKK
    2.59 +    	// set exchange rates
    2.60 +    	Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("CZK"), 15, 1);
    2.61 +    	Convertor.setConvertorRates(Currency.getInstance("USD"), Currency.getInstance("SKK"), 20, 1);
    2.62 +    	Convertor.setConvertorRates(Currency.getInstance("SKK"), Currency.getInstance("CZK"), 75, 100);
    2.63 +        
    2.64 +        // create new instance
    2.65 +        Convertor convertor = null;
    2.66 +        try {
    2.67 +          convertor = Convertor.getConvertorInstance(Currency.getInstance("USD"), Currency.getInstance("SKK"), Currency.getInstance("CZK"));
    2.68 +        } catch (UnknownConvertorException e) {
    2.69 +          e.printStackTrace();
    2.70 +        }
    2.71 +    	return convertor;
    2.72 +    }
    2.73 +
    2.74 +    /** Define convertor that understands three currencies. Use it.
    2.75 +     */
    2.76 +    public void testConvertorForUSDandCZKandSKK() throws Exception {
    2.77 +        Convertor c = createTripleConvertor();
    2.78 +
    2.79 +        // convert $5 to CZK using c:
    2.80 +        double result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
    2.81 +        assertEquals("Result is not 75 CZK", 75.0, result);
    2.82 +
    2.83 +        // convert $5 to SKK using c:
    2.84 +        result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("SKK"));
    2.85 +        assertEquals("Result is not 100 SKK", 100.0, result);
    2.86 +
    2.87 +        // convert 200SKK to CZK using c:
    2.88 +        result = c.convert(200d, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
    2.89 +        assertEquals("Result is not 150 CZK", 150.0, result);
    2.90 +
    2.91 +        // convert 200SKK to USK using c:
    2.92 +        result = c.convert(200d, Currency.getInstance("SKK"), Currency.getInstance("USD"));
    2.93 +        assertEquals("Result is not 10 USD", 10.0, result);
    2.94 +    }
    2.95 +
    2.96 +    /** Merge all currency rates of convertor 1 with convertor 2.
    2.97 +     * Implement this using your API, preferably this method just delegates
    2.98 +     * into some API method which does the actual work, without requiring
    2.99 +     * API clients to code anything complex.
   2.100 +     */
   2.101 +    public static Convertor merge(Convertor one, Convertor two) {
   2.102 +        return one.merge(two);
   2.103 +    }
   2.104 +
   2.105 +    /** Join the convertors from previous task, Task1Test and show that it
   2.106 +     * can be used to do reasonable conversions.
   2.107 +     */
   2.108 +    public void testConvertorComposition() throws Exception {
   2.109 +        Convertor c = merge(
   2.110 +            Task1Test.createCZKtoUSD(),
   2.111 +            Task1Test.createSKKtoCZK()
   2.112 +        );
   2.113 +
   2.114 +        // convert $5 to CZK using c:
   2.115 +        double result = c.convert(5d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
   2.116 +        assertEquals("Result is not 85 CZK", 85.0, result);
   2.117 +
   2.118 +        // convert $8 to CZK using c:
   2.119 +        result = c.convert(8d, Currency.getInstance("USD"), Currency.getInstance("CZK"));
   2.120 +        assertEquals("Result is not 136 CZK", 136.0, result);
   2.121 +
   2.122 +        // convert 1003CZK to USD using c:
   2.123 +        result = c.convert(1003d, Currency.getInstance("CZK"), Currency.getInstance("USD"));
   2.124 +        assertEquals("Result is not 59 USD", 59.0, result);
   2.125 +
   2.126 +        // convert 16CZK using c:
   2.127 +        result = c.convert(16d, Currency.getInstance("CZK"), Currency.getInstance("SKK"));
   2.128 +        assertEquals("Result is not 20 SKK", 20.0, result);
   2.129 +
   2.130 +        // convert 500SKK to CZK using c:
   2.131 +        result = c.convert(500d, Currency.getInstance("SKK"), Currency.getInstance("CZK"));
   2.132 +        assertEquals("Result is not 400 CZK", 400.0, result);
   2.133 +
   2.134 +    }
   2.135 +}