package junit.samples.money; import java.util.ArrayList; import java.util.List; /** * A MoneyBag defers exchange rate conversions. For example adding * 12 Swiss Francs to 14 US Dollars is represented as a bag * containing the two Monies 12 CHF and 14 USD. Adding another * 10 Swiss francs gives a bag with 22 CHF and 14 USD. Due to * the deferred exchange rate conversion we can later value a * MoneyBag with different exchange rates. * * A MoneyBag is represented as a list of Monies and provides * different constructors to create a MoneyBag. */ public class MoneyBag implements IMoney { private List<Money> fMonies= new ArrayList<Money>(5); public static IMoney create(IMoney m1, IMoney m2) { MoneyBag result= new MoneyBag(); m1.appendTo(result); m2.appendTo(result); return result.simplify(); } public IMoney add(IMoney m) { return m.addMoneyBag(this); } public IMoney addMoney(Money m) { return MoneyBag.create(m, this); } public IMoney addMoneyBag(MoneyBag s) { return MoneyBag.create(s, this); } void appendBag(MoneyBag aBag) { for (Money each : aBag.fMonies) appendMoney(each); } void appendMoney(Money aMoney) { if (aMoney.isZero()) return; IMoney old= findMoney(aMoney.currency()); if (old == null) { fMonies.add(aMoney); return; } fMonies.remove(old); Money sum= (Money) old.add(aMoney); if (sum.isZero()) return; fMonies.add(sum); } @Override public boolean equals(Object anObject) { if (isZero()) if (anObject instanceof IMoney) return ((IMoney)anObject).isZero(); if (anObject instanceof MoneyBag) { MoneyBag aMoneyBag= (MoneyBag)anObject; if (aMoneyBag.fMonies.size() != fMonies.size()) return false; for (Money each : fMonies) if (! aMoneyBag.contains(each)) return false; return true; } return false; } private Money findMoney(String currency) { for (Money each : fMonies) if (each.currency().equals(currency)) return each; return null; } private boolean contains(Money m) { Money found= findMoney(m.currency()); if (found == null) return false; return found.amount() == m.amount(); } @Override public int hashCode() { int hash= 0; for (Money each : fMonies) hash^= each.hashCode(); return hash; } public boolean isZero() { return fMonies.size() == 0; } public IMoney multiply(int factor) { MoneyBag result= new MoneyBag(); if (factor != 0) for (Money each : fMonies) result.appendMoney((Money) each.multiply(factor)); return result; } public IMoney negate() { MoneyBag result= new MoneyBag(); for (Money each : fMonies) result.appendMoney((Money) each.negate()); return result; } private IMoney simplify() { if (fMonies.size() == 1) return fMonies.iterator().next(); return this; } public IMoney subtract(IMoney m) { return add(m.negate()); } @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("{"); for (Money each : fMonies) buffer.append(each); buffer.append("}"); return buffer.toString(); } public void appendTo(MoneyBag m) { m.appendBag(this); } }