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.format.OceanusDataFormatter;
20 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataFieldId;
21 import io.github.tonywasher.joceanus.metis.data.MetisDataResource;
22 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem.MetisFieldDef;
23 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem.MetisFieldSetDef;
24 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem.MetisFieldVersionedDef;
25 import io.github.tonywasher.joceanus.metis.field.MetisFieldVersionValues;
26 import org.w3c.dom.Document;
27 import org.w3c.dom.Element;
28 import org.w3c.dom.Node;
29
30 import java.util.ArrayList;
31 import java.util.Iterator;
32 import java.util.LinkedHashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Map.Entry;
36
37
38
39
40
41
42 public class PrometheusDataValues {
43
44
45
46 @FunctionalInterface
47 public interface PrometheusInfoSetItem {
48
49
50
51
52
53 PrometheusDataInfoSet<?> getInfoSet();
54 }
55
56
57
58
59 public interface PrometheusGroupedItem {
60
61
62
63
64
65 boolean isChild();
66
67
68
69
70
71
72 Iterator<? extends PrometheusDataItem> childIterator();
73 }
74
75
76
77
78 private static final String TAG_INFOSET = PrometheusDataResource.DATAINFOSET_NAME.getValue();
79
80
81
82
83 private static final String TAG_CHILDREN = PrometheusDataResource.DATAVALUES_CHILDREN.getValue();
84
85
86
87
88 private static final String TAG_CHILD = PrometheusDataResource.DATAVALUES_CHILD.getValue();
89
90
91
92
93 protected static final String ATTR_TYPE = PrometheusDataResource.DATAVALUES_ATTRTYPE.getValue();
94
95
96
97
98 protected static final String ATTR_SIZE = PrometheusDataResource.DATAVALUES_ATTRSIZE.getValue();
99
100
101
102
103 protected static final String ATTR_VERS = PrometheusDataResource.DATAVALUES_ATTRVER.getValue();
104
105
106
107
108 private final String theItemType;
109
110
111
112
113 private final Map<MetisDataFieldId, Object> theFields;
114
115
116
117
118 private final List<PrometheusInfoItem> theInfoItems;
119
120
121
122
123 private final List<PrometheusDataValues> theChildren;
124
125
126
127
128
129
130
131 protected PrometheusDataValues(final PrometheusDataItem pItem,
132 final String pItemName) {
133
134 theItemType = pItemName;
135
136
137 theFields = new LinkedHashMap<>();
138
139
140 theFields.put(MetisDataResource.DATA_ID, pItem.getIndexedId());
141
142
143 final MetisFieldVersionValues myValues = pItem.getValues();
144
145
146 final Iterator<MetisFieldDef> myIterator = pItem.getDataFieldSet().fieldIterator();
147 while (myIterator.hasNext()) {
148 final MetisFieldDef myField = myIterator.next();
149 final MetisDataFieldId myFieldId = myField.getFieldId();
150
151
152 if (!(myField instanceof MetisFieldVersionedDef myVersioned)
153 || !myVersioned.isEquality()) {
154 continue;
155 }
156
157
158 if (pItem.includeXmlField(myFieldId)) {
159
160 theFields.put(myFieldId, myValues.getValue(myField));
161 }
162 }
163
164
165 if (pItem instanceof PrometheusInfoSetItem myInfoItem) {
166
167 final PrometheusDataInfoSet<?> myInfoSet = myInfoItem.getInfoSet();
168
169
170 if (myInfoSet.isEmpty()) {
171
172 theInfoItems = null;
173 } else {
174
175 theInfoItems = new ArrayList<>();
176
177
178 final Iterator<?> myInfoIterator = myInfoSet.iterator();
179 while (myInfoIterator.hasNext()) {
180 final Object myCurr = myInfoIterator.next();
181
182
183 if (myCurr instanceof PrometheusDataInfoItem myItem) {
184
185 final PrometheusInfoItem myInfo = new PrometheusInfoItem(myItem);
186 theInfoItems.add(myInfo);
187 }
188 }
189 }
190
191
192 } else {
193 theInfoItems = null;
194 }
195
196
197 if (pItem instanceof PrometheusGroupedItem myGrouped) {
198
199 final Iterator<? extends PrometheusDataItem> myChildIterator = myGrouped.childIterator();
200
201
202 if (myChildIterator == null) {
203 theChildren = null;
204 } else {
205
206 theChildren = new ArrayList<>();
207
208
209 while (myChildIterator.hasNext()) {
210 final PrometheusDataItem myCurr = myChildIterator.next();
211
212
213 final PrometheusDataValues myChild = new PrometheusDataValues(myCurr, TAG_CHILD);
214 theChildren.add(myChild);
215 }
216 }
217
218
219 } else {
220 theChildren = null;
221 }
222 }
223
224
225
226
227
228
229
230 private PrometheusDataValues(final PrometheusDataItem pOwner,
231 final PrometheusInfoItem pInfo) {
232
233 theItemType = "";
234
235
236 theFields = new LinkedHashMap<>();
237
238
239 final Integer myId = pInfo.getId();
240 if (myId != null) {
241 theFields.put(MetisDataResource.DATA_ID, myId);
242 }
243
244
245 theFields.put(PrometheusDataResource.DATAINFO_TYPE, pInfo.getName());
246
247
248 theFields.put(PrometheusDataResource.DATAINFO_OWNER, pOwner.getIndexedId());
249
250
251 theFields.put(PrometheusDataResource.DATAINFO_VALUE, pInfo.getValue());
252
253
254 theInfoItems = null;
255 theChildren = null;
256 }
257
258
259
260
261
262
263
264 public PrometheusDataValues(final Element pElement,
265 final MetisFieldSetDef pFields) {
266 this(pElement, pFields, pElement.getNodeName());
267 }
268
269
270
271
272
273
274
275
276 protected PrometheusDataValues(final Element pElement,
277 final MetisFieldSetDef pFields,
278 final String pItemName) {
279
280 theItemType = pItemName;
281
282
283 theFields = new LinkedHashMap<>();
284
285
286 final Integer myId = getId(pElement);
287 if (myId != null) {
288 theFields.put(MetisDataResource.DATA_ID, myId);
289 }
290
291
292 final Iterator<MetisFieldDef> myIterator = pFields.fieldIterator();
293 while (myIterator.hasNext()) {
294 final MetisFieldDef myField = myIterator.next();
295
296
297 if (myField instanceof MetisFieldVersionedDef myVersioned
298 && myVersioned.isEquality()) {
299
300 final Element myChild = getChild(pElement, myField.getFieldId().getId());
301 if (myChild != null) {
302
303 theFields.put(myField.getFieldId(), myChild.getTextContent());
304 }
305 }
306 }
307
308
309 final Element myInfoSet = getChild(pElement, TAG_INFOSET);
310 if (myInfoSet != null) {
311
312 theInfoItems = new ArrayList<>();
313
314
315 for (Node myCurr = myInfoSet.getFirstChild(); myCurr != null; myCurr = myCurr.getNextSibling()) {
316
317 if (myCurr instanceof Element myChild) {
318
319 final PrometheusInfoItem myInfo = new PrometheusInfoItem(myChild);
320 theInfoItems.add(myInfo);
321 }
322 }
323
324
325 } else {
326 theInfoItems = null;
327 }
328
329
330 final Element myChildren = getChild(pElement, TAG_CHILDREN);
331 if (myChildren != null) {
332
333 theChildren = new ArrayList<>();
334
335
336 for (Node myCurr = myChildren.getFirstChild(); myCurr != null; myCurr = myCurr.getNextSibling()) {
337
338 if (myCurr instanceof Element myChild
339 && TAG_CHILD.equals(myCurr.getNodeName())) {
340
341 final PrometheusDataValues myValues = new PrometheusDataValues(myChild, pFields, theItemType);
342 theChildren.add(myValues);
343 }
344 }
345
346
347 } else {
348 theChildren = null;
349 }
350 }
351
352
353
354
355
356
357 public PrometheusDataValues(final String pName) {
358
359 theItemType = pName;
360
361
362 theFields = new LinkedHashMap<>();
363
364
365 theInfoItems = null;
366 theChildren = null;
367 }
368
369
370
371
372
373
374 public PrometheusDataValues(final PrometheusDataItem pItem) {
375 this(pItem, pItem.getDataFieldSet().getName());
376 }
377
378
379
380
381
382
383 public final String getItemType() {
384 return theItemType;
385 }
386
387
388
389
390
391
392 public final Iterator<Entry<MetisDataFieldId, Object>> fieldIterator() {
393 return theFields.entrySet().iterator();
394 }
395
396
397
398
399
400
401 public final boolean hasInfoItems() {
402 return theInfoItems != null;
403 }
404
405
406
407
408
409
410 public final Iterator<PrometheusInfoItem> infoIterator() {
411 return theInfoItems.iterator();
412 }
413
414
415
416
417
418
419 public final boolean hasChildren() {
420 return theChildren != null;
421 }
422
423
424
425
426
427
428 public final Iterator<PrometheusDataValues> childIterator() {
429 return theChildren.iterator();
430 }
431
432
433
434
435
436
437
438 public void addValue(final MetisDataFieldId pField,
439 final Object pValue) {
440
441 if (pValue != null) {
442
443 theFields.put(pField, pValue);
444 }
445 }
446
447
448
449
450
451
452
453 public Object getValue(final MetisDataFieldId pField) {
454
455 return theFields.get(pField);
456 }
457
458
459
460
461
462
463
464
465
466 public <T> T getValue(final MetisDataFieldId pField,
467 final Class<T> pClass) {
468
469 return pClass.cast(getValue(pField));
470 }
471
472
473
474
475
476
477
478 private static Integer getId(final Element pElement) {
479
480 final String myId = pElement.getAttribute(MetisDataResource.DATA_ID.getId());
481 return !myId.isEmpty()
482 ? Integer.parseInt(myId)
483 : null;
484 }
485
486
487
488
489
490
491
492
493 private static Element getChild(final Element pParent,
494 final String pName) {
495
496 for (Node myCurr = pParent.getFirstChild(); myCurr != null; myCurr = myCurr.getNextSibling()) {
497
498 if (myCurr instanceof Element myElement
499 && pName.equals(myCurr.getNodeName())) {
500
501 return myElement;
502 }
503 }
504
505
506 return null;
507 }
508
509
510
511
512
513
514
515
516
517 protected Element createXML(final Document pDocument,
518 final OceanusDataFormatter pFormatter,
519 final boolean pStoreIds) {
520
521 final Element myElement = pDocument.createElement(theItemType);
522
523
524 for (Entry<MetisDataFieldId, Object> myEntry : theFields.entrySet()) {
525
526 final MetisDataFieldId myFieldId = myEntry.getKey();
527 final Object myValue = myEntry.getValue();
528
529
530 if (MetisDataResource.DATA_ID.equals(myFieldId)) {
531
532 if (pStoreIds) {
533 myElement.setAttribute(myFieldId.getId(), myValue.toString());
534 }
535
536
537 continue;
538 }
539
540
541 final Element myChild = pDocument.createElement(myFieldId.getId());
542 myElement.appendChild(myChild);
543
544
545 myChild.setTextContent(pFormatter.formatObject(myValue));
546 }
547
548
549 if (theInfoItems != null) {
550
551 final Element myInfoSet = pDocument.createElement(TAG_INFOSET);
552 myElement.appendChild(myInfoSet);
553
554
555 for (PrometheusInfoItem myInfo : theInfoItems) {
556
557 final Element myItem = pDocument.createElement(myInfo.getName());
558 myInfoSet.appendChild(myItem);
559
560
561 if (pStoreIds) {
562 myItem.setAttribute(MetisDataResource.DATA_ID.getValue(), myInfo.getId().toString());
563 }
564
565
566 myItem.setTextContent(pFormatter.formatObject(myInfo.getValue()));
567 }
568 }
569
570
571 if (theChildren != null) {
572
573 final Element myChildren = pDocument.createElement(TAG_CHILDREN);
574 myElement.appendChild(myChildren);
575
576
577 final Iterator<PrometheusDataValues> myIterator = theChildren.iterator();
578 while (myIterator.hasNext()) {
579 final PrometheusDataValues myValues = myIterator.next();
580
581
582 final Element myChild = myValues.createXML(pDocument, pFormatter, pStoreIds);
583 myChildren.appendChild(myChild);
584 }
585 }
586
587
588 return myElement;
589 }
590
591
592
593
594 public static final class PrometheusInfoItem {
595
596
597
598 private final String theName;
599
600
601
602
603 private final Integer theId;
604
605
606
607
608 private final Object theValue;
609
610
611
612
613
614
615 private PrometheusInfoItem(final PrometheusDataInfoItem pInfo) {
616
617 final PrometheusDataInfoClass myClass = pInfo.getInfoClass();
618
619
620 theName = myClass.toString();
621 theId = pInfo.getIndexedId();
622 theValue = myClass.isLink()
623 ? pInfo.getLink()
624 : pInfo.getValue(Object.class);
625 }
626
627
628
629
630
631
632 private PrometheusInfoItem(final Element pElement) {
633
634 theName = pElement.getNodeName();
635 theId = PrometheusDataValues.getId(pElement);
636 theValue = pElement.getTextContent();
637 }
638
639
640
641
642
643
644 public String getName() {
645 return theName;
646 }
647
648
649
650
651
652
653 public Integer getId() {
654 return theId;
655 }
656
657
658
659
660
661
662 public Object getValue() {
663 return theValue;
664 }
665
666 @Override
667 public boolean equals(final Object pThat) {
668
669 if (this == pThat) {
670 return true;
671 }
672 if (pThat == null) {
673 return false;
674 }
675
676
677 if (pThat.getClass() != getClass()) {
678 return false;
679 }
680
681
682 final PrometheusInfoItem myItem = (PrometheusInfoItem) pThat;
683
684 if (!theName.equals(myItem.getName())) {
685 return false;
686 }
687 if (!theId.equals(myItem.getId())) {
688 return false;
689 }
690 return theValue.equals(myItem.getValue());
691 }
692
693 @Override
694 public int hashCode() {
695 return theName.hashCode() + theId + theValue.hashCode();
696 }
697
698 @Override
699 public String toString() {
700 return theName + "=" + theValue;
701 }
702
703
704
705
706
707
708
709 public PrometheusDataValues getValues(final PrometheusDataItem pOwner) {
710 return new PrometheusDataValues(pOwner, this);
711 }
712 }
713 }