View Javadoc
1   package org.apache.commons.beanutils2;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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" ) // we can be sure, that bean is of Class<B>
44          Class<B> beanClass = (Class<B>) bean.getClass();
45          properties = on( beanClass ).getProperties();
46      }
47  
48      // get
49  
50      /**
51       * {@inheritDoc}
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       * {@inheritDoc}
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       * {@inheritDoc}
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       * {@inheritDoc}
98       */
99      public B get()
100     {
101         return bean;
102     }
103 
104     /**
105      * {@inheritDoc}
106      */
107     public <V> V cast()
108     {
109         @SuppressWarnings( "unchecked" )
110         V returned = (V) bean;
111         return returned;
112     }
113 
114     // set
115 
116     /**
117      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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" ) // we can be sure, that bean is of Class<B>
162         Class<B> beanType = (Class<B>) bean.getClass();
163         return beanType;
164     }
165 
166     /**
167      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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      * {@inheritDoc}
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 }