solution06 task3
authorjapod@localhost
Fri, 10 Oct 2008 21:54:39 +0200
changeset 52c38391fb9b38
parent 51 221f1930cbfb
child 53 09d690bb97f6
solution06 task3
task3/solution06/src/org/apidesign/apifest08/currency/Convertor.java
task3/solution06/test/org/apidesign/apifest08/test/Task3Test.java
     1.1 --- a/task3/solution06/src/org/apidesign/apifest08/currency/Convertor.java	Fri Oct 10 21:48:49 2008 +0200
     1.2 +++ b/task3/solution06/src/org/apidesign/apifest08/currency/Convertor.java	Fri Oct 10 21:54:39 2008 +0200
     1.3 @@ -8,6 +8,9 @@
     1.4  import java.util.Currency;
     1.5  import java.util.List;
     1.6  
     1.7 +/**
     1.8 + * Currency covertor.
     1.9 + */
    1.10  public final class Convertor {
    1.11  	
    1.12  	private List<ConvertorDelegate> convertorDelegates = new ArrayList<ConvertorDelegate>();
    1.13 @@ -24,7 +27,22 @@
    1.14  		notNull(currencyFirst, "currencyFirst");
    1.15  		notNull(currencySecond, "currencySecond");		
    1.16  		notNull(rateValue, "rateValue");	
    1.17 -		convertorDelegates.add(new ConvertorDelegate(rateValue, currencyFirst, currencySecond));
    1.18 +		convertorDelegates.add(new ConvertorDelegate(new StaticRateProvider(rateValue), currencyFirst, currencySecond));
    1.19 +	}
    1.20 +	
    1.21 +	/**
    1.22 +	 * Create new instance of the converter for the given currencies and its rate. 
    1.23 +	 * A rate value is provided by {@link RateProvider}.
    1.24 +	 * 
    1.25 +	 * @param rateProvider the rate provider
    1.26 +	 * @param currencyFirst the first currency
    1.27 +	 * @param currencySecond the second currency
    1.28 +	 */
    1.29 +	public Convertor(RateProvider rateProvider, Currency currencyFirst, Currency currencySecond) {
    1.30 +		notNull(currencyFirst, "currencyFirst");
    1.31 +		notNull(currencySecond, "currencySecond");		
    1.32 +		notNull(rateProvider, "rateProvider");
    1.33 +		convertorDelegates.add(new ConvertorDelegate(rateProvider, currencyFirst, currencySecond));
    1.34  	}
    1.35  	
    1.36  	/**
    1.37 @@ -84,11 +102,12 @@
    1.38  	private static class ConvertorDelegate {
    1.39  		private final Currency first;
    1.40  		private final Currency second;
    1.41 -		private final BigDecimal rateValue; // a rate between the first currency and the second currency
    1.42 +		private final RateProvider rateProvider;
    1.43  		public static final BigDecimal one = new BigDecimal(1);
    1.44  		
    1.45 -		private ConvertorDelegate(BigDecimal rateValue, Currency currencyFirst, Currency currencySecond) {
    1.46 -			this.rateValue = rateValue;
    1.47 +		
    1.48 +		private ConvertorDelegate(RateProvider rateProvider, Currency currencyFirst, Currency currencySecond) {
    1.49 +			this.rateProvider = rateProvider;
    1.50  			this.first = currencyFirst;
    1.51  			this.second = currencySecond;
    1.52  		}
    1.53 @@ -104,8 +123,16 @@
    1.54  			BigDecimal retVal;
    1.55  			
    1.56  			if(first == fromCurrency) {
    1.57 +				BigDecimal rateValue = rateProvider.getRate();
    1.58 +				if(rateValue == null) {
    1.59 +					throw new NullPointerException("Rate cannot be null!");
    1.60 +				}
    1.61  				retVal = rateValue;
    1.62  			} else {	
    1.63 +				BigDecimal rateValue = rateProvider.getRate();
    1.64 +				if(rateValue == null) {
    1.65 +					throw new NullPointerException("Rate cannot be null!");
    1.66 +				}
    1.67  				//reverse rate	
    1.68  				retVal = one.divide(rateValue, 10 ,RoundingMode.HALF_UP);
    1.69  			}
    1.70 @@ -121,4 +148,29 @@
    1.71  			return ((fromCurrency == first || fromCurrency == second) && (toCurrency == first || toCurrency == second));
    1.72  		}
    1.73  	}
    1.74 +	
    1.75 +	/**
    1.76 +	 * A rate provider. This class represents a way how could be "static" convertor
    1.77 +	 * extended in order converts according to current rate.
    1.78 +	 */
    1.79 +	public static abstract class RateProvider { 
    1.80 +		
    1.81 +		/**
    1.82 +		 * @return a rate between the from currency and the to currency associated with
    1.83 +		 * a given convertor.
    1.84 +		 */
    1.85 +		public abstract BigDecimal getRate();
    1.86 +	}
    1.87 +	
    1.88 +	private static class StaticRateProvider extends RateProvider{
    1.89 +		private final BigDecimal rateValue;
    1.90 +		
    1.91 +		private StaticRateProvider(BigDecimal rateValue){
    1.92 +			this.rateValue = rateValue;
    1.93 +		}
    1.94 +		
    1.95 +		public BigDecimal getRate() {
    1.96 +			return this.rateValue;
    1.97 +		}
    1.98 +	}
    1.99  }
     2.1 --- a/task3/solution06/test/org/apidesign/apifest08/test/Task3Test.java	Fri Oct 10 21:48:49 2008 +0200
     2.2 +++ b/task3/solution06/test/org/apidesign/apifest08/test/Task3Test.java	Fri Oct 10 21:54:39 2008 +0200
     2.3 @@ -1,7 +1,11 @@
     2.4  package org.apidesign.apifest08.test;
     2.5  
     2.6 +import java.math.BigDecimal;
     2.7 +import java.math.RoundingMode;
     2.8 +
     2.9  import junit.framework.TestCase;
    2.10  import org.apidesign.apifest08.currency.Convertor;
    2.11 +import static org.apidesign.apifest08.test.Currencies.*;
    2.12  
    2.13  /** The exchange rates are not always the same. They are changing. Day by day,
    2.14   * hour by hour, minute by minute. For every bank it is important to always
    2.15 @@ -43,6 +47,21 @@
    2.16       * @return new instance of "online" USD and CZK convertor starting with rate 1USD = 16CZK
    2.17       */
    2.18      public static Convertor createOnlineCZKUSDConvertor() {
    2.19 +    	Convertor.RateProvider rateProvider = new Convertor.RateProvider() {
    2.20 +    		private BigDecimal seed = new BigDecimal("16.01").setScale(2);
    2.21 +    		
    2.22 +			@Override
    2.23 +			public BigDecimal getRate() {
    2.24 +				if(seed.equals(new BigDecimal("15").setScale(2))) {
    2.25 +					seed = seed.add(new BigDecimal("0.01")).setScale(2);
    2.26 +				} else {
    2.27 +					seed = seed.subtract(new BigDecimal("0.01")).setScale(2);
    2.28 +				}	
    2.29 +				return seed;
    2.30 +			}
    2.31 +    		
    2.32 +    	};
    2.33 +    	
    2.34          // initial rate: 1USD = 16CZK
    2.35          // 2nd query 1USD = 15.99CZK
    2.36          // 3rd query 1USD = 15.98CZK
    2.37 @@ -51,7 +70,7 @@
    2.38          // then 1USD = 15.02CZK
    2.39          // and so on and on up to 1USD = 16CZK
    2.40          // and then another round to 15, etc.
    2.41 -        return null;
    2.42 +        return new Convertor(rateProvider, USD, CZK);
    2.43      }
    2.44  
    2.45      public void testFewQueriesForOnlineConvertor() {
    2.46 @@ -66,18 +85,16 @@
    2.47  
    2.48      static void doFewQueriesForOnlineConvertor(Convertor c) {
    2.49          // convert $5 to CZK using c:
    2.50 -        //assertEquals("Result is 80 CZK");
    2.51 +        assertEquals("Result is 80 CZK",80 ,c.convert(new BigDecimal(5), USD, CZK).getValue().intValue());
    2.52  
    2.53          // convert $8 to CZK using c:
    2.54 -        //assertEquals("Result is 127.92 CZK");
    2.55 +        assertEquals("Result is 127.92 CZK", 127.92d , c.convert(new BigDecimal(8), USD, CZK).getValue().doubleValue());
    2.56  
    2.57          // convert $1 to CZK using c:
    2.58 -        //assertEquals("Result is 15.98 CZK");
    2.59 +        assertEquals("Result is 15.98 CZK", 15.98d,  c.convert(new BigDecimal(1), USD, CZK).getValue().doubleValue());
    2.60  
    2.61          // convert 15.97CZK to USD using c:
    2.62 -        //assertEquals("Result is 1$");
    2.63 -
    2.64 -        fail("Implement me!");
    2.65 +        assertEquals("Result is 1$", 1, c.convert(new BigDecimal("15.97").setScale(2), CZK, USD).getValue().intValue());
    2.66      }
    2.67  
    2.68      /** Join the convertors and show they behave sane.
    2.69 @@ -94,10 +111,10 @@
    2.70          );
    2.71  
    2.72          // convert 16CZK to SKK using c:
    2.73 -        // assertEquals("Result is 20 SKK");
    2.74 +        assertEquals("Result is 20 SKK", 20, c.convert(new BigDecimal(16), CZK, SKK).getValue().intValue());
    2.75  
    2.76          // convert 500SKK to CZK using c:
    2.77 -        // assertEquals("Result is 400 CZK");
    2.78 +        assertEquals("Result is 400 CZK", 400, c.convert(new BigDecimal(500), SKK, CZK).getValue().intValue());
    2.79  
    2.80          doFewQueriesForOnlineConvertor(c);
    2.81      }