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.atlas.data.analysis.buckets;
18  
19  import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
20  import io.github.tonywasher.joceanus.oceanus.date.OceanusDateRange;
21  import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
22  import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
23  import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataList;
24  import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
25  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
26  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseAssetType;
27  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseBasicResource;
28  import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseTransAsset;
29  
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  
36  /**
37   * The TaxBasis Account Bucket class.
38   */
39  public final class MoneyWiseXAnalysisTaxBasisAccountBucket
40          extends MoneyWiseXAnalysisTaxBasisBucket {
41      /**
42       * Local Report fields.
43       */
44      private static final MetisFieldSet<MoneyWiseXAnalysisTaxBasisAccountBucket> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseXAnalysisTaxBasisAccountBucket.class);
45  
46      /*
47       * Declare Fields.
48       */
49      static {
50          FIELD_DEFS.declareLocalField(MoneyWiseBasicResource.TRANSACTION_ACCOUNT, MoneyWiseXAnalysisTaxBasisAccountBucket::getAccount);
51      }
52  
53      /**
54       * AssetId.
55       */
56      private final Long theAssetId;
57  
58      /**
59       * Parent.
60       */
61      private final MoneyWiseXAnalysisTaxBasisBucket theParent;
62  
63      /**
64       * Account.
65       */
66      private final MoneyWiseTransAsset theAccount;
67  
68      /**
69       * Constructor.
70       *
71       * @param pAnalysis the analysis
72       * @param pParent   the parent bucket
73       * @param pAccount  the account
74       */
75      MoneyWiseXAnalysisTaxBasisAccountBucket(final MoneyWiseXAnalysis pAnalysis,
76                                              final MoneyWiseXAnalysisTaxBasisBucket pParent,
77                                              final MoneyWiseTransAsset pAccount) {
78          /* Store the parameters */
79          super(pAnalysis, pParent.getTaxBasis());
80          theAssetId = deriveAssetId(pAccount);
81          theAccount = pAccount;
82          theParent = pParent;
83      }
84  
85      /**
86       * Constructor.
87       *
88       * @param pAnalysis the analysis
89       * @param pParent   the parent bucket
90       * @param pBase     the underlying bucket
91       * @param pDate     the date for the bucket
92       */
93      private MoneyWiseXAnalysisTaxBasisAccountBucket(final MoneyWiseXAnalysis pAnalysis,
94                                                      final MoneyWiseXAnalysisTaxBasisBucket pParent,
95                                                      final MoneyWiseXAnalysisTaxBasisAccountBucket pBase,
96                                                      final OceanusDate pDate) {
97          /* Copy details from base */
98          super(pAnalysis, pBase, pDate);
99          theAssetId = pBase.getBucketId();
100         theAccount = pBase.getAccount();
101         theParent = pParent;
102     }
103 
104     /**
105      * Constructor.
106      *
107      * @param pAnalysis the analysis
108      * @param pParent   the parent bucket
109      * @param pBase     the underlying bucket
110      * @param pRange    the range for the bucket
111      */
112     private MoneyWiseXAnalysisTaxBasisAccountBucket(final MoneyWiseXAnalysis pAnalysis,
113                                                     final MoneyWiseXAnalysisTaxBasisBucket pParent,
114                                                     final MoneyWiseXAnalysisTaxBasisAccountBucket pBase,
115                                                     final OceanusDateRange pRange) {
116         /* Copy details from base */
117         super(pAnalysis, pBase, pRange);
118         theAssetId = pBase.getBucketId();
119         theAccount = pBase.getAccount();
120         theParent = pParent;
121     }
122 
123     /**
124      * derive asset key for an asset.
125      *
126      * @param pAsset the asset
127      * @return the asset key
128      */
129     private static Long deriveAssetId(final MoneyWiseTransAsset pAsset) {
130         /* Calculate the key */
131         return MoneyWiseAssetType.createAlternateExternalId(MoneyWiseAssetType.TAXBASISACCOUNT, pAsset.getExternalId());
132     }
133 
134     @Override
135     public MetisFieldSet<MoneyWiseXAnalysisTaxBasisAccountBucket> getDataFieldSet() {
136         return FIELD_DEFS;
137     }
138 
139     @Override
140     public Integer getIndexedId() {
141         return theAccount.getExternalId().intValue();
142     }
143 
144     @Override
145     public Long getBucketId() {
146         return theAssetId;
147     }
148 
149     /**
150      * Obtain simple name.
151      *
152      * @return the simple name
153      */
154     public String getSimpleName() {
155         return theAccount.getName();
156     }
157 
158     @Override
159     public String getName() {
160         return getTaxBasis().getName()
161                 + ':'
162                 + getSimpleName();
163     }
164 
165     /**
166      * Obtain account.
167      *
168      * @return the account
169      */
170     public MoneyWiseTransAsset getAccount() {
171         return theAccount;
172     }
173 
174     /**
175      * Obtain parent.
176      *
177      * @return the parent
178      */
179     public MoneyWiseXAnalysisTaxBasisBucket getParent() {
180         return theParent;
181     }
182 
183     /**
184      * TaxBasisAccountBucketList class.
185      */
186     public static class MoneyWiseXAnalysisTaxBasisAccountBucketList
187             implements MetisFieldItem, MetisDataList<MoneyWiseXAnalysisTaxBasisAccountBucket> {
188         /**
189          * Local Report fields.
190          */
191         private static final MetisFieldSet<MoneyWiseXAnalysisTaxBasisAccountBucketList> FIELD_DEFS = MetisFieldSet.newFieldSet(MoneyWiseXAnalysisTaxBasisAccountBucketList.class);
192 
193         /*
194          * Declare Fields.
195          */
196         static {
197             FIELD_DEFS.declareLocalField(MoneyWiseXAnalysisBucketResource.ANALYSIS_NAME, MoneyWiseXAnalysisTaxBasisAccountBucketList::getAnalysis);
198         }
199 
200         /**
201          * The analysis.
202          */
203         private final MoneyWiseXAnalysis theAnalysis;
204 
205         /**
206          * The list.
207          */
208         private final List<MoneyWiseXAnalysisTaxBasisAccountBucket> theList;
209 
210         /**
211          * Parent.
212          */
213         private final MoneyWiseXAnalysisTaxBasisBucket theParent;
214 
215         /**
216          * Bucket map.
217          */
218         private final Map<Long, MoneyWiseXAnalysisTaxBasisAccountBucket> theMap;
219 
220         /**
221          * Construct a top-level List.
222          *
223          * @param pAnalysis the analysis
224          * @param pParent   the parent bucket
225          */
226         protected MoneyWiseXAnalysisTaxBasisAccountBucketList(final MoneyWiseXAnalysis pAnalysis,
227                                                               final MoneyWiseXAnalysisTaxBasisBucket pParent) {
228             theAnalysis = pAnalysis;
229             theParent = pParent;
230             theMap = new HashMap<>();
231             theList = new ArrayList<>();
232         }
233 
234         /**
235          * Construct a dated List.
236          *
237          * @param pAnalysis the analysis
238          * @param pParent   the parent bucket
239          * @param pBase     the base list
240          * @param pDate     the Date
241          */
242         protected MoneyWiseXAnalysisTaxBasisAccountBucketList(final MoneyWiseXAnalysis pAnalysis,
243                                                               final MoneyWiseXAnalysisTaxBasisBucket pParent,
244                                                               final MoneyWiseXAnalysisTaxBasisAccountBucketList pBase,
245                                                               final OceanusDate pDate) {
246             /* Initialise class */
247             this(pAnalysis, pParent);
248 
249             /* Loop through the buckets */
250             final Iterator<MoneyWiseXAnalysisTaxBasisAccountBucket> myIterator = pBase.iterator();
251             while (myIterator.hasNext()) {
252                 final MoneyWiseXAnalysisTaxBasisAccountBucket myCurr = myIterator.next();
253 
254                 /* Access the bucket for this date */
255                 final MoneyWiseXAnalysisTaxBasisAccountBucket myBucket = new MoneyWiseXAnalysisTaxBasisAccountBucket(pAnalysis, theParent, myCurr, pDate);
256 
257                 /* If the bucket is non-idle */
258                 if (!myBucket.isIdle()) {
259                     /* Calculate the delta and add to the list */
260                     theList.add(myBucket);
261                     theMap.put(myBucket.getBucketId(), myBucket);
262                 }
263             }
264         }
265 
266         /**
267          * Construct a ranged List.
268          *
269          * @param pAnalysis the analysis
270          * @param pParent   the parent bucket
271          * @param pBase     the base list
272          * @param pRange    the Date Range
273          */
274         protected MoneyWiseXAnalysisTaxBasisAccountBucketList(final MoneyWiseXAnalysis pAnalysis,
275                                                               final MoneyWiseXAnalysisTaxBasisBucket pParent,
276                                                               final MoneyWiseXAnalysisTaxBasisAccountBucketList pBase,
277                                                               final OceanusDateRange pRange) {
278             /* Initialise class */
279             this(pAnalysis, pParent);
280 
281             /* Loop through the buckets */
282             final Iterator<MoneyWiseXAnalysisTaxBasisAccountBucket> myIterator = pBase.iterator();
283             while (myIterator.hasNext()) {
284                 final MoneyWiseXAnalysisTaxBasisAccountBucket myCurr = myIterator.next();
285 
286                 /* Access the bucket for this range */
287                 final MoneyWiseXAnalysisTaxBasisAccountBucket myBucket = new MoneyWiseXAnalysisTaxBasisAccountBucket(pAnalysis, theParent, myCurr, pRange);
288 
289                 /* If the bucket is non-idle */
290                 if (!myBucket.isIdle()) {
291                     /* Adjust to the base */
292                     myBucket.adjustToBase();
293 
294                     /* Add to list and to map */
295                     theList.add(myBucket);
296                     theMap.put(myBucket.getBucketId(), myBucket);
297                 }
298             }
299         }
300 
301         @Override
302         public MetisFieldSet<MoneyWiseXAnalysisTaxBasisAccountBucketList> getDataFieldSet() {
303             return FIELD_DEFS;
304         }
305 
306         @Override
307         public List<MoneyWiseXAnalysisTaxBasisAccountBucket> getUnderlyingList() {
308             return theList;
309         }
310 
311         @Override
312         public String formatObject(final OceanusDataFormatter pFormatter) {
313             return getDataFieldSet().getName();
314         }
315 
316         /**
317          * Obtain the analysis.
318          *
319          * @return the analysis
320          */
321         protected MoneyWiseXAnalysis getAnalysis() {
322             return theAnalysis;
323         }
324 
325         /**
326          * Adjust value.
327          *
328          * @param pAccount the relevant account
329          * @param pValue   the value
330          * @param pAdjust  adjustment control
331          * @return the adjusted taxBasisAccountBucket (or null)
332          */
333         MoneyWiseXAnalysisTaxBasisAccountBucket adjustValue(final MoneyWiseTransAsset pAccount,
334                                                             final OceanusMoney pValue,
335                                                             final MoneyWiseXTaxBasisAdjust pAdjust) {
336             /* Access the relevant account bucket */
337             final MoneyWiseXAnalysisTaxBasisAccountBucket myBucket = getBucket(pAccount);
338 
339             /* register deltas */
340             return myBucket.adjustValue(pAccount, pValue, pAdjust);
341         }
342 
343         /**
344          * Obtain the TaxBasisAccountBucket for a given account.
345          *
346          * @param pAccount the account
347          * @return the bucket
348          */
349         private MoneyWiseXAnalysisTaxBasisAccountBucket getBucket(final MoneyWiseTransAsset pAccount) {
350             /* Locate the bucket in the list */
351             final Long myKey = deriveAssetId(pAccount);
352             return theMap.computeIfAbsent(myKey, m -> {
353                 /* Create the new bucket */
354                 final MoneyWiseXAnalysisTaxBasisAccountBucket myNew = new MoneyWiseXAnalysisTaxBasisAccountBucket(theAnalysis, theParent, pAccount);
355 
356                 /* Add to the list */
357                 theList.add(myNew);
358                 return myNew;
359             });
360         }
361 
362         /**
363          * SortBuckets.
364          */
365         protected void sortBuckets() {
366             theList.sort((l, r) -> l.getBucketId().compareTo(r.getBucketId()));
367         }
368 
369         /**
370          * Find the TaxBasisAccountBucket for a given account.
371          *
372          * @param pAccount the account
373          * @return the bucket (or null)
374          */
375         protected MoneyWiseXAnalysisTaxBasisAccountBucket findBucket(final MoneyWiseTransAsset pAccount) {
376             /* Locate the bucket in the list */
377             final Long myKey = deriveAssetId(pAccount);
378             return theMap.get(myKey);
379         }
380     }
381 }