1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.trinidad.bean;
20
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.ArrayList;
25
26 import java.util.Collection;
27 import java.util.Collections;
28
29 import javax.faces.component.PartialStateHolder;
30
31 import javax.faces.component.StateHolder;
32 import javax.faces.context.FacesContext;
33
34 import org.apache.myfaces.trinidad.bean.util.StateUtils;
35
36
37
38
39 public class AttachedObjects<K, T> implements PartialStateHolder
40 {
41
42
43
44
45
46 final public void addAttachedObject(K key, T obj)
47 {
48 List<T> objects = _objectMap.get(key);
49 if (objects == null)
50 {
51 objects = new ArrayList<T>(5);
52 _objectMap.put(key, objects);
53 }
54
55 objects.add(obj);
56
57 if (initialStateMarked())
58 {
59
60 clearInitialState();
61 }
62 }
63
64
65
66
67
68
69 final public boolean removeAttachedObject(K key, T obj)
70 {
71 List<T> objects = _objectMap.get(key);
72 if (objects == null)
73 {
74 return false;
75 }
76
77 boolean removed = objects.remove(obj);
78 if (removed)
79 {
80 if (initialStateMarked())
81 {
82
83 clearInitialState();
84 }
85 }
86 return removed;
87 }
88
89
90
91
92
93
94 final public List<T> getAttachedObjectList(K key)
95 {
96 List<T> objects = _objectMap.get(key);
97 if (objects == null)
98 {
99 return Collections.emptyList();
100 }
101 return Collections.unmodifiableList(objects);
102 }
103
104
105
106
107
108 final public Map<K, List<T>> getAttachedObjectMap()
109 {
110 if (_readOnlyObjectMap == null)
111 {
112 _readOnlyObjectMap = Collections.unmodifiableMap(_objectMap);
113 }
114 return _readOnlyObjectMap;
115 }
116
117 @Override
118 public void markInitialState()
119 {
120 for (Map.Entry<K, List<T>> e : _objectMap.entrySet())
121 {
122 for (T obj : e.getValue())
123 {
124 if (obj instanceof PartialStateHolder)
125 {
126 ((PartialStateHolder)obj).markInitialState();
127 }
128 }
129 }
130 _initialStateMarked = true;
131 }
132
133 @Override
134 public void clearInitialState()
135 {
136 _initialStateMarked = false;
137 for (Map.Entry<K, List<T>> e : _objectMap.entrySet())
138 {
139 for (T obj : e.getValue())
140 {
141 if (obj instanceof PartialStateHolder)
142 {
143 ((PartialStateHolder)obj).clearInitialState();
144 }
145 }
146 }
147 }
148
149 @Override
150 public boolean initialStateMarked()
151 {
152 return _initialStateMarked;
153 }
154
155 @Override
156 public Object saveState(
157 FacesContext facesContext)
158 {
159 Map<K, Object[]> state = new HashMap<K, Object[]>(_objectMap.size());
160 for (Map.Entry<K, List<T>> e : _objectMap.entrySet())
161 {
162 List<T> l = e.getValue();
163 Object[] entryState = new Object[l.size()];
164 boolean stateWasSaved = false;
165 for (int i = 0, size = entryState.length; i < size; ++i)
166 {
167 T obj = l.get(i);
168 if (_initialStateMarked)
169 {
170
171
172
173 if (obj instanceof StateHolder)
174 {
175 entryState[i] = ((StateHolder)obj).saveState(facesContext);
176 }
177 }
178 else
179 {
180
181 entryState[i] = StateUtils.saveStateHolder(facesContext, obj);
182 }
183
184 stateWasSaved = (entryState[i] != null) ? true : stateWasSaved;
185 }
186
187 if (stateWasSaved)
188 {
189 state.put(e.getKey(), entryState);
190 }
191 }
192
193 Object [] savedState = null;
194 if (!state.isEmpty())
195 {
196
197
198
199
200
201 savedState = new Object[2];
202 savedState[0] = _initialStateMarked;
203 savedState[1] = state;
204 }
205 return savedState;
206 }
207
208 @Override
209 public void restoreState(
210 FacesContext facesContext,
211 Object state)
212 {
213 if (state == null)
214 return;
215
216 Object stateArray[] = (Object [])state;
217 boolean usePartialStateSaving = (Boolean)stateArray[0];
218
219 @SuppressWarnings("unchecked")
220 Map<K, Object[]> savedState = (Map<K, Object[]>) stateArray[1];
221
222 if (usePartialStateSaving)
223 {
224
225
226
227
228 for (Map.Entry<K, Object[]> e : savedState.entrySet())
229 {
230
231
232 List<T> l = _objectMap.get(e.getKey());
233 Object[] entryState = e.getValue();
234 for (int i = 0, size = entryState.length; i < size; ++i)
235 {
236 if (entryState[i] != null)
237 {
238 T obj = l.get(i);
239 if (obj instanceof StateHolder)
240 {
241 ((StateHolder)obj).restoreState(facesContext, entryState[i]);
242 }
243 }
244 }
245 }
246 }
247 else
248 {
249
250
251 _objectMap.clear();
252
253 for (Map.Entry<K, Object[]> e : savedState.entrySet())
254 {
255 Object[] entryState = e.getValue();
256
257
258 List<T> list = new ArrayList<T>(entryState.length);
259 for (int i = 0, size = entryState.length; i < size; ++i)
260 {
261 list.add((T)StateUtils.restoreStateHolder(facesContext, entryState[i]));
262 }
263
264 _objectMap.put(e.getKey(), list);
265 }
266 }
267 }
268
269 public boolean isTransient()
270 {
271 return _transient;
272 }
273
274 public void setTransient(
275 boolean newTransientValue)
276 {
277 _transient = newTransientValue;
278 }
279
280
281
282 private Map<K, List<T>> _objectMap = new HashMap<K, List<T>>(5, 1.0f);
283
284 private Map<K, List<T>> _readOnlyObjectMap = null;
285
286 private boolean _initialStateMarked = false;
287 private boolean _transient = false;
288 }