//----------------------------BEGIN LICENSE----------------------------
/* 
 * Willow : the Open Source WorkFlow Project
 * Distributable under GNU LGPL license by gun.org
 *
 * Copyright (C) 2004-2010 huihoo.org 
 * Copyright (C) 2004-2010  ZosaTapo <dertyang@hotmail.com> 
 * 
 * ====================================================================
 * Project Homepage : http://www.huihoo.org/willow
 * Source Forge     : http://sourceforge.net/projects/huihoo
 * Mailing list     : willow@lists.sourceforge.net 
 */
//----------------------------END  LICENSE-----------------------------
package org.huihoo.workflow.coreImpl.xpdl.parser.xmlrules;

import java.beans.PropertyDescriptor;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.digester.Rule;
import org.xml.sax.Attributes;

import org.huihoo.workflow.xpdl.util.TypeDefinition;

public class SetBasicTypeRule  extends Rule
{
  //----------------------------------------------------------- Constructors
  /**
   * Construct a "set property" rule with the specified name and value
   * attributes.
   *
   * @param digester The digester with which this rule is associated
   * @param name Name of the property 
   * @param value Name of the attribute that will contain the value to which
   *        the property should be set
   */

  public SetBasicTypeRule(String name, String value)
  {
    this.name = name;
    this.value = value;
  }
  // ----------------------------------------------------- Instance Variables
  /**
   * The attribute that will contain the property name.
   */
  protected String name = null;
  /**
   * The attribute that will contain the property value.
   */
  protected String value = null;
  // --------------------------------------------------------- Public Methods
  /**
   * This method is called when the beginning of a matching XML element
   * is encountered. The default implementation delegates to the deprecated
   * method {@link #begin(Attributes) begin} without the 
   * <code>namespace</code> and <code>name</code> parameters, to retain 
   * backwards compatibility.
   *
   * @param namespace the namespace URI of the matching element, or an 
   *   empty string if the parser is not namespace aware or the element has
   *   no namespace
   * @param eleName the local name if the parser is namespace aware, or just 
   *   the element name otherwise
   * @param attributes The attribute list of this element
   * @since Digester 1.4
   */
  public void begin(String namespace, String eleNname, Attributes attributes)
  throws Exception
  {
    // Identify the actual property name and value to be used
    String actualName = this.name;
    
    String actualValue = null;
    
    for (int i = 0; i < attributes.getLength(); i++)
    {
      String localName = attributes.getLocalName(i);
      if ("".equals(localName))
      {
        localName = attributes.getQName(i);
      }
   
      if(localName.equals(this.value))
      {
        actualValue = attributes.getValue(i);
      }
    }
    
    // Get a reference to the top object
    Object top = digester.peek();
    // Log some debugging information
    if (digester.getLogger().isDebugEnabled())
    {
      digester.getLogger().debug(
        "[SetBasicTypeRule]{"
          + digester.getMatch()
          + "} Set "
          + top.getClass().getName()
          + " property "
          + actualName
          + " to "
          + actualValue);
    }
    // Force an exception if the property does not exist
    // (BeanUtils.setProperty() silently returns in this case)
    if (top instanceof DynaBean)
    {
      DynaProperty desc =((DynaBean) top).getDynaClass().getDynaProperty(actualName);
      if (desc == null)
      {
        throw new NoSuchMethodException(
          "Bean has no property named " + actualName);
      }
    }
    else /* this is a standard JavaBean */ {
      PropertyDescriptor desc =
        PropertyUtils.getPropertyDescriptor(top, actualName);
      if (desc == null)
      {
        throw new NoSuchMethodException(
          "Bean has no property named " + actualName);
      }
    }
    
    // Set the property (with conversion as necessary)
    Class clazz=TypeDefinition.XPDLToJava(actualValue);
    //System.err.println("[Class]="+clazz);
    BeanUtils.setProperty(top, actualName, clazz);   
  }
  /**
   * Render a printable version of this Rule.
   */
  public String toString()
  {
    StringBuffer sb = new StringBuffer("SetBasicTypeRule[");
    sb.append("name=");
    sb.append(name);
    sb.append(", value=");
    sb.append(value);
    sb.append("]");
    return (sb.toString());
  }
}

