1.1 --- a/task2/solution11/src/org/apidesign/apifest08/currency/Convertor.java Wed Oct 01 10:43:05 2008 +0200
1.2 +++ b/task2/solution11/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 00:25:53 2008 +0200
1.3 @@ -1,5 +1,10 @@
1.4 package org.apidesign.apifest08.currency;
1.5
1.6 +import java.util.ArrayList;
1.7 +import java.util.Collection;
1.8 +import java.util.HashSet;
1.9 +import java.util.List;
1.10 +import java.util.Set;
1.11 import org.apidesign.apifest08.currency.Computer.ComputerRequest;
1.12 import org.apidesign.apifest08.currency.Computer.ComputerResponse;
1.13
1.14 @@ -10,31 +15,50 @@
1.15 * with amount stored in integer or double, that are identified
1.16 * with string value. Exchange rates are immutable.
1.17 *
1.18 + * In Task2's version provides support for multiple exchange rates
1.19 + * between different currencies & merging exchange rates from
1.20 + * existing convertors into new convertor's instance.
1.21 + * No time for javadoc these features, sorry.
1.22 + *
1.23 * @author ked
1.24 */
1.25 public final class Convertor<AmountType, IdentifierType> {
1.26
1.27 Computer<AmountType> computer;
1.28 - CurrencyValue<AmountType, IdentifierType> firstCurrencyExchangeRate;
1.29 - CurrencyValue<AmountType, IdentifierType> secondCurrencyExchangeRate;
1.30 + List<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates = new ArrayList<ExchangeRateValue<AmountType, IdentifierType>>();
1.31
1.32 Convertor(
1.33 Computer<AmountType> computer,
1.34 - CurrencyValue<AmountType, IdentifierType> firstCurrencyExchangeRate,
1.35 - CurrencyValue<AmountType, IdentifierType> secondCurrencyExchangeRate) {
1.36 - if (firstCurrencyExchangeRate.getIdentifier() == null ||
1.37 - secondCurrencyExchangeRate.getIdentifier() == null ||
1.38 - firstCurrencyExchangeRate.getIdentifier().equals(secondCurrencyExchangeRate.getIdentifier())) {
1.39 - throw new IllegalArgumentException("Inappropriate exchange rates' identifiers!");
1.40 + Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates) {
1.41 + this.computer = computer;
1.42 +
1.43 + for (ExchangeRateValue<AmountType, IdentifierType> exchangeRate : exchangeRates) {
1.44 + if (findExchangeRate(
1.45 + this.exchangeRates,
1.46 + exchangeRate.getCurrencyA().getIdentifier(),
1.47 + exchangeRate.getCurrencyB().getIdentifier()) != null) {
1.48 + throw new IllegalArgumentException("Duplicate exchange rate!");
1.49 + }
1.50 + this.exchangeRates.add(exchangeRate);
1.51 }
1.52 - this.computer = computer;
1.53 - this.firstCurrencyExchangeRate = firstCurrencyExchangeRate;
1.54 - this.secondCurrencyExchangeRate = secondCurrencyExchangeRate;
1.55 + }
1.56 +
1.57 + private ExchangeRateValue<AmountType, IdentifierType> findExchangeRate(
1.58 + Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates,
1.59 + IdentifierType currencyA,
1.60 + IdentifierType currencyB) {
1.61 + for (ExchangeRateValue<AmountType, IdentifierType> exchangeRate : exchangeRates) {
1.62 + if ((exchangeRate.getCurrencyA().getIdentifier().equals(currencyA) && exchangeRate.getCurrencyB().getIdentifier().equals(currencyB)) ||
1.63 + (exchangeRate.getCurrencyA().getIdentifier().equals(currencyB) && exchangeRate.getCurrencyB().getIdentifier().equals(currencyA))) {
1.64 + return exchangeRate;
1.65 + }
1.66 + }
1.67 + return null;
1.68 }
1.69
1.70 /**
1.71 * Convert an amount of the one currency to an amount of the another one currency
1.72 - * with respect to previously specified exchange rate.
1.73 + * with respect to previously specified exchange rates.
1.74 *
1.75 * @param targetCurrency an identifier of the requested currency
1.76 * @param currencyValue an amount of the another one currency
1.77 @@ -43,52 +67,117 @@
1.78 public CurrencyValue<AmountType, IdentifierType> convert(
1.79 IdentifierType targetCurrency,
1.80 CurrencyValue<AmountType, IdentifierType> currencyValue) {
1.81 - if (firstCurrencyExchangeRate.getIdentifier().equals(targetCurrency) &&
1.82 - secondCurrencyExchangeRate.getIdentifier().equals(currencyValue.getIdentifier())) {
1.83 - ComputerRequest<AmountType> computerRequest = new ComputerRequest<AmountType>();
1.84 - computerRequest.setInput(currencyValue.getAmount());
1.85 - computerRequest.setInputCurrencyRatio(secondCurrencyExchangeRate.getAmount());
1.86 - computerRequest.setOutputCurrencyRatio(firstCurrencyExchangeRate.getAmount());
1.87 - ComputerResponse<AmountType> computerResponse = computer.compute(computerRequest);
1.88 -
1.89 - return CurrencyValue.getCurrencyValue(
1.90 - computerResponse.getResult(),
1.91 - firstCurrencyExchangeRate.getIdentifier());
1.92 - } else if (secondCurrencyExchangeRate.getIdentifier().equals(targetCurrency) &&
1.93 - firstCurrencyExchangeRate.getIdentifier().equals(currencyValue.getIdentifier())) {
1.94 - ComputerRequest<AmountType> computerRequest = new ComputerRequest<AmountType>();
1.95 - computerRequest.setInput(currencyValue.getAmount());
1.96 - computerRequest.setInputCurrencyRatio(firstCurrencyExchangeRate.getAmount());
1.97 - computerRequest.setOutputCurrencyRatio(secondCurrencyExchangeRate.getAmount());
1.98 - ComputerResponse<AmountType> computerResponse = computer.compute(computerRequest);
1.99 -
1.100 - return CurrencyValue.getCurrencyValue(
1.101 - computerResponse.getResult(),
1.102 - secondCurrencyExchangeRate.getIdentifier());
1.103 - } else {
1.104 + ExchangeRateValue<AmountType, IdentifierType> exchangeRate =
1.105 + findExchangeRate(exchangeRates, currencyValue.getIdentifier(), targetCurrency);
1.106 + if (exchangeRate == null) {
1.107 throw new IllegalArgumentException("Inappropriate currencies to convert!");
1.108 }
1.109 +
1.110 + ComputerRequest<AmountType> computerRequest = new ComputerRequest<AmountType>();
1.111 + computerRequest.setInput(currencyValue.getAmount());
1.112 +
1.113 + IdentifierType targetCurrencyRef; // just for backward compatibility :-(
1.114 + if (exchangeRate.getCurrencyA().getIdentifier().equals(targetCurrency)) {
1.115 + computerRequest.setInputCurrencyRatio(exchangeRate.getCurrencyB().getAmount());
1.116 + computerRequest.setOutputCurrencyRatio(exchangeRate.getCurrencyA().getAmount());
1.117 + targetCurrencyRef = exchangeRate.getCurrencyA().getIdentifier();
1.118 + } else {
1.119 + computerRequest.setInputCurrencyRatio(exchangeRate.getCurrencyA().getAmount());
1.120 + computerRequest.setOutputCurrencyRatio(exchangeRate.getCurrencyB().getAmount());
1.121 + targetCurrencyRef = exchangeRate.getCurrencyB().getIdentifier();
1.122 + }
1.123 +
1.124 + ComputerResponse<AmountType> computerResponse = computer.compute(computerRequest);
1.125 + return CurrencyValue.getCurrencyValue(
1.126 + computerResponse.getResult(),
1.127 + targetCurrencyRef);
1.128 + }
1.129 +
1.130 + // ---
1.131 + // MERGING
1.132 + // ---
1.133 + static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> mergeConvertors(
1.134 + Computer<AmountType> computer,
1.135 + Collection<Convertor<AmountType, IdentifierType>> convertors) {
1.136 + Set<ExchangeRateValue<AmountType, IdentifierType>> exchangeRatesSet = new HashSet<ExchangeRateValue<AmountType, IdentifierType>>();
1.137 + for (Convertor<AmountType, IdentifierType> convertor : convertors) {
1.138 + exchangeRatesSet.addAll(convertor.exchangeRates);
1.139 + }
1.140 + return getConvertor(computer, exchangeRatesSet);
1.141 + }
1.142 +
1.143 + static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> mergeConvertors(
1.144 + Computer<AmountType> computer,
1.145 + Convertor<AmountType, IdentifierType> convertorA,
1.146 + Convertor<AmountType, IdentifierType> convertorB) {
1.147 + Collection<Convertor<AmountType, IdentifierType>> convertors =
1.148 + new ArrayList<Convertor<AmountType, IdentifierType>>();
1.149 + convertors.add(convertorA);
1.150 + convertors.add(convertorB);
1.151 + return mergeConvertors(computer, convertors);
1.152 + }
1.153 +
1.154 + public static Convertor<Double, String> mergeConvertorsDoubleString(
1.155 + Collection<Convertor<Double, String>> convertors) {
1.156 + return mergeConvertors(DoubleComputer, convertors);
1.157 + }
1.158 +
1.159 + public static Convertor<Double, String> mergeConvertorsDoubleString(
1.160 + Convertor<Double, String> convertorA,
1.161 + Convertor<Double, String> convertorB) {
1.162 + return mergeConvertors(DoubleComputer, convertorA, convertorB);
1.163 + }
1.164 +
1.165 + public static Convertor<Integer, String> mergeConvertorsIntegerString(
1.166 + Collection<Convertor<Integer, String>> convertors) {
1.167 + return mergeConvertors(IntegerComputer, convertors);
1.168 + }
1.169 +
1.170 + public static Convertor<Integer, String> mergeConvertorsIntegerString(
1.171 + Convertor<Integer, String> convertorA,
1.172 + Convertor<Integer, String> convertorB) {
1.173 + return mergeConvertors(IntegerComputer, convertorA, convertorB);
1.174 + }
1.175 +
1.176 + // ---
1.177 + // CREATION
1.178 + // ---
1.179 + static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertor(
1.180 + Computer<AmountType> computer, Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates) {
1.181 + return new Convertor<AmountType, IdentifierType>(computer, exchangeRates);
1.182 }
1.183
1.184 static <AmountType, IdentifierType> Convertor<AmountType, IdentifierType> getConvertor(
1.185 - Computer<AmountType> computer,
1.186 - CurrencyValue<AmountType, IdentifierType> firstCurrencyExchangeRate,
1.187 - CurrencyValue<AmountType, IdentifierType> secondCurrencyExchangeRate) {
1.188 - return new Convertor<AmountType, IdentifierType>(
1.189 - computer,
1.190 - firstCurrencyExchangeRate,
1.191 - secondCurrencyExchangeRate);
1.192 + Computer<AmountType> computer, ExchangeRateValue<AmountType, IdentifierType> exchangeRate) {
1.193 + Collection<ExchangeRateValue<AmountType, IdentifierType>> exchangeRates =
1.194 + new ArrayList<ExchangeRateValue<AmountType, IdentifierType>>();
1.195 + exchangeRates.add(exchangeRate);
1.196 + return getConvertor(computer, exchangeRates);
1.197 }
1.198
1.199 - static final Computer<Double> DoubleComputer = new Computer<Double>() {
1.200 + public static Convertor<Double, String> getConvertorDoubleString(
1.201 + Collection<ExchangeRateValue<Double, String>> exchangeRates) {
1.202 + return getConvertor(DoubleComputer, exchangeRates);
1.203 + }
1.204
1.205 - public ComputerResponse<Double> compute(ComputerRequest<Double> request) {
1.206 - ComputerResponse<Double> response = new ComputerResponse<Double>();
1.207 - response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
1.208 - return response;
1.209 - }
1.210 - };
1.211 + public static Convertor<Double, String> getConvertorDoubleString(
1.212 + ExchangeRateValue<Double, String> exchangeRate) {
1.213 + return getConvertor(DoubleComputer, exchangeRate);
1.214 + }
1.215
1.216 + public static Convertor<Integer, String> getConvertorIntegerString(
1.217 + Collection<ExchangeRateValue<Integer, String>> exchangeRates) {
1.218 + return getConvertor(IntegerComputer, exchangeRates);
1.219 + }
1.220 +
1.221 + public static Convertor<Integer, String> getConvertorIntegerString(
1.222 + ExchangeRateValue<Integer, String> exchangeRate) {
1.223 + return getConvertor(IntegerComputer, exchangeRate);
1.224 + }
1.225 +
1.226 + // ---
1.227 + // BACKWARD COMPATIBILITY - CREATION
1.228 + // ---
1.229 /**
1.230 * Creates convertor for Double|String values with specified exchange rate
1.231 * between two currencies.
1.232 @@ -97,21 +186,11 @@
1.233 * @param secondCurrencyExchangeRate second currency
1.234 * @return convertor
1.235 */
1.236 -
1.237 public static Convertor<Double, String> getConvertorDoubleString(
1.238 CurrencyValue<Double, String> firstCurrencyExchangeRate,
1.239 CurrencyValue<Double, String> secondCurrencyExchangeRate) {
1.240 - return getConvertor(DoubleComputer, firstCurrencyExchangeRate, secondCurrencyExchangeRate);
1.241 + return getConvertorDoubleString(ExchangeRateValue.getExchangeRate(firstCurrencyExchangeRate, secondCurrencyExchangeRate));
1.242 }
1.243 -
1.244 - static final Computer<Integer> IntegerComputer = new Computer<Integer>() {
1.245 -
1.246 - public ComputerResponse<Integer> compute(ComputerRequest<Integer> request) {
1.247 - ComputerResponse<Integer> response = new ComputerResponse<Integer>();
1.248 - response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
1.249 - return response;
1.250 - }
1.251 - };
1.252
1.253 /**
1.254 * Creates convertor for Integer|String values with specified exchange rate
1.255 @@ -124,6 +203,26 @@
1.256 public static Convertor<Integer, String> getConvertorIntegerString(
1.257 CurrencyValue<Integer, String> firstCurrencyExchangeRate,
1.258 CurrencyValue<Integer, String> secondCurrencyExchangeRate) {
1.259 - return getConvertor(IntegerComputer, firstCurrencyExchangeRate, secondCurrencyExchangeRate);
1.260 + return getConvertorIntegerString(ExchangeRateValue.getExchangeRate(firstCurrencyExchangeRate, secondCurrencyExchangeRate));
1.261 }
1.262 +
1.263 + // ---
1.264 + // COMPUTERS
1.265 + // ---
1.266 + static final Computer<Double> DoubleComputer = new Computer<Double>() {
1.267 +
1.268 + public ComputerResponse<Double> compute(ComputerRequest<Double> request) {
1.269 + ComputerResponse<Double> response = new ComputerResponse<Double>();
1.270 + response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
1.271 + return response;
1.272 + }
1.273 + };
1.274 + static final Computer<Integer> IntegerComputer = new Computer<Integer>() {
1.275 +
1.276 + public ComputerResponse<Integer> compute(ComputerRequest<Integer> request) {
1.277 + ComputerResponse<Integer> response = new ComputerResponse<Integer>();
1.278 + response.setResult(request.getInput() * request.getOutputCurrencyRatio() / request.getInputCurrencyRatio());
1.279 + return response;
1.280 + }
1.281 + };
1.282 }