1 package org.apache.commons.beanutils2;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import static org.apache.commons.beanutils2.Assertions.checkNotNull;
23 import static org.apache.commons.beanutils2.BeanUtils.on;
24
25 import java.beans.PropertyDescriptor;
26 import java.lang.reflect.InvocationTargetException;
27 import java.lang.reflect.Method;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.Map.Entry;
31
32 final class DefaultBeanAccessor<B>
33 implements BeanAccessor<B>
34 {
35
36 private final B bean;
37
38 private final BeanProperties<B> properties;
39
40 public DefaultBeanAccessor( B bean )
41 {
42 this.bean = bean;
43 @SuppressWarnings( "unchecked" )
44 Class<B> beanClass = (Class<B>) bean.getClass();
45 properties = on( beanClass ).getProperties();
46 }
47
48
49
50
51
52
53 public BeanAccessor<?> get( String propertyName )
54 {
55 checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
56 Method readMethod = properties.getReadPropertyMethod( propertyName );
57
58 Object newBean;
59 try
60 {
61 newBean = readMethod.invoke( bean );
62 }
63 catch ( IllegalAccessException e )
64 {
65 throw new PropertyGetterNotAccessibleException( propertyName, readMethod.getName(), bean.getClass(), e );
66 }
67 catch ( InvocationTargetException e )
68 {
69 throw new PropertyGetterInvocationException( propertyName, readMethod.getName(), bean.getClass(), e );
70 }
71 return new DefaultBeanAccessor<Object>( newBean );
72 }
73
74
75
76
77 public IndexedPropertyGetterAccessor<B> getIndexed( String propertyName )
78 {
79 checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
80 Method indexedReadMethod;
81 indexedReadMethod = properties.getIndexedReadMethod( propertyName );
82 return new DefaultIndexedPropertyGetterAccessor<B>( bean, propertyName, indexedReadMethod );
83 }
84
85
86
87
88 public MappedPropertyGetterAccessor getMapped( String propertyName )
89 {
90 checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
91 Method mappedReadMethod;
92 mappedReadMethod = properties.getMappedReadMethod( propertyName );
93 return new DefaultMappedPropertyGetterAccessor<B>( bean, propertyName, mappedReadMethod );
94 }
95
96
97
98
99 public B get()
100 {
101 return bean;
102 }
103
104
105
106
107 public <V> V cast()
108 {
109 @SuppressWarnings( "unchecked" )
110 V returned = (V) bean;
111 return returned;
112 }
113
114
115
116
117
118
119 public BeanPropertySetter<B> set( String propertyName )
120 {
121 checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
122 Method writeMethod;
123 writeMethod = properties.getWriteMethod( propertyName );
124 return new DefaultBeanPropertySetter<B>( bean, writeMethod, propertyName );
125 }
126
127
128
129
130 public IndexedPropertySetterAccessor<B> setIndexed( String propertyName )
131 {
132 checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
133 Method indexedWriteMethod;
134 indexedWriteMethod = properties.getIndexedWriteMethod( propertyName );
135 return new DefaultIndexedPropertySetterAccessor<B>( bean, propertyName, indexedWriteMethod );
136 }
137
138
139
140
141 public MappedPropertySetterAccessor<B> setMapped( String propertyName )
142 {
143 checkNotNull( propertyName, "Parameter 'propertyName' must not be null!" );
144 Method mappedWriteMethod;
145 mappedWriteMethod = properties.getMappedWriteMethod( propertyName );
146 return new DefaultMappedPropertySetterAccessor<B>( bean, propertyName, mappedWriteMethod );
147 }
148
149
150
151
152 public B cloneBean()
153 {
154 BeanAccessor<B> cloneAccessor = on( getBeanClass() ).newInstance();
155 cloneAccessor.populate( describe() );
156 return cloneAccessor.get();
157 }
158
159 private Class<B> getBeanClass()
160 {
161 @SuppressWarnings( "unchecked" )
162 Class<B> beanType = (Class<B>) bean.getClass();
163 return beanType;
164 }
165
166
167
168
169 public <T extends B> void copyPropertiesTo( T target )
170 {
171 checkNotNull( target, "Can not copy properties to null!" );
172 on( target ).populate( describe() );
173 }
174
175
176
177
178 public Map<String, Object> describe()
179 {
180 Map<String, PropertyDescriptor> propertiesIndex;
181 propertiesIndex = properties.getPropertiesIndex();
182 final Map<String, Object> result = new HashMap<String, Object>( propertiesIndex.size() );
183
184 for ( Entry<String, PropertyDescriptor> key : propertiesIndex.entrySet() )
185 {
186 PropertyDescriptor propertyDescriptor = key.getValue();
187 if ( propertyDescriptor.getReadMethod() != null )
188 {
189 Object value = invoke( propertyDescriptor );
190 result.put( key.getKey(), value );
191 }
192 }
193
194 return result;
195 }
196
197 private Object invoke( PropertyDescriptor propertyDescriptor )
198 {
199 Method readMethod = propertyDescriptor.getReadMethod();
200 Object value;
201 try
202 {
203 value = readMethod.invoke( bean );
204 }
205 catch ( IllegalAccessException e )
206 {
207 throw new PropertyGetterNotAccessibleException( propertyDescriptor.getName(), readMethod.getName(),
208 getBeanClass(), e );
209 }
210 catch ( InvocationTargetException e )
211 {
212 throw new PropertyGetterInvocationException( propertyDescriptor.getName(), readMethod.getName(),
213 getBeanClass(), e );
214 }
215 return value;
216 }
217
218
219
220
221 public void populate( Map<String, Object> properties )
222 {
223 for ( Entry<String, Object> entry : properties.entrySet() )
224 {
225 if ( entry.getKey() != null )
226 {
227 setIfWritable( entry.getKey(), entry.getValue() );
228 }
229 }
230 }
231
232 private void setIfWritable( String propertyName, Object propertyValue )
233 {
234 if ( properties.hasProperty( propertyName ) && properties.isWritable( propertyName ) )
235 {
236 set( propertyName ).with( propertyValue );
237 }
238 }
239
240
241
242
243 public ArgumentsAccessor invoke( String methodName )
244 {
245 Class<B> beanClass = getBeanClass();
246 checkNotNull( methodName, "Impossible to execute null method in %s", beanClass.getName() );
247 return new DefaultArgumentsAccessor( beanClass, false, methodName, bean );
248 }
249
250
251
252
253 public ArgumentsAccessor invokeExact( String methodName )
254 {
255 Class<B> beanClass = getBeanClass();
256 checkNotNull( methodName, "Impossible to execute null method in %s", beanClass.getName() );
257 return new DefaultArgumentsAccessor( beanClass, true, methodName, bean );
258 }
259
260 }