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