1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.context;
20
21 import java.util.ArrayDeque;
22 import java.util.Collections;
23 import java.util.Deque;
24 import java.util.Iterator;
25 import java.util.Queue;
26
27 import javax.faces.context.FacesContext;
28
29 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
30
31
32
33
34
35
36 final class ComponentContextManagerImpl
37 extends ComponentContextManager
38 {
39 public void pushChange(ComponentContextChange change)
40 {
41 if (_stack == null)
42 {
43 _stack = Collections.asLifoQueue(new ArrayDeque<ComponentContextChange>());
44 }
45
46 _stack.offer(change);
47
48 if (_LOG.isFine())
49 {
50 _LOG.fine("Component context change pushed onto the stack. Change: {0}. New stack size: {1}",
51 new Object[] { change, _stack.size() });
52 }
53 }
54
55 public ComponentContextChange popChange()
56 throws IllegalStateException
57 {
58 if (_stack == null)
59 {
60 throw new IllegalStateException("No changes to pop");
61 }
62
63 ComponentContextChange change = _stack.poll();
64
65 if (_LOG.isFine())
66 {
67 _LOG.fine("Component context change popped from the stack. Popped change: {0}. " +
68 "New head of stack: {1}. New stack size: {2}",
69 new Object[] { change, _stack.peek(), _stack.size() });
70 }
71
72 if (_stack.isEmpty())
73 {
74 _stack = null;
75 }
76
77 return change;
78 }
79
80 public ComponentContextChange peekChange()
81 {
82 return _stack == null ? null : _stack.peek();
83 }
84
85 public SuspendedContextChanges suspend(FacesContext facesContext)
86 {
87 if (_stack == null)
88 {
89 _LOG.fine("Stack with no changes has been suspended");
90 return new SuspendedContextChangesImpl(new ArrayDeque<ComponentContextChange>(0));
91 }
92
93 ArrayDeque<ComponentContextChange> q = new ArrayDeque<ComponentContextChange>(_stack.size());
94 for (ComponentContextChange change : _stack)
95 {
96 change.suspend(facesContext);
97 q.offer(change);
98 }
99
100 _stack = null;
101
102 if (_LOG.isFine())
103 {
104 _LOG.fine("Component change stack has been suspended. Number of suspended changes: {0}",
105 new Object[] { q.size() });
106 }
107
108 return new SuspendedContextChangesImpl(q);
109 }
110
111 public SuspendedContextChanges partialSuspend(
112 FacesContext facesContext,
113 SuspendCallback callback)
114 {
115 if (_stack == null)
116 {
117 _LOG.fine("Stack with no changes has been partially suspended");
118 return new SuspendedContextChangesImpl(new ArrayDeque<ComponentContextChange>(0));
119 }
120
121 ArrayDeque<ComponentContextChange> q = new ArrayDeque<ComponentContextChange>(_stack.size());
122 for (Iterator<ComponentContextChange> iter = _stack.iterator();
123 iter.hasNext(); )
124 {
125 ComponentContextChange change = iter.next();
126 SuspendCallback.SuspendResult result = callback.getSuspendResult(change);
127
128 if (result == SuspendCallback.SuspendResult.STOP)
129 {
130 break;
131 }
132
133 iter.remove();
134 change.suspend(facesContext);
135 q.offer(change);
136
137 if (result == SuspendCallback.SuspendResult.STOP_AFTER_CURRENT)
138 {
139 break;
140 }
141 }
142
143 if (_LOG.isFine())
144 {
145 _LOG.fine("Component change stack has been partially suspended. " +
146 "Number of suspended changes: {0}. New stack size: {1}",
147 new Object[] { q.size(), _stack.size() });
148 }
149
150 if (_stack.isEmpty())
151 {
152 _stack = null;
153 }
154
155 return new SuspendedContextChangesImpl(q);
156 }
157
158 public Iterator<ComponentContextChange> resume(
159 FacesContext facesContext,
160 SuspendedContextChanges suspendedChanges)
161 {
162 assert suspendedChanges instanceof SuspendedContextChangesImpl :
163 "Invalid suspend changes";
164
165 SuspendedContextChangesImpl suspendedChangesImpl =
166 (SuspendedContextChangesImpl)suspendedChanges;
167
168 if (_stack == null)
169 {
170 _stack = Collections.asLifoQueue(new ArrayDeque<ComponentContextChange>());
171 }
172
173 for (Iterator<ComponentContextChange> iter =
174 suspendedChangesImpl._suspendedStack.descendingIterator();
175 iter.hasNext(); )
176 {
177 ComponentContextChange change = iter.next();
178 change.resume(facesContext);
179 _stack.offer(change);
180 }
181
182 if (_LOG.isFine())
183 {
184 _LOG.fine("Component change stack has been resumed. " +
185 "Number of resumed changes: {0}. New stack size: {1}",
186 new Object[] { suspendedChangesImpl._suspendedStack.size(), _stack.size() });
187 }
188
189 return suspendedChangesImpl._suspendedStack.descendingIterator();
190 }
191
192 private static class SuspendedContextChangesImpl
193 extends SuspendedContextChanges
194 {
195 SuspendedContextChangesImpl(
196 Deque<ComponentContextChange> suspendedStack)
197 {
198 _suspendedStack = suspendedStack;
199 }
200
201 private Deque<ComponentContextChange> _suspendedStack;
202 }
203
204 private Queue<ComponentContextChange> _stack;
205
206 private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
207 ComponentContextManagerImpl.class);
208 }