View Javadoc

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 org.apache.commons.betwixt.expression;
17  
18  import java.lang.reflect.Array;
19  import java.util.Collection;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  /***
25   * Abstracts common features for strongly typed <code>Updater</code>'s.
26   * Strongly type <code>Updater</code>'s perform conversions based on this
27   * the expected type before the bean update is invoked.
28   * @since 0.7
29   * @author <a href='http://jakarta.apache.org/commons'>Jakarta Commons Team</a>, <a href='http://www.apache.org'>Apache Software Foundation</a>
30   */
31  public abstract class TypedUpdater implements Updater {
32  
33      /*** Logger */
34      private static final Log log = LogFactory.getLog( TypedUpdater.class );
35  
36      
37      /*** The type of the first parameter of the method */
38      private Class valueType;
39  
40      /*** 
41       * Updates the current bean context with the given String value 
42       * @param context the Context to be updated
43       * @param newValue the update to this new value 
44       */
45      public void update(Context context, Object newValue) {
46              Object bean = context.getBean();
47              if ( bean != null ) {
48                  if ( newValue instanceof String ) {
49                      // try to convert into primitive types
50                      if ( log.isTraceEnabled() ) {
51                          log.trace("Converting primitive to " + valueType);
52                      }
53                      newValue = context.getObjectStringConverter()
54                          .stringToObject( (String) newValue, valueType, context );
55                  }
56                  if ( newValue != null ) {
57                      // check that it is of the correct type
58      /*                
59                      if ( ! valueType.isAssignableFrom( newValue.getClass() ) ) {
60                          log.warn( 
61                              "Cannot call setter method: " + method.getName() + " on bean: " + bean
62                              + " with type: " + bean.getClass().getName() 
63                              + " as parameter should be of type: " + valueType.getName() 
64                              + " but is: " + newValue.getClass().getName() 
65                          );
66                          return;
67                      }
68      */                
69                  }
70                  // special case for collection objects into arrays                    
71                  if (newValue instanceof Collection && valueType.isArray()) {
72                      Collection valuesAsCollection = (Collection) newValue;
73                      Class componentType = valueType.getComponentType();
74                      if (componentType != null) {
75                          Object[] valuesAsArray = 
76                              (Object[]) Array.newInstance(componentType, valuesAsCollection.size());
77                          newValue = valuesAsCollection.toArray(valuesAsArray);
78                      }
79                  }
80                  
81                  ;
82                  try {
83                      executeUpdate( context, bean, newValue );
84                      
85                  } catch (Exception e) {
86                      String valueTypeName = (newValue != null) ? newValue.getClass().getName() : "null";
87                      log.warn( 
88                          "Cannot evaluate: " + this.toString() + " on bean: " + bean 
89                          + " of type: " + bean.getClass().getName() + " with value: " + newValue 
90                          + " of type: " + valueTypeName 
91                      );
92                      handleException(context, e);
93                  }
94              }
95          }
96  
97      
98      
99      /***
100      * Gets the type expected.
101      * The value passed into {@link #update}
102      * will be converted on the basis of this type
103      * before being passed to {@link #executeUpdate}.
104      * @return <code>Class</code> giving expected type, not null
105      */
106     public Class getValueType() {
107         return valueType;
108     }
109     
110     /***
111      * Sets the type expected.
112      * The value passed into {@link #update}
113      * will be converted on the basis of this type
114      * before being passed to {@link #executeUpdate}.
115      * @param valueType <code>Class</code> giving expected type, not null
116      */
117     public void setValueType(Class valueType) {
118         this.valueType = valueType;
119     }
120     
121     /***
122      * Updates the bean with the given value.
123      * @param bean 
124      * @param value value after type conversion
125      */
126     protected abstract void executeUpdate(Context context, Object bean, Object value) throws Exception;
127 
128     /*** 
129      * Strategy method to allow derivations to handle exceptions differently.
130      * @param context the Context being updated when this exception occured
131      * @param e the Exception that occured during the update
132      */
133     protected void handleException(Context context, Exception e) {
134         log.info( "Caught exception: " + e, e );
135     }
136     
137 }