Java tutorial
/******************************************************************************* * Copyright SemanticBits, Northwestern University and Akaza Research * * Distributed under the OSI-approved BSD 3-Clause License. * See http://ncip.github.com/caaers/LICENSE.txt for details. ******************************************************************************/ package gov.nih.nci.cabig.caaers.domain; import gov.nih.nci.cabig.caaers.CaaersSystemException; import gov.nih.nci.cabig.caaers.domain.attribution.AdverseEventAttribution; import gov.nih.nci.cabig.caaers.domain.report.Report; import gov.nih.nci.cabig.caaers.domain.report.ReportDefinition; import gov.nih.nci.cabig.caaers.utils.DateUtils; import gov.nih.nci.cabig.caaers.utils.ObjectUtils; import gov.nih.nci.cabig.caaers.validation.annotation.UniqueObjectInCollection; import gov.nih.nci.cabig.ctms.collections.LazyListHelper; import gov.nih.nci.cabig.ctms.domain.AbstractMutableDomainObject; import gov.nih.nci.cabig.ctms.domain.DomainObject; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.annotations.*; import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.Parameter; import javax.persistence.*; import javax.persistence.Entity; import javax.persistence.Table; import java.io.Serializable; import java.sql.Timestamp; import java.util.*; /** * This class represents the ExpeditedAdverseEventReport domain object. * * @author Rhett Sutphin * @author Biju Joseph * @author Ion C. Olaru * */ @Entity @Table(name = "ae_reports") @GenericGenerator(name = "id-generator", strategy = "native", parameters = { @Parameter(name = "sequence", value = "seq_ae_reports_id") }) public class ExpeditedAdverseEventReport extends AbstractMutableDomainObject implements Serializable { /** The Constant serialVersionUID. */ private static final long serialVersionUID = -3747213703166595074L; private static final Log log = LogFactory.getLog(ExpeditedAdverseEventReport.class); private Boolean investigationalDeviceAdministered; /** The created at. */ private Timestamp createdAt; /** The lazy list helper. */ private LazyListHelper lazyListHelper; /** The response description. */ private AdverseEventResponseDescription responseDescription; /** The treatment information. */ private TreatmentInformation treatmentInformation; /** The additional information. */ private AdditionalInformation additionalInformation; /** The reporter. */ private Reporter reporter; /** The physician. */ private Physician physician; /** The participant history. */ private ParticipantHistory participantHistory; /** The disease history. */ private DiseaseHistory diseaseHistory; /** The reporting period. */ private AdverseEventReportingPeriod reportingPeriod; /** The reports. */ private List<Report> reports; //transient field to be used in adding reviewer information in report generation private Reporter reviewer; private String externalId; // TODO // private List<MedicalDevice> medicalDevices; /** * Instantiates a new expedited adverse event report. */ public ExpeditedAdverseEventReport() { lazyListHelper = new LazyListHelper(); addReportChildLazyList(AdverseEvent.class); addReportChildLazyList(Lab.class); addReportChildLazyList(MedicalDevice.class); addReportChildLazyList(RadiationIntervention.class); addReportChildLazyList(SurgeryIntervention.class); addReportChildLazyList(BehavioralIntervention.class); addReportChildLazyList(GeneticIntervention.class); addReportChildLazyList(BiologicalIntervention.class); addReportChildLazyList(DietarySupplementIntervention.class); addReportChildLazyList(OtherAEIntervention.class); addReportChildLazyList(ConcomitantMedication.class); addReportChildLazyList(OtherCause.class); addReportChildLazyList(SAEReportPriorTherapy.class); addReportChildLazyList(SAEReportPreExistingCondition.class); } /** * Adds the report child lazy list. * * @param <T> the generic type * @param klass the klass */ private <T extends ExpeditedAdverseEventReportChild> void addReportChildLazyList(Class<T> klass) { lazyListHelper.add(klass, new ExpeditedAdverseEventReportChildFactory<T>(klass, this)); } ////// LOGIC /** * Gets the notification message. * * @return the notification message */ @Transient public String getNotificationMessage() { if (isNotificationMessagePossible()) { String other = ""; String fullName = ""; AdverseEvent firstAe = getAdverseEventsInternal().get(0); if (firstAe.getAdverseEventCtcTerm().getCtcTerm() != null) { CtcTerm term = firstAe.getAdverseEventCtcTerm().getCtcTerm(); fullName = term.getFullName(); other = term.isOtherRequired() ? String.format(" (%s)", firstAe.getDetailsForOther()) : ""; } else { fullName = firstAe.getAdverseEventTerm().getUniversalTerm(); } return String.format("Grade %d adverse event with term %s%s", firstAe.getGrade().getCode(), fullName, other); } else { throw new CaaersSystemException("Cannot create notification message until primary AE is filled in"); } } @Transient public Reporter getReviewer() { return reviewer; } public void setReviewer(Reporter reviewer) { this.reviewer = reviewer; } /** * Checks if is notification message possible. * * @return true, if is notification message possible */ @Transient public boolean isNotificationMessagePossible() { if (getAdverseEventsInternal().size() < 1) return false; AdverseEvent ae = getAdverseEventsInternal().get(0); return ae != null && ae.getGrade() != null && ae.getAdverseEventTerm().getTerm() != null; } /** * Gets the participant. * * @return the participant */ @Transient public Participant getParticipant() { return getAssignment() == null ? null : getAssignment().getParticipant(); } /** * Gets the study. * * @return the study */ @Transient public Study getStudy() { StudySite ss = getAssignment() == null ? null : getAssignment().getStudySite(); return ss == null ? null : ss.getStudy(); } /** * Gets the study site. * * @return the study site */ @Transient public StudySite getStudySite() { StudySite ss = getAssignment() == null ? null : getAssignment().getStudySite(); return ss; } @Transient public Map<String, String> getSummary() { return getSummary(true); } /** * Gets the summary. * * @return the summary */ @Transient public Map<String, String> getSummary(boolean unIdentifiedMode) { Map<String, String> summary = new LinkedHashMap<String, String>(); summary.put("Study", summaryLine(getStudy())); if (unIdentifiedMode) { summary.put("Participant", summaryLine(getAssignment())); } else { summary.put("Participant", summaryLine(getParticipant())); } summary.put("Report created at", getCreatedAt() == null ? null : getCreatedAt().toString()); String primaryAeLine = null; if (getAdverseEvents().size() > 0 && getAdverseEvents().get(0).getAdverseEventTerm() != null && getAdverseEvents().get(0).getAdverseEventTerm().getUniversalTerm() != null) { primaryAeLine = getAdverseEvents().get(0).getAdverseEventTerm().getUniversalTerm(); } summary.put("Primary AE", primaryAeLine); summary.put("AE count", Integer.toString(getAdverseEvents().size())); summary.put("Public identifier", getPublicIdentifier()); // TODO: placeholders summary.put("Ticket number", null); summary.put("Next report due", null); summary.put("Course", getReportingPeriod().getName()); return summary; } /** * Summary line. * * @param participant the participant * @return the string */ private String summaryLine(Participant participant) { if (participant == null) return null; StringBuilder sb = new StringBuilder(); appendPrimaryIdentifier(participant, sb); sb.append(" ").append(participant.getFullName()); return sb.toString(); } private String summaryLine(StudyParticipantAssignment assignment) { if (assignment == null) return null; StringBuilder sb = new StringBuilder(); sb.append(assignment.getStudySubjectIdentifier()); return sb.toString(); } /** * Summary line. * * @param study the study * @return the string */ private String summaryLine(Study study) { if (study == null) return null; StringBuilder sb = new StringBuilder(); appendPrimaryIdentifier(study, sb); sb.append(" ").append(study.getShortTitle()); return sb.toString(); } /** * Append primary identifier. * * @param ided the ided * @param sb the sb */ private void appendPrimaryIdentifier(IdentifiableByAssignedIdentifers ided, StringBuilder sb) { if (ided.getPrimaryIdentifier() != null) { sb.append(" (").append(ided.getPrimaryIdentifier().getValue()).append(')'); } } /** * Adds the adverse event. * * @param adverseEvent the adverse event */ public void addAdverseEvent(AdverseEvent adverseEvent) { if (adverseEvent != null) { getAdverseEventsInternal().add(adverseEvent); adverseEvent.setReport(this); } else { log.warn("Trying to add a null adverse event to a report. Stacktrace; ", new NullPointerException()); } } /** * To cover cases when we do not need the AdverseEvent to have a referrence to ExpeditedAdverseEventReport * @param adverseEvent */ public void addAdverseEventUnidirectional(AdverseEvent adverseEvent) { if (adverseEvent != null) { getAdverseEventsInternal().add(adverseEvent); } else { log.warn("Trying to add a null adverse event to a report. Stacktrace; ", new NullPointerException()); } } /** * This method will remove the {@link AdverseEvent} from the list and will * reset the {@link AdverseEvent#getReport()} association to null. However, * you're still responsible for persisting the updated {@link AdverseEvent} * instance, because the removal operation will not cascade. * * @param adverseEvent */ public void removeAdverseEvent(AdverseEvent adverseEvent) { adverseEvent.deleteAttributions(); getAdverseEventsInternal().remove(adverseEvent); adverseEvent.setReport(null); } /** * @param aeId * @return */ @Transient public AdverseEvent getAdverseEvent(int aeId) { for (AdverseEvent ae : getAdverseEventsInternal()) { if (ae.getId() != null && ae.getId() == aeId) { return ae; } } return null; } /** * Gets the adverse events. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient public List<AdverseEvent> getAdverseEvents() { return lazyListHelper.getLazyList(AdverseEvent.class); } /** * List of adverse events that are not retired. * * @return the active adverse events */ @Transient public List<AdverseEvent> getActiveAdverseEvents() { List<AdverseEvent> activeEvents = new ArrayList<AdverseEvent>(); for (AdverseEvent ae : getAdverseEvents()) { if (ae == null || ae.isRetired()) continue; activeEvents.add(ae); } return activeEvents; } /** * List of deleted adverse events. * @return */ @Transient public List<AdverseEvent> getRetiredAdverseEvents() { List<AdverseEvent> aes = new ArrayList<AdverseEvent>(); for (AdverseEvent ae : getAdverseEvents()) { if (ae == null) continue; if (ae.isRetired()) { aes.add(ae); } } return aes; } /** * List of active adverse events, that are modified. * * @return the active modified adverse events */ @Transient public List<AdverseEvent> getActiveModifiedAdverseEvents() { List<AdverseEvent> adverseEvents = new ArrayList<AdverseEvent>(); for (AdverseEvent ae : getActiveAdverseEvents()) { if (ae.isModified()) { adverseEvents.add(ae); } } return adverseEvents; } /** * This method will return all the adverse events,which got modified. * It is obtained by comparing the saved signature and newly calculated signature. * * @return the modified adverse events */ @Transient public List<AdverseEvent> getModifiedAdverseEvents() { List<AdverseEvent> adverseEvents = new ArrayList<AdverseEvent>(); for (AdverseEvent ae : getAdverseEvents()) { if (ae.isModified()) { adverseEvents.add(ae); } } return adverseEvents; } /** * Gets the modified adverse events. * * @param ruleableFields the ruleable fields * @return the modified adverse events * @author Ion C. Olaru * This method will return all the adverse events, which have at least one ruleable field modified */ @Transient public List<AdverseEvent> getModifiedAdverseEvents(List<String> ruleableFields) { List<AdverseEvent> adverseEvents = new ArrayList<AdverseEvent>(); for (AdverseEvent ae : getAdverseEvents()) { if (ae.isRuleableFieldsModified(ruleableFields)) { adverseEvents.add(ae); } } return adverseEvents; } /** * Adds the lab. * * @param lab the lab */ public void addLab(Lab lab) { getLabsInternal().add(lab); if (lab != null) lab.setReport(this); } /** * Adds the lab. * * @param lab the lab */ public void removeLab(Lab lab) { getLabsInternal().remove(lab); lab.setReport(null); } /** * Adds the RaditionIntervention. * * @param radiationIntervention the radiationIntervention */ public void removeRadiaitonIntervention(RadiationIntervention radiationIntervention) { getRadiationInterventionsInternal().remove(radiationIntervention); radiationIntervention.setReport(null); } /** * Adds the SurgeryIntervention. * * @param surgeryIntervention the surgeryIntervention */ public void removeSurgeryIntervention(SurgeryIntervention surgeryIntervention) { getSurgeryInterventionsInternal().remove(surgeryIntervention); surgeryIntervention.setReport(null); } /** * Gets the labs. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient public List<Lab> getLabs() { return lazyListHelper.getLazyList(Lab.class); } /** * Adds the medical device. * * @param medicalDevice the medical device */ public void addMedicalDevice(MedicalDevice medicalDevice) { getMedicalDevicesInternal().add(medicalDevice); if (medicalDevice != null) medicalDevice.setReport(this); } /** * Gets the medical devices. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient public List<MedicalDevice> getMedicalDevices() { return lazyListHelper.getLazyList(MedicalDevice.class); } /** * Adds the radiation intervention. * * @param radiationIntervention the radiation intervention */ public void addRadiationIntervention(RadiationIntervention radiationIntervention) { getRadiationInterventionsInternal().add(radiationIntervention); if (radiationIntervention != null) radiationIntervention.setReport(this); } /** * Gets the radiation interventions. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient public List<RadiationIntervention> getRadiationInterventions() { return lazyListHelper.getLazyList(RadiationIntervention.class); } /** * Adds the surgery intervention. * * @param surgeryIntervention the surgery intervention */ public void addSurgeryIntervention(SurgeryIntervention surgeryIntervention) { getSurgeryInterventionsInternal().add(surgeryIntervention); if (surgeryIntervention != null) surgeryIntervention.setReport(this); } public void addBehavioralIntervention(BehavioralIntervention i) { getBehavioralInterventionsInternal().add(i); if (i != null) i.setReport(this); } public void addBilogicalIntervention(BiologicalIntervention i) { getBiologicalInterventionsInternal().add(i); if (i != null) i.setReport(this); } public void addGeneticIntervention(GeneticIntervention i) { getGeneticInterventionsInternal().add(i); if (i != null) i.setReport(this); } public void addDietarySupplementalIntervention(DietarySupplementIntervention i) { getDietarySupplementInterventionsInternal().add(i); if (i != null) i.setReport(this); } public void addOtherAEIntervention(OtherAEIntervention i) { getOtherAEInterventionsInternal().add(i); if (i != null) i.setReport(this); } public void addAbstractAEIntervention(AbstractAEIntervention i) { if (i instanceof BehavioralIntervention) addBehavioralIntervention((BehavioralIntervention) i); if (i instanceof DietarySupplementIntervention) addDietarySupplementalIntervention((DietarySupplementIntervention) i); if (i instanceof GeneticIntervention) addGeneticIntervention((GeneticIntervention) i); if (i instanceof BiologicalIntervention) addBilogicalIntervention((BiologicalIntervention) i); if (i instanceof OtherAEIntervention) addOtherAEIntervention((OtherAEIntervention) i); } /** * Gets the surgery interventions. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient public List<SurgeryIntervention> getSurgeryInterventions() { return lazyListHelper.getLazyList(SurgeryIntervention.class); } @Transient public List<BehavioralIntervention> getBehavioralInterventions() { return lazyListHelper.getLazyList(BehavioralIntervention.class); } @Transient public List<BiologicalIntervention> getBiologicalInterventions() { return lazyListHelper.getLazyList(BiologicalIntervention.class); } @Transient public List<GeneticIntervention> getGeneticInterventions() { return lazyListHelper.getLazyList(GeneticIntervention.class); } @Transient public List<DietarySupplementIntervention> getDietaryInterventions() { return lazyListHelper.getLazyList(DietarySupplementIntervention.class); } @Transient public List<OtherAEIntervention> getOtherAEInterventions() { return lazyListHelper.getLazyList(OtherAEIntervention.class); } /** * Adds the concomitant medication. * * @param concomitantMedication the concomitant medication */ public void addConcomitantMedication(ConcomitantMedication concomitantMedication) { getConcomitantMedicationsInternal().add(concomitantMedication); if (concomitantMedication != null) concomitantMedication.setReport(this); } /** * Gets the concomitant medications. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient public List<ConcomitantMedication> getConcomitantMedications() { return lazyListHelper.getLazyList(ConcomitantMedication.class); } /** * Adds the sae report pre existing condition. * * @param sAEReportPreExistingCondition the s ae report pre existing condition */ public void addSaeReportPreExistingCondition(SAEReportPreExistingCondition sAEReportPreExistingCondition) { getSaeReportPreExistingConditionsInternal().add(sAEReportPreExistingCondition); if (sAEReportPreExistingCondition != null) sAEReportPreExistingCondition.setReport(this); } /** * Gets the sae report pre existing conditions. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient // @UniqueObjectInCollection(message = "Duplicate pre existing condition") public List<SAEReportPreExistingCondition> getSaeReportPreExistingConditions() { return lazyListHelper.getLazyList(SAEReportPreExistingCondition.class); } /** * Adds the sae report prior therapies. * * @param saeReportPriorTherapy the sae report prior therapy */ public void addSaeReportPriorTherapies(SAEReportPriorTherapy saeReportPriorTherapy) { getSaeReportPriorTherapiesInternal().add(saeReportPriorTherapy); if (saeReportPriorTherapy != null) saeReportPriorTherapy.setReport(this); } /** * Gets the sae report prior therapies. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient @UniqueObjectInCollection(message = "Duplicate prior therapy") public List<SAEReportPriorTherapy> getSaeReportPriorTherapies() { return lazyListHelper.getLazyList(SAEReportPriorTherapy.class); } /** * Adds the other cause. * * @param otherCause the other cause */ public void addOtherCause(OtherCause otherCause) { getOtherCausesInternal().add(otherCause); if (otherCause != null) otherCause.setReport(this); } /** * Gets the other causes. * * @return a wrapped list which will never throw an {@link IndexOutOfBoundsException} */ @Transient @UniqueObjectInCollection(message = "Duplicate other cause") public List<OtherCause> getOtherCauses() { return lazyListHelper.getLazyList(OtherCause.class); } ////// BEAN PROPERTIES @Column(name = "ide_administered") public Boolean getInvestigationalDeviceAdministered() { return investigationalDeviceAdministered; } public void setInvestigationalDeviceAdministered(Boolean investigationalDeviceAdministered) { this.investigationalDeviceAdministered = investigationalDeviceAdministered; } /** * Gets the assignment. * * @return the assignment */ @Transient public StudyParticipantAssignment getAssignment() { return getReportingPeriod().getAssignment(); } /** * Sets the assignment. * * @param assignment the new assignment */ public void setAssignment(StudyParticipantAssignment assignment) { this.reportingPeriod.setAssignment(assignment); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the adverse events internal. * * @return the adverse events internal */ @OneToMany @JoinColumn(name = "report_id", nullable = true) @IndexColumn(name = "list_index", nullable = false) @Cascade(value = { // Manually-managing PERSIST cascades due to cascade ordering issue CascadeType.DELETE, CascadeType.DETACH, CascadeType.LOCK, CascadeType.MERGE, CascadeType.REFRESH }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) public List<AdverseEvent> getAdverseEventsInternal() { return lazyListHelper.getInternalList(AdverseEvent.class); } /** * Sets the adverse events internal. * * @param adverseEvents the new adverse events internal */ public void setAdverseEventsInternal(List<AdverseEvent> adverseEvents) { lazyListHelper.setInternalList(AdverseEvent.class, adverseEvents); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the labs internal. * * @return the labs internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<Lab> getLabsInternal() { return lazyListHelper.getInternalList(Lab.class); } /** * Sets the labs internal. * * @param labsInternal the new labs internal */ protected void setLabsInternal(List<Lab> labsInternal) { lazyListHelper.setInternalList(Lab.class, labsInternal); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the medical devices internal. * * @return the medical devices internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<MedicalDevice> getMedicalDevicesInternal() { return lazyListHelper.getInternalList(MedicalDevice.class); } /** * Sets the medical devices internal. * * @param medicalDevicesInternal the new medical devices internal */ protected void setMedicalDevicesInternal(List<MedicalDevice> medicalDevicesInternal) { lazyListHelper.setInternalList(MedicalDevice.class, medicalDevicesInternal); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the radiation interventions internal. * * @return the radiation interventions internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<RadiationIntervention> getRadiationInterventionsInternal() { return lazyListHelper.getInternalList(RadiationIntervention.class); } /** * Sets the radiation interventions internal. * * @param radiationInterventionsInternal the new radiation interventions internal */ protected void setRadiationInterventionsInternal(List<RadiationIntervention> radiationInterventionsInternal) { lazyListHelper.setInternalList(RadiationIntervention.class, radiationInterventionsInternal); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the surgery interventions internal. * * @return the surgery interventions internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<SurgeryIntervention> getSurgeryInterventionsInternal() { return lazyListHelper.getInternalList(SurgeryIntervention.class); } @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<BehavioralIntervention> getBehavioralInterventionsInternal() { return lazyListHelper.getInternalList(BehavioralIntervention.class); } @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<BiologicalIntervention> getBiologicalInterventionsInternal() { return lazyListHelper.getInternalList(BiologicalIntervention.class); } @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<GeneticIntervention> getGeneticInterventionsInternal() { return lazyListHelper.getInternalList(GeneticIntervention.class); } @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<DietarySupplementIntervention> getDietarySupplementInterventionsInternal() { return lazyListHelper.getInternalList(DietarySupplementIntervention.class); } @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<OtherAEIntervention> getOtherAEInterventionsInternal() { return lazyListHelper.getInternalList(OtherAEIntervention.class); } /** * Sets the surgery interventions internal. * * @param surgeryInterventionsInternal the new surgery interventions internal */ protected void setSurgeryInterventionsInternal(List<SurgeryIntervention> surgeryInterventionsInternal) { lazyListHelper.setInternalList(SurgeryIntervention.class, surgeryInterventionsInternal); } protected void setBehavioralInterventionsInternal(List<BehavioralIntervention> l) { lazyListHelper.setInternalList(BehavioralIntervention.class, l); } protected void setBiologicalInterventionsInternal(List<BiologicalIntervention> l) { lazyListHelper.setInternalList(BiologicalIntervention.class, l); } protected void setGeneticInterventionsInternal(List<GeneticIntervention> l) { lazyListHelper.setInternalList(GeneticIntervention.class, l); } protected void setDietarySupplementInterventionsInternal(List<DietarySupplementIntervention> l) { lazyListHelper.setInternalList(DietarySupplementIntervention.class, l); } protected void setOtherAEInterventionsInternal(List<OtherAEIntervention> l) { lazyListHelper.setInternalList(OtherAEIntervention.class, l); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the concomitant medications internal. * * @return the concomitant medications internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<ConcomitantMedication> getConcomitantMedicationsInternal() { return lazyListHelper.getInternalList(ConcomitantMedication.class); } /** * Sets the concomitant medications internal. * * @param concomitantMedicationsInternal the new concomitant medications internal */ protected void setConcomitantMedicationsInternal(List<ConcomitantMedication> concomitantMedicationsInternal) { lazyListHelper.setInternalList(ConcomitantMedication.class, concomitantMedicationsInternal); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the sae report pre existing conditions internal. * * @return the sae report pre existing conditions internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<SAEReportPreExistingCondition> getSaeReportPreExistingConditionsInternal() { return lazyListHelper.getInternalList(SAEReportPreExistingCondition.class); } /** * Sets the sae report pre existing conditions internal. * * @param saeReportPreExistingConditionInternal the new sae report pre existing conditions internal */ protected void setSaeReportPreExistingConditionsInternal( List<SAEReportPreExistingCondition> saeReportPreExistingConditionInternal) { lazyListHelper.setInternalList(SAEReportPreExistingCondition.class, saeReportPreExistingConditionInternal); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the other causes internal. * * @return the other causes internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) protected List<OtherCause> getOtherCausesInternal() { return lazyListHelper.getInternalList(OtherCause.class); } /** * Sets the other causes internal. * * @param otherCausesInternal the new other causes internal */ protected void setOtherCausesInternal(List<OtherCause> otherCausesInternal) { lazyListHelper.setInternalList(OtherCause.class, otherCausesInternal); } // This is annotated this way so that the IndexColumn will work with // the bidirectional mapping. See section 2.4.6.2.3 of the hibernate annotations docs. /** * Gets the sae report prior therapies internal. * * @return the sae report prior therapies internal */ @OneToMany(orphanRemoval = true) @JoinColumn(name = "report_id", nullable = false) @IndexColumn(name = "list_index") @Cascade(value = { CascadeType.ALL }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) public List<SAEReportPriorTherapy> getSaeReportPriorTherapiesInternal() { return lazyListHelper.getInternalList(SAEReportPriorTherapy.class); } /** * Sets the sae report prior therapies internal. * * @param saeReportPriorTherapiesInternal the new sae report prior therapies internal */ public void setSaeReportPriorTherapiesInternal(List<SAEReportPriorTherapy> saeReportPriorTherapiesInternal) { lazyListHelper.setInternalList(SAEReportPriorTherapy.class, saeReportPriorTherapiesInternal); } /** * Gets the treatment information. * * @return the treatment information */ @OneToOne(fetch = FetchType.LAZY, mappedBy = "report", orphanRemoval = true) @Cascade(value = { CascadeType.ALL }) public TreatmentInformation getTreatmentInformation() { if (treatmentInformation == null) setTreatmentInformation(new TreatmentInformation()); return treatmentInformation; } /** * Sets the treatment information. * * @param treatmentInformation the new treatment information */ public void setTreatmentInformation(TreatmentInformation treatmentInformation) { this.treatmentInformation = treatmentInformation; if (treatmentInformation != null) treatmentInformation.setReport(this); } /** * Gets the additional information. * * @return the additional information */ @OneToOne(fetch = FetchType.LAZY, mappedBy = "report", orphanRemoval = true) @Cascade(value = { CascadeType.ALL }) public AdditionalInformation getAdditionalInformation() { if (additionalInformation == null) setAdditionalInformation(new AdditionalInformation()); return additionalInformation; } /** * Sets the additional information. * * @param additionalInformation the new additional information */ public void setAdditionalInformation(AdditionalInformation additionalInformation) { this.additionalInformation = additionalInformation; if (additionalInformation != null) additionalInformation.setReport(this); } /** * Gets the response description. * * @return the response description */ @OneToOne(fetch = FetchType.LAZY, mappedBy = "report", orphanRemoval = true) @Cascade(value = { CascadeType.ALL }) public AdverseEventResponseDescription getResponseDescription() { if (responseDescription == null) setResponseDescription(new AdverseEventResponseDescription()); return responseDescription; } /** * Sets the response description. * * @param responseDescription the new response description */ public void setResponseDescription(AdverseEventResponseDescription responseDescription) { this.responseDescription = responseDescription; if (responseDescription != null) responseDescription.setReport(this); } // non-total cascade allows us to skip saving if the reporter hasn't been filled in yet /** * Gets the reporter. * * @return the reporter */ @OneToOne(mappedBy = "expeditedReport", fetch = FetchType.LAZY) @Cascade(value = { CascadeType.DELETE, CascadeType.DETACH, CascadeType.LOCK, CascadeType.REMOVE }) public Reporter getReporter() { return reporter; } /** * Sets the reporter. * * @param reporter the new reporter */ public void setReporter(Reporter reporter) { this.reporter = reporter; if (reporter != null) reporter.setExpeditedReport(this); } // non-total cascade allows us to skip saving if the physician hasn't been filled in yet /** * Gets the physician. * * @return the physician */ @OneToOne(mappedBy = "expeditedReport", fetch = FetchType.LAZY) @Cascade(value = { CascadeType.DELETE, CascadeType.DETACH, CascadeType.LOCK, CascadeType.REMOVE, CascadeType.MERGE }) public Physician getPhysician() { return physician; } /** * Sets the physician. * * @param physician the new physician */ public void setPhysician(Physician physician) { this.physician = physician; if (physician != null) physician.setExpeditedReport(this); } /** * Gets the disease history. * * @return the disease history */ @OneToOne(mappedBy = "report", fetch = FetchType.LAZY) @Cascade(value = { CascadeType.ALL }) public DiseaseHistory getDiseaseHistory() { if (diseaseHistory == null) setDiseaseHistory(new DiseaseHistory()); return diseaseHistory; } /** * Sets the disease history. * * @param diseaseHistory the new disease history */ public void setDiseaseHistory(DiseaseHistory diseaseHistory) { this.diseaseHistory = diseaseHistory; if (diseaseHistory != null) diseaseHistory.setReport(this); } /** * Gets the participant history. * * @return the participant history */ @OneToOne(mappedBy = "report", fetch = FetchType.LAZY, orphanRemoval = true) @Cascade(value = { CascadeType.ALL }) public ParticipantHistory getParticipantHistory() { if (participantHistory == null) setParticipantHistory(new ParticipantHistory()); return participantHistory; } /** * Sets the participant history. * * @param participantHistory the new participant history */ public void setParticipantHistory(ParticipantHistory participantHistory) { this.participantHistory = participantHistory; if (participantHistory != null) participantHistory.setReport(this); } /** * Gets the reports. * * @return the reports */ @OneToMany(fetch = FetchType.LAZY, mappedBy = "aeReport") @Cascade(value = { CascadeType.DELETE, CascadeType.DETACH, CascadeType.LOCK, CascadeType.REMOVE }) @Fetch(value = org.hibernate.annotations.FetchMode.SUBSELECT) // Manually manage update-style reassociates and saves public List<Report> getReports() { if (reports == null) reports = new ArrayList<Report>(); return reports; } /** * True,when at least one Report is active. * * @return true, if is active */ @Transient public boolean isActive() { for (Report report : getReports()) { if (report.isActive()) return true; } return false; } /** * This method returns all the reports that are not in {@link ReportStatus}.WITHDRAWN or {@link ReportStatus}.REPLACED. * * @return the active reports */ @Transient public List<Report> getActiveReports() { List<Report> reports = getReports(); if (reports.isEmpty()) return reports; List<Report> activeReports = new ArrayList<Report>(); for (Report report : reports) { if (report.isActive()) activeReports.add(report); } return activeReports; } /** * Returns all the pending reports, that are in PENDING. * * @return the pending reports */ @Transient public List<Report> getPendingReports() { List<Report> pendingReports = new ArrayList<Report>(); for (Report report : getReports()) { if (ReportStatus.PENDING.equals(report.getStatus())) pendingReports.add(report); } return pendingReports; } /** * Tells whether an active report (ie. in PENDING, INPROCESS, FAILED) status, beloing to the same report definition is present. * * @param reportType the report type * @return true, if is an active report present */ @Transient public boolean isAnActiveReportPresent(ReportDefinition reportType) { for (Report report : getActiveReports()) { if (report.getReportDefinition().getId().equals(reportType.getId())) return true; } return false; } /** * Lists the reports that are completed and is amendable. * * @return the list */ public List<Report> findCompletedAmendableReports() { List<Report> completedReports = listReportsHavingStatus(ReportStatus.COMPLETED); List<Report> amendableReports = new ArrayList<Report>(); for (Report report : completedReports) { if (report.isAmendable()) amendableReports.add(report); } return amendableReports; } /** * Sets the reports. * * @param reports the new reports */ public void setReports(List<Report> reports) { this.reports = reports; } /** * Adds the report. * * @param report the report */ public void addReport(Report report) { getReports().add(report); report.setAeReport(this); } /** * Gets the created at. * * @return the created at */ public Timestamp getCreatedAt() { return createdAt; } /** * Sets the created at. * * @param createdAt the new created at */ public void setCreatedAt(Timestamp createdAt) { this.createdAt = createdAt; } /** * Gets the reporting period. * * @return the reporting period */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "reporting_period_id") @Cascade(value = { CascadeType.LOCK }) public AdverseEventReportingPeriod getReportingPeriod() { return reportingPeriod; } /** * Sets the reporting period. * * @param reportingPeriod the new reporting period */ public void setReportingPeriod(AdverseEventReportingPeriod reportingPeriod) { this.reportingPeriod = reportingPeriod; } public String getExternalId() { return externalId; } public void setExternalId(String externalId) { this.externalId = externalId; } /** * Gets the public identifier. * * @return the public identifier */ @Transient public String getPublicIdentifier() { String id = getAssignment().getStudySite().getOrganization().getNciInstituteCode() + "-" + getAssignment().getStudySite().getOrganization().getNciInstituteCode(); id = (id.indexOf("null") > -1) ? "None" : id; return id; } /** * Sets the public identifier. * * @param strId the new public identifier */ @Transient public void setPublicIdentifier(String strId) { } /** * Find phone numbers. * * @param role the role * @return the list */ @Transient List<String> findPhoneNumbers(String role) { assert false : "Not implemented"; return null; } /** * Find fax numbers. * * @param role the role * @return the list */ @Transient List<String> findFaxNumbers(String role) { assert false : "Not implemented"; return null; } /** * Gets the number of aes. * * @return the number of aes */ @Transient public int getNumberOfAes() { int count = (this.getAdverseEvents() != null) ? this.getAdverseEvents().size() : 0; return count; } /** * Gets the primary report. * * @return the primary report */ @Transient public Report getPrimaryReport() { return getReports().get(0); } /* you should call this method only once */ /** * Synchronize medical history from assignment to report. */ public void synchronizeMedicalHistoryFromAssignmentToReport() { StudyParticipantAssignment assignment = getAssignment(); if (assignment == null) { throw new CaaersSystemException( "Must set assignment before calling synchronizeMedicalHistoryFromAssignmentToReport"); } else { // synchronize from assignment to report getParticipantHistory().setBaselinePerformanceStatus(assignment.getBaselinePerformance()); syncrhonizePriorTherapies(); syncrhonizePreExistingConditions(); syncrhonizeConcomitantMedications(); syncrhonizeDiseaseHistories(); } } /** * synchronize prior therapies from assignment to report. */ private void syncrhonizePriorTherapies() { HashSet<String> set = new HashSet<String>(); if (getSaeReportPriorTherapies().isEmpty()) { //copy only once for (StudyParticipantPriorTherapy studyParticipantPriorTherapy : getAssignment().getPriorTherapies()) { if (studyParticipantPriorTherapy.getPriorTherapy() == null) continue; if (studyParticipantPriorTherapy.getPriorTherapy().isRetired()) continue; if (set.add(studyParticipantPriorTherapy.getDisplayName())) { SAEReportPriorTherapy priorTherapy = SAEReportPriorTherapy .createSAEReportPriorTherapy(studyParticipantPriorTherapy); addSaeReportPriorTherapies(priorTherapy); } } } } /** * Syncrhonize pre existing conditions. */ private void syncrhonizePreExistingConditions() { HashSet<String> set = new HashSet<String>(); if (getSaeReportPreExistingConditions().isEmpty()) { //copy only once for (StudyParticipantPreExistingCondition studyParticipantPreExistingCondition : getAssignment() .getPreExistingConditions()) { if (studyParticipantPreExistingCondition.getPreExistingCondition() == null) continue; if (studyParticipantPreExistingCondition.getPreExistingCondition().isRetired()) continue; if (set.add(studyParticipantPreExistingCondition.getName())) { SAEReportPreExistingCondition saeReportPreExistingCondition = SAEReportPreExistingCondition .createSAEReportPreExistingCondition(studyParticipantPreExistingCondition); addSaeReportPreExistingCondition(saeReportPreExistingCondition); } } } } /** * Syncrhonize concomitant medications. */ private void syncrhonizeConcomitantMedications() { HashSet<String> set = new HashSet<String>(); if (getConcomitantMedications().isEmpty()) { //copy only once for (StudyParticipantConcomitantMedication studyParticipantConcomitantMedication : getAssignment() .getConcomitantMedications()) { if (studyParticipantConcomitantMedication.getAgentName() == null) continue; if (set.add(studyParticipantConcomitantMedication.getAgentName())) { ConcomitantMedication saeReportConcomitantMedication = ConcomitantMedication .createConcomitantMedication(studyParticipantConcomitantMedication); addConcomitantMedication(saeReportConcomitantMedication); } } } } /** * Syncrhonize disease histories. */ private void syncrhonizeDiseaseHistories() { if ((getDiseaseHistory() == null) || (getDiseaseHistory() != null && getDiseaseHistory().getId() == null)) { //copy only once DiseaseHistory saeReportDiseaseHistory = DiseaseHistory .createDiseaseHistory(getAssignment().getDiseaseHistory()); setDiseaseHistory(saeReportDiseaseHistory); } } /** * This method returns true if any of the reports associated to this data-collection was submitted * successfully. * * @return the checks for submitted amendable report */ @Transient public Boolean getHasSubmittedAmendableReport() { for (Report report : reports) { if (report.isSubmitted() && report.isAmendable()) return true; } return false; } /** * This method returns true if the data-collection has atleast one amendable report. It returns false otherwise. * * @return the checks for amendable report */ @Transient public Boolean getHasAmendableReport() { Boolean hasAmendableReport = false; for (Report report : reports) { if (report.getReportDefinition().getAmendable()) hasAmendableReport = true; } return hasAmendableReport; } /** * Returns true if all of the active {@link Report} associated to this data collection, says attribution is requried. * * @return true, if is attribution required */ @Transient public boolean isAttributionRequired() { boolean attributionRequired = true; int activeCount = 0; for (Report report : getReports()) { if (!report.isActive()) continue; activeCount++; attributionRequired &= report.isAttributionRequired(); } return activeCount > 0 && attributionRequired; } /** * This method will update the signatures in all the adverse events associated to * this expedited data collection. */ public void updateSignatureOfAdverseEvents() { for (AdverseEvent ae : getAdverseEvents()) { ae.setSignature(ae.getCurrentSignature()); } } /** * This method will return the earliest graded date, of adverse events. * * @return the earliest adverse event graded date */ @Transient public Date getEarliestAdverseEventGradedDate() { Date d = null; for (AdverseEvent ae : getAdverseEvents()) { if (ae.getGradedDate() == null) continue; if (d == null) { d = ae.getGradedDate(); } else { d = (DateUtils.compateDateAndTime(ae.getGradedDate(), d) < 0) ? ae.getGradedDate() : d; } } return d; } /** * This method will set the reported flag on adverse events. */ public void updateReportedFlagOnAdverseEvents() { for (AdverseEvent ae : getAdverseEvents()) { ae.setReported(true); } } /** * This method will clear the post submission updated date on each of the adverse events. */ public void clearPostSubmissionUpdatedDate() { for (AdverseEvent ae : getAdverseEvents()) { ae.setPostSubmissionUpdatedDate(null); } } /** * Checks if is physician sign off required. * * @return true, if is physician sign off required */ @Transient public boolean isPhysicianSignOffRequired() { boolean physicianSignOffRequired = false; for (Report report : getReports()) { if (report.isActive()) physicianSignOffRequired |= report.getReportDefinition().getPhysicianSignOff(); } return physicianSignOffRequired; } /** * Gets the physician sign off. * * @return the physician sign off */ @Transient public Boolean getPhysicianSignOff() { Boolean physicianSignOff = true; for (Report report : getReports()) { if (report.getPhysicianSignoff() != null) physicianSignOff &= report.getPhysicianSignoff(); else physicianSignOff = false; } return physicianSignOff; } /** * Sets the physician sign off. * * @param physicianSignOff the new physician sign off */ @Transient public void setPhysicianSignOff(Boolean physicianSignOff) { for (Report report : getReports()) report.setPhysicianSignoff(physicianSignOff); } /** * List all the reports that were created manually. * @return - all {@link Report}s whose manuallySelected flag is set. */ @Transient public List<Report> getManuallySelectedReports() { ArrayList<Report> manuallySelectedReports = new ArrayList<Report>(); for (Report report : getActiveReports()) { if (report.isManuallySelected()) manuallySelectedReports.add(report); } return manuallySelectedReports; } /** * Lists out the report that completed, belonging to the same group and organization * of the {@link ReportDefinition} param rd. * * @param rd the rd * @return the list */ public List<Report> findReportsToAmmend(ReportDefinition rd) { List<Report> reports = listReportsHavingStatus(ReportStatus.COMPLETED); List<Report> reportsToAmmend = new ArrayList<Report>(); //check if the reports are amendable and belongs to same organization & group. for (Report report : reports) { ReportDefinition rdOther = report.getReportDefinition(); if (!rdOther.getAmendable()) continue; if (!rdOther.getOrganization().getId().equals(rd.getOrganization().getId())) continue; if (!rdOther.getGroup().getCode().equals(rd.getGroup().getCode())) continue; reportsToAmmend.add(report); } return reportsToAmmend; } /** * Find reports to witdraw. * * @param rd the rd * @return the list */ public List<Report> findReportsToWithdraw(ReportDefinition rd) { List<Report> reports = listReportsHavingStatus(ReportStatus.PENDING, ReportStatus.FAILED, ReportStatus.INPROCESS); List<Report> reportsToWitdraw = new ArrayList<Report>(); //check if they belong to same group/organization and rd is less than rdOther for (Report report : reports) { ReportDefinition rdOther = report.getReportDefinition(); if (rdOther.getId().equals(rd.getId())) continue; if (!rdOther.getOrganization().getId().equals(rd.getOrganization().getId())) continue; if (!rdOther.getGroup().getCode().equals(rd.getGroup().getCode())) continue; // int delta = rd.compareTo(rdOther); // if( delta < 0) continue; reportsToWitdraw.add(report); } return reportsToWitdraw; } /** * Find reports to edit. * * @param rd the rd * @return the list */ public List<Report> findReportsToEdit(ReportDefinition rd) { List<Report> reports = listReportsHavingStatus(ReportStatus.PENDING, ReportStatus.FAILED, ReportStatus.INPROCESS); List<Report> reportsToEdit = new ArrayList<Report>(); //check if they belong to the same report definition. for (Report report : reports) { if (report.getReportDefinition().getId().equals(rd.getId())) { reportsToEdit.add(report); } } return reportsToEdit; } /** * This method will find the recently amended report, that belongs to the same group and organization. * * @param rd the rd * @return the report */ public Report findLastAmendedReport(ReportDefinition rd) { List<Report> reports = listReportsHavingStatus(ReportStatus.AMENDED); Report theReport = null; for (Report report : reports) { if (report.isOfSameOrganizationAndType(rd)) { if (theReport == null) { theReport = report; } else { if (DateUtils.compateDateAndTime(theReport.getAmendedOn(), report.getAmendedOn()) < 0) { theReport = report; } } } } return theReport; } /** * The report that is instantiated last, and is belonging to same organization and type. * * @param rd the rd * @return the report */ public Report findLastSubmittedReport(ReportDefinition rd) { List<Report> reports = listReportsHavingStatus(ReportStatus.AMENDED, ReportStatus.COMPLETED); Report theReport = null; for (Report report : reports) { if (report.isOfSameOrganizationAndType(rd)) { if (theReport == null) { theReport = report; } else { if (DateUtils.compateDateAndTime(theReport.getSubmittedOn(), report.getSubmittedOn()) < 0) { theReport = report; } } } } return theReport; } /** * List reports having status. * * @param statuses the statuses * @return the list */ public List<Report> listReportsHavingStatus(ReportStatus... statuses) { List<Report> reports = new ArrayList<Report>(); for (Report report : getReports()) { if (report.isHavingStatus(statuses)) reports.add(report); } return reports; } /** * Will return true, if there is an organization of same group and type is already instantiated * on this expedited report. * * @param rd the rd * @return true, if successful */ public boolean hasExistingReportsOfSameOrganizationAndType(ReportDefinition rd) { for (Report report : getReports()) { if (report.isOfSameOrganizationAndType(rd)) return true; } return false; } /** * This method will return the AdverseEvent that is associated with this data collection, identified by ID. * * @param id the id * @return the adverse event */ public AdverseEvent findAdverseEventById(Integer id) { for (AdverseEvent ae : getAdverseEvents()) { if (ae.getId().equals(id)) return ae; } return null; } /** * Will find the labs with matching ID or Term otherwise treat it as new lab. * */ public Lab findLabsByTerm(Lab thatLab) { for (Lab l : getLabs()) { if (l.getLabTerm() != null && thatLab.getLabTerm() != null && ObjectUtils.equals(l.getLabTerm().getTerm(), thatLab.getLabTerm().getTerm())) return l; // Compare Term. } return null; } /** * Will find the Adverse Event that has matching * - externalId * - term * - dates * @param thatAe * @return */ @SuppressWarnings("rawtypes") public AdverseEvent findAdverseEventByIdTermAndDates(AdverseEvent thatAe) { for (AdverseEvent thisAe : getAdverseEvents()) { //are Ids matching ? if (ObjectUtils.equals(thisAe.getId(), thatAe.getId())) return thisAe; if (ObjectUtils.equals(thisAe.getExternalId(), thatAe.getExternalId())) return thisAe; AbstractAdverseEventTerm thisTerm = thisAe.getAdverseEventTerm(); AbstractAdverseEventTerm thatTerm = thatAe.getAdverseEventTerm(); if (thisTerm != null && thatTerm != null) //are dates matching ? if (DateUtils.compareDate(thisAe.getStartDate(), thatAe.getStartDate()) != 0) continue; if (DateUtils.compareDate(thisAe.getEndDate(), thatAe.getEndDate()) != 0) continue; DomainObject thisAeTerm = thisAe.getAdverseEventTerm() != null ? thisAe.getAdverseEventTerm().getTerm() : null; DomainObject thatAeTerm = thatAe.getAdverseEventTerm() != null ? thatAe.getAdverseEventTerm().getTerm() : null; if ((thisAeTerm == null && thatAeTerm != null) || (thisAeTerm != null && thatAeTerm == null)) continue; if (thisAeTerm == null && thatAeTerm == null) { //verbatim only AE entry if (!StringUtils.equals(thisAe.getDetailsForOther(), thatAe.getDetailsForOther())) continue; } else { //check terms if (!ObjectUtils.equals(thisAeTerm.getId(), thatAeTerm.getId())) continue; if (thisAeTerm instanceof AdverseEventCtcTerm) { //check other specify if (!StringUtils.equals(thisAe.getOtherSpecify(), thatAe.getOtherSpecify())) continue; //check other MedDRA Integer thisLltId = thisAe.getLowLevelTerm() != null ? thisAe.getLowLevelTerm().getId() : Integer.MIN_VALUE; Integer thatLltId = thatAe.getLowLevelTerm() != null ? thatAe.getLowLevelTerm().getId() : Integer.MIN_VALUE; if (!ObjectUtils.equals(thisLltId, thatLltId)) continue; } } //found a match return thisAe; } return null; } /** * This method will return the Report associated to this data collection, identified by ID. * * @param id the id * @return the report */ public Report findReportById(Integer id) { for (Report report : getReports()) { if (report.getId().equals(id)) return report; } return null; } /** * This method returns is used to determine if there are any active reports which are in a workflow. * * @return boolean */ public boolean hasWorkflowOnActiveReports() { boolean hasWorkflowOnActiveReports = false; for (Report r : getActiveReports()) if (r.getWorkflowId() != null) hasWorkflowOnActiveReports = true; return hasWorkflowOnActiveReports; } /** * Will create other cause from PreExistingCondition. */ public void autoGenerateOtherCauses() { for (SAEReportPreExistingCondition saePreCondition : getSaeReportPreExistingConditions()) { if (saePreCondition.getLinkedToOtherCause()) continue; //already linked to a cause. String preConditionName = saePreCondition.getName(); if (preConditionName == null) continue; OtherCause otherCause = findOtherCauseByCause(preConditionName); if (otherCause == null) { addOtherCause(new OtherCause(preConditionName)); saePreCondition.setLinkedToOtherCause(true); } } } /** * Will return the OtherCause matching the cause. * @param cause - The cause to find. * @return OtherCause if found, otherwise null. */ public OtherCause findOtherCauseByCause(String cause) { for (OtherCause otherCause : getOtherCauses()) { String otherCauseText = otherCause.getText(); if (StringUtils.equals(cause, otherCauseText)) return otherCause; } return null; } public boolean removeOtherCause(String cause) { OtherCause otherCause = findOtherCauseByCause(cause); if (otherCause != null) return getOtherCauses().remove(otherCause); return false; } @Transient public List<StudyTherapyType> getInterventionTypes() { List<StudyTherapyType> interventionTypes = new ArrayList<StudyTherapyType>(); if (CollectionUtils.isNotEmpty(getRadiationInterventions())) interventionTypes.add(StudyTherapyType.RADIATION); if (CollectionUtils.isNotEmpty(getSurgeryInterventions())) interventionTypes.add(StudyTherapyType.SURGERY); if (CollectionUtils.isNotEmpty(getBehavioralInterventions())) interventionTypes.add(StudyTherapyType.BEHAVIORAL); if (CollectionUtils.isNotEmpty(getBiologicalInterventionsInternal())) interventionTypes.add(StudyTherapyType.BIOLOGICAL_VACCINE); if (CollectionUtils.isNotEmpty(getGeneticInterventions())) interventionTypes.add(StudyTherapyType.GENETIC); if (CollectionUtils.isNotEmpty(getDietaryInterventions())) interventionTypes.add(StudyTherapyType.DIETARY_SUPPLEMENT); if (CollectionUtils.isNotEmpty(getOtherAEInterventions())) interventionTypes.add(StudyTherapyType.OTHER); if (CollectionUtils.isNotEmpty(getMedicalDevices())) interventionTypes.add(StudyTherapyType.DEVICE); if (CollectionUtils.isNotEmpty(getTreatmentInformation().getCourseAgents())) interventionTypes.add(StudyTherapyType.DRUG_ADMINISTRATION); return interventionTypes; } @SuppressWarnings("rawtypes") @Transient public List<AdverseEventAttribution> getAdverseEventAttributions() { List<AdverseEventAttribution> attributions = new ArrayList<AdverseEventAttribution>(); for (AdverseEvent ae : getAdverseEvents()) { attributions.addAll(ae.getAdverseEventAttributions()); } return attributions; } @Transient public boolean getHasNciIndAgent() { if (getTreatmentInformation().getCourseAgents() != null) { for (CourseAgent ca : getTreatmentInformation().getCourseAgents()) { if (ca.getStudyAgent() != null && ca.getStudyAgent().getHasIndHeldByNci()) return true; } } return false; } @Transient public boolean getHasNciIdeDevice() { if (getMedicalDevices() != null) { for (MedicalDevice md : getMedicalDevices()) { if (md.getStudyDevice() != null && md.getStudyDevice().getHasIdeHeldByNci()) return true; } } return false; } /** * When we delete an element which has been attributed, the attribution also needs to be deleted. * @param o */ public boolean cascaeDeleteToAttributions(DomainObject o) { for (AdverseEvent ae : getAdverseEvents()) { if (o instanceof RadiationIntervention) { ae.deleteAttribution(o, ae.getRadiationAttributions()); } else if (o instanceof MedicalDevice) { ae.deleteAttribution(o, ae.getDeviceAttributions()); } else if (o instanceof SurgeryIntervention) { ae.deleteAttribution(o, ae.getSurgeryAttributions()); } else if (o instanceof CourseAgent) { ae.deleteAttribution(o, ae.getCourseAgentAttributions()); } else if (o instanceof ConcomitantMedication) { ae.deleteAttribution(o, ae.getConcomitantMedicationAttributions()); } else if (o instanceof OtherCause) { ae.deleteAttribution(o, ae.getOtherCauseAttributions()); } else if (o instanceof DiseaseHistory) { ae.deleteAttribution(o, ae.getDiseaseAttributions()); } else if (o instanceof OtherAEIntervention) { ae.deleteAttribution(o, ae.getOtherInterventionAttributions()); } else if (o instanceof BehavioralIntervention) { ae.deleteAttribution(o, ae.getBehavioralInterventionAttributions()); } else if (o instanceof BiologicalIntervention) { ae.deleteAttribution(o, ae.getBiologicalInterventionAttributions()); } else if (o instanceof DietarySupplementIntervention) { ae.deleteAttribution(o, ae.getDietarySupplementInterventionAttributions()); } else if (o instanceof GeneticIntervention) { ae.deleteAttribution(o, ae.getGeneticInterventionAttributions()); } } return true; } /** * Insert a new Attribution for the a new Object * * @param o * @return */ public boolean addAttributionsToAEs(DomainObject o) { for (AdverseEvent ae : getAdverseEvents()) { ae.addAttribution(o, null); } return true; } public CourseAgent findReportCourseAgentByNscNumber(String nscNumber) { for (CourseAgent ca : getTreatmentInformation().getCourseAgents()) { if (ca.getStudyAgent().isRetired()) continue; if (ca.getStudyAgent().getAgent() != null && ca.getStudyAgent().getAgent().getNscNumber().equals(nscNumber)) { return ca; } else if (ca.getStudyAgent().getAgent() == null) { if (ca.getStudyAgent().getOtherAgent().equals(nscNumber)) { return ca; } } } return null; } public ConcomitantMedication findReportConcomitantMedication(ConcomitantMedication inputConcomitantMedication) { for (ConcomitantMedication cm : getConcomitantMedications()) { if (cm.equals(inputConcomitantMedication)) { return cm; } } return null; } public SurgeryIntervention findReportSurgeryInterventionBySiteAndDate(SurgeryIntervention surgeryIntervention) { for (SurgeryIntervention si : getSurgeryInterventions()) { if (si.getInterventionSite().getName().equals(surgeryIntervention.getInterventionSite().getName()) && DateUtils.compareDate(si.getInterventionDate(), surgeryIntervention.getInterventionDate()) == 0) { return si; } } return null; } public RadiationIntervention findReportRadiationInterventionByAdministrationAndLastTreatmentDate( RadiationIntervention radiationIntervention) { for (RadiationIntervention ri : getRadiationInterventions()) { if (DateUtils.compareDate(ri.getLastTreatmentDate(), radiationIntervention.getLastTreatmentDate()) == 0 && ri.getAdministration().equals(radiationIntervention.getAdministration())) { return ri; } } return null; } public MedicalDevice findReportMedicalDevice(MedicalDevice medicalDevice) { for (MedicalDevice md : getMedicalDevices()) { if (StringUtils.equals(md.getCommonName(), medicalDevice.getCommonName()) && StringUtils.equals(md.getBrandName(), medicalDevice.getBrandName()) && StringUtils.equals(md.getDeviceType(), medicalDevice.getDeviceType())) return md; } return null; } /** * Update the Signatures of the AE to identify the modification. */ public void updateAESignatures() { for (AdverseEvent ae : getAdverseEvents()) { ae.setSignature(ae.getCurrentSignature()); } } public Report findReportByCaseNumber(String caseNumber) { //Look in active reports first for (Report report : getActiveReports()) { if (report.getCaseNumber() != null && report.getCaseNumber().equalsIgnoreCase(caseNumber)) { return report; } } //check in others also for (Report report : getReports()) { if (report.getCaseNumber() != null && report.getCaseNumber().equalsIgnoreCase(caseNumber)) { return report; } } return null; } public AdverseEvent doesAnotherAeWithSameTermExist(AdverseEvent sae) { if (sae != null && sae.getAdverseEventCtcTerm() != null && sae.getAdverseEventCtcTerm().getCtcTerm() != null) { for (AdverseEvent ae : getAdverseEvents()) { if (ae != null && ae.getAdverseEventCtcTerm() != null && ae.getAdverseEventCtcTerm().getCtcTerm() != null) { if (sae.getAdverseEventCtcTerm().getCtcTerm() .equals(ae.getAdverseEventCtcTerm().getCtcTerm())) { if (!sae.getId().equals(ae.getId())) { return ae; } } } } } return null; } @Transient public List<AdverseEvent> getUnReportedAdverseEvents() { List<AdverseEvent> aes = new ArrayList<AdverseEvent>(); for (AdverseEvent ae : getActiveAdverseEvents()) { if (!BooleanUtils.isTrue(ae.getReported())) aes.add(ae); } return aes; } public void removeReport(String reportName) { List<Report> reportsToRemove = new ArrayList<Report>(); for (Report r : getReports()) { if (reportsToRemove.isEmpty() && StringUtils.equals(r.getName(), reportName)) reportsToRemove.add(r); } getReports().removeAll(reportsToRemove); } @Override public String toString() { return "ExpeditedAdverseEventReport [investigationalDeviceAdministered=" + investigationalDeviceAdministered + ", createdAt=" + createdAt + ", lazyListHelper=" + lazyListHelper + ", responseDescription=" + responseDescription + ", treatmentInformation=" + treatmentInformation + ", additionalInformation=" + additionalInformation + ", reporter=" + reporter + ", physician=" + physician + ", participantHistory=" + participantHistory + ", diseaseHistory=" + diseaseHistory + ", reportingPeriod=" + reportingPeriod + ", reports=" + reports + ", reviewer=" + reviewer + ", externalId=" + externalId + "]"; } }