View Javadoc
1   /*
2    * MoneyWise: Finance Application
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets;
18  
19  import io.github.tonywasher.joceanus.metis.data.MetisDataFieldValue;
20  import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
21  import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataList;
22  import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
23  import io.github.tonywasher.joceanus.metis.field.MetisFieldItem.MetisFieldTableItem;
24  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
25  import io.github.tonywasher.joceanus.metis.list.MetisListIndexed;
26  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.base.MoneyWiseXAnalysisEvent;
27  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.base.MoneyWiseXAnalysisHistory;
28  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.buckets.MoneyWiseXAnalysisInterfaces.MoneyWiseXAnalysisBucketRegister;
29  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.values.MoneyWiseXAnalysisPayeeAttr;
30  import io.github.tonywasher.joceanus.moneywise.atlas.data.analysis.values.MoneyWiseXAnalysisPayeeValues;
31  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseAssetBase;
32  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
33  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee;
34  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee.MoneyWisePayeeList;
35  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCurrency;
36  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWisePayeeClass;
37  import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
38  import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
39  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimal;
40  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
41  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
42  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
43  
44  import java.util.Comparator;
45  import java.util.Currency;
46  import java.util.Iterator;
47  import java.util.List;
48  
49  /**
50   * The Payee Bucket class.
51   */
52  public final class MoneyWiseXAnalysisPayeeBucket
53          implements MetisFieldTableItem, MoneyWiseXAnalysisBucketRegister {
54      /**
55       * Local Report fields.
56       */
57      private static final MetisFieldSet<MoneyWiseXAnalysisPayeeBucket> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseXAnalysisPayeeBucket.class);
58  
59      /*
60       * Declare Fields.
61       */
62      static {
63          FIELD_DEFS.declareLocalField(MoneyWiseXAnalysisBucketResource.ANALYSIS_NAME, MoneyWiseXAnalysisPayeeBucket::getAnalysis);
64          FIELD_DEFS.declareLocalField(MoneyWiseBasicDataType.PAYEE, MoneyWiseXAnalysisPayeeBucket::getPayee);
65          FIELD_DEFS.declareLocalField(MoneyWiseXAnalysisBucketResource.BUCKET_BASEVALUES, MoneyWiseXAnalysisPayeeBucket::getBaseValues);
66          FIELD_DEFS.declareLocalField(MoneyWiseXAnalysisBucketResource.BUCKET_HISTORY, MoneyWiseXAnalysisPayeeBucket::getHistoryMap);
67          FIELD_DEFS.declareLocalFieldsForEnum(MoneyWiseXAnalysisPayeeAttr.class, MoneyWiseXAnalysisPayeeBucket::getAttributeValue);
68      }
69  
70      /**
71       * Totals bucket name.
72       */
73      private static final MetisDataFieldId NAME_TOTALS = MoneyWiseXAnalysisBucketResource.ANALYSIS_TOTALS;
74  
75      /**
76       * The analysis.
77       */
78      private final MoneyWiseXAnalysisHolder theAnalysis;
79  
80      /**
81       * The payee.
82       */
83      private final MoneyWisePayee thePayee;
84  
85      /**
86       * Values.
87       */
88      private final MoneyWiseXAnalysisPayeeValues theValues;
89  
90      /**
91       * The base values.
92       */
93      private final MoneyWiseXAnalysisPayeeValues theBaseValues;
94  
95      /**
96       * History Map.
97       */
98      private final MoneyWiseXAnalysisHistory<MoneyWiseXAnalysisPayeeValues, MoneyWiseXAnalysisPayeeAttr> theHistory;
99  
100     /**
101      * Constructor.
102      *
103      * @param pAnalysis the analysis
104      * @param pPayee    the payee
105      */
106     private MoneyWiseXAnalysisPayeeBucket(final MoneyWiseXAnalysisHolder pAnalysis,
107                                           final MoneyWisePayee pPayee) {
108         /* Store the details */
109         thePayee = pPayee;
110         theAnalysis = pAnalysis;
111 
112         /* Create the history map */
113         final MoneyWiseCurrency myDefault = theAnalysis.getCurrency();
114         final Currency myCurrency = myDefault == null
115                 ? MoneyWiseXAnalysisAccountBucket.DEFAULT_CURRENCY
116                 : myDefault.getCurrency();
117         final MoneyWiseXAnalysisPayeeValues myValues = new MoneyWiseXAnalysisPayeeValues(myCurrency);
118         theHistory = new MoneyWiseXAnalysisHistory<>(myValues);
119 
120         /* Access the key value maps */
121         theValues = theHistory.getValues();
122         theBaseValues = theHistory.getBaseValues();
123     }
124 
125     /**
126      * Constructor.
127      *
128      * @param pAnalysis the analysis
129      * @param pBase     the underlying bucket
130      * @param pDate     the date for the bucket
131      */
132     private MoneyWiseXAnalysisPayeeBucket(final MoneyWiseXAnalysisHolder pAnalysis,
133                                           final MoneyWiseXAnalysisPayeeBucket pBase,
134                                           final OceanusDate pDate) {
135         /* Copy details from base */
136         thePayee = pBase.getPayee();
137         theAnalysis = pAnalysis;
138 
139         /* Access the relevant history */
140         theHistory = new MoneyWiseXAnalysisHistory<>(pBase.getHistoryMap(), pDate);
141 
142         /* Access the key value maps */
143         theValues = theHistory.getValues();
144         theBaseValues = theHistory.getBaseValues();
145     }
146 
147     /**
148      * Constructor.
149      *
150      * @param pAnalysis the analysis
151      * @param pBase     the underlying bucket
152      * @param pRange    the range for the bucket
153      */
154     private MoneyWiseXAnalysisPayeeBucket(final MoneyWiseXAnalysisHolder pAnalysis,
155                                           final MoneyWiseXAnalysisPayeeBucket pBase,
156                                           final OceanusDateRange pRange) {
157         /* Copy details from base */
158         thePayee = pBase.getPayee();
159         theAnalysis = pAnalysis;
160 
161         /* Access the relevant history */
162         theHistory = new MoneyWiseXAnalysisHistory<>(pBase.getHistoryMap(), pRange);
163 
164         /* Access the key value maps */
165         theValues = theHistory.getValues();
166         theBaseValues = theHistory.getBaseValues();
167     }
168 
169     @Override
170     public MetisFieldSet<MoneyWiseXAnalysisPayeeBucket> getDataFieldSet() {
171         return FIELD_DEFS;
172     }
173 
174     @Override
175     public String formatObject(final OceanusDataFormatter pFormatter) {
176         return toString();
177     }
178 
179     @Override
180     public String toString() {
181         return getName() + " " + theValues;
182     }
183 
184     /**
185      * Obtain the name.
186      *
187      * @return the name
188      */
189     public String getName() {
190         return thePayee == null
191                 ? NAME_TOTALS.getId()
192                 : thePayee.getName();
193     }
194 
195     /**
196      * Obtain the payee.
197      *
198      * @return the payee account
199      */
200     public MoneyWisePayee getPayee() {
201         return thePayee;
202     }
203 
204     @Override
205     public Integer getIndexedId() {
206         return thePayee.getIndexedId();
207     }
208 
209     @Override
210     public Long getBucketId() {
211         return thePayee.getExternalId();
212     }
213 
214     /**
215      * Is this bucket idle?
216      *
217      * @return true/false
218      */
219     public boolean isIdle() {
220         return theHistory.isIdle();
221     }
222 
223     /**
224      * Obtain the analysis.
225      *
226      * @return the analysis
227      */
228     MoneyWiseXAnalysisHolder getAnalysis() {
229         return theAnalysis;
230     }
231 
232     /**
233      * Obtain date range.
234      *
235      * @return the range
236      */
237     public OceanusDateRange getDateRange() {
238         return theAnalysis.getDateRange();
239     }
240 
241     /**
242      * Obtain the value map.
243      *
244      * @return the value map
245      */
246     public MoneyWiseXAnalysisPayeeValues getValues() {
247         return theValues;
248     }
249 
250     /**
251      * Obtain the base value map.
252      *
253      * @return the base value map
254      */
255     public MoneyWiseXAnalysisPayeeValues getBaseValues() {
256         return theBaseValues;
257     }
258 
259     /**
260      * Obtain values for event.
261      *
262      * @param pEvent the event
263      * @return the values (or null)
264      */
265     public MoneyWiseXAnalysisPayeeValues getValuesForEvent(final MoneyWiseXAnalysisEvent pEvent) {
266         /* Obtain values for transaction */
267         return theHistory.getValuesForEvent(pEvent);
268     }
269 
270     /**
271      * Obtain previous values for event.
272      *
273      * @param pEvent the event
274      * @return the values (or null)
275      */
276     public MoneyWiseXAnalysisPayeeValues getPreviousValuesForEvent(final MoneyWiseXAnalysisEvent pEvent) {
277         return theHistory.getPreviousValuesForEvent(pEvent);
278     }
279 
280     /**
281      * Obtain delta for event.
282      *
283      * @param pEvent the event
284      * @param pAttr  the attribute
285      * @return the delta (or null)
286      */
287     public OceanusDecimal getDeltaForEvent(final MoneyWiseXAnalysisEvent pEvent,
288                                            final MoneyWiseXAnalysisPayeeAttr pAttr) {
289         /* Obtain delta for event */
290         return theHistory.getDeltaValue(pEvent, pAttr);
291     }
292 
293     /**
294      * Obtain the history map.
295      *
296      * @return the history map
297      */
298     private MoneyWiseXAnalysisHistory<MoneyWiseXAnalysisPayeeValues, MoneyWiseXAnalysisPayeeAttr> getHistoryMap() {
299         return theHistory;
300     }
301 
302     /**
303      * Set Attribute.
304      *
305      * @param pAttr  the attribute
306      * @param pValue the value of the attribute
307      */
308     void setValue(final MoneyWiseXAnalysisPayeeAttr pAttr,
309                   final Object pValue) {
310         /* Set the value */
311         theValues.setValue(pAttr, pValue);
312     }
313 
314     /**
315      * Get an attribute value.
316      *
317      * @param pAttr the attribute
318      * @return the value to set
319      */
320     private Object getAttributeValue(final MoneyWiseXAnalysisPayeeAttr pAttr) {
321         /* Access value of object */
322         final Object myValue = getValue(pAttr);
323 
324         /* Return the value */
325         return myValue != null
326                 ? myValue
327                 : MetisDataFieldValue.SKIP;
328     }
329 
330     /**
331      * Obtain an attribute value.
332      *
333      * @param pAttr the attribute
334      * @return the value of the attribute or null
335      */
336     private Object getValue(final MoneyWiseXAnalysisPayeeAttr pAttr) {
337         /* Obtain the value */
338         return theValues.getValue(pAttr);
339     }
340 
341     /**
342      * Adjust counter.
343      *
344      * @param pAttr  the attribute
345      * @param pDelta the delta
346      */
347     void adjustCounter(final MoneyWiseXAnalysisPayeeAttr pAttr,
348                        final OceanusMoney pDelta) {
349         OceanusMoney myValue = theValues.getMoneyValue(pAttr);
350         myValue = new OceanusMoney(myValue);
351         myValue.addAmount(pDelta);
352         setValue(pAttr, myValue);
353     }
354 
355     @Override
356     public void registerEvent(final MoneyWiseXAnalysisEvent pEvent) {
357         /* Register the event in the history */
358         theHistory.registerEvent(pEvent, theValues);
359     }
360 
361     /**
362      * Add income value.
363      *
364      * @param pValue the value to add
365      */
366     public void addIncome(final OceanusMoney pValue) {
367         /* Only adjust on non-zero */
368         if (pValue.isNonZero()) {
369             adjustCounter(MoneyWiseXAnalysisPayeeAttr.INCOME, pValue);
370         }
371     }
372 
373     /**
374      * Subtract income value.
375      *
376      * @param pValue the value to subtract
377      */
378     public void subtractIncome(final OceanusMoney pValue) {
379         /* Only adjust on non-zero */
380         if (pValue.isNonZero()) {
381             final OceanusMoney myIncome = new OceanusMoney(pValue);
382             myIncome.negate();
383             adjustCounter(MoneyWiseXAnalysisPayeeAttr.INCOME, myIncome);
384         }
385     }
386 
387     /**
388      * Add expense value.
389      *
390      * @param pValue the value to add
391      */
392     public void addExpense(final OceanusMoney pValue) {
393         /* Only adjust on non-zero */
394         if (pValue.isNonZero()) {
395             adjustCounter(MoneyWiseXAnalysisPayeeAttr.EXPENSE, pValue);
396         }
397     }
398 
399     /**
400      * Subtract expense value.
401      *
402      * @param pValue the value to subtract
403      */
404     public void subtractExpense(final OceanusMoney pValue) {
405         /* Only adjust on non-zero */
406         if (pValue.isNonZero()) {
407             final OceanusMoney myExpense = new OceanusMoney(pValue);
408             myExpense.negate();
409             adjustCounter(MoneyWiseXAnalysisPayeeAttr.EXPENSE, myExpense);
410         }
411     }
412 
413     /**
414      * Add bucket to totals.
415      *
416      * @param pSource the bucket to add
417      */
418     void addValues(final MoneyWiseXAnalysisPayeeBucket pSource) {
419         /* Access source values */
420         final MoneyWiseXAnalysisPayeeValues mySource = pSource.getValues();
421 
422         /* Add income values */
423         OceanusMoney myValue = theValues.getMoneyValue(MoneyWiseXAnalysisPayeeAttr.INCOME);
424         OceanusMoney mySrcValue = mySource.getMoneyValue(MoneyWiseXAnalysisPayeeAttr.INCOME);
425         myValue.addAmount(mySrcValue);
426 
427         /* Add expense values */
428         myValue = theValues.getMoneyValue(MoneyWiseXAnalysisPayeeAttr.EXPENSE);
429         mySrcValue = mySource.getMoneyValue(MoneyWiseXAnalysisPayeeAttr.EXPENSE);
430         myValue.addAmount(mySrcValue);
431     }
432 
433     /**
434      * Calculate delta.
435      */
436     void calculateDelta() {
437         /* Calculate delta for the values */
438         theValues.calculateDelta();
439     }
440 
441     /**
442      * Adjust to base.
443      */
444     void adjustToBase() {
445         /* Adjust to base values */
446         theValues.adjustToBaseValues(theBaseValues);
447         theBaseValues.resetBaseValues();
448     }
449 
450     /**
451      * PayeeBucket list class.
452      */
453     public static final class MoneyWiseXAnalysisPayeeBucketList
454             implements MetisFieldItem, MetisDataList<MoneyWiseXAnalysisPayeeBucket> {
455         /**
456          * Local Report fields.
457          */
458         private static final MetisFieldSet<MoneyWiseXAnalysisPayeeBucketList> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseXAnalysisPayeeBucketList.class);
459 
460         /*
461          * Declare Fields.
462          */
463         static {
464             FIELD_DEFS.declareLocalField(MoneyWiseXAnalysisBucketResource.ANALYSIS_NAME, MoneyWiseXAnalysisPayeeBucketList::getAnalysis);
465             FIELD_DEFS.declareLocalField(MoneyWiseXAnalysisBucketResource.ANALYSIS_TOTALS, MoneyWiseXAnalysisPayeeBucketList::getTotals);
466         }
467 
468         /**
469          * The analysis.
470          */
471         private final MoneyWiseXAnalysisHolder theAnalysis;
472 
473         /**
474          * The list.
475          */
476         private final MetisListIndexed<MoneyWiseXAnalysisPayeeBucket> theList;
477 
478         /**
479          * The editSet.
480          */
481         private final PrometheusEditSet theEditSet;
482 
483         /**
484          * The totals.
485          */
486         private final MoneyWiseXAnalysisPayeeBucket theTotals;
487 
488         /**
489          * Construct a top-level List.
490          *
491          * @param pAnalysis the analysis
492          */
493         MoneyWiseXAnalysisPayeeBucketList(final MoneyWiseXAnalysisHolder pAnalysis) {
494             /* Initialise class */
495             theAnalysis = pAnalysis;
496             theEditSet = theAnalysis.getEditSet();
497             theTotals = allocateTotalsBucket();
498             theList = new MetisListIndexed<>();
499             theList.setComparator(Comparator.comparing(MoneyWiseXAnalysisPayeeBucket::getPayee));
500         }
501 
502         /**
503          * Construct a dated List.
504          *
505          * @param pAnalysis the analysis
506          * @param pBase     the base list
507          * @param pDate     the Date
508          */
509         MoneyWiseXAnalysisPayeeBucketList(final MoneyWiseXAnalysisHolder pAnalysis,
510                                           final MoneyWiseXAnalysisPayeeBucketList pBase,
511                                           final OceanusDate pDate) {
512             /* Initialise class */
513             this(pAnalysis);
514 
515             /* Loop through the buckets */
516             final Iterator<MoneyWiseXAnalysisPayeeBucket> myIterator = pBase.iterator();
517             while (myIterator.hasNext()) {
518                 final MoneyWiseXAnalysisPayeeBucket myCurr = myIterator.next();
519 
520                 /* Access the bucket for this date */
521                 final MoneyWiseXAnalysisPayeeBucket myBucket = new MoneyWiseXAnalysisPayeeBucket(pAnalysis, myCurr, pDate);
522 
523                 /* If the bucket is non-idle */
524                 if (!myBucket.isIdle()) {
525                     /* Add to the list */
526                     theList.add(myBucket);
527                 }
528             }
529         }
530 
531         /**
532          * Construct a ranged List.
533          *
534          * @param pAnalysis the analysis
535          * @param pBase     the base list
536          * @param pRange    the Date Range
537          */
538         MoneyWiseXAnalysisPayeeBucketList(final MoneyWiseXAnalysisHolder pAnalysis,
539                                           final MoneyWiseXAnalysisPayeeBucketList pBase,
540                                           final OceanusDateRange pRange) {
541             /* Initialise class */
542             this(pAnalysis);
543 
544             /* Loop through the buckets */
545             final Iterator<MoneyWiseXAnalysisPayeeBucket> myIterator = pBase.iterator();
546             while (myIterator.hasNext()) {
547                 final MoneyWiseXAnalysisPayeeBucket myCurr = myIterator.next();
548 
549                 /* Access the bucket for this range */
550                 final MoneyWiseXAnalysisPayeeBucket myBucket = new MoneyWiseXAnalysisPayeeBucket(pAnalysis, myCurr, pRange);
551 
552                 /* If the bucket is non-idle */
553                 if (!myBucket.isIdle()) {
554                     /* Adjust to the base and add to the list */
555                     myBucket.adjustToBase();
556                     theList.add(myBucket);
557                 }
558             }
559         }
560 
561         @Override
562         public MetisFieldSet<MoneyWiseXAnalysisPayeeBucketList> getDataFieldSet() {
563             return FIELD_DEFS;
564         }
565 
566         @Override
567         public List<MoneyWiseXAnalysisPayeeBucket> getUnderlyingList() {
568             return theList.getUnderlyingList();
569         }
570 
571         @Override
572         public String formatObject(final OceanusDataFormatter pFormatter) {
573             return getDataFieldSet().getName();
574         }
575 
576         /**
577          * Obtain item by id.
578          *
579          * @param pId the id to lookup
580          * @return the item (or null if not present)
581          */
582         public MoneyWiseXAnalysisPayeeBucket findItemById(final Integer pId) {
583             /* Return results */
584             return theList.getItemById(pId);
585         }
586 
587         /**
588          * Obtain the analysis.
589          *
590          * @return the analysis
591          */
592         MoneyWiseXAnalysisHolder getAnalysis() {
593             return theAnalysis;
594         }
595 
596         /**
597          * Obtain the Totals.
598          *
599          * @return the totals
600          */
601         public MoneyWiseXAnalysisPayeeBucket getTotals() {
602             return theTotals;
603         }
604 
605         /**
606          * Allocate the Totals PayeeBucket.
607          *
608          * @return the bucket
609          */
610         private MoneyWiseXAnalysisPayeeBucket allocateTotalsBucket() {
611             /* Obtain the totals payee */
612             return new MoneyWiseXAnalysisPayeeBucket(theAnalysis, null);
613         }
614 
615         /**
616          * Obtain the PayeeBucket for a given payee.
617          *
618          * @param pPayee the payee
619          * @return the bucket
620          */
621         public MoneyWiseXAnalysisPayeeBucket getBucket(final MoneyWiseAssetBase pPayee) {
622             /* Handle null payee */
623             if (pPayee == null) {
624                 return null;
625             }
626 
627             /* Access as payee */
628             final MoneyWisePayee myPayee = (MoneyWisePayee) pPayee;
629 
630             /* Locate the bucket in the list */
631             MoneyWiseXAnalysisPayeeBucket myItem = findItemById(myPayee.getIndexedId());
632 
633             /* If the item does not yet exist */
634             if (myItem == null) {
635                 /* Create the new bucket */
636                 myItem = new MoneyWiseXAnalysisPayeeBucket(theAnalysis, myPayee);
637 
638                 /* Add to the list */
639                 theList.add(myItem);
640             }
641 
642             /* Return the bucket */
643             return myItem;
644         }
645 
646         /**
647          * Obtain the PayeeBucket for a given payee class.
648          *
649          * @param pClass the account category class
650          * @return the bucket
651          */
652         public MoneyWiseXAnalysisPayeeBucket getBucket(final MoneyWisePayeeClass pClass) {
653             /* Determine required payee */
654             final MoneyWisePayee myPayee = theEditSet.getDataList(MoneyWiseBasicDataType.PAYEE, MoneyWisePayeeList.class).getSingularClass(pClass);
655 
656             /* Return the bucket */
657             return getBucket(myPayee);
658         }
659 
660         /**
661          * Obtain the matching PayeeBucket.
662          *
663          * @param pPayee the payee
664          * @return the matching bucket
665          */
666         public MoneyWiseXAnalysisPayeeBucket getMatchingPayee(final MoneyWisePayee pPayee) {
667             /* Return the matching payee if it exists else an orphan bucket */
668             final MoneyWiseXAnalysisPayeeBucket myPayee = findItemById(pPayee.getIndexedId());
669             return myPayee != null
670                     ? myPayee
671                     : new MoneyWiseXAnalysisPayeeBucket(theAnalysis, pPayee);
672         }
673 
674         /**
675          * Obtain the default PayeeBucket.
676          *
677          * @return the default bucket
678          */
679         public MoneyWiseXAnalysisPayeeBucket getDefaultPayee() {
680             /* Return the first payee in the list if it exists */
681             return isEmpty()
682                     ? null
683                     : theList.getUnderlyingList().getFirst();
684         }
685 
686         /**
687          * Produce totals for the Payees.
688          */
689         public void produceTotals() {
690             /* Loop through the buckets */
691             final Iterator<MoneyWiseXAnalysisPayeeBucket> myIterator = iterator();
692             while (myIterator.hasNext()) {
693                 final MoneyWiseXAnalysisPayeeBucket myCurr = myIterator.next();
694 
695                 /* Remove idle items */
696                 if (myCurr.isIdle()) {
697                     myIterator.remove();
698                     continue;
699                 }
700 
701                 /* Calculate the delta */
702                 myCurr.calculateDelta();
703 
704                 /* Add to totals bucket */
705                 theTotals.addValues(myCurr);
706             }
707 
708             /* Sort the payees */
709             theList.sortList();
710 
711             /* Calculate delta for the totals */
712             if (theTotals != null) {
713                 theTotals.calculateDelta();
714             }
715         }
716     }
717 }