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 }