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