📄 mapentryadder.java
字号:
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.betwixt.expression;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/** <p><code>MapEntryAdder</code> is used to add entries to a map.</p>
*
* <p>
* <code>MapEntryAdder</code> supplies two updaters:
* <ul>
* <li>{@link #getKeyUpdater()} which allows the entry key to be updated</li>
* <li>{@link #getValueUpdater()} which allows the entry value to be updated</li>
* </ul>
* When both of these updaters have been called, the entry adder method is called.
* Once this has happened then the values can be updated again.
* Note that only the <code>Context</code> passed by the last update will be used.
* </p>
*
* @author <a href="mailto:rdonkin@apache.org">Robert Burrell Donkin</a>
* @since 0.5
*/
public class MapEntryAdder {
// Class Attributes
//-------------------------------------------------------------------------
/** Log used by this class */
private static Log log = LogFactory.getLog( MapEntryAdder.class );
// Class Methods
//-------------------------------------------------------------------------
/**
* Sets the logger used by this class.
*
* @param newLog log to this
*/
public static void setLog(Log newLog) {
log = newLog;
}
// Attributes
//-------------------------------------------------------------------------
/** The method to be called to add a new map entry */
private Method adderMethod;
/** Has the entry key been updated? */
private boolean keyUpdated = false;
/** The entry key */
private Object key;
/** Has the entry value been updated? */
private boolean valueUpdated = false;
/** The entry value */
private Object value;
// Constructors
//-------------------------------------------------------------------------
/**
* Construct a <code>MapEntryAdder</code> which adds entries to given method.
*
* @param method the <code>Method</code> called to add a key-value entry
* @throws IllegalArgumentException if the given method does not take two parameters
*/
public MapEntryAdder(Method method) {
Class[] types = method.getParameterTypes();
if ( types == null || types.length != 2) {
throw new IllegalArgumentException(
"Method used to add entries to maps must have two parameter.");
}
this.adderMethod = method;
}
// Properties
//-------------------------------------------------------------------------
/**
* Gets the entry key <code>Updater</code>.
* This is used to update the entry key value to the read value.
* If {@link #getValueUpdater} has been called previously,
* then this trigger the updating of the adder method.
*
* @return the <code>Updater</code> which should be used to populate the entry key
*/
public Updater getKeyUpdater() {
return new Updater() {
public void update( Context context, Object keyValue ) {
// might as well make sure that his can only be set once
if ( !keyUpdated ) {
keyUpdated = true;
key = keyValue;
if ( log.isTraceEnabled() ) {
log.trace( "Setting entry key to " + key );
log.trace( "Current entry value is " + value );
}
if ( valueUpdated ) {
callAdderMethod( context );
}
}
}
};
}
/**
* Gets the entry value <code>Updater</code>.
* This is used to update the entry key value to the read value.
* If {@link #getKeyUpdater} has been called previously,
* then this trigger the updating of the adder method.
*
* @return the <code>Updater</code> which should be used to populate the entry value
*/
public Updater getValueUpdater() {
return new Updater() {
public void update( Context context, Object valueValue ) {
// might as well make sure that his can only be set once
if ( !valueUpdated ) {
valueUpdated = true;
value = valueValue;
if ( log.isTraceEnabled() ) {
log.trace( "Setting entry value to " + value);
log.trace( "Current entry key is " + key );
}
if ( keyUpdated ) {
callAdderMethod( context );
}
}
}
};
}
// Implementation methods
//-------------------------------------------------------------------------
/**
* Call the adder method on the bean associated with the <code>Context</code>
* with the key, value entry values stored previously.
*
* @param context the Context against whose bean the adder method will be invoked
*/
private void callAdderMethod(Context context) {
log.trace("Calling adder method");
// this allows the same instance to be used multiple times.
keyUpdated = false;
valueUpdated = false;
//
// XXX This is (basically) cut and pasted from the MethodUpdater code
// I haven't abstracted this code just yet since I think that adding
// handling for non-beans will mean adding quite a lot more structure
// and only once this is added will the proper position for this method
// become clear.
//
Class[] types = adderMethod.getParameterTypes();
// key is first parameter
Class keyType = types[0];
// value is the second
Class valueType = types[1];
Object bean = context.getBean();
if ( bean != null ) {
if ( key instanceof String ) {
// try to convert into primitive types
key = context.getObjectStringConverter()
.stringToObject( (String) key, keyType, null, context );
}
if ( value instanceof String ) {
// try to convert into primitive types
value = context.getObjectStringConverter()
.stringToObject( (String) value, valueType, null, context );
}
// special case for collection objects into arrays
if (value instanceof Collection && valueType.isArray()) {
Collection valuesAsCollection = (Collection) value;
Class componentType = valueType.getComponentType();
if (componentType != null) {
Object[] valuesAsArray =
(Object[]) Array.newInstance(componentType, valuesAsCollection.size());
value = valuesAsCollection.toArray(valuesAsArray);
}
}
Object[] arguments = { key, value };
try {
if ( log.isTraceEnabled() ) {
log.trace(
"Calling adder method: " + adderMethod.getName() + " on bean: " + bean
+ " with key: " + key + " and value: " + value
);
}
adderMethod.invoke( bean, arguments );
} catch (Exception e) {
log.warn(
"Cannot evaluate adder method: " + adderMethod.getName() + " on bean: " + bean
+ " of type: " + bean.getClass().getName() + " with value: " + value
+ " of type: " + valueType + " and key: " + key
+ " of type: " + keyType
);
log.debug(e);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -