1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package io.github.tonywasher.joceanus.moneywise.data.basic;
19
20 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataMap;
21 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataObjectFormat;
22 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWisePortfolio.MoneyWisePortfolioList;
23 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurity.MoneyWiseSecurityList;
24 import io.github.tonywasher.joceanus.moneywise.data.basic.MoneyWiseSecurityHoldingMap.MoneyWisePortfolioHoldingsMap;
25 import io.github.tonywasher.joceanus.moneywise.data.statics.MoneyWiseSecurityClass;
26 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
27 import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataSet;
28 import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
29
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36
37
38
39
40 public class MoneyWiseSecurityHoldingMap
41 implements MetisDataObjectFormat, MetisDataMap<Integer, MoneyWisePortfolioHoldingsMap>, MoneyWiseSecurityHoldingMapCtl {
42
43
44
45 private final MoneyWisePortfolioList thePortfolios;
46
47
48
49
50 private final MoneyWiseSecurityList theSecurities;
51
52
53
54
55 private final Map<Integer, MoneyWisePortfolioHoldingsMap> theMap;
56
57
58
59
60
61
62 public MoneyWiseSecurityHoldingMap(final PrometheusDataSet pData) {
63
64 thePortfolios = pData.getDataList(MoneyWiseBasicDataType.PORTFOLIO, MoneyWisePortfolioList.class);
65 theSecurities = pData.getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class);
66 theMap = new HashMap<>();
67 }
68
69
70
71
72
73
74 public MoneyWiseSecurityHoldingMap(final PrometheusEditSet pEditSet) {
75
76 thePortfolios = pEditSet.getDataList(MoneyWiseBasicDataType.PORTFOLIO, MoneyWisePortfolioList.class);
77 theSecurities = pEditSet.getDataList(MoneyWiseBasicDataType.SECURITY, MoneyWiseSecurityList.class);
78 theMap = new HashMap<>();
79 }
80
81 @Override
82 public Map<Integer, MoneyWisePortfolioHoldingsMap> getUnderlyingMap() {
83 return theMap;
84 }
85
86 @Override
87 public String formatObject(final OceanusDataFormatter pFormatter) {
88 return MoneyWiseSecurityHoldingMap.class.getSimpleName();
89 }
90
91 @Override
92 public void clear() {
93 theMap.clear();
94 }
95
96
97
98
99
100
101
102 public MoneyWiseSecurityHolding findHoldingById(final Long pId) {
103
104 final Integer myPortId = getPortfolioId(pId);
105 final Integer mySecId = getSecurityId(pId);
106
107
108 final MoneyWisePortfolioHoldingsMap myMap = getMapForPortfolio(myPortId);
109 return myMap == null
110 ? null
111 : myMap.getHoldingForSecurity(mySecId);
112 }
113
114
115
116
117
118
119
120 public MoneyWiseSecurityHolding findHoldingByName(final String pName) {
121
122 final String myPortName = getPortfolioName(pName);
123 final String mySecName = getSecurityName(pName);
124
125
126 final MoneyWisePortfolioHoldingsMap myMap = getMapForPortfolio(myPortName);
127 return myMap == null
128 ? null
129 : myMap.getHoldingForSecurity(mySecName);
130 }
131
132
133
134
135
136
137
138 private static String getPortfolioName(final String pName) {
139 final int iIndex = pName.indexOf(MoneyWiseSecurityHolding.SECURITYHOLDING_SEP);
140 return iIndex == -1
141 ? pName
142 : pName.substring(0, iIndex);
143 }
144
145
146
147
148
149
150
151 private static String getSecurityName(final String pName) {
152 final int iIndex = pName.indexOf(MoneyWiseSecurityHolding.SECURITYHOLDING_SEP);
153 return iIndex == -1
154 ? ""
155 : pName.substring(iIndex + 1);
156 }
157
158
159
160
161
162
163
164 private static Integer getPortfolioId(final Long pId) {
165 return MoneyWiseAssetType.getMajorId(pId);
166 }
167
168
169
170
171
172
173
174 private static Integer getSecurityId(final Long pId) {
175 return MoneyWiseAssetType.getBaseId(pId);
176 }
177
178
179
180
181
182
183
184
185 public MoneyWiseSecurityHolding declareHolding(final MoneyWisePortfolio pPortfolio,
186 final MoneyWiseSecurity pSecurity) {
187
188 final MoneyWisePortfolioHoldingsMap myPortMap = getMapForPortfolio(pPortfolio.getIndexedId());
189 if (myPortMap == null) {
190 throw new IllegalStateException("Invalid Portfolio");
191 }
192 final Map<Integer, MoneyWiseSecurityHolding> myMap = myPortMap.getUnderlyingMap();
193
194
195 final Integer myId = pSecurity.getIndexedId();
196 return myMap.computeIfAbsent(myId, i -> new MoneyWiseSecurityHolding(pPortfolio, pSecurity));
197 }
198
199
200
201
202
203
204
205 private MoneyWisePortfolioHoldingsMap getMapForPortfolio(final Integer pId) {
206
207 MoneyWisePortfolioHoldingsMap myMap = theMap.get(pId);
208
209
210 if (myMap == null) {
211
212 final MoneyWisePortfolio myPortfolio = thePortfolios.findItemById(pId);
213
214
215 if (myPortfolio == null
216 || myPortfolio.isDeleted()) {
217 return null;
218 }
219
220
221 myMap = new MoneyWisePortfolioHoldingsMap(myPortfolio, theSecurities);
222 theMap.put(pId, myMap);
223 }
224
225
226 return myMap;
227 }
228
229
230
231
232
233
234
235 private MoneyWisePortfolioHoldingsMap getMapForPortfolio(final String pName) {
236
237 final MoneyWisePortfolio myPortfolio = thePortfolios.findItemByName(pName);
238
239
240 if (myPortfolio == null) {
241 return null;
242 }
243
244
245 final Integer myId = myPortfolio.getIndexedId();
246 return theMap.computeIfAbsent(myId, i -> new MoneyWisePortfolioHoldingsMap(myPortfolio, theSecurities));
247 }
248
249 @Override
250 public void deRegister(final MoneyWiseAssetBase pAsset) {
251
252 switch (pAsset) {
253 case MoneyWisePortfolio myPortfolio -> deRegister(myPortfolio);
254 case MoneyWiseSecurity mySecurity -> deRegister(mySecurity);
255 default -> {
256
257 }
258 }
259 }
260
261
262
263
264
265
266 private void deRegister(final MoneyWisePortfolio pPortfolio) {
267
268 final Integer myId = pPortfolio.getIndexedId();
269 theMap.remove(myId);
270 }
271
272
273
274
275
276
277 private void deRegister(final MoneyWiseSecurity pSecurity) {
278
279 final Integer myId = pSecurity.getIndexedId();
280
281
282 final Iterator<MoneyWisePortfolioHoldingsMap> myIterator = theMap.values().iterator();
283 while (myIterator.hasNext()) {
284 final MoneyWisePortfolioHoldingsMap myMap = myIterator.next();
285
286
287 myMap.getUnderlyingMap().remove(myId);
288 }
289 }
290
291
292
293
294
295
296
297 public Iterator<MoneyWiseSecurityHolding> existingIterator(final MoneyWisePortfolio pPortfolio) {
298
299 final MoneyWisePortfolioHoldingsMap myMap = theMap.get(pPortfolio.getIndexedId());
300
301
302 return myMap == null
303 ? null
304 : myMap.existingIterator();
305 }
306
307
308
309
310
311
312
313 public Iterator<MoneyWiseSecurityHolding> newIterator(final MoneyWisePortfolio pPortfolio) {
314 return newIterator(pPortfolio, null);
315 }
316
317
318
319
320
321
322
323
324 public Iterator<MoneyWiseSecurityHolding> newIterator(final MoneyWisePortfolio pPortfolio,
325 final MoneyWiseSecurityClass pClass) {
326
327 final MoneyWisePortfolioHoldingsMap myMap = theMap.get(pPortfolio.getIndexedId());
328
329
330 return myMap == null
331 ? fullIterator(pPortfolio, pClass)
332 : myMap.newIterator(pClass);
333 }
334
335
336
337
338
339
340
341
342 private Iterator<MoneyWiseSecurityHolding> fullIterator(final MoneyWisePortfolio pPortfolio,
343 final MoneyWiseSecurityClass pClass) {
344
345 if (Boolean.TRUE.equals(pPortfolio.isClosed()) || pPortfolio.isDeleted()) {
346
347 return null;
348 }
349
350
351 List<MoneyWiseSecurityHolding> myList = new ArrayList<>();
352
353
354 final Iterator<MoneyWiseSecurity> myIterator = theSecurities.iterator();
355 while (myIterator.hasNext()) {
356 final MoneyWiseSecurity mySecurity = myIterator.next();
357
358
359 boolean bIgnore = mySecurity.isClosed() || mySecurity.isDeleted();
360 bIgnore |= pClass != null && !pClass.equals(mySecurity.getCategoryClass());
361 if (bIgnore) {
362 continue;
363 }
364
365
366 final MoneyWiseSecurityHolding myHolding = new MoneyWiseSecurityHolding(pPortfolio, mySecurity);
367 myList.add(myHolding);
368 }
369
370
371 if (myList.isEmpty()) {
372 myList = null;
373 } else {
374 Collections.sort(myList);
375 }
376
377
378 return myList == null
379 ? null
380 : myList.iterator();
381 }
382
383
384
385
386 public static final class MoneyWisePortfolioHoldingsMap
387 implements MetisDataObjectFormat, MetisDataMap<Integer, MoneyWiseSecurityHolding> {
388
389
390
391 private final MoneyWisePortfolio thePortfolio;
392
393
394
395
396 private final MoneyWiseSecurityList theSecurities;
397
398
399
400
401 private final Map<Integer, MoneyWiseSecurityHolding> theMap;
402
403
404
405
406
407
408
409 private MoneyWisePortfolioHoldingsMap(final MoneyWisePortfolio pPortfolio,
410 final MoneyWiseSecurityList pSecurities) {
411 thePortfolio = pPortfolio;
412 theSecurities = pSecurities;
413 theMap = new HashMap<>();
414 }
415
416 @Override
417 public Map<Integer, MoneyWiseSecurityHolding> getUnderlyingMap() {
418 return theMap;
419 }
420
421 @Override
422 public String formatObject(final OceanusDataFormatter pFormatter) {
423 return thePortfolio.formatObject(pFormatter);
424 }
425
426 @Override
427 public String toString() {
428 return thePortfolio.toString();
429 }
430
431
432
433
434
435
436
437 private MoneyWiseSecurityHolding getHoldingForSecurity(final Integer pId) {
438
439 MoneyWiseSecurityHolding myHolding = theMap.get(pId);
440
441
442 if (myHolding == null) {
443
444 final MoneyWiseSecurity mySecurity = theSecurities.findItemById(pId);
445
446
447 if (mySecurity == null || mySecurity.isDeleted()) {
448 return null;
449 }
450
451
452 myHolding = new MoneyWiseSecurityHolding(thePortfolio, mySecurity);
453 theMap.put(pId, myHolding);
454 }
455
456
457 return myHolding;
458 }
459
460
461
462
463
464
465
466 private MoneyWiseSecurityHolding getHoldingForSecurity(final String pName) {
467
468 final MoneyWiseSecurity mySecurity = theSecurities.findItemByName(pName);
469
470
471 if (mySecurity == null) {
472 return null;
473 }
474
475
476 final Integer myId = mySecurity.getIndexedId();
477 return theMap.computeIfAbsent(myId, i -> new MoneyWiseSecurityHolding(thePortfolio, mySecurity));
478 }
479
480
481
482
483
484
485 private Iterator<MoneyWiseSecurityHolding> existingIterator() {
486
487 if (Boolean.TRUE.equals(thePortfolio.isClosed()) || thePortfolio.isDeleted()) {
488
489 return null;
490 }
491
492
493 List<MoneyWiseSecurityHolding> myList = new ArrayList<>();
494
495
496 final Iterator<MoneyWiseSecurityHolding> myIterator = theMap.values().iterator();
497 while (myIterator.hasNext()) {
498 final MoneyWiseSecurityHolding myHolding = myIterator.next();
499 final MoneyWiseSecurity mySecurity = myHolding.getSecurity();
500
501
502 if (Boolean.FALSE.equals(mySecurity.isClosed()) && !mySecurity.isDeleted()) {
503
504 myList.add(myHolding);
505 }
506 }
507
508
509 if (myList.isEmpty()) {
510 myList = null;
511 } else {
512 Collections.sort(myList);
513 }
514
515
516 return myList == null
517 ? null
518 : myList.iterator();
519 }
520
521
522
523
524
525
526
527 private Iterator<MoneyWiseSecurityHolding> newIterator(final MoneyWiseSecurityClass pClass) {
528
529 if (Boolean.TRUE.equals(thePortfolio.isClosed()) || thePortfolio.isDeleted()) {
530
531 return null;
532 }
533
534
535 List<MoneyWiseSecurityHolding> myList = new ArrayList<>();
536
537
538 final Iterator<MoneyWiseSecurity> myIterator = theSecurities.iterator();
539 while (myIterator.hasNext()) {
540 final MoneyWiseSecurity mySecurity = myIterator.next();
541
542
543 boolean bIgnore = mySecurity.isClosed() || mySecurity.isDeleted();
544 bIgnore |= pClass != null && pClass.equals(mySecurity.getCategoryClass());
545 if (bIgnore) {
546 continue;
547 }
548
549
550 if (theMap.get(mySecurity.getIndexedId()) == null) {
551
552 final MoneyWiseSecurityHolding myHolding = new MoneyWiseSecurityHolding(thePortfolio, mySecurity);
553 myList.add(myHolding);
554 }
555 }
556
557
558 if (myList.isEmpty()) {
559 myList = null;
560 } else {
561 Collections.sort(myList);
562 }
563
564
565 return myList == null
566 ? null
567 : myList.iterator();
568 }
569 }
570 }