package edu.ualberta.med.biobank.forms;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import edu.ualberta.med.biobank.SessionManager;
import edu.ualberta.med.biobank.common.action.processingEvent.ProcessingEventGetInfoAction;
import edu.ualberta.med.biobank.common.action.processingEvent.ProcessingEventGetInfoAction.PEventInfo;
import edu.ualberta.med.biobank.common.action.processingEvent.ProcessingEventSaveAction;
import edu.ualberta.med.biobank.common.action.specimen.SpecimenGetInfoAction;
import edu.ualberta.med.biobank.common.action.specimen.SpecimenInfo;
import edu.ualberta.med.biobank.common.formatters.DateFormatter;
import edu.ualberta.med.biobank.common.peer.ProcessingEventPeer;
import edu.ualberta.med.biobank.common.wrappers.CenterWrapper;
import edu.ualberta.med.biobank.common.wrappers.CommentWrapper;
import edu.ualberta.med.biobank.common.wrappers.ProcessingEventWrapper;
import edu.ualberta.med.biobank.common.wrappers.SpecimenWrapper;
import edu.ualberta.med.biobank.forms.input.FormInput;
import edu.ualberta.med.biobank.gui.common.validators.NonEmptyStringValidator;
import edu.ualberta.med.biobank.gui.common.widgets.BgcBaseText;
import edu.ualberta.med.biobank.gui.common.widgets.BgcEntryFormWidgetListener;
import edu.ualberta.med.biobank.gui.common.widgets.DateTimeWidget;
import edu.ualberta.med.biobank.gui.common.widgets.IInfoTableDoubleClickItemListener;
import edu.ualberta.med.biobank.gui.common.widgets.InfoTableEvent;
import edu.ualberta.med.biobank.gui.common.widgets.InfoTableSelection;
import edu.ualberta.med.biobank.gui.common.widgets.MultiSelectEvent;
import edu.ualberta.med.biobank.gui.common.widgets.utils.ComboSelectionUpdate;
import edu.ualberta.med.biobank.model.ActivityStatus;
import edu.ualberta.med.biobank.model.Comment;
import edu.ualberta.med.biobank.model.ProcessingEvent;
import edu.ualberta.med.biobank.model.Specimen;
import edu.ualberta.med.biobank.model.Study;
import edu.ualberta.med.biobank.treeview.AdapterBase;
import edu.ualberta.med.biobank.treeview.SpecimenAdapter;
import edu.ualberta.med.biobank.treeview.processing.ProcessingEventAdapter;
import edu.ualberta.med.biobank.validators.NotNullValidator;
import edu.ualberta.med.biobank.widgets.SpecimenEntryWidget;
import edu.ualberta.med.biobank.widgets.SpecimenEntryWidget.ItemAction;
import edu.ualberta.med.biobank.widgets.infotables.CommentsInfoTable;
import edu.ualberta.med.biobank.widgets.listeners.VetoListenerSupport.Event;
import edu.ualberta.med.biobank.widgets.listeners.VetoListenerSupport.VetoException;
import edu.ualberta.med.biobank.widgets.listeners.VetoListenerSupport.VetoListener;
import edu.ualberta.med.biobank.widgets.utils.GuiUtil;
public class ProcessingEventEntryForm extends BiobankEntryForm {
public static final String ID =
"edu.ualberta.med.biobank.forms.ProcessingEventEntryForm";
private static final String MSG_NEW_PEVENT_OK =
"Creating a new processing event";
private static final String MSG_PEVENT_OK =
"Editing a processing event";
private ProcessingEventAdapter pEventAdapter;
private ComboViewer activityStatusComboViewer;
private DateTimeWidget dateWidget;
private SpecimenEntryWidget specimenEntryWidget;
private ActivityStatus closedActivityStatus;
private CommentsInfoTable commentEntryTable;
private final ProcessingEventWrapper pevent = new ProcessingEventWrapper(
SessionManager.getAppService());
private final CommentWrapper comment = new CommentWrapper(
SessionManager.getAppService());
private List<SpecimenInfo> specimens;
protected Study study;
@Override
protected void init() throws Exception {
Assert.isTrue(adapter instanceof ProcessingEventAdapter,
"Invalid editor input: object of type "
+ adapter.getClass().getName());
pEventAdapter = (ProcessingEventAdapter) adapter;
setPEventInfo(adapter.getId());
String tabName;
if (pEventAdapter.getId() == null) {
tabName = "New processing event";
} else {
if (pevent.getWorksheet() == null)
tabName =
NLS.bind(
"Processing event {0} on {1}",
pevent.getWorksheet(), pevent.getFormattedCreatedAt());
else
tabName =
NLS.bind(
"Processing event date {0}",
DateFormatter.formatAsDateTime(pevent.getCreatedAt()));
}
closedActivityStatus = ActivityStatus.CLOSED;
setPartName(tabName);
}
private void setPEventInfo(Integer id) throws Exception {
if (id == null) {
ProcessingEvent p = new ProcessingEvent();
p.setActivityStatus(ActivityStatus.ACTIVE);
pevent.setWrappedObject(p);
pevent
.setCenter(SessionManager.getUser().getCurrentWorkingCenter());
specimens = new ArrayList<SpecimenInfo>();
} else {
PEventInfo read =
SessionManager.getAppService().doAction(
new ProcessingEventGetInfoAction(adapter.getId()));
pevent.setWrappedObject(read.pevent);
specimens = read.sourceSpecimenInfos;
SessionManager.logLookup(read.pevent);
}
comment.setWrappedObject(new Comment());
}
@Override
protected void createFormContent() throws Exception {
form.setText("Processing event information");
form.setMessage(getOkMessage(), IMessageProvider.NONE);
page.setLayout(new GridLayout(1, false));
createMainSection();
createSpecimensSection();
}
private void createMainSection() {
Composite client = toolkit.createComposite(page);
GridLayout layout = new GridLayout(2, false);
layout.horizontalSpacing = 10;
client.setLayout(layout);
client.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
toolkit.paintBordersFor(client);
createReadOnlyLabelledField(client, SWT.NONE,
"Center", pevent.getCenter()
.getName());
dateWidget =
createDateTimeWidget(
client,
"Start time",
pevent.getCreatedAt(),
pevent,
ProcessingEventPeer.CREATED_AT.getName(),
new NotNullValidator(
"A creation date/time should be selected"));
setFirstControl(dateWidget);
createBoundWidgetWithLabel(client, BgcBaseText.class, SWT.NONE,
"Worksheet", null, pevent,
ProcessingEventPeer.WORKSHEET.getName(),
(!pevent.isNew() && pevent.getWorksheet() == null) ? null
: new NonEmptyStringValidator(
"Worksheet cannot be null"));
activityStatusComboViewer =
createComboViewer(
client,
"Activity status",
ActivityStatus.valuesList(),
pevent.getActivityStatus(),
"Processing event must have an activity status ",
new ComboSelectionUpdate() {
@Override
public void doSelection(Object selectedObject) {
setDirty(true);
pevent
.setActivityStatus((ActivityStatus) selectedObject);
}
});
if (pevent.getActivityStatus() != null) {
activityStatusComboViewer.setSelection(new StructuredSelection(
pevent.getActivityStatus()));
setDirty(false);
}
createCommentSection();
}
private void createCommentSection() {
Composite client = createSectionWithClient("Comments");
GridLayout gl = new GridLayout(2, false);
client.setLayout(gl);
commentEntryTable =
new CommentsInfoTable(client,
pevent.getCommentCollection(false));
GridData gd = new GridData();
gd.horizontalSpan = 2;
gd.grabExcessHorizontalSpace = true;
gd.horizontalAlignment = SWT.FILL;
commentEntryTable.setLayoutData(gd);
createBoundWidgetWithLabel(client, BgcBaseText.class,
SWT.MULTI, "Add a comment", null, comment, "message", null);
}
private void createSpecimensSection() {
Assert.isNotNull(SessionManager.getUser().getCurrentWorkingCenter());
Composite client =
createSectionWithClient("Source specimens");
GridLayout layout = new GridLayout(1, false);
client.setLayout(layout);
client.setLayoutData(new GridData(GridData.FILL, GridData.FILL));
toolkit.paintBordersFor(client);
specimenEntryWidget =
new SpecimenEntryWidget(client, SWT.NONE, toolkit, true);
specimenEntryWidget
.addSelectionChangedListener(new BgcEntryFormWidgetListener() {
@Override
public void selectionChanged(MultiSelectEvent event) {
setDirty(true);
}
});
specimenEntryWidget
.addDoubleClickListener(new IInfoTableDoubleClickItemListener<SpecimenInfo>() {
@Override
public void doubleClick(InfoTableEvent<SpecimenInfo> event) {
Specimen s =
((SpecimenInfo) ((InfoTableSelection) event
.getSelection()).getObject()).specimen;
AdapterBase.openForm(
new FormInput(
new SpecimenAdapter(null,
new SpecimenWrapper(SessionManager
.getAppService(), s))),
SpecimenViewForm.ID);
}
});
VetoListener<ItemAction, SpecimenWrapper> vetoListener =
new VetoListener<ItemAction, SpecimenWrapper>() {
@Override
public void handleEvent(Event<ItemAction, SpecimenWrapper> event)
throws VetoException {
SpecimenWrapper specimen = event.getObject();
switch (event.getType()) {
case PRE_ADD:
if (specimen == null)
throw new VetoException(
"No specimen found for that inventory id.");
else if (!SessionManager.getUser()
.getCurrentWorkingCenter()
.equals(specimen.getCurrentCenter())) {
String centerName =
"'none'";
if (specimen.getCurrentCenter() != null)
centerName =
specimen.getCurrentCenter().getNameShort();
throw new VetoException(
NLS.bind(
"Specimen is currently in center {0}. You can''t process it.",
centerName));
} else if (specimen.getProcessingEvent() != null) {
throw new VetoException(
NLS.bind(
"This specimen is already in processing event ''{0}'' ({1}). Remove it from the other processing event first.",
specimen.getProcessingEvent()
.getWorksheet(), specimen
.getProcessingEvent()
.getFormattedCreatedAt()));
} else if (!specimen.isActive())
throw new VetoException(
NLS.bind(
"This specimen has status ''{0}''. Only ''Active'' specimens can be added to a processing event.",
specimen.getActivityStatus().getName()));
else if (specimen.isUsedInDispatch())
throw new VetoException(
"Specimen is currently listed in a dispatch.");
else if (specimen.getParentContainer() != null)
throw new VetoException(
"Specimen is currently listed as stored in a container.");
else if (!SessionManager.getUser()
.getCurrentWorkingCenter().getStudyCollection()
.contains(
specimen.getCollectionEvent().getPatient()
.getStudy()))
throw new VetoException(
NLS.bind(
"This specimen is from study ''{0}''. This study is not linked to your current working center. Processing is not allowed.",
specimen.getCollectionEvent().getPatient()
.getStudy().getNameShort()));
else if (study == null) {
if (specimens.size() == 0)
study =
specimen.getCollectionEvent().getPatient()
.getStudy().getWrappedObject();
else {
try {
study = SessionManager
.getAppService()
.doAction(
new SpecimenGetInfoAction(specimens
.get(0).specimen.getId()))
.getSpecimen().getCollectionEvent()
.getPatient().getStudy();
} catch (Exception e) {
throw new VetoException(
"All Specimens must be part of the same study.");
}
}
}
if (!specimen.getCollectionEvent().getPatient()
.getStudy().getWrappedObject().equals(study))
throw new VetoException(
"In a processing event, all specimens must be part of the same study.");
case POST_ADD:
specimen.setProcessingEvent(pevent);
specimen.setActivityStatus(closedActivityStatus);
break;
case PRE_DELETE:
if (specimen.getChildSpecimenCollection(false).size() != 0)
throw new VetoException(
"Cannot remove processed specimens with children.");
}
}
};
specimenEntryWidget.addBinding(widgetCreator,
"Specimens should be added to a processing event");
specimenEntryWidget.addVetoListener(ItemAction.PRE_ADD, vetoListener);
specimenEntryWidget.addVetoListener(ItemAction.POST_ADD, vetoListener);
specimenEntryWidget
.addVetoListener(ItemAction.PRE_DELETE, vetoListener);
specimenEntryWidget.addVetoListener(ItemAction.POST_DELETE,
vetoListener);
specimenEntryWidget.setSpecimens(specimens);
}
@Override
protected void saveForm() throws Exception {
Set<Integer> added = new HashSet<Integer>();
Set<Integer> removed = new HashSet<Integer>();
for (SpecimenInfo spec : specimenEntryWidget.getAddedSpecimens())
added.add(spec.specimen.getId());
for (SpecimenInfo spec : specimenEntryWidget.getRemovedSpecimens())
removed.add(spec.specimen.getId());
Integer peventId =
SessionManager
.getAppService()
.doAction(
new ProcessingEventSaveAction(pevent.getId(), pevent
.getCenter().getId(), pevent.getCreatedAt(), pevent
.getWorksheet(), pevent.getActivityStatus(), comment
.getMessage(),
added, removed)).getId();
pevent.setId(peventId);
((AdapterBase) adapter).setModelObject(pevent);
}
@Override
protected void doAfterSave() throws Exception {
SessionManager.updateAllSimilarNodes(pEventAdapter, true);
}
@Override
protected String getOkMessage() {
return (pevent.isNew()) ? MSG_NEW_PEVENT_OK : MSG_PEVENT_OK;
}
@Override
public String getNextOpenedFormId() {
return ProcessingEventViewForm.ID;
}
@Override
public void setValues() throws Exception {
CenterWrapper<?> center = pevent.getCenter();
pevent.reset();
pevent.setCenter(center);
if (pevent.isNew()) {
pevent.setActivityStatus(ActivityStatus.ACTIVE);
}
GuiUtil.reset(activityStatusComboViewer, pevent.getActivityStatus());
specimenEntryWidget.setSpecimens(specimens);
}
}