Source code: javax/faces/component/_ComponentAttributesMap.java
1 /*
2 * Copyright 2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package javax.faces.component;
17
18 import java.beans.BeanInfo;
19 import java.beans.IntrospectionException;
20 import java.beans.Introspector;
21 import java.beans.PropertyDescriptor;
22 import java.io.Serializable;
23 import java.lang.reflect.Method;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.Map;
28 import java.util.Set;
29
30 import javax.faces.FacesException;
31 import javax.faces.context.FacesContext;
32 import javax.faces.el.ValueBinding;
33
34 /**
35 * @author Manfred Geiler (latest modification by $Author: mmarinschek $)
36 * @version $Revision: 265007 $ $Date: 2005-08-31 06:36:40 -0400 (Wed, 31 Aug 2005) $
37 */
38 class _ComponentAttributesMap
39 implements Map, Serializable
40 {
41 private static final long serialVersionUID = -9106832179394257866L;
42
43 private static final Object[] EMPTY_ARGS = new Object[0];
44
45 private UIComponent _component;
46 private Map _attributes = null; //We delegate instead of derive from HashMap, so that we can later optimize Serialization
47 private transient Map _propertyDescriptorMap = null;
48
49 _ComponentAttributesMap(UIComponent component)
50 {
51 _component = component;
52 _attributes = new HashMap();
53 }
54
55 _ComponentAttributesMap(UIComponent component, Map attributes)
56 {
57 _component = component;
58 _attributes = attributes;
59 }
60
61 public int size()
62 {
63 return _attributes.size();
64 }
65
66 public void clear()
67 {
68 _attributes.clear();
69 }
70
71 public boolean isEmpty()
72 {
73 return _attributes.isEmpty();
74 }
75
76 public boolean containsKey(Object key)
77 {
78 checkKey(key);
79 if (getPropertyDescriptor((String)key) == null)
80 {
81 return _attributes.containsKey(key);
82 }
83 else
84 {
85 return false;
86 }
87 }
88
89 /**
90 * @param value null is allowed
91 */
92 public boolean containsValue(Object value)
93 {
94 return _attributes.containsValue(value);
95 }
96
97 public Collection values()
98 {
99 return _attributes.values();
100 }
101
102 public void putAll(Map t)
103 {
104 for (Iterator it = t.entrySet().iterator(); it.hasNext(); )
105 {
106 Map.Entry entry = (Entry)it.next();
107 put(entry.getKey(), entry.getValue());
108 }
109 }
110
111 public Set entrySet()
112 {
113 return _attributes.entrySet();
114 }
115
116 public Set keySet()
117 {
118 return _attributes.keySet();
119 }
120
121 public Object get(Object key)
122 {
123 checkKey(key);
124 PropertyDescriptor propertyDescriptor
125 = getPropertyDescriptor((String)key);
126 if (propertyDescriptor != null)
127 {
128 return getComponentProperty(propertyDescriptor);
129 }
130 Object mapValue = _attributes.get(key);
131 if (mapValue != null)
132 {
133 return mapValue;
134 }
135 ValueBinding vb = _component.getValueBinding((String) key);
136 if (vb != null)
137 {
138 return vb.getValue(FacesContext.getCurrentInstance());
139 }
140 return null;
141 }
142
143 public Object remove(Object key)
144 {
145 checkKey(key);
146 PropertyDescriptor propertyDescriptor = getPropertyDescriptor((String)key);
147 if (propertyDescriptor != null)
148 {
149 throw new IllegalArgumentException("Cannot remove component property attribute");
150 }
151 return _attributes.remove(key);
152 }
153
154 /**
155 * @param key String, null is not allowed
156 * @param value null is allowed
157 */
158 public Object put(Object key, Object value)
159 {
160 checkKeyAndValue(key, value);
161 PropertyDescriptor propertyDescriptor = getPropertyDescriptor((String)key);
162 if (propertyDescriptor != null)
163 {
164 if (propertyDescriptor.getReadMethod() != null)
165 {
166 Object oldValue = getComponentProperty(propertyDescriptor);
167 setComponentProperty(propertyDescriptor, value);
168 return oldValue;
169 }
170 else
171 {
172 setComponentProperty(propertyDescriptor, value);
173 return null;
174 }
175 }
176 else
177 {
178 return _attributes.put(key, value);
179 }
180 }
181
182
183 private PropertyDescriptor getPropertyDescriptor(String key)
184 {
185 if (_propertyDescriptorMap == null)
186 {
187 BeanInfo beanInfo;
188 try
189 {
190 beanInfo = Introspector.getBeanInfo(_component.getClass());
191 }
192 catch (IntrospectionException e)
193 {
194 throw new FacesException(e);
195 }
196 PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
197 _propertyDescriptorMap = new HashMap();
198 for (int i = 0; i < propertyDescriptors.length; i++)
199 {
200 PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
201 if (propertyDescriptor.getReadMethod() != null)
202 {
203 _propertyDescriptorMap.put(propertyDescriptor.getName(),
204 propertyDescriptor);
205 }
206 }
207 }
208 return (PropertyDescriptor)_propertyDescriptorMap.get(key);
209 }
210
211
212 private Object getComponentProperty(PropertyDescriptor propertyDescriptor)
213 {
214 Method readMethod = propertyDescriptor.getReadMethod();
215 if (readMethod == null)
216 {
217 throw new IllegalArgumentException("Component property " + propertyDescriptor.getName() + " is not readable");
218 }
219 try
220 {
221 return readMethod.invoke(_component, EMPTY_ARGS);
222 }
223 catch (Exception e)
224 {
225 FacesContext facesContext = FacesContext.getCurrentInstance();
226 throw new FacesException("Could not get property " + propertyDescriptor.getName() + " of component " + _component.getClientId(facesContext), e);
227 }
228 }
229
230
231 private void setComponentProperty(PropertyDescriptor propertyDescriptor, Object value)
232 {
233 Method writeMethod = propertyDescriptor.getWriteMethod();
234 if (writeMethod == null)
235 {
236 throw new IllegalArgumentException("Component property " + propertyDescriptor.getName() + " is not writable");
237 }
238 try
239 {
240 writeMethod.invoke(_component, new Object[] {value});
241 }
242 catch (Exception e)
243 {
244 FacesContext facesContext = FacesContext.getCurrentInstance();
245 throw new FacesException("Could not set property " + propertyDescriptor.getName() + " of component " + _component.getClientId(facesContext), e);
246 }
247 }
248
249
250 private void checkKeyAndValue(Object key, Object value)
251 {
252 if (value == null) throw new NullPointerException("value");
253 checkKey(key);
254 }
255
256 private void checkKey(Object key)
257 {
258 if (key == null) throw new NullPointerException("key");
259 if (!(key instanceof String)) throw new ClassCastException("key is not a String");
260 }
261
262 Map getUnderlyingMap()
263 {
264 return _attributes;
265 }
266
267 public boolean equals(Object obj)
268 {
269 return _attributes.equals(obj);
270 }
271
272 public int hashCode()
273 {
274 return _attributes.hashCode();
275 }
276 }