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