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.lang.reflect.Array;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Set;
28
29 import javax.faces.context.FacesContext;
30 import javax.faces.el.ValueBinding;
31
32
33
34 import org.apache.myfaces.trinidad.bean.util.FlaggedPropertyMap;
35 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
36
37
38
39
40
41 abstract public class FacesBeanImpl implements FacesBean
42 {
43 public FacesBeanImpl()
44 {
45 }
46
47
48
49
50
51 abstract public Type getType();
52
53 final public Object getProperty(PropertyKey key)
54 {
55 Object o = getLocalProperty(key);
56 if (o != null)
57 return o;
58
59
60 if (key.getSupportsBinding())
61 {
62 ValueBinding binding = getValueBinding(key);
63 if (binding != null)
64 {
65 FacesContext context = FacesContext.getCurrentInstance();
66 return binding.getValue(context);
67 }
68 }
69
70 return null;
71 }
72
73
74
75
76
77
78 final public Object getRawProperty(PropertyKey key)
79 {
80 Object local = getLocalProperty(key);
81 if (local != null)
82 return local;
83
84
85 return key.getSupportsBinding() ? getValueBinding(key) : null;
86 }
87
88
89
90
91
92
93 public void setProperty(PropertyKey key, Object value)
94 {
95 _checkNotListKey(key);
96 setPropertyImpl(key, value);
97 }
98
99 final public Object getLocalProperty(PropertyKey key)
100 {
101 _checkNotListKey(key);
102
103 return getLocalPropertyImpl(key);
104 }
105
106 final public ValueBinding getValueBinding(PropertyKey key)
107 {
108 _checkNotListKey(key);
109
110 PropertyMap map = _getBindingsMap(false);
111 if (map == null)
112 return null;
113
114 return (ValueBinding) map.get(key);
115 }
116
117 final public void setValueBinding(PropertyKey key, ValueBinding binding)
118 {
119 _checkNotListKey(key);
120
121 if (!key.getSupportsBinding())
122 {
123 throw new IllegalArgumentException(_LOG.getMessage(
124 "CANNOT_FIND_PROPERTY", key.getName()));
125 }
126
127 if (binding == null)
128 {
129 PropertyMap map = _getBindingsMap(false);
130 if (map != null)
131 map.remove(key);
132 }
133 else
134 {
135 _getBindingsMap(true).put(key, binding);
136 }
137
138 }
139
140
141 @SuppressWarnings("unchecked")
142 final public void addEntry(PropertyKey listKey, Object value)
143 {
144 _checkListKey(listKey);
145
146 List<Object> l = (List<Object>) getLocalPropertyImpl(listKey);
147 if (l == null)
148 {
149 l = _createList();
150 setPropertyImpl(listKey, l);
151 }
152
153 l.add(value);
154
155
156
157 if (_initialStateMarked)
158 setPropertyImpl(listKey, l);
159 }
160
161 @SuppressWarnings("unchecked")
162 final public void removeEntry(PropertyKey listKey, Object value)
163 {
164 _checkListKey(listKey);
165
166 List<Object> l = (List<Object>) getLocalPropertyImpl(listKey);
167 if (l != null)
168 {
169 l.remove(value);
170 }
171
172
173
174 if (_initialStateMarked && (l != null))
175 setPropertyImpl(listKey, l);
176 }
177
178 @SuppressWarnings("unchecked")
179 final public Object[] getEntries(PropertyKey listKey, Class clazz)
180 {
181 _checkListKey(listKey);
182
183 List<Object> l = (List<Object>) getLocalPropertyImpl(listKey);
184 if (l == null)
185 return (Object[]) Array.newInstance(clazz, 0);
186
187 int size = l.size();
188 ArrayList<Object> tempList = new ArrayList<Object>(size);
189 for (int i = 0; i < size; i++)
190 {
191 Object o = l.get(i);
192 if (clazz.isInstance(o))
193 tempList.add(o);
194 }
195
196 return tempList.toArray((Object[]) Array.newInstance(clazz,
197 tempList.size()));
198 }
199
200 @SuppressWarnings("unchecked")
201 final public boolean containsEntry(PropertyKey listKey, Class<?> clazz)
202 {
203 _checkListKey(listKey);
204
205 List<Object> l = (List<Object>) getLocalPropertyImpl(listKey);
206 if (l == null)
207 return false;
208
209 int size = l.size();
210 for (int i = 0; i < size; i++)
211 {
212 Object o = l.get(i);
213 if (clazz.isInstance(o))
214 return true;
215 }
216
217 return false;
218 }
219
220 @SuppressWarnings("unchecked")
221 final public Iterator<Object> entries(PropertyKey listKey)
222 {
223 _checkListKey(listKey);
224
225 List<Object> l = (List<Object>) getLocalPropertyImpl(listKey);
226 if (l == null)
227 return Collections.emptyList().iterator();
228
229 return l.iterator();
230 }
231
232
233
234 public void addAll(FacesBean from)
235 {
236 if (from == this)
237 return;
238
239 for(PropertyKey fromKey : from.keySet())
240 {
241 PropertyKey toKey = _convertKey(fromKey);
242 if ((toKey != null) &&
243 _isCompatible(fromKey, toKey))
244 {
245 if (!fromKey.isList())
246 {
247 setProperty(toKey, from.getLocalProperty(fromKey));
248 }
249 else
250 {
251 Iterator<? extends Object> entries = from.entries(fromKey);
252 while (entries.hasNext())
253 addEntry(toKey, entries.next());
254 }
255 }
256 }
257
258 for(PropertyKey fromKey : from.bindingKeySet())
259 {
260 PropertyKey toKey = _convertKey(fromKey);
261 if (toKey.getSupportsBinding())
262 {
263 setValueBinding(toKey, from.getValueBinding(fromKey));
264 }
265 }
266 }
267
268 final public Set<PropertyKey> keySet()
269 {
270 if (_properties == null)
271 return Collections.emptySet();
272
273 return _properties.keySet();
274 }
275
276 @SuppressWarnings("unchecked")
277 final public Set<PropertyKey> bindingKeySet()
278 {
279 if (_bindings == null)
280 return Collections.emptySet();
281
282 return _bindings.keySet();
283 }
284
285
286 public void markInitialState()
287 {
288 _initialStateMarked = true;
289
290 if (_properties != null)
291 _properties.markInitialState();
292
293 if (_bindings != null)
294 _bindings.markInitialState();
295 }
296
297 public void restoreState(FacesContext context, Object state)
298 {
299 if (_LOG.isFiner())
300 {
301 _LOG.finer("Restoring state into " + this);
302 }
303
304 if (state instanceof Object[])
305 {
306 Object[] asArray = (Object[]) state;
307 if (asArray.length == 2)
308 {
309 Object propertyState = asArray[0];
310 Object bindingsState = asArray[1];
311 _getPropertyMap().restoreState(context, getType(), propertyState);
312 _getBindingsMap(true).restoreState(context, getType(), bindingsState);
313 return;
314 }
315 else if (asArray.length == 1)
316 {
317 Object propertyState = asArray[0];
318 _getPropertyMap().restoreState(context, getType(), propertyState);
319 return;
320 }
321 }
322
323 _getPropertyMap().restoreState(context, getType(), state);
324 }
325
326 public Object saveState(FacesContext context)
327 {
328 if (_LOG.isFiner())
329 {
330 _LOG.finer("Saving state of " + this);
331 }
332
333
334 Object propertyState = (_properties == null)
335 ? null
336 : _properties.saveState(context);
337 Object bindingsState = (_bindings == null)
338 ? null
339 : _bindings.saveState(context);
340
341 if (bindingsState != null)
342 {
343 return new Object[]{propertyState, bindingsState};
344 }
345
346 if (propertyState == null)
347 return null;
348
349 if (propertyState instanceof Object[])
350 {
351 Object[] asArray = (Object[]) propertyState;
352 if (asArray.length <= 2)
353 return new Object[]{propertyState};
354 }
355
356 return propertyState;
357 }
358
359 @Override
360 public String toString()
361 {
362 String className = getClass().getName();
363 int lastPeriod = className.lastIndexOf('.');
364 if (lastPeriod < 0)
365 return className;
366
367 return className.substring(lastPeriod + 1);
368 }
369
370 protected void setPropertyImpl(PropertyKey key, Object value)
371 {
372 if (value == null)
373 _getPropertyMap().remove(key);
374 else
375 _getPropertyMap().put(key, value);
376 }
377
378 protected Object getLocalPropertyImpl(PropertyKey key)
379 {
380 return _getPropertyMap().get(key);
381 }
382
383 protected PropertyMap createPropertyMap()
384 {
385 return new FlaggedPropertyMap();
386 }
387
388 protected PropertyMap createBindingsMap()
389 {
390 FlaggedPropertyMap bindings = new FlaggedPropertyMap();
391 bindings.setUseStateHolder(true);
392 return bindings;
393 }
394
395
396
397
398 private List<Object> _createList(
399 {
400 return new ArrayList<Object>();
401 }
402
403
404
405
406 private PropertyKey _convertKey(PropertyKey fromKey)
407 {
408 Type type = getType();
409
410
411 PropertyKey toKey = type.findKey(fromKey.getIndex());
412 if (toKey == fromKey)
413 return toKey;
414
415
416 String name = fromKey.getName();
417 toKey = type.findKey(name);
418 if (toKey != null)
419 return toKey;
420
421
422 return new PropertyKey(name);
423 }
424
425
426
427
428 static private boolean _isCompatible(
429 PropertyKey fromKey, PropertyKey toKey)
430 {
431 return (fromKey.isList() == toKey.isList());
432 }
433
434
435 private PropertyMap _getPropertyMap()
436 {
437 if (_properties == null)
438 _properties = createPropertyMap();
439
440 return _properties;
441 }
442
443 private PropertyMap _getBindingsMap(boolean createIfNew)
444 {
445 if (_bindings == null)
446 {
447 if (createIfNew)
448 {
449 _bindings = createBindingsMap();
450 }
451 }
452
453 return _bindings;
454 }
455
456
457 static private void _checkListKey(PropertyKey listKey)
458 throws IllegalArgumentException
459 {
460 if (!listKey.isList())
461 throw new IllegalArgumentException(_LOG.getMessage(
462 ">KEY_CANNOT_BE_USED_FOR_LISTS", listKey));
463 }
464
465 static private void _checkNotListKey(PropertyKey key)
466 throws IllegalArgumentException
467 {
468 if (key.isList())
469 throw new IllegalArgumentException(_LOG.getMessage(
470 "KEY_IS_LIST_KEY", key));
471 }
472
473 private PropertyMap _properties;
474 private PropertyMap _bindings;
475 private transient boolean _initialStateMarked;
476
477 static private final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(FacesBeanImpl.class);
478 }