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