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