solution11 task3
authorjapod@localhost
Fri, 10 Oct 2008 21:58:12 +0200
changeset 5309d690bb97f6
parent 52 c38391fb9b38
child 54 1b300c79f4ce
solution11 task3
task3/solution11/src/org/apidesign/apifest08/currency/Computer.java
task3/solution11/src/org/apidesign/apifest08/currency/Convertor.java
task3/solution11/src/org/apidesign/apifest08/currency/ExchangeRateDataSource.java
task3/solution11/src/org/apidesign/apifest08/currency/ExchangeRateProvider.java
task3/solution11/test/org/apidesign/apifest08/test/Task1Test.java
task3/solution11/test/org/apidesign/apifest08/test/Task2Test.java
task3/solution11/test/org/apidesign/apifest08/test/Task3Test.java
     1.1 --- a/task3/solution11/src/org/apidesign/apifest08/currency/Computer.java	Fri Oct 10 21:54:39 2008 +0200
     1.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/Computer.java	Fri Oct 10 21:58:12 2008 +0200
     1.3 @@ -11,12 +11,8 @@
     1.4   */
     1.5  interface Computer<AmountType> {
     1.6  
     1.7 -    ComputerResponse<AmountType> compute(ComputerRequest<AmountType> request);
     1.8 +    void compute(ComputerRequest<AmountType> request, ComputerResponse<AmountType> response);
     1.9  
    1.10 -    /**
    1.11 -     * 
    1.12 -     * @param <AmountType>
    1.13 -     */
    1.14      final class ComputerRequest<AmountType> {
    1.15  
    1.16          private AmountType input;
     2.1 --- a/task3/solution11/src/org/apidesign/apifest08/currency/Convertor.java	Fri Oct 10 21:54:39 2008 +0200
     2.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/Convertor.java	Fri Oct 10 21:58:12 2008 +0200
     2.3 @@ -20,31 +20,47 @@
     2.4   * existing convertors into new convertor's instance.
     2.5   * No time for javadoc these features, sorry.
     2.6   * 
     2.7 + * In Task3's version supports reading of current exchange rates
     2.8 + * from data sources. Data sources are merged during convertors' merging
     2.9 + * as well as static exchange rates.
    2.10 + * No time for javadoc, again.
    2.11 + * 
    2.12   * @author ked
    2.13   */
    2.14  public final class Convertor<AmountType, IdentifierType> {
    2.15  
    2.16      Computer<AmountType> computer;
    2.17 +    // each static exchange rate could be a special case of an exchange rate data source
    2.18      List<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates = new ArrayList<ExchangeRateValue<AmountType, IdentifierType>>();
    2.19 +    List<ExchangeRateDataSource<AmountType, IdentifierType>> exchangeRateDataSources = new ArrayList<ExchangeRateDataSource<AmountType, IdentifierType>>();
    2.20  
    2.21 -    Convertor(
    2.22 -            Computer<AmountType> computer,
    2.23 -            Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates) {
    2.24 +    Convertor(Computer<AmountType> computer) {
    2.25          this.computer = computer;
    2.26 -
    2.27 +    }
    2.28 +    
    2.29 +    void addExchangeRates(Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates) {
    2.30          for (ExchangeRateValue<AmountType, IdentifierType> exchangeRate : exchangeRates) {
    2.31 -            if (findExchangeRate(
    2.32 -                    this.exchangeRates,
    2.33 +            if (isExchangeRate(
    2.34                      exchangeRate.getCurrencyA().getIdentifier(),
    2.35 -                    exchangeRate.getCurrencyB().getIdentifier()) != null) {
    2.36 +                    exchangeRate.getCurrencyB().getIdentifier())) {
    2.37                  throw new IllegalArgumentException("Duplicate exchange rate!");
    2.38              }
    2.39              this.exchangeRates.add(exchangeRate);
    2.40          }
    2.41      }
    2.42 -
    2.43 -    private ExchangeRateValue<AmountType, IdentifierType> findExchangeRate(
    2.44 -            Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates,
    2.45 +    
    2.46 +    void addExchangeRateDataSources(Collection<ExchangeRateDataSource<AmountType, IdentifierType>> exchangeRateDataSources) {
    2.47 +        for (ExchangeRateDataSource<AmountType, IdentifierType> exchangeRateDataSource : exchangeRateDataSources) {
    2.48 +            if (isExchangeRate(
    2.49 +                    exchangeRateDataSource.getCurrencyAIdentifier(),
    2.50 +                    exchangeRateDataSource.getCurrencyBIdentifier())) {
    2.51 +                throw new IllegalArgumentException("Duplicate exchange rate!");
    2.52 +            }
    2.53 +            this.exchangeRateDataSources.add(exchangeRateDataSource);
    2.54 +        }
    2.55 +    }
    2.56 +    
    2.57 +    ExchangeRateValue<AmountType, IdentifierType> findExchangeRate(
    2.58              IdentifierType currencyA,
    2.59              IdentifierType currencyB) {
    2.60          for (ExchangeRateValue<AmountType, IdentifierType> exchangeRate : exchangeRates) {
    2.61 @@ -53,8 +69,32 @@
    2.62                  return exchangeRate;
    2.63              }
    2.64          }
    2.65 +        for (ExchangeRateDataSource<AmountType, IdentifierType> exchangeRateDataSource : exchangeRateDataSources) {
    2.66 +            if ((exchangeRateDataSource.getCurrencyAIdentifier().equals(currencyA) && exchangeRateDataSource.getCurrencyBIdentifier().equals(currencyB)) ||
    2.67 +                    (exchangeRateDataSource.getCurrencyAIdentifier().equals(currencyB) && exchangeRateDataSource.getCurrencyBIdentifier().equals(currencyA))) {
    2.68 +                return exchangeRateDataSource.getExchangeRate();
    2.69 +            }
    2.70 +        }
    2.71          return null;
    2.72      }
    2.73 +    
    2.74 +    boolean isExchangeRate(
    2.75 +            IdentifierType currencyA,
    2.76 +            IdentifierType currencyB) {
    2.77 +        for (ExchangeRateValue<AmountType, IdentifierType> exchangeRate : exchangeRates) {
    2.78 +            if ((exchangeRate.getCurrencyA().getIdentifier().equals(currencyA) && exchangeRate.getCurrencyB().getIdentifier().equals(currencyB)) ||
    2.79 +                    (exchangeRate.getCurrencyA().getIdentifier().equals(currencyB) && exchangeRate.getCurrencyB().getIdentifier().equals(currencyA))) {
    2.80 +                return true;
    2.81 +            }
    2.82 +        }
    2.83 +        for (ExchangeRateDataSource<AmountType, IdentifierType> exchangeRateDataSource : exchangeRateDataSources) {
    2.84 +            if ((exchangeRateDataSource.getCurrencyAIdentifier().equals(currencyA) && exchangeRateDataSource.getCurrencyBIdentifier().equals(currencyB)) ||
    2.85 +                    (exchangeRateDataSource.getCurrencyAIdentifier().equals(currencyB) && exchangeRateDataSource.getCurrencyBIdentifier().equals(currencyA))) {
    2.86 +                return true;
    2.87 +            }
    2.88 +        }
    2.89 +        return false;
    2.90 +    }
    2.91  
    2.92      /**
    2.93       * Convert an amount of the one currency to an amount of the another one currency
    2.94 @@ -68,7 +108,7 @@
    2.95              IdentifierType targetCurrency,
    2.96              CurrencyValue<AmountType, IdentifierType> currencyValue) {
    2.97          ExchangeRateValue<AmountType, IdentifierType> exchangeRate =
    2.98 -                findExchangeRate(exchangeRates, currencyValue.getIdentifier(), targetCurrency);
    2.99 +                findExchangeRate(currencyValue.getIdentifier(), targetCurrency);
   2.100          if (exchangeRate == null) {
   2.101              throw new IllegalArgumentException("Inappropriate currencies to convert!");
   2.102          }
   2.103 @@ -87,7 +127,9 @@
   2.104              targetCurrencyRef = exchangeRate.getCurrencyB().getIdentifier();
   2.105          }
   2.106  
   2.107 -        ComputerResponse<AmountType> computerResponse = computer.compute(computerRequest);
   2.108 +        ComputerResponse<AmountType> computerResponse = new ComputerResponse<AmountType>();
   2.109 +        computer.compute(computerRequest, computerResponse);
   2.110 +
   2.111          return CurrencyValue.getCurrencyValue(
   2.112                  computerResponse.getResult(),
   2.113                  targetCurrencyRef);
   2.114 @@ -100,10 +142,18 @@
   2.115              Computer<AmountType> computer,
   2.116              Collection<Convertor<AmountType, IdentifierType>> convertors) {
   2.117          Set<ExchangeRateValue<AmountType, IdentifierType>> exchangeRatesSet = new HashSet<ExchangeRateValue<AmountType, IdentifierType>>();
   2.118 +        Set<ExchangeRateDataSource<AmountType, IdentifierType>> exchangeRateDataSourcesSet = new HashSet<ExchangeRateDataSource<AmountType, IdentifierType>>();
   2.119          for (Convertor<AmountType, IdentifierType> convertor : convertors) {
   2.120              exchangeRatesSet.addAll(convertor.exchangeRates);
   2.121          }
   2.122 -        return getConvertor(computer, exchangeRatesSet);
   2.123 +        for (Convertor<AmountType, IdentifierType> convertor : convertors) {
   2.124 +            exchangeRateDataSourcesSet.addAll(convertor.exchangeRateDataSources);
   2.125 +        }
   2.126 +        
   2.127 +        Convertor<AmountType, IdentifierType> c = new Convertor<AmountType, IdentifierType>(computer);
   2.128 +        c.addExchangeRates(exchangeRatesSet);
   2.129 +        c.addExchangeRateDataSources(exchangeRateDataSourcesSet);
   2.130 +        return c;
   2.131      }
   2.132  
   2.133      static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> mergeConvertors(
   2.134 @@ -144,9 +194,18 @@
   2.135      // ---
   2.136      static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertor(
   2.137              Computer<AmountType> computer, Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates) {
   2.138 -        return new Convertor<AmountType, IdentifierType>(computer, exchangeRates);
   2.139 +        Convertor<AmountType, IdentifierType> c = new Convertor<AmountType, IdentifierType>(computer);
   2.140 +        c.addExchangeRates(exchangeRates);
   2.141 +        return c;
   2.142      }
   2.143  
   2.144 +    static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertorDataSource(
   2.145 +            Computer<AmountType> computer, Collection<ExchangeRateDataSource<AmountType, IdentifierType>> exchangeRateDataSources) {
   2.146 +        Convertor<AmountType, IdentifierType> c = new Convertor<AmountType, IdentifierType>(computer);
   2.147 +        c.addExchangeRateDataSources(exchangeRateDataSources);
   2.148 +        return c;
   2.149 +    }
   2.150 +    
   2.151      static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertor(
   2.152              Computer<AmountType> computer, ExchangeRateValue<AmountType, IdentifierType> exchangeRate) {
   2.153          Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates =
   2.154 @@ -155,6 +214,14 @@
   2.155          return getConvertor(computer, exchangeRates);
   2.156      }
   2.157      
   2.158 +    static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertorDataSource(
   2.159 +            Computer<AmountType> computer, ExchangeRateDataSource<AmountType, IdentifierType> exchangeRateDataSource) {
   2.160 +        Collection<ExchangeRateDataSource<AmountType, IdentifierType>> exchangeRateDataSources =
   2.161 +                new ArrayList<ExchangeRateDataSource<AmountType, IdentifierType>>();
   2.162 +        exchangeRateDataSources.add(exchangeRateDataSource);
   2.163 +        return getConvertorDataSource(computer, exchangeRateDataSources);
   2.164 +    }
   2.165 +    
   2.166      public static Convertor<Double, String> getConvertorDoubleString(
   2.167              Collection<ExchangeRateValue<Double, String>> exchangeRates) {
   2.168          return getConvertor(DoubleComputer, exchangeRates);
   2.169 @@ -164,7 +231,17 @@
   2.170              ExchangeRateValue<Double, String> exchangeRate) {
   2.171          return getConvertor(DoubleComputer, exchangeRate);
   2.172      }
   2.173 +    
   2.174 +    public static Convertor<Double, String> getConvertorDataSourceDoubleString(
   2.175 +            Collection<ExchangeRateDataSource<Double, String>> exchangeRateDataSources) {
   2.176 +        return getConvertorDataSource(DoubleComputer, exchangeRateDataSources);
   2.177 +    }
   2.178  
   2.179 +    public static Convertor<Double, String> getConvertorDataSourceDoubleString(
   2.180 +            ExchangeRateDataSource<Double, String> exchangeRateDataSource) {
   2.181 +        return getConvertorDataSource(DoubleComputer, exchangeRateDataSource);
   2.182 +    }
   2.183 +    
   2.184      public static Convertor<Integer, String> getConvertorIntegerString(
   2.185              Collection<ExchangeRateValue<Integer, String>> exchangeRates) {
   2.186          return getConvertor(IntegerComputer, exchangeRates);
   2.187 @@ -174,6 +251,16 @@
   2.188              ExchangeRateValue<Integer, String> exchangeRate) {
   2.189          return getConvertor(IntegerComputer, exchangeRate);
   2.190      }
   2.191 +    
   2.192 +    public static Convertor<Integer, String> getConvertorDataSourceIntegerString(
   2.193 +            Collection<ExchangeRateDataSource<Integer, String>> exchangeRateDataSources) {
   2.194 +        return getConvertorDataSource(IntegerComputer, exchangeRateDataSources);
   2.195 +    }
   2.196 +
   2.197 +    public static Convertor<Integer, String> getConvertorDataSourceIntegerString(
   2.198 +            ExchangeRateDataSource<Integer, String> exchangeRateDataSource) {
   2.199 +        return getConvertorDataSource(IntegerComputer, exchangeRateDataSource);
   2.200 +    }
   2.201  
   2.202      // ---
   2.203      // BACKWARD COMPATIBILITY - CREATION
   2.204 @@ -211,18 +298,14 @@
   2.205      // ---
   2.206      static final Computer<Double> DoubleComputer = new Computer<Double>() {
   2.207  
   2.208 -        public ComputerResponse<Double> compute(ComputerRequest<Double> request) {
   2.209 -            ComputerResponse<Double> response = new ComputerResponse<Double>();
   2.210 +        public void compute(ComputerRequest<Double> request, ComputerResponse<Double> response) {
   2.211              response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
   2.212 -            return response;
   2.213          }
   2.214      };
   2.215      static final Computer<Integer> IntegerComputer = new Computer<Integer>() {
   2.216  
   2.217 -        public ComputerResponse<Integer> compute(ComputerRequest<Integer> request) {
   2.218 -            ComputerResponse<Integer> response = new ComputerResponse<Integer>();
   2.219 +        public void compute(ComputerRequest<Integer> request, ComputerResponse<Integer> response) {
   2.220              response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
   2.221 -            return response;
   2.222          }
   2.223      };
   2.224  }
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/ExchangeRateDataSource.java	Fri Oct 10 21:58:12 2008 +0200
     3.3 @@ -0,0 +1,103 @@
     3.4 +package org.apidesign.apifest08.currency;
     3.5 +
     3.6 +import org.apidesign.apifest08.currency.ExchangeRateProvider.ExchangeRateRequest;
     3.7 +import org.apidesign.apifest08.currency.ExchangeRateProvider.ExchangeRateResponse;
     3.8 +
     3.9 +/**
    3.10 + * Exchange rate data source.
    3.11 + * 
    3.12 + * @author ked
    3.13 + */
    3.14 +public final class ExchangeRateDataSource<AmountType, IdentifierType> {
    3.15 +
    3.16 +  private final IdentifierType currencyAIdentifier;
    3.17 +
    3.18 +  private final IdentifierType currencyBIdentifier;
    3.19 +
    3.20 +  private final ExchangeRateProvider<AmountType, IdentifierType> exchangeRateProvider;
    3.21 +
    3.22 +  private ExchangeRateDataSource(
    3.23 +      IdentifierType currencyAIdentifier,
    3.24 +      IdentifierType currencyBIdentifier,
    3.25 +      ExchangeRateProvider<AmountType, IdentifierType> exchangeRateProvider) {
    3.26 +        if (currencyAIdentifier == null ||
    3.27 +            currencyBIdentifier == null ||
    3.28 +            currencyAIdentifier.equals(currencyBIdentifier)) {
    3.29 +                throw new IllegalArgumentException("Inappropriate exchange rates' identifiers!");
    3.30 +        }
    3.31 +  this.currencyAIdentifier = currencyAIdentifier;
    3.32 +    this.currencyBIdentifier = currencyBIdentifier;
    3.33 +    this.exchangeRateProvider = exchangeRateProvider;
    3.34 +  }
    3.35 +
    3.36 +  public IdentifierType getCurrencyAIdentifier() {
    3.37 +    return currencyAIdentifier;
    3.38 +  }
    3.39 +
    3.40 +  public IdentifierType getCurrencyBIdentifier() {
    3.41 +    return currencyBIdentifier;
    3.42 +  }
    3.43 +
    3.44 +  public ExchangeRateValue<AmountType, IdentifierType> getExchangeRate() {
    3.45 +    ExchangeRateRequest<AmountType, IdentifierType> request =
    3.46 +        new ExchangeRateRequest<AmountType, IdentifierType>();
    3.47 +    ExchangeRateResponse<AmountType, IdentifierType> response =
    3.48 +        new ExchangeRateResponse<AmountType, IdentifierType>();
    3.49 +
    3.50 +    request.setCurrencyAIdentifier(currencyAIdentifier);
    3.51 +    request.setCurrencyBIdentifier(currencyBIdentifier);
    3.52 +
    3.53 +    exchangeRateProvider.getExchangeRate(request, response);
    3.54 +
    3.55 +    if (response.getExchangeRate().getCurrencyA().getIdentifier().equals(currencyAIdentifier) &&
    3.56 +        response.getExchangeRate().getCurrencyB().getIdentifier().equals(currencyBIdentifier)) {
    3.57 +      return response.getExchangeRate();
    3.58 +    } else {
    3.59 +      throw new IllegalStateException("Data source's provider returned inappropriate exchange rate!");
    3.60 +    }
    3.61 +  }
    3.62 +
    3.63 +  public static <AmountType, IdentifierType> ExchangeRateDataSource<AmountType, IdentifierType> getExchangeRateDataSource(
    3.64 +      IdentifierType currencyAIdentifier,
    3.65 +      IdentifierType currencyBIdentifier,
    3.66 +      ExchangeRateProvider<AmountType, IdentifierType> exchangeRateProvider) {
    3.67 +    return new ExchangeRateDataSource<AmountType, IdentifierType>(
    3.68 +        currencyAIdentifier,
    3.69 +        currencyBIdentifier,
    3.70 +        exchangeRateProvider);
    3.71 +  }
    3.72 +
    3.73 +  @Override
    3.74 +  public boolean equals(Object obj) {
    3.75 +    if (obj == null) {
    3.76 +      return false;
    3.77 +    }
    3.78 +    if (getClass() != obj.getClass()) {
    3.79 +      return false;
    3.80 +    }
    3.81 +    final ExchangeRateDataSource other =
    3.82 +        (ExchangeRateDataSource) obj;
    3.83 +    if (this.currencyAIdentifier != other.currencyAIdentifier &&
    3.84 +        (this.currencyAIdentifier == null || !this.currencyAIdentifier.equals(other.currencyAIdentifier))) {
    3.85 +      return false;
    3.86 +    }
    3.87 +    if (this.currencyBIdentifier != other.currencyBIdentifier &&
    3.88 +        (this.currencyBIdentifier == null || !this.currencyBIdentifier.equals(other.currencyBIdentifier))) {
    3.89 +      return false;
    3.90 +    }
    3.91 +    if (this.exchangeRateProvider != other.exchangeRateProvider &&
    3.92 +        (this.exchangeRateProvider == null || !this.exchangeRateProvider.equals(other.exchangeRateProvider))) {
    3.93 +      return false;
    3.94 +    }
    3.95 +    return true;
    3.96 +  }
    3.97 +
    3.98 +  @Override
    3.99 +  public int hashCode() {
   3.100 +    int hash = 7;
   3.101 +    hash = 83 * hash + (this.currencyAIdentifier != null ? this.currencyAIdentifier.hashCode() : 0);
   3.102 +    hash = 83 * hash + (this.currencyBIdentifier != null ? this.currencyBIdentifier.hashCode() : 0);
   3.103 +    hash = 83 * hash + (this.exchangeRateProvider != null ? this.exchangeRateProvider.hashCode() : 0);
   3.104 +    return hash;
   3.105 +  }
   3.106 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/task3/solution11/src/org/apidesign/apifest08/currency/ExchangeRateProvider.java	Fri Oct 10 21:58:12 2008 +0200
     4.3 @@ -0,0 +1,55 @@
     4.4 +package org.apidesign.apifest08.currency;
     4.5 +
     4.6 +/**
     4.7 + * Exchange rate provider.
     4.8 + * 
     4.9 + * @author ked
    4.10 + * @see http://wiki.apidesign.org/wiki/APIDesignPatterns:ResponseReply
    4.11 + */
    4.12 +public interface ExchangeRateProvider<AmountType, IdentifierType> {
    4.13 +
    4.14 +    public void getExchangeRate(
    4.15 +            ExchangeRateRequest<AmountType, IdentifierType> request,
    4.16 +            ExchangeRateResponse<AmountType, IdentifierType> response);
    4.17 +
    4.18 +    public final class ExchangeRateRequest<AmountType, IdentifierType> {
    4.19 +
    4.20 +        private IdentifierType currencyAIdentifier;
    4.21 +        private IdentifierType currencyBIdentifier;
    4.22 +
    4.23 +        ExchangeRateRequest() {
    4.24 +        }
    4.25 +
    4.26 +        public IdentifierType getCurrencyAIdentifier() {
    4.27 +            return currencyAIdentifier;
    4.28 +        }
    4.29 +
    4.30 +        void setCurrencyAIdentifier(IdentifierType currencyAIdentifier) {
    4.31 +            this.currencyAIdentifier = currencyAIdentifier;
    4.32 +        }
    4.33 +
    4.34 +        public IdentifierType getCurrencyBIdentifier() {
    4.35 +            return currencyBIdentifier;
    4.36 +        }
    4.37 +
    4.38 +        void setCurrencyBIdentifier(IdentifierType currencyBIdentifier) {
    4.39 +            this.currencyBIdentifier = currencyBIdentifier;
    4.40 +        }
    4.41 +    }
    4.42 +
    4.43 +    public final class ExchangeRateResponse<AmountType, IdentifierType> {
    4.44 +
    4.45 +        private ExchangeRateValue<AmountType, IdentifierType> exchangeRate;
    4.46 +
    4.47 +        ExchangeRateResponse() {
    4.48 +        }
    4.49 +
    4.50 +        ExchangeRateValue<AmountType, IdentifierType> getExchangeRate() {
    4.51 +            return exchangeRate;
    4.52 +        }
    4.53 +
    4.54 +        public void setExchangeRate(ExchangeRateValue<AmountType, IdentifierType> exchangeRate) {
    4.55 +            this.exchangeRate = exchangeRate;
    4.56 +        }
    4.57 +    }
    4.58 +}
     5.1 --- a/task3/solution11/test/org/apidesign/apifest08/test/Task1Test.java	Fri Oct 10 21:54:39 2008 +0200
     5.2 +++ b/task3/solution11/test/org/apidesign/apifest08/test/Task1Test.java	Fri Oct 10 21:58:12 2008 +0200
     5.3 @@ -42,10 +42,10 @@
     5.4       *
     5.5       * @return prepared convertor ready for converting USD to CZK and CZK to USD
     5.6       */
     5.7 -    public static Convertor<Integer, String> createCZKtoUSD() {
     5.8 -        return Convertor.getConvertorIntegerString(
     5.9 -                CurrencyValue.getCurrencyValue(1, "USD"),
    5.10 -                CurrencyValue.getCurrencyValue(17, "CZK")
    5.11 +    public static Convertor<Double, String> createCZKtoUSD() {
    5.12 +        return Convertor.getConvertorDoubleString(
    5.13 +                CurrencyValue.getCurrencyValue(1d, "USD"),
    5.14 +                CurrencyValue.getCurrencyValue(17d, "CZK")
    5.15          );
    5.16      }
    5.17  
    5.18 @@ -61,10 +61,10 @@
    5.19       * 
    5.20       * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
    5.21       */
    5.22 -    public static Convertor<Integer, String> createSKKtoCZK() {
    5.23 -        return Convertor.getConvertorIntegerString(
    5.24 -                CurrencyValue.getCurrencyValue(100, "SKK"),
    5.25 -                CurrencyValue.getCurrencyValue(80, "CZK")
    5.26 +    public static Convertor<Double, String> createSKKtoCZK() {
    5.27 +        return Convertor.getConvertorDoubleString(
    5.28 +                CurrencyValue.getCurrencyValue(100d, "SKK"),
    5.29 +                CurrencyValue.getCurrencyValue(80d, "CZK")
    5.30          );
    5.31      }
    5.32  
    5.33 @@ -79,62 +79,60 @@
    5.34       * with it.
    5.35       */
    5.36      public void testCurrencyCZKUSD() throws Exception {
    5.37 -        Convertor<Integer, String> c = createCZKtoUSD();
    5.38 +        Convertor<Double, String> c = createCZKtoUSD();
    5.39          
    5.40 -        CurrencyValue<Integer, String> result;
    5.41 +        CurrencyValue<Double, String> result;
    5.42          
    5.43          // convert $5 to CZK using c:
    5.44          // assertEquals("Result is 85 CZK");
    5.45 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(5, "USD"));
    5.46 -        assertEquals(CurrencyValue.getCurrencyValue(85, "CZK"), result);
    5.47 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(5d, "USD"));
    5.48 +        assertEquals(CurrencyValue.getCurrencyValue(85d, "CZK"), result);
    5.49  
    5.50          // convert $8 to CZK
    5.51          // assertEquals("Result is 136 CZK");
    5.52 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(8, "USD"));
    5.53 -        assertEquals(CurrencyValue.getCurrencyValue(136, "CZK"), result);
    5.54 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(8d, "USD"));
    5.55 +        assertEquals(CurrencyValue.getCurrencyValue(136d, "CZK"), result);
    5.56  
    5.57          // convert 1003CZK to USD
    5.58          // assertEquals("Result is 59 USD");
    5.59 -        result = c.convert("USD", CurrencyValue.getCurrencyValue(1003, "CZK"));
    5.60 -        assertEquals(CurrencyValue.getCurrencyValue(59, "USD"), result);
    5.61 +        result = c.convert("USD", CurrencyValue.getCurrencyValue(1003d, "CZK"));
    5.62 +        assertEquals(CurrencyValue.getCurrencyValue(59d, "USD"), result);
    5.63      }
    5.64  
    5.65      /** Use the convertor from <code>createSKKtoCZK</code> method and do few conversions
    5.66       * with it.
    5.67       */
    5.68      public void testCurrencySKKCZK() throws Exception {
    5.69 -        Convertor<Integer, String> c = createSKKtoCZK();
    5.70 +        Convertor<Double, String> c = createSKKtoCZK();
    5.71          
    5.72 -        CurrencyValue<Integer, String> result;
    5.73 +        CurrencyValue<Double, String> result;
    5.74          
    5.75          // convert 16CZK using c:
    5.76          // assertEquals("Result is 20 SKK");
    5.77 -        result = c.convert("SKK", CurrencyValue.getCurrencyValue(16, "CZK"));
    5.78 -        assertEquals(CurrencyValue.getCurrencyValue(20, "SKK"), result);
    5.79 +        result = c.convert("SKK", CurrencyValue.getCurrencyValue(16d, "CZK"));
    5.80 +        assertEquals(CurrencyValue.getCurrencyValue(20d, "SKK"), result);
    5.81  
    5.82          // convert 500SKK to CZK
    5.83          // assertEquals("Result is 400 CZK");
    5.84 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(500, "SKK"));
    5.85 -        assertEquals(CurrencyValue.getCurrencyValue(400, "CZK"), result);
    5.86 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(500d, "SKK"));
    5.87 +        assertEquals(CurrencyValue.getCurrencyValue(400d, "CZK"), result);
    5.88      }
    5.89  
    5.90      /** Verify that the CZK to USD convertor knows nothing about SKK.
    5.91       */
    5.92      public void testCannotConvertToSKKwithCZKUSDConvertor() throws Exception {
    5.93 -        Convertor<Integer, String> c = createCZKtoUSD();
    5.94 +        Convertor<Double, String> c = createCZKtoUSD();
    5.95          try {
    5.96              // convert $5 to SKK, the API shall say this is not possible
    5.97 -            c.convert("SKK", CurrencyValue.getCurrencyValue(16, "CZK"));
    5.98 -            assertTrue("Should not convert", false);
    5.99 +            c.convert("SKK", CurrencyValue.getCurrencyValue(16d, "CZK"));
   5.100 +            fail("Should not convert");
   5.101          } catch (Exception e) {
   5.102 -            assertTrue(true);
   5.103          }
   5.104          try {
   5.105              // convert 500 SKK to CZK, the API shall say this is not possible
   5.106 -            c.convert("CZK", CurrencyValue.getCurrencyValue(500, "SKK"));
   5.107 -            assertTrue("Should not convert", false);
   5.108 +            c.convert("CZK", CurrencyValue.getCurrencyValue(500d, "SKK"));
   5.109 +            fail("Should not convert");
   5.110          } catch (Exception e) {
   5.111 -            assertTrue(true);
   5.112          }
   5.113          
   5.114      }
   5.115 @@ -142,20 +140,18 @@
   5.116      /** Verify that the CZK to SKK convertor knows nothing about USD.
   5.117       */
   5.118      public void testCannotConvertToUSDwithSKKCZKConvertor() throws Exception {
   5.119 -        Convertor<Integer, String> c = createSKKtoCZK();
   5.120 +        Convertor<Double, String> c = createSKKtoCZK();
   5.121          try {
   5.122              // convert $5 to SKK, the API shall say this is not possible
   5.123 -            c.convert("SKK", CurrencyValue.getCurrencyValue(5, "USD"));
   5.124 -            assertTrue("Should not convert", false);
   5.125 +            c.convert("SKK", CurrencyValue.getCurrencyValue(5d, "USD"));
   5.126 +            fail("Should not convert");
   5.127          } catch (Exception e) {
   5.128 -            assertTrue(true);
   5.129          }
   5.130          try {
   5.131              // convert 500 CZK to USD, the API shall say this is not possible
   5.132 -            c.convert("USD", CurrencyValue.getCurrencyValue(500, "CZK"));
   5.133 -            assertTrue("Should not convert", false);
   5.134 +            c.convert("USD", CurrencyValue.getCurrencyValue(500d, "CZK"));
   5.135 +            fail("Should not convert");
   5.136          } catch (Exception e) {
   5.137 -            assertTrue(true);
   5.138          }
   5.139      }
   5.140  }
     6.1 --- a/task3/solution11/test/org/apidesign/apifest08/test/Task2Test.java	Fri Oct 10 21:54:39 2008 +0200
     6.2 +++ b/task3/solution11/test/org/apidesign/apifest08/test/Task2Test.java	Fri Oct 10 21:58:12 2008 +0200
     6.3 @@ -49,49 +49,49 @@
     6.4       *  any other method being called previously. The API itself shall know
     6.5       *  nothing about any rates, before this method is called.
     6.6       */
     6.7 -    public static Convertor<Integer, String> createTripleConvertor() {
     6.8 +    public static Convertor<Double, String> createTripleConvertor() {
     6.9          // Rates: 1USD = 15CZK
    6.10          // Rates: 1USD = 20SKK
    6.11          // Rates: 75CZK = 100SKK
    6.12 -        Collection<ExchangeRateValue<Integer, String>> exchangeRates =
    6.13 -                new ArrayList<ExchangeRateValue<Integer, String>>();
    6.14 +        Collection<ExchangeRateValue<Double, String>> exchangeRates =
    6.15 +                new ArrayList<ExchangeRateValue<Double, String>>();
    6.16          exchangeRates.add(ExchangeRateValue.getExchangeRate(
    6.17 -                CurrencyValue.getCurrencyValue(1, "USD"),
    6.18 -                CurrencyValue.getCurrencyValue(15, "CZK")));
    6.19 +                CurrencyValue.getCurrencyValue(1d, "USD"),
    6.20 +                CurrencyValue.getCurrencyValue(15d, "CZK")));
    6.21          exchangeRates.add(ExchangeRateValue.getExchangeRate(
    6.22 -                CurrencyValue.getCurrencyValue(1, "USD"),
    6.23 -                CurrencyValue.getCurrencyValue(20, "SKK")));
    6.24 +                CurrencyValue.getCurrencyValue(1d, "USD"),
    6.25 +                CurrencyValue.getCurrencyValue(20d, "SKK")));
    6.26          exchangeRates.add(ExchangeRateValue.getExchangeRate(
    6.27 -                CurrencyValue.getCurrencyValue(75, "CZK"),
    6.28 -                CurrencyValue.getCurrencyValue(100, "SKK")));
    6.29 -        return Convertor.getConvertorIntegerString(exchangeRates);
    6.30 +                CurrencyValue.getCurrencyValue(75d, "CZK"),
    6.31 +                CurrencyValue.getCurrencyValue(100d, "SKK")));
    6.32 +        return Convertor.getConvertorDoubleString(exchangeRates);
    6.33      }
    6.34  
    6.35      /** Define convertor that understands three currencies. Use it.
    6.36       */
    6.37      public void testConvertorForUSDandCZKandSKK() throws Exception {
    6.38 -        Convertor<Integer, String> c = createTripleConvertor();
    6.39 +        Convertor<Double, String> c = createTripleConvertor();
    6.40  
    6.41 -        CurrencyValue<Integer, String> result;
    6.42 +        CurrencyValue<Double, String> result;
    6.43          // convert $5 to CZK using c:
    6.44          // assertEquals("Result is 75 CZK");
    6.45 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(5, "USD"));
    6.46 -        assertEquals(CurrencyValue.getCurrencyValue(75, "CZK"), result);
    6.47 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(5d, "USD"));
    6.48 +        assertEquals(CurrencyValue.getCurrencyValue(75d, "CZK"), result);
    6.49  
    6.50          // convert $5 to SKK using c:
    6.51          // assertEquals("Result is 100 SKK");
    6.52 -        result = c.convert("SKK", CurrencyValue.getCurrencyValue(5, "USD"));
    6.53 -        assertEquals(CurrencyValue.getCurrencyValue(100, "SKK"), result);
    6.54 +        result = c.convert("SKK", CurrencyValue.getCurrencyValue(5d, "USD"));
    6.55 +        assertEquals(CurrencyValue.getCurrencyValue(100d, "SKK"), result);
    6.56  
    6.57          // convert 200SKK to CZK using c:
    6.58          // assertEquals("Result is 150 CZK");
    6.59 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(200, "SKK"));
    6.60 -        assertEquals(CurrencyValue.getCurrencyValue(150, "CZK"), result);
    6.61 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(200d, "SKK"));
    6.62 +        assertEquals(CurrencyValue.getCurrencyValue(150d, "CZK"), result);
    6.63  
    6.64          // convert 200SKK to USK using c:
    6.65          // assertEquals("Result is 10 USD");
    6.66 -        result = c.convert("USD", CurrencyValue.getCurrencyValue(200, "SKK"));
    6.67 -        assertEquals(CurrencyValue.getCurrencyValue(10, "USD"), result);
    6.68 +        result = c.convert("USD", CurrencyValue.getCurrencyValue(200d, "SKK"));
    6.69 +        assertEquals(CurrencyValue.getCurrencyValue(10d, "USD"), result);
    6.70      }
    6.71  
    6.72      /** Merge all currency rates of convertor 1 with convertor 2.
    6.73 @@ -99,42 +99,42 @@
    6.74       * into some API method which does the actual work, without requiring
    6.75       * API clients to code anything complex.
    6.76       */
    6.77 -    public static Convertor<Integer, String> merge(Convertor<Integer, String> one, Convertor<Integer, String> two) {
    6.78 -        return Convertor.mergeConvertorsIntegerString(one, two);
    6.79 +    public static Convertor<Double, String> merge(Convertor<Double, String> one, Convertor<Double, String> two) {
    6.80 +        return Convertor.mergeConvertorsDoubleString(one, two);
    6.81      }
    6.82  
    6.83      /** Join the convertors from previous task, Task1Test and show that it
    6.84       * can be used to do reasonable conversions.
    6.85       */
    6.86      public void testConvertorComposition() throws Exception {
    6.87 -        Convertor<Integer, String> c = merge(
    6.88 +        Convertor<Double, String> c = merge(
    6.89                  Task1Test.createCZKtoUSD(),
    6.90                  Task1Test.createSKKtoCZK());
    6.91  
    6.92 -        CurrencyValue<Integer, String> result;
    6.93 +        CurrencyValue<Double, String> result;
    6.94          // convert $5 to CZK using c:
    6.95          // assertEquals("Result is 85 CZK");
    6.96 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(5, "USD"));
    6.97 -        assertEquals(CurrencyValue.getCurrencyValue(85, "CZK"), result);
    6.98 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(5d, "USD"));
    6.99 +        assertEquals(CurrencyValue.getCurrencyValue(85d, "CZK"), result);
   6.100  
   6.101          // convert $8 to CZK using c:
   6.102          // assertEquals("Result is 136 CZK");
   6.103 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(8, "USD"));
   6.104 -        assertEquals(CurrencyValue.getCurrencyValue(136, "CZK"), result);
   6.105 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(8d, "USD"));
   6.106 +        assertEquals(CurrencyValue.getCurrencyValue(136d, "CZK"), result);
   6.107  
   6.108          // convert 1003CZK to USD using c:
   6.109          // assertEquals("Result is 59 USD");
   6.110 -        result = c.convert("USD", CurrencyValue.getCurrencyValue(1003, "CZK"));
   6.111 -        assertEquals(CurrencyValue.getCurrencyValue(59, "USD"), result);
   6.112 +        result = c.convert("USD", CurrencyValue.getCurrencyValue(1003d, "CZK"));
   6.113 +        assertEquals(CurrencyValue.getCurrencyValue(59d, "USD"), result);
   6.114  
   6.115          // convert 16CZK using c:
   6.116          // assertEquals("Result is 20 SKK");
   6.117 -        result = c.convert("SKK", CurrencyValue.getCurrencyValue(16, "CZK"));
   6.118 -        assertEquals(CurrencyValue.getCurrencyValue(20, "SKK"), result);
   6.119 +        result = c.convert("SKK", CurrencyValue.getCurrencyValue(16d, "CZK"));
   6.120 +        assertEquals(CurrencyValue.getCurrencyValue(20d, "SKK"), result);
   6.121  
   6.122          // convert 500SKK to CZK using c:
   6.123          // assertEquals("Result is 400 CZK");
   6.124 -        result = c.convert("CZK", CurrencyValue.getCurrencyValue(500, "SKK"));
   6.125 -        assertEquals(CurrencyValue.getCurrencyValue(400, "CZK"), result);
   6.126 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(500d, "SKK"));
   6.127 +        assertEquals(CurrencyValue.getCurrencyValue(400d, "CZK"), result);
   6.128      }
   6.129  }
     7.1 --- a/task3/solution11/test/org/apidesign/apifest08/test/Task3Test.java	Fri Oct 10 21:54:39 2008 +0200
     7.2 +++ b/task3/solution11/test/org/apidesign/apifest08/test/Task3Test.java	Fri Oct 10 21:58:12 2008 +0200
     7.3 @@ -2,6 +2,12 @@
     7.4  
     7.5  import junit.framework.TestCase;
     7.6  import org.apidesign.apifest08.currency.Convertor;
     7.7 +import org.apidesign.apifest08.currency.CurrencyValue;
     7.8 +import org.apidesign.apifest08.currency.ExchangeRateDataSource;
     7.9 +import org.apidesign.apifest08.currency.ExchangeRateProvider;
    7.10 +import org.apidesign.apifest08.currency.ExchangeRateProvider.ExchangeRateRequest;
    7.11 +import org.apidesign.apifest08.currency.ExchangeRateProvider.ExchangeRateResponse;
    7.12 +import org.apidesign.apifest08.currency.ExchangeRateValue;
    7.13  
    7.14  /** The exchange rates are not always the same. They are changing. Day by day,
    7.15   * hour by hour, minute by minute. For every bank it is important to always
    7.16 @@ -16,6 +22,7 @@
    7.17   * to be used.
    7.18   */
    7.19  public class Task3Test extends TestCase {
    7.20 +
    7.21      public Task3Test(String testName) {
    7.22          super(testName);
    7.23      }
    7.24 @@ -31,8 +38,6 @@
    7.25      // Backward compatibly enhance your existing API to support following
    7.26      // usecases:
    7.27      //
    7.28 -
    7.29 -
    7.30      /** Without knowing anything about the surrounding system, write an
    7.31       * implementation of convertor that will return different rates everytime
    7.32       * it is queried. Convert USD to CZK and vice versa. Start with the rate of
    7.33 @@ -42,7 +47,7 @@
    7.34       *
    7.35       * @return new instance of "online" USD and CZK convertor starting with rate 1USD = 16CZK
    7.36       */
    7.37 -    public static Convertor createOnlineCZKUSDConvertor() {
    7.38 +    public static Convertor<Double, String> createOnlineCZKUSDConvertor() {
    7.39          // initial rate: 1USD = 16CZK
    7.40          // 2nd query 1USD = 15.99CZK
    7.41          // 3rd query 1USD = 15.98CZK
    7.42 @@ -51,53 +56,80 @@
    7.43          // then 1USD = 15.02CZK
    7.44          // and so on and on up to 1USD = 16CZK
    7.45          // and then another round to 15, etc.
    7.46 -        return null;
    7.47 +        return Convertor.getConvertorDataSourceDoubleString(
    7.48 +                ExchangeRateDataSource.getExchangeRateDataSource(
    7.49 +                "USD", "CZK", new ExchangeRateProvider<Double, String>() {
    7.50 +
    7.51 +            double currentRate = 16d;
    7.52 +            double step;
    7.53 +
    7.54 +            public void getExchangeRate(ExchangeRateRequest<Double, String> request,
    7.55 +                    ExchangeRateResponse<Double, String> response) {
    7.56 +                if ((request.getCurrencyAIdentifier().equals("CZK") && request.getCurrencyBIdentifier().equals("USD")) ||
    7.57 +                        (request.getCurrencyAIdentifier().equals("USD") && request.getCurrencyBIdentifier().equals("CZK"))) {
    7.58 +                    response.setExchangeRate(ExchangeRateValue.getExchangeRate(
    7.59 +                            CurrencyValue.getCurrencyValue(1d, "USD"),
    7.60 +                            CurrencyValue.getCurrencyValue(currentRate, "CZK")));
    7.61 +
    7.62 +                    if (currentRate == 16d) {
    7.63 +                        step = -0.01;
    7.64 +                    }
    7.65 +                    if (currentRate == 15d) {
    7.66 +                        step = 0.01;
    7.67 +                    }
    7.68 +                    currentRate += step;
    7.69 +                } else {
    7.70 +                    throw new IllegalArgumentException("No exchange rate for requested currencies!");
    7.71 +                }
    7.72 +            }
    7.73 +        }));
    7.74      }
    7.75  
    7.76      public void testFewQueriesForOnlineConvertor() {
    7.77 -        if (Boolean.getBoolean("ignore.failing")) {
    7.78 -            // implement me!
    7.79 -            return;
    7.80 -        }
    7.81 -
    7.82 -        Convertor c = createOnlineCZKUSDConvertor();
    7.83 +        Convertor<Double, String> c = createOnlineCZKUSDConvertor();
    7.84          doFewQueriesForOnlineConvertor(c);
    7.85      }
    7.86  
    7.87 -    static void doFewQueriesForOnlineConvertor(Convertor c) {
    7.88 +    static void doFewQueriesForOnlineConvertor(Convertor<Double, String> c) {
    7.89 +        CurrencyValue<Double, String> result;
    7.90          // convert $5 to CZK using c:
    7.91          //assertEquals("Result is 80 CZK");
    7.92 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(5d, "USD"));
    7.93 +        assertEquals(CurrencyValue.getCurrencyValue(80d, "CZK"), result);
    7.94  
    7.95          // convert $8 to CZK using c:
    7.96          //assertEquals("Result is 127.92 CZK");
    7.97 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(8d, "USD"));
    7.98 +        assertEquals(CurrencyValue.getCurrencyValue(127.92d, "CZK"), result);
    7.99  
   7.100          // convert $1 to CZK using c:
   7.101          //assertEquals("Result is 15.98 CZK");
   7.102 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(1d, "USD"));
   7.103 +        assertEquals(CurrencyValue.getCurrencyValue(15.98d, "CZK"), result);
   7.104  
   7.105          // convert 15.97CZK to USD using c:
   7.106          //assertEquals("Result is 1$");
   7.107 -
   7.108 -        fail("Implement me!");
   7.109 +        result = c.convert("USD", CurrencyValue.getCurrencyValue(15.97d, "CZK"));
   7.110 +        assertEquals(CurrencyValue.getCurrencyValue(1d, "USD"), result);
   7.111      }
   7.112  
   7.113      /** Join the convertors and show they behave sane.
   7.114       */
   7.115      public void testOnlineConvertorComposition() throws Exception {
   7.116 -        if (Boolean.getBoolean("ignore.failing")) {
   7.117 -            // implement me!
   7.118 -            return;
   7.119 -        }
   7.120 -        
   7.121 -        Convertor c = Task2Test.merge(
   7.122 -            createOnlineCZKUSDConvertor(),
   7.123 -            Task1Test.createSKKtoCZK()
   7.124 -        );
   7.125 +        Convertor<Double, String> c = Task2Test.merge(
   7.126 +                createOnlineCZKUSDConvertor(),
   7.127 +                Task1Test.createSKKtoCZK());
   7.128  
   7.129 +        CurrencyValue<Double, String> result;
   7.130          // convert 16CZK to SKK using c:
   7.131          // assertEquals("Result is 20 SKK");
   7.132 +        result = c.convert("SKK", CurrencyValue.getCurrencyValue(16d, "CZK"));
   7.133 +        assertEquals(CurrencyValue.getCurrencyValue(20d, "SKK"), result);
   7.134  
   7.135          // convert 500SKK to CZK using c:
   7.136          // assertEquals("Result is 400 CZK");
   7.137 +        result = c.convert("CZK", CurrencyValue.getCurrencyValue(500d, "SKK"));
   7.138 +        assertEquals(CurrencyValue.getCurrencyValue(400d, "CZK"), result);
   7.139  
   7.140          doFewQueriesForOnlineConvertor(c);
   7.141      }