// **************************************************************** // This is free software licensed under the NUnit license. You // may obtain a copy of the license as well as information regarding // copyright ownership at http://nunit.org/?p=license&r=2.4. // **************************************************************** namespace NUnit.Samples.Money { using System; using System.Collections; using System.Text; /// 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. class MoneyBag: IMoney { private ArrayList fMonies= new ArrayList(5); private MoneyBag() { } public MoneyBag(Money[] bag) { for (int i= 0; i < bag.Length; i++) { if (!bag[i].IsZero) AppendMoney(bag[i]); } } public MoneyBag(Money m1, Money m2) { AppendMoney(m1); AppendMoney(m2); } public MoneyBag(Money m, MoneyBag bag) { AppendMoney(m); AppendBag(bag); } public MoneyBag(MoneyBag m1, MoneyBag m2) { AppendBag(m1); AppendBag(m2); } public IMoney Add(IMoney m) { return m.AddMoneyBag(this); } public IMoney AddMoney(Money m) { return (new MoneyBag(m, this)).Simplify(); } public IMoney AddMoneyBag(MoneyBag s) { return (new MoneyBag(s, this)).Simplify(); } private void AppendBag(MoneyBag aBag) { foreach (Money m in aBag.fMonies) AppendMoney(m); } private void AppendMoney(Money aMoney) { IMoney old= FindMoney(aMoney.Currency); if (old == null) { fMonies.Add(aMoney); return; } fMonies.Remove(old); IMoney sum= old.Add(aMoney); if (sum.IsZero) return; fMonies.Add(sum); } private bool Contains(Money aMoney) { Money m= FindMoney(aMoney.Currency); return m.Amount == aMoney.Amount; } public override bool Equals(Object anObject) { if (IsZero) if (anObject is IMoney) return ((IMoney)anObject).IsZero; if (anObject is MoneyBag) { MoneyBag aMoneyBag= (MoneyBag)anObject; if (aMoneyBag.fMonies.Count != fMonies.Count) return false; foreach (Money m in fMonies) { if (!aMoneyBag.Contains(m)) return false; } return true; } return false; } private Money FindMoney(String currency) { foreach (Money m in fMonies) { if (m.Currency.Equals(currency)) return m; } return null; } public override int GetHashCode() { int hash= 0; foreach (Money m in fMonies) { hash^= m.GetHashCode(); } return hash; } public bool IsZero { get { return fMonies.Count == 0; } } public IMoney Multiply(int factor) { MoneyBag result= new MoneyBag(); if (factor != 0) { foreach (Money m in fMonies) { result.AppendMoney((Money)m.Multiply(factor)); } } return result; } public IMoney Negate() { MoneyBag result= new MoneyBag(); foreach (Money m in fMonies) { result.AppendMoney((Money)m.Negate()); } return result; } private IMoney Simplify() { if (fMonies.Count == 1) return (IMoney)fMonies[0]; return this; } public IMoney Subtract(IMoney m) { return Add(m.Negate()); } public override String ToString() { StringBuilder buffer = new StringBuilder(); buffer.Append("{"); foreach (Money m in fMonies) buffer.Append(m); buffer.Append("}"); return buffer.ToString(); } } }