Package cookxml.core

Source Code of cookxml.core.FunctionHandler

/*
* (c) Copyright 2004 by Heng Yuan
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* ITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package cookxml.core;

import java.lang.reflect.Method;

import cookxml.core.exception.FunctionHandlerException;
import cookxml.core.exception.HandlerException;
import cookxml.core.interfaces.Converter;
import cookxml.core.interfaces.Handler;
import cookxml.core.util.ClassUtils;

/**
* Ths handler deals with functions.
*
* @author Heng Yuan
* @version $Id: FunctionHandler.java 265 2007-06-10 18:47:06Z coconut $
* @since CookXml 1.0
*/
public class FunctionHandler implements Handler
{
  private final Method m_method;
  private final Class m_cl;
  // check if we set accessible for the method before
  private boolean m_access;

  private FunctionHandler (Method method)
  {
    m_method = method;
    m_cl = method.getParameterTypes ()[0];
  }

  public void invoke (String ns, Object obj, Object value, DecodeEngine decodeEngine) throws HandlerException
  {
    try
    {
      Method method = m_method;

      if (value == null)
      {
        method.invoke (obj, new Object[]{ null });
        if (!m_access)
        {
          try
          {
            m_method.setAccessible (true);
          }
          catch (Exception ex)
          {
          }
          m_access = true;
        }
        return;
      }

      if (value instanceof String)
      {
        Converter converter = decodeEngine.getCookXml ().getTagLibrary ().getConverter (ns, m_cl);
        if (converter != null)
          value = converter.convert ((String)value, decodeEngine);
      }

      method.invoke (obj, new Object[]{ value });
      if (!m_access)
      {
        try
        {
          m_method.setAccessible (true);
        }
        catch (Exception ex)
        {
        }
        m_access = true;
      }
    }
    catch (Exception ex)
    {
      throw new FunctionHandlerException (decodeEngine, ex, obj, value, m_method);
    }
  }

  public Method getMethod ()
  {
    return m_method;
  }

  /**
   * for debugging purpose.
   *
   * @return the method involved
   */
  public String toString ()
  {
    return m_method.toString ();
  }

  /**
   * This function assumes that each function name is only associated with a single
   * data type.  Although it may be possible to switch types, but we won't be able
   * to utilize cache in that case, making it rather slow to find function each
   * and every time.
   *
   * @param  cl
   *       the class we are dealing with
   * @param  funcName
   *       the function to be located in the class
   * @param  valueClass
   *       the class type of the value, can be null to skip check.
   * @return  the handler which can be used to deal with the element
   */
  public static Method getMethod (Class cl, String funcName, Class valueClass)
  {
    Method[] methods = cl.getMethods ();
    for (int i = 0; i < methods.length; ++i)
    {
      if (methods[i].getName ().equalsIgnoreCase (funcName))
      {
        Method method = methods[i];
        // we need to check if it is possible to match the parameter type
        Class[] params = method.getParameterTypes ();
        if (params.length != 1)
          continue;

        if (valueClass == null)
          return method;

        Class targetClass = ClassUtils.getEquivalentClass (params[0]);

        if (targetClass.isAssignableFrom (valueClass))
          return method;
      }
    }
    return null;
  }

  /**
   * This function assumes that each function name is only associated with a single
   * data type.  Although it may be possible to switch types, but we won't be able
   * to utilize cache in that case, making it rather slow to find function each
   * and every time.
   *
   * @param  obj
   *       the object we are dealing with.  we are actually only interested in
   *       its class type
   * @param  funcName
   *       the function to be located in the class
   * @param  valueClass
   *       the class type of the value, can be null to skip check.
   * @return  the handler which can be used to deal with the element
   */
  public static Handler getHandler (Object obj, String funcName, Class valueClass)
  {
    Method[] methods = obj.getClass ().getMethods ();
    for (int i = 0; i < methods.length; ++i)
    {
      if (methods[i].getName ().equalsIgnoreCase (funcName))
      {
        Method method = methods[i];
        // we need to check if it is possible to match the parameter type
        Class[] params = method.getParameterTypes ();
        if (params.length != 1)
          continue;

        if (valueClass == null)
          return new FunctionHandler (method);

        Class targetClass = ClassUtils.getEquivalentClass (params[0]);

        if (targetClass.isAssignableFrom (valueClass))
          return new FunctionHandler (method);
      }
    }
    return null;
  }
}
TOP

Related Classes of cookxml.core.FunctionHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.