⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mapentryadder.java

📁 JAVA 文章管理系统源码
💻 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 + -