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.util;
20
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Set;
24
25 import javax.el.ValueExpression;
26
27 import javax.faces.component.PartialStateHolder;
28 import javax.faces.context.FacesContext;
29
30 import org.apache.myfaces.trinidad.bean.FacesBean;
31 import org.apache.myfaces.trinidad.bean.PropertyKey;
32 import org.apache.myfaces.trinidad.bean.PropertyMap;
33
34
35 public class PropertyHashMap extends HashMap<PropertyKey,Object>
36 implements PropertyMap
37 {
38 public PropertyHashMap(
39 PropertyMap map)
40 {
41 super(map);
42 }
43
44 public PropertyHashMap(
45 int initialCapacity,
46 float loadFactor)
47 {
48 super(initialCapacity, loadFactor);
49 }
50
51 public PropertyHashMap(
52 int initialCapacity)
53 {
54 super(initialCapacity);
55 }
56
57 public PropertyHashMap()
58 {
59 super();
60 }
61
62 @Override
63 public Object put(
64 PropertyKey key,
65 Object value)
66 {
67 Object retValue = super.put(key, value);
68 if (_createDeltas())
69 {
70
71 if ( key.getMutable().isAtLeastSometimesMutable() || !_equals(value, retValue))
72 _deltas.put(key, value);
73 }
74 else if (key.getMutable().isAtLeastSometimesMutable() && !(value instanceof ValueExpression))
75 {
76 _getMutableTracker(true).addProperty(key);
77 }
78
79 if (key.isPartialStateHolder())
80 {
81 _getPartialStateHolderTracker(true).addProperty(key);
82 }
83
84 return retValue;
85 }
86
87 @Override
88 public Object remove(
89 Object key)
90 {
91 boolean useDeltas = _createDeltas();
92
93 if (useDeltas)
94 {
95 if (!super.containsKey(key))
96 return null;
97
98
99 assert(key instanceof PropertyKey);
100 _deltas.put((PropertyKey) key, null);
101 }
102
103 if (key instanceof PropertyKey)
104 {
105 PropertyKey propKey = (PropertyKey)key;
106 if (propKey.isPartialStateHolder())
107 {
108 _getPartialStateHolderTracker(true).removeProperty(propKey);
109 }
110
111 if (!useDeltas && propKey.getMutable().isAtLeastSometimesMutable())
112 {
113 PropertyTracker mutableTracker = _getMutableTracker(false);
114
115 if (mutableTracker != null)
116 mutableTracker.removeProperty(propKey);
117 }
118 }
119
120 return super.remove(key);
121 }
122
123 @Override
124 public void putAll(Map<? extends PropertyKey, ? extends Object> t)
125 {
126 boolean useDeltas =_createDeltas();
127
128 if (useDeltas)
129 _deltas.putAll(t);
130
131 Set<? extends PropertyKey> keys = t.keySet();
132 for (PropertyKey key: keys)
133 {
134 if (key.isPartialStateHolder())
135 {
136 _getPartialStateHolderTracker(true).addProperty(key);
137 }
138
139 if (!useDeltas && key.getMutable().isAtLeastSometimesMutable())
140 {
141 Object value = t.get(key);
142
143 if (!(value instanceof ValueExpression))
144 {
145 _getMutableTracker(true).addProperty(key);
146 }
147 }
148
149 }
150
151 super.putAll(t);
152 }
153
154 public Object saveState(FacesContext context)
155 {
156 if (_initialStateMarked)
157 {
158 if (_deltas == null)
159 {
160
161
162 _deltas = _createDeltaPropertyMap(false);
163 }
164
165 if (_deltas == null)
166 return null;
167
168 return StateUtils.saveState(_deltas, context, getUseStateHolder());
169 }
170 else
171 {
172 return StateUtils.saveState(this, context, getUseStateHolder());
173 }
174 }
175
176 public void restoreState(
177 FacesContext context,
178 FacesBean.Type type,
179 Object state)
180 {
181 StateUtils.restoreState(this, context, type, state, getUseStateHolder());
182 }
183
184 protected PropertyMap createDeltaPropertyMap()
185 {
186 return _createDeltaPropertyMap(true);
187 }
188
189
190
191
192
193
194 private PropertyMap _createDeltaPropertyMap(boolean createAlways)
195 {
196 PropertyTracker tracker = _getMutableTracker(false);
197 PropertyTracker partialTracker = _getPartialStateHolderTracker(false);
198
199
200
201 if (createAlways || tracker != null || partialTracker != null)
202 {
203 PropertyHashMap map = new PropertyHashMap(2);
204 map.setUseStateHolder(getUseStateHolder());
205 map.setType(_type);
206
207 if (tracker != null)
208 {
209 for (PropertyKey key: tracker)
210 {
211 Object val = get(key);
212
213 if (val != null)
214 {
215 map.put(key, val);
216 }
217 }
218
219 _mutableTracker = null;
220 }
221
222
223 if (partialTracker != null)
224 {
225 for (PropertyKey key: partialTracker)
226 {
227
228 if(!map.containsKey(key))
229 {
230 Object val = get(key);
231
232 if (val != null)
233 {
234 map.put(key, val);
235 }
236 }
237 }
238 }
239
240 return map;
241 }
242
243 return null;
244 }
245
246 public boolean getUseStateHolder()
247 {
248 return _useStateHolder;
249 }
250
251 public void setUseStateHolder(boolean useStateHolder)
252 {
253 _useStateHolder = useStateHolder;
254 }
255
256
257
258 public void markInitialState()
259 {
260 _initialStateMarked = true;
261
262
263
264
265 PropertyTracker tracker = _getPartialStateHolderTracker(false);
266 if (tracker != null)
267 {
268 for (PropertyKey key: tracker)
269 {
270 Object val = get(key);
271 if (val != null)
272 {
273 ((PartialStateHolder)val).markInitialState();
274 }
275 }
276 }
277 }
278
279 public void clearInitialState()
280 {
281 _initialStateMarked = false;
282 _deltas = null;
283
284
285
286
287 PropertyTracker tracker = _getPartialStateHolderTracker(false);
288 if (tracker != null)
289 {
290 for (PropertyKey key: tracker)
291 {
292 Object val = get(key);
293 if (val != null)
294 {
295 ((PartialStateHolder)val).clearInitialState();
296 }
297 }
298 }
299 }
300
301 public boolean initialStateMarked()
302 {
303 return _initialStateMarked;
304 }
305
306
307
308
309
310 public void setType(FacesBean.Type type)
311 {
312 _type = type;
313 }
314
315 private boolean _createDeltas()
316 {
317 if (_initialStateMarked)
318 {
319 if (_deltas == null)
320 {
321 _deltas = createDeltaPropertyMap();
322 }
323
324 return true;
325 }
326
327 return false;
328 }
329
330 static private boolean _equals(Object a, Object b)
331 {
332 if (a == b)
333 return true;
334
335 if (a == null)
336 return false;
337
338 return a.equals(b);
339 }
340
341 private PropertyTracker _getPartialStateHolderTracker(boolean create)
342 {
343 if (_tracker == null && create)
344 {
345 if (_type == null)
346 {
347 throw new IllegalStateException("FacesBean.TYPE is required to track properties");
348 }
349 _tracker = new PropertyTracker(_type);
350 }
351 return _tracker;
352 }
353
354
355 private PropertyTracker _getMutableTracker(boolean create)
356 {
357 if (_mutableTracker == null && create)
358 {
359 if (_type == null)
360 {
361 throw new IllegalStateException("FacesBean.TYPE is required to track properties");
362 }
363 _mutableTracker = new PropertyTracker(_type);
364 }
365 return _mutableTracker;
366 }
367
368 private transient boolean _initialStateMarked;
369 private transient PropertyMap _deltas;
370 private boolean _useStateHolder;
371 private transient FacesBean.Type _type;
372 private transient PropertyTracker _tracker;
373 private transient PropertyTracker _mutableTracker;
374
375 private static final long serialVersionUID = 1L;
376
377 }