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