# HG changeset patch # User japod@localhost # Date 1223332977 -7200 # Node ID 5838e0aaa81f23f25f846bd0ce86c1bd5bea1525 # Parent d333e45f6df14493ecefe1a0a304fae936c45e36 adding solution06 for task2 diff -r d333e45f6df1 -r 5838e0aaa81f task2/solution06/src/org/apidesign/apifest08/currency/Convertor.java --- a/task2/solution06/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 00:25:53 2008 +0200 +++ b/task2/solution06/src/org/apidesign/apifest08/currency/Convertor.java Tue Oct 07 00:42:57 2008 +0200 @@ -4,23 +4,44 @@ import java.math.BigDecimal; import java.math.RoundingMode; +import java.util.ArrayList; import java.util.Currency; +import java.util.List; public final class Convertor { - private final Currency first; - private final Currency second; - private final BigDecimal rateValue; // a rate between the first currency and the second currency - public static final BigDecimal one = new BigDecimal(1); + private List convertorDelegates = new ArrayList(); + + /** + * Create new instance of the converter for the given currencies and its rate. + * + * @param rateValue the rate between the first and the second currency + * @param currencyFirst the first currency + * @param currencySecond the second currency + */ public Convertor(BigDecimal rateValue, Currency currencyFirst, Currency currencySecond) { notNull(currencyFirst, "currencyFirst"); notNull(currencySecond, "currencySecond"); - notNull(rateValue, "rateValue"); + notNull(rateValue, "rateValue"); + convertorDelegates.add(new ConvertorDelegate(rateValue, currencyFirst, currencySecond)); + } + + /** + * Create new instance of the convertor from the given convertors. + * @param convertors the convertors + */ + public Convertor(Convertor... convertors) { + notNull(convertors, "convertors"); + if(convertors.length == 0) { + throw new IllegalArgumentException("There must be at least one converter."); + } - this.rateValue = rateValue; - this.first = currencyFirst; - this.second = currencySecond; + for(Convertor convertor: convertors) { + if(convertor != null) { + convertorDelegates.addAll(convertor.convertorDelegates); + } + } } /** @@ -38,27 +59,66 @@ notNull(amount, "amount"); notNull(fromCurrency, "fromCurrency"); notNull(toCurrency, "toCurrency"); + ConvertorDelegate appropriateDelegate = null; - if((fromCurrency != first && fromCurrency != second) || (toCurrency != first && toCurrency != second)) { + //try find an appropriate delegate for conversion + for(ConvertorDelegate delegate : convertorDelegates) { + if(delegate.isConversionSupported(fromCurrency, toCurrency)) { + appropriateDelegate = delegate; + break; + } + } + + if(appropriateDelegate == null) { throw new UnsupportedConversionException(fromCurrency, toCurrency); - } - - BigDecimal rateValue = getRateValue(fromCurrency, toCurrency); - BigDecimal result = rateValue.multiply(amount); - return new Amount(result, toCurrency); + } + + return appropriateDelegate.convert(amount, fromCurrency, toCurrency); } - private BigDecimal getRateValue(Currency fromCurrency, Currency toCurrency) { + /** + * Internal delegate implements a logic for conversion between two currencies + * and vice versa. + * @see #isConversionSupported(Currency, Currency) + */ + private static class ConvertorDelegate { + private final Currency first; + private final Currency second; + private final BigDecimal rateValue; // a rate between the first currency and the second currency + public static final BigDecimal one = new BigDecimal(1); - BigDecimal retVal; - - if(first == fromCurrency) { - retVal = rateValue; - } else { - //reverse rate - retVal = one.divide(rateValue, 10 ,RoundingMode.HALF_UP); + private ConvertorDelegate(BigDecimal rateValue, Currency currencyFirst, Currency currencySecond) { + this.rateValue = rateValue; + this.first = currencyFirst; + this.second = currencySecond; } - return retVal; + private Amount convert(BigDecimal amount, Currency fromCurrency, Currency toCurrency) throws ConversionException { + BigDecimal rateValue = getRateValue(fromCurrency, toCurrency); + BigDecimal result = rateValue.multiply(amount); + return new Amount(result, toCurrency); + } + + private BigDecimal getRateValue(Currency fromCurrency, Currency toCurrency) { + + BigDecimal retVal; + + if(first == fromCurrency) { + retVal = rateValue; + } else { + //reverse rate + retVal = one.divide(rateValue, 10 ,RoundingMode.HALF_UP); + } + + return retVal; + } + + /** + * @return true if the delegate is able to convert from the given currency + * to the given currency and vice versa otherwise false. + */ + private boolean isConversionSupported(Currency fromCurrency, Currency toCurrency) { + return ((fromCurrency == first || fromCurrency == second) && (toCurrency == first || toCurrency == second)); + } } }