| 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() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("{"); |
| for (Money each : fMonies) { |
| sb.append(each); |
| } |
| sb.append("}"); |
| return sb.toString(); |
| } |
| |
| public void appendTo(MoneyBag m) { |
| m.appendBag(this); |
| } |
| } |