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