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 }