1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.internal.behavior;
21
22 import org.apache.myfaces.tobago.exception.TobagoException;
23
24 import javax.el.ValueExpression;
25 import javax.faces.component.StateHelper;
26 import javax.faces.component.StateHolder;
27 import javax.faces.component.UIComponentBase;
28 import javax.faces.context.FacesContext;
29 import java.io.Serializable;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.Map;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 class DeltaStateHelper<A extends EventBehavior> implements StateHelper {
150
151
152
153
154
155
156
157 private A target;
158
159
160
161
162 private Map<Serializable, Object> fullState;
163
164
165
166
167 private Map<Serializable, Object> deltas;
168
169
170
171
172
173
174
175 private boolean transientBoolean = false;
176
177 DeltaStateHelper(final A target) {
178 super();
179 this.target = target;
180 fullState = new HashMap<>();
181 deltas = null;
182
183 }
184
185
186
187
188
189
190 private boolean createDeltas() {
191 if (isInitialStateMarked()) {
192 if (deltas == null) {
193 deltas = new HashMap<>(2);
194 }
195 return true;
196 }
197
198 return false;
199 }
200
201 protected boolean isInitialStateMarked() {
202 return target.initialStateMarked();
203 }
204
205 @Override
206 public void add(final Serializable key, final Object value) {
207 if (createDeltas()) {
208
209 Map<Object, Boolean> deltaListMapValues = (Map<Object, Boolean>) deltas
210 .get(key);
211 if (deltaListMapValues == null) {
212 deltaListMapValues = new DeltaStateHelper.InternalDeltaListMap<>(
213 3);
214 deltas.put(key, deltaListMapValues);
215 }
216 deltaListMapValues.put(value, Boolean.TRUE);
217 }
218
219
220 List<Object> fullListValues = (List<Object>) fullState.get(key);
221 if (fullListValues == null) {
222 fullListValues = new DeltaStateHelper.InternalList<>(3);
223 fullState.put(key, fullListValues);
224 }
225 fullListValues.add(value);
226 }
227
228 @Override
229 public Object eval(final Serializable key) {
230 final Object returnValue = fullState.get(key);
231 if (returnValue != null) {
232 return returnValue;
233 }
234 final ValueExpression expression = target.getValueExpression(key
235 .toString());
236 if (expression != null) {
237 return expression.getValue(FacesContext.getCurrentInstance()
238 .getELContext());
239 }
240 return null;
241 }
242
243 @Override
244 public Object eval(final Serializable key, final Object defaultValue) {
245 final Object returnValue = fullState.get(key);
246 if (returnValue != null) {
247 return returnValue;
248 }
249 final ValueExpression expression = target.getValueExpression(key
250 .toString());
251 if (expression != null) {
252 return expression.getValue(FacesContext.getCurrentInstance()
253 .getELContext());
254 }
255 return defaultValue;
256 }
257
258 @Override
259 public Object get(final Serializable key) {
260 return fullState.get(key);
261 }
262
263 @Override
264 public Object put(final Serializable key, final Object value) {
265 Object returnValue = null;
266 if (createDeltas()) {
267 if (deltas.containsKey(key)) {
268 returnValue = deltas.put(key, value);
269 fullState.put(key, value);
270 } else if (value == null && !fullState.containsKey(key)) {
271 returnValue = null;
272 } else {
273 deltas.put(key, value);
274 returnValue = fullState.put(key, value);
275 }
276 } else {
277
278
279
280
281
282
283 returnValue = fullState.put(key, value);
284 }
285 return returnValue;
286 }
287
288 @Override
289 public Object put(final Serializable key, final String mapKey, final Object value) {
290 boolean returnSet = false;
291 Object returnValue = null;
292 if (createDeltas()) {
293
294 Map<String, Object> mapValues = (Map<String, Object>) deltas
295 .get(key);
296 if (mapValues == null) {
297 mapValues = new DeltaStateHelper.InternalMap<>();
298 deltas.put(key, mapValues);
299 }
300 if (mapValues.containsKey(mapKey)) {
301 returnValue = mapValues.put(mapKey, value);
302 returnSet = true;
303 } else {
304 mapValues.put(mapKey, value);
305 }
306 }
307
308
309 Map<String, Object> mapValues = (Map<String, Object>) fullState
310 .get(key);
311 if (mapValues == null) {
312 mapValues = new DeltaStateHelper.InternalMap<>();
313 fullState.put(key, mapValues);
314 }
315 if (returnSet) {
316 mapValues.put(mapKey, value);
317 } else {
318 returnValue = mapValues.put(mapKey, value);
319 }
320 return returnValue;
321 }
322
323 @Override
324 public Object remove(final Serializable key) {
325 Object returnValue = null;
326 if (createDeltas()) {
327 if (deltas.containsKey(key)) {
328
329 returnValue = deltas.put(key, null);
330 fullState.remove(key);
331 } else {
332
333 deltas.put(key, null);
334 returnValue = fullState.remove(key);
335 }
336 } else {
337 returnValue = fullState.remove(key);
338 }
339 return returnValue;
340 }
341
342 @Override
343 public Object remove(final Serializable key, final Object valueOrKey) {
344
345
346
347
348
349
350 final Object collectionOrMap = fullState.get(key);
351 Object returnValue = null;
352 if (collectionOrMap instanceof DeltaStateHelper.InternalMap) {
353 if (createDeltas()) {
354 returnValue = removeValueOrKeyFromMap(deltas, key,
355 valueOrKey, true);
356 removeValueOrKeyFromMap(fullState, key, valueOrKey, false);
357 } else {
358 returnValue = removeValueOrKeyFromMap(fullState, key,
359 valueOrKey, false);
360 }
361 } else if (collectionOrMap instanceof DeltaStateHelper.InternalList) {
362 if (createDeltas()) {
363 returnValue = removeValueOrKeyFromCollectionDelta(deltas,
364 key, valueOrKey);
365 removeValueOrKeyFromCollection(fullState, key, valueOrKey);
366 } else {
367 returnValue = removeValueOrKeyFromCollection(fullState, key,
368 valueOrKey);
369 }
370 }
371 return returnValue;
372 }
373
374 private static Object removeValueOrKeyFromCollectionDelta(
375 final Map<Serializable, Object> stateMap, final Serializable key,
376 final Object valueOrKey) {
377 Object returnValue = null;
378 final Map<Object, Boolean> c = (Map<Object, Boolean>) stateMap.get(key);
379 if (c != null) {
380 if (c.containsKey(valueOrKey)) {
381 returnValue = valueOrKey;
382 }
383 c.put(valueOrKey, Boolean.FALSE);
384 }
385 return returnValue;
386 }
387
388 private static Object removeValueOrKeyFromCollection(
389 final Map<Serializable, Object> stateMap, final Serializable key,
390 final Object valueOrKey) {
391 Object returnValue = null;
392 final Collection c = (Collection) stateMap.get(key);
393 if (c != null) {
394 if (c.remove(valueOrKey)) {
395 returnValue = valueOrKey;
396 }
397 if (c.isEmpty()) {
398 stateMap.remove(key);
399 }
400 }
401 return returnValue;
402 }
403
404 private static Object removeValueOrKeyFromMap(
405 final Map<Serializable, Object> stateMap, final Serializable key,
406 final Object valueOrKey, final boolean delta) {
407 if (valueOrKey == null) {
408 return null;
409 }
410
411 Object returnValue = null;
412 final Map<String, Object> map = (Map<String, Object>) stateMap.get(key);
413 if (map != null) {
414 if (delta) {
415
416 returnValue = map.put((String) valueOrKey, null);
417 } else {
418 returnValue = map.remove(valueOrKey);
419 }
420
421 if (map.isEmpty()) {
422
423 stateMap.put(key, null);
424 }
425 }
426 return returnValue;
427 }
428
429 @Override
430 public boolean isTransient() {
431 return transientBoolean;
432 }
433
434
435
436
437
438
439
440
441
442
443
444 @Override
445 public Object saveState(final FacesContext context) {
446 final Map serializableMap = (isInitialStateMarked()) ? deltas : fullState;
447
448 if (serializableMap == null || serializableMap.size() == 0) {
449 return null;
450 }
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 Map.Entry<Serializable, Object> entry;
467
468 final Object[] retArr = new Object[serializableMap.entrySet().size() * 2];
469
470
471 final Iterator<Map.Entry<Serializable, Object>> it = serializableMap.entrySet().iterator();
472 int cnt = 0;
473 while (it.hasNext()) {
474 entry = it.next();
475 retArr[cnt] = entry.getKey();
476
477 final Object value = entry.getValue();
478
479
480
481
482 if (value instanceof StateHolder || value instanceof List || !(value instanceof Serializable)) {
483 final Object savedValue = saveAttachedState(context, value);
484 retArr[cnt + 1] = savedValue;
485 } else {
486 retArr[cnt + 1] = value;
487 }
488 cnt += 2;
489 }
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524 return retArr;
525 }
526
527 @Override
528 public void restoreState(final FacesContext context, final Object state) {
529 if (state == null) {
530 return;
531 }
532
533 final Object[] serializedState = (Object[]) state;
534
535 if (!isInitialStateMarked() && !fullState.isEmpty()) {
536 fullState.clear();
537 if (deltas != null) {
538 deltas.clear();
539 }
540 }
541
542 for (int cnt = 0; cnt < serializedState.length; cnt += 2) {
543 final Serializable key = (Serializable) serializedState[cnt];
544 final Object savedValue = restoreAttachedState(context,
545 serializedState[cnt + 1]);
546
547 if (isInitialStateMarked()) {
548 if (savedValue instanceof DeltaStateHelper.InternalDeltaListMap) {
549 for (final Map.Entry<Object, Boolean> mapEntry : ((Map<Object, Boolean>) savedValue)
550 .entrySet()) {
551 final boolean addOrRemove = mapEntry.getValue();
552 if (addOrRemove) {
553
554 this.add(key, mapEntry.getKey());
555 } else {
556
557 this.remove(key, mapEntry.getKey());
558 }
559 }
560 } else if (savedValue instanceof DeltaStateHelper.InternalMap) {
561 for (final Map.Entry<String, Object> mapEntry : ((Map<String, Object>) savedValue)
562 .entrySet()) {
563 this.put(key, mapEntry.getKey(), mapEntry.getValue());
564 }
565
566
567
568
569
570
571
572
573
574
575 } else {
576 put(key, savedValue);
577 }
578 } else {
579 put(key, savedValue);
580 }
581 }
582 }
583
584 @Override
585 public void setTransient(final boolean transientValue) {
586 transientBoolean = transientValue;
587 }
588
589
590
591 static class InternalMap<K, V> extends HashMap<K, V> implements StateHolder {
592 InternalMap() {
593 super();
594 }
595
596 InternalMap(final int initialCapacity, final float loadFactor) {
597 super(initialCapacity, loadFactor);
598 }
599
600 InternalMap(final Map<? extends K, ? extends V> m) {
601 super(m);
602 }
603
604 InternalMap(final int initialSize) {
605 super(initialSize);
606 }
607
608 @Override
609 public boolean isTransient() {
610 return false;
611 }
612
613 @Override
614 public void setTransient(final boolean newTransientValue) {
615
616 }
617
618 @Override
619 public void restoreState(final FacesContext context, final Object state) {
620 final Object[] listAsMap = (Object[]) state;
621 for (int cnt = 0; cnt < listAsMap.length; cnt += 2) {
622 this.put((K) listAsMap[cnt], (V) UIComponentBase.restoreAttachedState(context, listAsMap[cnt + 1]));
623 }
624 }
625
626 @Override
627 public Object saveState(final FacesContext context) {
628 int cnt = 0;
629 final Object[] mapArr = new Object[this.size() * 2];
630 for (final Map.Entry<K, V> entry : this.entrySet()) {
631 mapArr[cnt] = entry.getKey();
632 final Object value = entry.getValue();
633
634 if (value instanceof StateHolder || value instanceof List || !(value instanceof Serializable)) {
635 mapArr[cnt + 1] = saveAttachedState(context, value);
636 } else {
637 mapArr[cnt + 1] = value;
638 }
639 cnt += 2;
640 }
641 return mapArr;
642 }
643 }
644
645
646
647
648 static class InternalDeltaListMap<K, V> extends DeltaStateHelper.InternalMap<K, V> {
649
650 InternalDeltaListMap() {
651 super();
652 }
653
654 InternalDeltaListMap(final int initialCapacity, final float loadFactor) {
655 super(initialCapacity, loadFactor);
656 }
657
658 InternalDeltaListMap(final int initialSize) {
659 super(initialSize);
660 }
661
662 InternalDeltaListMap(final Map<? extends K, ? extends V> m) {
663 super(m);
664 }
665 }
666
667 static class InternalList<T> extends ArrayList<T> implements StateHolder {
668 InternalList() {
669 super();
670 }
671
672 InternalList(final Collection<? extends T> c) {
673 super(c);
674 }
675
676 InternalList(final int initialSize) {
677 super(initialSize);
678 }
679
680 @Override
681 public boolean isTransient() {
682 return false;
683 }
684
685 @Override
686 public void setTransient(final boolean newTransientValue) {
687 }
688
689 @Override
690 public void restoreState(final FacesContext context, final Object state) {
691 final Object[] listAsArr = (Object[]) state;
692
693
694 for (final Object elem : listAsArr) {
695 add((T) restoreAttachedState(context, elem));
696 }
697 }
698
699 @Override
700 public Object saveState(final FacesContext context) {
701 final Object[] values = new Object[size()];
702 for (int i = 0; i < size(); i++) {
703 final Object value = get(i);
704
705 if (value instanceof StateHolder || value instanceof List || !(value instanceof Serializable)) {
706 values[i] = saveAttachedState(context, value);
707 } else {
708 values[i] = value;
709 }
710 }
711 return values;
712 }
713 }
714
715 private static Object saveAttachedState(final FacesContext context, final Object attachedObject) {
716 if (context == null) {
717 throw new NullPointerException("context");
718 }
719
720 if (attachedObject == null) {
721 return null;
722 }
723
724
725 if (attachedObject instanceof StateHolder) {
726 final StateHolder holder = (StateHolder) attachedObject;
727 if (holder.isTransient()) {
728 return null;
729 }
730
731 return new AttachedStateWrapper(attachedObject.getClass(), holder.saveState(context));
732 } else if (attachedObject instanceof List) {
733 final List<Object> lst = new ArrayList<>(((List<?>) attachedObject).size());
734 for (final Object item : (List<?>) attachedObject) {
735 if (item != null) {
736 lst.add(saveAttachedState(context, item));
737 }
738 }
739
740 return new AttachedListStateWrapper(lst);
741 } else if (attachedObject instanceof Serializable) {
742 return attachedObject;
743 } else {
744 return new AttachedStateWrapper(attachedObject.getClass(), null);
745 }
746 }
747
748 private static Object restoreAttachedState(final FacesContext context, final Object stateObj)
749 throws IllegalStateException {
750 if (context == null) {
751 throw new NullPointerException("context");
752 }
753 if (stateObj == null) {
754 return null;
755 }
756 if (stateObj instanceof AttachedListStateWrapper) {
757 final List<Object> lst = ((AttachedListStateWrapper) stateObj).getWrappedStateList();
758 final List<Object> restoredList = new ArrayList<>(lst.size());
759 for (final Object item : lst) {
760 restoredList.add(restoreAttachedState(context, item));
761 }
762 return restoredList;
763 } else if (stateObj instanceof AttachedStateWrapper) {
764 final Class<?> clazz = ((AttachedStateWrapper) stateObj).getClazz();
765 final Object restoredObject;
766 try {
767 restoredObject = clazz.newInstance();
768 } catch (final InstantiationException e) {
769 throw new TobagoException("Could not restore StateHolder of type " + clazz.getName()
770 + " (missing no-args constructor?)", e);
771 } catch (final IllegalAccessException e) {
772 throw new TobagoException(e);
773 }
774 if (restoredObject instanceof StateHolder) {
775 final AttachedStateWrapper wrapper = (AttachedStateWrapper) stateObj;
776 final Object wrappedState = wrapper.getWrappedStateObject();
777
778 final StateHolder holder = (StateHolder) restoredObject;
779 holder.restoreState(context, wrappedState);
780 }
781 return restoredObject;
782 } else {
783 return stateObj;
784 }
785 }
786 }