Encounter encounter = highestOnStack(Encounter.class);
if (encounter == null)
throw new IllegalArgumentException("Cannot change state without an Encounter");
// fetch any existing patient program with a state from this workflow
PatientProgram patientProgram = HtmlFormEntryUtil.getPatientProgramByWorkflow(patient, state.getProgramWorkflow());
// if no existing patient program, see if a patient program for this program is already set to be created at part of this submission (HTML-416)
if (patientProgram == null) {
patientProgram = HtmlFormEntryUtil.getPatientProgramByProgram(patientProgramsToCreate, state.getProgramWorkflow().getProgram());
}
if (patientProgram == null) {
patientProgram = HtmlFormEntryUtil.getPatientProgramByProgram(patientProgramsToUpdate, state.getProgramWorkflow().getProgram());
}
// if patient program is still null, we need to create a new program
if (patientProgram == null) {
patientProgram = new PatientProgram();
patientProgram.setPatient(patient);
patientProgram.setProgram(state.getProgramWorkflow().getProgram());
patientProgram.setDateEnrolled(encounter.getEncounterDatetime());
// HACK: we need to set the date created, creator, and uuid here as a hack around a hibernate flushing issue
// (should be able to remove this once we move to Hibernate Interceptors instead of Spring AOP to set these parameters)
patientProgram.setDateCreated(new Date());
patientProgram.setCreator(Context.getAuthenticatedUser());
patientProgram.setUuid(UUID.randomUUID().toString());
}
for (PatientState patientState : patientProgram.statesInWorkflow(state.getProgramWorkflow(), false)) {
if (patientState.getActive(encounter.getEncounterDatetime())) {
if (patientState.getState().equals(state)) {
return;
}
}
}
PatientState previousState = null;
PatientState nextState = null;
PatientState newState = new PatientState();
newState.setPatientProgram(patientProgram);
newState.setState(state);
newState.setStartDate(encounter.getEncounterDatetime());
// HACK: we need to set the date created, creator, and uuid here as a hack around a hibernate flushing issue
// (should be able to remove this once we move to Hibernate Interceptors instead of Spring AOP to set these parameters)
newState.setDateCreated(new Date());
newState.setCreator(Context.getAuthenticatedUser());
newState.setUuid(UUID.randomUUID().toString());
Collection<PatientState> sortedStates = new TreeSet<PatientState>(new Comparator<PatientState>() {
@Override
public int compare(PatientState o1, PatientState o2) {
int result = OpenmrsUtil.compareWithNullAsEarliest(o1.getStartDate(), o2.getStartDate());
if (result == 0) {
result = OpenmrsUtil.compareWithNullAsLatest(o1.getEndDate(), o2.getEndDate());
}
return result;
}
});
sortedStates.addAll(patientProgram.statesInWorkflow(state.getProgramWorkflow(), false));
for (PatientState currentState : sortedStates) {
Date newStartDate = newState.getStartDate();
Date currentStartDate = currentState.getStartDate();
Date currentEndDate = currentState.getEndDate();
if (currentEndDate != null) {
if (currentEndDate.after(newStartDate)) {
if (currentStartDate.after(newStartDate)) {
nextState = currentState;
break;
} else {
previousState = currentState;
}
} else {
previousState = currentState;
}
} else if (currentStartDate.after(newStartDate)) {
nextState = currentState;
break;
} else {
previousState = currentState;
nextState = null;
break;
}
}
if (nextState == null) {
if (previousState != null) {
previousState.setEndDate(newState.getStartDate());
}
} else {
if (previousState != null) {
previousState.setEndDate(newState.getStartDate());
}
newState.setEndDate(nextState.getStartDate());
}
patientProgram.getStates().add(newState);
patientProgramsToUpdate.add(patientProgram);
}