//----------------------------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 java.lang.reflect.InvocationTargetException;

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;

public class SetReferenceTypeRule extends Rule
{
  //----------------------------------------------------------- Constructors
  /**
   * Construct a "set property" rule 
   */
  public SetReferenceTypeRule()
  {
  }
  // ----------------------------------------------------- Instance Variables

  // --------------------------------------------------------- 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
  {
    String xrefName = "xref"; 
    String xrefValue = null;
    
    String locationName  = "location";   
    String locationValue = null;
    
    String namespaceName  = "namespace";
    String namespaceValue = null;
    
    for (int i = 0; i < attributes.getLength(); i++)
    {
      String localName = attributes.getLocalName(i);
      if ("".equals(localName))
      {
        localName = attributes.getQName(i);
      }
   
      if(localName.equals(xrefName))
      {
        xrefValue = attributes.getValue(i);
      }
      else if(localName.equals(locationName))
      {
        locationValue = attributes.getValue(i);
      }
      else if(localName.equals(namespaceName))
      {
        namespaceValue = attributes.getValue(i);
      }
    }
    
    // Get a reference to the top object
    Object top = digester.peek();
    
    //In current edition , only property 'location' is available
    //ExternalReference ref=new ExternalReference(locationValue,namespaceValue,xrefValue);
    //setProperty(top,"type",ExternalReference.class);
    //setProperty(top,"value",ref);        
    Class clazz=Class.forName(locationValue);
    setProperty(top,"type",clazz);
  }
  
  private void setProperty(Object top,String actualName,Object actualValue)
  throws NoSuchMethodException,InvocationTargetException,IllegalAccessException
  {
//  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)
    BeanUtils.setProperty(top, actualName, actualValue);
  }
}
