/**
     * Obtain a validated reason and button value via a Question prompt. Reason is validated against
     * sensitive data patterns, and max Note text length
     *
     * @param mapping Struts mapping
     * @param form Struts form
     * @param request http request
     * @param response http response
     * @return Response object representing *either*: 1) an ActionForward due to error or abort 2) a
     *     reason and button clicked
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    public Response ask(
        ActionMapping mapping,
        ActionForm form,
        HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {
      String question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
      String reason = request.getParameter(KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME);

      if (StringUtils.isBlank(reason)) {
        String context = request.getParameter(KRADConstants.QUESTION_CONTEXT);
        if (context != null
            && StringUtils.contains(context, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME + "=")) {
          reason =
              StringUtils.substringAfter(
                  context, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME + "=");
        }
      }

      String disapprovalNoteText = "";

      // start in logic for confirming the disapproval
      if (question == null) {
        // ask question if not already asked
        return new Response(
            question,
            performQuestionWithInput(
                mapping,
                form,
                request,
                response,
                this.questionId,
                getKualiConfigurationService().getPropertyValueAsString(this.questionTextKey),
                this.questionType,
                this.questionCallerMapping,
                ""));
      }

      String buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
      if (this.questionId.equals(question)
          && abortButton != null
          && abortButton.equals(buttonClicked)) {
        // if no button clicked just reload the doc
        return new Response(question, mapping.findForward(RiceConstants.MAPPING_BASIC));
      }

      // have to check length on value entered
      String introNoteMessage = "";
      if (noteIntroKey != null) {
        introNoteMessage =
            getKualiConfigurationService().getPropertyValueAsString(this.noteIntroKey)
                + KRADConstants.BLANK_SPACE;
      }

      // build out full message
      disapprovalNoteText = introNoteMessage + reason;

      // check for sensitive data in note
      boolean warnForSensitiveData =
          CoreFrameworkServiceLocator.getParameterService()
              .getParameterValueAsBoolean(
                  KRADConstants.KNS_NAMESPACE,
                  ParameterConstants.ALL_COMPONENT,
                  KRADConstants.SystemGroupParameterNames.SENSITIVE_DATA_PATTERNS_WARNING_IND);
      if (warnForSensitiveData) {
        String context = KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME + "=" + reason;
        ActionForward forward =
            checkAndWarnAboutSensitiveData(
                mapping,
                form,
                request,
                response,
                KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME,
                disapprovalNoteText,
                this.questionCallerMapping,
                context);
        if (forward != null) {
          return new Response(question, forward);
        }
      } else {
        if (KRADUtils.containsSensitiveDataPatternMatch(disapprovalNoteText)) {
          return new Response(
              question,
              performQuestionWithInputAgainBecauseOfErrors(
                  mapping,
                  form,
                  request,
                  response,
                  this.questionId,
                  getKualiConfigurationService().getPropertyValueAsString(this.questionTextKey),
                  this.questionType,
                  this.questionCallerMapping,
                  "",
                  reason,
                  RiceKeyConstants.ERROR_DOCUMENT_FIELD_CONTAINS_POSSIBLE_SENSITIVE_DATA,
                  KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME,
                  "reason"));
        }
      }

      int disapprovalNoteTextLength = disapprovalNoteText.length();

      // get note text max length from DD
      int noteTextMaxLength =
          getDataDictionaryService()
              .getAttributeMaxLength(Note.class, KRADConstants.NOTE_TEXT_PROPERTY_NAME);

      if (StringUtils.isBlank(reason) || (disapprovalNoteTextLength > noteTextMaxLength)) {

        if (reason == null) {
          // prevent a NPE by setting the reason to a blank string
          reason = "";
        }
        return new Response(
            question,
            performQuestionWithInputAgainBecauseOfErrors(
                mapping,
                form,
                request,
                response,
                this.questionId,
                getKualiConfigurationService().getPropertyValueAsString(this.questionTextKey),
                this.questionType,
                this.questionCallerMapping,
                "",
                reason,
                this.missingReasonKey,
                KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME,
                Integer.toString(noteTextMaxLength)));
      }

      return new Response(question, disapprovalNoteText, buttonClicked);
    }