1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.prometheus.data;
18
19 import io.github.tonywasher.joceanus.metis.data.MetisDataDifference;
20 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
21 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataNamedItem;
22 import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
23 import io.github.tonywasher.joceanus.metis.list.MetisListKey;
24 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
25 import io.github.tonywasher.joceanus.oceanus.format.OceanusDataFormatter;
26 import io.github.tonywasher.joceanus.prometheus.data.PrometheusCryptographyData.PrometheusCryptographicDataSet;
27 import io.github.tonywasher.joceanus.prometheus.exc.PrometheusDataException;
28
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34
35
36
37
38
39
40 public abstract class PrometheusStaticDataItem
41 extends PrometheusEncryptedDataItem
42 implements MetisDataNamedItem {
43
44
45
46 private static final PrometheusEncryptedFieldSet<PrometheusStaticDataItem> FIELD_DEFS = PrometheusEncryptedFieldSet.newEncryptedFieldSet(PrometheusStaticDataItem.class);
47
48
49
50
51 static {
52 FIELD_DEFS.declareEncryptedStringField(PrometheusDataResource.DATAITEM_FIELD_NAME, NAMELEN);
53 FIELD_DEFS.declareEncryptedStringField(PrometheusDataResource.DATAITEM_FIELD_DESC, DESCLEN);
54 FIELD_DEFS.declareBooleanField(PrometheusDataResource.STATICDATA_ENABLED);
55 FIELD_DEFS.declareIntegerField(PrometheusDataResource.STATICDATA_SORT);
56 FIELD_DEFS.declareEnumField(PrometheusDataResource.STATICDATA_CLASS);
57 }
58
59
60
61
62 public static final String ERROR_BADID = PrometheusDataResource.STATICDATA_ERROR_ID.getValue();
63
64
65
66
67 public static final String ERROR_BADNAME = PrometheusDataResource.STATICDATA_ERROR_NAME.getValue();
68
69
70
71
72 private final Class<? extends PrometheusStaticDataClass> theEnumClass;
73
74
75
76
77
78
79
80 protected PrometheusStaticDataItem(final PrometheusStaticList<?> pList,
81 final PrometheusStaticDataItem pSource) {
82 super(pList, pSource);
83 theEnumClass = pSource.getEnumClass();
84 setIndexedId(pSource.getIndexedId());
85 }
86
87
88
89
90
91
92
93
94 protected PrometheusStaticDataItem(final PrometheusStaticList<?> pList,
95 final String pValue) throws OceanusException {
96
97 super(pList, 0);
98
99
100 theEnumClass = pList.getEnumClass();
101 parseEnumValue(pValue);
102
103
104 setValueName(pValue);
105 setValueEnabled(Boolean.TRUE);
106 }
107
108
109
110
111
112
113
114
115 protected PrometheusStaticDataItem(final PrometheusStaticList<?> pList,
116 final PrometheusStaticDataClass pClass) throws OceanusException {
117
118 super(pList, 0);
119
120
121 theEnumClass = pList.getEnumClass();
122
123
124 setValueClass(pClass);
125
126
127 setNextDataKeySet();
128
129
130 setIndexedId(pClass.getClassId());
131 setValueOrder(pClass.getOrder());
132
133
134 setValueName(pClass.toString());
135 setValueEnabled(Boolean.TRUE);
136
137
138 setNextDataKeySet();
139 }
140
141
142
143
144
145
146
147
148 protected PrometheusStaticDataItem(final PrometheusStaticList<?> pList,
149 final PrometheusDataValues pValues) throws OceanusException {
150
151 super(pList, pValues);
152
153
154 final OceanusDataFormatter myFormatter = getDataSet().getDataFormatter();
155
156
157 try {
158
159 theEnumClass = pList.getEnumClass();
160
161
162 Object myValue = pValues.getValue(PrometheusDataResource.DATAITEM_FIELD_NAME);
163 if (myValue instanceof String s) {
164 setValueName(s);
165 } else if (myValue instanceof byte[] ba) {
166 setValueName(ba);
167 }
168
169
170 myValue = pValues.getValue(PrometheusDataResource.DATAITEM_FIELD_DESC);
171 if (myValue instanceof String s) {
172 setValueDesc(s);
173 } else if (myValue instanceof byte[] ba) {
174 setValueDesc(ba);
175 }
176
177
178 myValue = pValues.getValue(PrometheusDataResource.STATICDATA_CLASS);
179 if (myValue instanceof String s) {
180 parseEnumValue(s);
181 } else {
182 parseEnumValue(getIndexedId());
183 }
184
185
186 myValue = pValues.getValue(PrometheusDataResource.STATICDATA_SORT);
187 if (myValue instanceof Integer i) {
188 setValueOrder(i);
189 } else if (myValue instanceof String s) {
190 setValueOrder(myFormatter.parseValue(s, Integer.class));
191 }
192
193
194 myValue = pValues.getValue(PrometheusDataResource.STATICDATA_ENABLED);
195 switch (myValue) {
196 case Boolean b -> setValueEnabled(b);
197 case String s -> setValueEnabled(myFormatter.parseValue(s, Boolean.class));
198 case null, default -> setValueEnabled(Boolean.TRUE);
199 }
200
201
202 } catch (NumberFormatException
203 | OceanusException e) {
204
205 throw new PrometheusDataException(this, ERROR_CREATEITEM, e);
206 }
207 }
208
209 @Override
210 public MetisFieldSetDef getDataFieldSet() {
211 return FIELD_DEFS;
212 }
213
214 @Override
215 public String formatObject(final OceanusDataFormatter pFormatter) {
216 return toString();
217 }
218
219 @Override
220 public String toString() {
221 return getName();
222 }
223
224 @Override
225 public boolean includeXmlField(final MetisDataFieldId pField) {
226
227 if (PrometheusDataResource.DATAITEM_FIELD_NAME.equals(pField)) {
228 return true;
229 }
230 if (PrometheusDataResource.DATAITEM_FIELD_DESC.equals(pField)) {
231 return getDesc() != null;
232 }
233 if (PrometheusDataResource.STATICDATA_ENABLED.equals(pField)) {
234 return !getEnabled();
235 }
236 if (PrometheusDataResource.STATICDATA_CLASS.equals(pField)) {
237 return !getName().equalsIgnoreCase(getStaticClass().name());
238 }
239
240
241 return super.includeXmlField(pField);
242 }
243
244 @Override
245 public final String getName() {
246 return getValues().getValue(PrometheusDataResource.DATAITEM_FIELD_NAME, String.class);
247 }
248
249
250
251
252
253
254 public final byte[] getNameBytes() {
255 return getValues().getEncryptedBytes(PrometheusDataResource.DATAITEM_FIELD_NAME);
256 }
257
258
259
260
261
262
263 private PrometheusEncryptedPair getNameField() {
264 return getValues().getEncryptedPair(PrometheusDataResource.DATAITEM_FIELD_NAME);
265 }
266
267
268
269
270
271
272 public final String getDesc() {
273 return getValues().getValue(PrometheusDataResource.DATAITEM_FIELD_DESC, String.class);
274 }
275
276
277
278
279
280
281 public final byte[] getDescBytes() {
282 return getValues().getEncryptedBytes(PrometheusDataResource.DATAITEM_FIELD_DESC);
283 }
284
285
286
287
288
289
290 private PrometheusEncryptedPair getDescField() {
291 return getValues().getEncryptedPair(PrometheusDataResource.DATAITEM_FIELD_DESC);
292 }
293
294
295
296
297
298
299 public final Integer getOrder() {
300 return getValues().getValue(PrometheusDataResource.STATICDATA_SORT, Integer.class);
301 }
302
303
304
305
306
307
308 public final PrometheusStaticDataClass getStaticClass() {
309 return getValues().getValue(PrometheusDataResource.STATICDATA_CLASS, PrometheusStaticDataClass.class);
310 }
311
312
313
314
315
316
317 public final boolean getEnabled() {
318 return getValues().getValue(PrometheusDataResource.STATICDATA_ENABLED, Boolean.class);
319 }
320
321 @Override
322 public boolean isDisabled() {
323 return !getEnabled();
324 }
325
326
327
328
329
330
331 protected final Class<? extends PrometheusStaticDataClass> getEnumClass() {
332 return theEnumClass;
333 }
334
335
336
337
338
339
340
341 private void setValueName(final String pValue) throws OceanusException {
342 setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pValue);
343 }
344
345
346
347
348
349
350
351 private void setValueName(final byte[] pBytes) throws OceanusException {
352 setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pBytes, String.class);
353 }
354
355
356
357
358
359
360 private void setValueName(final PrometheusEncryptedPair pField) {
361 getValues().setUncheckedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pField);
362 }
363
364
365
366
367
368
369
370 protected final void setValueDesc(final String pValue) throws OceanusException {
371 setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pValue);
372 }
373
374
375
376
377
378
379
380 private void setValueDesc(final byte[] pBytes) throws OceanusException {
381 setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pBytes, String.class);
382 }
383
384
385
386
387
388
389 private void setValueDesc(final PrometheusEncryptedPair pField) {
390 getValues().setUncheckedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pField);
391 }
392
393
394
395
396
397
398 protected final void setValueEnabled(final Boolean isEnabled) {
399 getValues().setUncheckedValue(PrometheusDataResource.STATICDATA_ENABLED, isEnabled);
400 }
401
402
403
404
405
406
407 private void setValueOrder(final Integer pOrder) {
408 getValues().setUncheckedValue(PrometheusDataResource.STATICDATA_SORT, pOrder);
409 }
410
411
412
413
414
415
416 private void setValueClass(final PrometheusStaticDataClass pClass) {
417 getValues().setUncheckedValue(PrometheusDataResource.STATICDATA_CLASS, pClass);
418 }
419
420 @Override
421 public int compareValues(final PrometheusDataItem pThat) {
422
423 final PrometheusStaticDataItem myThat = (PrometheusStaticDataItem) pThat;
424
425
426 if (!MetisDataDifference.isEqual(getEnumClass(), myThat.getEnumClass())) {
427
428 return getEnumClass().getCanonicalName().compareTo(myThat.getEnumClass().getCanonicalName());
429 }
430
431
432 final int iDiff = getOrder() - myThat.getOrder();
433 return iDiff != 0 ? iDiff : MetisDataDifference.compareObject(getName(), myThat.getName());
434 }
435
436 @Override
437 public PrometheusStaticList<?> getList() {
438 return (PrometheusStaticList<?>) super.getList();
439 }
440
441
442
443
444
445
446
447 private void parseEnumValue(final String pValue) throws OceanusException {
448 final Class<? extends PrometheusStaticDataClass> myClass = getEnumClass();
449 final PrometheusStaticDataClass[] myEnums = myClass.getEnumConstants();
450
451
452 for (PrometheusStaticDataClass myValue : myEnums) {
453
454 if (myValue.toString().equalsIgnoreCase(pValue)) {
455
456 setValueClass(myValue);
457
458
459 setIndexedId(myValue.getClassId());
460 setValueOrder(myValue.getOrder());
461 break;
462 }
463 }
464
465
466 if (getStaticClass() == null) {
467 throw new PrometheusDataException(ERROR_BADNAME + " " + myClass.getSimpleName() + ": " + pValue);
468 }
469 }
470
471
472
473
474
475
476
477 private void parseEnumValue(final Integer pValue) throws OceanusException {
478 final Class<? extends PrometheusStaticDataClass> myClass = getEnumClass();
479 final PrometheusStaticDataClass[] myEnums = myClass.getEnumConstants();
480
481
482 for (PrometheusStaticDataClass myValue : myEnums) {
483
484 if (pValue.equals(myValue.getClassId())) {
485
486 setValueClass(myValue);
487
488
489 setIndexedId(myValue.getClassId());
490 setValueOrder(myValue.getOrder());
491 break;
492 }
493 }
494
495
496 if (getStaticClass() == null) {
497 throw new PrometheusDataException(ERROR_BADNAME + " " + myClass.getSimpleName() + ": " + pValue);
498 }
499 }
500
501
502
503
504
505
506
507 public void setName(final String pName) throws OceanusException {
508 setValueName(pName);
509 }
510
511
512
513
514
515
516
517 public void setDescription(final String pDesc) throws OceanusException {
518
519 setValueDesc(pDesc);
520 }
521
522
523
524
525
526
527 public void setEnabled(final boolean isEnabled) {
528
529 setValueEnabled(isEnabled);
530 }
531
532
533
534
535
536
537 public void setOrder(final int iOrder) {
538
539 setValueOrder(iOrder);
540 }
541
542 @Override
543 public boolean applyChanges(final PrometheusDataItem pData) {
544
545 if (!(pData instanceof PrometheusStaticDataItem)) {
546 return false;
547 }
548
549
550 final PrometheusStaticDataItem myData = (PrometheusStaticDataItem) pData;
551
552
553 pushHistory();
554
555
556 applyBasicChanges(myData);
557
558
559 return checkForHistory();
560 }
561
562
563
564
565
566
567 protected void applyBasicChanges(final PrometheusStaticDataItem pData) {
568
569 if (!MetisDataDifference.isEqual(getName(), pData.getName())) {
570 setValueName(pData.getNameField());
571 }
572
573
574 if (!MetisDataDifference.isEqual(getDesc(), pData.getDesc())) {
575 setValueDesc(pData.getDescField());
576 }
577
578
579 if (!MetisDataDifference.isEqual(getEnabled(), pData.getEnabled())) {
580 setEnabled(pData.getEnabled());
581 }
582
583
584 if (!MetisDataDifference.isEqual(getOrder(), pData.getOrder())) {
585 setOrder(pData.getOrder());
586 }
587 }
588
589 @Override
590 public void adjustMapForItem() {
591 final PrometheusStaticList<?> myList = getList();
592 final PrometheusStaticDataMap<?> myMap = myList.getDataMap();
593 myMap.adjustForItem(myList.getBaseClass().cast(this));
594 }
595
596
597
598
599
600
601 public abstract static class PrometheusStaticList<T extends PrometheusStaticDataItem>
602 extends PrometheusEncryptedList<T> {
603
604
605
606 static {
607 MetisFieldSet.newFieldSet(PrometheusStaticList.class);
608 }
609
610
611
612
613
614
615
616
617
618 protected PrometheusStaticList(final Class<T> pBaseClass,
619 final PrometheusCryptographicDataSet pData,
620 final MetisListKey pItemType,
621 final PrometheusListStyle pStyle) {
622 super(pBaseClass, pData, pItemType, pStyle);
623 }
624
625
626
627
628
629
630 protected PrometheusStaticList(final PrometheusStaticList<T> pSource) {
631 super(pSource);
632 }
633
634
635
636
637
638
639 protected abstract Class<? extends PrometheusStaticDataClass> getEnumClass();
640
641 @Override
642 @SuppressWarnings("unchecked")
643 public PrometheusStaticDataMap<T> getDataMap() {
644 return (PrometheusStaticDataMap<T>) super.getDataMap();
645 }
646
647
648
649
650
651
652
653 public T findItemByClass(final PrometheusStaticDataClass eClass) {
654
655 return findItemById(eClass.getClassId());
656 }
657
658 @Override
659 public T findItemByName(final String pName) {
660
661 return getDataMap().findItemByName(pName);
662 }
663
664
665
666
667
668
669 public boolean isFull() {
670
671 if (size() < getEnumClass().getEnumConstants().length) {
672 return false;
673 }
674
675
676 final Iterator<T> myIterator = iterator();
677 while (myIterator.hasNext()) {
678 final T myCurr = myIterator.next();
679
680
681 if (myCurr.isDeleted()) {
682
683 return false;
684 }
685 }
686
687
688 return true;
689 }
690
691
692
693
694
695
696 public List<PrometheusStaticDataClass> getMissingClasses() {
697
698 final List<PrometheusStaticDataClass> myList = new ArrayList<>();
699
700
701 for (PrometheusStaticDataClass myClass : getEnumClass().getEnumConstants()) {
702
703 final T myItem = findItemById(myClass.getClassId());
704
705
706 if ((myItem == null)
707 || myItem.isDeleted()) {
708
709 myList.add(myClass);
710 }
711 }
712
713
714 return myList;
715 }
716
717
718
719
720
721
722
723
724 public T addNewItem(final PrometheusStaticDataClass pClass) throws OceanusException {
725
726 return newItem(pClass);
727 }
728
729
730
731
732
733
734
735
736 protected abstract T newItem(PrometheusStaticDataClass pClass) throws OceanusException;
737
738
739
740
741
742
743 public void populateDefaults() throws OceanusException {
744
745 for (PrometheusStaticDataClass myClass : getEnumClass().getEnumConstants()) {
746
747 final T myItem = newItem(myClass);
748
749
750 myItem.validate();
751
752
753 if (myItem.hasErrors()) {
754 throw new PrometheusDataException(myItem, ERROR_VALIDATION);
755 }
756 }
757
758
759 reSort();
760 }
761
762 @Override
763 protected PrometheusDataMapItem allocateDataMap() {
764 return new PrometheusStaticDataMap<>();
765 }
766 }
767
768
769
770
771
772
773 public static class PrometheusStaticDataMap<T extends PrometheusStaticDataItem>
774 extends PrometheusDataInstanceMap<T, String> {
775
776
777
778 @SuppressWarnings("rawtypes")
779 private static final MetisFieldSet<PrometheusStaticDataMap> FIELD_DEFS = MetisFieldSet.newFieldSet(PrometheusStaticDataMap.class);
780
781
782
783
784 static {
785 FIELD_DEFS.declareLocalField(PrometheusDataResource.STATICDATAMAP_ORDERCOUNTS, PrometheusStaticDataMap::getOrderCountMap);
786 }
787
788
789
790
791 private final Map<Integer, Integer> theOrderCountMap;
792
793
794
795
796 public PrometheusStaticDataMap() {
797
798 theOrderCountMap = new HashMap<>();
799 }
800
801 @SuppressWarnings("rawtypes")
802 @Override
803 public MetisFieldSet<? extends PrometheusStaticDataMap> getDataFieldSet() {
804 return FIELD_DEFS;
805 }
806
807 @Override
808 public String formatObject(final OceanusDataFormatter pFormatter) {
809 return FIELD_DEFS.getName();
810 }
811
812
813
814
815
816
817 private Map<Integer, Integer> getOrderCountMap() {
818 return theOrderCountMap;
819 }
820
821 @Override
822 public void resetMap() {
823 super.resetMap();
824 theOrderCountMap.clear();
825 }
826
827 @Override
828 @SuppressWarnings("unchecked")
829 public void adjustForItem(final PrometheusDataItem pItem) {
830
831 final T myItem = (T) pItem;
832
833
834 final Integer myOrder = myItem.getOrder();
835 final Integer myCount = theOrderCountMap.get(myOrder);
836 if (myCount == null) {
837 theOrderCountMap.put(myOrder, ONE);
838 } else {
839 theOrderCountMap.put(myOrder, myCount + 1);
840 }
841
842
843 adjustForItem(myItem, myItem.getName());
844 }
845
846
847
848
849
850
851
852 public T findItemByName(final String pName) {
853 return findItemByKey(pName);
854 }
855
856
857
858
859
860
861
862 public boolean validNameCount(final String pName) {
863 return validKeyCount(pName);
864 }
865
866
867
868
869
870
871
872 public boolean availableName(final String pName) {
873 return availableKey(pName);
874 }
875
876
877
878
879
880
881
882 public boolean validOrderCount(final Integer pOrder) {
883 final Integer myResult = theOrderCountMap.get(pOrder);
884 return ONE.equals(myResult);
885 }
886 }
887 }