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.maps;
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.MetisDataType;
22  import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
23  import io.github.tonywasher.joceanus.metis.field.MetisFieldSet;
24  import io.github.tonywasher.joceanus.metis.list.MetisListKey;
25  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataInfoClass;
26  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataInfoItem;
27  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataItem;
28  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataList;
29  import io.github.tonywasher.joceanus.prometheus.data.PrometheusDataSet;
30  import io.github.tonywasher.joceanus.prometheus.views.PrometheusEditSet;
31  
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.function.Function;
35  
36  /**
37   * Maps control.
38   */
39  public class PrometheusMapsCtl
40          implements MetisFieldItem {
41      /**
42       * Report fields.
43       */
44      private static final MetisFieldSet<PrometheusMapsCtl> FIELD_DEFS = MetisFieldSet.newFieldSet(PrometheusMapsCtl.class);
45  
46      /*
47       * Declare Fields.
48       */
49      static {
50          FIELD_DEFS.declareLocalField(PrometheusMapsResource.MAPS_TOUCHMAP, PrometheusMapsCtl::getTouchMap);
51          FIELD_DEFS.declareLocalField(PrometheusMapsResource.MAPS_INSTANCEMAP, PrometheusMapsCtl::getInstanceMap);
52      }
53  
54      /**
55       * The touchMap.
56       */
57      private PrometheusMapsTouchCtl theTouch;
58  
59      /**
60       * The instanceMap.
61       */
62      private PrometheusMapsInstanceCtl theInstance;
63  
64      /**
65       * The deconstruct lambda.
66       */
67      private Function<Object, List<PrometheusDataItem>> theDeconstruct;
68  
69      /**
70       * Constructor.
71       *
72       * @param pDeconstruct the deconstruct processor
73       */
74      public PrometheusMapsCtl(final Function<Object, List<PrometheusDataItem>> pDeconstruct) {
75          /* Create maps */
76          theTouch = new PrometheusMapsTouchCtl();
77          theInstance = new PrometheusMapsInstanceCtl();
78          theDeconstruct = pDeconstruct;
79      }
80  
81      @Override
82      public MetisFieldSetDef getDataFieldSet() {
83          return FIELD_DEFS;
84      }
85  
86      @Override
87      public String formatObject(final OceanusDataFormatter pFormatter) {
88          return PrometheusMapsInstanceCtl.class.getSimpleName();
89      }
90  
91      /**
92       * Obtain the touch map.
93       *
94       * @return the touch map
95       */
96      private PrometheusMapsTouchCtl getTouchMap() {
97          return theTouch;
98      }
99  
100     /**
101      * Obtain the instance map.
102      *
103      * @return the instance map
104      */
105     private PrometheusMapsInstanceCtl getInstanceMap() {
106         return theInstance;
107     }
108 
109     /**
110      * Declare fieldId map.
111      *
112      * @param pListKey the listKey
113      * @param pFieldId the fieldId
114      */
115     public void declareFieldIdMap(final MetisListKey pListKey,
116                                   final MetisDataFieldId pFieldId) {
117         theInstance.declareFieldIdMap(pListKey, pFieldId);
118     }
119 
120     /**
121      * Declare fieldId map.
122      *
123      * @param pListKey the listKey
124      * @param pFieldId the fieldId
125      * @param pFilter  the filter
126      */
127     public void declareFieldIdMap(final MetisListKey pListKey,
128                                   final MetisDataFieldId pFieldId,
129                                   final Function<PrometheusDataItem, Boolean> pFilter) {
130         theInstance.declareFieldIdMap(pListKey, pFieldId, pFilter);
131     }
132 
133     /**
134      * Declare shared fieldId map.
135      *
136      * @param pListKey   the listKey
137      * @param pFieldId   the fieldId
138      * @param pSharedKey the shared listKey
139      */
140     public void declareFieldIdMap(final MetisListKey pListKey,
141                                   final MetisDataFieldId pFieldId,
142                                   final MetisListKey pSharedKey) {
143         theInstance.declareFieldIdMap(pListKey, pFieldId, pSharedKey);
144     }
145 
146     /**
147      * Declare dateId map.
148      *
149      * @param pListKey the listKey
150      * @param pOwnerId the ownerId
151      * @param pDateId  the dateId
152      */
153     public void declareDateIdMap(final MetisListKey pListKey,
154                                  final MetisDataFieldId pOwnerId,
155                                  final MetisDataFieldId pDateId) {
156         theInstance.declareDateIdMap(pListKey, pOwnerId, pDateId, false);
157     }
158 
159     /**
160      * Declare dateId map.
161      *
162      * @param pListKey   the listKey
163      * @param pOwnerId   the ownerId
164      * @param pDateId    the dateId
165      * @param pAllowNull do we allow null value?
166      */
167     public void declareDateIdMap(final MetisListKey pListKey,
168                                  final MetisDataFieldId pOwnerId,
169                                  final MetisDataFieldId pDateId,
170                                  final boolean pAllowNull) {
171         theInstance.declareDateIdMap(pListKey, pOwnerId, pDateId, pAllowNull);
172     }
173 
174     /**
175      * Reset the maps.
176      */
177     public void resetMaps() {
178         theTouch.resetMap();
179         theInstance.resetMaps();
180     }
181 
182     /**
183      * Adjust for DataSet.
184      *
185      * @param pDataSet the dataSet
186      */
187     public void adjustForDataSet(final PrometheusDataSet pDataSet) {
188         final Iterator<MetisListKey> myIterator = pDataSet.keyIterator();
189         while (myIterator.hasNext()) {
190             final MetisListKey myKey = myIterator.next();
191             final PrometheusDataList<?> myList = pDataSet.getDataList(myKey, PrometheusDataList.class);
192 
193             adjustForDataList(myList);
194         }
195     }
196 
197     /**
198      * Adjust for EditSet.
199      *
200      * @param pEditSet the editSet
201      */
202     public void adjustForEditSet(final PrometheusEditSet pEditSet) {
203         final PrometheusDataSet myDataSet = pEditSet.getDataSet();
204         final Iterator<MetisListKey> myIterator = myDataSet.keyIterator();
205         while (myIterator.hasNext()) {
206             final MetisListKey myKey = myIterator.next();
207             final PrometheusDataList<?> myList = pEditSet.getDataList(myKey, PrometheusDataList.class);
208 
209             adjustForDataList(myList);
210         }
211     }
212 
213     /**
214      * Adjust for DataList.
215      *
216      * @param pDataList the dataList
217      */
218     void adjustForDataList(final PrometheusDataList<?> pDataList) {
219         final Iterator<?> myIterator = pDataList.iterator();
220         while (myIterator.hasNext()) {
221             final PrometheusDataItem myItem = (PrometheusDataItem) myIterator.next();
222             if (!myItem.isDeleted()) {
223                 adjustForDataItem(myItem);
224             }
225         }
226     }
227 
228     /**
229      * Adjust for DataItem.
230      *
231      * @param pItem the dataItem
232      */
233     void adjustForDataItem(final PrometheusDataItem pItem) {
234         /* Add item to instance maps */
235         theInstance.addItemToMaps(pItem);
236 
237         /* If the item is an InfoItem */
238         if (pItem instanceof PrometheusDataInfoItem myItem) {
239             adjustForDataInfoItemTouches(myItem);
240         } else {
241             adjustForStandardItemTouches(pItem);
242         }
243     }
244 
245     /**
246      * Adjust for DataItem.
247      *
248      * @param pItem the dataItem
249      */
250     void adjustForStandardItemTouches(final PrometheusDataItem pItem) {
251         /* Loop through the item fields */
252         final MetisFieldSetDef myFieldSet = pItem.getDataFieldSet();
253         final Iterator<MetisFieldDef> myIterator = myFieldSet.fieldIterator();
254         while (myIterator.hasNext()) {
255             final MetisFieldDef myField = myIterator.next();
256 
257             /* If this is a link */
258             if (MetisDataType.LINK.equals(myField.getDataType())) {
259                 final Object myTouched = myField.getFieldValue(pItem);
260                 if (myTouched != null) {
261                     if (myTouched instanceof PrometheusDataItem myItem) {
262                         theTouch.recordTouch(myItem, pItem);
263                     } else {
264                         final List<PrometheusDataItem> myList = theDeconstruct.apply(myTouched);
265                         for (PrometheusDataItem myItem : myList) {
266                             theTouch.recordTouch(myItem, pItem);
267                         }
268                     }
269                 }
270             }
271         }
272     }
273 
274     /**
275      * Adjust for DataInfoItem.
276      *
277      * @param pInfo the dataInfoItem
278      */
279     void adjustForDataInfoItemTouches(final PrometheusDataInfoItem pInfo) {
280         final PrometheusDataInfoClass myClass = pInfo.getInfoClass();
281         if (myClass.isLink()) {
282             theTouch.recordTouch(pInfo.getLink(PrometheusDataItem.class), pInfo.getOwner());
283         }
284     }
285 }