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.data.basic;
18  
19  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
20  import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
21  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
22  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
23  import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
24  import io.github.tonywasher.joceanus.metis.data.MetisDataEditState;
25  import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
26  import io.github.tonywasher.joceanus.metis.data.MetisDataResource;
27  import io.github.tonywasher.joceanus.metis.data.MetisDataState;
28  import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
29  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
30  import io.github.tonywasher.joceanus.metis.field.MetisFieldVersionedSet;
31  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDepositCategory.MoneyWiseDepositCategoryList;
32  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDepositInfo.MoneyWiseDepositInfoList;
33  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePayee.MoneyWisePayeeList;
34  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTax.MoneyWiseTaxCredit;
35  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransCategory.MoneyWiseTransCategoryList;
36  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoClass;
37  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoType.MoneyWiseAccountInfoTypeList;
38  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCurrency;
39  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseCurrency.MoneyWiseCurrencyList;
40  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseDepositCategoryClass;
41  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
42  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransCategoryClass;
43  import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseDataException;
44  import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseLogicException;
45  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataItem;
46  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataMapItem;
47  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
48  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataValues;
49  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataValues.PrometheusInfoItem;
50  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataValues.PrometheusInfoSetItem;
51  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
52  
53  import java.util.Iterator;
54  
55  /**
56   * Deposit class.
57   */
58  public class MoneyWiseDeposit
59          extends MoneyWiseAssetBase
60          implements PrometheusInfoSetItem {
61      /**
62       * Object name.
63       */
64      public static final String OBJECT_NAME = MoneyWiseBasicDataType.DEPOSIT.getItemName();
65  
66      /**
67       * List name.
68       */
69      public static final String LIST_NAME = MoneyWiseBasicDataType.DEPOSIT.getListName();
70  
71      /**
72       * Local Report fields.
73       */
74      private static final MetisFieldVersionedSet<MoneyWiseDeposit> FIELD_DEFS = MetisFieldVersionedSet.newVersionedFieldSet(MoneyWiseDeposit.class);
75  
76      /*
77       * FieldIds.
78       */
79      static {
80          FIELD_DEFS.declareLocalField(PrometheusDataResource.DATAINFOSET_NAME, MoneyWiseDeposit::getInfoSet);
81          FIELD_DEFS.buildFieldMap(MoneyWiseAccountInfoClass.class, MoneyWiseDeposit::getFieldValue);
82      }
83  
84      /**
85       * Do we have an InfoSet.
86       */
87      private final boolean hasInfoSet;
88  
89      /**
90       * Should we use infoSet for DataState etc.
91       */
92      private final boolean useInfoSet;
93  
94      /**
95       * DepositInfoSet.
96       */
97      private final MoneyWiseDepositInfoSet theInfoSet;
98  
99      /**
100      * Copy Constructor.
101      *
102      * @param pList    the list
103      * @param pDeposit The Deposit to copy
104      */
105     protected MoneyWiseDeposit(final MoneyWiseDepositList pList,
106                                final MoneyWiseDeposit pDeposit) {
107         /* Set standard values */
108         super(pList, pDeposit);
109 
110         /* switch on list type */
111         switch (getList().getStyle()) {
112             case EDIT:
113                 theInfoSet = new MoneyWiseDepositInfoSet(this, pList.getActInfoTypes(), pList.getDepositInfo());
114                 theInfoSet.cloneDataInfoSet(pDeposit.getInfoSet());
115                 hasInfoSet = true;
116                 useInfoSet = true;
117                 break;
118             case CLONE:
119             case CORE:
120                 theInfoSet = new MoneyWiseDepositInfoSet(this, pList.getActInfoTypes(), pList.getDepositInfo());
121                 hasInfoSet = true;
122                 useInfoSet = false;
123                 break;
124             default:
125                 theInfoSet = null;
126                 hasInfoSet = false;
127                 useInfoSet = false;
128                 break;
129         }
130     }
131 
132     /**
133      * Values constructor.
134      *
135      * @param pList   the List to add to
136      * @param pValues the values constructor
137      * @throws OceanusException on error
138      */
139     private MoneyWiseDeposit(final MoneyWiseDepositList pList,
140                              final PrometheusDataValues pValues) throws OceanusException {
141         /* Initialise the item */
142         super(pList, pValues);
143 
144         /* Create the InfoSet */
145         theInfoSet = new MoneyWiseDepositInfoSet(this, pList.getActInfoTypes(), pList.getDepositInfo());
146         hasInfoSet = true;
147         useInfoSet = false;
148     }
149 
150     /**
151      * Edit Constructor.
152      *
153      * @param pList the list
154      */
155     public MoneyWiseDeposit(final MoneyWiseDepositList pList) {
156         super(pList);
157 
158         /* Build InfoSet */
159         theInfoSet = new MoneyWiseDepositInfoSet(this, pList.getActInfoTypes(), pList.getDepositInfo());
160         hasInfoSet = true;
161         useInfoSet = true;
162     }
163 
164     @Override
165     public MetisFieldSetDef getDataFieldSet() {
166         return FIELD_DEFS;
167     }
168 
169     @Override
170     public boolean includeXmlField(final MetisDataFieldId pField) {
171         /* Determine whether fields should be included */
172         if (MoneyWiseBasicResource.CATEGORY_NAME.equals(pField)) {
173             return true;
174         }
175         if (MoneyWiseStaticDataType.CURRENCY.equals(pField)) {
176             return true;
177         }
178         if (MoneyWiseBasicResource.ASSET_PARENT.equals(pField)) {
179             return true;
180         }
181 
182         /* Pass call on */
183         return super.includeXmlField(pField);
184     }
185 
186     @Override
187     public Long getExternalId() {
188         return MoneyWiseAssetType.createExternalId(MoneyWiseAssetType.DEPOSIT, getIndexedId());
189     }
190 
191     @Override
192     public MoneyWiseDepositInfoSet getInfoSet() {
193         return theInfoSet;
194     }
195 
196     /**
197      * Obtain fieldValue for infoSet.
198      *
199      * @param pFieldId the fieldId
200      * @return the value
201      */
202     private Object getFieldValue(final MetisDataFieldId pFieldId) {
203         return theInfoSet != null ? theInfoSet.getFieldValue(pFieldId) : null;
204     }
205 
206     /**
207      * Obtain Maturity.
208      *
209      * @return the maturity date
210      */
211     public OceanusDate getMaturity() {
212         return hasInfoSet
213                 ? theInfoSet.getValue(MoneyWiseAccountInfoClass.MATURITY, OceanusDate.class)
214                 : null;
215     }
216 
217     /**
218      * Obtain SortCode.
219      *
220      * @return the sort code
221      */
222     public char[] getSortCode() {
223         return hasInfoSet
224                 ? theInfoSet.getValue(MoneyWiseAccountInfoClass.SORTCODE, char[].class)
225                 : null;
226     }
227 
228     /**
229      * Obtain Reference.
230      *
231      * @return the reference
232      */
233     public char[] getReference() {
234         return hasInfoSet
235                 ? theInfoSet.getValue(MoneyWiseAccountInfoClass.REFERENCE, char[].class)
236                 : null;
237     }
238 
239     /**
240      * Obtain Account.
241      *
242      * @return the account
243      */
244     public char[] getAccount() {
245         return hasInfoSet
246                 ? theInfoSet.getValue(MoneyWiseAccountInfoClass.ACCOUNT, char[].class)
247                 : null;
248     }
249 
250     /**
251      * Obtain Notes.
252      *
253      * @return the notes
254      */
255     public char[] getNotes() {
256         return hasInfoSet
257                 ? theInfoSet.getValue(MoneyWiseAccountInfoClass.NOTES, char[].class)
258                 : null;
259     }
260 
261     @Override
262     public OceanusMoney getOpeningBalance() {
263         return hasInfoSet
264                 ? theInfoSet.getValue(MoneyWiseAccountInfoClass.OPENINGBALANCE, OceanusMoney.class)
265                 : null;
266     }
267 
268     @Override
269     public MoneyWiseDepositCategory getCategory() {
270         return getValues().getValue(MoneyWiseBasicResource.CATEGORY_NAME, MoneyWiseDepositCategory.class);
271     }
272 
273     /**
274      * Obtain CategoryId.
275      *
276      * @return the categoryId
277      */
278     public Integer getCategoryId() {
279         final MoneyWiseDepositCategory myCategory = getCategory();
280         return myCategory == null
281                 ? null
282                 : myCategory.getIndexedId();
283     }
284 
285     /**
286      * Obtain CategoryName.
287      *
288      * @return the categoryName
289      */
290     public String getCategoryName() {
291         final MoneyWiseDepositCategory myCategory = getCategory();
292         return myCategory == null
293                 ? null
294                 : myCategory.getName();
295     }
296 
297     /**
298      * Obtain DepositCategoryClass.
299      *
300      * @return the categoryClass
301      */
302     public MoneyWiseDepositCategoryClass getCategoryClass() {
303         final MoneyWiseDepositCategory myCategory = getCategory();
304         return myCategory == null
305                 ? null
306                 : myCategory.getCategoryTypeClass();
307     }
308 
309     @Override
310     public boolean isGross() {
311         final MoneyWiseDepositCategory myCategory = getCategory();
312         final MoneyWiseDepositCategoryClass myClass = myCategory == null ? null : myCategory.getCategoryTypeClass();
313         return myClass != null && myClass.isGross();
314     }
315 
316     @Override
317     public boolean isTaxFree() {
318         final MoneyWiseDepositCategory myCategory = getCategory();
319         final MoneyWiseDepositCategoryClass myClass = myCategory == null ? null : myCategory.getCategoryTypeClass();
320         return myClass != null && myClass.isTaxFree();
321     }
322 
323     @Override
324     public boolean isForeign() {
325         final MoneyWiseCurrency myDefault = getDataSet().getReportingCurrency();
326         return !myDefault.equals(getAssetCurrency());
327     }
328 
329     @Override
330     public MoneyWiseDeposit getBase() {
331         return (MoneyWiseDeposit) super.getBase();
332     }
333 
334     @Override
335     public MoneyWiseDepositList getList() {
336         return (MoneyWiseDepositList) super.getList();
337     }
338 
339     @Override
340     public MetisDataState getState() {
341         /* Pop history for self */
342         MetisDataState myState = super.getState();
343 
344         /* If we should use the InfoSet */
345         if ((myState == MetisDataState.CLEAN) && useInfoSet) {
346             /* Get state for infoSet */
347             myState = theInfoSet.getState();
348         }
349 
350         /* Return the state */
351         return myState;
352     }
353 
354     @Override
355     public MetisDataEditState getEditState() {
356         /* Pop history for self */
357         MetisDataEditState myState = super.getEditState();
358 
359         /* If we should use the InfoSet */
360         if (myState == MetisDataEditState.CLEAN
361                 && useInfoSet) {
362             /* Get state for infoSet */
363             myState = theInfoSet.getEditState();
364         }
365 
366         /* Return the state */
367         return myState;
368     }
369 
370     @Override
371     public boolean hasHistory() {
372         /* Check for history for self */
373         boolean hasHistory = super.hasHistory();
374 
375         /* If we should use the InfoSet */
376         if (!hasHistory && useInfoSet) {
377             /* Check history for infoSet */
378             hasHistory = theInfoSet.hasHistory();
379         }
380 
381         /* Return details */
382         return hasHistory;
383     }
384 
385     @Override
386     public void pushHistory() {
387         /* Push history for self */
388         super.pushHistory();
389 
390         /* If we should use the InfoSet */
391         if (useInfoSet) {
392             /* Push history for infoSet */
393             theInfoSet.pushHistory();
394         }
395     }
396 
397     @Override
398     public void popHistory() {
399         /* Pop history for self */
400         super.popHistory();
401 
402         /* If we should use the InfoSet */
403         if (useInfoSet) {
404             /* Pop history for infoSet */
405             theInfoSet.popHistory();
406         }
407     }
408 
409     @Override
410     public boolean checkForHistory() {
411         /* Check for history for self */
412         boolean bChanges = super.checkForHistory();
413 
414         /* If we should use the InfoSet */
415         if (useInfoSet) {
416             /* Check for history for infoSet */
417             bChanges |= theInfoSet.checkForHistory();
418         }
419 
420         /* return result */
421         return bChanges;
422     }
423 
424     @Override
425     public MetisDataDifference fieldChanged(final MetisDataFieldId pField) {
426         /* Handle InfoSet fields */
427         final MoneyWiseAccountInfoClass myClass = MoneyWiseDepositInfoSet.getClassForField(pField);
428         if (myClass != null) {
429             return useInfoSet
430                     ? theInfoSet.fieldChanged(myClass)
431                     : MetisDataDifference.IDENTICAL;
432         }
433 
434         /* Check super fields */
435         return super.fieldChanged(pField);
436     }
437 
438     @Override
439     public void setDeleted(final boolean bDeleted) {
440         /* Pass call to infoSet if required */
441         if (useInfoSet) {
442             theInfoSet.setDeleted(bDeleted);
443         }
444 
445         /* Pass call onwards */
446         super.setDeleted(bDeleted);
447     }
448 
449     /**
450      * Is this deposit the required class.
451      *
452      * @param pClass the required deposit class.
453      * @return true/false
454      */
455     public boolean isDepositClass(final MoneyWiseDepositCategoryClass pClass) {
456         /* Check for match */
457         return getCategoryClass() == pClass;
458     }
459 
460     /**
461      * Set defaults.
462      *
463      * @throws OceanusException on error
464      */
465     public void setDefaults() throws OceanusException {
466         getList().getValidator().setDefaults(this);
467     }
468 
469     /**
470      * autoCorrect values after change.
471      *
472      * @throws OceanusException on error
473      */
474     public void autoCorrect() throws OceanusException {
475         getList().getValidator().autoCorrect(this);
476     }
477 
478     @Override
479     public int compareValues(final PrometheusDataItem pThat) {
480         /* Check the category and then the name */
481         final MoneyWiseDeposit myThat = (MoneyWiseDeposit) pThat;
482         int iDiff = MetisDataDifference.compareObject(getCategory(), myThat.getCategory());
483         if (iDiff == 0) {
484             iDiff = MetisDataDifference.compareObject(getName(), myThat.getName());
485         }
486         return iDiff;
487     }
488 
489     @Override
490     public void resolveDataSetLinks() throws OceanusException {
491         /* Update the Encryption details */
492         super.resolveDataSetLinks();
493 
494         /* Resolve data links */
495         final MoneyWiseDataSet myData = getDataSet();
496         resolveDataLink(MoneyWiseBasicResource.CATEGORY_NAME, myData.getDepositCategories());
497         resolveDataLink(MoneyWiseStaticDataType.CURRENCY, myData.getAccountCurrencies());
498         resolveDataLink(MoneyWiseBasicResource.ASSET_PARENT, myData.getPayees());
499     }
500 
501     @Override
502     protected void resolveEditSetLinks() throws OceanusException {
503         /* Access the editSet */
504         final PrometheusEditSet myEditSet = getList().getEditSet();
505 
506         /* Resolve Parent/Category/Currency if required */
507         resolveDataLink(MoneyWiseBasicResource.ASSET_PARENT, myEditSet.getDataList(MoneyWiseBasicDataType.PAYEE, MoneyWisePayeeList.class));
508         if (myEditSet.hasDataType(MoneyWiseBasicDataType.DEPOSITCATEGORY)) {
509             resolveDataLink(MoneyWiseBasicResource.CATEGORY_NAME, myEditSet.getDataList(MoneyWiseBasicDataType.DEPOSITCATEGORY, MoneyWiseDepositCategoryList.class));
510         }
511         if (myEditSet.hasDataType(MoneyWiseStaticDataType.CURRENCY)) {
512             resolveDataLink(MoneyWiseStaticDataType.CURRENCY, myEditSet.getDataList(MoneyWiseStaticDataType.CURRENCY, MoneyWiseCurrencyList.class));
513         }
514 
515         /* Resolve links in infoSet */
516         theInfoSet.resolveEditSetLinks(myEditSet);
517     }
518 
519     /**
520      * Set a new Maturity.
521      *
522      * @param pMaturity the new maturity
523      * @throws OceanusException on error
524      */
525     public void setMaturity(final OceanusDate pMaturity) throws OceanusException {
526         setInfoSetValue(MoneyWiseAccountInfoClass.MATURITY, pMaturity);
527     }
528 
529     /**
530      * Set a new SortCode.
531      *
532      * @param pSortCode the new sort code
533      * @throws OceanusException on error
534      */
535     public void setSortCode(final char[] pSortCode) throws OceanusException {
536         setInfoSetValue(MoneyWiseAccountInfoClass.SORTCODE, pSortCode);
537     }
538 
539     /**
540      * Set a new Account.
541      *
542      * @param pAccount the new account
543      * @throws OceanusException on error
544      */
545     public void setAccount(final char[] pAccount) throws OceanusException {
546         setInfoSetValue(MoneyWiseAccountInfoClass.ACCOUNT, pAccount);
547     }
548 
549     /**
550      * Set a new Reference.
551      *
552      * @param pReference the new reference
553      * @throws OceanusException on error
554      */
555     public void setReference(final char[] pReference) throws OceanusException {
556         setInfoSetValue(MoneyWiseAccountInfoClass.REFERENCE, pReference);
557     }
558 
559     /**
560      * Set a new Notes.
561      *
562      * @param pNotes the new notes
563      * @throws OceanusException on error
564      */
565     public void setNotes(final char[] pNotes) throws OceanusException {
566         setInfoSetValue(MoneyWiseAccountInfoClass.NOTES, pNotes);
567     }
568 
569     /**
570      * Set a new opening balance.
571      *
572      * @param pBalance the new opening balance
573      * @throws OceanusException on error
574      */
575     public void setOpeningBalance(final OceanusMoney pBalance) throws OceanusException {
576         setInfoSetValue(MoneyWiseAccountInfoClass.OPENINGBALANCE, pBalance);
577     }
578 
579     /**
580      * Set an infoSet value.
581      *
582      * @param pInfoClass the class of info to set
583      * @param pValue     the value to set
584      * @throws OceanusException on error
585      */
586     private void setInfoSetValue(final MoneyWiseAccountInfoClass pInfoClass,
587                                  final Object pValue) throws OceanusException {
588         /* Reject if there is no infoSet */
589         if (!hasInfoSet) {
590             throw new MoneyWiseLogicException(ERROR_BADINFOSET);
591         }
592 
593         /* Set the value */
594         theInfoSet.setValue(pInfoClass, pValue);
595     }
596 
597     @Override
598     public void adjustClosed() throws OceanusException {
599         /* Adjust closed date */
600         super.adjustClosed();
601 
602         /* If the maturity is null for a bond set it to close date */
603         if (isDepositClass(MoneyWiseDepositCategoryClass.BOND) && getMaturity() == null) {
604             /* Record a date for maturity */
605             setMaturity(getCloseDate());
606         }
607     }
608 
609     @Override
610     public MoneyWiseTransCategory getDetailedCategory(final MoneyWiseTransCategory pCategory,
611                                                       final MoneyWiseTaxCredit pYear) {
612         /* Switch on category type */
613         final MoneyWiseTransCategoryList myCategories = getDataSet().getTransCategories();
614         switch (pCategory.getCategoryTypeClass()) {
615             case INTEREST:
616                 if (isTaxFree()) {
617                     return myCategories.getSingularClass(MoneyWiseTransCategoryClass.TAXFREEINTEREST);
618                 }
619                 if (isDepositClass(MoneyWiseDepositCategoryClass.PEER2PEER)) {
620                     return myCategories.getSingularClass(MoneyWiseTransCategoryClass.PEER2PEERINTEREST);
621                 }
622                 return myCategories.getSingularClass(isGross()
623                         || !pYear.isTaxCreditRequired()
624                         ? MoneyWiseTransCategoryClass.GROSSINTEREST
625                         : MoneyWiseTransCategoryClass.TAXEDINTEREST);
626             case LOYALTYBONUS:
627                 if (isTaxFree()) {
628                     return myCategories.getSingularClass(MoneyWiseTransCategoryClass.TAXFREELOYALTYBONUS);
629                 }
630                 return myCategories.getSingularClass(isGross()
631                         || !pYear.isTaxCreditRequired()
632                         ? MoneyWiseTransCategoryClass.GROSSLOYALTYBONUS
633                         : MoneyWiseTransCategoryClass.TAXEDLOYALTYBONUS);
634             default:
635                 return pCategory;
636         }
637     }
638 
639     @Override
640     public void touchUnderlyingItems() {
641         /* touch the category and currency */
642         getCategory().touchItem(this);
643         getAssetCurrency().touchItem(this);
644 
645         /* Touch parent */
646         getParent().touchItem(this);
647 
648         /* touch infoSet items */
649         theInfoSet.touchUnderlyingItems();
650     }
651 
652     @Override
653     public void touchOnUpdate() {
654         /* Reset touches from update set */
655         clearTouches(MoneyWiseBasicDataType.DEPOSITRATE);
656         clearTouches(MoneyWiseBasicDataType.PORTFOLIO);
657 
658         /* Touch parent */
659         getParent().touchItem(this);
660     }
661 
662     /**
663      * Update base deposit from an edited deposit.
664      *
665      * @param pDeposit the edited deposit
666      * @return whether changes have been made
667      */
668     @Override
669     public boolean applyChanges(final PrometheusDataItem pDeposit) {
670         /* Can only update from a deposit */
671         if (!(pDeposit instanceof MoneyWiseDeposit)) {
672             return false;
673         }
674         final MoneyWiseDeposit myDeposit = (MoneyWiseDeposit) pDeposit;
675 
676         /* Store the current detail into history */
677         pushHistory();
678 
679         /* Apply basic changes */
680         applyBasicChanges(myDeposit);
681 
682         /* Check for changes */
683         return checkForHistory();
684     }
685 
686     @Override
687     public void adjustMapForItem() {
688         final MoneyWiseDepositList myList = getList();
689         final MoneyWiseDepositDataMap myMap = myList.getDataMap();
690         myMap.adjustForItem(this);
691     }
692 
693     @Override
694     public void removeItem() {
695         theInfoSet.removeItems();
696         super.removeItem();
697     }
698 
699     /**
700      * The Deposit List class.
701      */
702     public static class MoneyWiseDepositList
703             extends MoneyWiseAssetBaseList<MoneyWiseDeposit> {
704         /**
705          * Report fields.
706          */
707         private static final MetisFieldSet<MoneyWiseDepositList> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseDepositList.class);
708 
709         /**
710          * The DepositInfo List.
711          */
712         private MoneyWiseDepositInfoList theInfoList;
713 
714         /**
715          * The AccountInfoType list.
716          */
717         private MoneyWiseAccountInfoTypeList theInfoTypeList;
718 
719         /**
720          * Construct an empty CORE list.
721          *
722          * @param pData the DataSet for the list
723          */
724         public MoneyWiseDepositList(final MoneyWiseDataSet pData) {
725             super(pData, MoneyWiseDeposit.class, MoneyWiseBasicDataType.DEPOSIT);
726         }
727 
728         /**
729          * Constructor for a cloned List.
730          *
731          * @param pSource the source List
732          */
733         protected MoneyWiseDepositList(final MoneyWiseDepositList pSource) {
734             super(pSource);
735         }
736 
737         @Override
738         public MetisFieldSet<MoneyWiseDepositList> getDataFieldSet() {
739             return FIELD_DEFS;
740         }
741 
742         @Override
743         public String listName() {
744             return LIST_NAME;
745         }
746 
747         @Override
748         public MetisFieldSetDef getItemFields() {
749             return MoneyWiseDeposit.FIELD_DEFS;
750         }
751 
752         @Override
753         protected MoneyWiseDepositDataMap getDataMap() {
754             return (MoneyWiseDepositDataMap) super.getDataMap();
755         }
756 
757         /**
758          * Obtain the depositInfoList.
759          *
760          * @return the deposit info list
761          */
762         public MoneyWiseDepositInfoList getDepositInfo() {
763             if (theInfoList == null) {
764                 theInfoList = getDataSet().getDepositInfo();
765             }
766             return theInfoList;
767         }
768 
769         /**
770          * Obtain the accountInfoTypeList.
771          *
772          * @return the account info type list
773          */
774         public MoneyWiseAccountInfoTypeList getActInfoTypes() {
775             if (theInfoTypeList == null) {
776                 theInfoTypeList = getEditSet() == null
777                         ? getDataSet().getActInfoTypes()
778                         : getEditSet().getDataList(MoneyWiseStaticDataType.ACCOUNTINFOTYPE, MoneyWiseAccountInfoTypeList.class);
779             }
780             return theInfoTypeList;
781         }
782 
783         @Override
784         protected MoneyWiseDepositList getEmptyList(final PrometheusListStyle pStyle) {
785             final MoneyWiseDepositList myList = new MoneyWiseDepositList(this);
786             myList.setStyle(pStyle);
787             return myList;
788         }
789 
790         /**
791          * Derive Edit list.
792          *
793          * @param pEditSet the editSet
794          * @return the edit list
795          * @throws OceanusException on error
796          */
797         public MoneyWiseDepositList deriveEditList(final PrometheusEditSet pEditSet) throws OceanusException {
798             /* Build an empty List */
799             final MoneyWiseDepositList myList = getEmptyList(PrometheusListStyle.EDIT);
800             final MoneyWisePayeeList myPayees = pEditSet.getDataList(MoneyWiseBasicDataType.PAYEE, MoneyWisePayeeList.class);
801             myList.ensureMap(myPayees);
802             pEditSet.setEditEntryList(MoneyWiseBasicDataType.DEPOSIT, myList);
803             myList.getValidator().setEditSet(pEditSet);
804 
805             /* Store InfoType list */
806             myList.theInfoTypeList = pEditSet.getDataList(MoneyWiseStaticDataType.ACCOUNTINFOTYPE, MoneyWiseAccountInfoTypeList.class);
807 
808             /* Create info List */
809             final MoneyWiseDepositInfoList myDepInfo = getDepositInfo();
810             myList.theInfoList = myDepInfo.getEmptyList(PrometheusListStyle.EDIT);
811             pEditSet.setEditEntryList(MoneyWiseBasicDataType.DEPOSITINFO, myList.theInfoList);
812 
813             /* Store the editSet */
814             myList.setEditSet(pEditSet);
815 
816             /* Loop through the deposits */
817             final Iterator<MoneyWiseDeposit> myIterator = iterator();
818             while (myIterator.hasNext()) {
819                 final MoneyWiseDeposit myCurr = myIterator.next();
820 
821                 /* Ignore deleted deposits */
822                 if (myCurr.isDeleted()) {
823                     continue;
824                 }
825 
826                 /* Build the new linked deposit and add it to the list */
827                 final MoneyWiseDeposit myDeposit = new MoneyWiseDeposit(myList, myCurr);
828                 myList.add(myDeposit);
829                 myDeposit.resolveEditSetLinks();
830 
831                 /* Adjust the map */
832                 myDeposit.adjustMapForItem();
833             }
834 
835             /* Return the list */
836             return myList;
837         }
838 
839         @Override
840         public MoneyWiseDeposit findItemByName(final String pName) {
841             /* look up the name in the map */
842             return getDataMap().findItemByName(pName);
843         }
844 
845         @Override
846         public boolean checkAvailableName(final String pName) {
847             /* check availability in map */
848             return getDataMap().availableName(pName);
849         }
850 
851         @Override
852         public boolean validNameCount(final String pName) {
853             /* check availability in map */
854             return getDataMap().validNameCount(pName);
855         }
856 
857         @Override
858         public MoneyWiseDeposit addCopyItem(final PrometheusDataItem pDeposit) {
859             /* Can only clone a Deposit */
860             if (!(pDeposit instanceof MoneyWiseDeposit)) {
861                 throw new UnsupportedOperationException();
862             }
863 
864             final MoneyWiseDeposit myDeposit = new MoneyWiseDeposit(this, (MoneyWiseDeposit) pDeposit);
865             add(myDeposit);
866             return myDeposit;
867         }
868 
869         @Override
870         public MoneyWiseDeposit addNewItem() {
871             final MoneyWiseDeposit myDeposit = new MoneyWiseDeposit(this);
872             add(myDeposit);
873             return myDeposit;
874         }
875 
876         @Override
877         public MoneyWiseDeposit addValuesItem(final PrometheusDataValues pValues) throws OceanusException {
878             /* Create the deposit */
879             final MoneyWiseDeposit myDeposit = new MoneyWiseDeposit(this, pValues);
880 
881             /* Check that this DepositId has not been previously added */
882             if (!isIdUnique(myDeposit.getIndexedId())) {
883                 myDeposit.addError(ERROR_DUPLICATE, MetisDataResource.DATA_ID);
884                 throw new MoneyWiseDataException(myDeposit, ERROR_VALIDATION);
885             }
886 
887             /* Add to the list */
888             add(myDeposit);
889 
890             /* Loop through the info items */
891             if (pValues.hasInfoItems()) {
892                 /* Loop through the items */
893                 final Iterator<PrometheusInfoItem> myIterator = pValues.infoIterator();
894                 while (myIterator.hasNext()) {
895                     final PrometheusInfoItem myItem = myIterator.next();
896 
897                     /* Build info */
898                     final PrometheusDataValues myValues = myItem.getValues(myDeposit);
899                     theInfoList.addValuesItem(myValues);
900                 }
901             }
902 
903             /* Return it */
904             return myDeposit;
905         }
906 
907         /**
908          * Obtain default holding for portfolio.
909          *
910          * @param pParent   the parent
911          * @param isTaxFree should holding be taxFree?
912          * @return the default holding
913          */
914         public MoneyWiseDeposit getDefaultHolding(final MoneyWisePayee pParent,
915                                                   final boolean isTaxFree) {
916             /* loop through the deposits */
917             final Iterator<MoneyWiseDeposit> myIterator = iterator();
918             while (myIterator.hasNext()) {
919                 final MoneyWiseDeposit myDeposit = myIterator.next();
920 
921                 /* Ignore deleted and closed deposits and wrong taxFree status */
922                 boolean bIgnore = myDeposit.isDeleted() || myDeposit.isClosed();
923                 bIgnore |= !pParent.equals(myDeposit.getParent());
924                 bIgnore |= !isTaxFree == myDeposit.isTaxFree();
925                 if (!bIgnore) {
926                     return myDeposit;
927                 }
928             }
929 
930             /* Return no deposit */
931             return null;
932         }
933 
934         /**
935          * Ensure Map based on the payee list.
936          *
937          * @param pPayees the payee list
938          */
939         private void ensureMap(final MoneyWisePayeeList pPayees) {
940             setDataMap(new MoneyWiseDepositDataMap(pPayees));
941         }
942 
943         @Override
944         protected MoneyWiseDepositDataMap allocateDataMap() {
945             return new MoneyWiseDepositDataMap(getDataSet().getPayees());
946         }
947 
948         @Override
949         public void postProcessOnLoad() throws OceanusException {
950             /* Resolve links and sort the data */
951             super.resolveDataSetLinks();
952             reSort();
953         }
954     }
955 
956     /**
957      * The dataMap class.
958      */
959     protected static class MoneyWiseDepositDataMap
960             implements PrometheusDataMapItem, MetisFieldItem {
961         /**
962          * Report fields.
963          */
964         private static final MetisFieldSet<MoneyWiseDepositDataMap> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseDepositDataMap.class);
965 
966         /*
967          * UnderlyingMap Field Id.
968          */
969         static {
970             FIELD_DEFS.declareLocalField(MoneyWiseBasicResource.MONEYWISEDATA_MAP_UNDERLYING, MoneyWiseDepositDataMap::getUnderlyingMap);
971         }
972 
973         /**
974          * The assetMap.
975          */
976         private final MoneyWiseAssetDataMap theUnderlyingMap;
977 
978         /**
979          * Constructor.
980          *
981          * @param pPayees the payee list
982          */
983         protected MoneyWiseDepositDataMap(final MoneyWisePayeeList pPayees) {
984             theUnderlyingMap = pPayees.getDataMap().getUnderlyingMap();
985         }
986 
987         @Override
988         public MetisFieldSet<MoneyWiseDepositDataMap> getDataFieldSet() {
989             return FIELD_DEFS;
990         }
991 
992         @Override
993         public String formatObject(final OceanusDataFormatter pFormatter) {
994             return FIELD_DEFS.getName();
995         }
996 
997         /**
998          * Obtain the underlying map.
999          *
1000          * @return the underlying map
1001          */
1002         private MoneyWiseAssetDataMap getUnderlyingMap() {
1003             return theUnderlyingMap;
1004         }
1005 
1006         @Override
1007         public void resetMap() {
1008             /* No action */
1009         }
1010 
1011         @Override
1012         public void adjustForItem(final PrometheusDataItem pItem) {
1013             /* Adjust name count */
1014             theUnderlyingMap.adjustForItem(pItem);
1015         }
1016 
1017         /**
1018          * find item by name.
1019          *
1020          * @param pName the name to look up
1021          * @return the matching item
1022          */
1023         public MoneyWiseDeposit findItemByName(final String pName) {
1024             final MoneyWiseAssetBase myAsset = theUnderlyingMap.findAssetByName(pName);
1025             return myAsset instanceof MoneyWiseDeposit myDeposit
1026                     ? myDeposit
1027                     : null;
1028         }
1029 
1030         /**
1031          * Check validity of name.
1032          *
1033          * @param pName the name to look up
1034          * @return true/false
1035          */
1036         public boolean validNameCount(final String pName) {
1037             return theUnderlyingMap.validNameCount(pName);
1038         }
1039 
1040         /**
1041          * Check availability of name.
1042          *
1043          * @param pName the key to look up
1044          * @return true/false
1045          */
1046         public boolean availableName(final String pName) {
1047             return theUnderlyingMap.availableKey(pName);
1048         }
1049     }
1050 }