/**
   * Checks if the action received in the request is the same as the one stored in the HDIV state.
   *
   * @param request HttpServletRequest to validate
   * @param target Part of the url that represents the target action
   * @param state The restored state for this url
   * @return valid result if the actions are the same. False otherwise.
   */
  public ValidatorHelperResult isTheSameAction(
      HttpServletRequest request, String target, IState state) {

    if (state.getAction().equalsIgnoreCase(target)) {
      return ValidatorHelperResult.VALID;
    }

    if (target.endsWith("/")) {
      String actionSlash = state.getAction() + "/";
      if (actionSlash.equalsIgnoreCase(target)) {
        return ValidatorHelperResult.VALID;
      }
    }

    if (log.isDebugEnabled()) {
      log.debug("target:" + target);
      log.debug("state action:" + state.getAction());
    }

    this.logger.log(HDIVErrorCodes.ACTION_ERROR, target, null, null);

    if (log.isDebugEnabled()) {
      log.debug(
          "Detected validation error in the action: action in state:"
              + state.getAction()
              + ", action in the request:"
              + target);
    }

    return new ValidatorHelperResult(HDIVErrorCodes.ACTION_ERROR);
  }
  /**
   * Check if all required parameters are received in <code>request</code>.
   *
   * @param request HttpServletRequest to validate
   * @param state IState The restored state for this url
   * @param target Part of the url that represents the target action
   * @return valid result if all required parameters are received. False in otherwise.
   */
  private ValidatorHelperResult allRequiredParametersReceived(
      HttpServletRequest request, IState state, String target) {

    Hashtable receivedParameters = new Hashtable(state.getRequiredParams());

    String currentParameter = null;
    Enumeration requestParameters = request.getParameterNames();
    while (requestParameters.hasMoreElements()) {

      currentParameter = (String) requestParameters.nextElement();
      if (receivedParameters.containsKey(currentParameter)) {
        receivedParameters.remove(currentParameter);
      }

      // If multiple parameters are received, it is possible to pass this
      // verification without checking all the request parameters.
      if (receivedParameters.size() == 0) {
        return ValidatorHelperResult.VALID;
      }
    }

    if (receivedParameters.size() > 0) {
      this.logger.log(
          HDIVErrorCodes.REQUIRED_PARAMETERS, target, receivedParameters.keySet().toString(), null);
      return new ValidatorHelperResult(HDIVErrorCodes.REQUIRED_PARAMETERS);
    }

    return ValidatorHelperResult.VALID;
  }
  /**
   * Checks if the values of the parameters received in the request <code>request</code> are valid.
   * These values are valid if and only if the noneditable parameters haven't been modified.<br>
   * Validation process is as follows.<br>
   * 1. If the action to which the request is directed is an init page, then it is a valid request.
   * <br>
   * 2. if the cookies received in the request are not found in the user session, the validation is
   * incorrect.<br>
   * 3. if the state recover process has produced an error, incorrect validation.<br>
   * 4. If the action received in the request is different to the action of the recovered state,
   * incorrect validation.<br>
   * 5. If not, all the parameter values are checked and if all the received values are valid then
   * the request is valid. <br>
   * 5.1. If it is an init parameter or a HDIV parameter then it is a valid parameter.<br>
   * 5.2. If the received parameter is not in the state:<br>
   * 5.2.1. If it has been defined by the user as a no validation required parameter, then it is a
   * valid parameter.<br>
   * 5.2.2. otherwise, it is a no valid request.<br>
   * 5.3. If the parameter is editable, if validations have been defined values are checked.<br>
   * 5.4. If it is a noneditable parameter, all the received values are checked.
   *
   * @param request HttpServletRequest to validate
   * @return valid result If all the parameter values of the request <code>request</code> pass the
   *     the HDIV validation. False, otherwise.
   * @throws HDIVException If the request doesn't pass the HDIV validation an exception is thrown
   *     explaining the cause of the error.
   */
  public ValidatorHelperResult validate(HttpServletRequest request) {

    String target = this.getTarget(request);
    String targetWithoutContextPath = this.getTargetWithoutContextPath(request, target);

    // Hook before the validation
    Boolean pre = this.preValidate(request, target);
    if (pre != null) {
      return new ValidatorHelperResult(pre.booleanValue());
    }

    if (this.hdivConfig.hasExtensionToExclude(target)) {
      log.debug("The target " + target + " has an extension to exclude from validation");
      return ValidatorHelperResult.VALID;
    }

    if (!this.hdivConfig.isValidationInUrlsWithoutParamsActivated()) {

      boolean requestHasParameters =
          (request.getParameterNames() != null) && (request.getParameterNames().hasMoreElements());
      if (!requestHasParameters) {
        log.debug(
            "The url "
                + request.getRequestURI()
                + " is not be validated because it has not got parameters");
        return ValidatorHelperResult.VALID;
      }
    }

    if (this.hdivConfig.isStartPage(targetWithoutContextPath, request.getMethod())) {
      return (this.validateStartPageParameters(request, target));
    }

    if (this.hdivConfig.isCookiesIntegrityActivated()) {
      ValidatorHelperResult result = this.validateRequestCookies(request, target);
      if (!result.isValid()) {
        return result;
      }
    }

    // Restore state from request or from memory
    ValidatorHelperResult result = this.restoreState(request, target);
    if (!result.isValid()) {
      return result;
    }
    // Get resultant object, the stored state
    IState state = (IState) result.getValue();

    result = this.isTheSameAction(request, target, state);
    if (!result.isValid()) {
      return result;
    }

    result = this.allRequiredParametersReceived(request, state, target);
    if (!result.isValid()) {
      return result;
    }

    // Hdiv parameter name
    String hdivParameter = getHdivParameter(request);

    Hashtable unauthorizedEditableParameters = new Hashtable();
    Enumeration parameters = request.getParameterNames();
    while (parameters.hasMoreElements()) {

      String parameter = (String) parameters.nextElement();

      // Check if the HDIV validation must be applied to the parameter
      if (!this.hdivConfig.needValidation(parameter, hdivParameter)) {

        if (log.isDebugEnabled() && !parameter.equals(hdivParameter)) {
          log.debug("parameter " + parameter + " doesn't need validation");
        }
        continue;
      }

      // If the parameter requires no validation it is considered a valid parameter
      if (this.isUserDefinedNonValidationParameter(targetWithoutContextPath, parameter)) {
        continue;
      }

      IParameter stateParameter = state.getParameter(parameter);
      if (stateParameter == null) {

        // If the parameter is not defined in the state, it is an error.
        // With this verification we guarantee that no extra parameters are added.
        this.logger.log(HDIVErrorCodes.PARAMETER_NOT_EXISTS, target, parameter, null);

        if (log.isDebugEnabled()) {
          log.debug(
              "Validation Error Detected: Parameter ["
                  + parameter
                  + "] does not exist in the state for action ["
                  + target
                  + "]");
        }

        return new ValidatorHelperResult(HDIVErrorCodes.PARAMETER_NOT_EXISTS);
      }

      // At this point we are processing a noneditable parameter
      String[] values = request.getParameterValues(parameter);

      // Check if the parameter is editable
      if (stateParameter.isEditable()) {

        if (hdivConfig.existValidations() && (stateParameter.getEditableDataType() != null)) {
          this.validateEditableParameter(
              request,
              target,
              parameter,
              values,
              stateParameter.getEditableDataType(),
              unauthorizedEditableParameters);
        }
        continue;
      }

      try {
        result =
            this.validateParameterValues(request, target, state, stateParameter, parameter, values);
        if (!result.isValid()) {
          return result;
        }
      } catch (Exception e) {
        String errorMessage = HDIVUtil.getMessage("validation.error", e.getMessage());
        throw new HDIVException(errorMessage, e);
      }
    }

    if (unauthorizedEditableParameters.size() > 0) {

      return this.processValidateParameterErrors(request, unauthorizedEditableParameters);
    }

    return ValidatorHelperResult.VALID;
  }