package org.appfuse.webapp.form;

import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.Globals;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.util.MessageResources;
import org.apache.struts.validator.ValidatorForm;


/**
 * Base ActionForm bean. An ActionForm bean serves as an adapter to make data
 * entered into an HTML available to the rest of a Web application, usually by
 * transferring data to an internal object that uses native types and
 * implements a business logic interface.
 *
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 * @version $Revision: 1.5 $ $Date: 2004/03/31 13:04:28 $
 */
public class BaseForm extends ValidatorForm implements Serializable {
    //~ Methods ================================================================

    public String toString()
    {
        StringBuffer results = new StringBuffer();
        
        results.append(getClass().getName() + "\n");
        
        // get super class as String        
        results.append(getClassAsString(getClass().getSuperclass()));
        
        // get this class as String
        results.append(getClassAsString(getClass()));

        return results.toString();
    }
    
    private StringBuffer getClassAsString(Class clazz) {
        StringBuffer results = new StringBuffer();
        
        Field[] fields = clazz.getDeclaredFields();

        try {
            AccessibleObject.setAccessible(fields, true);

            for (int i = 0; i < fields.length; i++) {
                results.append("\t" + fields[i].getName() + "=" +
                               fields[i].get(this) + "\n");
            }
        } catch (Exception e) {
            // ignored!
        }
        
        return results;
    }

   /**
    * This validation method is designed to be a parent of all other Form's
    * validate methods - this allows the cancel and delete buttons to bypass
    * validation.
    *
    * @param mapping The <code>ActionMapping</code> used to select this
    *   instance
    * @param request The servlet request we are processing
    * @return <code>ActionErrors</code> object that encapsulates any
    *   validation errors
    */
    public ActionErrors validate(ActionMapping mapping,
                                 HttpServletRequest request) {
        // Identify the request parameter containing the method name
        String parameter = mapping.getParameter();

        if( parameter != null ) {
            // Identify the method name to be dispatched to.
            String method = request.getParameter(parameter);
            MessageResources resources =
                (MessageResources) request.getAttribute(Globals.MESSAGES_KEY);
            // Identify the localized message for the cancel button
            String cancel = resources.getMessage("button.cancel");
            String goBack = resources.getMessage("button.goBack");
            // if message resource matches the cancel button then no
            // need to validate
            if (method != null && method.equalsIgnoreCase(cancel)
                || method.equalsIgnoreCase(goBack)) {
                return null;
            }
        }
        // perform regular validation
        return super.validate(mapping, request);
    }
}