1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.github.tonywasher.joceanus.metis.viewer;
18
19 import io.github.tonywasher.joceanus.metis.data.MetisDataDelta;
20 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataList;
21 import io.github.tonywasher.joceanus.metis.data.MetisDataItem.MetisDataMap;
22 import io.github.tonywasher.joceanus.metis.field.MetisFieldItem;
23 import io.github.tonywasher.joceanus.oceanus.profile.OceanusProfile;
24
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28
29
30
31
32 public class MetisViewerPage {
33
34
35
36 static final int ITEMS_PER_PAGE = 50;
37
38
39
40
41 private final MetisViewerEntry theEntry;
42
43
44
45
46 private final MetisViewerPage theParent;
47
48
49
50
51 private final Map<String, Object> theLinkMap;
52
53
54
55
56 private final StringBuilder theBuilder;
57
58
59
60
61 private final Object theObject;
62
63
64
65
66 private final int theSize;
67
68
69
70
71 private final int thePages;
72
73
74
75
76 private MetisViewerMode theMode;
77
78
79
80
81 private int theItemNo;
82
83
84
85
86 private int thePageNo;
87
88
89
90
91 private int theNextId;
92
93
94
95
96 private String theHtml;
97
98
99
100
101
102
103 protected MetisViewerPage(final MetisViewerEntry pEntry) {
104 this(pEntry, null, pEntry.getObject());
105 }
106
107
108
109
110
111
112
113
114 private MetisViewerPage(final MetisViewerEntry pEntry,
115 final MetisViewerPage pParent,
116 final Object pData) {
117
118 theEntry = pEntry;
119 theParent = pParent;
120 theObject = pData;
121
122
123 theLinkMap = new HashMap<>();
124 theBuilder = new StringBuilder();
125
126
127 theSize = determineSize();
128 thePages = determinePages();
129
130
131 theMode = determineInitialMode();
132 }
133
134
135
136
137
138
139 protected MetisViewerEntry getMasterEntry() {
140 return theEntry;
141 }
142
143
144
145
146
147
148 protected MetisViewerPage getParent() {
149 return theParent;
150 }
151
152
153
154
155
156
157 protected boolean hasParent() {
158 return theParent != null;
159 }
160
161
162
163
164
165
166 protected Object getObject() {
167 return theObject;
168 }
169
170
171
172
173
174
175 protected MetisViewerMode getMode() {
176 return theMode;
177 }
178
179
180
181
182
183
184 protected String getHtml() {
185 return theHtml;
186 }
187
188
189
190
191
192
193 protected void setHtml(final String pHtml) {
194 theHtml = pHtml;
195 }
196
197
198
199
200
201
202
203 protected boolean validMode(final MetisViewerMode pMode) {
204 return switch (pMode) {
205 case CONTENTS -> hasContents(theObject);
206 case SUMMARY -> isCollection(theObject);
207 case ITEMS -> isNonEmptyList(theObject);
208 default -> false;
209 };
210 }
211
212
213
214
215
216
217 protected int getItemNo() {
218 return switch (theMode) {
219 case SUMMARY -> thePageNo + 1;
220 case ITEMS -> theItemNo + 1;
221 default -> -1;
222 };
223 }
224
225
226
227
228
229
230 protected int getSize() {
231 return switch (theMode) {
232 case SUMMARY -> thePages;
233 case ITEMS -> theSize;
234 default -> -1;
235 };
236 }
237
238
239
240
241
242
243 protected boolean hasPrevious() {
244 return getItemNo() > 1;
245 }
246
247
248
249
250
251
252 protected boolean hasNext() {
253 return getItemNo() < getSize();
254 }
255
256
257
258
259 protected void previous() {
260 if (hasPrevious()) {
261 if (MetisViewerMode.ITEMS.equals(theMode)) {
262 theItemNo--;
263 } else {
264 thePageNo--;
265 }
266 }
267 }
268
269
270
271
272 protected void next() {
273 if (hasNext()) {
274 if (MetisViewerMode.ITEMS.equals(theMode)) {
275 theItemNo++;
276 } else {
277 thePageNo++;
278 }
279 }
280 }
281
282
283
284
285
286
287 protected void setPageNo(final int pPage) {
288 if ((pPage > 0)
289 && (pPage <= getSize())) {
290 if (MetisViewerMode.ITEMS.equals(theMode)) {
291 theItemNo = pPage - 1;
292 } else {
293 thePageNo = pPage - 1;
294 }
295 }
296 }
297
298
299
300
301
302
303 protected void setMode(final MetisViewerMode pMode) {
304 if (validMode(pMode)) {
305 theMode = pMode;
306 }
307 }
308
309
310
311
312 protected void resetPage() {
313 theLinkMap.clear();
314 theNextId = 0;
315 }
316
317
318
319
320
321
322
323 protected String newLink(final Object pData) {
324
325 theBuilder.setLength(0);
326 theBuilder.append("Object");
327 theBuilder.append(theNextId++);
328 final String myId = theBuilder.toString();
329
330
331 theLinkMap.put(myId, pData);
332 return myId;
333 }
334
335
336
337
338
339
340
341 protected MetisViewerPage newPage(final String pLink) {
342
343 final Object myData = theLinkMap.get(pLink);
344 return myData == null
345 ? this
346 : new MetisViewerPage(theEntry, this, myData);
347 }
348
349
350
351
352
353
354 private int determineSize() {
355
356 Object myObject = theObject instanceof MetisDataDelta myDelta
357 ? myDelta.getObject()
358 : theObject;
359
360
361 if (myObject instanceof MetisDataList<?> myList) {
362 myObject = myList.getUnderlyingList();
363 }
364 if (myObject instanceof MetisDataMap<?, ?> myMap) {
365 myObject = myMap.getUnderlyingMap();
366 }
367
368
369 if (myObject instanceof List<?> myList) {
370 return myList.size();
371 } else if (myObject instanceof Map<?, ?> myMap) {
372 return myMap.size();
373 }
374 return -1;
375 }
376
377
378
379
380
381
382 private int determinePages() {
383 return theSize == -1
384 ? -1
385 : ((theSize - 1) / ITEMS_PER_PAGE) + 1;
386 }
387
388
389
390
391
392
393 private MetisViewerMode determineInitialMode() {
394
395 if (validMode(MetisViewerMode.CONTENTS)) {
396 return MetisViewerMode.CONTENTS;
397 }
398
399
400 if (validMode(MetisViewerMode.SUMMARY)) {
401 return MetisViewerMode.SUMMARY;
402 }
403
404
405 if (theObject == null) {
406 return MetisViewerMode.NULL;
407 }
408
409
410 throw new IllegalArgumentException("Invalid object: " + theObject);
411 }
412
413
414
415
416
417
418
419 private static boolean isCollection(final Object pObject) {
420
421 final Object myObject = pObject instanceof MetisDataDelta myDelta
422 ? myDelta.getObject()
423 : pObject;
424
425
426 if (myObject instanceof MetisDataList
427 || myObject instanceof MetisDataMap) {
428 return true;
429 }
430
431
432 return myObject instanceof List
433 || myObject instanceof Map;
434 }
435
436
437
438
439
440
441
442 private static boolean isNonEmptyList(final Object pObject) {
443
444 Object myObject = pObject instanceof MetisDataDelta myDelta
445 ? myDelta.getObject()
446 : pObject;
447
448
449 if (myObject instanceof MetisDataList<?> myList) {
450 myObject = myList.getUnderlyingList();
451 }
452
453
454 return myObject instanceof List<?> myList
455 && !myList.isEmpty();
456 }
457
458
459
460
461
462
463
464 private static boolean hasContents(final Object pObject) {
465
466 if (pObject == null) {
467 return false;
468 }
469
470
471 final Object myObject = pObject instanceof MetisDataDelta myDelta
472 ? myDelta.getObject()
473 : pObject;
474
475
476 if (myObject instanceof MetisFieldItem) {
477 return true;
478 }
479
480
481 if (myObject instanceof OceanusProfile) {
482 return true;
483 }
484
485
486 return myObject instanceof Throwable
487 || myObject instanceof StackTraceElement[];
488 }
489
490
491
492
493
494
495 protected boolean hasMultiModes() {
496 return hasContents(theObject) && isCollection(theObject);
497 }
498
499
500
501
502
503
504
505 protected static boolean isLinkable(final Object pObject) {
506 return hasContents(pObject) || isCollection(pObject);
507 }
508 }