@Override
  protected String getActionUrlHref(
      LookupForm lookupForm, Object dataObject, String methodToCall, List<String> pkNames) {
    LOG.debug("Inside getActionUrlHref()");
    LookupView lookupView = (LookupView) lookupForm.getView();

    Properties props = new Properties();
    props.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
    Map<String, String> primaryKeyValues =
        KRADUtils.getPropertyKeyValuesFromDataObject(pkNames, dataObject);
    for (String primaryKey : primaryKeyValues.keySet()) {
      String primaryKeyValue = primaryKeyValues.get(primaryKey);

      props.put(primaryKey, primaryKeyValue);
    }

    if (StringUtils.isNotBlank(lookupForm.getReturnLocation())) {
      props.put(KRADConstants.RETURN_LOCATION_PARAMETER, lookupForm.getReturnLocation());
    }

    props.put(UifParameters.DATA_OBJECT_CLASS_NAME, OleFixedDueDate.class.getName());
    props.put(UifParameters.VIEW_TYPE_NAME, UifConstants.ViewType.MAINTENANCE.name());

    String maintenanceMapping = OLEConstants.FIXED_DUE_DATE_CONTROLLER;

    return UrlFactory.parameterizeUrl(maintenanceMapping, props);
  }
  @Override
  protected boolean processPreprocess(HttpServletRequest request, HttpServletResponse response) {
    final UserSession session = KRADUtils.getUserSessionFromRequest(request);

    if (session == null) {
      throw new IllegalStateException("the user session has not been established");
    }
    GlobalVariables.setUserSession(session);
    KNSGlobalVariables.clear();
    return true;
  }
 @Override
 public void verifyVersionNumber(Object dataObject) {
   if (isPersistable(dataObject.getClass())) {
     PersistableBusinessObject pbObject =
         businessObjectService.retrieve((PersistableBusinessObject) dataObject);
     Long pbObjectVerNbr = KRADUtils.isNull(pbObject) ? null : pbObject.getVersionNumber();
     Long newObjectVerNbr = ((PersistableBusinessObject) dataObject).getVersionNumber();
     if (pbObjectVerNbr != null && !(pbObjectVerNbr.equals(newObjectVerNbr))) {
       GlobalVariables.getMessageMap()
           .putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_VERSION_MISMATCH);
       throw new ValidationException(
           "Version mismatch between the local business object and the database business object");
     }
   }
 }
  /**
   * Method to add and enter key add to the given Group. Will use given lineContext and
   * expressionEvaluator if action string starts with '@{'.
   *
   * @param group
   * @param lineContext
   * @param expressionEvaluator
   * @param enterKeyAction
   */
  protected void addEnterKeyDataAttributeToGroup(
      Group group,
      Map<String, Object> lineContext,
      ExpressionEvaluator expressionEvaluator,
      String enterKeyAction) {
    if (StringUtils.isNotBlank(enterKeyAction)) {
      String action = enterKeyAction;
      if (action.contains("@{")) {
        action = expressionEvaluator.evaluateExpressionTemplate(lineContext, enterKeyAction);
      }

      group.addDataAttribute(
          UifConstants.DataAttributes.ENTER_KEY,
          KRADUtils.convertToHTMLAttributeSafeString(action));
    }
  }
  private KualiDocumentEvent generateKualiDocumentEvent(
      Document document, Class<? extends KualiDocumentEvent> eventClass)
      throws ConfigurationException {
    String potentialErrorMessage =
        "Found error trying to generate Kuali Document Event using event class '"
            + eventClass.getName()
            + "' for document "
            + document.getDocumentNumber();

    try {
      Constructor<?> usableConstructor = null;
      List<Object> paramList = new ArrayList<Object>();
      for (Constructor<?> currentConstructor : eventClass.getConstructors()) {
        for (Class<?> parameterClass : currentConstructor.getParameterTypes()) {
          if (Document.class.isAssignableFrom(parameterClass)) {
            usableConstructor = currentConstructor;
            paramList.add(document);
          } else {
            paramList.add(null);
          }
        }
        if (KRADUtils.isNotNull(usableConstructor)) {
          break;
        }
      }
      if (usableConstructor == null) {
        throw new RuntimeException(
            "Cannot find a constructor for class '"
                + eventClass.getName()
                + "' that takes in a document parameter");
      }
      return (KualiDocumentEvent) usableConstructor.newInstance(paramList.toArray());
    } catch (SecurityException e) {
      throw new ConfigurationException(potentialErrorMessage, e);
    } catch (IllegalArgumentException e) {
      throw new ConfigurationException(potentialErrorMessage, e);
    } catch (InstantiationException e) {
      throw new ConfigurationException(potentialErrorMessage, e);
    } catch (IllegalAccessException e) {
      throw new ConfigurationException(potentialErrorMessage, e);
    } catch (InvocationTargetException e) {
      throw new ConfigurationException(potentialErrorMessage, e);
    }
  }
 @Override
 public Map<String, String> getInquiryParameters(
     Object dataObject, List<String> keys, String propertyName) {
   Map<String, String> inquiryParameters = new HashMap<String, String>();
   Class<?> objectClass = ObjectUtils.materializeClassForProxiedObject(dataObject);
   org.kuali.rice.krad.bo.DataObjectRelationship relationship =
       dataObjectMetaDataService.getDataObjectRelationship(
           dataObject, objectClass, propertyName, "", true, false, true);
   for (String keyName : keys) {
     String keyConversion = keyName;
     if (relationship != null) {
       keyConversion = relationship.getParentAttributeForChildAttribute(keyName);
     } else if (PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName)) {
       String nestedAttributePrefix = KRADUtils.getNestedAttributePrefix(propertyName);
       keyConversion = nestedAttributePrefix + "." + keyName;
     }
     inquiryParameters.put(keyConversion, keyName);
   }
   return inquiryParameters;
 }
  /**
   * Invoked to request an inquiry view for a data object class
   *
   * <p>Checks if the data object is externalizable and we need to redirect to the appropriate
   * inquiry URL, else continues with the inquiry view display
   *
   * <p>Data object class name and values for a primary or alternate key set must be sent in the
   * request
   *
   * <p>Invokes the inquirable to perform the query for the data object record, if not found an
   * exception will be thrown. If found the object is set on the form and then the view is rendered
   */
  @RequestMapping(params = "methodToCall=start")
  @Override
  public ModelAndView start(
      @ModelAttribute("KualiForm") UifFormBase form,
      BindingResult result,
      HttpServletRequest request,
      HttpServletResponse response) {
    InquiryForm inquiryForm = (InquiryForm) form;

    // if request is not a redirect, determine if we need to redirect for an externalizable object
    // inquiry
    if (!inquiryForm.isRedirectedInquiry()) {
      Class inquiryObjectClass = null;
      try {
        inquiryObjectClass = Class.forName(inquiryForm.getDataObjectClassName());
      } catch (ClassNotFoundException e) {
        throw new RiceRuntimeException(
            "Unable to get class for name: " + inquiryForm.getDataObjectClassName());
      }

      ModuleService responsibleModuleService =
          KRADServiceLocatorWeb.getKualiModuleService()
              .getResponsibleModuleService(inquiryObjectClass);
      if (responsibleModuleService != null
          && responsibleModuleService.isExternalizable(inquiryObjectClass)) {
        String inquiryUrl =
            responsibleModuleService.getExternalizableDataObjectInquiryUrl(
                inquiryObjectClass,
                KRADUtils.convertRequestMapToProperties(request.getParameterMap()));

        Properties redirectUrlProps = new Properties();
        redirectUrlProps.put(UifParameters.REDIRECTED_INQUIRY, "true");

        // clear current form from session
        GlobalVariables.getUifFormManager().removeSessionForm(form);

        return performRedirect(form, inquiryUrl, redirectUrlProps);
      }
    }

    // initialize data object class in inquirable
    try {
      inquiryForm
          .getInquirable()
          .setDataObjectClass(Class.forName(inquiryForm.getDataObjectClassName()));
    } catch (ClassNotFoundException e) {
      LOG.error(
          "Unable to get new instance for object class: " + inquiryForm.getDataObjectClassName(),
          e);
      throw new RuntimeException(
          "Unable to get new instance for object class: " + inquiryForm.getDataObjectClassName(),
          e);
    }

    // invoke inquirable to retrieve inquiry data object
    Object dataObject =
        inquiryForm
            .getInquirable()
            .retrieveDataObject(KRADUtils.translateRequestParameterMap(request.getParameterMap()));

    inquiryForm.setDataObject(dataObject);

    return super.start(form, result, request, response);
  }
    /**
     * 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);
    }
  /**
   * Builds the incident report model and view from the request that threw the exception
   *
   * @param request - the request
   * @param response - the response
   * @param handler - the current handler when the exception occurred
   * @param ex - the exception
   * @return the incident report model and view
   * @see
   *     org.springframework.web.servlet.HandlerExceptionResolver#resolveException(javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
   */
  @Override
  public ModelAndView resolveException(
      HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    LOG.error("The following error was caught by the UifHandlerExceptionResolver : ", ex);

    // log exception
    LOG.error(ex.getMessage(), ex);

    String incidentDocId = request.getParameter(KRADConstants.DOCUMENT_DOCUMENT_NUMBER);
    String incidentViewId = "";

    UifFormBase form = (UifFormBase) request.getAttribute(UifConstants.REQUEST_FORM);
    if (form instanceof DocumentFormBase) {
      if (((DocumentFormBase) form).getDocument() != null) {
        incidentDocId = ((DocumentFormBase) form).getDocument().getDocumentNumber();
      }
      incidentViewId = ((DocumentFormBase) form).getViewId();
    }

    if (GlobalVariables.getUifFormManager() != null) {
      GlobalVariables.getUifFormManager().removeSessionForm(form);
    }

    UserSession userSession =
        (UserSession) request.getSession().getAttribute(KRADConstants.USER_SESSION_KEY);
    IncidentReportForm incidentReportForm = new IncidentReportForm();
    incidentReportForm.setSessionId(request.getSession().getId());

    // Set the post url map to the incident report controller and not
    // the one the exception occurred on
    String postUrl = request.getRequestURL().toString();
    postUrl = postUrl.substring(0, postUrl.lastIndexOf("/")) + "/incidentReport";
    incidentReportForm.setFormPostUrl(postUrl);

    incidentReportForm.setException(ex);
    incidentReportForm.setIncidentDocId(incidentDocId);
    incidentReportForm.setIncidentViewId(incidentViewId);
    incidentReportForm.setController(handler.getClass().toString());

    if (userSession != null) {
      incidentReportForm.setUserId(userSession.getPrincipalId());
      incidentReportForm.setUserName(userSession.getPrincipalName());
      incidentReportForm.setUserEmail(userSession.getPerson().getEmailAddress());
    }

    incidentReportForm.setDevMode(!KRADUtils.isProductionEnvironment());
    incidentReportForm.setViewId("Uif-IncidentReportView");

    if (form != null) {
      incidentReportForm.setAjaxRequest(form.isAjaxRequest());
    } else {
      String ajaxRequestParm = request.getParameter(UifParameters.AJAX_REQUEST);
      if (StringUtils.isNotBlank(ajaxRequestParm)) {
        incidentReportForm.setAjaxRequest(Boolean.parseBoolean(ajaxRequestParm));
      }
    }

    // Set the view object
    incidentReportForm.setView(getViewService().getViewById("Uif-IncidentReportView"));

    // Set the ajax return type
    incidentReportForm.setAjaxReturnType(UifConstants.AjaxReturnTypes.UPDATEVIEW.getKey());

    ModelAndView modelAndView = getModelAndViewService().getModelAndView(incidentReportForm, "");
    try {
      getModelAndViewService().prepareView(request, modelAndView);
    } catch (Exception e) {
      LOG.error("An error stopped the incident form from loading", e);
    }

    return modelAndView;
  }