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