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.Collections;
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import javax.faces.context.FacesContext;
26
27 import org.apache.myfaces.trinidad.bean.util.StateUtils;
28 import org.apache.myfaces.trinidad.logging.TrinidadLogger;
29
30 /**
31 * Key for an entry in a FacesBean.
32 */
33 public class PropertyKey
34 {
35 /**
36 * Capability indicating this property does not support bindings.
37 */
38 static public final int CAP_NOT_BOUND = 1;
39
40 /**
41 * Capability indicating this property is transient.
42 */
43 static public final int CAP_TRANSIENT = 2;
44
45 /**
46 * Capability indicating this property describes a list. List
47 * PropertyKeys will automatically be marked as not supporting
48 * bindings.
49 */
50 static public final int CAP_LIST = 4;
51
52 /**
53 * Capability indicating this property can use the StateHolder API.
54 */
55 static public final int CAP_STATE_HOLDER = 8;
56
57 /**
58 * Create a named PropertyKey, not attached to any type.
59 */
60 static public PropertyKey createPropertyKey(String name)
61 {
62 return new PropertyKey(name);
63 }
64
65
66
67
68
69
70
71
72
73 PropertyKey(
74 String name)
75 {
76 this(name, _TYPE_DEFAULT);
77 }
78
79 PropertyKey(
80 String name,
81 Class<?> type)
82 {
83 this(name, type, null);
84 }
85
86 PropertyKey(
87 String name,
88 Class<?> type,
89 Object defaultValue)
90 {
91 this(name, type, defaultValue, _CAPS_DEFAULT, -1);
92 }
93
94
95 protected PropertyKey(
96 String name,
97 Class<?> type,
98 Object defaultValue,
99 int capabilities,
100 int index)
101 {
102 if (name == null)
103 throw new NullPointerException();
104
105 if (type == null)
106 throw new NullPointerException();
107
108 if (defaultValue != null)
109 {
110
111 Class<?> boxedType = _getBoxedType(type);
112 if (!boxedType.isAssignableFrom(defaultValue.getClass()))
113 {
114 throw new IllegalStateException(_LOG.getMessage(
115 "DEFAULT_VALUE_IS_NOT_ASSIGNED_TO_TYPE", new Object[]{defaultValue, type}));
116 }
117 }
118 else
119 {
120
121 defaultValue = _getJavaDefault(type);
122
123
124 if (defaultValue == null)
125 defaultValue = _OBJECT_NULL;
126 }
127
128 if ((capabilities & ~_CAPS_ALL) != 0)
129 throw new IllegalStateException(_LOG.getMessage(
130 "CAPABILITY_MASK_NOT_UNDERSTOOD", (capabilities & ~_CAPS_ALL)));
131
132
133 if ((capabilities & CAP_LIST) != 0)
134 capabilities = capabilities | CAP_NOT_BOUND;
135
136 _name = name;
137 _type = type;
138 _default = defaultValue;
139 _capabilities = capabilities;
140 _index = index;
141
142 _hashCode = _name.hashCode();
143 }
144
145 /**
146 * Returns the type of this property.
147 */
148 public Class<?> getType()
149 {
150 return _type;
151 }
152
153 /**
154 * Returns the default value of this property.
155 */
156 public Object getDefault()
157 {
158 return (_default != _OBJECT_NULL) ? _default : null;
159 }
160
161 /**
162 * Returns the owning type for this property key.
163 */
164 public FacesBean.Type getOwner()
165 {
166 return _owner;
167 }
168
169 /**
170 * Returns true if the property supports being bound.
171 */
172 public boolean getSupportsBinding()
173 {
174 return (_capabilities & CAP_NOT_BOUND) == 0;
175 }
176
177 /**
178 * Returns true if the property is transient.
179 */
180 public boolean isTransient()
181 {
182 return (_capabilities & CAP_TRANSIENT) != 0;
183 }
184
185 /**
186 * Returns true if the property is used to store a list.
187 */
188 public boolean isList()
189 {
190 return (_capabilities & CAP_LIST) != 0;
191 }
192
193 /**
194 * Returns the name of this property.
195 */
196 public String getName()
197 {
198 return _name;
199 }
200
201 /**
202 * Returns the index of this property.
203 */
204 public int getIndex()
205 {
206 return _index;
207 }
208
209
210 public Object saveValue(
211 FacesContext context,
212 Object value)
213 {
214 if ((_capabilities & CAP_STATE_HOLDER) != 0)
215 return StateUtils.saveStateHolder(context, value);
216
217 if (isList())
218 return StateUtils.saveList(context, value);
219
220 return value;
221 }
222
223 public Object restoreValue(
224 FacesContext context,
225 Object savedValue)
226 {
227 if ((_capabilities & CAP_STATE_HOLDER) != 0)
228 return StateUtils.restoreStateHolder(context, savedValue);
229
230 if (isList())
231 return StateUtils.restoreList(context, savedValue);
232
233 return savedValue;
234 }
235
236
237 @Override
238 public boolean equals(Object o)
239 {
240 if (o == this)
241 return true;
242
243 if (!(o instanceof PropertyKey))
244 return false;
245
246 PropertyKey that = (PropertyKey)o;
247
248
249 if (_owner != that._owner)
250 return false;
251
252
253
254 int index = this._index;
255 if (index == -1)
256 {
257 return ((that._index == -1) &&
258 (that._name.equals(_name)) &&
259 (that._type.equals(_type)) &&
260 (that._default.equals(_default)));
261 }
262
263
264
265
266 return false;
267 }
268
269 @Override
270 public int hashCode()
271 {
272 return _hashCode;
273 }
274
275 @Override
276 public String toString()
277 {
278 String className = getClass().getName();
279 int lastPeriod = className.lastIndexOf('.');
280 if (lastPeriod >= 0)
281 className = className.substring(lastPeriod + 1);
282
283 if (_index >= 0)
284 return className + "[" + _name + "," + _index + "]";
285 return className + "[" + _name + "]";
286 }
287
288 void __setOwner(FacesBean.Type owner)
289 {
290 _owner = owner;
291 }
292
293 static private Object _getJavaDefault(
294 Class<?> type)
295 {
296 return _PRIMITIVE_DEFAULTS.get(type);
297 }
298
299 static private Class<?> _getBoxedType(
300 Class<?> type)
301 {
302 Class<?> boxedType = _BOXED_PRIMITIVES.get(type);
303 return (boxedType != null ? boxedType : type);
304 }
305
306 static private Map<Class<?>, Object> _createPrimitiveDefaults()
307 {
308 Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();
309 map.put(Boolean.TYPE, Boolean.FALSE);
310 map.put(Byte.TYPE, Byte.valueOf((byte)0));
311 map.put(Character.TYPE, Character.valueOf('\0'));
312 map.put(Double.TYPE, Double.valueOf(0.0));
313 map.put(Float.TYPE, Float.valueOf(0.0f));
314 map.put(Integer.TYPE, Integer.valueOf(0));
315 map.put(Long.TYPE, Long.valueOf(0L));
316 map.put(Short.TYPE, Short.valueOf((short)0));
317
318 return Collections.unmodifiableMap(map);
319 }
320
321 static private Map<Class<?>, Class<?>> _createBoxedPrimitives()
322 {
323 Map<Class<?>, Class<?>> map = new HashMap<Class<?>, Class<?>>();
324 map.put(Boolean.TYPE, Boolean.class);
325 map.put(Byte.TYPE, Byte.class);
326 map.put(Character.TYPE, Character.class);
327 map.put(Double.TYPE, Double.class);
328 map.put(Float.TYPE, Float.class);
329 map.put(Integer.TYPE, Integer.class);
330 map.put(Long.TYPE, Long.class);
331 map.put(Short.TYPE, Short.class);
332
333 return Collections.unmodifiableMap(map);
334 }
335
336 static private final Map<Class<?>, Object> _PRIMITIVE_DEFAULTS = _createPrimitiveDefaults();
337 static private final Map<Class<?>, Class<?>> _BOXED_PRIMITIVES = _createBoxedPrimitives();
338
339 private final int _hashCode;
340 private final String _name;
341 private final int _index;
342 private final int _capabilities;
343 private final Class<?> _type;
344 private final Object _default;
345 private FacesBean.Type _owner;
346
347 static private final int _CAPS_DEFAULT =
348 0;
349
350 static private final int _CAPS_ALL =
351 CAP_NOT_BOUND |
352 CAP_TRANSIENT |
353 CAP_LIST |
354 CAP_STATE_HOLDER;
355
356 static private final Class<Object> _TYPE_DEFAULT = Object.class;
357
358 static private final Object _OBJECT_NULL = new Object();
359 private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
360 PropertyKey.class);
361 }
362