001: package net.sf.jmoney.charts;
002:
003: import java.util.Collections;
004: import java.util.Date;
005: import java.util.Iterator;
006: import java.util.LinkedList;
007: import java.util.List;
008: import java.util.Vector;
009:
010: import net.sf.jmoney.model2.CapitalAccount;
011: import net.sf.jmoney.model2.Session;
012:
013: import org.jfree.data.CategoryDataset;
014: import org.jfree.data.DefaultCategoryDataset;
015: import org.jfree.data.time.Month;
016: import org.jfree.data.time.RegularTimePeriod;
017:
018: public class StackedAccountChart extends StackedChart {
019:
020: private static final long serialVersionUID = 83591871943261555L;
021:
022: public StackedAccountChart(String title, Session session,
023: StackedChartParameters params) {
024: super (title, session, params);
025: }
026:
027: protected CategoryDataset createValues(Session session) {
028: int numberOfPeriods;
029: List listAccounts;
030: long totalValue = 0;
031:
032: params.instanciateConstructor();
033:
034: // Calculate the number of Periods
035: numberOfPeriods = 0;
036: for (RegularTimePeriod period = params
037: .createPeriod(params.fromDate); period
038: .getFirstMillisecond() < params.toDate.getTime(); period = period
039: .next()) {
040:
041: numberOfPeriods++;
042: }
043:
044: // Calculate the begin and the end of each Time-Gap
045: Date[] dateBegin = new Date[numberOfPeriods];
046: Date[] dateEnd = new Date[numberOfPeriods];
047: String[] dateLabels = new String[numberOfPeriods];
048: RegularTimePeriod period = params.createPeriod(params.fromDate);
049: for (int i = 0; i < numberOfPeriods; i++) {
050: dateBegin[i] = new Date(period.getFirstMillisecond());
051: dateEnd[i] = new Date(period.getLastMillisecond());
052: period = period.next();
053: }
054: for (int i = 0; i < numberOfPeriods; i++)
055: dateLabels[i] = params.dateformat.format(dateBegin[i]);
056:
057: // Get the accounts
058: listAccounts = new LinkedList();
059: for (int i = 0; i < params.accountList.size(); i++) {
060: CapitalAccount acc = (CapitalAccount) Util
061: .getAccountByFullName(session,
062: (String) params.accountList.get(i));
063: listAccounts.add(acc);
064: listAccounts.addAll(Util.getSubAccountsUntilLevel(acc,
065: params.maxLevel));
066: }
067:
068: // Now, enter the values in our table
069: DefaultCategoryDataset dataset = new DefaultCategoryDataset();
070: List accounts = new LinkedList();
071:
072: // for each account
073: int currentAccount = 0;
074: Iterator itAccounts = listAccounts.iterator();
075: while (itAccounts.hasNext()) {
076: CapitalAccount a = (CapitalAccount) itAccounts.next();
077: accountCategory accountCategory = new accountCategory(a
078: .getName(), 0);
079: // get the entries
080: boolean includeSubAccounts;
081: if (a.getLevel() < params.maxLevel) {
082: // If the account has sub accounts, they will have their own entry -> we don't have to include them here
083: includeSubAccounts = false;
084: } else {
085: // If the account has sub accounts, they won't have their own entry -> we have to include them here
086: includeSubAccounts = true;
087: }
088:
089: long[] totals = Util.getEntryTotalsByPeriod(a, params
090: .createPeriod(params.fromDate), numberOfPeriods,
091: includeSubAccounts);
092:
093: // calculate the sum for each period
094: for (int i = 0; i < numberOfPeriods; i++) {
095: accountCategory.setLong(i, totals[i]);
096: accountCategory.orderingValue += accountCategory
097: .getLong(i);
098: accountCategory.totalValue += accountCategory
099: .getLong(i);
100: }
101: // add an Entry for the "average"
102: accountCategory.setLong(numberOfPeriods,
103: accountCategory.totalValue / numberOfPeriods);
104:
105: currentAccount++;
106: accounts.add(accountCategory);
107: totalValue += accountCategory.totalValue;
108: }
109:
110: // Order them
111: Collections.sort(accounts);
112: Collections.reverse(accounts);
113:
114: // remove the last ones
115: boolean maximumReached = false;
116: while (!maximumReached && accounts.size() > 2) {
117: accountCategory last = (accountCategory) accounts
118: .get(accounts.size() - 1);
119: accountCategory antelast = (accountCategory) accounts
120: .get(accounts.size() - 2);
121: if (last.totalValue + antelast.totalValue < (totalValue / 10)) {
122: antelast.add(last);
123: accounts.remove(last);
124: } else {
125: maximumReached = true;
126: }
127: }
128:
129: // Cut the last name to avoid it to be too long
130: {
131: accountCategory last = (accountCategory) accounts
132: .get(accounts.size() - 1);
133: if (last.name.length() > 120)
134: last.name = last.name.substring(0, 120) + "...";
135: }
136:
137: // enter them in graph
138: currentAccount = 0;
139: itAccounts = accounts.iterator();
140: while (itAccounts.hasNext()) {
141: accountCategory a = (accountCategory) itAccounts.next();
142: for (int i = 0; i < numberOfPeriods; i++) {
143: dataset.setValue(a.getLong(i), a, new Month(
144: dateBegin[i]));
145: }
146: // don't forget the middle value
147: dataset.setValue(a.getLong(numberOfPeriods), a, "Moyenne");
148:
149: currentAccount++;
150: }
151:
152: return dataset;
153: }
154:
155: private class accountCategory implements Comparable {
156:
157: String name;
158: public long orderingValue;
159: public Vector values;
160: public long totalValue;
161:
162: public accountCategory(String name, long orderingValue) {
163: this .name = name;
164: this .orderingValue = orderingValue;
165: values = new Vector(10, 10);
166: this .totalValue = orderingValue;
167: }
168:
169: public int compareTo(Object o) {
170: long this Val = this .orderingValue;
171: long anotherVal = ((accountCategory) o).orderingValue;
172: return (this Val < anotherVal ? -1
173: : (this Val == anotherVal ? 0 : 1));
174: }
175:
176: public String toString() {
177: return name;
178: }
179:
180: public long getLong(int index) {
181: return ((Long) values.get(index)).longValue();
182: }
183:
184: public void setLong(int index, long value) {
185: if (values.size() <= index)
186: values.setSize(index + 1);
187: values.set(index, new Long(value));
188: }
189:
190: /**
191: * "Add" a category to the current one by summing their values and concacenate their names.
192: * @param other
193: */
194: public void add(accountCategory other) {
195:
196: // Concatenate the names. Don't contatenate the name of an empty account.
197: if (this .totalValue != 0 && other.totalValue != 0)
198: this .name = this .name + " + " + other.name;
199: else if (this .totalValue == 0)
200: this .name = other.name;
201:
202: this .totalValue += other.totalValue;
203: for (int i = 0; i < this.values.size(); i++) {
204: setLong(i, this.getLong(i) + other.getLong(i));
205: }
206: }
207:
208: }
209: }
|