001: /*
002: *
003: * JMoney - A Personal Finance Manager
004: * Copyright (c) 2002 Johann Gyger <johann.gyger@switzerland.org>
005: * Copyright (c) 2004 Nigel Westbury <westbury@users.sourceforge.net>
006: *
007: *
008: * This program is free software; you can redistribute it and/or modify
009: * it under the terms of the GNU General Public License as published by
010: * the Free Software Foundation; either version 2 of the License, or
011: * (at your option) any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: *
022: */
023:
024: package net.sf.jmoney.model2;
025:
026: import java.util.Date;
027:
028: import net.sf.jmoney.JMoneyPlugin;
029:
030: /**
031: * The data model for an account.
032: */
033: public abstract class CurrencyAccount extends CapitalAccount {
034:
035: /**
036: * Guaranteed non-null because the session default currency is
037: * set by default.
038: */
039: protected IObjectKey currencyKey;
040:
041: protected long startBalance = 0;
042:
043: /**
044: * The full constructor for a CurrencyAccount object. This constructor is called
045: * only by the datastore plug-in when loading data from the datastore. The properties
046: * passed to this constructor must be valid because datastores should only pass back
047: * values that were previously saved from a CapitalAccount object. So, for example,
048: * we can be sure that a non-null name and currency are passed to this constructor.
049: *
050: * @param name the name of the account
051: */
052: public CurrencyAccount(IObjectKey objectKey, ListKey parent,
053: String name, IListManager<CapitalAccount> subAccounts,
054: String abbreviation, String comment,
055: IObjectKey currencyKey, long startBalance,
056: IValues extensionValues) {
057: super (objectKey, parent, name, subAccounts, abbreviation,
058: comment, extensionValues);
059:
060: /*
061: * The currency for this account is not allowed to be null, because
062: * users of this class may assume it to be non-null and would not know
063: * how to handle this account if it were null.
064: *
065: * If null is passed, set to the default currency for the session.
066: * This is guaranteed to be never null.
067: */
068: if (currencyKey != null) {
069: this .currencyKey = currencyKey;
070: } else {
071: this .currencyKey = objectKey.getSession()
072: .getDefaultCurrency().getObjectKey();
073: }
074:
075: this .startBalance = startBalance;
076: }
077:
078: /**
079: * The default constructor for a CapitalAccount object. This constructor is called
080: * when a new CapitalAccount object is created. The properties are set to default
081: * values. The list properties are set to empty lists. The parameter list for this
082: * constructor is the same as the full constructor except that there are no parameters
083: * for the scalar properties.
084: */
085: public CurrencyAccount(IObjectKey objectKey, ListKey parent) {
086: super (objectKey, parent);
087:
088: // Set a default name.
089: this .name = JMoneyPlugin
090: .getResourceString("Account.newAccount");
091:
092: // Set the currency to the session default currency.
093: this .currencyKey = objectKey.getSession().getDefaultCurrency()
094: .getObjectKey();
095:
096: this .startBalance = 0;
097: }
098:
099: @Override
100: protected String getExtendablePropertySetId() {
101: return "net.sf.jmoney.currencyAccount";
102: }
103:
104: /**
105: * @return the locale of this account.
106: */
107: public String getCurrencyCode() {
108: return getCurrency().getCode();
109: }
110:
111: public Currency getCurrency() {
112: return (Currency) currencyKey.getObject();
113: }
114:
115: @Override
116: public Commodity getCommodity(Entry entry) {
117: // All entries in this account must be in the
118: // same currency, so return the currency for this
119: // account.
120: return getCurrency();
121: }
122:
123: /**
124: * @return the initial balance of this account.
125: */
126: public long getStartBalance() {
127: return startBalance;
128: }
129:
130: public void setCurrency(Currency aCurrency) {
131: if (aCurrency == null)
132: throw new IllegalArgumentException();
133: Currency oldCurrency = getCurrency();
134: currencyKey = aCurrency.getObjectKey();
135:
136: // Notify the change manager.
137: processPropertyChange(
138: CurrencyAccountInfo.getCurrencyAccessor(), oldCurrency,
139: aCurrency);
140: }
141:
142: /**
143: * Sets the initial balance of this account.
144: * @param startBalance the start balance
145: */
146: public void setStartBalance(long startBalance) {
147: long oldStartBalance = this .startBalance;
148: this .startBalance = startBalance;
149:
150: // Notify the change manager.
151: processPropertyChange(CurrencyAccountInfo
152: .getStartBalanceAccessor(), oldStartBalance,
153: startBalance);
154: }
155:
156: @Override
157: public String toString() {
158: return name;
159: }
160:
161: @Override
162: public String getFullAccountName() {
163: if (getParent() == null) {
164: return name;
165: } else {
166: return getParent().getFullAccountName() + "." + this .name;
167: }
168: }
169:
170: /**
171: * Get the balance at a given date
172: *
173: * @param date
174: * @return the balance
175: * @author Faucheux
176: */
177: public long getBalance(Session session, Date fromDate, Date toDate) {
178: if (JMoneyPlugin.DEBUG)
179: System.out.println("Calculing the Balance for >" + name
180: + "< (without sub-accounts) between " + fromDate
181: + " and " + toDate);
182:
183: long bal = getStartBalance();
184:
185: IEntryQueries queries = (IEntryQueries) getSession()
186: .getAdapter(IEntryQueries.class);
187: if (queries != null) {
188: bal += queries.sumOfAmounts(this , fromDate, toDate);
189: } else {
190: // IEntryQueries has not been implemented in the datastore.
191: // We must therefore provide our own implementation.
192:
193: // Sum each entry the entry between the two dates
194: for (Entry e : getEntries()) {
195: if ((e.getTransaction().getDate().compareTo(fromDate) >= 0)
196: && e.getTransaction().getDate().compareTo(
197: toDate) <= 0) {
198: bal += e.getAmount();
199:
200: }
201: }
202: }
203:
204: return bal;
205: }
206:
207: /**
208: * Get the balance between two dates , inclusive sub-accounts
209: *
210: * @param date
211: * @return the balance
212: * @author Faucheux
213: */
214: public long getBalanceWithSubAccounts(Session session,
215: Date fromDate, Date toDate) {
216: if (JMoneyPlugin.DEBUG)
217: System.out.println("Calculing the Balance for >" + name
218: + "< (with sub-accounts) between " + fromDate
219: + " and " + toDate);
220: long bal = getBalance(session, fromDate, toDate);
221:
222: // This logic may not be quite right. If a stock account is a sub account of
223: // a currency account then the balance of the stock account cannot be added
224: // into the total (stock accounts don't hold currency). However, what if the
225: // stock account has a sub account that is a currency account? This code
226: // will not include that currency account.
227: // Also, even if the sub-accounts are currency accounts, they may be in a
228: // different currency.
229: // However, this logic is probably ok for most uses.
230: for (CapitalAccount account : getSubAccountCollection()) {
231: if (account instanceof CurrencyAccount) {
232: bal += ((CurrencyAccount) account)
233: .getBalanceWithSubAccounts(session, fromDate,
234: toDate);
235: }
236: }
237: return bal;
238: }
239: }
|