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.metis.data.MetisDataDifference;
21  import io.github.tonywasher.joceanus.metis.data.MetisDataResource;
22  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
23  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseRegion.MoneyWiseRegionList;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity.MoneyWiseSecurityList;
25  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoClass;
26  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoType;
27  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseAccountInfoType.MoneyWiseAccountInfoTypeList;
28  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
29  import io.github.tonywasher.joceanus.moneywise.exc.MoneyWiseDataException;
30  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataInfoClass;
31  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataInfoItem;
32  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataItem;
33  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataResource;
34  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataValues;
35  import io.github.tonywasher.joceanus.prometheus.data.PrometheusStaticDataItem;
36  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
37  
38  /**
39   * Representation of an information extension of a security.
40   *
41   * @author Tony Washer
42   */
43  public class MoneyWiseSecurityInfo
44          extends PrometheusDataInfoItem {
45      /**
46       * Object name.
47       */
48      public static final String OBJECT_NAME = MoneyWiseBasicDataType.SECURITYINFO.getItemName();
49  
50      /**
51       * List name.
52       */
53      public static final String LIST_NAME = MoneyWiseBasicDataType.SECURITYINFO.getListName();
54  
55      /**
56       * Local Report fields.
57       */
58      private static final MetisFieldSet<MoneyWiseSecurityInfo> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseSecurityInfo.class);
59  
60      /**
61       * Copy Constructor.
62       *
63       * @param pList the list
64       * @param pInfo The Info to copy
65       */
66      protected MoneyWiseSecurityInfo(final MoneyWiseSecurityInfoList pList,
67                                      final MoneyWiseSecurityInfo pInfo) {
68          /* Set standard values */
69          super(pList, pInfo);
70      }
71  
72      /**
73       * Edit Constructor.
74       *
75       * @param pList     the list
76       * @param pSecurity the security
77       * @param pType     the type
78       */
79      private MoneyWiseSecurityInfo(final MoneyWiseSecurityInfoList pList,
80                                    final MoneyWiseSecurity pSecurity,
81                                    final MoneyWiseAccountInfoType pType) {
82          /* Initialise the item */
83          super(pList);
84          setNextDataKeySet();
85  
86          /* Record the Detail */
87          setValueInfoType(pType);
88          setValueOwner(pSecurity);
89      }
90  
91      /**
92       * Values constructor.
93       *
94       * @param pList   the List to add to
95       * @param pValues the values constructor
96       * @throws OceanusException on error
97       */
98      private MoneyWiseSecurityInfo(final MoneyWiseSecurityInfoList pList,
99                                    final PrometheusDataValues pValues) throws OceanusException {
100         /* Initialise the item */
101         super(pList, pValues);
102 
103         /* Protect against exceptions */
104         try {
105             /* Resolve links */
106             final MoneyWiseDataSet myData = getDataSet();
107             resolveDataLink(PrometheusDataResource.DATAINFO_TYPE, myData.getActInfoTypes());
108             resolveDataLink(PrometheusDataResource.DATAINFO_OWNER, myData.getSecurities());
109 
110             /* Set the value */
111             setValue(pValues.getValue(PrometheusDataResource.DATAINFO_VALUE));
112 
113             /* Resolve any link value */
114             resolveLink(null);
115 
116             /* Access the SecurityInfoSet and register this data */
117             final MoneyWiseSecurityInfoSet mySet = getOwner().getInfoSet();
118             mySet.registerInfo(this);
119 
120         } catch (OceanusException e) {
121             /* Pass on exception */
122             throw new MoneyWiseDataException(this, ERROR_CREATEITEM, e);
123         }
124     }
125 
126     @Override
127     public MetisFieldSetDef getDataFieldSet() {
128         return FIELD_DEFS;
129     }
130 
131     @Override
132     public MoneyWiseAccountInfoType getInfoType() {
133         return getValues().getValue(PrometheusDataResource.DATAINFO_TYPE, MoneyWiseAccountInfoType.class);
134     }
135 
136     @Override
137     public MoneyWiseAccountInfoClass getInfoClass() {
138         return getInfoType().getInfoClass();
139     }
140 
141     @Override
142     public MoneyWiseSecurity getOwner() {
143         return getValues().getValue(PrometheusDataResource.DATAINFO_OWNER, MoneyWiseSecurity.class);
144     }
145 
146     /**
147      * Obtain Region.
148      *
149      * @return the Region
150      */
151     public MoneyWiseRegion getRegion() {
152         return getValues().getValue(PrometheusDataResource.DATAINFO_LINK, MoneyWiseRegion.class);
153     }
154 
155     /**
156      * Obtain Security.
157      *
158      * @return the Security
159      */
160     public MoneyWiseSecurity getSecurity() {
161         return getValues().getValue(PrometheusDataResource.DATAINFO_LINK, MoneyWiseSecurity.class);
162     }
163 
164     @Override
165     public String getLinkName() {
166         final PrometheusDataItem myItem = getLink();
167         if (myItem instanceof MoneyWiseRegion myRegion) {
168             return myRegion.getName();
169         }
170         if (myItem instanceof MoneyWiseSecurity mySecurity) {
171             return mySecurity.getName();
172         }
173         return null;
174     }
175 
176     @Override
177     public MoneyWiseDataSet getDataSet() {
178         return (MoneyWiseDataSet) super.getDataSet();
179     }
180 
181     @Override
182     public MoneyWiseSecurityInfo getBase() {
183         return (MoneyWiseSecurityInfo) super.getBase();
184     }
185 
186     @Override
187     public MoneyWiseSecurityInfoList getList() {
188         return (MoneyWiseSecurityInfoList) super.getList();
189     }
190 
191     @Override
192     public void deRegister() {
193         /* Access the SecurityInfoSet and register this value */
194         final MoneyWiseSecurityInfoSet mySet = getOwner().getInfoSet();
195         mySet.deRegisterInfo(this);
196     }
197 
198     @Override
199     public void resolveDataSetLinks() throws OceanusException {
200         /* Update the Encryption details */
201         super.resolveDataSetLinks();
202 
203         /* Resolve data links */
204         final MoneyWiseDataSet myData = getDataSet();
205         resolveDataLink(PrometheusDataResource.DATAINFO_TYPE, myData.getActInfoTypes());
206         resolveDataLink(PrometheusDataResource.DATAINFO_OWNER, myData.getSecurities());
207 
208         /* Resolve any link value */
209         resolveLink(null);
210 
211         /* Access the SecurityInfoSet and register this data */
212         final MoneyWiseSecurityInfoSet mySet = getOwner().getInfoSet();
213         mySet.registerInfo(this);
214     }
215 
216     /**
217      * resolve editSet links.
218      *
219      * @param pEditSet the edit set
220      * @throws OceanusException on error
221      */
222     public void resolveEditSetLinks(final PrometheusEditSet pEditSet) throws OceanusException {
223         /* Update the Encryption details */
224         super.resolveDataSetLinks();
225 
226         /* Resolve data links */
227         resolveDataLink(PrometheusDataResource.DATAINFO_TYPE, pEditSet.getDataList(MoneyWiseStaticDataType.ACCOUNTINFOTYPE, MoneyWiseAccountInfoTypeList.class));
228         resolveDataLink(PrometheusDataResource.DATAINFO_OWNER, pEditSet.getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class));
229 
230         /* Resolve any link value */
231         resolveLink(pEditSet);
232     }
233 
234     /**
235      * Resolve link reference.
236      *
237      * @param pEditSet the edit set
238      * @throws OceanusException on error
239      */
240     private void resolveLink(final PrometheusEditSet pEditSet) throws OceanusException {
241         /* If we have a link */
242         final MoneyWiseAccountInfoType myType = getInfoType();
243         if (myType.isLink()) {
244             /* Access data */
245             final MoneyWiseDataSet myData = getDataSet();
246             final Object myLinkId = getValues().getValue(PrometheusDataResource.DATAINFO_VALUE);
247 
248             /* Switch on link type */
249             switch (myType.getInfoClass()) {
250                 case REGION:
251                     resolveDataLink(PrometheusDataResource.DATAINFO_LINK, pEditSet == null
252                             ? myData.getRegions()
253                             : pEditSet.getDataList(MoneyWiseBasicDataType.REGION, MoneyWiseRegionList.class));
254                     if (myLinkId == null) {
255                         setValueValue(getRegion().getIndexedId());
256                     }
257                     break;
258                 case UNDERLYINGSTOCK:
259                     resolveDataLink(PrometheusDataResource.DATAINFO_LINK, pEditSet == null
260                             ? myData.getSecurities()
261                             : pEditSet.getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class));
262                     if (myLinkId == null) {
263                         setValueValue(getSecurity().getIndexedId());
264                     }
265                     break;
266                 default:
267                     break;
268             }
269         }
270     }
271 
272     /**
273      * Update securityInfo from a securityInfo extract.
274      *
275      * @param pInfo the changed securityInfo
276      * @return whether changes have been made
277      */
278     @Override
279     public boolean applyChanges(final PrometheusDataItem pInfo) {
280         /* Can only update from SecurityInfo */
281         if (!(pInfo instanceof MoneyWiseSecurityInfo)) {
282             return false;
283         }
284 
285         /* Access as SecurityInfo */
286         final MoneyWiseSecurityInfo mySecInfo = (MoneyWiseSecurityInfo) pInfo;
287 
288         /* Store the current detail into history */
289         pushHistory();
290 
291         /* Update the value if required */
292         if (!MetisDataDifference.isEqual(getField(), mySecInfo.getField())) {
293             setValueValue(mySecInfo.getField());
294         }
295 
296         /* Check for changes */
297         return checkForHistory();
298     }
299 
300     @Override
301     public void touchUnderlyingItems() {
302         /* touch info class */
303         super.touchUnderlyingItems();
304 
305         /* Switch on info class */
306         switch (getInfoClass()) {
307             case UNDERLYINGSTOCK:
308                 getSecurity().touchItem(getOwner());
309                 break;
310             case REGION:
311                 getRegion().touchItem(getOwner());
312                 break;
313             default:
314                 break;
315         }
316     }
317 
318     /**
319      * SecurityInfoList.
320      */
321     public static class MoneyWiseSecurityInfoList
322             extends PrometheusDataInfoList<MoneyWiseSecurityInfo> {
323         /**
324          * Report fields.
325          */
326         private static final MetisFieldSet<MoneyWiseSecurityInfoList> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseSecurityInfoList.class);
327 
328         /**
329          * Construct an empty CORE info list.
330          *
331          * @param pData the DataSet for the list
332          */
333         protected MoneyWiseSecurityInfoList(final MoneyWiseDataSet pData) {
334             super(MoneyWiseSecurityInfo.class, pData, MoneyWiseBasicDataType.SECURITYINFO, PrometheusListStyle.CORE);
335         }
336 
337         /**
338          * Constructor for a cloned List.
339          *
340          * @param pSource the source List
341          */
342         private MoneyWiseSecurityInfoList(final MoneyWiseSecurityInfoList pSource) {
343             super(pSource);
344         }
345 
346         @Override
347         public MetisFieldSet<MoneyWiseSecurityInfoList> getDataFieldSet() {
348             return FIELD_DEFS;
349         }
350 
351         @Override
352         public String listName() {
353             return LIST_NAME;
354         }
355 
356         @Override
357         public MetisFieldSetDef getItemFields() {
358             return MoneyWiseSecurityInfo.FIELD_DEFS;
359         }
360 
361         @Override
362         public MoneyWiseDataSet getDataSet() {
363             return (MoneyWiseDataSet) super.getDataSet();
364         }
365 
366         /**
367          * Set base list for Edit InfoList.
368          *
369          * @param pBase the base list
370          */
371         protected void setBase(final MoneyWiseSecurityInfoList pBase) {
372             /* Set the style and base */
373             setStyle(PrometheusListStyle.EDIT);
374             super.setBase(pBase);
375         }
376 
377         @Override
378         protected MoneyWiseSecurityInfoList getEmptyList(final PrometheusListStyle pStyle) {
379             final MoneyWiseSecurityInfoList myList = new MoneyWiseSecurityInfoList(this);
380             myList.setStyle(pStyle);
381             return myList;
382         }
383 
384         @Override
385         public MoneyWiseSecurityInfo addCopyItem(final PrometheusDataItem pItem) {
386             /* Can only clone a SecurityInfo */
387             if (!(pItem instanceof MoneyWiseSecurityInfo)) {
388                 throw new UnsupportedOperationException();
389             }
390 
391             final MoneyWiseSecurityInfo myInfo = new MoneyWiseSecurityInfo(this, (MoneyWiseSecurityInfo) pItem);
392             add(myInfo);
393             return myInfo;
394         }
395 
396         @Override
397         public MoneyWiseSecurityInfo addNewItem() {
398             throw new UnsupportedOperationException();
399         }
400 
401         @Override
402         protected MoneyWiseSecurityInfo addNewItem(final PrometheusDataItem pOwner,
403                                                    final PrometheusStaticDataItem pInfoType) {
404             /* Allocate the new entry and add to list */
405             final MoneyWiseSecurityInfo myInfo = new MoneyWiseSecurityInfo(this, (MoneyWiseSecurity) pOwner, (MoneyWiseAccountInfoType) pInfoType);
406             add(myInfo);
407 
408             /* return it */
409             return myInfo;
410         }
411 
412         @Override
413         public void addInfoItem(final Integer pId,
414                                 final PrometheusDataItem pSecurity,
415                                 final PrometheusDataInfoClass pInfoClass,
416                                 final Object pValue) throws OceanusException {
417             /* Ignore item if it is null */
418             if (pValue == null) {
419                 return;
420             }
421 
422             /* Access the data set */
423             final MoneyWiseDataSet myData = getDataSet();
424 
425             /* Look up the Info Type */
426             final MoneyWiseAccountInfoType myInfoType = myData.getActInfoTypes().findItemByClass(pInfoClass);
427             if (myInfoType == null) {
428                 throw new MoneyWiseDataException(pSecurity, ERROR_BADINFOCLASS + " [" + pInfoClass + "]");
429             }
430 
431             /* Create the values */
432             final PrometheusDataValues myValues = new PrometheusDataValues(OBJECT_NAME);
433             myValues.addValue(MetisDataResource.DATA_ID, pId);
434             myValues.addValue(PrometheusDataResource.DATAINFO_TYPE, myInfoType);
435             myValues.addValue(PrometheusDataResource.DATAINFO_OWNER, pSecurity);
436             myValues.addValue(PrometheusDataResource.DATAINFO_VALUE, pValue);
437 
438             /* Create a new Security Info */
439             final MoneyWiseSecurityInfo myInfo = new MoneyWiseSecurityInfo(this, myValues);
440 
441             /* Check that this InfoTypeId has not been previously added */
442             if (!isIdUnique(pId)) {
443                 myInfo.addError(ERROR_DUPLICATE, MetisDataResource.DATA_ID);
444                 throw new MoneyWiseDataException(myInfo, ERROR_VALIDATION);
445             }
446 
447             /* Add the Info to the list */
448             add(myInfo);
449         }
450 
451         @Override
452         public MoneyWiseSecurityInfo addValuesItem(final PrometheusDataValues pValues) throws OceanusException {
453             /* Create the info */
454             final MoneyWiseSecurityInfo myInfo = new MoneyWiseSecurityInfo(this, pValues);
455 
456             /* Check that this InfoId has not been previously added */
457             if (!isIdUnique(myInfo.getIndexedId())) {
458                 myInfo.addError(ERROR_DUPLICATE, MetisDataResource.DATA_ID);
459                 throw new MoneyWiseDataException(myInfo, ERROR_VALIDATION);
460             }
461 
462             /* Add to the list */
463             add(myInfo);
464 
465             /* Return it */
466             return myInfo;
467         }
468 
469         @Override
470         public void postProcessOnLoad() throws OceanusException {
471             /* Validate the SecurityInfo */
472             validateOnLoad();
473 
474             /* Map and Validate the Securities */
475             final MoneyWiseSecurityList mySecurities = getDataSet().getSecurities();
476             mySecurities.mapData();
477             mySecurities.validateOnLoad();
478         }
479     }
480 }