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.base;
18
19 import io.github.tonywasher.joceanus.oceanus.date.OceanusDate;
20 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusDecimal;
21 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusMoney;
22 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusPrice;
23 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRate;
24 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusRatio;
25 import io.github.tonywasher.joceanus.oceanus.decimal.OceanusUnits;
26 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
27 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataMap;
28 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataObjectFormat;
29
30 import java.util.EnumMap;
31 import java.util.Map;
32
33 /**
34 * Values for a bucket.
35 *
36 * @param <T> the values class
37 * @param <E> the enum class
38 */
39 public abstract class MoneyWiseXAnalysisValues<T extends MoneyWiseXAnalysisValues<T, E>, E extends Enum<E> & MoneyWiseXAnalysisAttribute>
40 implements MetisDataObjectFormat, MetisDataMap<E, Object> {
41 /**
42 * Map.
43 */
44 private final Map<E, Object> theMap;
45
46 /**
47 * Enum class.
48 */
49 private final Class<E> theClass;
50
51 /**
52 * Constructor.
53 *
54 * @param pClass the Enum class
55 */
56 protected MoneyWiseXAnalysisValues(final Class<E> pClass) {
57 theMap = new EnumMap<>(pClass);
58 theClass = pClass;
59 }
60
61 /**
62 * Constructor.
63 *
64 * @param pSource the source values
65 */
66 protected MoneyWiseXAnalysisValues(final T pSource) {
67 theMap = new EnumMap<>(pSource.getUnderlyingMap());
68 theClass = pSource.getEnumClass();
69 }
70
71 /**
72 * Reset nonPreserved items.
73 */
74 void resetNonPreserved() {
75 /* Loop through the constants */
76 for (E myKey : theClass.getEnumConstants()) {
77 /* If we are copying all or the attribute is preserved */
78 if (!myKey.isPreserved()) {
79 /* Remove values that are not preserved */
80 theMap.remove(myKey);
81 }
82 }
83 }
84
85 @Override
86 public String formatObject(final OceanusDataFormatter pFormatter) {
87 return getClass().getSimpleName();
88 }
89
90 /**
91 * Obtain EnumClass.
92 *
93 * @return the class.
94 */
95 protected Class<E> getEnumClass() {
96 return theClass;
97 }
98
99 /**
100 * Obtain new snapShot.
101 *
102 * @return the snapShot.
103 */
104 protected abstract T newSnapShot();
105
106 @Override
107 public Map<E, Object> getUnderlyingMap() {
108 return theMap;
109 }
110
111 /**
112 * Adjust to base values.
113 *
114 * @param pBaseValues the base values.
115 */
116 public void adjustToBaseValues(final T pBaseValues) {
117 }
118
119 /**
120 * Obtain delta value.
121 *
122 * @param pPrevious the previous values.
123 * @param pAttr the attribute
124 * @return the delta
125 */
126 protected OceanusDecimal getDeltaValue(final T pPrevious,
127 final E pAttr) {
128 switch (pAttr.getDataType()) {
129 case MONEY:
130 return getDeltaMoneyValue(pPrevious, pAttr);
131 case UNITS:
132 return getDeltaUnitsValue(pPrevious, pAttr);
133 default:
134 return null;
135 }
136 }
137
138 /**
139 * Obtain delta money value.
140 *
141 * @param pPrevious the previous values.
142 * @param pAttr the attribute
143 * @return the delta
144 */
145 protected OceanusMoney getDeltaMoneyValue(final T pPrevious,
146 final E pAttr) {
147 /* Access current and previous values */
148 OceanusMoney myCurr = getMoneyValue(pAttr);
149 if (pPrevious != null) {
150 final OceanusMoney myPrev = pPrevious.getMoneyValue(pAttr);
151
152 /* Calculate delta */
153 myCurr = new OceanusMoney(myCurr);
154 myCurr.subtractAmount(myPrev);
155 }
156 return myCurr;
157 }
158
159 /**
160 * Obtain delta units value.
161 *
162 * @param pPrevious the previous values.
163 * @param pAttr the attribute
164 * @return the delta
165 */
166 protected OceanusUnits getDeltaUnitsValue(final T pPrevious,
167 final E pAttr) {
168 /* Access current and previous values */
169 OceanusUnits myCurr = getUnitsValue(pAttr);
170 if (pPrevious != null) {
171 final OceanusUnits myPrev = pPrevious.getUnitsValue(pAttr);
172
173 /* Calculate delta */
174 myCurr = new OceanusUnits(myCurr);
175 myCurr.subtractUnits(myPrev);
176 }
177 return myCurr;
178 }
179
180 /**
181 * Adjust money value relative to base.
182 *
183 * @param pBase the base values.
184 * @param pAttr the attribute to reBase.
185 */
186 protected void adjustMoneyToBase(final T pBase,
187 final E pAttr) {
188 /* Adjust spend values */
189 OceanusMoney myValue = getMoneyValue(pAttr);
190 myValue = new OceanusMoney(myValue);
191 final OceanusMoney myBaseValue = pBase.getMoneyValue(pAttr);
192 myValue.subtractAmount(myBaseValue);
193 theMap.put(pAttr, myValue);
194 }
195
196 /**
197 * Reset base values.
198 */
199 public void resetBaseValues() {
200 }
201
202 /**
203 * Set Value.
204 *
205 * @param pAttr the attribute
206 * @param pValue the value of the attribute
207 */
208 public void setValue(final E pAttr,
209 final Object pValue) {
210 /* Set the value into the map */
211 theMap.put(pAttr, pValue);
212 }
213
214 /**
215 * Obtain an attribute value.
216 *
217 * @param <X> the data type
218 * @param pAttr the attribute
219 * @param pClass the class of the attribute
220 * @return the value of the attribute or null
221 */
222 private <X> X getValue(final E pAttr,
223 final Class<X> pClass) {
224 /* Obtain the value */
225 return pClass.cast(getValue(pAttr));
226 }
227
228 /**
229 * Obtain an attribute value.
230 *
231 * @param pAttr the attribute
232 * @return the value of the attribute or null
233 */
234 public Object getValue(final E pAttr) {
235 /* Obtain the attribute value */
236 return theMap.get(pAttr);
237 }
238
239 /**
240 * Obtain a decimal attribute value.
241 *
242 * @param pAttr the attribute
243 * @return the value of the attribute or null
244 */
245 public OceanusDecimal getDecimalValue(final E pAttr) {
246 /* Obtain the attribute value */
247 return getValue(pAttr, OceanusDecimal.class);
248 }
249
250 /**
251 * Obtain a units attribute value.
252 *
253 * @param pAttr the attribute
254 * @return the value of the attribute or null
255 */
256 public OceanusUnits getUnitsValue(final E pAttr) {
257 /* Obtain the attribute value */
258 return getValue(pAttr, OceanusUnits.class);
259 }
260
261 /**
262 * Obtain a price attribute value.
263 *
264 * @param pAttr the attribute
265 * @return the value of the attribute or null
266 */
267 public OceanusPrice getPriceValue(final E pAttr) {
268 /* Obtain the attribute value */
269 return getValue(pAttr, OceanusPrice.class);
270 }
271
272 /**
273 * Obtain a money attribute value.
274 *
275 * @param pAttr the attribute
276 * @return the value of the attribute or null
277 */
278 public OceanusMoney getMoneyValue(final E pAttr) {
279 /* Obtain the attribute value */
280 return getValue(pAttr, OceanusMoney.class);
281 }
282
283 /**
284 * Obtain a rate attribute value.
285 *
286 * @param pAttr the attribute
287 * @return the value of the attribute or null
288 */
289 public OceanusRate getRateValue(final E pAttr) {
290 /* Obtain the attribute value */
291 return getValue(pAttr, OceanusRate.class);
292 }
293
294 /**
295 * Obtain a ratio attribute value.
296 *
297 * @param pAttr the attribute
298 * @return the value of the attribute or null
299 */
300 public OceanusRatio getRatioValue(final E pAttr) {
301 /* Obtain the attribute value */
302 return getValue(pAttr, OceanusRatio.class);
303 }
304
305 /**
306 * Obtain a date attribute value.
307 *
308 * @param pAttr the attribute
309 * @return the value of the attribute or null
310 */
311 public OceanusDate getDateValue(final E pAttr) {
312 /* Obtain the attribute value */
313 return getValue(pAttr, OceanusDate.class);
314 }
315
316 /**
317 * Obtain an integer attribute value.
318 *
319 * @param pAttr the attribute
320 * @return the value of the attribute or null
321 */
322 public Integer getIntegerValue(final E pAttr) {
323 /* Obtain the attribute */
324 return getValue(pAttr, Integer.class);
325 }
326
327 /**
328 * Obtain an enum attribute value.
329 *
330 * @param <V> the enum type
331 * @param pAttr the attribute
332 * @param pClass the Class of the enum
333 * @return the value of the attribute or null
334 */
335 public <V extends Enum<V>> V getEnumValue(final E pAttr,
336 final Class<V> pClass) {
337 /* Obtain the attribute */
338 return getValue(pAttr, pClass);
339 }
340
341 @Override
342 public String toString() {
343 final StringBuilder myBuilder = new StringBuilder();
344 for (Map.Entry<E, Object> myEntry : theMap.entrySet()) {
345 final Object myValue = myEntry.getValue();
346 if (!(myValue instanceof OceanusDecimal myDec) || myDec.isNonZero()) {
347 if (!myBuilder.isEmpty()) {
348 myBuilder.append(", ");
349 }
350 myBuilder.append(myEntry.getKey());
351 myBuilder.append("=");
352 myBuilder.append(myEntry.getValue());
353 }
354 }
355 return myBuilder.toString();
356 }
357 }