package com.papajo.examples.pab.struts;

import com.papajo.examples.util.*;

import org.apache.struts.action.*;
import org.apache.struts.util.*;

import javax.servlet.http.*;
import java.lang.reflect.*;
import java.util.*;

public abstract class ValidatingForm extends ActionForm
{
  protected StringValidator SV = new StringValidator();
  private static String keyPrefix  = "errmsg.";

  public final ActionErrors
    validate(ActionMapping mapping, HttpServletRequest request)
  {
    ActionErrors errs = new ActionErrors();
    String name = mapping.getName();

    String[] req   = getRequiredFields(name);
    String[] ints  = getIntegerFields(name);
    String[] email = getEmailAddressFields(name);
    String[] dates = getDateFields(name);

    if(servlet.getDebug() >= 1)
    {
      servlet.log("-- ValidatingForm validate() req: "   + DebugUtil.dumpArray(req));
      servlet.log("-- ValidatingForm validate() ints: "  + DebugUtil.dumpArray(ints));
      servlet.log("-- ValidatingForm validate() email: " + DebugUtil.dumpArray(email));
      servlet.log("-- ValidatingForm validate() dates: " + DebugUtil.dumpArray(dates));
    }

    try
    {
      Object result = null;
      boolean emptyOk = false;
      int location = -1;

      if(req != null && req.length > 0) {
        for(int i = 0; i < req.length; i++ ) {
          if(servlet.getDebug() >= 1)
            servlet.log("-- Attempting to retrieve value for: \"" + req[i] + "\"");
          result = PropertyUtils.getProperty(this,req[i]);
          if(result instanceof String)
          {
            if(SV.isEmpty((String)result))
            {
              if(servlet.getDebug() >= 1) {
                servlet.log("-- Required field missing: " + req[i]);
                servlet.log("-- ActionError key       : " + name + "." + req[i] + ".error.missing");
              }
              errs.add(req[i], new ActionError(name + "." +  req[i] + ".error.missing"));
            }
          }
        }// end for loop
      }// end validating required fields


      if(ints != null && ints.length > 0) {
        for(int i = 0; i < ints.length; i++ ) {
          if(servlet.getDebug() >= 1)
            servlet.log("-- Attempting to retrieve value for: \"" + ints[i] + "\"");
          result = PropertyUtils.getProperty(this,ints[i]);
          if(result instanceof String)
          {
            location = Arrays.binarySearch(req, ints[i]);
            emptyOk = location < 0;
            if(! SV.checkInteger( (String)result, emptyOk) )
            {
              if(servlet.getDebug() >= 1) {
                servlet.log("-- Invalid integer field : " + ints[i]);
                servlet.log("-- ActionError key       : " + name + "." + ints[i] + ".error.invalid");
              }
              errs.add(ints[i],  new ActionError(name + "." +  ints[i] + ".error.invalid"));
            }
          }
        }// end for loop
      }// end validating integer fields

      if(email != null && email.length > 0) {
        for(int i = 0; i < email.length; i++ ) {
          if(servlet.getDebug() >= 1)
            servlet.log("-- Attempting to retrieve value for: \"" + email[i] + "\"");
          result = PropertyUtils.getProperty(this,email[i]);
          if(result instanceof String)
          {
            location = Arrays.binarySearch(req, email[i]);
            emptyOk = location < 0;
            if(! SV.checkEmail( (String)result, emptyOk ))
            {
              if(servlet.getDebug() >= 1) {
                servlet.log("-- Invalid email field   : " + email[i]);
                servlet.log("-- ActionError key       : " + name + "." + email[i] + ".error.invalid");
              }
              errs.add(email[i], new ActionError(name + "." +  email[i] + ".error.invalid"));
            }
          }
        }// end for loop
      }// end validating email address fields

      if(dates != null && dates.length > 0) {
        for(int i = 0; i < dates.length; i++ ) {
          if(servlet.getDebug() >= 1)
            servlet.log("-- Attempting to retrieve value for: \"" + dates[i] + "\"");
          result = PropertyUtils.getProperty(this,dates[i]);
          if(result instanceof String)
          {
            location = Arrays.binarySearch(req, dates[i]);
            emptyOk = location < 0;
            if(! SV.checkDate( (String)result, emptyOk ) )
            {
              if(servlet.getDebug() >= 1) {
                servlet.log("-- Invalid date field    : " + dates[i]);
                servlet.log("-- ActionError key       : " + name + "." + dates[i] + ".error.invalid");
              }
              errs.add(dates[i], new ActionError(name + "." + dates[i] + ".error.invalid"));
            }
          }
        }// end for loop
      }// end validating date fields

    } catch (SecurityException e) {
      System.out.println(e);
    } catch (IllegalAccessException e) {
      System.out.println(e);
    } catch (InvocationTargetException e) {
      System.out.println(e);
    } catch (NoSuchMethodException e) {
      System.out.println(e);
    }
    return errs;
  }

  /** Defines fields that cannot be empty */
  protected abstract String[] getRequiredFields(String formName);

  /** Defines fields that contain int primitive types */
  protected abstract String[] getIntegerFields(String formName);

  /** Defines other common types we could validate */
  protected abstract String[] getEmailAddressFields(String formName);
  protected abstract String[] getDateFields(String formName);
}