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);
}
}