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.lethe.views;
18  
19  import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
20  import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
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.MoneyWiseDataSet;
24  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransInfo;
25  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransInfo.MoneyWiseTransInfoList;
26  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction;
27  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransaction.MoneyWiseTransactionList;
28  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseStaticDataType;
29  import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseTransInfoType.MoneyWiseTransInfoTypeList;
30  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.analyse.MoneyWiseAnalysisTransAnalyser;
31  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysis;
32  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisDataResource;
33  import io.github.tonywasher.joceanus.moneywise.lethe.data.analysis.data.MoneyWiseAnalysisManager;
34  import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseView;
35  import io.github.tonywasher.joceanus.moneywise.views.MoneyWiseViewResource;
36  import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
37  import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
38  import io.github.tonywasher.joceanus.oceanus.event.OceanusEventManager;
39  import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar;
40  import io.github.tonywasher.joceanus.oceanus.event.OceanusEventRegistrar.OceanusEventProvider;
41  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
42  import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogManager;
43  import io.github.tonywasher.joceanus.oceanus.logger.OceanusLogger;
44  import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
45  import io.github.tonywasher.joceanus.prometheus.data.PrometheusListStyle;
46  import io.github.tonywasher.joceanus.prometheus.views.PrometheusDataEvent;
47  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditEntry;
48  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
49  
50  import java.util.Iterator;
51  
52  /**
53   * Analysis Edit View.
54   */
55  public class MoneyWiseAnalysisView
56          implements MetisFieldItem, OceanusEventProvider<PrometheusDataEvent> {
57      /**
58       * Report fields.
59       */
60      private static final MetisFieldSet<MoneyWiseAnalysisView> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseAnalysisView.class);
61  
62      /*
63       * Declare Fields.
64       */
65      static {
66          FIELD_DEFS.declareLocalField(MoneyWiseViewResource.ANALYSISVIEW_UPDATESET, MoneyWiseAnalysisView::getEditSet);
67          FIELD_DEFS.declareLocalField(MoneyWiseAnalysisDataResource.ANALYSIS_NAME, MoneyWiseAnalysisView::getAnalysis);
68      }
69  
70      /**
71       * Logger.
72       */
73      private static final OceanusLogger LOGGER = OceanusLogManager.getLogger(MoneyWiseAnalysisView.class);
74  
75      /**
76       * The Event Manager.
77       */
78      private final OceanusEventManager<PrometheusDataEvent> theEventManager;
79  
80      /**
81       * The View.
82       */
83      private final MoneyWiseView theView;
84  
85      /**
86       * The UpdateSet.
87       */
88      private final PrometheusEditSet theEditSet;
89  
90      /**
91       * The event entry.
92       */
93      private final PrometheusEditEntry<MoneyWiseTransaction> theTransEntry;
94  
95      /**
96       * The info entry.
97       */
98      private final PrometheusEditEntry<MoneyWiseTransInfo> theInfoEntry;
99  
100     /**
101      * The transactions.
102      */
103     private MoneyWiseTransactionView theTransactions;
104 
105     /**
106      * Analysis Manager.
107      */
108     private MoneyWiseAnalysisManager theManager;
109 
110     /**
111      * The active analysis.
112      */
113     private MoneyWiseAnalysis theAnalysis;
114 
115     /**
116      * The current range.
117      */
118     private OceanusDateRange theRange;
119 
120     /**
121      * Constructor.
122      *
123      * @param pView    the view
124      * @param pEditSet the edit set
125      */
126     public MoneyWiseAnalysisView(final MoneyWiseView pView,
127                                  final PrometheusEditSet pEditSet) {
128         /* Store update set */
129         theView = pView;
130         theEditSet = pEditSet;
131 
132         /* Register data entries */
133         theTransEntry = theEditSet.registerType(MoneyWiseBasicDataType.TRANSACTION);
134         theInfoEntry = theEditSet.registerType(MoneyWiseBasicDataType.TRANSACTIONINFO);
135 
136         /* Create event manager */
137         theEventManager = new OceanusEventManager<>();
138     }
139 
140     @Override
141     public MetisFieldSet<MoneyWiseAnalysisView> getDataFieldSet() {
142         return FIELD_DEFS;
143     }
144 
145     @Override
146     public String formatObject(final OceanusDataFormatter pFormatter) {
147         return FIELD_DEFS.getName();
148     }
149 
150     @Override
151     public OceanusEventRegistrar<PrometheusDataEvent> getEventRegistrar() {
152         return theEventManager.getEventRegistrar();
153     }
154 
155     /**
156      * Obtain the active analysis.
157      *
158      * @return the active analysis
159      */
160     public MoneyWiseAnalysis getAnalysis() {
161         return theAnalysis;
162     }
163 
164     /**
165      * Obtain the editSet.
166      *
167      * @return the editSet
168      */
169     private PrometheusEditSet getEditSet() {
170         return theEditSet;
171     }
172 
173     /**
174      * Obtain the transaction list.
175      *
176      * @return the transaction list
177      */
178     public MoneyWiseTransactionList getTransactions() {
179         return theTransactions;
180     }
181 
182     /**
183      * Obtain the range.
184      *
185      * @return the range
186      */
187     public OceanusDateRange getRange() {
188         return theRange;
189     }
190 
191     /**
192      * Refresh data.
193      */
194     public void refreshData() {
195         /* Protect against exceptions */
196         try {
197             /* Access the new analysis manager */
198             theManager = theView.getAnalysisManager();
199             theEditSet.setDataSet(theView.getData());
200 
201             /* If we have a range */
202             if (theRange != null) {
203                 /* Obtain the required analysis and reset to it */
204                 theAnalysis = theManager.getRangedAnalysis(theRange);
205 
206                 /* Create the new transaction list */
207                 final MoneyWiseDataSet myData = theView.getData();
208                 theTransactions = new MoneyWiseTransactionView(myData.getTransactions());
209 
210                 /* else no range */
211             } else {
212                 /* Set nulls */
213                 theAnalysis = null;
214                 theTransactions = null;
215             }
216 
217             /* register the lists */
218             registerLists();
219 
220             /* Notify listeners */
221             theEventManager.fireEvent(PrometheusDataEvent.ADJUSTVISIBILITY);
222 
223         } catch (OceanusException e) {
224             LOGGER.error("Failed to refreshData", e);
225         }
226     }
227 
228     /**
229      * Set the selected date range.
230      *
231      * @param pRange the date range
232      */
233     public void setRange(final OceanusDateRange pRange) {
234         /* If we have changed the range */
235         if (!MetisDataDifference.isEqual(theRange, pRange)) {
236             /* Obtain the required analysis and reset to it */
237             theRange = pRange;
238             theAnalysis = theManager == null ? null : theManager.getRangedAnalysis(theRange);
239 
240             /* Notify listeners */
241             theEventManager.fireEvent(PrometheusDataEvent.ADJUSTVISIBILITY);
242         }
243     }
244 
245     /**
246      * /** Register lists.
247      */
248     private void registerLists() {
249         /* If we have transactions */
250         if (theTransactions != null) {
251             final MoneyWiseTransInfoList myInfo = theTransactions.getTransactionInfo();
252             theTransEntry.setDataList(theTransactions);
253             theInfoEntry.setDataList(myInfo);
254         } else {
255             theTransEntry.setDataList(null);
256             theInfoEntry.setDataList(null);
257         }
258     }
259 
260     /**
261      * TransactionView class.
262      */
263     private final class MoneyWiseTransactionView
264             extends MoneyWiseTransactionList {
265         /**
266          * Constructor.
267          *
268          * @param pSource the source transaction list
269          * @throws OceanusException on error
270          */
271         private MoneyWiseTransactionView(final MoneyWiseTransactionList pSource) throws OceanusException {
272             /* Initialise as edit list */
273             super(pSource);
274             setStyle(PrometheusListStyle.EDIT);
275             setEditSet(theEditSet);
276             theEditSet.setEditEntryList(MoneyWiseBasicDataType.TRANSACTION, this);
277 
278             /* Store InfoType list */
279             setTransInfoTypes(theEditSet.getDataList(MoneyWiseStaticDataType.TRANSINFOTYPE, MoneyWiseTransInfoTypeList.class));
280 
281             /* Create and store info List */
282             final MoneyWiseTransInfoList myTransInfo = pSource.getTransactionInfo().getEmptyList(PrometheusListStyle.EDIT);
283             theEditSet.setEditEntryList(MoneyWiseBasicDataType.TRANSACTIONINFO, myTransInfo);
284             setTransactionInfo(myTransInfo);
285 
286             /* Loop through the Transactions extracting relevant elements */
287             final Iterator<MoneyWiseTransaction> myIterator = pSource.iterator();
288             while (myIterator.hasNext()) {
289                 final MoneyWiseTransaction myCurr = myIterator.next();
290 
291                 /* Ignore deleted events */
292                 if (myCurr.isDeleted()) {
293                     continue;
294                 }
295 
296                 /* Build the new linked transaction and add it to the list */
297                 final MoneyWiseTransaction myTrans = new MoneyWiseTransaction(this, myCurr);
298                 add(myTrans);
299                 myTrans.resolveEditSetLinks();
300 
301                 /* Adjust the map */
302                 myTrans.adjustMapForItem();
303             }
304         }
305 
306         @Override
307         public void postProcessOnUpdate() {
308             /* Pass call on */
309             super.postProcessOnUpdate();
310 
311             /* Obtain the active profile */
312             OceanusProfile myTask = theView.getActiveTask();
313             myTask = myTask.startTask("updateAnalysis");
314 
315             /* Protect against exceptions */
316             try {
317                 /* Sort the transaction list */
318                 myTask.startTask("sortTransactions");
319                 reSort();
320 
321                 /* Initialise the analysis */
322                 myTask.startTask("UpdateMaps");
323                 theView.getData().updateMaps();
324 
325                 /* Analyse the data */
326                 myTask.startTask("analyseData");
327                 final MoneyWiseAnalysisTransAnalyser myAnalyser = new MoneyWiseAnalysisTransAnalyser(myTask, theEditSet, theView.getPreferenceManager());
328                 final MoneyWiseAnalysis myAnalysis = myAnalyser.getAnalysis();
329                 theManager = new MoneyWiseAnalysisManager(myAnalysis);
330                 theAnalysis = theManager.getRangedAnalysis(theRange);
331 
332                 /* Notify listeners */
333                 myTask.startTask("Notify");
334                 theEventManager.fireEvent(PrometheusDataEvent.ADJUSTVISIBILITY);
335 
336                 /* Catch exceptions */
337             } catch (OceanusException e) {
338                 LOGGER.error("Failed to analyse changes", e);
339             }
340         }
341     }
342 }