View Javadoc
1   /*
2    * Prometheus: Application Framework
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
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   * Template for a Static Data item and List.
37   *
38   * @author Tony Washer
39   */
40  public abstract class PrometheusStaticDataItem
41          extends PrometheusEncryptedDataItem
42          implements MetisDataNamedItem {
43      /**
44       * Report fields.
45       */
46      private static final PrometheusEncryptedFieldSet<PrometheusStaticDataItem> FIELD_DEFS = PrometheusEncryptedFieldSet.newEncryptedFieldSet(PrometheusStaticDataItem.class);
47  
48      /*
49       * FieldIds.
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       * BadId error.
61       */
62      public static final String ERROR_BADID = PrometheusDataResource.STATICDATA_ERROR_ID.getValue();
63  
64      /**
65       * BadName error.
66       */
67      public static final String ERROR_BADNAME = PrometheusDataResource.STATICDATA_ERROR_NAME.getValue();
68  
69      /**
70       * The Enum Class for this Static Data.
71       */
72      private final Class<? extends PrometheusStaticDataClass> theEnumClass;
73  
74      /**
75       * Copy Constructor.
76       *
77       * @param pList   The list to associate the Static Data with
78       * @param pSource The static data to copy
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       * Basic Constructor.
89       *
90       * @param pList  The list to associate the Static Data with
91       * @param pValue the name of the new item
92       * @throws OceanusException on error
93       */
94      protected PrometheusStaticDataItem(final PrometheusStaticList<?> pList,
95                                         final String pValue) throws OceanusException {
96          /* Call super constructor */
97          super(pList, 0);
98  
99          /* Determine the class */
100         theEnumClass = pList.getEnumClass();
101         parseEnumValue(pValue);
102 
103         /* Record the name */
104         setValueName(pValue);
105         setValueEnabled(Boolean.TRUE);
106     }
107 
108     /**
109      * Basic Constructor.
110      *
111      * @param pList  The list to associate the Static Data with
112      * @param pClass the class of the new item
113      * @throws OceanusException on error
114      */
115     protected PrometheusStaticDataItem(final PrometheusStaticList<?> pList,
116                                        final PrometheusStaticDataClass pClass) throws OceanusException {
117         /* Call super constructor */
118         super(pList, 0);
119 
120         /* Determine the class */
121         theEnumClass = pList.getEnumClass();
122 
123         /* Store the class */
124         setValueClass(pClass);
125 
126         /* Set encryption */
127         setNextDataKeySet();
128 
129         /* Access classId and order */
130         setIndexedId(pClass.getClassId());
131         setValueOrder(pClass.getOrder());
132 
133         /* Record the name */
134         setValueName(pClass.toString());
135         setValueEnabled(Boolean.TRUE);
136 
137         /* Set the DataKeySet */
138         setNextDataKeySet();
139     }
140 
141     /**
142      * Values constructor.
143      *
144      * @param pList   the List to add to
145      * @param pValues the values constructor
146      * @throws OceanusException on error
147      */
148     protected PrometheusStaticDataItem(final PrometheusStaticList<?> pList,
149                                        final PrometheusDataValues pValues) throws OceanusException {
150         /* Initialise the item */
151         super(pList, pValues);
152 
153         /* Access formatter */
154         final OceanusDataFormatter myFormatter = getDataSet().getDataFormatter();
155 
156         /* Protect against exceptions */
157         try {
158             /* Determine the class */
159             theEnumClass = pList.getEnumClass();
160 
161             /* Store the Name */
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             /* Store the Description */
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             /* Store the class */
178             myValue = pValues.getValue(PrometheusDataResource.STATICDATA_CLASS);
179             if (myValue instanceof String s) {
180                 parseEnumValue(s);
181             } else {
182                 parseEnumValue(getIndexedId());
183             }
184 
185             /* Store the Order */
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             /* Store the Enabled flag */
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             /* Catch Exceptions */
202         } catch (NumberFormatException
203                  | OceanusException e) {
204             /* Pass on exception */
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         /* Determine whether fields should be included */
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         /* Pass call on */
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      * Return the encrypted name of the Static Data.
251      *
252      * @return the encrypted name
253      */
254     public final byte[] getNameBytes() {
255         return getValues().getEncryptedBytes(PrometheusDataResource.DATAITEM_FIELD_NAME);
256     }
257 
258     /**
259      * Return the encrypted name field of the Static Data.
260      *
261      * @return the encrypted field
262      */
263     private PrometheusEncryptedPair getNameField() {
264         return getValues().getEncryptedPair(PrometheusDataResource.DATAITEM_FIELD_NAME);
265     }
266 
267     /**
268      * Return the description of the Static Data.
269      *
270      * @return the description
271      */
272     public final String getDesc() {
273         return getValues().getValue(PrometheusDataResource.DATAITEM_FIELD_DESC, String.class);
274     }
275 
276     /**
277      * Return the encrypted description of the Static Data.
278      *
279      * @return the encrypted description
280      */
281     public final byte[] getDescBytes() {
282         return getValues().getEncryptedBytes(PrometheusDataResource.DATAITEM_FIELD_DESC);
283     }
284 
285     /**
286      * Return the encrypted description field of the Static Data.
287      *
288      * @return the encrypted name
289      */
290     private PrometheusEncryptedPair getDescField() {
291         return getValues().getEncryptedPair(PrometheusDataResource.DATAITEM_FIELD_DESC);
292     }
293 
294     /**
295      * Return the sort order of the Static Data.
296      *
297      * @return the order
298      */
299     public final Integer getOrder() {
300         return getValues().getValue(PrometheusDataResource.STATICDATA_SORT, Integer.class);
301     }
302 
303     /**
304      * Return the Static class of the Static Data.
305      *
306      * @return the class
307      */
308     public final PrometheusStaticDataClass getStaticClass() {
309         return getValues().getValue(PrometheusDataResource.STATICDATA_CLASS, PrometheusStaticDataClass.class);
310     }
311 
312     /**
313      * Is the Static item enabled.
314      *
315      * @return <code>true/false</code>
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      * Obtain the Enum class of this Static Data.
328      *
329      * @return the class
330      */
331     protected final Class<? extends PrometheusStaticDataClass> getEnumClass() {
332         return theEnumClass;
333     }
334 
335     /**
336      * Set the Name.
337      *
338      * @param pValue the name
339      * @throws OceanusException on error
340      */
341     private void setValueName(final String pValue) throws OceanusException {
342         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pValue);
343     }
344 
345     /**
346      * Set the Name.
347      *
348      * @param pBytes the encrypted name
349      * @throws OceanusException on error
350      */
351     private void setValueName(final byte[] pBytes) throws OceanusException {
352         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pBytes, String.class);
353     }
354 
355     /**
356      * Set the Name field.
357      *
358      * @param pField the encrypted name
359      */
360     private void setValueName(final PrometheusEncryptedPair pField) {
361         getValues().setUncheckedValue(PrometheusDataResource.DATAITEM_FIELD_NAME, pField);
362     }
363 
364     /**
365      * Set the Description.
366      *
367      * @param pValue the description
368      * @throws OceanusException on error
369      */
370     protected final void setValueDesc(final String pValue) throws OceanusException {
371         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pValue);
372     }
373 
374     /**
375      * Set the Description.
376      *
377      * @param pBytes the encrypted description
378      * @throws OceanusException on error
379      */
380     private void setValueDesc(final byte[] pBytes) throws OceanusException {
381         setEncryptedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pBytes, String.class);
382     }
383 
384     /**
385      * Set the Description field.
386      *
387      * @param pField the encrypted description
388      */
389     private void setValueDesc(final PrometheusEncryptedPair pField) {
390         getValues().setUncheckedValue(PrometheusDataResource.DATAITEM_FIELD_DESC, pField);
391     }
392 
393     /**
394      * Set the Enabled flag.
395      *
396      * @param isEnabled TRUE/FALSE
397      */
398     protected final void setValueEnabled(final Boolean isEnabled) {
399         getValues().setUncheckedValue(PrometheusDataResource.STATICDATA_ENABLED, isEnabled);
400     }
401 
402     /**
403      * Set the Order.
404      *
405      * @param pOrder the order
406      */
407     private void setValueOrder(final Integer pOrder) {
408         getValues().setUncheckedValue(PrometheusDataResource.STATICDATA_SORT, pOrder);
409     }
410 
411     /**
412      * Set the Class.
413      *
414      * @param pClass the class
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         /* Access as StaticDataItem */
423         final PrometheusStaticDataItem myThat = (PrometheusStaticDataItem) pThat;
424 
425         /* Make sure that the object is the same enumeration class */
426         if (!MetisDataDifference.isEqual(getEnumClass(), myThat.getEnumClass())) {
427             /* Order the classes by canonical name */
428             return getEnumClass().getCanonicalName().compareTo(myThat.getEnumClass().getCanonicalName());
429         }
430 
431         /* Compare on order and name */
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      * Parse enum type.
443      *
444      * @param pValue the value
445      * @throws OceanusException on error
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         /* Loop through the enum constants */
452         for (PrometheusStaticDataClass myValue : myEnums) {
453             /* If this is the desired value */
454             if (myValue.toString().equalsIgnoreCase(pValue)) {
455                 /* Store the class */
456                 setValueClass(myValue);
457 
458                 /* Access classId and order */
459                 setIndexedId(myValue.getClassId());
460                 setValueOrder(myValue.getOrder());
461                 break;
462             }
463         }
464 
465         /* Reject if we didn't find the class */
466         if (getStaticClass() == null) {
467             throw new PrometheusDataException(ERROR_BADNAME + " " + myClass.getSimpleName() + ": " + pValue);
468         }
469     }
470 
471     /**
472      * Parse enum type.
473      *
474      * @param pValue the value
475      * @throws OceanusException on error
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         /* Loop through the enum constants */
482         for (PrometheusStaticDataClass myValue : myEnums) {
483             /* If this is the desired value */
484             if (pValue.equals(myValue.getClassId())) {
485                 /* Store the class */
486                 setValueClass(myValue);
487 
488                 /* Access classId and order */
489                 setIndexedId(myValue.getClassId());
490                 setValueOrder(myValue.getOrder());
491                 break;
492             }
493         }
494 
495         /* Reject if we didn't find the class */
496         if (getStaticClass() == null) {
497             throw new PrometheusDataException(ERROR_BADNAME + " " + myClass.getSimpleName() + ": " + pValue);
498         }
499     }
500 
501     /**
502      * Set a new name.
503      *
504      * @param pName the name
505      * @throws OceanusException on error
506      */
507     public void setName(final String pName) throws OceanusException {
508         setValueName(pName);
509     }
510 
511     /**
512      * Set a new description.
513      *
514      * @param pDesc the description
515      * @throws OceanusException on error
516      */
517     public void setDescription(final String pDesc) throws OceanusException {
518         /* Set the appropriate value */
519         setValueDesc(pDesc);
520     }
521 
522     /**
523      * Set Enabled indicator.
524      *
525      * @param isEnabled TRUE/FALSE
526      */
527     public void setEnabled(final boolean isEnabled) {
528         /* Set the appropriate value */
529         setValueEnabled(isEnabled);
530     }
531 
532     /**
533      * Set Order indicator.
534      *
535      * @param iOrder the order
536      */
537     public void setOrder(final int iOrder) {
538         /* Set the appropriate value */
539         setValueOrder(iOrder);
540     }
541 
542     @Override
543     public boolean applyChanges(final PrometheusDataItem pData) {
544         /* Can only apply changes for Static Data */
545         if (!(pData instanceof PrometheusStaticDataItem)) {
546             return false;
547         }
548 
549         /* Access the data */
550         final PrometheusStaticDataItem myData = (PrometheusStaticDataItem) pData;
551 
552         /* Store the current detail into history */
553         pushHistory();
554 
555         /* Apply basic changes */
556         applyBasicChanges(myData);
557 
558         /* Check for changes */
559         return checkForHistory();
560     }
561 
562     /**
563      * Apply basic changes.
564      *
565      * @param pData the changed element
566      */
567     protected void applyBasicChanges(final PrometheusStaticDataItem pData) {
568         /* Update the name if required */
569         if (!MetisDataDifference.isEqual(getName(), pData.getName())) {
570             setValueName(pData.getNameField());
571         }
572 
573         /* Update the description if required */
574         if (!MetisDataDifference.isEqual(getDesc(), pData.getDesc())) {
575             setValueDesc(pData.getDescField());
576         }
577 
578         /* Update the enabled indication if required */
579         if (!MetisDataDifference.isEqual(getEnabled(), pData.getEnabled())) {
580             setEnabled(pData.getEnabled());
581         }
582 
583         /* Update the order indication if required */
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      * Represents a list of StaticData objects.
598      *
599      * @param <T> the item type
600      */
601     public abstract static class PrometheusStaticList<T extends PrometheusStaticDataItem>
602             extends PrometheusEncryptedList<T> {
603         /*
604          * Report fields.
605          */
606         static {
607             MetisFieldSet.newFieldSet(PrometheusStaticList.class);
608         }
609 
610         /**
611          * Construct a generic static data list.
612          *
613          * @param pBaseClass the class of the underlying object
614          * @param pData      the dataSet
615          * @param pItemType  the item type
616          * @param pStyle     the style of the list
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          * Constructor for a cloned List.
627          *
628          * @param pSource the source List
629          */
630         protected PrometheusStaticList(final PrometheusStaticList<T> pSource) {
631             super(pSource);
632         }
633 
634         /**
635          * Obtain the enumClass.
636          *
637          * @return the enumClass
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          * Search for a particular item by class.
649          *
650          * @param eClass The class of the item to search for
651          * @return The Item if present (or <code>null</code> if not found)
652          */
653         public T findItemByClass(final PrometheusStaticDataClass eClass) {
654             /* Look for item by class Id */
655             return findItemById(eClass.getClassId());
656         }
657 
658         @Override
659         public T findItemByName(final String pName) {
660             /* look up the name in the map */
661             return getDataMap().findItemByName(pName);
662         }
663 
664         /**
665          * Is the list full?
666          *
667          * @return true/false
668          */
669         public boolean isFull() {
670             /* We can only be full with the correct number of items */
671             if (size() < getEnumClass().getEnumConstants().length) {
672                 return false;
673             }
674 
675             /* Loop through all elements */
676             final Iterator<T> myIterator = iterator();
677             while (myIterator.hasNext()) {
678                 final T myCurr = myIterator.next();
679 
680                 /* If the item is deleted */
681                 if (myCurr.isDeleted()) {
682                     /* Not full */
683                     return false;
684                 }
685             }
686 
687             /* Must be full */
688             return true;
689         }
690 
691         /**
692          * Obtain a list of classes that are missing/deleted.
693          *
694          * @return The List of classes
695          */
696         public List<PrometheusStaticDataClass> getMissingClasses() {
697             /* Allocate the list */
698             final List<PrometheusStaticDataClass> myList = new ArrayList<>();
699 
700             /* Loop through all elements */
701             for (PrometheusStaticDataClass myClass : getEnumClass().getEnumConstants()) {
702                 /* Locate the element */
703                 final T myItem = findItemById(myClass.getClassId());
704 
705                 /* If the item is missing or deleted */
706                 if ((myItem == null)
707                         || myItem.isDeleted()) {
708                     /* Add it to the list */
709                     myList.add(myClass);
710                 }
711             }
712 
713             /* Return the list */
714             return myList;
715         }
716 
717         /**
718          * Add Item for class.
719          *
720          * @param pClass the class to add
721          * @return the added class
722          * @throws OceanusException on error
723          */
724         public T addNewItem(final PrometheusStaticDataClass pClass) throws OceanusException {
725             /* Create the new item */
726             return newItem(pClass);
727         }
728 
729         /**
730          * Create new Item for class.
731          *
732          * @param pClass the class to create
733          * @return the created class
734          * @throws OceanusException on error
735          */
736         protected abstract T newItem(PrometheusStaticDataClass pClass) throws OceanusException;
737 
738         /**
739          * Populate default values.
740          *
741          * @throws OceanusException on error
742          */
743         public void populateDefaults() throws OceanusException {
744             /* Loop through all elements */
745             for (PrometheusStaticDataClass myClass : getEnumClass().getEnumConstants()) {
746                 /* Create new element */
747                 final T myItem = newItem(myClass);
748 
749                 /* Validate the item */
750                 myItem.validate();
751 
752                 /* Handle validation failure */
753                 if (myItem.hasErrors()) {
754                     throw new PrometheusDataException(myItem, ERROR_VALIDATION);
755                 }
756             }
757 
758             /* Ensure that the list is sorted */
759             reSort();
760         }
761 
762         @Override
763         protected PrometheusDataMapItem allocateDataMap() {
764             return new PrometheusStaticDataMap<>();
765         }
766     }
767 
768     /**
769      * The dataMap class.
770      *
771      * @param <T> the item type
772      */
773     public static class PrometheusStaticDataMap<T extends PrometheusStaticDataItem>
774             extends PrometheusDataInstanceMap<T, String> {
775         /**
776          * Report fields.
777          */
778         @SuppressWarnings("rawtypes")
779         private static final MetisFieldSet<PrometheusStaticDataMap> FIELD_DEFS = MetisFieldSet.newFieldSet(PrometheusStaticDataMap.class);
780 
781         /*
782          * Declare Fields.
783          */
784         static {
785             FIELD_DEFS.declareLocalField(PrometheusDataResource.STATICDATAMAP_ORDERCOUNTS, PrometheusStaticDataMap::getOrderCountMap);
786         }
787 
788         /**
789          * Map of order counts.
790          */
791         private final Map<Integer, Integer> theOrderCountMap;
792 
793         /**
794          * Constructor.
795          */
796         public PrometheusStaticDataMap() {
797             /* Create the maps */
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          * Obtain the keyMap.
814          *
815          * @return the map
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             /* Access item */
831             final T myItem = (T) pItem;
832 
833             /* Adjust order count */
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             /* Adjust name count */
843             adjustForItem(myItem, myItem.getName());
844         }
845 
846         /**
847          * find item by name.
848          *
849          * @param pName the name to look up
850          * @return the matching item
851          */
852         public T findItemByName(final String pName) {
853             return findItemByKey(pName);
854         }
855 
856         /**
857          * Check validity of name.
858          *
859          * @param pName the name to look up
860          * @return true/false
861          */
862         public boolean validNameCount(final String pName) {
863             return validKeyCount(pName);
864         }
865 
866         /**
867          * Check availability of name.
868          *
869          * @param pName the key to look up
870          * @return true/false
871          */
872         public boolean availableName(final String pName) {
873             return availableKey(pName);
874         }
875 
876         /**
877          * Check validity of order.
878          *
879          * @param pOrder the order to look up
880          * @return true/false
881          */
882         public boolean validOrderCount(final Integer pOrder) {
883             final Integer myResult = theOrderCountMap.get(pOrder);
884             return ONE.equals(myResult);
885         }
886     }
887 }