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