Java tutorial
/* * 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.protocol; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.kuali.coeus.common.committee.impl.bo.CommitteeMembershipBase; import org.kuali.coeus.common.framework.attachment.AttachmentFile; import org.kuali.coeus.common.framework.custom.attr.CustomAttributeDocument; import org.kuali.coeus.common.framework.version.sequence.owner.SequenceOwner; import org.kuali.coeus.common.notification.impl.bo.KcNotification; import org.kuali.coeus.common.framework.auth.perm.Permissionable; import org.kuali.coeus.sys.framework.model.KcPersistableBusinessObjectBase; import org.kuali.coeus.sys.framework.service.KcServiceLocator; import org.kuali.kra.protocol.auth.UnitAclLoadable; import org.kuali.kra.coi.Disclosurable; import org.kuali.kra.infrastructure.Constants; import org.kuali.coeus.common.framework.krms.KcKrmsContextBo; import org.kuali.kra.protocol.actions.ProtocolActionBase; import org.kuali.kra.protocol.actions.ProtocolStatusBase; import org.kuali.kra.protocol.actions.amendrenew.ProtocolAmendRenewModuleBase; import org.kuali.kra.protocol.actions.amendrenew.ProtocolAmendRenewalBase; import org.kuali.kra.protocol.actions.submit.ProtocolSubmissionBase; import org.kuali.kra.protocol.actions.submit.ProtocolSubmissionStatusBase; import org.kuali.kra.protocol.actions.submit.ProtocolSubmissionTypeBase; import org.kuali.kra.protocol.noteattachment.*; import org.kuali.kra.protocol.onlinereview.ProtocolOnlineReviewBase; import org.kuali.kra.protocol.personnel.ProtocolPersonBase; import org.kuali.kra.protocol.personnel.ProtocolPersonnelService; import org.kuali.kra.protocol.personnel.ProtocolUnitBase; import org.kuali.kra.protocol.protocol.ProtocolTypeBase; import org.kuali.kra.protocol.protocol.funding.ProtocolFundingSourceBase; import org.kuali.kra.protocol.protocol.location.ProtocolLocationBase; import org.kuali.kra.protocol.protocol.location.ProtocolLocationService; import org.kuali.kra.protocol.protocol.reference.ProtocolReferenceBase; import org.kuali.kra.protocol.protocol.research.ProtocolResearchAreaBase; import org.kuali.kra.protocol.specialreview.ProtocolSpecialReviewBase; import org.kuali.kra.protocol.specialreview.ProtocolSpecialReviewExemption; import org.kuali.kra.protocol.summary.*; import org.kuali.coeus.common.questionnaire.framework.answer.Answer; import org.kuali.coeus.common.questionnaire.framework.answer.AnswerHeader; import org.kuali.coeus.common.questionnaire.framework.answer.QuestionnaireAnswerService; import org.kuali.rice.core.api.datetime.DateTimeService; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.krad.service.BusinessObjectService; import org.kuali.rice.krad.service.SequenceAccessorService; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.ObjectUtils; import java.io.Serializable; import java.sql.Date; import java.util.*; import java.util.Map.Entry; public abstract class ProtocolBase extends KcPersistableBusinessObjectBase implements SequenceOwner<ProtocolBase>, Permissionable, UnitAclLoadable, Disclosurable, KcKrmsContextBo { private static final long serialVersionUID = -5556152547067349988L; protected static final CharSequence AMENDMENT_LETTER = "A"; protected static final CharSequence RENEWAL_LETTER = "R"; protected static final String NEXT_ACTION_ID_KEY = "actionId"; private Long protocolId; private String protocolNumber; private Integer sequenceNumber; private boolean active = true; private String protocolTypeCode; private String protocolStatusCode; private String title; private String description; private Date initialSubmissionDate; private Date approvalDate; private Date expirationDate; private Date lastApprovalDate; private String fdaApplicationNumber; private String referenceNumber1; private String referenceNumber2; private String specialReviewIndicator = "Y"; private String keyStudyPersonIndicator; private String fundingSourceIndicator; private String correspondentIndicator; private String referenceIndicator; private String relatedProjectsIndicator; private ProtocolDocumentBase protocolDocument; private ProtocolStatusBase protocolStatus; private ProtocolTypeBase protocolType; private List<ProtocolResearchAreaBase> protocolResearchAreas; private List<ProtocolReferenceBase> protocolReferences; private List<ProtocolLocationBase> protocolLocations; //Is transient, used for lookup select option in UI by KNS private String newDescription; private boolean nonEmployeeFlag; private List<ProtocolFundingSourceBase> protocolFundingSources; private String leadUnitNumber; private String principalInvestigatorId; // lookup field private String keyPerson; private String investigator; private String fundingSource; private String performingOrganizationId; private String researchAreaCode; private String leadUnitName; private List<ProtocolPersonBase> protocolPersons; private List<ProtocolSpecialReviewBase> specialReviews; //these are the m:m attachment protocols that that a protocol has private List<ProtocolAttachmentProtocolBase> attachmentProtocols; private List<ProtocolNotepadBase> notepads; private List<ProtocolActionBase> protocolActions; private List<ProtocolSubmissionBase> protocolSubmissions; private ProtocolSubmissionBase protocolSubmission; private transient List<ProtocolActionBase> sortedActions; /* * There should only be zero or one entry in the protocolAmendRenewals * list. It is because of OJB that a list is used instead of a single item. */ private List<ProtocolAmendRenewalBase> protocolAmendRenewals; private transient boolean correctionMode = false; private transient DateTimeService dateTimeService; private transient SequenceAccessorService sequenceAccessorService; //Used to filter protocol attachments private transient ProtocolAttachmentFilterBase protocolAttachmentFilter; // passed in req param submissionid. used to check if irb ack is needed // this link is from protocosubmission or notify irb message private transient Long notifyIrbSubmissionId; // transient for protocol header combined label private transient String initiatorLastUpdated; private transient String protocolSubmissionStatus; // Custom ProtocolBase lookup fields private transient boolean lookupPendingProtocol; private transient boolean lookupPendingPIActionProtocol; private transient boolean lookupActionAmendRenewProtocol; private transient boolean lookupActionRequestProtocol; private transient boolean lookupProtocolPersonId; private transient boolean mergeAmendment; public String getInitiatorLastUpdated() { return initiatorLastUpdated; } public String getProtocolSubmissionStatus() { return protocolSubmissionStatus; } /** * * Constructs an ProtocolBase BO. */ public ProtocolBase() { super(); sequenceNumber = new Integer(0); protocolResearchAreas = new ArrayList<ProtocolResearchAreaBase>(); protocolReferences = new ArrayList<ProtocolReferenceBase>(); newDescription = getDefaultNewDescription(); protocolStatus = getProtocolStatusNewInstanceHook(); protocolStatusCode = protocolStatus.getProtocolStatusCode(); protocolLocations = new ArrayList<ProtocolLocationBase>(); protocolPersons = new ArrayList<ProtocolPersonBase>(); // set the default protocol type protocolTypeCode = getDefaultProtocolTypeCodeHook(); protocolFundingSources = new ArrayList<ProtocolFundingSourceBase>(); specialReviews = new ArrayList<ProtocolSpecialReviewBase>(); setProtocolActions(new ArrayList<ProtocolActionBase>()); setProtocolSubmissions(new ArrayList<ProtocolSubmissionBase>()); protocolAmendRenewals = new ArrayList<ProtocolAmendRenewalBase>(); // set statuscode default setProtocolStatusCode(getDefaultProtocolStatusCodeHook()); this.refreshReferenceObject(Constants.PROPERTY_PROTOCOL_STATUS); initializeProtocolAttachmentFilter(); } protected abstract ProtocolStatusBase getProtocolStatusNewInstanceHook(); protected abstract String getDefaultProtocolStatusCodeHook(); protected abstract String getDefaultProtocolTypeCodeHook(); public Long getProtocolId() { return protocolId; } public void setProtocolId(Long protocolId) { this.protocolId = protocolId; } public String getProtocolNumber() { return protocolNumber; } public void setProtocolNumber(String protocolNumber) { this.protocolNumber = protocolNumber; } public Integer getSequenceNumber() { return sequenceNumber; } public void setSequenceNumber(Integer sequenceNumber) { this.sequenceNumber = sequenceNumber; } public void setActive(boolean active) { this.active = active; } public boolean isActive() { return active; } public String getProtocolTypeCode() { return protocolTypeCode; } public void setProtocolTypeCode(String protocolTypeCode) { this.protocolTypeCode = protocolTypeCode; } public String getProtocolStatusCode() { return protocolStatusCode; } public void setProtocolStatusCode(String protocolStatusCode) { this.protocolStatusCode = protocolStatusCode; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } /** * Gets the submission date. If the submission date is the last * submission for the protocol. If the protocol has not been submitted, * null is returned. * @return the submission date or null if not yet submitted */ public Date getSubmissionDate() { // TODO : the last one in the list may not be the last one submitted // getProtocolSubmission will get the last one. SO, this method may not needed. // Also, this method only referenced in test once. Date submissionDate = null; if (protocolSubmissions.size() > 0) { // ProtocolSubmissionBase submission = protocolSubmissions.get(protocolSubmissions.size() - 1); // submissionDate = submission.getSubmissionDate(); submissionDate = getProtocolSubmission().getSubmissionDate(); } return submissionDate; } public Date getInitialSubmissionDate() { return initialSubmissionDate; } public void setInitialSubmissionDate(Date initialSubmissionDate) { this.initialSubmissionDate = initialSubmissionDate; } public Date getApprovalDate() { return approvalDate; } public void setApprovalDate(Date approvalDate) { this.approvalDate = approvalDate; } public Date getExpirationDate() { return expirationDate; } public void setExpirationDate(Date expirationDate) { this.expirationDate = expirationDate; } public Date getLastApprovalDate() { return lastApprovalDate; } public void setLastApprovalDate(Date lastApprovalDate) { this.lastApprovalDate = lastApprovalDate; } public String getFdaApplicationNumber() { return fdaApplicationNumber; } public void setFdaApplicationNumber(String fdaApplicationNumber) { this.fdaApplicationNumber = fdaApplicationNumber; } public String getReferenceNumber1() { return referenceNumber1; } public void setReferenceNumber1(String referenceNumber1) { this.referenceNumber1 = referenceNumber1; } public String getReferenceNumber2() { return referenceNumber2; } public void setReferenceNumber2(String referenceNumber2) { this.referenceNumber2 = referenceNumber2; } public String getSpecialReviewIndicator() { return specialReviewIndicator; } public void setSpecialReviewIndicator(String specialReviewIndicator) { this.specialReviewIndicator = specialReviewIndicator; } public String getKeyStudyPersonIndicator() { return keyStudyPersonIndicator; } public void setKeyStudyPersonIndicator(String keyStudyPersonIndicator) { this.keyStudyPersonIndicator = keyStudyPersonIndicator; } public String getFundingSourceIndicator() { return fundingSourceIndicator; } public void setFundingSourceIndicator(String fundingSourceIndicator) { this.fundingSourceIndicator = fundingSourceIndicator; } public String getCorrespondentIndicator() { return correspondentIndicator; } public void setCorrespondentIndicator(String correspondentIndicator) { this.correspondentIndicator = correspondentIndicator; } public String getReferenceIndicator() { return referenceIndicator; } public void setReferenceIndicator(String referenceIndicator) { this.referenceIndicator = referenceIndicator; } public String getRelatedProjectsIndicator() { return relatedProjectsIndicator; } public void setRelatedProjectsIndicator(String relatedProjectsIndicator) { this.relatedProjectsIndicator = relatedProjectsIndicator; } /** * Collects and returns all online reviews for all submissions for this protocol. * @return all online reviews for this protocol */ public List<ProtocolOnlineReviewBase> getProtocolOnlineReviews() { List<ProtocolOnlineReviewBase> reviews = new ArrayList<ProtocolOnlineReviewBase>(); for (ProtocolSubmissionBase submission : getProtocolSubmissions()) { reviews.addAll(submission.getProtocolOnlineReviews()); } return reviews; } public ProtocolStatusBase getProtocolStatus() { return protocolStatus; } public void setProtocolStatus(ProtocolStatusBase protocolStatus) { this.protocolStatus = protocolStatus; } public ProtocolTypeBase getProtocolType() { return protocolType; } public void setProtocolType(ProtocolTypeBase protocolType) { this.protocolType = protocolType; } public String getNewDescription() { return newDescription; } public void setNewDescription(String newDescription) { this.newDescription = newDescription; } public String getDefaultNewDescription() { return "(select)"; } public void setProtocolResearchAreas(List<ProtocolResearchAreaBase> protocolResearchAreas) { this.protocolResearchAreas = protocolResearchAreas; for (ProtocolResearchAreaBase researchArea : protocolResearchAreas) { researchArea.init(this); } } public List<ProtocolResearchAreaBase> getProtocolResearchAreas() { return protocolResearchAreas; } public void addProtocolResearchAreas(ProtocolResearchAreaBase protocolResearchArea) { getProtocolResearchAreas().add(protocolResearchArea); } public ProtocolResearchAreaBase getProtocolResearchAreas(int index) { while (getProtocolResearchAreas().size() <= index) { getProtocolResearchAreas().add(getNewProtocolResearchAreaInstance()); } return getProtocolResearchAreas().get(index); } protected abstract ProtocolResearchAreaBase getNewProtocolResearchAreaInstance(); public void setProtocolReferences(List<ProtocolReferenceBase> protocolReferences) { this.protocolReferences = protocolReferences; for (ProtocolReferenceBase reference : protocolReferences) { reference.init(this); } } public List<ProtocolReferenceBase> getProtocolReferences() { return protocolReferences; } public ProtocolDocumentBase getProtocolDocument() { return protocolDocument; } public void setProtocolDocument(ProtocolDocumentBase protocolDocument) { this.protocolDocument = protocolDocument; } public void setProtocolLocations(List<ProtocolLocationBase> protocolLocations) { this.protocolLocations = protocolLocations; for (ProtocolLocationBase location : protocolLocations) { location.init(this); } } public List<ProtocolLocationBase> getProtocolLocations() { return protocolLocations; } @SuppressWarnings("unchecked") @Override public List buildListOfDeletionAwareLists() { List managedLists = super.buildListOfDeletionAwareLists(); managedLists.add(this.protocolResearchAreas); managedLists.add(this.protocolReferences); managedLists.add(getProtocolFundingSources()); managedLists.add(getProtocolLocations()); managedLists.add(getProtocolAttachmentPersonnel()); managedLists.add(getProtocolUnits()); managedLists.add(getAttachmentProtocols()); managedLists.add(getProtocolPersons()); managedLists.add(getProtocolActions()); managedLists.add(getProtocolSubmissions()); if (getProtocolAmendRenewal() != null) { managedLists.add(getProtocolAmendRenewal().getModules()); } else { // needed to ensure that the OjbCollectionHelper receives constant list size. managedLists.add(new ArrayList<ProtocolAmendRenewModuleBase>()); } managedLists.add(getProtocolAmendRenewals()); List<ProtocolSpecialReviewExemption> specialReviewExemptions = new ArrayList<ProtocolSpecialReviewExemption>(); for (ProtocolSpecialReviewBase specialReview : getSpecialReviews()) { specialReviewExemptions.addAll(specialReview.getSpecialReviewExemptions()); } managedLists.add(specialReviewExemptions); managedLists.add(getSpecialReviews()); managedLists.add(getNotepads()); return managedLists; } /** * This method is to return all attachments for each person. * Purpose of this method is to use the list in buildListOfDeletionAwareLists. * Looks like OJB is not searching beyond the first level. It doesn't delete * from collection under ProtocolPersonBase. * @return List<ProtocolAttachmentPersonnelBase> */ private List<ProtocolAttachmentPersonnelBase> getProtocolAttachmentPersonnel() { List<ProtocolAttachmentPersonnelBase> protocolAttachmentPersonnel = new ArrayList<ProtocolAttachmentPersonnelBase>(); for (ProtocolPersonBase protocolPerson : getProtocolPersons()) { protocolAttachmentPersonnel.addAll(protocolPerson.getAttachmentPersonnels()); } return protocolAttachmentPersonnel; } /** * This method is to return all protocol units for each person. * Purpose of this method is to use the list in buildListOfDeletionAwareLists. * Looks like OJB is not searching beyond the first level. It doesn't delete * from collection under ProtocolPersonBase. * @return List<ProtocolUnitBase> */ private List<ProtocolUnitBase> getProtocolUnits() { List<ProtocolUnitBase> protocolUnits = new ArrayList<ProtocolUnitBase>(); for (ProtocolPersonBase protocolPerson : getProtocolPersons()) { protocolUnits.addAll(protocolPerson.getProtocolUnits()); } return protocolUnits; } /** * This method is to find Principal Investigator from ProtocolPersonBase list * @return ProtocolPersonBase */ public ProtocolPersonBase getPrincipalInvestigator() { return getProtocolPersonnelService().getPrincipalInvestigator(getProtocolPersons()); } public String getPrincipalInvestigatorName() { ProtocolPersonBase pi = getPrincipalInvestigator(); return pi != null ? pi.getFullName() : null; } public ProtocolUnitBase getLeadUnit() { ProtocolUnitBase leadUnit = null; if (getPrincipalInvestigator() != null) { for (ProtocolUnitBase unit : getPrincipalInvestigator().getProtocolUnits()) { if (unit.getLeadUnitFlag()) { leadUnit = unit; } } } return leadUnit; } public String getLeadUnitNumber() { if (StringUtils.isBlank(leadUnitNumber)) { if (getLeadUnit() != null) { setLeadUnitNumber(getLeadUnit().getUnitNumber()); } } return leadUnitNumber; } public void setLeadUnitNumber(String leadUnitNumber) { this.leadUnitNumber = leadUnitNumber; } public String getPrincipalInvestigatorId() { if (StringUtils.isBlank(principalInvestigatorId)) { if (getPrincipalInvestigator() != null) { ProtocolPersonBase principalInvestigator = getPrincipalInvestigator(); if (StringUtils.isNotBlank(principalInvestigator.getPersonId())) { setPrincipalInvestigatorId(principalInvestigator.getPersonId()); } else { if (principalInvestigator.getRolodexId() != null) { setPrincipalInvestigatorId(principalInvestigator.getRolodexId().toString()); } } } } return principalInvestigatorId; } public void setPrincipalInvestigatorId(String principalInvestigatorId) { this.principalInvestigatorId = principalInvestigatorId; } public boolean isNonEmployeeFlag() { return this.nonEmployeeFlag; } public void setNonEmployeeFlag(boolean nonEmployeeFlag) { this.nonEmployeeFlag = nonEmployeeFlag; } /** * This method is to get protocol location service * @return ProtocolLocationService */ protected ProtocolLocationService getProtocolLocationService() { ProtocolLocationService protocolLocationService = (ProtocolLocationService) KcServiceLocator .getService("protocolLocationService"); return protocolLocationService; } public List<ProtocolPersonBase> getProtocolPersons() { return protocolPersons; } public void setProtocolPersons(List<ProtocolPersonBase> protocolPersons) { this.protocolPersons = protocolPersons; for (ProtocolPersonBase person : protocolPersons) { person.init(this); } } /** * Gets index i from the protocol person list. * * @param index * @return protocol person at index i */ public ProtocolPersonBase getProtocolPerson(int index) { return getProtocolPersons().get(index); } /** * This method is a hook to get actual protocol personnel service impl corresponding to the protocol type * @return protocolPersonnelService */ protected abstract ProtocolPersonnelService getProtocolPersonnelService(); public List<ProtocolFundingSourceBase> getProtocolFundingSources() { return protocolFundingSources; } public void setProtocolFundingSources(List<ProtocolFundingSourceBase> protocolFundingSources) { this.protocolFundingSources = protocolFundingSources; for (ProtocolFundingSourceBase fundingSource : protocolFundingSources) { fundingSource.init(this); } } public String getResearchAreaCode() { return researchAreaCode; } public void setResearchAreaCode(String researchAreaCode) { this.researchAreaCode = researchAreaCode; } public String getFundingSource() { return fundingSource; } public void setFundingSource(String fundingSource) { this.fundingSource = fundingSource; } public String getPerformingOrganizationId() { return performingOrganizationId; } public void setPerformingOrganizationId(String performingOrganizationId) { this.performingOrganizationId = performingOrganizationId; } public String getLeadUnitName() { if (StringUtils.isBlank(leadUnitName)) { if (getLeadUnit() != null) { setLeadUnitName(getLeadUnit().getUnitName()); } } return leadUnitName; } public void setLeadUnitName(String leadUnitName) { this.leadUnitName = leadUnitName; } public void setSpecialReviews(List<ProtocolSpecialReviewBase> specialReviews) { this.specialReviews = specialReviews; } public void addSpecialReview(ProtocolSpecialReviewBase specialReview) { specialReview.setSequenceOwner(this); getSpecialReviews().add(specialReview); } public ProtocolSpecialReviewBase getSpecialReview(int index) { return getSpecialReviews().get(index); } public List<ProtocolSpecialReviewBase> getSpecialReviews() { return specialReviews; } /** * Gets the attachment protocols. Cannot return {@code null}. * @return the attachment protocols */ public List<ProtocolAttachmentProtocolBase> getAttachmentProtocols() { if (this.attachmentProtocols == null) { this.attachmentProtocols = new ArrayList<ProtocolAttachmentProtocolBase>(); } return this.attachmentProtocols; } /** * Gets an attachment protocol. * @param index the index * @return an attachment protocol */ public ProtocolAttachmentProtocolBase getAttachmentProtocol(int index) { return this.attachmentProtocols.get(index); } /** * Gets the notepads. Cannot return {@code null}. * @return the notepads */ public List<ProtocolNotepadBase> getNotepads() { if (this.notepads == null) { this.notepads = new ArrayList<ProtocolNotepadBase>(); } return this.notepads; } /** * Gets an attachment protocol. * @param index the index * @return an attachment protocol */ public ProtocolNotepadBase getNotepad(int index) { return this.notepads.get(index); } /** * adds an attachment protocol. * @param attachmentProtocol the attachment protocol * @throws IllegalArgumentException if attachmentProtocol is null */ private void addAttachmentProtocol(ProtocolAttachmentProtocolBase attachmentProtocol) { ProtocolAttachmentBase.addAttachmentToCollection(attachmentProtocol, this.getAttachmentProtocols()); } /** * removes an attachment protocol. * @param attachmentProtocol the attachment protocol * @throws IllegalArgumentException if attachmentProtocol is null */ private void removeAttachmentProtocol(ProtocolAttachmentProtocolBase attachmentProtocol) { ProtocolAttachmentBase.removeAttachmentFromCollection(attachmentProtocol, this.getAttachmentProtocols()); } /** * @deprecated * Gets the attachment personnels. Cannot return {@code null}. * @return the attachment personnels */ @Deprecated public List<ProtocolAttachmentPersonnelBase> getAttachmentPersonnels() { return getProtocolAttachmentPersonnel(); } private void updateUserFields(KcPersistableBusinessObjectBase bo) { bo.setUpdateUser(GlobalVariables.getUserSession().getPrincipalName()); bo.setUpdateTimestamp(getDateTimeService().getCurrentTimestamp()); } /** * Adds a attachment to a ProtocolBase where the type of attachment is used to determine * where to add the attachment. * @param attachment the attachment * @throws IllegalArgumentException if attachment is null or if an unsupported attachment is found */ public <T extends ProtocolAttachmentBase> void addAttachmentsByType(T attachment) { if (attachment == null) { throw new IllegalArgumentException("the attachment is null"); } updateUserFields(attachment); attachment.setProtocolId(getProtocolId()); if (attachment instanceof ProtocolAttachmentProtocolBase) { this.addAttachmentProtocol((ProtocolAttachmentProtocolBase) attachment); } else { throw new IllegalArgumentException("unsupported type: " + attachment.getClass().getName()); } } /** * removes an attachment to a ProtocolBase where the type of attachment is used to determine * where to add the attachment. * @param attachment the attachment * @throws IllegalArgumentException if attachment is null or if an unsupported attachment is found */ public <T extends ProtocolAttachmentBase> void removeAttachmentsByType(T attachment) { if (attachment == null) { throw new IllegalArgumentException("the attachment is null"); } if (attachment instanceof ProtocolAttachmentProtocolBase) { this.removeAttachmentProtocol((ProtocolAttachmentProtocolBase) attachment); } else { throw new IllegalArgumentException("unsupported type: " + attachment.getClass().getName()); } } public String getKeyPerson() { return keyPerson; } public void setKeyPerson(String keyPerson) { this.keyPerson = keyPerson; } public String getInvestigator() { if (StringUtils.isBlank(principalInvestigatorId)) { if (getPrincipalInvestigator() != null) { investigator = getPrincipalInvestigator().getPersonName(); } } return investigator; } public void setInvestigator(String investigator) { this.investigator = investigator; } public ProtocolSubmissionBase getProtocolSubmission() { if (!protocolSubmissions.isEmpty()) { // sorted by ojb if (protocolSubmission == null || protocolSubmission.getSubmissionNumber() == null || protocolSubmissions.get(protocolSubmissions.size() - 1) .getSubmissionNumber() > protocolSubmission.getSubmissionNumber()) { protocolSubmission = protocolSubmissions.get(protocolSubmissions.size() - 1); } } else { protocolSubmission = getProtocolSubmissionNewInstanceHook(); // TODO : the update protocol rule may not like null protocolSubmission.setProtocolSubmissionType(getProtocolSubmissionTypeNewInstanceHook()); protocolSubmission.setSubmissionStatus(getProtocolSubmissionStatusNewInstanceHook()); } // } refreshReferenceObject(protocolSubmission); return protocolSubmission; } protected abstract ProtocolSubmissionStatusBase getProtocolSubmissionStatusNewInstanceHook(); protected abstract ProtocolSubmissionTypeBase getProtocolSubmissionTypeNewInstanceHook(); protected abstract ProtocolSubmissionBase getProtocolSubmissionNewInstanceHook(); private void refreshReferenceObject(ProtocolSubmissionBase submission) { // if submission just added, then these probably are empty if (StringUtils.isNotBlank(submission.getProtocolReviewTypeCode()) && submission.getProtocolReviewType() == null) { submission.refreshReferenceObject("protocolReviewType"); } if (StringUtils.isNotBlank(submission.getSubmissionStatusCode()) && submission.getSubmissionStatus() == null) { submission.refreshReferenceObject("submissionStatus"); } if (StringUtils.isNotBlank(submission.getSubmissionTypeCode()) && submission.getProtocolSubmissionType() == null) { submission.refreshReferenceObject("protocolSubmissionType"); } if (StringUtils.isNotBlank(submission.getSubmissionTypeQualifierCode()) && submission.getProtocolSubmissionQualifierType() == null) { submission.refreshReferenceObject("protocolSubmissionQualifierType"); } } public void setProtocolSubmission(ProtocolSubmissionBase protocolSubmission) { this.protocolSubmission = protocolSubmission; } public void setProtocolActions(List<ProtocolActionBase> protocolActions) { this.protocolActions = protocolActions; } public List<ProtocolActionBase> getProtocolActions() { return protocolActions; } public ProtocolActionBase getLastProtocolAction() { if (protocolActions.size() == 0) { return null; } Collections.sort(protocolActions, new Comparator<ProtocolActionBase>() { public int compare(ProtocolActionBase action1, ProtocolActionBase action2) { return action2.getActualActionDate().compareTo(action1.getActualActionDate()); } }); return protocolActions.get(0); } public boolean containsAction(String action) { boolean result = false; for (ProtocolActionBase protocolActionBase : getProtocolActions()) { if (protocolActionBase.getProtocolActionTypeCode().equals(action)) { result = true; break; } } return result; } public void setProtocolSubmissions(List<ProtocolSubmissionBase> protocolSubmissions) { this.protocolSubmissions = protocolSubmissions; } public List<ProtocolSubmissionBase> getProtocolSubmissions() { return protocolSubmissions; } /** * Get the next value in a sequence. * @param key the unique key of the sequence * @return the next value */ public Integer getNextValue(String key) { return protocolDocument.getDocumentNextValue(key); } public void setAttachmentProtocols(List<ProtocolAttachmentProtocolBase> attachmentProtocols) { this.attachmentProtocols = attachmentProtocols; for (ProtocolAttachmentProtocolBase attachment : attachmentProtocols) { attachment.resetPersistenceState(); attachment.setSequenceNumber(0); } } public void setNotepads(List<ProtocolNotepadBase> notepads) { this.notepads = notepads; } public void setProtocolAmendRenewal(ProtocolAmendRenewalBase amendRenewal) { protocolAmendRenewals.add(amendRenewal); } public ProtocolAmendRenewalBase getProtocolAmendRenewal() { if (protocolAmendRenewals.size() == 0) return null; return protocolAmendRenewals.get(0); } public List<ProtocolAmendRenewalBase> getProtocolAmendRenewals() { return protocolAmendRenewals; } public void setProtocolAmendRenewals(List<ProtocolAmendRenewalBase> protocolAmendRenewals) { this.protocolAmendRenewals = protocolAmendRenewals; } @Override public Integer getOwnerSequenceNumber() { return null; } @Override public String getVersionNameField() { return "protocolNumber"; } @Override public void incrementSequenceNumber() { this.sequenceNumber++; } @Override public ProtocolBase getSequenceOwner() { return this; } @Override public void setSequenceOwner(ProtocolBase newOwner) { //no-op } @Override public void resetPersistenceState() { this.protocolId = null; } /** * * This method merges the data of the amended protocol into this protocol. * @param amendment */ public void merge(ProtocolBase amendment) { merge(amendment, true); } // this method was modified during IRB backfit merge with the assumption that these changes are applicable to both IRB and IACUC public void merge(ProtocolBase amendment, boolean mergeActions) { // set this value here, since it is applicable regardless of which modules are amended this.lastApprovalDate = amendment.getLastApprovalDate(); List<ProtocolAmendRenewModuleBase> modules = amendment.getProtocolAmendRenewal().getModules(); removeMergeableLists(modules); // remove lists from copy of original protocol getBusinessObjectService().save(this); // force OJB to persist removal of lists for (ProtocolAmendRenewModuleBase module : modules) { merge(amendment, module.getProtocolModuleTypeCode()); } if (amendment.isRenewalWithoutAmendment() && isRenewalWithNewAttachment(amendment)) { merge(amendment, getProtocolModuleAddModifyAttachmentCodeHook()); } if (mergeActions) { mergeProtocolSubmission(amendment); mergeProtocolAction(amendment); } // if renewal, then set the expiration date to be the new one provided during renewal approval if (isExpirationDateToBeUpdated(amendment)) { this.setExpirationDate(amendment.getExpirationDate()); } } protected abstract String getProtocolModuleAddModifyAttachmentCodeHook(); // this method can be overridden to customize the conditions when the expiration date is to be updated for the main protocol protected boolean isExpirationDateToBeUpdated(ProtocolBase protocol) { return protocol.isRenewal(); } private boolean isRenewalWithNewAttachment(ProtocolBase renewal) { boolean hasNewAttachment = false; for (ProtocolAttachmentProtocolBase attachment : renewal.getAttachmentProtocols()) { if (attachment.isDraft()) { hasNewAttachment = true; break; } } return hasNewAttachment; } public abstract void merge(ProtocolBase amendment, String protocolModuleTypeCode); protected abstract void removeMergeableLists(List<ProtocolAmendRenewModuleBase> modules); protected void mergeProtocolQuestionnaire(ProtocolBase amendment) { // TODO : what if user did not edit questionnaire at all, then questionnaire will be wiped out ? removeOldQuestionnaire(); amendQuestionnaire(amendment); } /* * remove existing questionnaire from current */ protected void removeOldQuestionnaire() { List<AnswerHeader> answerHeaders = getAnswerHeaderForProtocol(this); if (!answerHeaders.isEmpty() && answerHeaders.get(0).getId() != null) { getBusinessObjectService().delete(answerHeaders); } } /* * add questionnaire answer from amendment to protocol */ protected void amendQuestionnaire(ProtocolBase amendment) { List<AnswerHeader> answerHeaders = getAnswerHeaderForProtocol(amendment); if (!answerHeaders.isEmpty()) { for (AnswerHeader answerHeader : answerHeaders) { for (Answer answer : answerHeader.getAnswers()) { answer.setAnswerHeaderId(null); answer.setId(null); } answerHeader.setId(null); answerHeader.setModuleItemKey(this.getProtocolNumber()); answerHeader.setModuleSubItemKey(this.getSequenceNumber().toString()); } getBusinessObjectService().save(answerHeaders); } } /* * get submit for review questionnaire answerheaders */ public abstract List<AnswerHeader> getAnswerHeaderForProtocol(ProtocolBase protocol); protected QuestionnaireAnswerService getQuestionnaireAnswerService() { return KcServiceLocator.getService(QuestionnaireAnswerService.class); } protected BusinessObjectService getBusinessObjectService() { return KcServiceLocator.getService(BusinessObjectService.class); } @SuppressWarnings("unchecked") protected void mergeProtocolSubmission(ProtocolBase amendment) { List<ProtocolSubmissionBase> submissions = (List<ProtocolSubmissionBase>) deepCopy( amendment.getProtocolSubmissions()); for (ProtocolSubmissionBase submission : submissions) { submission.setProtocolNumber(this.getProtocolNumber()); submission.setSubmissionId(null); submission.setSequenceNumber(sequenceNumber); submission.setProtocolId(this.getProtocolId()); this.getProtocolSubmissions().add(submission); } } protected abstract void mergeProtocolAction(ProtocolBase amendment); protected void mergeGeneralInfo(ProtocolBase amendment) { this.protocolTypeCode = amendment.getProtocolTypeCode(); this.title = amendment.getTitle(); this.initialSubmissionDate = amendment.getInitialSubmissionDate(); this.approvalDate = amendment.getApprovalDate(); this.expirationDate = amendment.getExpirationDate(); this.description = amendment.getDescription(); this.fdaApplicationNumber = amendment.getFdaApplicationNumber(); this.referenceNumber1 = amendment.getReferenceNumber1(); this.referenceNumber2 = amendment.getReferenceNumber2(); } @SuppressWarnings("unchecked") protected void mergeResearchAreas(ProtocolBase amendment) { setProtocolResearchAreas((List<ProtocolResearchAreaBase>) deepCopy(amendment.getProtocolResearchAreas())); } @SuppressWarnings("unchecked") protected void mergeFundingSources(ProtocolBase amendment) { setProtocolFundingSources( (List<ProtocolFundingSourceBase>) deepCopy(amendment.getProtocolFundingSources())); } @SuppressWarnings("unchecked") protected void mergeReferences(ProtocolBase amendment) { setProtocolReferences((List<ProtocolReferenceBase>) deepCopy(amendment.getProtocolReferences())); this.fdaApplicationNumber = amendment.getFdaApplicationNumber(); this.referenceNumber1 = amendment.getReferenceNumber1(); this.referenceNumber2 = amendment.getReferenceNumber2(); this.description = amendment.getDescription(); } @SuppressWarnings("unchecked") protected void mergeOrganizations(ProtocolBase amendment) { setProtocolLocations((List<ProtocolLocationBase>) deepCopy(amendment.getProtocolLocations())); } @SuppressWarnings("unchecked") protected void mergeAttachments(ProtocolBase amendment) { // TODO : may need to set protocolnumber // personnel attachment may have protocol person id issue // how about sequence number ? // need to change documentstatus to 2 if it is 1 // what the new protocol's protocol_status should be ? List<ProtocolAttachmentProtocolBase> attachmentProtocols = new ArrayList<ProtocolAttachmentProtocolBase>(); for (ProtocolAttachmentProtocolBase attachment : (List<ProtocolAttachmentProtocolBase>) deepCopy( amendment.getAttachmentProtocols())) { attachment.setProtocolNumber(this.getProtocolNumber()); attachment.setSequenceNumber(this.getSequenceNumber()); attachment.setProtocolId(this.getProtocolId()); attachment.setId(null); if (attachment.getFile() != null) { attachment.getFile().setId(null); } if (attachment.isDraft()) { attachment.setDocumentStatusCode(ProtocolAttachmentStatusBase.FINALIZED); attachmentProtocols.add(attachment); attachment.setProtocol(this); } if (attachment.isDeleted() && KcServiceLocator.getService(ProtocolAttachmentService.class) .isNewAttachmentVersion((ProtocolAttachmentProtocolBase) attachment)) { attachmentProtocols.add(attachment); attachment.setProtocol(this); } } getAttachmentProtocols().addAll(attachmentProtocols); removeDeletedAttachment(); mergeNotepads(amendment); } /* * the deleted attachment will not be merged */ private void removeDeletedAttachment() { List<Integer> documentIds = new ArrayList<Integer>(); List<ProtocolAttachmentProtocolBase> attachments = new ArrayList<ProtocolAttachmentProtocolBase>(); for (ProtocolAttachmentProtocolBase attachment : this.getAttachmentProtocols()) { attachment.setProtocol(this); if (attachment.isDeleted()) { documentIds.add(attachment.getDocumentId()); } } if (!documentIds.isEmpty()) { for (ProtocolAttachmentProtocolBase attachment : this.getAttachmentProtocols()) { attachment.setProtocol(this); if (!documentIds.contains(attachment.getDocumentId())) { attachments.add(attachment); } } this.setAttachmentProtocols(new ArrayList<ProtocolAttachmentProtocolBase>()); this.getAttachmentProtocols().addAll(attachments); } } /* * This is to restore attachments from protocol to amendment when 'attachment' section is unselected. * The attachment in amendment may have been modified. * delete 'attachment' need to be careful. * - if the 'file' is also used in other 'finalized' attachment, then should remove this file reference from attachment * otherwise, the delete will also delete any attachment that reference to this file */ protected void restoreAttachments(ProtocolBase protocol) { List<ProtocolAttachmentProtocolBase> attachmentProtocols = new ArrayList<ProtocolAttachmentProtocolBase>(); List<ProtocolAttachmentProtocolBase> deleteAttachments = new ArrayList<ProtocolAttachmentProtocolBase>(); List<AttachmentFile> deleteFiles = new ArrayList<AttachmentFile>(); for (ProtocolAttachmentProtocolBase attachment : this.getAttachmentProtocols()) { if (attachment.isFinal()) { attachmentProtocols.add(attachment); // } else if (attachment.isDraft()) { } else { // in amendment, DRAFT & DELETED must be new attachment because DELETED // will not be copied from original protocol deleteAttachments.add(attachment); if (!fileIsReferencedByOther(attachment.getFileId())) { deleteFiles.add(attachment.getFile()); } attachment.setFileId(null); } } if (!deleteAttachments.isEmpty()) { getBusinessObjectService().save(deleteAttachments); if (!deleteFiles.isEmpty()) { getBusinessObjectService().delete(deleteFiles); } getBusinessObjectService().delete(deleteAttachments); } this.getAttachmentProtocols().clear(); this.getAttachmentProtocols().addAll(attachmentProtocols); mergeNotepads(protocol); } private boolean fileIsReferencedByOther(Long fileId) { Map<String, String> fieldValues = new HashMap<String, String>(); fieldValues.put("fileId", fileId.toString()); return getBusinessObjectService().countMatching(getProtocolAttachmentProtocolClassHook(), fieldValues) > 1; } protected abstract Class<? extends ProtocolAttachmentProtocolBase> getProtocolAttachmentProtocolClassHook(); protected void mergeNotepads(ProtocolBase amendment) { List<ProtocolNotepadBase> notepads = new ArrayList<ProtocolNotepadBase>(); if (amendment.getNotepads() != null) { for (ProtocolNotepadBase notepad : (List<ProtocolNotepadBase>) deepCopy(amendment.getNotepads())) { notepad.setProtocolNumber(this.getProtocolNumber()); notepad.setSequenceNumber(this.getSequenceNumber()); notepad.setProtocolId(this.getProtocolId()); notepad.setId(null); notepad.setProtocol(this); notepads.add(notepad); } } this.setNotepads(notepads); } @SuppressWarnings("unchecked") protected void mergeSpecialReview(ProtocolBase amendment) { setSpecialReviews((List<ProtocolSpecialReviewBase>) deepCopy(amendment.getSpecialReviews())); cleanupSpecialReviews(amendment); } @SuppressWarnings("unchecked") protected void mergePersonnel(ProtocolBase amendment) { setProtocolPersons((List<ProtocolPersonBase>) deepCopy(amendment.getProtocolPersons())); for (ProtocolPersonBase person : protocolPersons) { Integer nextPersonId = getSequenceAccessorService() .getNextAvailableSequenceNumber("SEQ_PROTOCOL_ID", person.getClass()).intValue(); person.setProtocolPersonId(nextPersonId); for (ProtocolAttachmentPersonnelBase protocolAttachmentPersonnel : person.getAttachmentPersonnels()) { protocolAttachmentPersonnel.setId(null); protocolAttachmentPersonnel.setPersonId(person.getProtocolPersonId()); protocolAttachmentPersonnel.setProtocolId(getProtocolId()); protocolAttachmentPersonnel.setProtocolNumber(getProtocolNumber()); } } } protected void mergeOthers(ProtocolBase amendment) { if (protocolDocument.getCustomAttributeDocuments() == null || protocolDocument.getCustomAttributeDocuments().isEmpty()) { protocolDocument.initialize(); } if (amendment.getProtocolDocument().getCustomAttributeDocuments() == null || amendment.getProtocolDocument().getCustomAttributeDocuments().isEmpty()) { amendment.getProtocolDocument().initialize(); } for (Entry<String, CustomAttributeDocument> entry : protocolDocument.getCustomAttributeDocuments() .entrySet()) { CustomAttributeDocument cad = amendment.getProtocolDocument().getCustomAttributeDocuments() .get(entry.getKey()); entry.getValue().getCustomAttribute().setValue(cad.getCustomAttribute().getValue()); } } protected void mergeProtocolPermissions(ProtocolBase amendment) { // ToDo: merge permissions } protected Object deepCopy(Object obj) { return ObjectUtils.deepCopy((Serializable) obj); } public abstract ProtocolSummary getProtocolSummary(); protected void addAdditionalInfoSummary(ProtocolSummary protocolSummary) { AdditionalInfoSummary additionalInfoSummary = new AdditionalInfoSummary(); additionalInfoSummary.setFdaApplicationNumber(this.getFdaApplicationNumber()); additionalInfoSummary.setReferenceId1(this.getReferenceNumber1()); additionalInfoSummary.setReferenceId2(this.getReferenceNumber2()); additionalInfoSummary.setDescription(getDescription()); protocolSummary.setAdditionalInfo(additionalInfoSummary); } protected void addSpecialReviewSummaries(ProtocolSummary protocolSummary) { for (ProtocolSpecialReviewBase specialReview : getSpecialReviews()) { SpecialReviewSummary specialReviewSummary = new SpecialReviewSummary(); if (specialReview.getSpecialReviewType() == null) { specialReview.refreshReferenceObject("specialReviewType"); } specialReviewSummary.setType(specialReview.getSpecialReviewType().getDescription()); if (specialReview.getApprovalType() == null) { specialReview.refreshReferenceObject("approvalType"); } specialReviewSummary.setApprovalStatus(specialReview.getApprovalType().getDescription()); specialReviewSummary.setProtocolNumber(specialReview.getProtocolNumber()); specialReviewSummary.setApplicationDate(specialReview.getApplicationDate()); specialReviewSummary.setApprovalDate(specialReview.getApprovalDate()); specialReviewSummary.setExpirationDate(specialReview.getExpirationDate()); if (specialReview.getSpecialReviewExemptions() == null) { specialReview.refreshReferenceObject("specialReviewExemptions"); } specialReviewSummary.setExemptionNumbers(specialReview.getSpecialReviewExemptions()); specialReviewSummary.setComment(specialReview.getComments()); protocolSummary.add(specialReviewSummary); } } protected void addOrganizationSummaries(ProtocolSummary protocolSummary) { for (ProtocolLocationBase organization : this.getProtocolLocations()) { OrganizationSummary organizationSummary = new OrganizationSummary(); organizationSummary.setId(organization.getOrganizationId()); organizationSummary.setOrganizationId(organization.getOrganizationId()); organizationSummary.setName(organization.getOrganization().getOrganizationName()); organizationSummary.setType(organization.getProtocolOrganizationType().getDescription()); organizationSummary.setContactId(organization.getRolodexId()); organizationSummary.setContact(organization.getRolodex()); organizationSummary.setFwaNumber(organization.getOrganization().getHumanSubAssurance()); protocolSummary.add(organizationSummary); } } protected void addFundingSourceSummaries(ProtocolSummary protocolSummary) { for (ProtocolFundingSourceBase source : getProtocolFundingSources()) { FundingSourceSummary fundingSourceSummary = new FundingSourceSummary(); fundingSourceSummary.setFundingSourceType(source.getFundingSourceType().getDescription()); fundingSourceSummary.setFundingSource(source.getFundingSourceNumber()); fundingSourceSummary.setFundingSourceNumber(source.getFundingSourceNumber()); fundingSourceSummary.setFundingSourceName(source.getFundingSourceName()); fundingSourceSummary.setFundingSourceTitle(source.getFundingSourceTitle()); protocolSummary.add(fundingSourceSummary); } } protected void addAttachmentSummaries(ProtocolSummary protocolSummary) { for (ProtocolAttachmentProtocolBase attachment : getActiveAttachmentProtocols()) { if (!attachment.isDeleted()) { AttachmentSummary attachmentSummary = new AttachmentSummary(); attachmentSummary.setAttachmentId(attachment.getId()); attachmentSummary.setFileType(attachment.getFile().getType()); attachmentSummary.setFileName(attachment.getFile().getName()); attachmentSummary.setAttachmentType( Constants.PROTOCOL_ATTACHMENT_PREFIX + attachment.getType().getDescription()); attachmentSummary.setDescription(attachment.getDescription()); attachmentSummary.setDataLength( attachment.getFile().getData() == null ? 0 : attachment.getFile().getData().length); attachmentSummary.setUpdateTimestamp(attachment.getUpdateTimestamp()); attachmentSummary.setUpdateUser(attachment.getUpdateUser()); protocolSummary.add(attachmentSummary); } } for (ProtocolPersonBase person : getProtocolPersons()) { for (ProtocolAttachmentPersonnelBase attachment : person.getAttachmentPersonnels()) { AttachmentSummary attachmentSummary = new AttachmentSummary(); attachmentSummary.setAttachmentId(attachment.getId()); attachmentSummary.setFileType(attachment.getFile().getType()); attachmentSummary.setFileName(attachment.getFile().getName()); attachmentSummary .setAttachmentType(person.getPersonName() + ": " + attachment.getType().getDescription()); attachmentSummary.setDescription(attachment.getDescription()); attachmentSummary.setDataLength( attachment.getFile().getData() == null ? 0 : attachment.getFile().getData().length); attachmentSummary.setUpdateTimestamp(attachment.getUpdateTimestamp()); attachmentSummary.setUpdateUser(attachment.getUpdateUser()); protocolSummary.add(attachmentSummary); } } } protected void addResearchAreaSummaries(ProtocolSummary protocolSummary) { for (ProtocolResearchAreaBase researchArea : getProtocolResearchAreas()) { ResearchAreaSummary researchAreaSummary = new ResearchAreaSummary(); researchAreaSummary.setResearchAreaCode(researchArea.getResearchAreaCode()); researchAreaSummary.setDescription(researchArea.getResearchAreas().getDescription()); protocolSummary.add(researchAreaSummary); } } protected void addPersonnelSummaries(ProtocolSummary protocolSummary) { for (ProtocolPersonBase person : getProtocolPersons()) { PersonnelSummary personnelSummary = new PersonnelSummary(); personnelSummary.setPersonId(person.getPersonId()); personnelSummary.setName(person.getPersonName()); personnelSummary.setRoleName(person.getProtocolPersonRole().getDescription()); if (person.getAffiliationTypeCode() == null) { personnelSummary.setAffiliation(""); } else { if (person.getAffiliationType() == null) { person.refreshReferenceObject("affiliationType"); } personnelSummary.setAffiliation(person.getAffiliationType().getDescription()); } for (ProtocolUnitBase unit : person.getProtocolUnits()) { personnelSummary.addUnit(unit.getUnitNumber(), unit.getUnitName()); } protocolSummary.add(personnelSummary); } } protected abstract ProtocolSummary createProtocolSummary(); @Override public abstract String getDocumentKey(); @Override public String getDocumentNumberForPermission() { return protocolNumber; } @Override public abstract List<String> getRoleNames(); public void resetForeignKeys() { for (ProtocolActionBase action : protocolActions) { action.resetForeignKeys(); } } public void resetPersistenceStateForNotifications() { for (ProtocolActionBase action : protocolActions) { for (KcNotification notification : action.getProtocolNotifications()) { notification.resetPersistenceState(); } } } public abstract String getNamespace(); @Override public String getDocumentUnitNumber() { return getLeadUnitNumber(); } @Override public abstract String getDocumentRoleTypeCode(); public void populateAdditionalQualifiedRoleAttributes(Map<String, String> qualifiedRoleAttributes) { return; } public boolean isNew() { return !isAmendment() && !isRenewal(); } public boolean isAmendment() { return protocolNumber != null && protocolNumber.contains(AMENDMENT_LETTER); } public boolean isRenewal() { return protocolNumber != null && protocolNumber.contains(RENEWAL_LETTER); } public boolean isRenewalWithAmendment() { return isRenewal() && CollectionUtils.isNotEmpty(this.getProtocolAmendRenewal().getModules()); } public boolean isRenewalWithoutAmendment() { return isRenewal() && CollectionUtils.isEmpty(this.getProtocolAmendRenewal().getModules()); } /** * * If the protocol document is an amendment or renewal the parent protocol number is being returned. * (i.e. the protocol number of the protocol that is being amended or renewed). * * Null will be returned if the protocol is not an amendment or renewal. * * @return protocolNumber of the ProtocolBase that is being amended/renewed */ public String getAmendedProtocolNumber() { if (isAmendment()) { return StringUtils.substringBefore(getProtocolNumber(), AMENDMENT_LETTER.toString()); } else if (isRenewal()) { return StringUtils.substringBefore(getProtocolNumber(), RENEWAL_LETTER.toString()); } else { return null; } } /** * Decides whether or not the ProtocolBase is in a state where changes will require versioning. For example: has the protocol * had a change in status and not been versioned yet? * @return true if versioning required false if not. */ public boolean isVersioningRequired() { // TODO : why need this. it's always true return true; } /** * This method will return the list of all active attachments for this protocol; an attachment A is active for a * protocol if either A has a doc status code of 'draft' or * if for all other attachments for that protocol having the same doc id as A's doc id, none have a version number * greater than A's version number. * is defined as the o * @return */ public List<ProtocolAttachmentProtocolBase> getActiveAttachmentProtocols() { List<ProtocolAttachmentProtocolBase> activeAttachments = new ArrayList<ProtocolAttachmentProtocolBase>(); for (ProtocolAttachmentProtocolBase attachment1 : getAttachmentProtocols()) { if (attachment1.isDraft()) { activeAttachments.add(attachment1); } else if (attachment1.isFinal() || attachment1.isDeleted()) { //else if (attachment1.isFinal())) { boolean isActive = true; for (ProtocolAttachmentProtocolBase attachment2 : getAttachmentProtocols()) { if (attachment1.getDocumentId().equals(attachment2.getDocumentId()) && attachment1.getAttachmentVersion() < attachment2.getAttachmentVersion()) { isActive = false; break; } } if (isActive) { activeAttachments.add(attachment1); } else { attachment1.setActive(isActive); } } else { attachment1.setActive(false); } } return activeAttachments; } /** * This method will return the list of undeleted attachments that are still active for this protocol. * Essentially it filters out all the deleted elements from the list of active attachments. * See getActiveAttachmentProtocols() for a specification of what is an 'active attachment'. * * * @return */ // TODO the method code below could be restructured to combine the two for loops into one loop. public List<ProtocolAttachmentProtocolBase> getActiveAttachmentProtocolsNoDelete() { List<Integer> documentIds = new ArrayList<Integer>(); List<ProtocolAttachmentProtocolBase> activeAttachments = new ArrayList<ProtocolAttachmentProtocolBase>(); for (ProtocolAttachmentProtocolBase attachment : getActiveAttachmentProtocols()) { if (attachment.isDeleted()) { documentIds.add(attachment.getDocumentId()); } } for (ProtocolAttachmentProtocolBase attachment : getActiveAttachmentProtocols()) { if (documentIds.isEmpty() || !documentIds.contains(attachment.getDocumentId())) { activeAttachments.add(attachment); } else { attachment.setActive(false); } } return activeAttachments; } public boolean isCorrectionMode() { return correctionMode; } public void setCorrectionMode(boolean correctionMode) { this.correctionMode = correctionMode; } protected DateTimeService getDateTimeService() { if (dateTimeService == null) { dateTimeService = (DateTimeService) KcServiceLocator.getService(DateTimeService.class); } return dateTimeService; } protected SequenceAccessorService getSequenceAccessorService() { if (sequenceAccessorService == null) { sequenceAccessorService = (SequenceAccessorService) KcServiceLocator .getService(SequenceAccessorService.class); } return sequenceAccessorService; } public Long getNotifyIrbSubmissionId() { return notifyIrbSubmissionId; } public void setNotifyIrbSubmissionId(Long notifyIrbSubmissionId) { this.notifyIrbSubmissionId = notifyIrbSubmissionId; } public boolean isLookupPendingProtocol() { return lookupPendingProtocol; } public void setLookupPendingProtocol(boolean lookupPendingProtocol) { this.lookupPendingProtocol = lookupPendingProtocol; } public boolean isLookupPendingPIActionProtocol() { return lookupPendingPIActionProtocol; } public void setLookupPendingPIActionProtocol(boolean lookupPendingPIActionProtocol) { this.lookupPendingPIActionProtocol = lookupPendingPIActionProtocol; } public boolean isLookupActionAmendRenewProtocol() { return lookupActionAmendRenewProtocol; } public void setLookupActionAmendRenewProtocol(boolean lookupActionAmendRenewProtocol) { this.lookupActionAmendRenewProtocol = lookupActionAmendRenewProtocol; } public boolean isLookupActionRequestProtocol() { return lookupActionRequestProtocol; } public void setLookupActionRequestProtocol(boolean lookupActionRequestProtocol) { this.lookupActionRequestProtocol = lookupActionRequestProtocol; } public boolean isLookupProtocolPersonId() { return lookupProtocolPersonId; } public void setLookupProtocolPersonId(boolean lookupProtocolPersonId) { this.lookupProtocolPersonId = lookupProtocolPersonId; } /** * * This method is to check if the actiontypecode is a followup action. * @param actionTypeCode * @return */ public boolean isFollowupAction(String actionTypeCode) { return (getLastProtocolAction() == null || StringUtils.isBlank(getLastProtocolAction().getFollowupActionCode())) ? false : actionTypeCode.equals(getLastProtocolAction().getFollowupActionCode()); } public boolean isMergeAmendment() { return mergeAmendment; } public void setMergeAmendment(boolean mergeAmendment) { this.mergeAmendment = mergeAmendment; } public ProtocolAttachmentFilterBase getProtocolAttachmentFilter() { return protocolAttachmentFilter; } public void setProtocolAttachmentFilter(ProtocolAttachmentFilterBase protocolAttachmentFilter) { this.protocolAttachmentFilter = protocolAttachmentFilter; } /** * * This method returns a list of attachments which respect the sort filter * @return a filtered list of protocol attachments */ public List<ProtocolAttachmentProtocolBase> getFilteredAttachmentProtocols() { List<ProtocolAttachmentProtocolBase> filteredAttachments = new ArrayList<ProtocolAttachmentProtocolBase>(); ProtocolAttachmentFilterBase attachmentFilter = getProtocolAttachmentFilter(); if (attachmentFilter != null && StringUtils.isNotBlank(attachmentFilter.getFilterBy())) { for (ProtocolAttachmentProtocolBase attachment1 : getAttachmentProtocols()) { if ((attachment1.getTypeCode()).equals(attachmentFilter.getFilterBy())) { filteredAttachments.add(attachment1); } } } else { filteredAttachments = getAttachmentProtocols(); } if (attachmentFilter != null && StringUtils.isNotBlank(attachmentFilter.getSortBy())) { Collections.sort(filteredAttachments, attachmentFilter.getProtocolAttachmentComparator()); } return filteredAttachments; } public abstract void initializeProtocolAttachmentFilter(); public ParameterService getParameterService() { return KcServiceLocator.getService(ParameterService.class); } public void cleanupSpecialReviews(ProtocolBase srcProtocol) { List<ProtocolSpecialReviewBase> srcSpecialReviews = srcProtocol.getSpecialReviews(); List<ProtocolSpecialReviewBase> dstSpecialReviews = getSpecialReviews(); for (int i = 0; i < srcSpecialReviews.size(); i++) { ProtocolSpecialReviewBase srcSpecialReview = srcSpecialReviews.get(i); ProtocolSpecialReviewBase dstSpecialReview = dstSpecialReviews.get(i); // copy exemption codes, since they are transient and ignored by deepCopy() if (srcSpecialReview.getExemptionTypeCodes() != null) { List<String> exemptionCodeCopy = new ArrayList<String>(); for (String s : srcSpecialReview.getExemptionTypeCodes()) { exemptionCodeCopy.add(new String(s)); } dstSpecialReview.setExemptionTypeCodes(exemptionCodeCopy); } // force new table entry dstSpecialReview.resetPersistenceState(); } } /** * This method encapsulates the logic to decide if a committee member appears in the list of protocol personnel. * It will first try to match by personIds and if personIds are not available then it will try matching by rolodexIds. * @param member * @return */ public boolean isMemberInProtocolPersonnel(CommitteeMembershipBase member) { boolean retValue = false; for (ProtocolPersonBase protocolPerson : this.protocolPersons) { if (StringUtils.isNotBlank(member.getPersonId()) && StringUtils.isNotBlank(protocolPerson.getPersonId())) { if (member.getPersonId().equals(protocolPerson.getPersonId())) { retValue = true; break; } } else if (StringUtils.isBlank(member.getPersonId()) && StringUtils.isBlank(protocolPerson.getPersonId())) { // in this case check rolodex id if ((null != member.getRolodexId()) && (null != protocolPerson.getRolodexId())) { if (member.getRolodexId().equals(protocolPerson.getRolodexId())) { retValue = true; break; } } } } return retValue; } /** * This method will filter out this protocol's personnel from the given list of committee memberships * @param members * @return the filtered list of members */ public List<CommitteeMembershipBase> filterOutProtocolPersonnel(List<CommitteeMembershipBase> members) { List<CommitteeMembershipBase> filteredMemebers = new ArrayList<CommitteeMembershipBase>(); for (CommitteeMembershipBase member : members) { if (!isMemberInProtocolPersonnel(member)) { filteredMemebers.add(member); } } return filteredMemebers; } /** * * This method is to return the first submission date as application date. see kccoi-36 comment * @return */ public Date getApplicationDate() { if (CollectionUtils.isNotEmpty(this.protocolSubmissions)) { return this.protocolSubmissions.get(0).getSubmissionDate(); } else { return null; } } @Override public String getProjectName() { return getTitle(); } @Override public String getProjectId() { return getProtocolNumber(); } // This is for viewhistory/corespondence to search prev submission public List<ProtocolActionBase> getSortedActions() { if (sortedActions == null) { sortedActions = new ArrayList<ProtocolActionBase>(); for (ProtocolActionBase action : getProtocolActions()) { sortedActions.add((ProtocolActionBase) ObjectUtils.deepCopy(action)); } Collections.sort(sortedActions, new Comparator<ProtocolActionBase>() { public int compare(ProtocolActionBase action1, ProtocolActionBase action2) { return action1.getActionId().compareTo(action2.getActionId()); } }); } return sortedActions; } public boolean isEmptyProtocolResearchAreas() { return CollectionUtils.isEmpty(getProtocolResearchAreas()); } /* * determine if current user is named on the protocol. */ public boolean isUserNamedInProtocol(String principalName) { boolean result = false; for (ProtocolPersonBase protocolPerson : getProtocolPersons()) { if (principalName.equals(protocolPerson.getUserName())) { result = true; } } return result; } public void reconcileActionsWithSubmissions() { HashMap<Integer, ProtocolSubmissionBase> submissionNumberMap = new HashMap<Integer, ProtocolSubmissionBase>(); for (ProtocolSubmissionBase submission : getProtocolSubmissions()) { submissionNumberMap.put(submission.getSubmissionNumber(), submission); } for (ProtocolActionBase action : getProtocolActions()) { if (action.getSubmissionNumber() != null && !action.getSubmissionNumber().equals(0)) { if (submissionNumberMap.get(action.getSubmissionNumber()) != null) { action.setSubmissionIdFk( submissionNumberMap.get(action.getSubmissionNumber()).getSubmissionId()); } } } } }