package edu.ualberta.med.biobank.mvp.presenter.impl; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.inject.Inject; import com.google.web.bindery.event.shared.EventBus; import com.pietschy.gwt.pectin.client.form.validation.ValidationResultCollector; import com.pietschy.gwt.pectin.client.form.validation.Validator; import com.pietschy.gwt.pectin.client.form.validation.message.ErrorMessage; import edu.ualberta.med.biobank.common.action.ActionCallback; import edu.ualberta.med.biobank.common.action.patient.PatientGetProcessingEventsByPNumberAction; import edu.ualberta.med.biobank.common.action.patient.PatientGetProcessingEventsByPNumberResult; import edu.ualberta.med.biobank.common.util.Predicate; import edu.ualberta.med.biobank.common.util.PredicateUtil; import edu.ualberta.med.biobank.model.CollectionEvent; import edu.ualberta.med.biobank.model.ProcessingEvent; import edu.ualberta.med.biobank.model.SourceSpecimen; import edu.ualberta.med.biobank.mvp.AppContext; import edu.ualberta.med.biobank.mvp.action.StaleSafeDispatcher; import edu.ualberta.med.biobank.mvp.event.ExceptionEvent; import edu.ualberta.med.biobank.mvp.event.impl.DelayedValueChangeHandler; import edu.ualberta.med.biobank.mvp.presenter.impl.SpecimenLinkPresenter.View; import edu.ualberta.med.biobank.mvp.presenter.validation.ValueValidation; import edu.ualberta.med.biobank.mvp.presenter.validation.validator.NotNullValidator; import edu.ualberta.med.biobank.mvp.user.ui.HasButton; import edu.ualberta.med.biobank.mvp.user.ui.SelectedValueField; import edu.ualberta.med.biobank.mvp.user.ui.ValueField; import edu.ualberta.med.biobank.mvp.view.IEntryFormView; public class SpecimenLinkPresenter extends AbstractEntryFormPresenter<View> { private final PNumberMonitor pNumberMonitor = new PNumberMonitor(); private final PEventMonitor pEventMonitor = new PEventMonitor(); private final IsRecentMonitor isRecentMonitor = new IsRecentMonitor(); private final CEventMonitor cEventMonitor = new CEventMonitor(); private final StaleSafeDispatcher dispatcher; private final AppContext appContext; private boolean patientExists = false; private List<ProcessingEvent> processingEvents = Collections.emptyList(); @SuppressWarnings("unused") private List<CollectionEvent> collectionEvents = Collections.emptyList(); @SuppressWarnings("unused") private List<SourceSpecimen> sourceSpecimens = Collections.emptyList(); public interface View extends IEntryFormView { ValueField<String> getPatientNumber(); SelectedValueField<ProcessingEvent> getProcessingEvent(); ValueField<Boolean> isRecentProcessingEvent(); SelectedValueField<CollectionEvent> getCollectionEvent(); // ValueField<Mode> getMode(); // // void setSingleModeView(IView view); // // void setMultipleModeView(IView view); HasButton getConfirm(); } // public enum Mode { // SINGLE, // MULTIPLE; // } @Inject public SpecimenLinkPresenter(View view, EventBus eventBus, StaleSafeDispatcher dispatcher, AppContext appContext) { super(view, eventBus); this.dispatcher = dispatcher; this.appContext = appContext; } @Override protected void onBind() { view.getPatientNumber().addValueChangeHandler(pNumberMonitor); view.getProcessingEvent().addValueChangeHandler(pEventMonitor); view.isRecentProcessingEvent().addValueChangeHandler(isRecentMonitor); view.getCollectionEvent().addValueChangeHandler(cEventMonitor); // Conditions.v // binder.enable(view.getProcessingEvent()).when(); // binder.show(view.getCollectionEvent()).when() validation.validate(view.getPatientNumber()) .using(new PNumberValidator()); validation.validate(view.getProcessingEvent()) .using(new NotNullValidator("asdf")); validation.validate(view.getCollectionEvent()) .using(new NotNullValidator("asdf")); } @Override protected void onUnbind() { } @Override protected void doSave() { // TODO Auto-generated method stub } private class PNumberMonitor extends DelayedValueChangeHandler<String> { public PNumberMonitor() { super(500); } @Override public void onDelayedValueChange(ValueChangeEvent<String> event) { String pNumber = event.getValue(); Integer centerId = appContext.getWorkingCenterId(); dispatcher .asyncExec( new PatientGetProcessingEventsByPNumberAction(pNumber, centerId), new ActionCallback<PatientGetProcessingEventsByPNumberResult>() { @Override public void onFailure(Throwable caught) { processingEvents = Collections.emptyList(); patientExists = false; update(); eventBus.fireEvent(new ExceptionEvent(caught)); } @Override public void onSuccess( PatientGetProcessingEventsByPNumberResult result) { processingEvents = result.getProcessingEvents(); patientExists = result.isPatientExists(); update(); } }); } private void update() { ValueValidation<String> patientNumberValidation = validation.getValueValidation(view.getPatientNumber()); if (patientNumberValidation != null) { patientNumberValidation.validate(); } updatePEventOptions(); } } private void updatePEventOptions() { List<ProcessingEvent> options = new ArrayList<ProcessingEvent>(); options.addAll(processingEvents); if (Boolean.TRUE.equals(view.isRecentProcessingEvent().getValue())) { PredicateUtil.filterOut(options, new PEventOver7DaysOld()); } view.getProcessingEvent().setOptions(options); } private class IsRecentMonitor implements ValueChangeHandler<Boolean> { @Override public void onValueChange(ValueChangeEvent<Boolean> event) { updatePEventOptions(); } } private class PEventMonitor extends DelayedValueChangeHandler<ProcessingEvent> { public PEventMonitor() { super(500); } @Override public void onDelayedValueChange(ValueChangeEvent<ProcessingEvent> event) { // TODO: run async thing to update collection visit options } } private class CEventMonitor extends DelayedValueChangeHandler<CollectionEvent> { public CEventMonitor() { super(500); } @Override public void onDelayedValueChange(ValueChangeEvent<CollectionEvent> event) { // TODO: update source-specimen list on all views. } } private class PNumberValidator implements Validator<String> { @Override public void validate(String value, ValidationResultCollector results) { if (value == null || value.isEmpty()) { results.add(new ErrorMessage("Patient number is required")); } else if (!patientExists) { results.add(new ErrorMessage("Patient number '" + value + "' does not exist")); } else if (processingEvents.isEmpty()) { results.add(new ErrorMessage("Patient number '" + value + "' has no processing events.")); } } } private static class PEventOver7DaysOld implements Predicate<ProcessingEvent> { private final Date midnight7DaysAgo; public PEventOver7DaysOld() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.AM_PM, Calendar.AM); cal.set(Calendar.HOUR, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.add(Calendar.DAY_OF_MONTH, -7); midnight7DaysAgo = cal.getTime(); } @Override public boolean evaluate(ProcessingEvent pEvent) { return pEvent.getCreatedAt().before(midnight7DaysAgo); } }; }