public ModelAndView save(
      @ModelAttribute("KualiForm") DocumentFormBase form,
      BindingResult result,
      HttpServletRequest request,
      HttpServletResponse response,
      Class<? extends DocumentEventBase> eventClazz)
      throws Exception {
    ProposalDevelopmentDocumentForm pdForm = (ProposalDevelopmentDocumentForm) form;
    ProposalDevelopmentDocument proposalDevelopmentDocument =
        (ProposalDevelopmentDocument) pdForm.getDocument();
    proposalDevelopmentService.initializeUnitOrganizationLocation(proposalDevelopmentDocument);
    proposalDevelopmentService.initializeProposalSiteNumbers(proposalDevelopmentDocument);

    saveAnswerHeaders(pdForm, request.getParameter(UifParameters.PAGE_ID));

    if (eventClazz == null) {
      getTransactionalDocumentControllerService().save(form);
    } else {
      performCustomSave(proposalDevelopmentDocument, SaveDocumentSpecialReviewEvent.class);
    }

    populateAdHocRecipients(pdForm.getProposalDevelopmentDocument());

    String pageId = form.getActionParamaterValue(UifParameters.NAVIGATE_TO_PAGE_ID);
    final ModelAndView view;
    if (StringUtils.isNotBlank(pageId)
        && getGlobalVariableService().getMessageMap().hasNoErrors()) {
      form.setDirtyForm(false);
      view = getModelAndViewService().getModelAndView(form, pageId);
    } else {
      view = getModelAndViewService().getModelAndView(form);
    }

    if (pdForm.getProposalDevelopmentDocument().getDevelopmentProposal() != null
        && pdForm.getProposalDevelopmentDocument().getDevelopmentProposal().getPropSpecialReviews()
            != null) {
      pdForm
          .getProposalDevelopmentDocument()
          .getDevelopmentProposal()
          .getPropSpecialReviews()
          .stream()
          .filter(specialReview -> !specialReview.isLinkedToProtocol())
          .forEach(
              specialReview ->
                  pdForm.getSpecialReviewHelper().prepareProtocolLinkViewFields(specialReview));
    }
    getProjectPublisher()
        .publishProject(
            getPropDevProjectRetrievalService()
                .retrieveProject(
                    pdForm
                        .getProposalDevelopmentDocument()
                        .getDevelopmentProposal()
                        .getProposalNumber()));

    return view;
  }
  /** Verify the document can be edited in addition to the view */
  @Override
  public boolean canEditView(View view, ViewModel model) {
    DocumentFormBase documentForm = (DocumentFormBase) model;

    return super.canEditView(view, model) && canEdit(documentForm.getDocument());
  }
  @RequestMapping(method = RequestMethod.POST, params = "methodToCall=addAlertLine")
  public ModelAndView addAlertLine(
      @ModelAttribute("KualiForm") DocumentFormBase formBase,
      BindingResult result,
      HttpServletRequest request,
      HttpServletResponse response) {
    String selectedCollectionPath =
        formBase.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
    if (StringUtils.isBlank(selectedCollectionPath)) {
      throw new RuntimeException(
          "Selected collection was not set for add line action, cannot add new line");
    }
    CollectionGroup collectionGroup =
        formBase.getPostedView().getViewIndex().getCollectionGroupByPath(selectedCollectionPath);
    String addLinePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
    Object addLine = ObjectPropertyUtils.getPropertyValue(formBase, addLinePath);
    ModelAndView modelAndView = super.addLine(formBase, result, request, response);
    List<String> principalIds = new ArrayList<String>();
    MaintenanceDocumentForm maintenanceDocumentForm =
        (MaintenanceDocumentForm) modelAndView.getModel().get("KualiForm");
    OlePersistableBusinessObjectBase olePersistableBusinessObjectBase =
        (OlePersistableBusinessObjectBase)
            maintenanceDocumentForm.getDocument().getNewMaintainableObject().getDataObject();
    AlertBo alertBo = olePersistableBusinessObjectBase.getAlertBoList().get(0);
    olePersistableBusinessObjectBase.getAlertBoList().remove(0);
    if (StringUtils.isBlank(alertBo.getReceivingGroupId())
        && StringUtils.isBlank(alertBo.getReceivingUserId())
        && StringUtils.isBlank(alertBo.getReceivingRoleId())
        && StringUtils.isBlank(alertBo.getReceivingGroupId())
        && StringUtils.isEmpty(alertBo.getReceivingUserName())
        && StringUtils.isEmpty(alertBo.getReceivingRoleName())
        && StringUtils.isEmpty(alertBo.getReceivingGroupName())) {
      GlobalVariables.getMessageMap()
          .putErrorForSectionId("OLE-AlertSection", OLEConstants.SELECT_USER);
      return modelAndView;
    }
    alertBo.setAlertCreateDate(new Date(System.currentTimeMillis()));
    alertBo.setAlertInitiatorId(GlobalVariables.getUserSession().getPrincipalId());
    alertBo.setAlertInitiatorName(
        alertService.getName(GlobalVariables.getUserSession().getPrincipalId()));

    String status = null;
    if (alertBo.getAlertDate() != null) {
      Date alertDate = alertBo.getAlertDate();
      if (alertDate.toString().equals(new Date(System.currentTimeMillis()).toString())) {
        status = "Active";
      } else {
        int dateCompare = alertBo.getAlertDate().compareTo(new Date(System.currentTimeMillis()));
        if (dateCompare > 0) {
          status = "Future";
        } else if (dateCompare < 0) {
          status = "Complete";
        }
      }
    }
    alertBo.setStatus(status);
    alertBo.setAlertStatus(true);
    List<AlertBo> alerts = new ArrayList<AlertBo>();
    if (StringUtils.isNotBlank(alertBo.getReceivingUserId())
        && (alertBo.getReceivingUserName() == null
            || (alertBo.getReceivingUserName() != null
                && alertBo.getReceivingUserName().trim().isEmpty()))) {
      alertBo.setReceivingUserName(alertService.getName(alertBo.getReceivingUserId()));
    }
    if (StringUtils.isBlank(alertBo.getReceivingUserId())
        && (alertBo.getReceivingUserName() != null
            && !alertBo.getReceivingUserName().trim().isEmpty())) {
      alertBo.setReceivingUserId(alertService.getPersonId(alertBo.getReceivingUserName()));
    }
    if (StringUtils.isNotBlank(alertBo.getReceivingUserId())) {
      principalIds.add(alertBo.getReceivingUserId());
    }
    alerts.addAll(alertService.getAlertBo(alertBo, principalIds, false, false));
    principalIds = new ArrayList<String>();

    if (StringUtils.isNotBlank(alertBo.getReceivingGroupId())
        && (alertBo.getReceivingGroupName() == null
            || (alertBo.getReceivingGroupName() != null
                && alertBo.getReceivingGroupName().trim().isEmpty()))) {
      alertBo.setReceivingGroupName(alertService.getGroupName(alertBo.getReceivingGroupId()));
    }
    if (StringUtils.isBlank(alertBo.getReceivingGroupId())
        && (alertBo.getReceivingGroupName() != null
            && !alertBo.getReceivingGroupName().trim().isEmpty())) {
      alertBo.setReceivingGroupId(alertService.getGroupId((alertBo.getReceivingUserName())));
    }

    if (StringUtils.isNotBlank(alertBo.getReceivingGroupId())) {
      List<String> memberIds = groupService.getMemberPrincipalIds(alertBo.getReceivingGroupId());
      principalIds.addAll(memberIds);
    }
    alerts.addAll(alertService.getAlertBo(alertBo, principalIds, false, true));

    principalIds = new ArrayList<String>();

    if (StringUtils.isNotBlank(alertBo.getReceivingRoleId())
        && (alertBo.getReceivingRoleName() == null
            || (alertBo.getReceivingRoleName() != null
                && alertBo.getReceivingRoleName().trim().isEmpty()))) {
      alertBo.setReceivingRoleName(alertService.getRoleName(alertBo.getReceivingRoleId()));
    }
    if (StringUtils.isBlank(alertBo.getReceivingRoleId())
        && (alertBo.getReceivingRoleName() != null
            && !alertBo.getReceivingRoleName().trim().isEmpty())) {
      alertBo.setReceivingRoleId(alertService.getRoleId((alertBo.getReceivingRoleName())));
    }

    if (StringUtils.isNotBlank(alertBo.getReceivingRoleId())) {
      List<String> roleIds = new ArrayList<String>();
      roleIds.add(alertBo.getReceivingRoleId());
      Role role = roleService.getRole(alertBo.getReceivingRoleId());
      Collection collection =
          (Collection)
              roleService.getRoleMemberPrincipalIds(
                  role.getNamespaceCode(), role.getName(), new HashMap<String, String>());
      List<String> memberIds = new ArrayList<String>();
      memberIds.addAll(collection);
      principalIds.addAll(memberIds);
    }

    alerts.addAll(alertService.getAlertBo(alertBo, principalIds, true, false));

    olePersistableBusinessObjectBase.getAlertBoList().addAll(alerts);
    if (StringUtils.isBlank(alertBo.getReceivingUserId())
        && StringUtils.isNotBlank(alertBo.getReceivingGroupId())) {
      olePersistableBusinessObjectBase.getAlertBoList().remove(0);
    }
    if (StringUtils.isNotBlank(alertBo.getReceivingUserId())
        && StringUtils.isNotBlank(alertBo.getReceivingGroupId())) {
      alertBo.setReceivingGroupName(null);
      alertBo.setReceivingGroupId(null);
    }

    return modelAndView;
  }