blob: e02bb51ef8483159fea630e8755e66c21ff53587 [file] [log] [blame]
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);
}
}