View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */ 
17  package org.apache.commons.betwixt.expression;
18  
19  import java.lang.reflect.Array;
20  import java.util.Collection;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  /**
26   * Abstracts common features for strongly typed <code>Updater</code>'s.
27   * Strongly type <code>Updater</code>'s perform conversions based on this
28   * the expected type before the bean update is invoked.
29   * @since 0.7
30   * @author <a href='http://commons.apache.org'>Apache Commons Team</a>, <a href='http://www.apache.org'>Apache Software Foundation</a>
31   */
32  public abstract class TypedUpdater implements Updater {
33  
34      /** Logger */
35      private static final Log log = LogFactory.getLog( TypedUpdater.class );
36  
37      
38      /** The type of the first parameter of the method */
39      private Class valueType;
40  
41      /** 
42       * Updates the current bean context with the given String value 
43       * @param context the Context to be updated
44       * @param newValue the update to this new value 
45       */
46      public void update(Context context, Object newValue) {
47              Object bean = context.getBean();
48              if ( bean != null ) {
49                  if ( newValue instanceof String ) {
50                      // try to convert into primitive types
51                      if ( log.isTraceEnabled() ) {
52                          log.trace("Converting primitive to " + valueType);
53                      }
54                      newValue = context.getObjectStringConverter()
55                          .stringToObject( (String) newValue, valueType, context );
56                  }
57                  if ( newValue != null ) {
58                      // check that it is of the correct type
59      /*                
60                      if ( ! valueType.isAssignableFrom( newValue.getClass() ) ) {
61                          log.warn( 
62                              "Cannot call setter method: " + method.getName() + " on bean: " + bean
63                              + " with type: " + bean.getClass().getName() 
64                              + " as parameter should be of type: " + valueType.getName() 
65                              + " but is: " + newValue.getClass().getName() 
66                          );
67                          return;
68                      }
69      */                
70                  }
71                  // special case for collection objects into arrays                    
72                  if (newValue instanceof Collection && valueType.isArray()) {
73                      Collection valuesAsCollection = (Collection) newValue;
74                      Class componentType = valueType.getComponentType();
75                      if (componentType != null) {
76                          Object[] valuesAsArray = 
77                              (Object[]) Array.newInstance(componentType, valuesAsCollection.size());
78                          newValue = valuesAsCollection.toArray(valuesAsArray);
79                      }
80                  }
81                  
82                  ;
83                  try {
84                      executeUpdate( context, bean, newValue );
85                      
86                  } catch (Exception e) {
87                      String valueTypeName = (newValue != null) ? newValue.getClass().getName() : "null";
88                      log.warn( 
89                          "Cannot evaluate: " + this.toString() + " on bean: " + bean 
90                          + " of type: " + bean.getClass().getName() + " with value: " + newValue 
91                          + " of type: " + valueTypeName 
92                      );
93                      handleException(context, e);
94                  }
95              }
96          }
97  
98      
99      
100     /**
101      * Gets the type expected.
102      * The value passed into {@link #update}
103      * will be converted on the basis of this type
104      * before being passed to {@link #executeUpdate}.
105      * @return <code>Class</code> giving expected type, not null
106      */
107     public Class getValueType() {
108         return valueType;
109     }
110     
111     /**
112      * Sets the type expected.
113      * The value passed into {@link #update}
114      * will be converted on the basis of this type
115      * before being passed to {@link #executeUpdate}.
116      * @param valueType <code>Class</code> giving expected type, not null
117      */
118     public void setValueType(Class valueType) {
119         this.valueType = valueType;
120     }
121     
122     /**
123      * Updates the bean with the given value.
124      * @param bean 
125      * @param value value after type conversion
126      */
127     protected abstract void executeUpdate(Context context, Object bean, Object value) throws Exception;
128 
129     /** 
130      * Strategy method to allow derivations to handle exceptions differently.
131      * @param context the Context being updated when this exception occured
132      * @param e the Exception that occured during the update
133      */
134     protected void handleException(Context context, Exception e) {
135         log.info( "Caught exception: " + e, e );
136     }
137     
138 }