gt:         Protocol protocol = document.getProtocol();
context: /*
   * Kuali Coeus, a comprehensive research administration system for higher education.
   * 
   * Copyright 2005-2016 Kuali, Inc.
   * 
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Affero General Public License as
   * published by the Free Software Foundation, either version 3 of the
   * License, or (at your option) any later version.
   * 
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Affero General Public License for more details.
   * 
   * You should have received a copy of the GNU Affero General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package org.kuali.kra.irb.actions;
  
  import org.apache.commons.lang3.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.kuali.coeus.common.notification.impl.bo.NotificationTypeRecipient;
  import org.kuali.coeus.common.questionnaire.framework.answer.AnswerHeader;
  import org.kuali.coeus.common.questionnaire.framework.answer.ModuleQuestionnaireBean;
  import org.kuali.kra.committee.bo.Committee;
  import org.kuali.kra.committee.service.CommitteeService;
  import org.kuali.kra.infrastructure.Constants;
  import org.kuali.kra.infrastructure.TaskName;
  import org.kuali.kra.irb.Protocol;
  import org.kuali.kra.irb.ProtocolDocument;
  import org.kuali.kra.irb.ProtocolForm;
  import org.kuali.kra.irb.actions.abandon.ProtocolAbandonService;
  import org.kuali.kra.irb.actions.amendrenew.CreateAmendmentEvent;
  import org.kuali.kra.irb.actions.amendrenew.CreateRenewalEvent;
  import org.kuali.kra.irb.actions.amendrenew.ProtocolAmendRenewService;
  import org.kuali.kra.irb.actions.amendrenew.ProtocolAmendmentBean;
  import org.kuali.kra.irb.actions.approve.ProtocolApproveBean;
  import org.kuali.kra.irb.actions.approve.ProtocolApproveEvent;
  import org.kuali.kra.irb.actions.approve.ProtocolApproveService;
  import org.kuali.kra.irb.actions.assignagenda.ProtocolAssignToAgendaBean;
  import org.kuali.kra.irb.actions.assignagenda.ProtocolAssignToAgendaEvent;
  import org.kuali.kra.irb.actions.assignagenda.ProtocolAssignToAgendaService;
  import org.kuali.kra.irb.actions.assigncmtsched.ProtocolAssignCmtSchedBean;
  import org.kuali.kra.irb.actions.assigncmtsched.ProtocolAssignCmtSchedService;
  import org.kuali.kra.irb.actions.assignreviewers.ProtocolAssignReviewersBean;
  import org.kuali.kra.irb.actions.assignreviewers.ProtocolAssignReviewersEvent;
  import org.kuali.kra.irb.actions.assignreviewers.ProtocolAssignReviewersService;
  import org.kuali.kra.irb.actions.correction.AdminCorrectionBean;
  import org.kuali.kra.irb.actions.correction.ProtocolAdminCorrectionEvent;
  import org.kuali.kra.irb.actions.correspondence.ProtocolActionsCorrespondence;
  import org.kuali.kra.irb.actions.decision.CommitteeDecision;
  import org.kuali.kra.irb.actions.decision.CommitteeDecisionEvent;
  import org.kuali.kra.irb.actions.decision.CommitteeDecisionService;
  import org.kuali.kra.irb.actions.expeditedapprove.ProtocolExpeditedApproveBean;
  import org.kuali.kra.irb.actions.expeditedapprove.ProtocolExpeditedApproveEvent;
  import org.kuali.kra.irb.actions.genericactions.ProtocolGenericActionBean;
  import org.kuali.kra.irb.actions.genericactions.ProtocolGenericActionEvent;
  import org.kuali.kra.irb.actions.genericactions.ProtocolGenericActionService;
  import org.kuali.kra.irb.actions.grantexemption.ProtocolGrantExemptionBean;
  import org.kuali.kra.irb.actions.grantexemption.ProtocolGrantExemptionEvent;
  import org.kuali.kra.irb.actions.grantexemption.ProtocolGrantExemptionService;
  import org.kuali.kra.irb.actions.noreview.ProtocolReviewNotRequiredBean;
  import org.kuali.kra.irb.actions.noreview.ProtocolReviewNotRequiredEvent;
  import org.kuali.kra.irb.actions.noreview.ProtocolReviewNotRequiredService;
  import org.kuali.kra.irb.actions.notification.*;
  import org.kuali.kra.irb.actions.notifycommittee.ProtocolNotifyCommitteeBean;
  import org.kuali.kra.irb.actions.notifycommittee.ProtocolNotifyCommitteeService;
  import org.kuali.kra.irb.actions.notifyirb.ProtocolNotifyIrbService;
  import org.kuali.kra.irb.actions.request.ProtocolRequestBean;
  import org.kuali.kra.irb.actions.request.ProtocolRequestEvent;
  import org.kuali.kra.irb.actions.request.ProtocolRequestRule;
  import org.kuali.kra.irb.actions.request.ProtocolRequestService;
  import org.kuali.kra.irb.actions.submit.*;
  import org.kuali.kra.irb.actions.withdraw.ProtocolWithdrawService;
  import org.kuali.kra.irb.auth.GenericProtocolAuthorizer;
  import org.kuali.kra.irb.auth.ProtocolTask;
  import org.kuali.kra.irb.correspondence.ProtocolCorrespondence;
  import org.kuali.kra.irb.infrastructure.IrbConstants;
  import org.kuali.kra.irb.notification.IRBNotificationContext;
  import org.kuali.kra.irb.notification.IRBNotificationRenderer;
  import org.kuali.kra.irb.notification.IRBProtocolNotification;
  import org.kuali.kra.irb.onlinereview.ProtocolOnlineReview;
  import org.kuali.kra.irb.questionnaire.ProtocolQuestionnaireAuditRule;
  import org.kuali.kra.protocol.ProtocolBase;
  import org.kuali.kra.protocol.ProtocolFormBase;
  import org.kuali.kra.protocol.actions.ProtocolActionBean;
  import org.kuali.kra.protocol.actions.ProtocolActionRequestServiceImpl;
  import org.kuali.kra.protocol.actions.ProtocolActionTypeBase;
  import org.kuali.kra.protocol.actions.correspondence.ProtocolActionsCorrespondenceBase;
  import org.kuali.kra.protocol.actions.submit.ProtocolSubmissionBase;
  import org.kuali.kra.protocol.auth.ProtocolTaskBase;
  import org.kuali.kra.protocol.notification.ProtocolNotification;
  import org.kuali.kra.protocol.notification.ProtocolNotificationContextBase;
  import org.kuali.kra.protocol.notification.ProtocolNotificationRequestBeanBase;
  import org.kuali.kra.protocol.questionnaire.ProtocolQuestionnaireAuditRuleBase;
  import org.kuali.rice.kns.document.authorization.DocumentAuthorizerBase;
  import org.kuali.rice.kns.util.WebUtils;
  import org.kuali.rice.krad.util.GlobalVariables;
  import org.kuali.rice.krad.util.ObjectUtils;
  import org.springframework.util.CollectionUtils;
  
  import java.sql.Timestamp;
  import java.util.*;
  
  public class IrbProtocolActionRequestServiceImpl extends ProtocolActionRequestServiceImpl implements IrbProtocolActionRequestService {
      private static final Log LOG = LogFactory.getLog(IrbProtocolActionRequestServiceImpl.class);
  
      private ProtocolAssignToAgendaService protocolAssignToAgendaService;
      private ProtocolAssignCmtSchedService protocolAssignCmtSchedService;
      private ProtocolApproveService protocolApproveService;
      private ProtocolSubmitActionService protocolSubmitActionService;
      private ProtocolAmendRenewService protocolAmendRenewService;
      private ProtocolWithdrawService protocolWithdrawService;
      private ProtocolRequestService protocolRequestService;
      private ProtocolGenericActionService protocolGenericActionService;
      private ProtocolGrantExemptionService protocolGrantExemptionService;
      private CommitteeDecisionService committeeDecisionService;
      private ProtocolAbandonService protocolAbandonService;
      private ProtocolNotifyIrbService protocolNotifyIrbService;
      private ProtocolNotifyCommitteeService protocolNotifyCommitteeService;
      private CommitteeService committeeService;
      private ProtocolReviewNotRequiredService protocolReviewNotRequiredService;
      private ProtocolAssignReviewersService protocolAssignReviewersService;
      private ProtocolActionService protocolActionService;
      
      private static final String ACTION_NAME_RESPONSE_APPROVAL = "Response Approval";
      private static final String ACTION_NAME_CLOSE_ENROLLMENT = "Close Enrollment";
      private static final String ACTION_NAME_DEFER = "Defer";
      private static final String ACTION_NAME_GRANT_EXEMPTION = "Grant Exemption";
      private static final String ACTION_NAME_CLOSE = "Close";
      private static final String ACTION_NAME_IRB_ACKNOWLEDGEMENT = "IRB Acknowledgement";
      private static final String ACTION_NAME_DATA_ANALYSIS_ONLY = "Permit Data Analysis Only";
      private static final String ACTION_NAME_REOPEN_ENROLLMENT = "Re-open Enrollment";
      private static final String ACTION_NAME_SUSPEND_BY_DSMB = "Suspend by DSMB";
      private static final String ACTION_NAME_MANAGE_REVIEW_COMMENTS = "Manage Review Comments";
      private static final String ACTION_NAME_NOTIFY_IRB = "Notify IRB";
      private static final String ACTION_NAME_NOTIFY_COMMITTEE = "Notify Committee";
      
      private static final String FORWARD_TO_HOLDING_PAGE = "holdingPage";
      
      // map to decide the followup action page to open.  "value" part is the action tab "title"
      private static Map<String, String> motionTypeMap = new HashMap<String, String>() {
          {
              put("1", "Approve Action");
              put("2", "Disapprove");
              put("3", "Return for Specific Minor Revisions");
              put("4", "Return for Substantive Revisions Required");
          }
      };
  
      protected static List <String> requestSubmissionTypes = Arrays.asList(new String[] {ProtocolSubmissionType.REQUEST_FOR_SUSPENSION,
                                                                                          ProtocolSubmissionType.REQUEST_FOR_TERMINATION,
                                                                                          ProtocolSubmissionType.REQUEST_TO_CLOSE,
                                                                                          ProtocolSubmissionType.REQUEST_TO_CLOSE_ENROLLMENT,
                                                                                          ProtocolSubmissionType.REQUEST_TO_REOPEN_ENROLLMENT,
                                                                                          ProtocolSubmissionType.REQUEST_FOR_DATA_ANALYSIS_ONLY});
  
      @Override
      public boolean isExpeditedApprovalAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolExpeditedApproveBean expeditedActionBean = (ProtocolExpeditedApproveBean) ((ActionHelper) protocolForm.getActionHelper()).getProtocolExpeditedApprovalBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.EXPEDITE_APPROVAL, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolExpeditedApproveEvent(document, expeditedActionBean));
          }
          return requestAuthorized;
      }
  
      @Override
      public boolean isFullApprovalAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolApproveBean protocolApproveBean = (ProtocolApproveBean) protocolForm.getActionHelper().getProtocolFullApprovalBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.APPROVE_PROTOCOL, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolApproveEvent(document, protocolApproveBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isCreateRenewalAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          boolean requestAuthorized = false;
          String renewalSummary = protocolForm.getActionHelper().getRenewalSummary();
          if (hasPermission(TaskName.CREATE_PROTOCOL_RENEWAL, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new CreateRenewalEvent(document, Constants.PROTOCOL_CREATE_RENEWAL_SUMMARY_KEY, renewalSummary));
          }
          return requestAuthorized;
      }
  
      @Override
      public boolean isAssignToAgendaAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          boolean requestAuthorized = false;
          ProtocolAssignToAgendaBean actionBean = (ProtocolAssignToAgendaBean) protocolForm.getActionHelper().getAssignToAgendaBean();
          if (!hasDocumentStateChanged(protocolForm)) {
              if (hasPermission(TaskName.ASSIGN_TO_AGENDA, (Protocol) document.getProtocol())) {
                  requestAuthorized = applyRules(new ProtocolAssignToAgendaEvent(document, actionBean));
              }
          } else {
              updateDocumentStatusChangedMessage();
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isCreateAmendmentAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolAmendmentBean protocolAmendmentBean = (ProtocolAmendmentBean) protocolForm.getActionHelper().getProtocolAmendmentBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.CREATE_PROTOCOL_AMMENDMENT, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new CreateAmendmentEvent(document, Constants.PROTOCOL_CREATE_AMENDMENT_KEY, protocolAmendmentBean));
          }
          return requestAuthorized;
      }
  
      @Override
      public boolean isCreateRenewalWithAmendmentAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolAmendmentBean protocolAmendmentBean = (ProtocolAmendmentBean) protocolForm.getActionHelper().getProtocolRenewAmendmentBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.CREATE_PROTOCOL_RENEWAL, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new CreateAmendmentEvent(document, Constants.PROTOCOL_CREATE_RENEWAL_WITH_AMENDMENT_KEY, protocolAmendmentBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isWithdrawProtocolAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          boolean requestAuthorized = false;
          if (!hasDocumentStateChanged(protocolForm)) {
              requestAuthorized = hasPermission(TaskName.PROTOCOL_WITHDRAW, (Protocol) document.getProtocol());
          } else {
              updateDocumentStatusChangedMessage();
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isResponseApprovalAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolApproveBean actionBean = ((ActionHelper) protocolForm.getActionHelper()).getProtocolResponseApprovalBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.RESPONSE_APPROVAL, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolApproveEvent(document, actionBean));
          }
          return requestAuthorized;
      }
      /**
  
       * @see org.kuali.kra.irb.actions.IrbProtocolActionRequestService#isRequestActionAuthorized(org.kuali.kra.irb.ProtocolForm, java.lang.String)
       */
      public boolean isRequestActionAuthorized(ProtocolForm protocolForm, String taskName) {
          boolean requestAuthorized = false;
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          if (StringUtils.isNotBlank(taskName)) {
              requestAuthorized = hasPermission(taskName, (Protocol) document.getProtocol());
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isCloseProtocolAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolCloseBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.CLOSE_PROTOCOL, protocolForm, actionBean);
      }
      
      @Override
      public boolean isCloseEnrollmentAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolCloseEnrollmentBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.CLOSE_ENROLLMENT_PROTOCOL, protocolForm, actionBean);
      }
      
      private boolean isGenericProtocolActionAuthorized(String genericActionName, ProtocolForm protocolForm, ProtocolGenericActionBean actionBean) {
          boolean requestAuthorized = false;
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          if (hasGenericPermission(genericActionName, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolGenericActionEvent(document, actionBean));
          }
          return requestAuthorized;
      }
  
      @Override
      public boolean isDeferProtocolAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolDeferBean();
          boolean requestAuthorized = false;
          if (!hasDocumentStateChanged(protocolForm)) {
              if(hasPermission(TaskName.DEFER_PROTOCOL, (Protocol) document.getProtocol())) {
                  requestAuthorized = applyRules(new ProtocolGenericActionEvent(document, actionBean));
              }
          } else {
              updateDocumentStatusChangedMessage();
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isDisapproveProtocolAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolDisapproveBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.DISAPPROVE_PROTOCOL, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolGenericActionEvent(document, actionBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isExpireProtocolAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolExpireBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.EXPIRE_PROTOCOL, protocolForm, actionBean);
      }
      
      @Override
      public boolean isGrantExemptionAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolGrantExemptionBean actionBean = ((ActionHelper) protocolForm.getActionHelper()).getProtocolGrantExemptionBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.GRANT_EXEMPTION, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolGrantExemptionEvent(document, actionBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isIrbAcknowledgementAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolIrbAcknowledgementBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.IRB_ACKNOWLEDGEMENT, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolGenericActionEvent(document, actionBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isPermitDataAnalysisAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolPermitDataAnalysisBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.PERMIT_DATA_ANALYSIS, protocolForm, actionBean);
      }
      
      @Override
      public boolean isReopenEnrollmentAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolReopenEnrollmentBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.REOPEN_PROTOCOL, protocolForm, actionBean);
      }
      
      @Override
      public boolean isReturnForSMRAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolSMRBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.RETURN_FOR_SMR, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolGenericActionEvent(document, actionBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isReturnForSRRAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolSRRBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.RETURN_FOR_SRR, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolGenericActionEvent(document, actionBean));
          }
          return requestAuthorized;
      }
  
      @Override
      public boolean isReturnToPIAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolReturnToPIBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.RETURN_TO_PI_PROTOCOL, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolGenericActionEvent(document, actionBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isSuspendAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolSuspendBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.SUSPEND_PROTOCOL, protocolForm, actionBean);
      }
  
      @Override
      public boolean isSuspendByDsmbAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolSuspendByDsmbBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.SUSPEND_PROTOCOL_BY_DSMB, protocolForm, actionBean);
      }
      
      @Override
      public boolean isTerminateAuthorized(ProtocolForm protocolForm) {
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolTerminateBean();
          return isGenericProtocolActionAuthorized(GenericProtocolAuthorizer.TERMINATE_PROTOCOL, protocolForm, actionBean);
      }
      
      @Override
      public boolean isManageCommentsAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          boolean requestAuthorized = false;
          if (!hasDocumentStateChanged(protocolForm)) {
              requestAuthorized = hasPermission(TaskName.PROTOCOL_MANAGE_REVIEW_COMMENTS, (Protocol) document.getProtocol());
          } else {
              updateDocumentStatusChangedMessage();
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isOpenProtocolForAdminCorrectionAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          boolean requestAuthorized = false;
          AdminCorrectionBean actionBean = (AdminCorrectionBean) protocolForm.getActionHelper().getProtocolAdminCorrectionBean();
          if (!hasDocumentStateChanged(protocolForm)) {
              if (hasPermission(TaskName.PROTOCOL_ADMIN_CORRECTION, (Protocol) document.getProtocol())) {
                  requestAuthorized = applyRules(new ProtocolAdminCorrectionEvent(document, actionBean));
              }
          } else {
              updateDocumentStatusChangedMessage();
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isSubmitCommitteeDecisionAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          boolean requestAuthorized = false;
          CommitteeDecision actionBean = (CommitteeDecision) protocolForm.getActionHelper().getCommitteeDecision();
          if (!hasDocumentStateChanged(protocolForm)) {
              requestAuthorized = applyRules(new CommitteeDecisionEvent(document, actionBean));
          } else {
              updateDocumentStatusChangedMessage();
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isAbandonAuthorized(ProtocolForm protocolForm) {
          boolean requestAuthorized = false;
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          requestAuthorized = hasPermission(TaskName.ABANDON_PROTOCOL, (Protocol) document.getProtocol());
          return requestAuthorized;
      }
      
      @Override
      public boolean isProtocolReviewNotRequiredAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolReviewNotRequiredBean actionBean = ((ActionHelper) protocolForm.getActionHelper()).getProtocolReviewNotRequiredBean();
          boolean requestAuthorized = false;
          if (hasPermission(TaskName.PROTOCOL_REVIEW_NOT_REQUIRED, (Protocol) document.getProtocol())) {
              requestAuthorized = applyRules(new ProtocolReviewNotRequiredEvent(document, actionBean));
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isAssignReviewersAuthorized(ProtocolForm protocolForm) {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          boolean requestAuthorized = false;
          ProtocolAssignReviewersBean actionBean = protocolForm.getActionHelper().getProtocolAssignReviewersBean();
          if (!hasDocumentStateChanged(protocolForm)) {
              if (hasPermission(TaskName.ASSIGN_REVIEWERS, (Protocol) document.getProtocol())) {
                  requestAuthorized = applyRules(new ProtocolAssignReviewersEvent(document, actionBean));
              }
          } else {
              updateDocumentStatusChangedMessage();
          }
          return requestAuthorized;
      }
      
      @Override
      public boolean isWithdrawRequestActionAuthorized(ProtocolForm protocolForm) {
          return hasPermission(TaskName.PROTOCOL_WITHDRAW_SUBMISSION, (Protocol) protocolForm.getProtocolDocument().getProtocol());
      }
      
      @Override
      @SuppressWarnings("deprecation")
      public void grantExpeditedApproval(ProtocolForm protocolForm) throws Exception {
          // set the task name to prevent entered data from being overwritten (in case of user errors) due to bean refresh in the action helper's prepare view 
          protocolForm.getActionHelper().setCurrentTask(TaskName.EXPEDITE_APPROVAL);
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolExpeditedApproveBean expeditedActionBean = (ProtocolExpeditedApproveBean) ((ActionHelper) protocolForm.getActionHelper()).getProtocolExpeditedApprovalBean();
          
          if (expeditedActionBean.isAssignToAgenda()) {
              ProtocolAssignCmtSchedBean cmtAssignBean = protocolForm.getActionHelper().getAssignCmtSchedBean();
              cmtAssignBean.setScheduleId(expeditedActionBean.getScheduleId());
              boolean alreadyAssignedToAgenda = getProtocolAssignToAgendaService().isAssignedToAgenda(document.getProtocol());
              // call the appropriate schedule assingment service based on whether the protocol was already assigned to agenda 
              if(alreadyAssignedToAgenda) {
                  if(cmtAssignBean.scheduleHasChanged()) {
                      getProtocolAssignCmtSchedService().assignToCommitteeAndSchedulePostAgendaAssignment(
                          protocolForm.getProtocolDocument().getProtocol(), cmtAssignBean);
                  }
              }
              else {
                  getProtocolAssignCmtSchedService().assignToCommitteeAndSchedule(protocolForm.getProtocolDocument().getProtocol(), cmtAssignBean);
                  ProtocolAssignToAgendaBean agendaBean = (ProtocolAssignToAgendaBean) protocolForm.getActionHelper().getAssignToAgendaBean();
                  agendaBean.setScheduleDate(getProtocolAssignToAgendaService().getAssignedScheduleDate(protocolForm.getProtocolDocument().getProtocol()));
                  agendaBean.setActionDate(expeditedActionBean.getActionDate());
              }  
              
              // assign to agenda only if not already assigned or if a different schedule has been selected
              if(!alreadyAssignedToAgenda || cmtAssignBean.scheduleHasChanged()) {
                  getProtocolAssignToAgendaService().assignToAgenda(protocolForm.getProtocolDocument().getProtocol(), expeditedActionBean);
                  recordProtocolActionSuccess("Assign to Agenda");
                  generateActionCorrespondence(ProtocolActionType.ASSIGN_TO_AGENDA, protocolForm.getProtocolDocument().getProtocol());
              }
          }
          saveReviewComments(protocolForm, expeditedActionBean.getReviewCommentsBean());
          getProtocolApproveService().grantExpeditedApproval(protocolForm.getProtocolDocument().getProtocol(), expeditedActionBean);
          generateActionCorrespondence(ProtocolActionType.EXPEDITE_APPROVAL, protocolForm.getProtocolDocument().getProtocol());
          recordProtocolActionSuccess("Expedited Approval");
          protocolForm.getTabStates().put(":" + WebUtils.generateTabKey("Assign to Agenda"), "OPEN");
          
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(), ProtocolActionType.EXPEDITE_APPROVAL, "Expedited Approval Granted");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          if (protocolForm.getActionHelper().getProtocolCorrespondence() != null) {
              GlobalVariables.getUserSession().addObject("approvalComplCorrespondence", GlobalVariables.getUserSession().retrieveObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY));
              // temporarily remove this key which is generated by super.approve
              GlobalVariables.getUserSession().removeObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY);
          } else {
              IRBNotificationRenderer renderer = new IRBNotificationRenderer(document.getProtocol());
              IRBNotificationContext context = new IRBNotificationContext(document.getProtocol(), ProtocolActionType.EXPEDITE_APPROVAL, "Expedite Approved", renderer);
              getNotificationService().sendNotificationAndPersist(context, new IRBProtocolNotification(), document.getProtocol());                     
          }
      }
      
      @Override
      @SuppressWarnings("deprecation")
      public void grantFullApproval(ProtocolForm protocolForm) throws Exception {
          ProtocolApproveBean protocolApproveBean = (ProtocolApproveBean) protocolForm.getActionHelper().getProtocolFullApprovalBean();
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          saveReviewComments(protocolForm, protocolApproveBean.getReviewCommentsBean());
          getProtocolApproveService().grantFullApproval((Protocol) document.getProtocol(), protocolApproveBean);
          generateActionCorrespondence(ProtocolActionType.APPROVED, protocolForm.getProtocolDocument().getProtocol());
          recordProtocolActionSuccess("Full Approval");
          protocolForm.getProtocolHelper().prepareView();
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(), ProtocolActionType.APPROVED, "Approved");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          if (protocolForm.getActionHelper().getProtocolCorrespondence() != null) {
              GlobalVariables.getUserSession().addObject("approvalComplCorrespondence",GlobalVariables.getUserSession().retrieveObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY));
              // temporarily remove this key which is generated by super.approve
              GlobalVariables.getUserSession().removeObject(DocumentAuthorizerBase.USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY);
          } else {
              IRBNotificationRenderer renderer = new IRBNotificationRenderer(document.getProtocol());
              IRBNotificationContext context = new IRBNotificationContext(document.getProtocol(), ProtocolActionType.APPROVED, "Approved", renderer);
              getNotificationService().sendNotificationAndPersist(context, new IRBProtocolNotification(), document.getProtocol());                     
          }
      }
      
      @Override
      @SuppressWarnings({ "unchecked", "rawtypes" })
      public boolean submitForReviewAndPromptToNotifyUser(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument protocolDocument = (ProtocolDocument) protocolForm.getProtocolDocument();
          Protocol protocol = (Protocol) protocolDocument.getProtocol();
          ProtocolSubmitAction submitAction = (ProtocolSubmitAction) protocolForm.getActionHelper().getProtocolSubmitAction();
          
          getProtocolSubmitActionService().submitToIrbForReview(protocol, submitAction);
          protocolForm.getActionHelper().getAssignCmtSchedBean().init();
          generateActionCorrespondence(ProtocolActionType.SUBMIT_TO_IRB, protocolForm.getProtocolDocument().getProtocol());
          
          AssignReviewerNotificationRenderer renderer1 = new AssignReviewerNotificationRenderer((Protocol) protocolForm.getProtocolDocument().getProtocol(), "added");
          List<ProtocolNotificationRequestBean> addReviewerNotificationBeans = getNotificationRequestBeans((List) submitAction.getReviewers(),ProtocolReviewerBean.CREATE);
          if (!CollectionUtils.isEmpty(addReviewerNotificationBeans)) {
              ProtocolNotificationRequestBean notificationBean1 = addReviewerNotificationBeans.get(0);
              IRBNotificationContext context1 = new IRBNotificationContext((Protocol) notificationBean1.getProtocol(),
                      (ProtocolOnlineReview) notificationBean1.getProtocolOnlineReview(), notificationBean1.getActionType(),
                      notificationBean1.getDescription(), renderer1);             
              getNotificationService().sendNotificationAndPersist(context1, new IRBProtocolNotification(), protocol); 
              
          }
          ProtocolNotificationRequestBean notificationBean2 = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(), ProtocolActionType.SUBMIT_TO_IRB_NOTIFICATION, "Submit");
          IRBNotificationRenderer renderer2 = new IRBNotificationRenderer((Protocol) notificationBean2.getProtocol());
          IRBNotificationContext context2 = new IRBNotificationContext(protocol, notificationBean2.getActionType(), notificationBean2.getDescription(), renderer2);
          
          if (protocolForm.getNotificationHelper().getPromptUserForNotificationEditor(context2)) {
              context2.setForwardName(FORWARD_TO_HOLDING_PAGE);
              protocolForm.getNotificationHelper().initializeDefaultValues(context2);
              return true;
          } else {             
              getNotificationService().sendNotificationAndPersist(context2, new IRBProtocolNotification(), protocol);             
              return false;
          }
      }
      
      @Override
      public String createRenewal(ProtocolForm protocolForm) throws Exception {
          String newDocId = getProtocolAmendRenewService().createRenewal(protocolForm.getProtocolDocument(), protocolForm.getActionHelper().getRenewalSummary());
          generateActionCorrespondence(ProtocolActionType.RENEWAL_CREATED, protocolForm.getProtocolDocument().getProtocol());
          refreshAfterProtocolAction(protocolForm, newDocId, ACTION_NAME_RENEWAL_WITHOUT_AMENDMENT, true);
          // Form fields copy needed to support modifyAmendmentSections
          protocolForm.getActionHelper().getProtocolAmendmentBean().setSummary(protocolForm.getActionHelper().getRenewalSummary());
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(), ProtocolActionType.RENEWAL_CREATED_NOTIFICATION, "Renewal Created");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
      
      @Override
      public String assignToAgenda(ProtocolForm protocolForm) throws Exception {
          ProtocolAssignToAgendaBean actionBean = (ProtocolAssignToAgendaBean) protocolForm.getActionHelper().getAssignToAgendaBean();
          saveReviewComments(protocolForm, actionBean.getReviewCommentsBean());
          getProtocolAssignToAgendaService().assignToAgenda(protocolForm.getProtocolDocument().getProtocol(), actionBean);
          generateActionCorrespondence(ProtocolActionType.ASSIGN_TO_AGENDA, protocolForm.getProtocolDocument().getProtocol());
          recordProtocolActionSuccess(ACTION_NAME_ASSIGN_TO_AGENDA);
          
          Protocol protocol = (Protocol) protocolForm.getProtocolDocument().getProtocol();
          org.kuali.kra.irb.actions.ProtocolAction lastAction = (org.kuali.kra.irb.actions.ProtocolAction) protocolForm.getProtocolDocument().getProtocol().getLastProtocolAction();
          ProtocolActionType lastActionType = (ProtocolActionType) lastAction.getProtocolActionType();
          String description = lastActionType.getDescription();
  
          IRBNotificationRenderer renderer = new IRBNotificationRenderer(protocol);
          IRBNotificationContext context = new IRBNotificationContext(protocol, ProtocolActionType.ASSIGN_TO_AGENDA, description, renderer);
          
          if (protocolForm.getNotificationHelper().getPromptUserForNotificationEditor(context)) {
              protocolForm.getNotificationHelper().initializeDefaultValues(context);
              return IrbConstants.PROTOCOL_NOTIFICATION_EDITOR;
          } else {
              getNotificationService().sendNotificationAndPersist(context, new IRBProtocolNotification(), protocol);
              return Constants.MAPPING_BASIC;
          }
      }
      
      @Override
      public String createAmendment(ProtocolForm protocolForm) throws Exception {
          String newDocId = getProtocolAmendRenewService().createAmendment(protocolForm.getProtocolDocument(),
                  protocolForm.getActionHelper().getProtocolAmendmentBean());
          generateActionCorrespondence(ProtocolActionType.AMENDMENT_CREATED, protocolForm.getProtocolDocument().getProtocol());
          refreshAfterProtocolAction(protocolForm, newDocId, ACTION_NAME_AMENDMENT, true);
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(), ProtocolActionType.AMENDMENT_CREATED_NOTIFICATION, "Amendment Created");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
      
      @Override
      public String createRenewalWithAmendment(ProtocolForm protocolForm) throws Exception {
          String newDocId = getProtocolAmendRenewService().createRenewalWithAmendment(protocolForm.getProtocolDocument(),
                  protocolForm.getActionHelper().getProtocolRenewAmendmentBean());
          generateActionCorrespondence(ProtocolActionType.RENEWAL_WITH_AMENDMENT_CREATED, protocolForm.getProtocolDocument().getProtocol());
          refreshAfterProtocolAction(protocolForm, newDocId, ACTION_NAME_RENEWAL_WITH_AMENDMENT, true);
          // Form fields copy needed to support modifyAmendmentSections
          protocolForm.getActionHelper().setProtocolAmendmentBean(protocolForm.getActionHelper().getProtocolRenewAmendmentBean());
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(), ProtocolActionType.RENEWAL_WITH_AMENDMENT_CREATED, "Renewal With Amendment Created");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
      
      @Override
      public String withdrawProtocol(ProtocolForm protocolForm) throws Exception {
          ProtocolBase previousProtocol = protocolForm.getProtocolDocument().getProtocol();
          boolean isVersion = ProtocolStatus.IN_PROGRESS.equals(previousProtocol.getProtocolStatusCode()) || 
          ProtocolStatus.SUBMITTED_TO_IRB.equals(previousProtocol.getProtocolStatusCode());
          ProtocolDocument pd = (ProtocolDocument) getProtocolWithdrawService().withdraw(protocolForm.getProtocolDocument().getProtocol(),
                  protocolForm.getActionHelper().getProtocolWithdrawBean());
          Protocol protocol = pd.getProtocol();
          generateActionCorrespondence(ProtocolActionType.WITHDRAWN, protocol);
          refreshAfterProtocolAction(protocolForm, pd.getDocumentNumber(), ACTION_NAME_WITHDRAW, false);
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocol, ProtocolActionType.WITHDRAWN, "Withdrawn");
          ProtocolCorrespondence protocolCorrespondence = (ProtocolCorrespondence)getProtocolCorrespondence(protocol, IrbConstants.PROTOCOL_TAB, notificationBean, false);
          protocolForm.getActionHelper().setProtocolCorrespondence(protocolCorrespondence);
          if(isVersion) {
              ProtocolNotificationContextBase context = getProtocolNotificationContextHook(notificationBean, protocolForm);
              ProtocolBase notificationProtocol = null;
              if(protocolCorrespondence != null) {
                  getProtocolActionCorrespondenceGenerationService().attachProtocolCorrespondence(previousProtocol, protocolCorrespondence.getCorrespondence(), 
                          protocolCorrespondence.getProtoCorrespTypeCode());
                  notificationProtocol = previousProtocol;
              }else {
                  notificationProtocol = protocol;
              }
              getNotificationService().sendNotificationAndPersist(context, getProtocolNotificationInstanceHook(), notificationProtocol);
          }
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
      
      @Override
      public String grantResponseApproval(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument document = (ProtocolDocument) protocolForm.getProtocolDocument();
          ProtocolApproveBean actionBean = ((ActionHelper) protocolForm.getActionHelper()).getProtocolResponseApprovalBean();
          saveReviewComments(protocolForm, actionBean.getReviewCommentsBean());
          getProtocolApproveService().grantResponseApproval(document.getProtocol(), actionBean);
          generateActionCorrespondence(ProtocolActionType.RESPONSE_APPROVAL, protocolForm.getProtocolDocument().getProtocol());
          recordProtocolActionSuccess(ACTION_NAME_RESPONSE_APPROVAL);
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(document.getProtocol(), ProtocolActionType.RESPONSE_APPROVAL, "Response Approval");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
      
      @Override
      public String performRequestAction(ProtocolForm protocolForm, String taskName) throws Exception {
          ProtocolDocument document = protocolForm.getProtocolDocument();
          protocolForm.getActionHelper().preSaveSubmissionQuestionnaires();
          ProtocolRequestAction requestAction = ProtocolRequestAction.valueOfTaskName(taskName);
          ProtocolRequestBean requestBean = getProtocolRequestBean(protocolForm, taskName);
          if (requestBean != null) {
              boolean valid = applyRules(new ProtocolRequestEvent<ProtocolRequestRule>(document, requestAction.getErrorPath(), requestBean));
              List<AnswerHeader> answerHeaders = requestBean.getQuestionnaireHelper().getAnswerHeaders();
              valid &= isMandatoryQuestionnaireComplete(answerHeaders, "actionHelper." + requestAction.getBeanName() + ".datavalidation");
              if (valid) {
                  getProtocolRequestService().submitRequest(protocolForm.getProtocolDocument().getProtocol(), requestBean);            
                  
                  //Assign to Committee and Schedule sub-panel Committee drop down needs to reflect the Committee value just selected
                  protocolForm.getProtocolDocument().getProtocol().refreshReferenceObject("protocolSubmissions");
                  ProtocolAssignCmtSchedBean cmtAssignBean = protocolForm.getActionHelper().getAssignCmtSchedBean();
                  cmtAssignBean.setCommitteeId(requestBean.getCommitteeId());
                  cmtAssignBean.setScheduleId("");
                  cmtAssignBean.prepareView();
  
                  generateActionCorrespondence(requestBean.getProtocolActionTypeCode(), protocolForm.getProtocolDocument().getProtocol());
                  recordProtocolActionSuccess(requestAction.getActionName());
                  return sendRequestNotification(protocolForm, requestBean.getProtocolActionTypeCode(), requestBean.getReason(), IrbConstants.PROTOCOL_ACTIONS_TAB);
              }
          }
          return Constants.MAPPING_BASIC;
      }
      
      @Override
      public String withdrawRequestAction(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument document = protocolForm.getProtocolDocument();
          ProtocolRequestAction requestAction = ProtocolRequestAction.valueOfTaskName(TaskName.PROTOCOL_WITHDRAW_SUBMISSION);
          ProtocolRequestBean requestBean = getProtocolRequestBean(protocolForm, TaskName.PROTOCOL_WITHDRAW_SUBMISSION);
          if (requestBean != null) {
              boolean valid = applyRules(new ProtocolRequestEvent<ProtocolRequestRule>(document, requestAction.getErrorPath(), requestBean));
              if (valid) {
                  // find recently submitted action request and complete it
                  List<ProtocolSubmissionBase> submissions = document.getProtocol().getProtocolSubmissions();
                  ProtocolSubmissionBase submission = null;
                  for (ProtocolSubmissionBase sub: submissions) {
                      if (requestSubmissionTypes.contains(sub.getSubmissionTypeCode())) {
                          submission = sub;
                      }
                  }
                  if (submission != null) {
                      submission.setSubmissionStatusCode(ProtocolSubmissionStatus.WITHDRAWN);
                      ProtocolAction protocolAction = new ProtocolAction(document.getProtocol(), null, ProtocolActionType.WITHDRAW_SUBMISSION);
                      protocolAction.setComments(requestBean.getReason());
                      protocolAction.setActionDate(new Timestamp(Calendar.getInstance().getTimeInMillis()));
                      protocolAction.setSubmissionIdFk(submission.getSubmissionId());
                      protocolAction.setSubmissionNumber(submission.getSubmissionNumber());
                      document.getProtocol().getProtocolActions().add(protocolAction);
                      getProtocolActionService().updateProtocolStatus(protocolAction, document.getProtocol());
                      getBusinessObjectService().save(submission);
                      recordProtocolActionSuccess(requestAction.getActionName());
                      return sendRequestNotification(protocolForm, requestBean.getProtocolActionTypeCode(), requestBean.getReason(), IrbConstants.PROTOCOL_ACTIONS_TAB);
                  }
              }
          }
          return Constants.MAPPING_BASIC;
      }
      
      @Override
      public String closeProtocol(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument document = protocolForm.getProtocolDocument();
          Protocol protocol = document.getProtocol();
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolCloseBean();
          saveReviewComments(protocolForm, actionBean.getReviewCommentsBean());
          getProtocolGenericActionService().close(protocol, actionBean);
          generateActionCorrespondence(ProtocolActionType.CLOSED_ADMINISTRATIVELY_CLOSED, protocolForm.getProtocolDocument().getProtocol());
          recordProtocolActionSuccess(ACTION_NAME_CLOSE);
          ProtocolNotificationRequestBean notificationBean = null;
          if (ProtocolStatus.CLOSED_ADMINISTRATIVELY.equals(protocol.getProtocolStatus())) {
              notificationBean = new ProtocolNotificationRequestBean(protocol, ProtocolActionType.CLOSED_ADMINISTRATIVELY_CLOSED, "Closed By Administrator");
          } else {
              notificationBean = new ProtocolNotificationRequestBean(protocol, ProtocolActionType.CLOSED_ADMINISTRATIVELY_CLOSED, "Closed By Investigator");
          }
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
      
      @Override
      public String closeEnrollment(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument document = protocolForm.getProtocolDocument();
          Protocol protocol = document.getProtocol();
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolCloseEnrollmentBean();
          saveReviewComments(protocolForm, actionBean.getReviewCommentsBean());
          getProtocolGenericActionService().closeEnrollment(protocol, actionBean);
          generateActionCorrespondence(ProtocolActionType.CLOSED_FOR_ENROLLMENT, protocolForm.getProtocolDocument().getProtocol());
          recordProtocolActionSuccess(ACTION_NAME_CLOSE_ENROLLMENT);
          return Constants.MAPPING_BASIC;
      }
      
      @Override
      public String deferProtocol(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument document = protocolForm.getProtocolDocument();
          Protocol protocol = document.getProtocol();
          ProtocolGenericActionBean actionBean = protocolForm.getActionHelper().getProtocolDeferBean();
          saveReviewComments(protocolForm, actionBean.getReviewCommentsBean());
          getProtocolGenericActionService().defer(protocol, actionBean);
          generateActionCorrespondence(ProtocolActionType.DEFERRED, protocolForm.getProtocolDocument().getProtocol());
          ProtocolDocument newDocument = getProtocolGenericActionService().getDeferredVersionedDocument(protocol);
          refreshAfterProtocolAction(protocolForm, newDocument.getDocumentNumber(), ACTION_NAME_DEFER, false);
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(),ProtocolActionType.DEFERRED, "Deferred");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
  
      @Override
      public String disapproveProtocol(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument document = protocolForm.getProtocolDocument();
          Protocol protocol = document.getProtocol();
          ProtocolGenericActionBean actionBean = (ProtocolGenericActionBean) protocolForm.getActionHelper().getProtocolDisapproveBean();
          saveReviewComments(protocolForm, actionBean.getReviewCommentsBean());
          getProtocolGenericActionService().disapprove(protocol, actionBean);
          generateActionCorrespondence(ProtocolActionType.DISAPPROVED, protocolForm.getProtocolDocument().getProtocol());
          recordProtocolActionSuccess(ACTION_NAME_DISAPPROVE);
          ProtocolNotificationRequestBean notificationBean = new ProtocolNotificationRequestBean(protocolForm.getProtocolDocument().getProtocol(), ProtocolActionType.DISAPPROVED, "Disapproved");
          protocolForm.getActionHelper().setProtocolCorrespondence(getProtocolCorrespondence(protocolForm, IrbConstants.PROTOCOL_TAB, notificationBean, false));
          return getRedirectPathAfterProtocolAction(protocolForm, notificationBean, IrbConstants.PROTOCOL_TAB);
      }
      
      @Override
      public String expireProtocol(ProtocolForm protocolForm) throws Exception {
          ProtocolDocument document = protocolForm.getProtocolDocument();
  