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