1.1 --- a/task4/solution04/src/org/apidesign/apifest08/currency/CompositeConvertorImpl.java Fri Oct 17 17:39:18 2008 +0200
1.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/CompositeConvertorImpl.java Fri Oct 17 17:40:14 2008 +0200
1.3 @@ -16,7 +16,7 @@
1.4 * A composite convertor will build all possible conversions that are allowed by the underlying set of convertors.
1.5 *
1.6 * @author D'Arcy Smith
1.7 - * @verson 1.1
1.8 + * @verson 1.2
1.9 */
1.10 final class CompositeConvertorImpl
1.11 implements Convertor
1.12 @@ -88,7 +88,9 @@
1.13 // we cannot derive:
1.14 // USD <-> GBP
1.15 // CAD <-> GBP
1.16 - // CZK <-> GBP
1.17 + // CZK <-> GBP
1.18 + //
1.19 + // NOTE: no attempt is made to deal with dates for DatedConvertors... nothing we can do about it.
1.20 do
1.21 {
1.22 newConvertors = 0;
2.1 --- a/task4/solution04/src/org/apidesign/apifest08/currency/ConverterImpl.java Fri Oct 17 17:39:18 2008 +0200
2.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/ConverterImpl.java Fri Oct 17 17:40:14 2008 +0200
2.3 @@ -2,11 +2,7 @@
2.4
2.5
2.6 import java.math.BigDecimal;
2.7 -import java.math.MathContext;
2.8 -import java.math.RoundingMode;
2.9 -import java.util.Collections;
2.10 import java.util.Currency;
2.11 -import java.util.HashSet;
2.12 import java.util.Set;
2.13
2.14
2.15 @@ -14,32 +10,16 @@
2.16 * Convert between two currencies.
2.17 *
2.18 * @author D'Arcy Smith
2.19 - * @version 1.0
2.20 + * @version 1.1
2.21 */
2.22 -final class ConvertorImpl
2.23 - implements Convertor
2.24 +class ConvertorImpl
2.25 + implements ExchangeRateConvertor
2.26 {
2.27 /**
2.28 - * The currency to convert from.
2.29 */
2.30 - private final Currency currencyA;
2.31 + private final ExchangeRate rate;
2.32
2.33 /**
2.34 - * The currency to convert to.
2.35 - */
2.36 - private final Currency currencyB;
2.37 -
2.38 - /**
2.39 - * The echange rate between a and b.
2.40 - */
2.41 - private final BigDecimal currencyARate;
2.42 -
2.43 - /**
2.44 - * The echange rate between b and a.
2.45 - */
2.46 - private final BigDecimal currencyBRate;
2.47 -
2.48 - /**
2.49 * Constructs a convertor with the specified currencies.
2.50 *
2.51 * @param a the currency to convert from.
2.52 @@ -48,45 +28,14 @@
2.53 * @param bRate the exchage rage between to and from.
2.54 * @throws IllegalArgumentException if either any of the arguments are null or if either rate <= 0.
2.55 */
2.56 - public ConvertorImpl(final Currency a,
2.57 - final BigDecimal aRate,
2.58 - final Currency b,
2.59 - final BigDecimal bRate)
2.60 + public ConvertorImpl(final ExchangeRate r)
2.61 {
2.62 - if(a == null)
2.63 + if(r == null)
2.64 {
2.65 - throw new IllegalArgumentException("a cannot be null");
2.66 + throw new IllegalArgumentException("r cannot be null");
2.67 }
2.68
2.69 - if(b == null)
2.70 - {
2.71 - throw new IllegalArgumentException("b cannot be null");
2.72 - }
2.73 -
2.74 - if(aRate == null)
2.75 - {
2.76 - throw new IllegalArgumentException("aRate cannot be null");
2.77 - }
2.78 -
2.79 - if(bRate == null)
2.80 - {
2.81 - throw new IllegalArgumentException("bRate cannot be null");
2.82 - }
2.83 -
2.84 - if(aRate.compareTo(BigDecimal.ZERO) <= 0)
2.85 - {
2.86 - throw new IllegalArgumentException("aRate must be > 0, was: " + aRate);
2.87 - }
2.88 -
2.89 - if(bRate.compareTo(BigDecimal.ZERO) <= 0)
2.90 - {
2.91 - throw new IllegalArgumentException("bRate must be > 0, was: " + bRate);
2.92 - }
2.93 -
2.94 - currencyA = a;
2.95 - currencyB = b;
2.96 - currencyARate = aRate;
2.97 - currencyBRate = bRate;
2.98 + rate = r;
2.99 }
2.100
2.101 /**
2.102 @@ -104,36 +53,7 @@
2.103 final BigDecimal amount)
2.104 throws InvalidConversionException
2.105 {
2.106 - final BigDecimal result;
2.107 -
2.108 - if(amount == null)
2.109 - {
2.110 - throw new IllegalArgumentException("amount cannot be null");
2.111 - }
2.112 -
2.113 - if(from == null)
2.114 - {
2.115 - throw new IllegalArgumentException("from cannot be null");
2.116 - }
2.117 -
2.118 - if(to == null)
2.119 - {
2.120 - throw new IllegalArgumentException("to cannot be null");
2.121 - }
2.122 -
2.123 - if(!(from.equals(currencyA)) && (!(from.equals(currencyB))))
2.124 - {
2.125 - throw new InvalidConversionException("cannot convert from: " + from.getCurrencyCode(), from, currencyA, currencyB);
2.126 - }
2.127 -
2.128 - if(!(to.equals(currencyA)) && (!(to.equals(currencyB))))
2.129 - {
2.130 - throw new InvalidConversionException("cannot convert to: " + to.getCurrencyCode(), to, currencyA, currencyB);
2.131 - }
2.132 -
2.133 - result = amount.multiply(getConversionRate(from, to));
2.134 -
2.135 - return (result.setScale(2, RoundingMode.HALF_DOWN));
2.136 + return (rate.convert(from, to, amount));
2.137 }
2.138
2.139 /**
2.140 @@ -146,18 +66,7 @@
2.141 */
2.142 public boolean canConvert(final Currency from, final Currency to)
2.143 {
2.144 - if(from == null)
2.145 - {
2.146 - throw new IllegalArgumentException("from cannot be null");
2.147 - }
2.148 -
2.149 - if(to == null)
2.150 - {
2.151 - throw new IllegalArgumentException("to cannot be null");
2.152 - }
2.153 -
2.154 - return ((from.equals(currencyA) || from.equals(currencyB)) &&
2.155 - (to.equals(currencyA) || to.equals(currencyB)));
2.156 + return (rate.canConvert(from, to));
2.157 }
2.158
2.159 /**
2.160 @@ -167,13 +76,7 @@
2.161 */
2.162 public Set<Currency> getCurrencies()
2.163 {
2.164 - final Set<Currency> currencies;
2.165 -
2.166 - currencies = new HashSet<Currency>();
2.167 - currencies.add(currencyA);
2.168 - currencies.add(currencyB);
2.169 -
2.170 - return (Collections.unmodifiableSet(currencies));
2.171 + return (rate.getCurrencies());
2.172 }
2.173
2.174 /**
2.175 @@ -189,44 +92,7 @@
2.176 final Currency to)
2.177 throws InvalidConversionException
2.178 {
2.179 - final BigDecimal rate;
2.180 -
2.181 - if(from == null)
2.182 - {
2.183 - throw new IllegalArgumentException("from cannot be null");
2.184 - }
2.185 -
2.186 - if(to == null)
2.187 - {
2.188 - throw new IllegalArgumentException("to cannot be null");
2.189 - }
2.190 -
2.191 - if(from.equals(to))
2.192 - {
2.193 - rate = BigDecimal.ONE;
2.194 - }
2.195 - else
2.196 - {
2.197 - final BigDecimal rateX;
2.198 - final BigDecimal rateY;
2.199 - final BigDecimal temp;
2.200 -
2.201 - if(from.equals(currencyA))
2.202 - {
2.203 - rateX = currencyARate;
2.204 - rateY = currencyBRate;
2.205 - }
2.206 - else
2.207 - {
2.208 - rateX = currencyBRate;
2.209 - rateY = currencyARate;
2.210 - }
2.211 -
2.212 - temp = BigDecimal.ONE.divide(rateX, MathContext.DECIMAL64);
2.213 - rate = temp.multiply(rateY);
2.214 - }
2.215 -
2.216 - return (rate.setScale(20, RoundingMode.HALF_EVEN));
2.217 + return (rate.getConversionRate(from, to));
2.218 }
2.219
2.220 /**
2.221 @@ -250,29 +116,7 @@
2.222
2.223 final ConvertorImpl other = (ConvertorImpl) obj;
2.224
2.225 - // it would be nice if NetBeans could chck to see if the variable is final and guaranteed not to be null... but that
2.226 - // would likely be tricky... but in a NetBeans engineer reads that see if you can do it :-)
2.227 - if (this.currencyA != other.currencyA && (this.currencyA == null || !this.currencyA.equals(other.currencyA)))
2.228 - {
2.229 - return false;
2.230 - }
2.231 -
2.232 - if (this.currencyB != other.currencyB && (this.currencyB == null || !this.currencyB.equals(other.currencyB)))
2.233 - {
2.234 - return false;
2.235 - }
2.236 -
2.237 - if (this.currencyARate != other.currencyARate && (this.currencyARate == null || !this.currencyARate.equals(other.currencyARate)))
2.238 - {
2.239 - return false;
2.240 - }
2.241 -
2.242 - if (this.currencyBRate != other.currencyBRate && (this.currencyBRate == null || !this.currencyBRate.equals(other.currencyBRate)))
2.243 - {
2.244 - return false;
2.245 - }
2.246 -
2.247 - return true;
2.248 + return (rate.equals(other.rate));
2.249 }
2.250
2.251 /**
2.252 @@ -283,12 +127,7 @@
2.253 @Override
2.254 public int hashCode()
2.255 {
2.256 - int hash = 7;
2.257 - hash = 37 * hash + (this.currencyA != null ? this.currencyA.hashCode() : 0);
2.258 - hash = 37 * hash + (this.currencyB != null ? this.currencyB.hashCode() : 0);
2.259 - hash = 37 * hash + (this.currencyARate != null ? this.currencyARate.hashCode() : 0);
2.260 - hash = 37 * hash + (this.currencyBRate != null ? this.currencyBRate.hashCode() : 0);
2.261 - return hash;
2.262 + return (rate.hashCode());
2.263 }
2.264
2.265 /**
2.266 @@ -299,6 +138,11 @@
2.267 @Override
2.268 public String toString()
2.269 {
2.270 - return (currencyA.getCurrencyCode() + " to " + currencyB.getCurrencyCode());
2.271 + return (rate.getCurrencyA().getCurrencyCode() + " to " + rate.getCurrencyB().getCurrencyCode());
2.272 + }
2.273 +
2.274 + public ExchangeRate getExchangeRate()
2.275 + {
2.276 + return (rate);
2.277 }
2.278 }
3.1 --- a/task4/solution04/src/org/apidesign/apifest08/currency/ConvertorFactory.java Fri Oct 17 17:39:18 2008 +0200
3.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/ConvertorFactory.java Fri Oct 17 17:40:14 2008 +0200
3.3 @@ -2,26 +2,17 @@
3.4
3.5 import java.math.BigDecimal;
3.6 import java.util.Currency;
3.7 +import java.util.Date;
3.8
3.9
3.10 /**
3.11 * Create convertors using a flyweight to reduce the number of repetative creations of the same convertor.
3.12 *
3.13 * @author D'Arcy Smith
3.14 - * @version 1.0
3.15 + * @version 1.2
3.16 */
3.17 public final class ConvertorFactory
3.18 {
3.19 - /*
3.20 - * flyweight so that only one vestion of each converter is created at a time.
3.21 - private final static Map<String, WeakReference<Convertor>> convertors;
3.22 -
3.23 - static
3.24 - {
3.25 - convertors = new WeakHashMap<String, WeakReference<Convertor>>();
3.26 - }
3.27 - */
3.28 -
3.29 /**
3.30 * Prevent accidental construction.
3.31 */
3.32 @@ -71,8 +62,8 @@
3.33 final Currency b,
3.34 final BigDecimal bRate)
3.35 {
3.36 - // final String key;
3.37 - Convertor convertor;
3.38 + Convertor convertor;
3.39 + final ExchangeRate rate;
3.40
3.41 if(a == null)
3.42 {
3.43 @@ -94,27 +85,69 @@
3.44 throw new IllegalArgumentException("bRate cannot be null");
3.45 }
3.46
3.47 - /*
3.48 - key = a.getCurrencyCode() + aRate + b.getCurrencyCode() + bRate;
3.49 -
3.50 - // make sure that we don't try to overwrite one
3.51 - synchronized(convertors)
3.52 - {
3.53 - if(!(convertors.containsKey(key)))
3.54 - {
3.55 - convertor = new ConvertorImpl(a, aRate, b, bRate);
3.56 - convertors.put(key, new WeakReference(convertor));
3.57 - }
3.58 -
3.59 - convertor = convertors.get(key).get();
3.60 - }
3.61 - */
3.62 -
3.63 - convertor = new ConvertorImpl(a, aRate, b, bRate);
3.64 + rate = ExchangeRate.getExchangeRate(a, b, aRate, bRate);
3.65 + convertor = getConvertor(rate);
3.66
3.67 return (convertor);
3.68 }
3.69
3.70 + public static Convertor getConvertor(final ExchangeRate rate)
3.71 + {
3.72 + final ConvertorImpl convertor;
3.73 +
3.74 + if(rate == null)
3.75 + {
3.76 + throw new IllegalArgumentException("rate cannot be null");
3.77 + }
3.78 +
3.79 + convertor = new ConvertorImpl(rate);
3.80 +
3.81 + return (convertor);
3.82 + }
3.83 +
3.84 + public static DatedConvertor getConvertor(final Date from,
3.85 + final Date till,
3.86 + final Convertor convertor)
3.87 + {
3.88 + final DateRange range;
3.89 + final ExchangeRate rate;
3.90 + final DatedConvertor datedConvertor;
3.91 +
3.92 + if(from == null)
3.93 + {
3.94 + throw new IllegalArgumentException("from cannot be null");
3.95 + }
3.96 +
3.97 + if(till == null)
3.98 + {
3.99 + throw new IllegalArgumentException("till cannot be null");
3.100 + }
3.101 +
3.102 + if(convertor == null)
3.103 + {
3.104 + throw new IllegalArgumentException("convertor cannot be null");
3.105 + }
3.106 +
3.107 + if(from.after(till))
3.108 + {
3.109 + throw new IllegalArgumentException(from + " cannot be after " + till);
3.110 + }
3.111 +
3.112 + if(convertor instanceof ExchangeRateConvertor)
3.113 + {
3.114 + rate = ((ExchangeRateConvertor)convertor).getExchangeRate();
3.115 + }
3.116 + else
3.117 + {
3.118 + throw new Error();
3.119 + }
3.120 +
3.121 + range = new DateRange(from, till);
3.122 + datedConvertor = new DatedConvertorImpl(range, rate);
3.123 +
3.124 + return (datedConvertor);
3.125 + }
3.126 +
3.127 /**
3.128 *
3.129 * @param cs
3.130 @@ -123,55 +156,38 @@
3.131 public static Convertor mergeConvertors(final Convertor ... cs)
3.132 {
3.133 Convertor convertor;
3.134 -
3.135 - /*
3.136 - final String key;
3.137 + int dated;
3.138 + int nonDated;
3.139
3.140 - // ISSUE: only takes into account the names... not the rates...
3.141 - key = getKey(cs);
3.142 + dated = 0;
3.143 + nonDated = 0;
3.144
3.145 - // make sure that we don't try to overwrite one
3.146 - synchronized(convertors)
3.147 + for(final Convertor c : cs)
3.148 {
3.149 - if(!(convertors.containsKey(key)))
3.150 - {
3.151 - convertor = new CompositeConvertorImpl(cs);
3.152 - convertors.put(key, new WeakReference(convertor));
3.153 + if(c instanceof DatedConvertor)
3.154 + {
3.155 + dated++;
3.156 }
3.157 + else
3.158 + {
3.159 + nonDated++;
3.160 + }
3.161 + }
3.162
3.163 - convertor = convertors.get(key).get();
3.164 + if(dated != 0 && nonDated != 0)
3.165 + {
3.166 + throw new IllegalArgumentException("cannot mix DatedConvertors and non-DatedConvertors");
3.167 }
3.168 - */
3.169 -
3.170 - convertor = new CompositeConvertorImpl(cs);
3.171 -
3.172 +
3.173 + if(dated != 0)
3.174 + {
3.175 + convertor = new DatedCompositeConvertorImpl(cs);
3.176 + }
3.177 + else
3.178 + {
3.179 + convertor = new CompositeConvertorImpl(cs);
3.180 + }
3.181 +
3.182 return (convertor);
3.183 }
3.184 -
3.185 - /*
3.186 - private static String getKey(final Convertor ... cs)
3.187 - {
3.188 - final Set<Currency> currencies;
3.189 - final StringBuilder builder;
3.190 -
3.191 - currencies = new HashSet<Currency>();
3.192 -
3.193 - for(final Convertor convertor : cs)
3.194 - {
3.195 - final Set<Currency> c;
3.196 -
3.197 - c = convertor.getCurrencies();
3.198 - currencies.addAll(c);
3.199 - }
3.200 -
3.201 - builder = new StringBuilder();
3.202 -
3.203 - for(final Currency currency : currencies)
3.204 - {
3.205 - builder.append(currency.getCurrencyCode());
3.206 - }
3.207 -
3.208 - return (builder.toString());
3.209 - }
3.210 - */
3.211 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/DateRange.java Fri Oct 17 17:40:14 2008 +0200
4.3 @@ -0,0 +1,91 @@
4.4 +package org.apidesign.apifest08.currency;
4.5 +
4.6 +
4.7 +import java.util.Date;
4.8 +
4.9 +
4.10 +public final class DateRange
4.11 +{
4.12 + private final Date from;
4.13 + private final Date till;
4.14 +
4.15 + DateRange(final Date f,
4.16 + final Date t)
4.17 + {
4.18 + if(f == null && t != null)
4.19 + {
4.20 + throw new IllegalArgumentException("f was null but t was not");
4.21 + }
4.22 +
4.23 + if(f != null && t == null)
4.24 + {
4.25 + throw new IllegalArgumentException("f was null but t was not");
4.26 + }
4.27 +
4.28 + from = f;
4.29 + till = t;
4.30 + }
4.31 +
4.32 + public Date getFrom()
4.33 + {
4.34 + return (from);
4.35 + }
4.36 +
4.37 + public Date getTill()
4.38 + {
4.39 + return (from);
4.40 + }
4.41 +
4.42 + public boolean isInRange(final Date date)
4.43 + {
4.44 + final boolean retVal;
4.45 +
4.46 + if(date.equals(from) || date.equals(till))
4.47 + {
4.48 + retVal = true;
4.49 + }
4.50 + else if(date.after(from) && date.before(till))
4.51 + {
4.52 + retVal = true;
4.53 + }
4.54 + else
4.55 + {
4.56 + retVal = false;
4.57 + }
4.58 +
4.59 + return (retVal);
4.60 + }
4.61 +
4.62 + @Override
4.63 + public boolean equals(Object obj) {
4.64 + if (obj == null) {
4.65 + return false;
4.66 + }
4.67 + if (getClass() != obj.getClass()) {
4.68 + return false;
4.69 + }
4.70 + final DateRange other = (DateRange) obj;
4.71 + if (this.from != other.from && (this.from == null || !this.from.equals(other.from))) {
4.72 + return false;
4.73 + }
4.74 + if (this.till != other.till && (this.till == null || !this.till.equals(other.till))) {
4.75 + return false;
4.76 + }
4.77 + return true;
4.78 + }
4.79 +
4.80 + @Override
4.81 + public int hashCode() {
4.82 + int hash = 7;
4.83 + hash = 89 * hash + (this.from != null ? this.from.hashCode() : 0);
4.84 + hash = 89 * hash + (this.till != null ? this.till.hashCode() : 0);
4.85 + return hash;
4.86 + }
4.87 +
4.88 + @Override
4.89 + public String toString()
4.90 + {
4.91 + return (from + " until " + till);
4.92 + }
4.93 +
4.94 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/DatedCompositeConvertorImpl.java Fri Oct 17 17:40:14 2008 +0200
5.3 @@ -0,0 +1,319 @@
5.4 +package org.apidesign.apifest08.currency;
5.5 +
5.6 +import java.math.BigDecimal;
5.7 +import java.util.Currency;
5.8 +import java.util.Date;
5.9 +import java.util.HashMap;
5.10 +import java.util.Map;
5.11 +import java.util.Set;
5.12 +
5.13 +
5.14 +final class DatedCompositeConvertorImpl
5.15 + implements TimedConvertor
5.16 +{
5.17 + /**
5.18 + * The convertors that are supported.
5.19 + */
5.20 + private final DatedConvertor[] convertors;
5.21 +
5.22 + /**
5.23 + * Keeps track of what convertors to use to convert between currencies.
5.24 + */
5.25 + private final Map<DateRange, Map<Currency, Map<Currency, Convertor>>> datedConversions;
5.26 +
5.27 + {
5.28 + datedConversions = new HashMap<DateRange, Map<Currency, Map<Currency, Convertor>>>();
5.29 + }
5.30 +
5.31 + /**
5.32 + * Construct a ComositeConvertorImpl with the specified convertors.
5.33 + * This will result in all possible conversions between the supplied currencies being made.
5.34 + *
5.35 + * @param cs the convertors to use.
5.36 + * @throws IllegalArgumentException if any of the items in cs are null.
5.37 + */
5.38 + DatedCompositeConvertorImpl(Convertor ... cs)
5.39 + {
5.40 + int i;
5.41 +
5.42 + convertors = new DatedConvertor[cs.length];
5.43 + i = 0;
5.44 +
5.45 + for(final Convertor c : cs)
5.46 + {
5.47 + if(!(c instanceof DatedConvertor))
5.48 + {
5.49 + throw new IllegalArgumentException("cs must only contain DatedConvertors");
5.50 + }
5.51 +
5.52 + convertors[i] = (DatedConvertor)c;
5.53 + i++;
5.54 + }
5.55 +
5.56 + // track all of the known conversion
5.57 + for(final DatedConvertor convertor : convertors)
5.58 + {
5.59 + final Set<Currency> currencies;
5.60 + Map<Currency, Convertor> possible;
5.61 + DateRange range;
5.62 +
5.63 + if(convertor == null)
5.64 + {
5.65 + throw new IllegalArgumentException("cs cannot contain null");
5.66 + }
5.67 +
5.68 + currencies = convertor.getCurrencies();
5.69 + range = convertor.getDateRange();
5.70 +
5.71 + for(final Currency currency : currencies)
5.72 + {
5.73 + Map<Currency, Map<Currency, Convertor>> possibleConversions;
5.74 +
5.75 + possibleConversions = datedConversions.get(range);
5.76 +
5.77 + if(possibleConversions == null)
5.78 + {
5.79 + possibleConversions = new HashMap<Currency, Map<Currency, Convertor>>();
5.80 + datedConversions.put(range, possibleConversions);
5.81 + }
5.82 +
5.83 + possible = possibleConversions.get(currency);
5.84 +
5.85 + if(possible == null)
5.86 + {
5.87 + possible = new HashMap<Currency, Convertor>();
5.88 + possibleConversions.put(currency, possible);
5.89 + }
5.90 +
5.91 + for(final Currency c : currencies)
5.92 + {
5.93 + possible.put(c, convertor);
5.94 + }
5.95 + }
5.96 + }
5.97 +
5.98 +
5.99 + /*
5.100 + // make up conversions that can be derived... eg:
5.101 + // we have:
5.102 + // USD <-> CAD
5.103 + // CAD <-> CZK
5.104 + // SSK <-> GBP
5.105 + // we can derive:
5.106 + // USD <-> CZK
5.107 + // we cannot derive:
5.108 + // USD <-> GBP
5.109 + // CAD <-> GBP
5.110 + // CZK <-> GBP
5.111 + //
5.112 + // NOTE: no attempt is made to deal with dates for DatedConvertors... nothing we can do about it.
5.113 + do
5.114 + {
5.115 + newConvertors = 0;
5.116 +
5.117 + // todo... need to loop this until all the ones that can be handled are done.
5.118 + for(final Currency from : getCurrencies())
5.119 + {
5.120 + for(final Currency to : getCurrencies())
5.121 + {
5.122 + if(!(canConvert(from, to)))
5.123 + {
5.124 + final Set<Currency> fromCurrencies;
5.125 + final Set<Currency> toCurrencies;
5.126 + final Set<Currency> common;
5.127 + Map<Currency, Map<Currency, Convertor>> possibleConversions;
5.128 +
5.129 + possibleConversions.get(range);
5.130 + fromCurrencies = possibleConversions.get(from).keySet();
5.131 + toCurrencies = possibleConversions.get(to).keySet();
5.132 + common = new HashSet<Currency>();
5.133 +
5.134 + for(final Currency currency : fromCurrencies)
5.135 + {
5.136 + if(toCurrencies.contains(currency))
5.137 + {
5.138 + common.add(currency);
5.139 + }
5.140 + }
5.141 +
5.142 + for(final Currency currency : common)
5.143 + {
5.144 + final Convertor convertor;
5.145 +
5.146 + convertor = createConvertor(from, to, currency);
5.147 + possibleConversions.get(from).put(to, convertor);
5.148 + possibleConversions.get(to).put(from, convertor);
5.149 + newConvertors++;
5.150 + }
5.151 + }
5.152 + }
5.153 + }
5.154 + }
5.155 + while(newConvertors > 0);
5.156 + */
5.157 + }
5.158 +
5.159 + /**
5.160 + * Check to see if converting between the two currencies is possible.
5.161 + *
5.162 + * @param from the currency to convert from.
5.163 + * @param to the currency to convert to.
5.164 + * @return true if the conversion is possible.
5.165 + * @throws IllegalArgumentException if either from or to are null.
5.166 + */
5.167 + public boolean canConvert(final Currency from, final Currency to)
5.168 + {
5.169 + throw new UnsupportedOperationException();
5.170 + }
5.171 +
5.172 + /**
5.173 + * Get the currencies that the convertor supports. Just because a currency is
5.174 + * supported does not mean that canConvert will return true.
5.175 + *
5.176 + * @return the supported currencies.
5.177 + */
5.178 + public Set<Currency> getCurrencies()
5.179 + {
5.180 + throw new UnsupportedOperationException();
5.181 + }
5.182 +
5.183 + /**
5.184 + * Get the conversion rate between two currencies.
5.185 + *
5.186 + * @param from the currency to convert from.
5.187 + * @param to the currency to convert to.
5.188 + * @return the conversion rate between the two currencies.
5.189 + * @throws IllegalArgumentException if either from or to is null.
5.190 + * @throws InvalidConversionException if canConvert would return false.
5.191 + */
5.192 + public BigDecimal getConversionRate(final Currency from, final Currency to)
5.193 + throws InvalidConversionException
5.194 + {
5.195 + throw new UnsupportedOperationException();
5.196 + }
5.197 +
5.198 + private Convertor getConvertor(final Currency from, final Currency to, final Date date)
5.199 + {
5.200 + Map<Currency, Map<Currency, Convertor>> possibleConversions;
5.201 + final Map<Currency, Convertor> possible;
5.202 + Convertor convertor;
5.203 +
5.204 + if(from == null)
5.205 + {
5.206 + throw new IllegalArgumentException("from cannot be null");
5.207 + }
5.208 +
5.209 + if(to == null)
5.210 + {
5.211 + throw new IllegalArgumentException("to cannot be null");
5.212 + }
5.213 +
5.214 + possibleConversions = null;
5.215 +
5.216 + for(final DateRange range : datedConversions.keySet())
5.217 + {
5.218 + if(range.isInRange(date))
5.219 + {
5.220 + possibleConversions = datedConversions.get(range);
5.221 + break;
5.222 + }
5.223 + }
5.224 +
5.225 + if(possibleConversions == null)
5.226 + {
5.227 + return (null);
5.228 + }
5.229 +
5.230 + possible = possibleConversions.get(from);
5.231 +
5.232 +
5.233 + if(possible == null)
5.234 + {
5.235 + return (null);
5.236 + }
5.237 +
5.238 +
5.239 + convertor = possible.get(to);
5.240 +
5.241 +
5.242 + if(convertor == null)
5.243 + {
5.244 + return (null);
5.245 + }
5.246 +
5.247 + return (convertor);
5.248 + }
5.249 +
5.250 + /**
5.251 + * Convert an amount from one currency to another.
5.252 + *
5.253 + * @param from the currency to convert from.
5.254 + * @param to the currency to convert to.
5.255 + * @param amount the amount to convert.
5.256 + * @return the converted amount.
5.257 + * @throws IllegalArgumentException if any of the arguments are null.
5.258 + * @throws InvalidConversionException if either from or to are not valid for the convertor.
5.259 + */
5.260 + public BigDecimal convert(final Currency from,
5.261 + final Currency to,
5.262 + final BigDecimal amount)
5.263 + throws InvalidConversionException
5.264 + {
5.265 + throw new InvalidConversionException("No date for the conversion", from);
5.266 + }
5.267 +
5.268 + public BigDecimal convert(final Currency from,
5.269 + final Currency to,
5.270 + final BigDecimal amount,
5.271 + final Date date)
5.272 + throws InvalidConversionException
5.273 + {
5.274 + final Convertor convertor;
5.275 + final BigDecimal total;
5.276 +
5.277 + convertor = getConvertor(from, to, date);
5.278 +
5.279 + if(convertor == null)
5.280 + {
5.281 + throw new InvalidConversionException("cannot convert", from);
5.282 + }
5.283 +
5.284 + if(canConvert(from, to, date))
5.285 + {
5.286 + final TimedConvertor timeConvertor;
5.287 +
5.288 + timeConvertor = (TimedConvertor)convertor;
5.289 + total = timeConvertor.convert(from, to, amount, date);
5.290 + }
5.291 + else
5.292 + {
5.293 + throw new InvalidConversionException("cannot convert", from);
5.294 + }
5.295 +
5.296 + return (total);
5.297 + }
5.298 +
5.299 + public boolean canConvert(final Currency from,
5.300 + final Currency to,
5.301 + final Date date)
5.302 + {
5.303 + Convertor convertor;
5.304 + final boolean retVal;
5.305 +
5.306 + convertor = getConvertor(from, to, date);
5.307 +
5.308 + if(convertor != null)
5.309 + {
5.310 + final TimedConvertor timeConvertor;
5.311 +
5.312 + timeConvertor = (TimedConvertor)convertor;
5.313 + retVal = timeConvertor.canConvert(from, to, date);
5.314 + }
5.315 + else
5.316 + {
5.317 + retVal = false;
5.318 + }
5.319 +
5.320 + return (retVal);
5.321 + }
5.322 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/DatedConvertor.java Fri Oct 17 17:40:14 2008 +0200
6.3 @@ -0,0 +1,9 @@
6.4 +package org.apidesign.apifest08.currency;
6.5 +
6.6 +
6.7 +public interface DatedConvertor
6.8 + extends ExchangeRateConvertor,
6.9 + TimedConvertor
6.10 +{
6.11 + DateRange getDateRange();
6.12 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/DatedConvertorImpl.java Fri Oct 17 17:40:14 2008 +0200
7.3 @@ -0,0 +1,82 @@
7.4 +package org.apidesign.apifest08.currency;
7.5 +
7.6 +import java.math.BigDecimal;
7.7 +import java.util.Currency;
7.8 +import java.util.Date;
7.9 +
7.10 +
7.11 +final class DatedConvertorImpl
7.12 + extends ConvertorImpl
7.13 + implements DatedConvertor
7.14 +{
7.15 + private final DateRange range;
7.16 +
7.17 + DatedConvertorImpl(final DateRange rng,
7.18 + final ExchangeRate r)
7.19 + {
7.20 + super(r);
7.21 +
7.22 + if(rng == null)
7.23 + {
7.24 + throw new IllegalArgumentException("rng cannot be null");
7.25 + }
7.26 +
7.27 + range = rng;
7.28 + }
7.29 +
7.30 + public DateRange getDateRange()
7.31 + {
7.32 + return (range);
7.33 + }
7.34 +
7.35 + @Override
7.36 + public BigDecimal convert(final Currency from,
7.37 + final Currency to,
7.38 + final BigDecimal amount)
7.39 + throws InvalidConversionException
7.40 + {
7.41 + final BigDecimal total;
7.42 +
7.43 + total = convert(from, to, amount, new Date(System.currentTimeMillis()));
7.44 +
7.45 + return (total);
7.46 + }
7.47 +
7.48 + public BigDecimal convert(final Currency from,
7.49 + final Currency to,
7.50 + final BigDecimal amount,
7.51 + final Date date)
7.52 + throws InvalidConversionException
7.53 + {
7.54 + final BigDecimal total;
7.55 +
7.56 + if(range.isInRange(date))
7.57 + {
7.58 + total = super.convert(from, to, amount);
7.59 + }
7.60 + else
7.61 + {
7.62 + throw new InvalidConversionException("cannot convert for date", from);
7.63 + }
7.64 +
7.65 + return (total);
7.66 + }
7.67 +
7.68 + public boolean canConvert(final Currency from,
7.69 + final Currency to,
7.70 + final Date date)
7.71 + {
7.72 + final boolean retVal;
7.73 +
7.74 + if(canConvert(from, to))
7.75 + {
7.76 + retVal = range.isInRange(date);
7.77 + }
7.78 + else
7.79 + {
7.80 + retVal = false;
7.81 + }
7.82 +
7.83 + return (retVal);
7.84 + }
7.85 +}
8.1 --- a/task4/solution04/src/org/apidesign/apifest08/currency/ExchangeRate.java Fri Oct 17 17:39:18 2008 +0200
8.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/ExchangeRate.java Fri Oct 17 17:40:14 2008 +0200
8.3 @@ -2,14 +2,18 @@
8.4
8.5
8.6 import java.math.BigDecimal;
8.7 +import java.math.RoundingMode;
8.8 +import java.util.Collections;
8.9 import java.util.Currency;
8.10 +import java.util.HashSet;
8.11 +import java.util.Set;
8.12
8.13
8.14 /**
8.15 * The exchange rate between two currencies.
8.16 *
8.17 * @author D'Arcy Smith
8.18 - * @version 1.0
8.19 + * @version 1.1
8.20 */
8.21 public final class ExchangeRate
8.22 {
8.23 @@ -122,4 +126,201 @@
8.24 {
8.25 return rateBtoA;
8.26 }
8.27 +
8.28 + public static ExchangeRate getExchangeRate(final Currency a,
8.29 + final Currency b,
8.30 + final BigDecimal va,
8.31 + final BigDecimal vb)
8.32 + {
8.33 + final BigDecimal rateAtoB;
8.34 + final BigDecimal rateBtoA;
8.35 + final ExchangeRate rate;
8.36 +
8.37 + if(a == null)
8.38 + {
8.39 + throw new IllegalArgumentException("a cannot be null");
8.40 + }
8.41 +
8.42 + if(b == null)
8.43 + {
8.44 + throw new IllegalArgumentException("b cannot be null");
8.45 + }
8.46 +
8.47 + if(a.equals(b))
8.48 + {
8.49 + rateAtoB = BigDecimal.ONE;
8.50 + rateBtoA = BigDecimal.ONE;
8.51 + }
8.52 + else
8.53 + {
8.54 + rateAtoB = vb.divide(va, 20, RoundingMode.HALF_DOWN);
8.55 + rateBtoA = va.divide(vb, 20, RoundingMode.HALF_DOWN);
8.56 + }
8.57 +
8.58 + rate = new ExchangeRate(a,
8.59 + b,
8.60 + rateAtoB.setScale(20, RoundingMode.HALF_EVEN),
8.61 + rateBtoA.setScale(20, RoundingMode.HALF_EVEN));
8.62 +
8.63 + return (rate);
8.64 + }
8.65 +
8.66 + public BigDecimal convert(final Currency from,
8.67 + final Currency to,
8.68 + final BigDecimal amount)
8.69 + throws InvalidConversionException
8.70 + {
8.71 + final BigDecimal result;
8.72 +
8.73 + if(amount == null)
8.74 + {
8.75 + throw new IllegalArgumentException("amount cannot be null");
8.76 + }
8.77 +
8.78 + if(from == null)
8.79 + {
8.80 + throw new IllegalArgumentException("from cannot be null");
8.81 + }
8.82 +
8.83 + if(to == null)
8.84 + {
8.85 + throw new IllegalArgumentException("to cannot be null");
8.86 + }
8.87 +
8.88 + if(!(from.equals(currencyA)) && (!(from.equals(currencyB))))
8.89 + {
8.90 + throw new InvalidConversionException("cannot convert from: " + from.getCurrencyCode(), from, currencyA, currencyB);
8.91 + }
8.92 +
8.93 + if(!(to.equals(currencyA)) && (!(to.equals(currencyB))))
8.94 + {
8.95 + throw new InvalidConversionException("cannot convert to: " + to.getCurrencyCode(), to, currencyA, currencyB);
8.96 + }
8.97 +
8.98 + result = amount.multiply(getConversionRate(from, to));
8.99 +
8.100 + return (result.setScale(2, RoundingMode.HALF_DOWN));
8.101 + }
8.102 +
8.103 + /**
8.104 + * Check to see if converting between the two currencies is possible.
8.105 + *
8.106 + * @param from the currency to convert from.
8.107 + * @param to the currency to convert to.
8.108 + * @return true if the conversion is possible.
8.109 + * @throws IllegalArgumentException if either from or to are null.
8.110 + */
8.111 + public boolean canConvert(final Currency from, final Currency to)
8.112 + {
8.113 + if(from == null)
8.114 + {
8.115 + throw new IllegalArgumentException("from cannot be null");
8.116 + }
8.117 +
8.118 + if(to == null)
8.119 + {
8.120 + throw new IllegalArgumentException("to cannot be null");
8.121 + }
8.122 +
8.123 + return ((from.equals(currencyA) || from.equals(currencyB)) &&
8.124 + (to.equals(currencyA) || to.equals(currencyB)));
8.125 + }
8.126 + /**
8.127 + * Get the currencies that the convertor supports.
8.128 + *
8.129 + * @return the supported currencies.
8.130 + */
8.131 + public Set<Currency> getCurrencies()
8.132 + {
8.133 + final Set<Currency> currencies;
8.134 +
8.135 + currencies = new HashSet<Currency>();
8.136 + currencies.add(currencyA);
8.137 + currencies.add(currencyB);
8.138 +
8.139 + return (Collections.unmodifiableSet(currencies));
8.140 + }
8.141 +
8.142 + /**
8.143 + * Get the conversion rate between two currencies.
8.144 + *
8.145 + * @param from the currency to convert from.
8.146 + * @param to the currency to convert to.
8.147 + * @return the conversion rate between the two currencies.
8.148 + * @throws InvalidConversionException if canConvert would return false.
8.149 + * @throws IllegalArgumentException if either from or to are null.
8.150 + */
8.151 + public BigDecimal getConversionRate(final Currency from,
8.152 + final Currency to)
8.153 + throws InvalidConversionException
8.154 + {
8.155 + final BigDecimal rate;
8.156 +
8.157 + if(from == null)
8.158 + {
8.159 + throw new IllegalArgumentException("from cannot be null");
8.160 + }
8.161 +
8.162 + if(to == null)
8.163 + {
8.164 + throw new IllegalArgumentException("to cannot be null");
8.165 + }
8.166 +
8.167 + if(from.equals(to))
8.168 + {
8.169 + rate = BigDecimal.ONE;
8.170 + }
8.171 + else
8.172 + {
8.173 + if(from.equals(currencyA))
8.174 + {
8.175 + rate = rateAtoB;
8.176 + }
8.177 + else
8.178 + {
8.179 + rate = rateBtoA;
8.180 + }
8.181 + }
8.182 +
8.183 + return (rate);
8.184 + }
8.185 +
8.186 + public String toString()
8.187 + {
8.188 + return (rateAtoB + " : " + rateBtoA);
8.189 + }
8.190 +
8.191 + @Override
8.192 + public boolean equals(Object obj) {
8.193 + if (obj == null) {
8.194 + return false;
8.195 + }
8.196 + if (getClass() != obj.getClass()) {
8.197 + return false;
8.198 + }
8.199 + final ExchangeRate other = (ExchangeRate) obj;
8.200 + if (this.currencyA != other.currencyA && (this.currencyA == null || !this.currencyA.equals(other.currencyA))) {
8.201 + return false;
8.202 + }
8.203 + if (this.currencyB != other.currencyB && (this.currencyB == null || !this.currencyB.equals(other.currencyB))) {
8.204 + return false;
8.205 + }
8.206 + if (this.rateAtoB != other.rateAtoB && (this.rateAtoB == null || !this.rateAtoB.equals(other.rateAtoB))) {
8.207 + return false;
8.208 + }
8.209 + if (this.rateBtoA != other.rateBtoA && (this.rateBtoA == null || !this.rateBtoA.equals(other.rateBtoA))) {
8.210 + return false;
8.211 + }
8.212 + return true;
8.213 + }
8.214 +
8.215 + @Override
8.216 + public int hashCode() {
8.217 + int hash = 7;
8.218 + hash = 97 * hash + (this.currencyA != null ? this.currencyA.hashCode() : 0);
8.219 + hash = 97 * hash + (this.currencyB != null ? this.currencyB.hashCode() : 0);
8.220 + hash = 97 * hash + (this.rateAtoB != null ? this.rateAtoB.hashCode() : 0);
8.221 + hash = 97 * hash + (this.rateBtoA != null ? this.rateBtoA.hashCode() : 0);
8.222 + return hash;
8.223 + }
8.224 }
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/ExchangeRateConvertor.java Fri Oct 17 17:40:14 2008 +0200
9.3 @@ -0,0 +1,8 @@
9.4 +package org.apidesign.apifest08.currency;
9.5 +
9.6 +
9.7 +public interface ExchangeRateConvertor
9.8 + extends Convertor
9.9 +{
9.10 + ExchangeRate getExchangeRate();
9.11 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/task4/solution04/src/org/apidesign/apifest08/currency/TimedConvertor.java Fri Oct 17 17:40:14 2008 +0200
10.3 @@ -0,0 +1,17 @@
10.4 +package org.apidesign.apifest08.currency;
10.5 +
10.6 +import java.math.BigDecimal;
10.7 +import java.util.Currency;
10.8 +import java.util.Date;
10.9 +
10.10 +
10.11 +public interface TimedConvertor
10.12 + extends Convertor
10.13 +{
10.14 + BigDecimal convert(Currency from,
10.15 + Currency to,
10.16 + BigDecimal amount,
10.17 + Date date)
10.18 + throws InvalidConversionException;
10.19 + boolean canConvert(Currency from, Currency to, Date date);
10.20 +}
10.21 \ No newline at end of file
11.1 --- a/task4/solution04/test/org/apidesign/apifest08/test/Task1Test.java Fri Oct 17 17:39:18 2008 +0200
11.2 +++ b/task4/solution04/test/org/apidesign/apifest08/test/Task1Test.java Fri Oct 17 17:40:14 2008 +0200
11.3 @@ -18,9 +18,9 @@
11.4 */
11.5 public class Task1Test extends TestCase {
11.6
11.7 - private final static Currency CZK;
11.8 - private final static Currency SKK;
11.9 - private final static Currency USD;
11.10 + public final static Currency CZK;
11.11 + public final static Currency SKK;
11.12 + public final static Currency USD;
11.13
11.14 static
11.15 {
12.1 --- a/task4/solution04/test/org/apidesign/apifest08/test/Task4Test.java Fri Oct 17 17:39:18 2008 +0200
12.2 +++ b/task4/solution04/test/org/apidesign/apifest08/test/Task4Test.java Fri Oct 17 17:40:14 2008 +0200
12.3 @@ -1,8 +1,15 @@
12.4 package org.apidesign.apifest08.test;
12.5
12.6 +import java.math.BigDecimal;
12.7 +import java.util.Calendar;
12.8 import java.util.Date;
12.9 +import java.util.TimeZone;
12.10 import junit.framework.TestCase;
12.11 import org.apidesign.apifest08.currency.Convertor;
12.12 +import org.apidesign.apifest08.currency.ConvertorFactory;
12.13 +import org.apidesign.apifest08.currency.ExchangeRate;
12.14 +import org.apidesign.apifest08.currency.InvalidConversionException;
12.15 +import org.apidesign.apifest08.currency.TimedConvertor;
12.16
12.17 /** The exchange rates are not always the same. They are changing. However
12.18 * as in order to predict the future, one needs to understand own past. That is
12.19 @@ -22,8 +29,11 @@
12.20 super(testName);
12.21 }
12.22
12.23 + private Calendar gmtCalendar;
12.24 +
12.25 @Override
12.26 protected void setUp() throws Exception {
12.27 + gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
12.28 }
12.29
12.30 @Override
12.31 @@ -45,57 +55,133 @@
12.32 * @return new convertor
12.33 */
12.34 public static Convertor limitTo(Convertor old, Date from, Date till) {
12.35 - return null;
12.36 + final Convertor convertor;
12.37 +
12.38 + convertor = ConvertorFactory.getConvertor(from, till, old);
12.39 +
12.40 + return convertor;
12.41 }
12.42
12.43
12.44 public void testCompositionOfLimitedConvertors() throws Exception {
12.45 - if (Boolean.getBoolean("ignore.failing")) {
12.46 - // implement me! then delete this if statement
12.47 - return;
12.48 - }
12.49
12.50 - Date d1 = null; // 2008-10-01 0:00 GMT
12.51 - Date d2 = null; // 2008-10-02 0:00 GMT
12.52 - Date d3 = null; // 2008-10-03 0:00 GMT
12.53 + gmtCalendar.set(2008, Calendar.OCTOBER, 1, 0, 0, 0);
12.54 + Date d1 = gmtCalendar.getTime(); // 2008-10-01 0:00 GMT
12.55 + gmtCalendar.set(2008, Calendar.OCTOBER, 2, 0, 0, 0);
12.56 + Date d2 = gmtCalendar.getTime(); // 2008-10-02 0:00 GMT
12.57 + gmtCalendar.set(2008, Calendar.OCTOBER, 3, 0, 0, 0);
12.58 + Date d3 = gmtCalendar.getTime(); // 2008-10-03 0:00 GMT
12.59
12.60 Convertor c = Task2Test.merge(
12.61 limitTo(Task1Test.createCZKtoUSD(), d1, d2),
12.62 limitTo(Task1Test.createSKKtoCZK(), d2, d3)
12.63 );
12.64
12.65 + Date date;
12.66 + BigDecimal amount;
12.67 +
12.68 // convert $5 to CZK using c:
12.69 // cannot convert as no rate is applicable to current date
12.70 + try
12.71 + {
12.72 + c.convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("5.00"));
12.73 + fail("test A");
12.74 + }
12.75 + catch(final InvalidConversionException ex)
12.76 + {
12.77 + }
12.78
12.79 // convert $8 to CZK using c:
12.80 // cannot convert as no rate is applicable to current date
12.81 + try
12.82 + {
12.83 + c.convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("8.00"));
12.84 + fail("test B");
12.85 + }
12.86 + catch(final InvalidConversionException ex)
12.87 + {
12.88 + }
12.89
12.90 // convert 1003CZK to USD using c:
12.91 // cannot convert as no rate is applicable to current date
12.92 + try
12.93 + {
12.94 + c.convert(Task1Test.CZK, Task1Test.USD, new BigDecimal("1003.00"));
12.95 + fail("test C");
12.96 + }
12.97 + catch(final InvalidConversionException ex)
12.98 + {
12.99 + }
12.100
12.101 // convert 16CZK using c:
12.102 // cannot convert as no rate is applicable to current date
12.103 + try
12.104 + {
12.105 + c.convert(Task1Test.CZK, Task1Test.USD, new BigDecimal("16.00"));
12.106 + fail("test D");
12.107 + }
12.108 + catch(final InvalidConversionException ex)
12.109 + {
12.110 + }
12.111
12.112 // convert 500SKK to CZK using c:
12.113 // cannot convert as no rate is applicable to current date
12.114 + try
12.115 + {
12.116 + c.convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"));
12.117 + fail("test C");
12.118 + }
12.119 + catch(final InvalidConversionException ex)
12.120 + {
12.121 + }
12.122
12.123 // convert $5 to CZK using c at 2008-10-01 6:00 GMT:
12.124 // assertEquals("Result is 85 CZK");
12.125 + gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
12.126 + date = gmtCalendar.getTime();
12.127 + amount = ((TimedConvertor)c).convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("5.00"), date);
12.128 + assertEquals(new BigDecimal("85.00"), amount);
12.129
12.130 // convert $8 to CZK using c at 2008-10-01 6:00 GMT:
12.131 // assertEquals("Result is 136 CZK");
12.132 + gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
12.133 + date = gmtCalendar.getTime();
12.134 + amount = ((TimedConvertor)c).convert(Task1Test.USD, Task1Test.CZK, new BigDecimal("8.00"), date);
12.135 + assertEquals(new BigDecimal("136.00"), amount);
12.136
12.137 // convert 1003CZK to USD using c at 2008-10-01 6:00 GMT:
12.138 // assertEquals("Result is 59 USD");
12.139 + gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
12.140 + date = gmtCalendar.getTime();
12.141 + amount = ((TimedConvertor)c).convert(Task1Test.CZK, Task1Test.USD, new BigDecimal("1003.00"), date);
12.142 + assertEquals(new BigDecimal("59.00"), amount);
12.143
12.144 // convert 16CZK using c at 2008-10-02 9:00 GMT:
12.145 // assertEquals("Result is 20 SKK");
12.146 + gmtCalendar.set(2008, Calendar.OCTOBER, 2, 9, 0, 0);
12.147 + date = gmtCalendar.getTime();
12.148 + amount = ((TimedConvertor)c).convert(Task1Test.CZK, Task1Test.SKK, new BigDecimal("16.00"), date);
12.149 + assertEquals(new BigDecimal("20.00"), amount);
12.150
12.151 // convert 500SKK to CZK using c at 2008-10-02 9:00 GMT:
12.152 // assertEquals("Result is 400 CZK");
12.153 + gmtCalendar.set(2008, Calendar.OCTOBER, 2, 9, 0, 0);
12.154 + date = gmtCalendar.getTime();
12.155 + amount = ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
12.156 + assertEquals(new BigDecimal("400.00"), amount);
12.157
12.158 // convert 500SKK to CZK using c at 2008-10-01 6:00 GMT:
12.159 // cannot convert as no rate is applicable to current date
12.160 + try
12.161 + {
12.162 + gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
12.163 + date = gmtCalendar.getTime();
12.164 + ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
12.165 + fail("test D");
12.166 + }
12.167 + catch(final InvalidConversionException ex)
12.168 + {
12.169 + }
12.170 }
12.171
12.172 /** Create convertor that understands two currencies, CZK and
12.173 @@ -103,30 +189,49 @@
12.174 *
12.175 * @return prepared convertor ready for converting SKK to CZK and CZK to SKK
12.176 */
12.177 - public static Convertor createSKKtoCZK2() {
12.178 - return null;
12.179 + public static Convertor createSKKtoCZK2()
12.180 + {
12.181 + final ExchangeRate rate;
12.182 + final Convertor convertor;
12.183 +
12.184 + rate = ExchangeRate.getExchangeRate(Task1Test.SKK,
12.185 + Task1Test.CZK,
12.186 + new BigDecimal("100.00"),
12.187 + new BigDecimal("90.00"));
12.188 + convertor = ConvertorFactory.getConvertor(rate);
12.189 +
12.190 + return (convertor);
12.191 }
12.192
12.193 public void testDateConvetorWithTwoDifferentRates() throws Exception {
12.194 - if (Boolean.getBoolean("ignore.failing")) {
12.195 - // implement me! then delete this if statement
12.196 - return;
12.197 - }
12.198 -
12.199 - Date d1 = null; // 2008-10-01 0:00 GMT
12.200 - Date d2 = null; // 2008-10-02 0:00 GMT
12.201 - Date d3 = null; // 2008-10-03 0:00 GMT
12.202 + gmtCalendar.set(2008, Calendar.OCTOBER, 1, 0, 0, 0);
12.203 + Date d1 = gmtCalendar.getTime(); // 2008-10-01 0:00 GMT
12.204 + gmtCalendar.set(2008, Calendar.OCTOBER, 2, 0, 0, 0);
12.205 + Date d2 = gmtCalendar.getTime(); // 2008-10-02 0:00 GMT
12.206 + gmtCalendar.set(2008, Calendar.OCTOBER, 3, 0, 0, 0);
12.207 + Date d3 = gmtCalendar.getTime(); // 2008-10-03 0:00 GMT
12.208
12.209 Convertor c = Task2Test.merge(
12.210 limitTo(createSKKtoCZK2(), d1, d2),
12.211 limitTo(Task1Test.createSKKtoCZK(), d2, d3)
12.212 );
12.213
12.214 + Date date;
12.215 + BigDecimal amount;
12.216 +
12.217 // convert 500SKK to CZK using c at 2008-10-02 9:00 GMT:
12.218 // assertEquals("Result is 400 CZK");
12.219 + gmtCalendar.set(2008, Calendar.OCTOBER, 2, 6, 0, 0);
12.220 + date = gmtCalendar.getTime();
12.221 + amount = ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
12.222 + assertEquals(new BigDecimal("400.00"), amount);
12.223
12.224 // convert 500SKK to CZK using c at 2008-10-01 6:00 GMT:
12.225 // assertEquals("Result is 450 CZK");
12.226 + gmtCalendar.set(2008, Calendar.OCTOBER, 1, 6, 0, 0);
12.227 + date = gmtCalendar.getTime();
12.228 + amount = ((TimedConvertor)c).convert(Task1Test.SKK, Task1Test.CZK, new BigDecimal("500.00"), date);
12.229 + assertEquals(new BigDecimal("450.00"), amount);
12.230 }
12.231
12.232 }