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.views;
18  
19  import io.github.tonywasher.joceanus.metis.data.MetisDataEditState;
20  import io.github.tonywasher.joceanus.metis.data.MetisDataState;
21  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
22  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicDataType;
23  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicResource;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseDataSet;
25  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio;
26  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity;
27  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityPrice;
28  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysis;
29  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisManager;
30  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket;
31  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisPortfolioBucket.MoneyWiseAnalysisPortfolioBucketList;
32  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisSecurityBucket;
33  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisSecurityBucket.MoneyWiseAnalysisSecurityBucketList;
34  import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
35  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
36  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataItem;
37  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataValues;
38  import io.github.tonywasher.joceanus.prometheus.data.PrometheusEncryptedValues;
39  import io.github.tonywasher.joceanus.prometheus.data.PrometheusListStyle;
40  
41  import java.util.Iterator;
42  import java.util.ListIterator;
43  
44  /**
45   * Extension of SecurityPrice to cater for spot prices.
46   *
47   * @author Tony Washer
48   */
49  public final class MoneyWiseSpotSecurityPrice
50          extends MoneyWiseSecurityPrice {
51      /**
52       * Object name.
53       */
54      public static final String OBJECT_NAME = MoneyWiseSpotSecurityPrice.class.getSimpleName();
55  
56      /**
57       * List name.
58       */
59      public static final String LIST_NAME = OBJECT_NAME + "s";
60  
61      /**
62       * Report fields.
63       */
64      @SuppressWarnings("rawtypes")
65      private static final MetisFieldSet<MoneyWiseSpotSecurityPrice> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseSpotSecurityPrice.class);
66  
67      /*
68       * The fields.
69       */
70      static {
71          FIELD_DEFS.declareLocalField(MoneyWiseViewResource.SPOTEVENT_PREVDATE, MoneyWiseSpotSecurityPrice::getPrevDate);
72          FIELD_DEFS.declareLocalField(MoneyWiseViewResource.SPOTPRICE_PREVPRICE, MoneyWiseSpotSecurityPrice::getPrevPrice);
73      }
74  
75      /**
76       * the previous date.
77       */
78      private OceanusDate thePrevDate;
79  
80      /**
81       * the previous price.
82       */
83      private OceanusPrice thePrevPrice;
84  
85      /**
86       * isDisabled.
87       */
88      private boolean isDisabled;
89  
90      /**
91       * Constructor for a new SpotPrice where no price data exists.
92       *
93       * @param pList     the Spot Price List
94       * @param pSecurity the price for the date
95       */
96      private MoneyWiseSpotSecurityPrice(final MoneyWiseSpotSecurityList pList,
97                                         final MoneyWiseSecurity pSecurity) {
98          super(pList);
99  
100         /* Store base values */
101         setSecurity(pSecurity);
102     }
103 
104     @Override
105     public MetisFieldSetDef getDataFieldSet() {
106         return FIELD_DEFS;
107     }
108 
109     /**
110      * Obtain previous price.
111      *
112      * @return the price.
113      */
114     public OceanusPrice getPrevPrice() {
115         return thePrevPrice;
116     }
117 
118     /**
119      * Set previous price.
120      *
121      * @param pPrice the price
122      */
123     protected void setPrevPrice(final OceanusPrice pPrice) {
124         thePrevPrice = pPrice;
125     }
126 
127     /**
128      * Obtain previous date.
129      *
130      * @return the date.
131      */
132     public OceanusDate getPrevDate() {
133         return thePrevDate;
134     }
135 
136     /**
137      * Set previous date.
138      *
139      * @param pDate the date
140      */
141     protected void setPrevDate(final OceanusDate pDate) {
142         thePrevDate = pDate;
143     }
144 
145     @Override
146     public boolean isDisabled() {
147         return isDisabled;
148     }
149 
150     /**
151      * Set disabled.
152      *
153      * @param pDisabled the flag
154      */
155     protected void setDisabled(final boolean pDisabled) {
156         isDisabled = pDisabled;
157     }
158 
159     /**
160      * Validate the line.
161      */
162     @Override
163     public void validate() {
164         setValidEdit();
165     }
166 
167     /* Is this row locked */
168     @Override
169     public boolean isLocked() {
170         return isDeleted();
171     }
172 
173     /**
174      * Note that this item has been validated.
175      */
176     @Override
177     public void setValidEdit() {
178         setEditState(hasHistory()
179                 ? MetisDataEditState.VALID
180                 : MetisDataEditState.CLEAN);
181     }
182 
183     @Override
184     public OceanusPrice getPrice() {
185         /* Switch on state */
186         switch (getState()) {
187             case NEW:
188             case CHANGED:
189             case RECOVERED:
190             case CLEAN:
191                 return super.getPrice();
192             default:
193                 return null;
194         }
195     }
196 
197     @Override
198     public MetisDataState getState() {
199         final PrometheusEncryptedValues myCurr = getValues();
200         final PrometheusEncryptedValues myBase = getOriginalValues();
201 
202         /* If we have no changes we are CLEAN */
203         if (myCurr.getVersion() == 0) {
204             return MetisDataState.CLEAN;
205         }
206 
207         /* If the original price is Null */
208         if (myBase.getValue(MoneyWiseBasicResource.MONEYWISEDATA_FIELD_PRICE) == null) {
209             /* Return status */
210             return myCurr.getValue(MoneyWiseBasicResource.MONEYWISEDATA_FIELD_PRICE) == null
211                     ? MetisDataState.DELNEW
212                     : MetisDataState.NEW;
213         }
214 
215         /* If we are deleted return so */
216         return myCurr.getValue(MoneyWiseBasicResource.MONEYWISEDATA_FIELD_PRICE) == null
217                 ? MetisDataState.DELETED
218                 : MetisDataState.CHANGED;
219     }
220 
221     /**
222      * The Spot Prices List class.
223      */
224     public static class MoneyWiseSpotSecurityList
225             extends MoneyWiseSecurityPriceBaseList<MoneyWiseSpotSecurityPrice> {
226         /**
227          * Report fields.
228          */
229         @SuppressWarnings("rawtypes")
230         private static final MetisFieldSet<MoneyWiseSpotSecurityList> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseSpotSecurityList.class);
231 
232         /*
233          * The fields.
234          */
235         static {
236             FIELD_DEFS.declareLocalField(MoneyWiseBasicDataType.PORTFOLIO, MoneyWiseSpotSecurityList::getPortfolio);
237             FIELD_DEFS.declareLocalField(MoneyWiseBasicResource.MONEYWISEDATA_FIELD_DATE, MoneyWiseSpotSecurityList::getDate);
238             FIELD_DEFS.declareLocalField(MoneyWiseViewResource.SPOTEVENT_NEXTDATE, MoneyWiseSpotSecurityList::getNext);
239             FIELD_DEFS.declareLocalField(MoneyWiseViewResource.SPOTEVENT_PREVDATE, MoneyWiseSpotSecurityList::getPrev);
240         }
241 
242         /**
243          * The date.
244          */
245         private final OceanusDate theDate;
246 
247         /**
248          * The view.
249          */
250         private final MoneyWiseView theView;
251 
252         /**
253          * The portfolio.
254          */
255         private final MoneyWisePortfolio thePortfolio;
256 
257         /**
258          * The next date.
259          */
260         private OceanusDate theNext;
261 
262         /**
263          * The previous date.
264          */
265         private OceanusDate thePrev;
266 
267         /**
268          * Constructor.
269          *
270          * @param pView      the view
271          * @param pPortfolio the portfolio
272          * @param pDate      the date
273          */
274         public MoneyWiseSpotSecurityList(final MoneyWiseView pView,
275                                          final MoneyWisePortfolio pPortfolio,
276                                          final OceanusDate pDate) {
277             /* Build initial list */
278             super(pView.getData(), MoneyWiseSpotSecurityPrice.class, MoneyWiseBasicDataType.SECURITYPRICE);
279             setStyle(PrometheusListStyle.EDIT);
280             ensureMap();
281 
282             /* Store parameters */
283             theDate = pDate;
284             theView = pView;
285             thePortfolio = pPortfolio;
286 
287             /* Obtain the portfolio bucket */
288             final MoneyWiseAnalysisManager myManager = theView.getAnalysisManager();
289             final MoneyWiseAnalysis myAnalysis = myManager.getAnalysis();
290             final MoneyWiseAnalysisPortfolioBucketList myPortfolios = myAnalysis.getPortfolios();
291             final MoneyWiseAnalysisPortfolioBucket myBucket = myPortfolios.findItemById(thePortfolio.getIndexedId());
292             if (myBucket == null) {
293                 return;
294             }
295             final MoneyWiseAnalysisSecurityBucketList mySecurities = myBucket.getSecurities();
296 
297             /* Loop through the Securities */
298             final OceanusDate myDate = new OceanusDate(theDate);
299             final Iterator<MoneyWiseAnalysisSecurityBucket> mySecIterator = mySecurities.iterator();
300             while (mySecIterator.hasNext()) {
301                 final MoneyWiseAnalysisSecurityBucket mySecBucket = mySecIterator.next();
302                 final MoneyWiseSecurity mySecurity = mySecBucket.getSecurity();
303 
304                 /* Ignore Options */
305                 if (mySecurity.getCategoryClass().isOption()) {
306                     continue;
307                 }
308 
309                 /* Create a SpotPrice entry */
310                 final MoneyWiseSpotSecurityPrice mySpot = new MoneyWiseSpotSecurityPrice(this, mySecurity);
311                 mySpot.setIndexedId(mySecurity.getIndexedId());
312                 mySpot.setDate(myDate);
313                 mySpot.setDisabled(!mySecBucket.isActive());
314                 add(mySpot);
315             }
316 
317             /* Set the base for this list */
318             final MoneyWiseDataSet myData = theView.getData();
319             final MoneyWiseSecurityPriceList myPrices = myData.getSecurityPrices();
320             setBase(myPrices);
321 
322             /* Loop through the prices */
323             final ListIterator<MoneyWiseSecurityPrice> myIterator = myPrices.listIterator(myPrices.size());
324             while (myIterator.hasPrevious()) {
325                 final MoneyWiseSecurityPrice myPrice = myIterator.previous();
326 
327                 /* Access the Spot Price and ignore if not relevant/deleted */
328                 final MoneyWiseSecurity mySecurity = myPrice.getSecurity();
329                 final MoneyWiseSpotSecurityPrice mySpot = findItemById(mySecurity.getIndexedId());
330                 if (mySpot == null || myPrice.isDeleted()) {
331                     continue;
332                 }
333 
334                 /* Test the Date */
335                 final int iDiff = theDate.compareTo(myPrice.getDate());
336 
337                 /* If we are past the date */
338                 if (iDiff < 0) {
339                     /* Record the next date and break the loop */
340                     theNext = myPrice.getDate();
341                     break;
342                 }
343 
344                 /* If we are exactly the date */
345                 if (iDiff == 0) {
346                     /* Set price */
347                     mySpot.setValuePrice(myPrice.getPriceField());
348 
349                     /* Link to base and re-establish state */
350                     mySpot.setBase(myPrice);
351 
352                     /* else we are a previous date */
353                 } else {
354                     /* Set previous date and value */
355                     mySpot.setPrevDate(myPrice.getDate());
356                     mySpot.setPrevPrice(myPrice.getPrice());
357 
358                     /* Record the latest previous date */
359                     thePrev = myPrice.getDate();
360                 }
361             }
362         }
363 
364         @SuppressWarnings("rawtypes")
365         @Override
366         public MetisFieldSet<MoneyWiseSpotSecurityList> getDataFieldSet() {
367             return FIELD_DEFS;
368         }
369 
370         @Override
371         public String listName() {
372             return MoneyWiseSpotSecurityList.class.getSimpleName();
373         }
374 
375         @Override
376         public MetisFieldSetDef getItemFields() {
377             return MoneyWiseSpotSecurityPrice.FIELD_DEFS;
378         }
379 
380         @Override
381         protected MoneyWiseSpotSecurityList getEmptyList(final PrometheusListStyle pStyle) {
382             throw new UnsupportedOperationException();
383         }
384 
385         @Override
386         public MoneyWiseDataSet getDataSet() {
387             return (MoneyWiseDataSet) super.getDataSet();
388         }
389 
390         /**
391          * Obtain the portfolio.
392          *
393          * @return the portfolio
394          */
395         private MoneyWisePortfolio getPortfolio() {
396             return thePortfolio;
397         }
398 
399         /**
400          * Obtain the date.
401          *
402          * @return the date
403          */
404         private OceanusDate getDate() {
405             return theDate;
406         }
407 
408         /**
409          * Obtain the next date.
410          *
411          * @return the date
412          */
413         public OceanusDate getNext() {
414             return theNext;
415         }
416 
417         /**
418          * Obtain the previous date.
419          *
420          * @return the date
421          */
422         public OceanusDate getPrev() {
423             return thePrev;
424         }
425 
426         /* Is this list locked */
427         @Override
428         public boolean isLocked() {
429             return false;
430         }
431 
432         /* Disable Add a new item */
433         @Override
434         public MoneyWiseSpotSecurityPrice addCopyItem(final PrometheusDataItem pElement) {
435             throw new UnsupportedOperationException();
436         }
437 
438         @Override
439         public MoneyWiseSpotSecurityPrice addNewItem() {
440             throw new UnsupportedOperationException();
441         }
442 
443         @Override
444         public MoneyWiseSpotSecurityPrice addValuesItem(final PrometheusDataValues pValues) {
445             throw new UnsupportedOperationException();
446         }
447     }
448 }