gt:             currentSequenceNumber = getProtocol().getSequenceNumber();
context: /*
   * Kuali Coeus, a comprehensive research administration system for higher education.
   * 
   * Copyright 2005-2015 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.iacuc.actions;
  
  import java.sql.Date;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.commons.lang3.StringUtils;
  import org.apache.commons.lang3.time.DateUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.kuali.coeus.common.committee.impl.bo.CommitteeBase;
  import org.kuali.coeus.common.committee.impl.bo.CommitteeScheduleBase;
  import org.kuali.coeus.common.committee.impl.lookup.keyvalue.CommitteeIdByUnitValuesFinderService;
  import org.kuali.coeus.common.committee.impl.service.CommitteeScheduleServiceBase;
  import org.kuali.coeus.common.framework.module.CoeusModule;
  import org.kuali.coeus.common.framework.module.CoeusSubModule;
  import org.kuali.coeus.common.framework.auth.task.TaskAuthorizationService;
  import org.kuali.coeus.sys.framework.service.KcServiceLocator;
  import org.kuali.coeus.sys.framework.validation.ErrorReporter;
  import org.kuali.kra.iacuc.IacucProtocol;
  import org.kuali.kra.iacuc.IacucProtocolDocument;
  import org.kuali.kra.iacuc.IacucProtocolVersionService;
  import org.kuali.kra.iacuc.actions.amendrenew.IacucProtocolAmendRenewService;
  import org.kuali.kra.iacuc.actions.amendrenew.IacucProtocolAmendRenewal;
  import org.kuali.kra.iacuc.actions.amendrenew.IacucProtocolAmendmentBean;
  import org.kuali.kra.iacuc.actions.amendrenew.IacucProtocolModule;
  import org.kuali.kra.iacuc.actions.approve.IacucProtocolApproveBean;
  import org.kuali.kra.iacuc.actions.assignCmt.IacucProtocolAssignCmtBean;
  import org.kuali.kra.iacuc.actions.assignagenda.IacucProtocolAssignToAgendaBean;
  import org.kuali.kra.iacuc.actions.correction.IacucAdminCorrectionBean;
  import org.kuali.kra.iacuc.actions.decision.IacucCommitteeDecision;
  import org.kuali.kra.iacuc.actions.decision.IacucCommitteeDecisionService;
  import org.kuali.kra.iacuc.actions.delete.IacucProtocolDeleteBean;
  import org.kuali.kra.iacuc.actions.followup.IacucFollowupActionService;
  import org.kuali.kra.iacuc.actions.genericactions.IacucProtocolGenericActionBean;
  import org.kuali.kra.iacuc.actions.modifysubmission.IacucProtocolModifySubmissionBean;
  import org.kuali.kra.iacuc.actions.noreview.IacucProtocolReviewNotRequiredBean;
  import org.kuali.kra.iacuc.actions.notifycommittee.IacucProtocolNotifyCommitteeBean;
  import org.kuali.kra.iacuc.actions.notifyiacuc.IacucProtocolNotifyIacucBean;
  import org.kuali.kra.iacuc.actions.print.IacucProtocolQuestionnairePrintingService;
  import org.kuali.kra.iacuc.actions.request.IacucProtocolRequestBean;
  import org.kuali.kra.iacuc.actions.reviewcomments.IacucReviewCommentsService;
  import org.kuali.kra.iacuc.actions.submit.IacucProtocolReviewType;
  import org.kuali.kra.iacuc.actions.submit.IacucProtocolSubmissionType;
  import org.kuali.kra.iacuc.actions.submit.IacucProtocolSubmitAction;
  import org.kuali.kra.iacuc.actions.submit.IacucProtocolSubmitActionService;
  import org.kuali.kra.iacuc.actions.table.IacucProtocolTableBean;
  import org.kuali.kra.iacuc.actions.undo.IacucProtocolUndoLastActionBean;
  import org.kuali.kra.iacuc.actions.withdraw.IacucProtocolAdministrativelyIncompleteBean;
  import org.kuali.kra.iacuc.actions.withdraw.IacucProtocolAdministrativelyWithdrawBean;
  import org.kuali.kra.iacuc.actions.withdraw.IacucProtocolWithdrawBean;
  import org.kuali.kra.iacuc.auth.IacucGenericProtocolAuthorizer;
  import org.kuali.kra.iacuc.auth.IacucProtocolTask;
  import org.kuali.kra.iacuc.committee.lookup.keyvalue.IacucCommitteeIdByUnitValuesFinderService;
  import org.kuali.kra.iacuc.committee.service.IacucCommitteeScheduleService;
  import org.kuali.kra.iacuc.correspondence.IacucProtocolCorrespondenceAuthorizationService;
  import org.kuali.kra.iacuc.correspondence.IacucProtocolCorrespondenceType;
  import org.kuali.kra.iacuc.onlinereview.IacucProtocolOnlineReview;
  import org.kuali.kra.iacuc.onlinereview.IacucProtocolOnlineReviewService;
  import org.kuali.kra.iacuc.questionnaire.IacucProtocolModuleQuestionnaireBean;
  import org.kuali.kra.iacuc.questionnaire.IacucSubmissionQuestionnaireHelper;
  import org.kuali.kra.iacuc.summary.IacucProtocolSummary;
  import org.kuali.kra.infrastructure.Constants;
  import org.kuali.kra.infrastructure.KeyConstants;
  import org.kuali.kra.infrastructure.RoleConstants;
  import org.kuali.kra.infrastructure.TaskName;
  import org.kuali.kra.protocol.ProtocolBase;
  import org.kuali.kra.protocol.ProtocolDocumentBase;
  import org.kuali.kra.protocol.ProtocolFormBase;
  import org.kuali.kra.protocol.ProtocolOnlineReviewDocumentBase;
  import org.kuali.kra.protocol.ProtocolVersionService;
  import org.kuali.kra.protocol.actions.ActionHelperBase;
  import org.kuali.kra.protocol.actions.ProtocolActionBean;
  import org.kuali.kra.protocol.actions.ProtocolEditableBean;
  import org.kuali.kra.protocol.actions.ProtocolSubmissionDocBase;
  import org.kuali.kra.protocol.actions.amendrenew.ProtocolAmendRenewModuleBase;
  import org.kuali.kra.protocol.actions.amendrenew.ProtocolAmendRenewService;
  import org.kuali.kra.protocol.actions.amendrenew.ProtocolAmendRenewalBase;
  import org.kuali.kra.protocol.actions.amendrenew.ProtocolAmendmentBean;
  import org.kuali.kra.protocol.actions.approve.ProtocolApproveBean;
  import org.kuali.kra.protocol.actions.assignagenda.ProtocolAssignToAgendaBean;
  import org.kuali.kra.protocol.actions.correction.AdminCorrectionBean;
  import org.kuali.kra.protocol.actions.decision.CommitteeDecision;
  import org.kuali.kra.protocol.actions.decision.CommitteeDecisionService;
  import org.kuali.kra.protocol.actions.decision.CommitteePersonBase;
  import org.kuali.kra.protocol.actions.delete.ProtocolDeleteBean;
  import org.kuali.kra.protocol.actions.followup.FollowupActionService;
  import org.kuali.kra.protocol.actions.noreview.ProtocolReviewNotRequiredBean;
  import org.kuali.kra.protocol.actions.notify.ProtocolActionAttachment;
  import org.kuali.kra.protocol.actions.notifycommittee.ProtocolNotifyCommitteeBean;
  import org.kuali.kra.protocol.actions.print.CorrespondencePrintOption;
  import org.kuali.kra.protocol.actions.print.ProtocolQuestionnairePrintingService;
  import org.kuali.kra.protocol.actions.reviewcomments.ReviewCommentsService;
  import org.kuali.kra.protocol.actions.submit.ProtocolSubmitAction;
  import org.kuali.kra.protocol.actions.submit.ValidProtocolActionActionBase;
  import org.kuali.kra.protocol.actions.undo.UndoLastActionBean;
  import org.kuali.kra.protocol.actions.withdraw.ProtocolAdministrativelyIncompleteBean;
  import org.kuali.kra.protocol.actions.withdraw.ProtocolAdministrativelyWithdrawBean;
  import org.kuali.kra.protocol.actions.withdraw.ProtocolWithdrawBean;
  import org.kuali.kra.protocol.auth.ProtocolTaskBase;
  import org.kuali.kra.protocol.correspondence.CorrespondenceTypeModuleIdConstants;
  import org.kuali.kra.protocol.correspondence.ProtocolCorrespondence;
  import org.kuali.kra.protocol.correspondence.ProtocolCorrespondenceAuthorizationService;
  import org.kuali.kra.protocol.onlinereview.ProtocolOnlineReviewService;
  import org.kuali.kra.protocol.questionnaire.ProtocolModuleQuestionnaireBeanBase;
  import org.kuali.kra.protocol.questionnaire.ProtocolSubmissionQuestionnaireHelper;
  import org.kuali.coeus.common.questionnaire.framework.answer.ModuleQuestionnaireBean;
  import org.kuali.rice.core.api.util.KeyValue;
  import org.kuali.rice.krad.service.BusinessObjectService;
  import org.kuali.rice.krad.util.GlobalVariables;
  import org.kuali.rice.krad.util.ObjectUtils;
  
  /**
   * The form helper class for the ProtocolBase Actions tab.
   */
  public class IacucActionHelper extends ActionHelperBase {
    
      private static final Log LOG = LogFactory.getLog(IacucActionHelper.class);
  
      private static final long serialVersionUID = 777750088765246427L;
      
      /**
       * Each Helper must contain a reference to its document form
       * so that it can access the document.
       */
      private boolean canDeleteIacucProtocol;
      private boolean canDeleteIacucProtocolUnavailable;
      
      private boolean canReviewNotRequired;
      private boolean canReviewNotRequiredUnavailable;
      private boolean canNotifyIacuc = false;
      private boolean canNotifyIacucUnavailable = false;
      private boolean canDesignatedMemberApproval = false;
      private boolean canDesignatedMemberApprovalUnavailable = false;
      private boolean canHold = false;
      private boolean canHoldUnavailable = false;
      private boolean canLiftHold = false;
      private boolean canLiftHoldUnavailable = false;
      private boolean canRequestToLiftHold = false;
      private boolean canRequestToLiftHoldUnavailable = false;
      private boolean canRequestSuspend = false;
      private boolean canRequestSuspendUnavailable = false;
      private boolean canTable = false;
      private boolean canTableUnavailable = false;
      private boolean canIacucAcknowledge = false;
      private boolean canIacucAcknowledgeUnavailable = false;
      private boolean canIacucDeactivate = false;
      private boolean canIacucDeactivateUnavailable = false;
      private boolean canIacucRequestDeactivate = false;
      private boolean canIacucRequestDeactivateUnavailable = false;
      private boolean canAddDeactivateReviewerComments = false;
      private boolean canRemoveFromAgenda = false;
  
      private boolean canAssignCmt = false;
      private boolean canAssignCmtUnavailable = false;
  
      // indicator for whether there is submission questionnaire answer exist.
      // ie, questionnaire has been saved for a request/notify  action
      private boolean submissionQuestionnaireExist;
      // check if there is submission questionnaire to answer
      private boolean toAnswerSubmissionQuestionnaire;
  
      // action beans that are specific to IACUC
      protected IacucProtocolTableBean iacucProtocolTableBean;
      protected IacucProtocolAssignCmtBean protocolAssignCmtBean;
      protected IacucProtocolModifySubmissionBean iacucProtocolModifySubmissionBean;
      protected IacucProtocolNotifyIacucBean iacucProtocolNotifyIacucBean;
      protected IacucProtocolGenericActionBean iacucProtocolDeactivateBean;
      protected IacucProtocolGenericActionBean iacucAcknowledgeBean;
      protected IacucProtocolGenericActionBean iacucProtocolHoldBean;
      protected IacucProtocolGenericActionBean iacucProtocolLiftHoldBean;
      protected IacucProtocolGenericActionBean iacucProtocolRemoveFromAgendaBean;
      protected ProtocolReviewNotRequiredBean iacucProtocolReviewNotRequiredBean;
      
      protected IacucProtocolRequestBean iacucProtocolDeactivateRequestBean;
      protected IacucProtocolRequestBean iacucProtocolLiftHoldRequestBean;
      protected IacucProtocolRequestBean iacucProtocolSuspendRequestBean;
      protected IacucProtocolRequestBean iacucProtocolWithdrawSubmissionBean;
      
      protected boolean canCreateContinuation = false;
      protected boolean canCreateContinuationUnavailable = false;
      protected boolean hasContinuations;
      protected String continuationSummary;
      protected ProtocolAmendmentBean protocolContinuationAmendmentBean;
  
      private List<KeyValue> assignCmtActionCommitteeIdByUnitKeyValues;
      
      private List<KeyValue> modifySubmissionActionCommitteeIdByUnitKeyValues;
  
  
      /**
       * Constructs an ActionHelperBase.
       * @param form the protocol form
       * @throws Exception 
       */
      public IacucActionHelper(ProtocolFormBase form) throws Exception {
          super(form);
          
          protocolAssignCmtBean = new IacucProtocolAssignCmtBean(this);
          iacucProtocolTableBean = new IacucProtocolTableBean(this);
          iacucProtocolModifySubmissionBean = new IacucProtocolModifySubmissionBean(this);
          iacucProtocolNotifyIacucBean = new IacucProtocolNotifyIacucBean(this, "iacucProtocolNotifyIacucBean");
          iacucProtocolDeactivateBean = this.buildProtocolGenericActionBean(IacucProtocolActionType.DEACTIVATED, Constants.IACUC_DEACTIVATE_ACTION_PROPERTY_KEY);
          iacucAcknowledgeBean = new IacucProtocolGenericActionBean(this, "actionHelper.iacucAcknowledgeBean");
          iacucProtocolHoldBean = new IacucProtocolGenericActionBean(this, "actionHelper.iacucProtocolHoldBean");
          iacucProtocolLiftHoldBean = new IacucProtocolGenericActionBean(this, "actionHelper.iacucProtocolLiftHoldBean");
          iacucProtocolDeactivateRequestBean = new IacucProtocolRequestBean(this, IacucProtocolActionType.REQUEST_DEACTIVATE,
                  IacucProtocolSubmissionType.REQUEST_TO_DEACTIVATE, "iacucProtocolDeactivateRequestBean");
          iacucProtocolLiftHoldRequestBean = new IacucProtocolRequestBean(this, IacucProtocolActionType.REQUEST_LIFT_HOLD,
                  IacucProtocolSubmissionType.REQUEST_TO_LIFT_HOLD, "iacucProtocolLiftHoldRequestBean");
          iacucProtocolSuspendRequestBean = new IacucProtocolRequestBean(this, IacucProtocolActionType.IACUC_REQUEST_SUSPEND,
                  IacucProtocolSubmissionType.REQUEST_SUSPEND, "iacucProtocolSuspendRequestBean");
          iacucProtocolWithdrawSubmissionBean = new IacucProtocolRequestBean(this, IacucProtocolActionType.IACUC_WITHDRAW_SUBMISSION,
                  IacucProtocolSubmissionType.WITHDRAW_SUBMISSION, "iacucWithdrawProtocolSubmissionRequestBean");
          iacucProtocolRemoveFromAgendaBean = new IacucProtocolGenericActionBean(this, "actionHelper.iacucProtocolRemoveFromAgendaBean");
          iacucProtocolReviewNotRequiredBean = new IacucProtocolReviewNotRequiredBean(this);
          initIacucSpecificActionBeanTaskMap();
     }
      
  
      /**
       * Initializes the mapping between the task names and the beans.  This is used to get the bean associated to the task name passed in from the tag file.
       * The reason TaskName (a text code) is used and ProtocolActionType (a number code) is not is because not every task is mapped to a ProtocolActionType.
       */
      private void initIacucSpecificActionBeanTaskMap() {
          actionBeanTaskMap.put(TaskName.IACUC_MODIFY_PROTOCOL_SUBMISSION, iacucProtocolModifySubmissionBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_TABLE, iacucProtocolTableBean);
          actionBeanTaskMap.put(TaskName.IACUC_ASSIGN_TO_COMMITTEE, protocolAssignCmtBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_TABLE, iacucProtocolTableBean);
          actionBeanTaskMap.put(TaskName.IACUC_NOTIFY_IACUC, iacucProtocolNotifyIacucBean);
          actionBeanTaskMap.put(TaskName.IACUC_ACKNOWLEDGEMENT, iacucAcknowledgeBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_DEACTIVATE, iacucProtocolDeactivateBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_REQUEST_DEACTIVATE, iacucProtocolDeactivateRequestBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_REQUEST_LIFT_HOLD, iacucProtocolLiftHoldRequestBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_REQUEST_SUSPENSION, iacucProtocolSuspendRequestBean);
          actionBeanTaskMap.put(TaskName.IACUC_WITHDRAW_SUBMISSION, iacucProtocolWithdrawSubmissionBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_HOLD, iacucProtocolHoldBean);
          actionBeanTaskMap.put(TaskName.IACUC_PROTOCOL_LIFT_HOLD, iacucProtocolLiftHoldBean);
          actionBeanTaskMap.put(TaskName.REMOVE_FROM_AGENDA, iacucProtocolRemoveFromAgendaBean);
          actionBeanTaskMap.put(TaskName.CREATE_PROTOCOL_CONTINUATION, protocolContinuationAmendmentBean);
      }
  
          
      public IacucProtocolAssignCmtBean getProtocolAssignCmtBean() {
          return protocolAssignCmtBean;
      }
  
      public void setProtocolAssignCmtBean(IacucProtocolAssignCmtBean protocolAssignCmtBean) {
          this.protocolAssignCmtBean = protocolAssignCmtBean;
      }
  
      public IacucProtocolModifySubmissionBean getIacucProtocolModifySubmissionBean() {
          return iacucProtocolModifySubmissionBean;
      }
  
      public void setIacucProtocolModifySubmissionBean(IacucProtocolModifySubmissionBean iacucProtocolModifySubmissionBean) {
          this.iacucProtocolModifySubmissionBean = iacucProtocolModifySubmissionBean;
      }
      
      public IacucProtocolTableBean getIacucProtocolTableBean() {
          return iacucProtocolTableBean;
      }
  
      public void setIacucProtocolTableBean(IacucProtocolTableBean iacucProtocolTableBean) {
          this.iacucProtocolTableBean = iacucProtocolTableBean;
      }
  
  
      /**
       * Builds an approval date, defaulting to the approval date from the protocol.
       * 
       * If the approval date from the protocol is null, or if the protocol is new or a renewal, then if the committee has scheduled a meeting to approve the 
       * protocol, sets to the scheduled approval date; otherwise, sets to the current date.
       * 
       * @param protocol
       * @return a non-null approval date
       */
      @Override
      protected Date buildApprovalDate(ProtocolBase protocol) {
          Date approvalDate = protocol.getApprovalDate();
          
          if (approvalDate == null || protocol.isNew() || protocol.isRenewal() || ((IacucProtocol)protocol).isContinuation()) {
              CommitteeScheduleBase committeeSchedule = protocol.getProtocolSubmission().getCommitteeSchedule();
              if (committeeSchedule != null) {
                  approvalDate = committeeSchedule.getScheduledDate();
              } else {
                  approvalDate = new Date(System.currentTimeMillis());
              }
          }
          
          return approvalDate;
      }
      
      /**
       * Builds an expiration date, defaulting to the expiration date from the protocol.  
       * 
       * If the expiration date from the protocol is null, or if the protocol is new or a renewal, creates an expiration date exactly one year ahead and one day 
       * less than the approval date.
       * 
       * @param protocol
       * @param approvalDate
       * @return a non-null expiration date
       */
      @Override
      protected Date buildExpirationDate(ProtocolBase protocol, Date approvalDate) {
          Date expirationDate = protocol.getExpirationDate();
          
          if (expirationDate == null || protocol.isNew() || protocol.isRenewal() || ((IacucProtocol)protocol).isContinuation()) {
              java.util.Date newExpirationDate = DateUtils.addYears(approvalDate, getDefaultExpirationDateDifference());
              newExpirationDate = DateUtils.addDays(newExpirationDate, -1);
              expirationDate = org.kuali.coeus.sys.framework.util.DateUtils.convertToSqlDate(newExpirationDate);
          }
          
          return expirationDate;
      }
  
    
      public void prepareView() throws Exception {
          super.prepareView();
          prepareModifySubmissionActionView(); 
         
          // IACUC-specific actions
          prepareAssignCommitteeActionView();
          canNotifyIacuc = hasPermission(TaskName.IACUC_NOTIFY_IACUC);
          canNotifyIacucUnavailable = hasPermission(TaskName.IACUC_NOTIFY_IACUC_UNAVAILABLE);
          
          canHold = hasPermission(TaskName.IACUC_PROTOCOL_HOLD);
          canHoldUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_HOLD_UNAVAILABLE);
          canLiftHold = hasPermission(TaskName.IACUC_PROTOCOL_LIFT_HOLD);
          canLiftHoldUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_LIFT_HOLD_UNAVAILABLE);
          canRequestToLiftHold = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_LIFT_HOLD);
          canRequestToLiftHoldUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_LIFT_HOLD_UNAVAILABLE);
          canRequestSuspend = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_SUSPENSION);
          canRequestSuspendUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_SUSPENSION_UNAVAILABLE);
          canIacucAcknowledge = hasPermission(TaskName.IACUC_ACKNOWLEDGEMENT);
          canIacucAcknowledgeUnavailable = hasPermission(TaskName.IACUC_ACKNOWLEDGEMENT_UNAVAILABLE);
          canIacucDeactivate = hasPermission(TaskName.IACUC_PROTOCOL_DEACTIVATE);
          canIacucDeactivateUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_DEACTIVATE_UNAVAILABLE);
          canIacucRequestDeactivate = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_DEACTIVATE);
          canIacucRequestDeactivateUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_DEACTIVATE_UNAVAILABLE);
  
          canWithdrawSubmission = hasPermission(TaskName.IACUC_WITHDRAW_SUBMISSION);
          canWithdrawSubmissionUnavailable = hasPermission(TaskName.IACUC_WITHDRAW_SUBMISSION_UNAVAILABLE);
  
          canDesignatedMemberApproval = hasPermission(TaskName.IACUC_PROTOCOL_DESIGNATED_MEMBER_APPROVAL);
          canDesignatedMemberApprovalUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_DESIGNATED_MEMBER_APPROVAL_UNAVAILABLE);
          canLiftHold = hasPermission(TaskName.IACUC_PROTOCOL_LIFT_HOLD);
          canLiftHoldUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_LIFT_HOLD_UNAVAILABLE);
          canRequestToLiftHold = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_LIFT_HOLD);
          canRequestToLiftHoldUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_REQUEST_LIFT_HOLD_UNAVAILABLE);
          canReturnToPI = hasPermission(TaskName.RETURN_TO_PI_PROTOCOL);
          canReturnToPIUnavailable = hasPermission(TaskName.RETURN_TO_PI_PROTOCOL_UNAVAILABLE);
          canReviewNotRequired = hasPermission(TaskName.REVIEW_NOT_REQUIRED_IACUC_PROTOCOL);
          canReviewNotRequiredUnavailable = hasPermission(TaskName.REVIEW_NOT_REQUIRED_IACUC_PROTOCOL_UNAVAILABLE);
          canTable = hasPermission(TaskName.IACUC_PROTOCOL_TABLE);
          canTableUnavailable = hasPermission(TaskName.IACUC_PROTOCOL_TABLE_UNAVAILABLE);
          
          canAddDeactivateReviewerComments = hasDeactivateRequestLastAction();
          
          canRemoveFromAgenda = hasPermission(TaskName.REMOVE_FROM_AGENDA);
          
          canCreateContinuation = hasCreateContinuationPermission();
          canCreateContinuationUnavailable = hasCreateContinuationUnavailablePermission();
          hidePrivateFinalFlagsForPublicCommentsAttachments = checkToHidePrivateFinalFlagsForPublicCommentsAttachments();
  
          initSummaryDetails();
          setAmendmentDetails();
          initFilterDatesView();
          
          if(canSubmitProtocol) {
              canAssignReviewersCmtSel = hasAssignReviewersCmtSel();
          } 
          else {
              canAssignReviewersCmtSel = false;
          }
          
  
      }
   
      
      /**
       * Refreshes the comments for all the beans from the database.  Use sparingly since this will erase non-persisted comments.
       */
      public void prepareCommentsView() {
          super.prepareCommentsView();
          iacucProtocolDeactivateBean.getReviewCommentsBean().setReviewComments(getCopiedReviewComments());
          
          iacucAcknowledgeBean.getReviewCommentsBean().setReviewComments(getCopiedReviewComments());
          iacucProtocolRemoveFromAgendaBean.getReviewCommentsBean().setReviewComments(getCopiedReviewComments());
          iacucProtocolHoldBean.getReviewCommentsBean().setReviewComments(getCopiedReviewComments());
          iacucProtocolLiftHoldBean.getReviewCommentsBean().setReviewComments(getCopiedReviewComments());
      }
  
  
      public static boolean hasAssignCmtSchedPermission(String userId, String protocolNumber) {
          Map<String, String> fieldValues = new HashMap<String, String>();
          fieldValues.put("protocolNumber", protocolNumber);
          BusinessObjectService bos = KcServiceLocator.getService(BusinessObjectService.class);
          IacucProtocol protocol = ((List<IacucProtocol>) bos.findMatching(IacucProtocol.class, fieldValues)).get(0);
          IacucProtocolTask task = new IacucProtocolTask(TaskName.MODIFY_IACUC_PROTOCOL, protocol);
          TaskAuthorizationService tas = KcServiceLocator.getService(TaskAuthorizationService.class);
          return tas.isAuthorized(userId, task);
      }
  
      protected boolean hasFollowupAction(String actionCode) {
          return false;
      }
      
      public IacucProtocolSubmitAction getIacucProtocolSubmitAction() {
          return (IacucProtocolSubmitAction)protocolSubmitAction;
      }
  
      public ProtocolFormBase getProtocolForm() {
          return form;
      }
      
      public IacucProtocol getProtocol() {
          return (IacucProtocol) form.getProtocolDocument().getProtocol();
      }
  
      public IacucProtocolGenericActionBean getIacucProtocolDeactivateBean() {
          return iacucProtocolDeactivateBean;
      }
  
      public void setIacucProtocolDeactivateBean(IacucProtocolGenericActionBean iacucProtocolDeactivateBean) {
          this.iacucProtocolDeactivateBean = iacucProtocolDeactivateBean;
      }
      
      protected ModuleQuestionnaireBean getQuestionnaireBean(String moduleCode, String moduleKey, String subModuleCode, String subModuleKey, boolean finalDoc) {
          return new IacucProtocolModuleQuestionnaireBean(moduleCode, moduleKey, subModuleCode, subModuleKey, finalDoc);
      }
  
  
      public ProtocolActionBean getActionBean(String taskName) {
          return actionBeanTaskMap.get(taskName);
      }
  
      public boolean isCanAbandon() {
          return canAbandon;
      }
  
      public ProtocolCorrespondence getProtocolCorrespondence() {
          return protocolCorrespondence;
      }
  
      public void setProtocolCorrespondence(ProtocolCorrespondence protocolCorrespondence) {
          this.protocolCorrespondence = protocolCorrespondence;
      }
  
      public boolean getIsApproveOpenForFollowup() {
          return hasFollowupAction(IacucProtocolActionType.IACUC_APPROVED);
      }
  
      public boolean getIsDisapproveOpenForFollowup() {
          return hasFollowupAction(IacucProtocolActionType.IACUC_DISAPPROVED);
      }
  
      public boolean getIsReturnForSMROpenForFollowup() {
          return hasFollowupAction(IacucProtocolActionType.IACUC_MINOR_REVISIONS_REQUIRED);
      }
  
      public boolean getIsReturnForSRROpenForFollowup() {
          return hasFollowupAction(IacucProtocolActionType.IACUC_MAJOR_REVISIONS_REQUIRED);
      }
  
      public boolean isOpenForFollowup() {
          return getIsApproveOpenForFollowup() || getIsDisapproveOpenForFollowup() ||
                 getIsReturnForSMROpenForFollowup() || getIsReturnForSRROpenForFollowup();
      }
  
      public boolean isCanDesignatedMemberApproval() {
          return canDesignatedMemberApproval;
      }
  
      public boolean isCanDesignatedMemberApprovalUnavailable() {
          return canDesignatedMemberApprovalUnavailable;
      }
  
      public boolean isCanHold() {
          return canHold;
      }
  
      public boolean isCanHoldUnavailable() {
          return canHoldUnavailable;
      }
  
      public boolean isCanLiftHold() {
          return canLiftHold;
      }
  
      public boolean isCanLiftHoldUnavailable() {
          return canLiftHoldUnavailable;
      }
  
      public boolean isCanRequestToLiftHold() {
          return canRequestToLiftHold;
      }
  
      public boolean isCanRequestToLiftHoldUnavailable() {
          return canRequestToLiftHoldUnavailable;
      }
      
      public boolean isCanRequestSuspend() {
          return canRequestSuspend;
      }
  
      public boolean isCanRequestSuspendUnavailable() {
          return canRequestSuspendUnavailable;
      }
  
      public boolean isCanTable() {
          return canTable;
      }
  
      public boolean isCanTableUnavailable() {
          return canTableUnavailable;
      }
      
      public boolean isCanNotifyIacuc() {
          return canNotifyIacuc;
      }
      
      public boolean isCanNotifyIacucUnavailable() {
          return canNotifyIacucUnavailable;
      }
  
      public boolean isCanDeleteIacucProtocol() {
          return canDeleteIacucProtocol;
      }
      
      public boolean isCanDeleteIacucProtocolUnavailable() {
          return canDeleteIacucProtocolUnavailable;
      }
      
      public boolean isCanReviewNotRequired() {
          return canReviewNotRequired;
      }
      
      public boolean isCanReviewNotRequiredUnavailable() {
          return canReviewNotRequiredUnavailable;
      }
  
      public boolean isCanIacucRequestDeactivate() {
          return canIacucRequestDeactivate;
      }
      
      public boolean isCanIacucRequestDeactivateUnavailable() {
          return canIacucRequestDeactivateUnavailable;
      }
  
      protected String getParameterValue(String parameterName) {
          String result = getParameterService().getParameterValueAsString(IacucProtocolDocument.class, parameterName);
          if (result == null) {
              result = super.getParameterValue(parameterName);
          }
          return result;
      }
  
      protected IacucProtocol getIacucProtocol() {
          return (IacucProtocol)getProtocol();
      }
      
      public boolean getCanAssignCmt() {
          return canAssignCmt;
      }
  
      public void setCanAssignCmt(boolean canAssignCmt) {
          this.canAssignCmt = canAssignCmt;
      }
  
      public boolean getCanAssignCmtUnavailable() {
          return canAssignCmtUnavailable;
      }
  
      public void setCanAssignCmtUnavailable(boolean canAssignCmtUnavailable) {
          this.canAssignCmtUnavailable = canAssignCmtUnavailable;
      }
  
      @Override
      protected IacucProtocolTask createNewAmendRenewDeleteTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.PROTOCOL_AMEND_RENEW_DELETE, (IacucProtocol) protocol);
      }
      
      public boolean isCanWithdrawSubmission() {
          return canWithdrawSubmission;
      }
  
  
      public void setCanWithdrawSubmission(boolean canWithdrawSubmission) {
          this.canWithdrawSubmission = canWithdrawSubmission;
      }
  
  
      public boolean isCanWithdrawSubmissionUnavailable() {
          return canWithdrawSubmissionUnavailable;
      }
  
  
      public void setCanWithdrawSubmissionUnavailable(boolean canWithdrawSubmissionUnavailable) {
          this.canWithdrawSubmissionUnavailable = canWithdrawSubmissionUnavailable;
      }
  
  
      @Override
      protected IacucProtocolTask createNewAmendRenewDeleteUnavailableTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.PROTOCOL_AMEND_RENEW_DELETE_UNAVAILABLE, (IacucProtocol) protocol);
      }
  
      @Override
      protected ProtocolDeleteBean getNewProtocolDeleteBeanInstanceHook(ActionHelperBase actionHelper) {
          return new IacucProtocolDeleteBean((IacucActionHelper)actionHelper);
      }
  
      
      protected Class<? extends ReviewCommentsService> getReviewCommentsServiceClassHook() {
          return IacucReviewCommentsService.class;
      }
      
      protected IacucProtocolGenericActionBean buildProtocolGenericActionBean(String actionTypeCode, String errorPropertyKey) {
          IacucProtocolGenericActionBean bean = new IacucProtocolGenericActionBean(this, errorPropertyKey);
          
          bean.getReviewCommentsBean().setReviewComments(getCopiedReviewComments());
          bean.getReviewCommentsBean().setHideReviewerName(getReviewCommentsService().setHideReviewerName(bean.getReviewCommentsBean().getReviewComments()));            
          IacucProtocolAction protocolAction = (IacucProtocolAction) findProtocolAction(actionTypeCode, getProtocol().getProtocolActions(), getProtocol().getProtocolSubmission());
          if (protocolAction != null) {
              bean.setComments(protocolAction.getComments());
              bean.setActionDate(new Date(protocolAction.getActionDate().getTime()));
          }
          
          return bean;
      }
      
      public ProtocolOnlineReviewService getOnlineReviewService() {
          return KcServiceLocator.getService(IacucProtocolOnlineReviewService.class);
      }
      
      public List<String> getReviewRecommendations() {
          List<String> recommendations = new ArrayList<String>();
          List<ProtocolOnlineReviewDocumentBase> reviewDocs = getOnlineReviewService().getProtocolReviewDocumentsForCurrentSubmission(getProtocol());
          for (ProtocolOnlineReviewDocumentBase doc : reviewDocs) {
              IacucProtocolOnlineReview review = (IacucProtocolOnlineReview) doc.getProtocolOnlineReview();
              if (ObjectUtils.isNotNull(review) && ObjectUtils.isNotNull(review.getDeterminationReviewTypeCode())) {
                  recommendations.add(review.getProtocolReviewer().getFullName() + "--" + getReviewType(review.getDeterminationReviewTypeCode()));
              }
          }
          return recommendations;        
      }
      
      protected String getReviewType(String code) {
          Map<String, String> criteria = new HashMap<String, String>();
          criteria.put("reviewTypeCode", code);
          List<IacucProtocolReviewType> types = (List<IacucProtocolReviewType>) getBusinessObjectService().findMatching(IacucProtocolReviewType.class, criteria);
          return !types.isEmpty() ? types.get(0).getDescription() : "";        
      }
      
      @Override
      protected ProtocolTaskBase createNewAbandonTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.IACUC_ABANDON_PROTOCOL, (IacucProtocol) protocol);
      }
  
      @Override
      protected String getAbandonActionTypeHook() {    
          return IacucProtocolActionType.IACUC_ABANDON;
      }
  
      @Override
      protected String getAbandonPropertyKeyHook() {
          return Constants.PROTOCOL_ABANDON_ACTION_PROPERTY_KEY;
      }
      
      @Override
      protected String getExpireKeyHook() {
          return IacucProtocolActionType.EXPIRED;
      }
      
      @Override
      protected String getTerminateKeyHook() {
          return IacucProtocolActionType.TERMINATED;
      }
      
      @Override 
      protected String getSuspendKeyHook() {
          return IacucProtocolActionType.SUSPENDED;
      }
  
      @Override
      protected ProtocolSubmitAction getNewProtocolSubmitActionInstanceHook(ActionHelperBase actionHelper) {
         return new IacucProtocolSubmitAction((IacucActionHelper) actionHelper);
      }
  
      @Override
      protected ProtocolNotifyCommitteeBean getNewProtocolNotifyCommitteeBeanInstanceHook(ActionHelperBase actionHelper) {
          return new IacucProtocolNotifyCommitteeBean((IacucActionHelper) actionHelper);
      }
  
  
      @Override
      protected ProtocolModuleQuestionnaireBeanBase getNewProtocolModuleQuestionnaireBeanInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolModuleQuestionnaireBean((IacucProtocol)protocol);
      }
  
      @Override
      protected ProtocolTaskBase getModifySubmissionAvailableTaskHook() {
          return new IacucProtocolTask(TaskName.IACUC_MODIFY_PROTOCOL_SUBMISSION, (IacucProtocol) getProtocol());
  
      }
  
      @Override
      protected ProtocolTaskBase getModifySubmissionUnavailableTaskHook() {
          return new IacucProtocolTask(TaskName.IACUC_MODIFY_PROTOCOL_SUBMISSION_UNAVAILABLE, (IacucProtocol) getProtocol());
      }
      
      @Override
      protected ProtocolTaskBase getNewSubmitProtocolTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.SUBMIT_IACUC_PROTOCOL, (IacucProtocol) protocol);
      }
  
      @Override
      protected ProtocolTaskBase getNewSubmitProtocolUnavailableTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.SUBMIT_IACUC_PROTOCOL_UNAVAILABLE, (IacucProtocol) protocol);
      }
      
      @Override
      protected ProtocolTaskBase getNewNotifyCommitteeTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.NOTIFY_COMMITTEE, (IacucProtocol) protocol);
      }
  
      @Override
      protected ProtocolTaskBase getNewNotifyCommitteeUnavailableTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.NOTIFY_COMMITTEE_UNAVAILABLE, (IacucProtocol) protocol);
      }
  
  
      @Override
      protected ProtocolWithdrawBean getNewProtocolWithdrawBeanInstanceHook(ActionHelperBase actionHelper) {
          return new IacucProtocolWithdrawBean((IacucActionHelper) actionHelper);
      }
      
      @Override
      protected ProtocolAdministrativelyWithdrawBean getNewProtocolAdminWithdrawBeanInstanceHook(ActionHelperBase actionHelper) {
          return new IacucProtocolAdministrativelyWithdrawBean((IacucActionHelper) actionHelper);
      }
      
      @Override
      protected ProtocolAdministrativelyIncompleteBean getNewProtocolAdminIncompleteBeanInstanceHook(ActionHelperBase actionHelper) {
          return new IacucProtocolAdministrativelyIncompleteBean((IacucActionHelper) actionHelper);
      }
  
      @Override
      protected ProtocolAmendmentBean getNewProtocolAmendmentBeanInstanceHook(ActionHelperBase actionHelper) {
          return new IacucProtocolAmendmentBean((IacucActionHelper) actionHelper);
      }
      
  
      @Override
      protected ProtocolTaskBase getNewAmendmentProtocolTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.CREATE_IACUC_PROTOCOL_AMENDMENT, (IacucProtocol) protocol);
      }
  
      @Override
      protected ProtocolTaskBase getNewAmendmentProtocolUnavailableTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.CREATE_IACUC_PROTOCOL_AMENDMENT_UNAVAILABLE, (IacucProtocol) protocol);
      }
      
      @Override
      protected ProtocolTaskBase getNewWithdrawProtocolTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.PROTOCOL_WITHDRAW, (IacucProtocol) protocol);
      }
  
      @Override
      protected ProtocolTaskBase getNewWithdrawProtocolUnavailableTaskInstanceHook(ProtocolBase protocol) {
          return new IacucProtocolTask(TaskName.PROTOCOL_WITHDRAW_UNAVAILABLE, (IacucProtocol) protocol);
      }
  
      @Override
      protected ProtocolVersionService getProtocolVersionService() {
          if (this.protocolVersionService == null) {
              this.protocolVersionService = KcServiceLocator.getService(IacucProtocolVersionService.class);
          }
          return this.protocolVersionService;
      }
  
      @Override
      protected String getCoeusModule() {
          return CoeusModule.IACUC_PROTOCOL_MODULE_CODE;
      }
  
      /**
       * Sets up the summary details subpanel.
       * @throws Exception 
       */
      @Override
      public void initSummaryDetails() throws Exception {
          if (currentSequenceNumber == -1) {
              currentSequenceNumber = getProtocol().getSequenceNumber();
          } else if (currentSequenceNumber > getProtocol().getSequenceNumber()) {
  