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