package edu.ualberta.med.biobank.forms; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; 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.window.Window; 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 org.eclipse.swt.widgets.Label; import edu.ualberta.med.biobank.SessionManager; import edu.ualberta.med.biobank.common.action.info.OriginInfoSaveInfo; import edu.ualberta.med.biobank.common.action.info.ShipmentInfoSaveInfo; import edu.ualberta.med.biobank.common.action.info.ShipmentReadInfo; import edu.ualberta.med.biobank.common.action.originInfo.OriginInfoSaveAction; import edu.ualberta.med.biobank.common.action.shipment.ShipmentGetInfoAction; import edu.ualberta.med.biobank.common.action.specimen.SpecimenInfo; import edu.ualberta.med.biobank.common.peer.ShipmentInfoPeer; import edu.ualberta.med.biobank.common.wrappers.CenterWrapper; import edu.ualberta.med.biobank.common.wrappers.ClinicWrapper; import edu.ualberta.med.biobank.common.wrappers.CommentWrapper; import edu.ualberta.med.biobank.common.wrappers.OriginInfoWrapper; import edu.ualberta.med.biobank.common.wrappers.ShipmentInfoWrapper; import edu.ualberta.med.biobank.common.wrappers.ShippingMethodWrapper; import edu.ualberta.med.biobank.common.wrappers.SiteWrapper; import edu.ualberta.med.biobank.common.wrappers.SpecimenWrapper; import edu.ualberta.med.biobank.common.wrappers.helpers.SiteQuery; import edu.ualberta.med.biobank.dialogs.SpecimenOriginSelectDialog; 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.Comment; import edu.ualberta.med.biobank.model.OriginInfo; import edu.ualberta.med.biobank.model.ShipmentInfo; import edu.ualberta.med.biobank.model.Specimen; import edu.ualberta.med.biobank.treeview.AdapterBase; import edu.ualberta.med.biobank.treeview.SpecimenAdapter; import edu.ualberta.med.biobank.treeview.shipment.ShipmentAdapter; import edu.ualberta.med.biobank.validators.NotNullValidator; import edu.ualberta.med.biobank.views.SpecimenTransitView; 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; import gov.nih.nci.system.applicationservice.ApplicationException; public class ShipmentEntryForm extends BiobankEntryForm { public static final String ID = "edu.ualberta.med.biobank.forms.ShipmentEntryForm"; //$NON-NLS-1$ public static final String MSG_NEW_SHIPMENT_OK = Messages.ShipmentEntryForm_new_ship_ok_msg; public static final String MSG_SHIPMENT_OK = Messages.ShipmentEntryForm_edit_ship_ok_msg; private ComboViewer senderComboViewer; private ComboViewer receiverComboViewer; private ComboViewer shippingMethodComboViewer; private SpecimenEntryWidget specimenEntryWidget; private Label waybillLabel; private NonEmptyStringValidator waybillValidator; private static final String WAYBILL_BINDING = "shipment-waybill-binding"; //$NON-NLS-1$ private static final String DATE_SHIPPED_BINDING = "shipment-date-shipped-binding"; //$NON-NLS-1$ private static final String BOX_NUMBER_BINDING = "box-number-binding"; //$NON-NLS-1$ private DateTimeWidget dateSentWidget; private Label departedLabel; private NotNullValidator departedValidator; private BgcBaseText waybillWidget; private Set<SpecimenWrapper> removedSpecimensToPersist = new HashSet<SpecimenWrapper>(); private BgcBaseText boxNumberWidget; private Label boxLabel; @SuppressWarnings("unused") private NonEmptyStringValidator boxValidator; protected boolean tryAgain; private CommentsInfoTable commentEntryTable; private ShipmentReadInfo oiInfo; private OriginInfoWrapper originInfo = new OriginInfoWrapper( SessionManager.getAppService()); private ShipmentInfoWrapper shipmentInfo = new ShipmentInfoWrapper( SessionManager.getAppService()); private CommentWrapper comment = new CommentWrapper( SessionManager.getAppService()); private List<SpecimenInfo> specimens; @Override protected void init() throws Exception { Assert.isNotNull(SessionManager.getUser().getCurrentWorkingCenter()); Assert.isTrue(adapter instanceof ShipmentAdapter, "Invalid editor input: object of type " //$NON-NLS-1$ + adapter.getClass().getName()); setOiInfo(adapter.getId()); setDefaultValues(); String tabName; if (oiInfo == null) { tabName = Messages.ShipmentEntryForm_title_new; } else { tabName = NLS.bind(Messages.ShipmentEntryForm_title_edit, originInfo .getShipmentInfo().getFormattedDateReceived()); } setPartName(tabName); } private void setOiInfo(Integer id) throws ApplicationException { if (id == null) { OriginInfo oi = new OriginInfo(); oi.setShipmentInfo(new ShipmentInfo()); originInfo.setWrappedObject(oi); shipmentInfo.setWrappedObject(oi.getShipmentInfo()); specimens = new ArrayList<SpecimenInfo>(); } else { ShipmentReadInfo read = SessionManager.getAppService().doAction( new ShipmentGetInfoAction(id)); originInfo.setWrappedObject(read.originInfo); shipmentInfo.setWrappedObject(read.originInfo.getShipmentInfo()); specimens = read.specimens; SessionManager.logLookup(read.originInfo); } comment.setWrappedObject(new Comment()); } @Override protected void createFormContent() throws Exception { form.setText(Messages.ShipmentEntryForm_form_title); form.setMessage(getOkMessage(), IMessageProvider.NONE); page.setLayout(new GridLayout(1, false)); createMainSection(); createSpecimensSection(); } private void createMainSection() throws Exception, ApplicationException { 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); senderComboViewer = createComboViewer(client, Messages.ShipmentEntryForm_sender_label, ClinicWrapper.getAllClinics(SessionManager.getAppService()), (ClinicWrapper) originInfo.getCenter(), Messages.ShipmentEntryForm_sender_validation_msg, new ComboSelectionUpdate() { @Override public void doSelection(Object selectedObject) { originInfo.setCenter((CenterWrapper<?>) selectedObject); activateWidgets(((ClinicWrapper) selectedObject) .getSendsShipments()); } }); setFirstControl(senderComboViewer.getControl()); receiverComboViewer = createComboViewer(client, Messages.ShipmentEntryForm_receiver_label, SiteQuery.getSites(SessionManager.getAppService()), originInfo.getReceiverSite(), Messages.ShipmentEntryForm_receiver_validation_msg, new ComboSelectionUpdate() { @Override public void doSelection(Object selectedObject) { originInfo .setReceiverSite((SiteWrapper) selectedObject); } }); waybillLabel = widgetCreator.createLabel(client, Messages.ShipmentEntryForm_waybill_label); waybillLabel.setLayoutData(new GridData( GridData.VERTICAL_ALIGN_BEGINNING)); waybillValidator = new NonEmptyStringValidator( Messages.ShipmentEntryForm_waybill_validation_msg); waybillWidget = (BgcBaseText) createBoundWidget(client, BgcBaseText.class, SWT.NONE, waybillLabel, new String[0], shipmentInfo, ShipmentInfoPeer.WAYBILL.getName(), waybillValidator, WAYBILL_BINDING); shippingMethodComboViewer = createComboViewer(client, Messages.ShipmentEntryForm_shipMethod_label, ShippingMethodWrapper.getShippingMethods(SessionManager .getAppService()), shipmentInfo .getShippingMethod(), null, new ComboSelectionUpdate() { @Override public void doSelection(Object selectedObject) { ShippingMethodWrapper method = (ShippingMethodWrapper) selectedObject; shipmentInfo.setShippingMethod(method); if (dateSentWidget != null && method != null) { activateDepartedWidget(method.needDate()); } } }); departedLabel = widgetCreator.createLabel(client, Messages.ShipmentEntryForm_packed_label); departedLabel.setLayoutData(new GridData( GridData.VERTICAL_ALIGN_BEGINNING)); departedValidator = new NotNullValidator( Messages.ShipmentEntryForm_packed_validation_msg); dateSentWidget = createDateTimeWidget(client, departedLabel, shipmentInfo.getPackedAt(), shipmentInfo, ShipmentInfoPeer.PACKED_AT.getName(), departedValidator, SWT.DATE | SWT.TIME, DATE_SHIPPED_BINDING); activateDepartedWidget(shipmentInfo.getShippingMethod() != null && shipmentInfo.getShippingMethod().needDate()); boxLabel = widgetCreator.createLabel(client, Messages.ShipmentEntryForm_boxNber_label); boxLabel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); boxNumberWidget = (BgcBaseText) createBoundWidget(client, BgcBaseText.class, SWT.NONE, waybillLabel, new String[0], shipmentInfo, ShipmentInfoPeer.BOX_NUMBER.getName(), null, BOX_NUMBER_BINDING); ClinicWrapper clinic = (ClinicWrapper) originInfo.getCenter(); if (clinic != null) { activateWidgets(clinic.getSendsShipments()); } createDateTimeWidget(client, Messages.ShipmentEntryForm_received_label, shipmentInfo.getReceivedAt(), shipmentInfo, ShipmentInfoPeer.RECEIVED_AT.getName(), new NotNullValidator( Messages.ShipmentEntryForm_received_validation_msg)); createCommentSection(); } protected void activateWidgets(boolean sendsShipments) { if (waybillLabel != null && !waybillLabel.isDisposed()) { waybillLabel.setVisible(sendsShipments); ((GridData) waybillLabel.getLayoutData()).exclude = !sendsShipments; } if (waybillWidget != null && !waybillWidget.isDisposed()) { waybillWidget.setVisible(sendsShipments); ((GridData) waybillWidget.getLayoutData()).exclude = !sendsShipments; if (sendsShipments) { widgetCreator.addBinding(WAYBILL_BINDING); } else { widgetCreator.removeBinding(WAYBILL_BINDING); waybillWidget.setText(""); //$NON-NLS-1$ } } boxNumberWidget.setVisible(sendsShipments); ((GridData) boxNumberWidget.getLayoutData()).exclude = !sendsShipments; boxLabel.setVisible(sendsShipments); ((GridData) boxLabel.getLayoutData()).exclude = !sendsShipments; if (sendsShipments) { widgetCreator.addBinding(BOX_NUMBER_BINDING); } else { widgetCreator.removeBinding(BOX_NUMBER_BINDING); boxNumberWidget.setText(""); //$NON-NLS-1$ } form.layout(true, true); } protected void activateDepartedWidget(boolean departedNeeded) { dateSentWidget.setVisible(departedNeeded); ((GridData) dateSentWidget.getLayoutData()).exclude = !departedNeeded; departedLabel.setVisible(departedNeeded); ((GridData) departedLabel.getLayoutData()).exclude = !departedNeeded; if (departedNeeded) { widgetCreator.addBinding(DATE_SHIPPED_BINDING); } else { widgetCreator.removeBinding(DATE_SHIPPED_BINDING); shipmentInfo.setPackedAt(null); } form.layout(true, true); } private void createSpecimensSection() { Composite client = createSectionWithClient(Messages.ShipmentEntryForm_specimens_title); 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); } }); specimenEntryWidget.addBinding(widgetCreator, Messages.ShipmentEntryForm_specimens_validation_msg); 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( Messages.ShipmentEntryForm_notfound_error_msg); if (!SessionManager.getUser().getCurrentWorkingCenter() .equals(specimen.getCurrentCenter())) throw new VetoException( NLS.bind( Messages.ShipmentEntryForm_other_center_error_msg, specimen.getInventoryId(), specimen .getCurrentCenter().getNameShort())); if (specimen.isUsedInDispatch()) throw new VetoException( Messages.ShipmentEntryForm_dispatched_specimen_error_msg); if (specimen.getParentContainer() != null) throw new VetoException( Messages.ShipmentEntryForm_stored_error_msg); if (specimen.getOriginInfo() != null && specimen.getOriginInfo().getShipmentInfo() != null && !specimen.getOriginInfo().getShipmentInfo() .equals(shipmentInfo)) throw new VetoException( NLS.bind( Messages.ShipmentEntryForm_inAnother_ship_error_msg, specimen.getOriginInfo().getShipmentInfo())); break; case POST_ADD: // action performs this now break; case PRE_DELETE: if (!originInfo.isNew()) { try { List<CenterWrapper<?>> centers = CenterWrapper.getCenters(specimen .getAppService()); SpecimenOriginSelectDialog dlg = new SpecimenOriginSelectDialog( form.getShell(), specimen, centers); if (dlg.open() == Window.OK) { removedSpecimensToPersist.add(specimen); } else { throw new VetoException( Messages.ShipmentEntryForm_center_select_msg); } } catch (ApplicationException e) { throw new VetoException(e.getMessage()); } } break; case POST_DELETE: originInfo.removeFromSpecimenCollection(Arrays .asList(specimen)); break; } } }; 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); } private void createCommentSection() { Composite client = createSectionWithClient("Comments"); GridLayout gl = new GridLayout(2, false); client.setLayout(gl); commentEntryTable = new CommentsInfoTable(client, originInfo.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); } @Override public String getNextOpenedFormId() { return ShipmentViewForm.ID; } @Override protected String getOkMessage() { return (originInfo.isNew()) ? MSG_NEW_SHIPMENT_OK : MSG_SHIPMENT_OK; } @Override protected void saveForm() throws Exception { Set<Integer> addedSpecimenIds = new HashSet<Integer>(); for (SpecimenInfo info : specimenEntryWidget.getAddedSpecimens()) { addedSpecimenIds.add(info.specimen.getId()); } Set<Integer> removedSpecimenIds = new HashSet<Integer>(); for (SpecimenInfo info : specimenEntryWidget .getRemovedSpecimens()) { removedSpecimenIds.add(info.specimen.getId()); } OriginInfoSaveInfo oiInfo = new OriginInfoSaveInfo(originInfo.getId(), originInfo .getReceiverSite().getId(), originInfo.getCenter().getId(), comment.getMessage() == null ? "" : comment.getMessage(), addedSpecimenIds, removedSpecimenIds); ShipmentInfoSaveInfo siInfo = new ShipmentInfoSaveInfo(shipmentInfo.getId(), shipmentInfo.getBoxNumber(), originInfo .getShipmentInfo() .getPackedAt(), shipmentInfo.getReceivedAt(), originInfo .getShipmentInfo().getWaybill(), shipmentInfo.getShippingMethod().getId()); OriginInfoSaveAction save = new OriginInfoSaveAction(oiInfo, siInfo); originInfo.setId(SessionManager.getAppService().doAction(save).getId()); ((AdapterBase) adapter).setModelObject(originInfo); } @Override protected void doAfterSave() throws Exception { if (tryAgain) { tryAgain = false; confirm(); } else { SpecimenTransitView.reloadCurrent(); if (!shipmentInfo.isReceivedToday()) SpecimenTransitView.showShipment(originInfo); } } @Override public void setValues() throws Exception { // do not change origin if form reset removedSpecimensToPersist.clear(); originInfo.setShipmentInfo(shipmentInfo); specimenEntryWidget.setSpecimens(specimens); setDefaultValues(); GuiUtil.reset(senderComboViewer, originInfo.getCenter()); GuiUtil.reset(receiverComboViewer, originInfo.getReceiverSite()); GuiUtil.reset(shippingMethodComboViewer, shipmentInfo.getShippingMethod()); } private void setDefaultValues() { if (originInfo.isNew()) { CenterWrapper<?> userCenter = SessionManager.getUser().getCurrentWorkingCenter(); if (userCenter instanceof SiteWrapper) { originInfo.setReceiverSite((SiteWrapper) userCenter); } Date receivedAt = Calendar.getInstance().getTime(); shipmentInfo.setReceivedAt(receivedAt); } } }