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