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.MetisDataItem.MetisDataFieldId;
21  import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataNamedItem;
22  import io.github.tonywasher.joceanus.metis.data.MetisDataResource;
23  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDataValidator.MoneyWiseDataValidatorDefaults;
25  import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseDataException;
26  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
27  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
28  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataInstanceMap;
29  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataItem;
30  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
31  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataSet;
32  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataValues;
33  import io.github.tonywasher.joceanus.prometheus.data.PrometheusEncryptedDataItem;
34  import io.github.tonywasher.joceanus.prometheus.data.PrometheusEncryptedFieldSet;
35  import io.github.tonywasher.joceanus.prometheus.data.PrometheusEncryptedPair;
36  import io.github.tonywasher.joceanus.prometheus.data.PrometheusListStyle;
37  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
38  
39  import java.util.Iterator;
40  
41  /**
42   * Region for a Unit Trust.
43   */
44  public class MoneyWiseRegion
45          extends PrometheusEncryptedDataItem
46          implements MetisDataNamedItem {
47      /**
48       * Object name.
49       */
50      public static final String OBJECT_NAME = MoneyWiseBasicDataType.REGION.getItemName();
51  
52      /**
53       * List name.
54       */
55      public static final String LIST_NAME = MoneyWiseBasicDataType.REGION.getListName();
56  
57      /**
58       * Local Report fields.
59       */
60      private static final PrometheusEncryptedFieldSet<MoneyWiseRegion> FIELD_DEFS = PrometheusEncryptedFieldSet.newEncryptedFieldSet(MoneyWiseRegion.class);
61  
62      /*
63       * FieldIds.
64       */
65      static {
66          FIELD_DEFS.declareEncryptedStringField(PrometheusDataResource.DATAITEM_FIELD_NAME, NAMELEN);
67          FIELD_DEFS.declareEncryptedStringField(PrometheusDataResource.DATAITEM_FIELD_DESC, DESCLEN);
68      }
69  
70      /**
71       * Copy Constructor.
72       *
73       * @param pList   the list
74       * @param pRegion The region to copy
75       */
76      protected MoneyWiseRegion(final MoneyWiseRegionList pList,
77                                final MoneyWiseRegion pRegion) {
78          /* Set standard values */
79          super(pList, pRegion);
80      }
81  
82      /**
83       * Values constructor.
84       *
85       * @param pList   the List to add to
86       * @param pValues the values constructor
87       * @throws OceanusException on error
88       */
89      private MoneyWiseRegion(final MoneyWiseRegionList pList,
90                              final PrometheusDataValues pValues) throws OceanusException {
91          /* Initialise the item */
92          super(pList, pValues);
93  
94          /* Protect against exceptions */
95          try {
96              /* Store the Name */
97              Object myValue = pValues.getValue(PrometheusDataResource.DATAITEM_FIELD_NAME);
98              if (myValue instanceof String s) {
99                  setValueName(s);
100             } else if (myValue instanceof byte[] ba) {
101                 setValueName(ba);
102             }
103 
104             /* Store the Description */
105             myValue = pValues.getValue(PrometheusDataResource.DATAITEM_FIELD_DESC);
106             if (myValue instanceof String s) {
107                 setValueDesc(s);
108             } else if (myValue instanceof byte[] ba) {
109                 setValueDesc(ba);
110             }
111 
112             /* Catch Exceptions */
113         } catch (OceanusException e) {
114             /* Pass on exception */
115             throw new MoneyWiseDataException(this, ERROR_CREATEITEM, e);
116         }
117     }
118 
119     /**
120      * Edit Constructor.
121      *
122      * @param pList the list
123      */
124     public MoneyWiseRegion(final MoneyWiseRegionList pList) {
125         super(pList, 0);
126         setNextDataKeySet();
127     }
128 
129     @Override
130     public MetisFieldSetDef getDataFieldSet() {
131         return FIELD_DEFS;
132     }
133 
134     @Override
135     public String formatObject(final OceanusDataFormatter pFormatter) {
136         return toString();
137     }
138 
139     @Override
140     public String toString() {
141         return getName();
142     }
143 
144     @Override
145     public boolean includeXmlField(final MetisDataFieldId pField) {
146         /* Determine whether fields should be included */
147         if (PrometheusDataResource.DATAITEM_FIELD_NAME.equals(pField)) {
148             return true;
149         }
150         if (PrometheusDataResource.DATAITEM_FIELD_DESC.equals(pField)) {
151             return getDesc() != null;
152         }
153 
154         /* Pass call on */
155         return super.includeXmlField(pField);
156     }
157 
158     @Override
159     public String getName() {
160         return getValues().getValue(PrometheusDataResource.DATAITEM_FIELD_NAME, String.class);
161     }
162 
163     /**
164      * Obtain Encrypted name.
165      *
166      * @return the bytes
167      */
168     public byte[] getNameBytes() {
169         return getValues().getEncryptedBytes(PrometheusDataResource.DATAITEM_FIELD_NAME);
170     }
171 
172     /**
173      * Obtain Encrypted Name Field.
174      *
175      * @return the Field
176      */
177     private PrometheusEncryptedPair getNameField() {
178         return getValues().getEncryptedPair(PrometheusDataResource.DATAITEM_FIELD_NAME);
179     }
180 
181     /**
182      * Obtain Description.
183      *
184      * @return the description
185      */
186     public String getDesc() {
187         return getValues().getValue(PrometheusDataResource.DATAITEM_FIELD_DESC, String.class);
188     }
189 
190     /**
191      * Obtain Encrypted description.
192      *
193      * @return the bytes
194      */
195     public byte[] getDescBytes() {
196         return getValues().getEncryptedBytes(PrometheusDataResource.DATAITEM_FIELD_DESC);
197     }
198 
199     /**
200      * Obtain Encrypted Description Field.
201      *
202      * @return the Field
203      */
204     private PrometheusEncryptedPair getDescField() {
205         return getValues().getEncryptedPair(PrometheusDataResource.DATAITEM_FIELD_DESC);
206     }
207 
208     /**
209      * Set name value.
210      *
211      * @param pValue the value
212      * @throws OceanusException on error
213      */
214     private void setValueName(final String pValue) throws OceanusException {
215         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pValue);
216     }
217 
218     /**
219      * Set name value.
220      *
221      * @param pBytes the value
222      * @throws OceanusException on error
223      */
224     private void setValueName(final byte[] pBytes) throws OceanusException {
225         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pBytes, String.class);
226     }
227 
228     /**
229      * Set name value.
230      *
231      * @param pValue the value
232      */
233     private void setValueName(final PrometheusEncryptedPair pValue) {
234         getValues().setUncheckedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pValue);
235     }
236 
237     /**
238      * Set description value.
239      *
240      * @param pValue the value
241      * @throws OceanusException on error
242      */
243     private void setValueDesc(final String pValue) throws OceanusException {
244         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pValue);
245     }
246 
247     /**
248      * Set description value.
249      *
250      * @param pBytes the value
251      * @throws OceanusException on error
252      */
253     private void setValueDesc(final byte[] pBytes) throws OceanusException {
254         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pBytes, String.class);
255     }
256 
257     /**
258      * Set description value.
259      *
260      * @param pValue the value
261      */
262     private void setValueDesc(final PrometheusEncryptedPair pValue) {
263         getValues().setUncheckedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pValue);
264     }
265 
266     @Override
267     public MoneyWiseRegion getBase() {
268         return (MoneyWiseRegion) super.getBase();
269     }
270 
271     @Override
272     public MoneyWiseRegionList getList() {
273         return (MoneyWiseRegionList) super.getList();
274     }
275 
276     /**
277      * Set defaults.
278      *
279      * @throws OceanusException on error
280      */
281     public void setDefaults() throws OceanusException {
282         getList().getValidator().setDefaults(this);
283     }
284 
285     @Override
286     public int compareValues(final PrometheusDataItem pThat) {
287         /* Check the names */
288         final MoneyWiseRegion myThat = (MoneyWiseRegion) pThat;
289         return MetisDataDifference.compareObject(getName(), myThat.getName());
290     }
291 
292     /**
293      * Set a new tag name.
294      *
295      * @param pName the new name
296      * @throws OceanusException on error
297      */
298     public void setName(final String pName) throws OceanusException {
299         setValueName(pName);
300     }
301 
302     /**
303      * Set a new description.
304      *
305      * @param pDesc the description
306      * @throws OceanusException on error
307      */
308     public void setDescription(final String pDesc) throws OceanusException {
309         setValueDesc(pDesc);
310     }
311 
312     /**
313      * Update base tag from an edited tag.
314      *
315      * @param pTag the edited tag
316      * @return whether changes have been made
317      */
318     @Override
319     public boolean applyChanges(final PrometheusDataItem pTag) {
320         /* Can only update from a region */
321         if (!(pTag instanceof MoneyWiseRegion myRegion)) {
322             return false;
323         }
324 
325         /* Store the current detail into history */
326         pushHistory();
327 
328         /* Update the Name if required */
329         if (!MetisDataDifference.isEqual(getName(), myRegion.getName())) {
330             setValueName(myRegion.getNameField());
331         }
332 
333         /* Update the description if required */
334         if (!MetisDataDifference.isEqual(getDesc(), myRegion.getDesc())) {
335             setValueDesc(myRegion.getDescField());
336         }
337 
338         /* Check for changes */
339         return checkForHistory();
340     }
341 
342     @Override
343     public void adjustMapForItem() {
344         final MoneyWiseRegionList myList = getList();
345         final MoneyWiseRegionDataMap myMap = myList.getDataMap();
346         myMap.adjustForItem(this);
347     }
348 
349     /**
350      * The Region List class.
351      */
352     public static class MoneyWiseRegionList
353             extends PrometheusEncryptedList<MoneyWiseRegion> {
354         /**
355          * Report fields.
356          */
357         private static final MetisFieldSet<MoneyWiseRegionList> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseRegionList.class);
358 
359         /**
360          * Construct an empty CORE Tag list.
361          *
362          * @param pData the DataSet for the list
363          */
364         protected MoneyWiseRegionList(final PrometheusDataSet pData) {
365             super(MoneyWiseRegion.class, pData, MoneyWiseBasicDataType.REGION, PrometheusListStyle.CORE);
366         }
367 
368         /**
369          * Constructor for a cloned List.
370          *
371          * @param pSource the source List
372          */
373         protected MoneyWiseRegionList(final MoneyWiseRegionList pSource) {
374             super(pSource);
375         }
376 
377         @Override
378         public MetisFieldSet<MoneyWiseRegionList> getDataFieldSet() {
379             return FIELD_DEFS;
380         }
381 
382         @Override
383         public String listName() {
384             return LIST_NAME;
385         }
386 
387         @Override
388         public MetisFieldSetDef getItemFields() {
389             return MoneyWiseRegion.FIELD_DEFS;
390         }
391 
392         @Override
393         public MoneyWiseRegionDataMap getDataMap() {
394             return (MoneyWiseRegionDataMap) super.getDataMap();
395         }
396 
397         @Override
398         @SuppressWarnings("unchecked")
399         public MoneyWiseDataValidatorDefaults<MoneyWiseRegion> getValidator() {
400             return (MoneyWiseDataValidatorDefaults<MoneyWiseRegion>) super.getValidator();
401         }
402 
403         @Override
404         protected MoneyWiseRegionList getEmptyList(final PrometheusListStyle pStyle) {
405             final MoneyWiseRegionList myList = new MoneyWiseRegionList(this);
406             myList.setStyle(pStyle);
407             return myList;
408         }
409 
410         /**
411          * Derive Edit list.
412          *
413          * @param pEditSet the editSet
414          * @return the edit list
415          */
416         public MoneyWiseRegionList deriveEditList(final PrometheusEditSet pEditSet) {
417             /* Build an empty List */
418             final MoneyWiseRegionList myList = getEmptyList(PrometheusListStyle.EDIT);
419             myList.ensureMap();
420             pEditSet.setEditEntryList(MoneyWiseBasicDataType.REGION, myList);
421             myList.getValidator().setEditSet(pEditSet);
422 
423             /* Loop through the regions */
424             final Iterator<MoneyWiseRegion> myIterator = iterator();
425             while (myIterator.hasNext()) {
426                 final MoneyWiseRegion myCurr = myIterator.next();
427 
428                 /* Ignore deleted regions */
429                 if (myCurr.isDeleted()) {
430                     continue;
431                 }
432 
433                 /* Build the new linked region and add it to the list */
434                 final MoneyWiseRegion myRegion = new MoneyWiseRegion(myList, myCurr);
435                 myList.add(myRegion);
436 
437                 /* Adjust the map */
438                 myRegion.adjustMapForItem();
439             }
440 
441             /* Return the list */
442             return myList;
443         }
444 
445         /**
446          * Add a new item to the core list.
447          *
448          * @param pRegion item
449          * @return the newly added item
450          */
451         @Override
452         public MoneyWiseRegion addCopyItem(final PrometheusDataItem pRegion) {
453             /* Can only clone a Region */
454             if (!(pRegion instanceof MoneyWiseRegion)) {
455                 throw new UnsupportedOperationException();
456             }
457 
458             final MoneyWiseRegion myRegion = new MoneyWiseRegion(this, (MoneyWiseRegion) pRegion);
459             add(myRegion);
460             return myRegion;
461         }
462 
463         /**
464          * Add a new item to the edit list.
465          *
466          * @return the new item
467          */
468         @Override
469         public MoneyWiseRegion addNewItem() {
470             final MoneyWiseRegion myRegion = new MoneyWiseRegion(this);
471             add(myRegion);
472             return myRegion;
473         }
474 
475         @Override
476         public MoneyWiseRegion findItemByName(final String pName) {
477             /* look up the name in the map */
478             return getDataMap().findItemByName(pName);
479         }
480 
481         @Override
482         public MoneyWiseRegion addValuesItem(final PrometheusDataValues pValues) throws OceanusException {
483             /* Create the region */
484             final MoneyWiseRegion myRegion = new MoneyWiseRegion(this, pValues);
485 
486             /* Check that this regionId has not been previously added */
487             if (!isIdUnique(myRegion.getIndexedId())) {
488                 myRegion.addError(ERROR_DUPLICATE, MetisDataResource.DATA_ID);
489                 throw new MoneyWiseDataException(myRegion, ERROR_VALIDATION);
490             }
491 
492             /* Add to the list */
493             add(myRegion);
494 
495             /* Return it */
496             return myRegion;
497         }
498 
499         @Override
500         protected MoneyWiseRegionDataMap allocateDataMap() {
501             return new MoneyWiseRegionDataMap();
502         }
503     }
504 
505     /**
506      * The dataMap class.
507      */
508     public static class MoneyWiseRegionDataMap
509             extends PrometheusDataInstanceMap<MoneyWiseRegion, String> {
510         @Override
511         public void adjustForItem(final PrometheusDataItem pItem) {
512             /* Access item */
513             final MoneyWiseRegion myItem = (MoneyWiseRegion) pItem;
514 
515             /* Adjust name count */
516             adjustForItem(myItem, myItem.getName());
517         }
518 
519         /**
520          * find item by name.
521          *
522          * @param pName the name to look up
523          * @return the matching item
524          */
525         public MoneyWiseRegion findItemByName(final String pName) {
526             return findItemByKey(pName);
527         }
528 
529         /**
530          * Check validity of name.
531          *
532          * @param pName the name to look up
533          * @return true/false
534          */
535         public boolean validNameCount(final String pName) {
536             return validKeyCount(pName);
537         }
538 
539         /**
540          * Check availability of name.
541          *
542          * @param pName the key to look up
543          * @return true/false
544          */
545         public boolean availableName(final String pName) {
546             return availableKey(pName);
547         }
548     }
549 }