package edu.ualberta.med.biobank.forms;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.databinding.observable.value.WritableValue;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import edu.ualberta.med.biobank.SessionManager;
import edu.ualberta.med.biobank.common.action.patient.PatientGetCollectionEventInfosAction.PatientCEventInfo;
import edu.ualberta.med.biobank.common.action.patient.PatientGetInfoAction;
import edu.ualberta.med.biobank.common.action.patient.PatientGetInfoAction.PatientInfo;
import edu.ualberta.med.biobank.common.action.patient.PatientMergeAction;
import edu.ualberta.med.biobank.common.action.patient.PatientSearchAction;
import edu.ualberta.med.biobank.common.action.patient.PatientSearchAction.SearchedPatientInfo;
import edu.ualberta.med.biobank.common.wrappers.PatientWrapper;
import edu.ualberta.med.biobank.common.wrappers.StudyWrapper;
import edu.ualberta.med.biobank.gui.common.BgcPlugin;
import edu.ualberta.med.biobank.gui.common.widgets.BgcBaseText;
import edu.ualberta.med.biobank.treeview.patient.PatientAdapter;
import edu.ualberta.med.biobank.treeview.patient.PatientSearchedNode;
import edu.ualberta.med.biobank.views.CollectionView;
import edu.ualberta.med.biobank.widgets.infotables.ClinicVisitInfoTable;
import gov.nih.nci.system.applicationservice.ApplicationException;
public class PatientMergeForm extends BiobankEntryForm {
public static final String ID =
"edu.ualberta.med.biobank.forms.PatientMergeForm";
public static final String MSG_PATIENT_NOT_VALID =
"Select a second patient";
private PatientWrapper patient1 = new PatientWrapper(
SessionManager.getAppService());
private PatientWrapper patient2 = new PatientWrapper(
SessionManager.getAppService());
private BgcBaseText study2Text;
private ClinicVisitInfoTable patient2VisitsTable;
private BgcBaseText pnumber2Text;
private BgcBaseText pnumber1Text;
private BgcBaseText study1Text;
private IObservableValue patientNotNullValue;
private ClinicVisitInfoTable patient1VisitsTable;
private boolean canMerge;
private PatientInfo p;
@Override
public void init() throws Exception {
Assert.isTrue((adapter instanceof PatientAdapter),
"Invalid editor input: object of type "
+ adapter.getClass().getName());
p = SessionManager
.getAppService().doAction(
new PatientGetInfoAction(adapter.getId()));
patient1 =
new PatientWrapper(SessionManager.getAppService());
patient1.setWrappedObject(p.patient);
String tabName = NLS.bind("Merging Patient {0}",
patient1.getPnumber());
setPartName(tabName);
patientNotNullValue = new WritableValue(Boolean.FALSE, Boolean.class);
widgetCreator.addBooleanBinding(new WritableValue(Boolean.FALSE,
Boolean.class), patientNotNullValue, MSG_PATIENT_NOT_VALID);
}
@Override
protected void createFormContent() throws Exception {
form.setText(NLS.bind("Merging into Patient {0}",
patient1.getPnumber()));
page.setLayout(new GridLayout(1, false));
form.setImage(BgcPlugin.getDefault().getImageRegistry()
.get(BgcPlugin.IMG_PATIENT));
toolkit.createLabel(
page,
NLS.bind("Select Patient Number to merge into Patient {0} and press Enter",
patient1.getPnumber()), SWT.LEFT);
createPatientSection();
}
private void createPatientSection() {
Composite client = toolkit.createComposite(page);
GridLayout toplayout = new GridLayout(3, false);
toplayout.horizontalSpacing = 10;
client.setLayout(toplayout);
client.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Composite patientArea1 = toolkit.createComposite(client);
GridLayout patient1Layout = new GridLayout(2, false);
patient1Layout.horizontalSpacing = 10;
patientArea1.setLayout(patient1Layout);
GridData patient1Data = new GridData();
patient1Data.grabExcessHorizontalSpace = true;
patient1Data.horizontalAlignment = SWT.FILL;
patient1Data.verticalAlignment = SWT.FILL;
patientArea1.setLayoutData(patient1Data);
Label arrow = toolkit.createLabel(client, "Arrow", SWT.IMAGE_BMP);
arrow.setImage(BgcPlugin.getDefault().getImageRegistry()
.get(BgcPlugin.IMG_ARROW_LEFT2));
Composite patientArea2 = toolkit.createComposite(client);
GridLayout patient2Layout = new GridLayout(2, false);
patient2Layout.horizontalSpacing = 10;
patientArea2.setLayout(patient2Layout);
GridData patient2Data = new GridData();
patient2Data.grabExcessHorizontalSpace = true;
patient2Data.horizontalAlignment = SWT.FILL;
patient2Data.verticalAlignment = SWT.FILL;
patientArea2.setLayoutData(patient2Data);
toolkit.paintBordersFor(client);
pnumber1Text = createReadOnlyLabelledField(patientArea1, SWT.NONE,
"Patient Number");
pnumber1Text.setText(patient1.getPnumber());
pnumber2Text = (BgcBaseText) createLabelledWidget(patientArea2,
BgcBaseText.class, SWT.NONE,
"Patient Number");
pnumber2Text.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
patientNotNullValue.setValue(Boolean.FALSE);
}
@Override
public void keyReleased(KeyEvent e) {
if (e.keyCode == SWT.CR)
populateFields(pnumber2Text.getText());
}
});
pnumber2Text.addTraverseListener(new TraverseListener() {
@Override
public void keyTraversed(TraverseEvent e) {
if (e.keyCode == SWT.TAB)
populateFields(pnumber2Text.getText());
}
});
setFirstControl(pnumber2Text);
StudyWrapper selectedStudy = patient1.getStudy();
study1Text = createReadOnlyLabelledField(patientArea1, SWT.NONE,
"Study");
study1Text.setText(selectedStudy.getNameShort());
study2Text = createReadOnlyLabelledField(patientArea2, SWT.NONE,
"Study");
patient1VisitsTable = new ClinicVisitInfoTable(patientArea1,
p.ceventInfos);
GridData gd1 = new GridData();
gd1.horizontalSpan = 2;
gd1.grabExcessHorizontalSpace = true;
gd1.horizontalAlignment = SWT.FILL;
patient1VisitsTable.setLayoutData(gd1);
patient1VisitsTable.adaptToToolkit(toolkit, true);
patient2VisitsTable = new ClinicVisitInfoTable(patientArea2,
new ArrayList<PatientCEventInfo>());
GridData gd2 = new GridData();
gd2.horizontalSpan = 2;
gd2.grabExcessHorizontalSpace = true;
gd2.horizontalAlignment = SWT.FILL;
patient2VisitsTable.setLayoutData(gd2);
patient2VisitsTable.adaptToToolkit(toolkit, true);
}
protected void populateFields(String pnumber) {
PatientInfo p2;
List<PatientCEventInfo> newContents =
new ArrayList<PatientCEventInfo>();
try {
SearchedPatientInfo pinfo =
SessionManager.getAppService().doAction(
new PatientSearchAction(pnumber));
if (pinfo == null)
throw new ApplicationException(
"Patient not found");
p2 = SessionManager
.getAppService().doAction(
new PatientGetInfoAction(pinfo.patient.getId()));
patient2 =
new PatientWrapper(SessionManager.getAppService());
patient2.setWrappedObject(p2.patient);
} catch (ApplicationException e) {
BgcPlugin.openAsyncError(
"Error retrieving patient", e);
patient2VisitsTable.setList(newContents);
study2Text.setText("");
return;
}
if (patient2 == null) {
BgcPlugin.openAsyncError(
"Invalid Patient Number",
"Cannot find a patient with that pnumber");
patient2VisitsTable.setList(newContents);
study2Text.setText("");
return;
}
if (patient2.equals(patient1)) {
BgcPlugin.openAsyncError(
"Duplicate Patient Number",
"Cannot merge a patient with himself");
patient2VisitsTable.setList(newContents);
return;
}
study2Text.setText(patient2.getStudy().getNameShort());
if (!patient2.getStudy().equals(patient1.getStudy())) {
patient2VisitsTable.setList(newContents);
BgcPlugin.openAsyncError(
"Invalid Patient Number",
"Patients from different studies cannot be merged");
} else {
patient2VisitsTable.setList(p2.ceventInfos);
patientNotNullValue.setValue(Boolean.TRUE);
}
}
@Override
protected void doBeforeSave() throws Exception {
canMerge = false;
if (patient2 != null) {
if (BgcPlugin.openConfirm(
"Confirm Merge",
NLS.bind("Are you sure you want to merge patient {0} into patient {1}? All collection events, source specimens, and aliquoted specimens will be transferred.",
patient2.getPnumber(), patient1.getPnumber()))) {
canMerge = true;
}
}
}
@Override
protected void saveForm() throws Exception {
if (canMerge) {
boolean success = false;
try {
success =
SessionManager
.getAppService()
.doAction(
new PatientMergeAction(patient1.getId(), patient2
.getId())).isTrue();
} catch (Exception e) {
BgcPlugin.openAsyncError(
"Merge failed.", e);
return;
}
final boolean patientRemoved = success;
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
if (patientRemoved) {
TreePath[] expandedTreePaths = CollectionView
.getCurrent().getTreeViewer()
.getExpandedTreePaths();
PatientSearchedNode searcher = CollectionView
.getCurrent().getSearchedNode();
searcher.removeAll();
searcher.removePatient(patient2.getId());
searcher.rebuild();
CollectionView.getCurrent().getTreeViewer()
.setExpandedTreePaths(expandedTreePaths);
}
closeEntryOpenView(false, true);
}
});
SessionManager.log("merge",
patient2.getPnumber() + " " + "-->"
+ " " + patient1.getPnumber(),
"Patient");
}
}
@Override
public void setValues() throws Exception {
pnumber1Text.setText(patient1.getPnumber());
study1Text.setText(patient1.getStudy().getNameShort());
patient1VisitsTable.setList(p.ceventInfos);
pnumber2Text.setText("");
study2Text.setText("");
patient2VisitsTable
.setList(new ArrayList<PatientCEventInfo>());
patient2 = null;
}
@Override
protected String getOkMessage() {
return NLS.bind("Patient {0} will be merged into patient {1}",
patient2.getPnumber(), patient1.getPnumber());
}
@Override
public String getNextOpenedFormId() {
return PatientViewForm.ID;
}
}