001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.betwixt.expression;
018:
019: import java.lang.reflect.Array;
020: import java.util.Collection;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024:
025: /**
026: * Abstracts common features for strongly typed <code>Updater</code>'s.
027: * Strongly type <code>Updater</code>'s perform conversions based on this
028: * the expected type before the bean update is invoked.
029: * @since 0.7
030: * @author <a href='http://jakarta.apache.org/commons'>Jakarta Commons Team</a>, <a href='http://www.apache.org'>Apache Software Foundation</a>
031: */
032: public abstract class TypedUpdater implements Updater {
033:
034: /** Logger */
035: private static final Log log = LogFactory
036: .getLog(TypedUpdater.class);
037:
038: /** The type of the first parameter of the method */
039: private Class valueType;
040:
041: /**
042: * Updates the current bean context with the given String value
043: * @param context the Context to be updated
044: * @param newValue the update to this new value
045: */
046: public void update(Context context, Object newValue) {
047: Object bean = context.getBean();
048: if (bean != null) {
049: if (newValue instanceof String) {
050: // try to convert into primitive types
051: if (log.isTraceEnabled()) {
052: log.trace("Converting primitive to " + valueType);
053: }
054: newValue = context.getObjectStringConverter()
055: .stringToObject((String) newValue, valueType,
056: context);
057: }
058: if (newValue != null) {
059: // check that it is of the correct type
060: /*
061: if ( ! valueType.isAssignableFrom( newValue.getClass() ) ) {
062: log.warn(
063: "Cannot call setter method: " + method.getName() + " on bean: " + bean
064: + " with type: " + bean.getClass().getName()
065: + " as parameter should be of type: " + valueType.getName()
066: + " but is: " + newValue.getClass().getName()
067: );
068: return;
069: }
070: */
071: }
072: // special case for collection objects into arrays
073: if (newValue instanceof Collection && valueType.isArray()) {
074: Collection valuesAsCollection = (Collection) newValue;
075: Class componentType = valueType.getComponentType();
076: if (componentType != null) {
077: Object[] valuesAsArray = (Object[]) Array
078: .newInstance(componentType,
079: valuesAsCollection.size());
080: newValue = valuesAsCollection
081: .toArray(valuesAsArray);
082: }
083: }
084:
085: ;
086: try {
087: executeUpdate(context, bean, newValue);
088:
089: } catch (Exception e) {
090: String valueTypeName = (newValue != null) ? newValue
091: .getClass().getName() : "null";
092: log.warn("Cannot evaluate: " + this .toString()
093: + " on bean: " + bean + " of type: "
094: + bean.getClass().getName() + " with value: "
095: + newValue + " of type: " + valueTypeName);
096: handleException(context, e);
097: }
098: }
099: }
100:
101: /**
102: * Gets the type expected.
103: * The value passed into {@link #update}
104: * will be converted on the basis of this type
105: * before being passed to {@link #executeUpdate}.
106: * @return <code>Class</code> giving expected type, not null
107: */
108: public Class getValueType() {
109: return valueType;
110: }
111:
112: /**
113: * Sets the type expected.
114: * The value passed into {@link #update}
115: * will be converted on the basis of this type
116: * before being passed to {@link #executeUpdate}.
117: * @param valueType <code>Class</code> giving expected type, not null
118: */
119: public void setValueType(Class valueType) {
120: this .valueType = valueType;
121: }
122:
123: /**
124: * Updates the bean with the given value.
125: * @param bean
126: * @param value value after type conversion
127: */
128: protected abstract void executeUpdate(Context context, Object bean,
129: Object value) throws Exception;
130:
131: /**
132: * Strategy method to allow derivations to handle exceptions differently.
133: * @param context the Context being updated when this exception occured
134: * @param e the Exception that occured during the update
135: */
136: protected void handleException(Context context, Exception e) {
137: log.info("Caught exception: " + e, e);
138: }
139:
140: }
|