edu.harvard.med.screensaver.ui.cherrypickrequests.CherryPickRequestDetailViewer.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.med.screensaver.ui.cherrypickrequests.CherryPickRequestDetailViewer.java

Source

// $HeadURL$
// $Id$
//
// Copyright  2006, 2010, 2011, 2012 by the President and Fellows of Harvard College.
//
// Screensaver is an open-source project developed by the ICCB-L and NSRB labs
// at Harvard Medical School. This software is distributed under the terms of
// the GNU General Public License.

package edu.harvard.med.screensaver.ui.cherrypickrequests;

import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.faces.model.SelectItem;

import com.google.common.base.Joiner;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.TreeMultimap;
import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Transactional;

import edu.harvard.med.screensaver.db.CherryPickRequestDAO;
import edu.harvard.med.screensaver.db.GenericEntityDAO;
import edu.harvard.med.screensaver.model.BusinessRuleViolationException;
import edu.harvard.med.screensaver.model.Volume;
import edu.harvard.med.screensaver.model.VolumeUnit;
import edu.harvard.med.screensaver.model.activities.AdministrativeActivity;
import edu.harvard.med.screensaver.model.cherrypicks.CherryPickAssayProtocolsFollowed;
import edu.harvard.med.screensaver.model.cherrypicks.CherryPickFollowupResultsStatus;
import edu.harvard.med.screensaver.model.cherrypicks.CherryPickRequest;
import edu.harvard.med.screensaver.model.cherrypicks.LabCherryPick;
import edu.harvard.med.screensaver.model.cherrypicks.RNAiCherryPickRequest;
import edu.harvard.med.screensaver.model.cherrypicks.ScreenerCherryPick;
import edu.harvard.med.screensaver.model.cherrypicks.SmallMoleculeCherryPickRequest;
import edu.harvard.med.screensaver.model.libraries.Library;
import edu.harvard.med.screensaver.model.libraries.LibraryScreeningStatus;
import edu.harvard.med.screensaver.model.libraries.PlateType;
import edu.harvard.med.screensaver.model.libraries.Well;
import edu.harvard.med.screensaver.model.libraries.WellKey;
import edu.harvard.med.screensaver.model.libraries.WellName;
import edu.harvard.med.screensaver.model.users.AdministratorUser;
import edu.harvard.med.screensaver.model.users.ScreeningRoomUser;
import edu.harvard.med.screensaver.model.users.ScreensaverUserComparator;
import edu.harvard.med.screensaver.policy.CherryPickRequestAllowancePolicy;
import edu.harvard.med.screensaver.ui.arch.util.JSFUtils;
import edu.harvard.med.screensaver.ui.arch.util.UISelectOneBean;
import edu.harvard.med.screensaver.ui.arch.util.UISelectOneEntityBean;
import edu.harvard.med.screensaver.ui.arch.view.EditResult;
import edu.harvard.med.screensaver.ui.arch.view.EditableEntityViewerBackingBean;
import edu.harvard.med.screensaver.ui.arch.view.aspects.UICommand;
import edu.harvard.med.screensaver.ui.screens.ScreenViewer;
import edu.harvard.med.screensaver.util.DevelopmentException;

/**
 * Backing bean for Cherry Pick Request Detail Viewer page.
 *
 * @author <a mailto="andrew_tolopko@hms.harvard.edu">Andrew Tolopko</a>
 */
public class CherryPickRequestDetailViewer extends EditableEntityViewerBackingBean<CherryPickRequest> {
    private static Logger log = Logger.getLogger(CherryPickRequestDetailViewer.class);

    private CherryPickRequestDAO _cherryPickRequestDao;
    private CherryPickRequestViewer _cherryPickRequestViewer;
    private ScreenViewer _screenViewer;
    private CherryPickRequestAllowancePolicy<SmallMoleculeCherryPickRequest> _smallMoleculeCherryPickRequestAllowancePolicy;
    private CherryPickRequestAllowancePolicy<RNAiCherryPickRequest> _rnaiCherryPickRequestAllowancePolicy;

    private UISelectOneBean<PlateType> _assayPlateType;
    private UISelectOneEntityBean<ScreeningRoomUser> _requestedBy;
    private UISelectOneEntityBean<AdministratorUser> _volumeApprovedBy;

    private UISelectOneBean<VolumeUnit> _transferVolumePerWellRequestedType;
    private String _transferVolumePerWellRequestedValue;

    private UISelectOneBean<VolumeUnit> _transferVolumePerWellApprovedType;
    private String _transferVolumePerWellApprovedValue;

    /**
     * @motivation for CGLIB2
     */
    protected CherryPickRequestDetailViewer() {
    }

    public CherryPickRequestDetailViewer(CherryPickRequestDetailViewer thisProxy,
            CherryPickRequestViewer cherryPickRequestViewer, GenericEntityDAO dao,
            CherryPickRequestDAO cherryPickRequestDao, ScreenViewer screenViewer,
            CherryPickRequestAllowancePolicy<SmallMoleculeCherryPickRequest> smallMoleculeCherryPickRequestAllowancePolicy,
            CherryPickRequestAllowancePolicy<RNAiCherryPickRequest> rnaiCherryPickRequestAllowancePolicy) {
        super(thisProxy, CherryPickRequest.class, EDIT_CHERRY_PICK_REQUEST, dao);
        _cherryPickRequestDao = cherryPickRequestDao;
        _cherryPickRequestViewer = cherryPickRequestViewer;
        _screenViewer = screenViewer;
        _smallMoleculeCherryPickRequestAllowancePolicy = smallMoleculeCherryPickRequestAllowancePolicy;
        _rnaiCherryPickRequestAllowancePolicy = rnaiCherryPickRequestAllowancePolicy;
        getIsPanelCollapsedMap().put("cherryPickRequestDetails", false);
        getIsPanelCollapsedMap().put("cherryPickFollowupAssays", true);
    }

    @Override
    public void initializeEntity(CherryPickRequest cherryPickRequest) {
        getDao().needReadOnly(cherryPickRequest, CherryPickRequest.requestedBy);
        getDao().needReadOnly(cherryPickRequest, CherryPickRequest.emptyWellsOnAssayPlate);
        getDao().needReadOnly(cherryPickRequest, CherryPickRequest.cherryPickScreenings);
    }

    @Override
    public void initializeViewer(final CherryPickRequest cherryPickRequest) {
        SortedSet<ScreeningRoomUser> requestedByCandidates = Sets.newTreeSet();
        requestedByCandidates.addAll(cherryPickRequest.getScreen().getAssociatedScreeningRoomUsers());
        // add the current requestedBy user, even if it's no longer a valid candidate, to avoid inadvertently changing it   
        requestedByCandidates.add(cherryPickRequest.getRequestedBy());
        _requestedBy = new UISelectOneEntityBean<ScreeningRoomUser>(requestedByCandidates,
                cherryPickRequest.getRequestedBy(), getDao()) {
            @Override
            protected String makeLabel(ScreeningRoomUser u) {
                return u.getFullNameLastFirst();
            }
        };

        SortedSet<AdministratorUser> candidateVolumeApprovers = new TreeSet<AdministratorUser>(
                ScreensaverUserComparator.getInstance());
        candidateVolumeApprovers.addAll(getDao().findAllEntitiesOfType(AdministratorUser.class)); // TODO: filter out all but CherryPickAdmins
        _volumeApprovedBy = new UISelectOneEntityBean<AdministratorUser>(candidateVolumeApprovers,
                cherryPickRequest.getVolumeApprovedBy(), true, getDao()) {
            @Override
            protected String makeLabel(AdministratorUser a) {
                return a.getFullNameLastFirst();
            }
        };

        _assayPlateType = new UISelectOneBean<PlateType>(Arrays.asList(PlateType.values()),
                cherryPickRequest.getAssayPlateType());

        _transferVolumePerWellRequestedType = null;
        _transferVolumePerWellRequestedValue = null;
        _transferVolumePerWellApprovedType = null;
        _transferVolumePerWellApprovedValue = null;
    }

    @Override
    protected void initializeNewEntity(CherryPickRequest entity) {
        entity.addEmptyWellsOnAssayPlate(entity.getAssayPlateType().getPlateSize().getEdgeWellNames(2));
    }

    public UISelectOneBean<PlateType> getAssayPlateType() {
        return _assayPlateType;
    }

    public UISelectOneEntityBean<ScreeningRoomUser> getRequestedBy() {
        return _requestedBy;
    }

    public UISelectOneEntityBean<AdministratorUser> getVolumeApprovedBy() {
        return _volumeApprovedBy;
    }

    public int getActiveCherryPickPlatesCount() {
        return getEntity().getActiveCherryPickAssayPlates().size();
    }

    public int getCompletedCherryPickPlatesCount() {
        return getEntity().getCompletedCherryPickAssayPlates().size();
    }

    public UISelectOneBean<VolumeUnit> getTransferVolumePerWellRequestedType() {
        try {
            if (_transferVolumePerWellRequestedType == null) {
                Volume v = getEntity().getTransferVolumePerWellRequested();
                VolumeUnit unit = (v == null ? VolumeUnit.MICROLITERS : v.getUnits());
                _transferVolumePerWellRequestedType = new UISelectOneBean<VolumeUnit>(VolumeUnit.DISPLAY_VALUES,
                        unit) {
                    @Override
                    protected String makeLabel(VolumeUnit t) {
                        return t.getValue();
                    }
                };
            }
            return _transferVolumePerWellRequestedType;
        } catch (Exception e) {
            log.error("err: " + e);
            return null;
        }
    }

    /**
     * This method exists to grab the value portion of the Quantity stored
    */
    public String getTransferVolumePerWellRequestedValue() {
        if (_transferVolumePerWellRequestedValue == null) {
            if (getEntity().getTransferVolumePerWellRequested() != null)
                _transferVolumePerWellRequestedValue = getEntity().getTransferVolumePerWellRequested()
                        .getDisplayValue().toString();
            else
                _transferVolumePerWellRequestedValue = null;
        }
        return _transferVolumePerWellRequestedValue;
    }

    /**
     * This method exists to set the value portion of the Quantity stored
     * @see #save()
    */
    public void setTransferVolumePerWellRequestedValue(String value) {
        _transferVolumePerWellRequestedValue = value;
    }

    public UISelectOneBean<VolumeUnit> getTransferVolumePerWellApprovedType() {
        try {
            if (_transferVolumePerWellApprovedType == null) {
                Volume v = getEntity().getTransferVolumePerWellApproved();
                VolumeUnit unit = (v == null ? VolumeUnit.MICROLITERS : v.getUnits());
                _transferVolumePerWellApprovedType = new UISelectOneBean<VolumeUnit>(VolumeUnit.DISPLAY_VALUES,
                        unit) {
                    @Override
                    protected String makeLabel(VolumeUnit t) {
                        return t.getValue();
                    }
                };
            }
            return _transferVolumePerWellApprovedType;
        } catch (Exception e) {
            log.error("err: " + e);
            return null;
        }
    }

    /**
     * This method exists to grab the value portion of the Quantity stored
    */
    public String getTransferVolumePerWellApprovedValue() {
        if (_transferVolumePerWellApprovedValue == null) {
            if (getEntity().getTransferVolumePerWellApproved() != null)
                _transferVolumePerWellApprovedValue = getEntity().getTransferVolumePerWellApproved()
                        .getDisplayValue().toString();
            else
                _transferVolumePerWellApprovedValue = null;
        }
        return _transferVolumePerWellApprovedValue;
    }

    /**
     * This method exists to set the value portion of the Quantity stored
     * @see #save()
    */
    public void setTransferVolumePerWellApprovedValue(String value) {
        _transferVolumePerWellApprovedValue = value;
    }

    public List<SelectItem> getCherryPickAssayProtocolsFollowedSelectItems() {
        return JSFUtils.createUISelectItemsWithEmptySelection(
                Arrays.asList(CherryPickAssayProtocolsFollowed.values()), "<none>");
    }

    public List<SelectItem> getCherryPickFollowupResultsStatusSelectItems() {
        return JSFUtils.createUISelectItemsWithEmptySelection(
                Arrays.asList(CherryPickFollowupResultsStatus.values()), "<none>");
    }

    @Override
    public boolean isDeleteSupported() {
        return !!!getEntity().isAllocated() && !!!(getEntity() instanceof RNAiCherryPickRequest
                && ((RNAiCherryPickRequest) getEntity()).isScreened());
    }

    @UICommand
    @Override
    public String delete() {
        if (!!!isDeleteSupported()) {
            throw new BusinessRuleViolationException(
                    "cannot delete a cherry pick request that has been allocated or that has been screened");
        }
        _cherryPickRequestDao.deleteCherryPickRequest(getEntity());
        return _screenViewer.viewEntity(getEntity().getScreen());
    }

    @UICommand
    public String deleteAllCherryPicks() {
        _cherryPickRequestDao.deleteAllCherryPicks(getEntity());
        return _cherryPickRequestViewer.reload();
    }

    @Override
    protected boolean validateEntity(CherryPickRequest entity) {
        boolean valid = true;
        try {
            Volume.makeVolume(_transferVolumePerWellRequestedValue,
                    _transferVolumePerWellRequestedType.getSelection());
        } catch (Exception e) {
            showFieldInputError("Requested Volume", e.getLocalizedMessage());
            valid = false;
        }
        try {
            Volume.makeVolume(_transferVolumePerWellApprovedValue,
                    _transferVolumePerWellApprovedType.getSelection());
        } catch (Exception e) {
            showFieldInputError("Approved Volume", e.getLocalizedMessage());
            valid = false;
        }
        return valid;
    }

    @Override
    protected void updateEntityProperties(CherryPickRequest entity) {
        getEntity().setTransferVolumePerWellRequested(Volume.makeVolume(_transferVolumePerWellRequestedValue,
                _transferVolumePerWellRequestedType.getSelection()));
        getEntity().setTransferVolumePerWellApproved(Volume.makeVolume(_transferVolumePerWellApprovedValue,
                _transferVolumePerWellApprovedType.getSelection()));

        entity.setAssayPlateType(_assayPlateType.getSelection());
        entity.setRequestedBy(_requestedBy.getSelection());
        entity.setVolumeApprovedBy(_volumeApprovedBy.getSelection());
    }

    /**
     * Get the set of empty rows requested by the screener.
     * @return well names that must be left empty on each cherry pick assay plate
     */
    public Set<WellName> getEmptyWellsOnAssayPlate() {
        return getEntity().getEmptyWellsOnAssayPlate();
    }

    /**
     * Set the set of empty wells.
     * @param emptyWellsOnAssayPlate wells that screener has requested be
     * left empty on each cherry pick assay plate
     */
    public void setEmptyWellsOnAssayPlate(Set<WellName> emptyWellsOnAssayPlate) {
        getEntity().clearEmptyWellsOnAssayPlate();
        getEntity().addEmptyWellsOnAssayPlate(emptyWellsOnAssayPlate);
    }

    @UICommand
    @Transactional
    public void showAdminWarnings() {
        // eager fetch all data needed to calculate warnings
        CherryPickRequest cherryPickRequest = getDao().reloadEntity(getEntity(), true, CherryPickRequest.screen);
        getDao().needReadOnly(cherryPickRequest,
                CherryPickRequest.labCherryPicks.to(LabCherryPick.screenerCherryPick)
                        .to(ScreenerCherryPick.screenedWell).to(Well.deprecationActivity));
        getDao().needReadOnly(cherryPickRequest,
                CherryPickRequest.labCherryPicks.to(LabCherryPick.sourceWell).to(Well.deprecationActivity));
        getDao().needReadOnly(cherryPickRequest,
                CherryPickRequest.screenerCherryPicks.to(ScreenerCherryPick.screenedWell).to(Well.library));

        boolean warningIssued = false;
        warningIssued |= doWarnOnCherryPickAllowanceExceeded(cherryPickRequest);
        warningIssued |= doWarnOnInvalidSourceWell(cherryPickRequest);
        warningIssued |= doWarnOnDuplicateScreenerCherryPicks(cherryPickRequest);
        warningIssued |= doWarnOnDeprecatedWells(cherryPickRequest);
        warningIssued |= doWarnOnLibraryScreeningStatus(cherryPickRequest);
        if (!warningIssued) {
            showMessage("cherryPicks.allCherryPicksAreValid");
        }
    }

    private <CPR extends CherryPickRequest> boolean doWarnOnCherryPickAllowanceExceeded(CPR cherryPickRequest) {
        CherryPickRequestAllowancePolicy<CPR> policy;
        if (cherryPickRequest instanceof SmallMoleculeCherryPickRequest) {
            policy = (CherryPickRequestAllowancePolicy<CPR>) _smallMoleculeCherryPickRequestAllowancePolicy;
        } else if (cherryPickRequest instanceof RNAiCherryPickRequest) {
            policy = (CherryPickRequestAllowancePolicy<CPR>) _rnaiCherryPickRequestAllowancePolicy;
        } else {
            throw new DevelopmentException(
                    "unsupported cherry pick request type: " + cherryPickRequest.getClass().getName());
        }
        if (policy.isCherryPickAllowanceExceeded(cherryPickRequest)) {
            showMessage("cherryPicks.cherryPickAllowanceExceeded",
                    policy.getCherryPickAllowanceUsed(cherryPickRequest),
                    policy.getCherryPickAllowance(cherryPickRequest));
            return true;
        }
        return false;
    }

    private boolean doWarnOnInvalidSourceWell(CherryPickRequest cherryPickRequest) {
        Set<WellKey> invalidCherryPicks = Sets.newHashSet();
        for (ScreenerCherryPick screenerCherryPick : cherryPickRequest.getScreenerCherryPicks()) {
            if (screenerCherryPick.getLabCherryPicks().size() == 0) {
                invalidCherryPicks.add(screenerCherryPick.getScreenedWell().getWellKey());
            }
        }
        if (!!!invalidCherryPicks.isEmpty()) {
            showMessage("cherryPicks.invalidWells", Joiner.on(", ").join(invalidCherryPicks));
            return true;
        }
        return false;
    }

    private boolean doWarnOnDuplicateScreenerCherryPicks(CherryPickRequest cherryPickRequest) {
        Map<WellKey, Number> duplicateScreenerCherryPickWellKeysMap = _cherryPickRequestDao
                .findDuplicateCherryPicksForScreen(cherryPickRequest.getScreen());
        Set<WellKey> duplicateScreenerCherryPickWellKeys = duplicateScreenerCherryPickWellKeysMap.keySet();
        Set<WellKey> ourScreenerCherryPickWellsKeys = new HashSet<WellKey>();
        for (ScreenerCherryPick screenerCherryPick : cherryPickRequest.getScreenerCherryPicks()) {
            ourScreenerCherryPickWellsKeys.add(screenerCherryPick.getScreenedWell().getWellKey());
        }
        duplicateScreenerCherryPickWellKeys.retainAll(ourScreenerCherryPickWellsKeys);
        if (duplicateScreenerCherryPickWellKeysMap.size() > 0) {
            String duplicateWellsList = Joiner.on(", ").join(duplicateScreenerCherryPickWellKeys);
            showMessage("cherryPicks.duplicateCherryPicksInScreen", cherryPickRequest.getScreen().getFacilityId(),
                    duplicateWellsList);
            return true;
        }
        return false;
    }

    private boolean doWarnOnDeprecatedWells(CherryPickRequest cherryPickRequest) {
        Multimap<AdministrativeActivity, WellKey> wellDeprecations = TreeMultimap.create();
        for (LabCherryPick labCherryPick : cherryPickRequest.getLabCherryPicks()) {
            Well well = labCherryPick.getSourceWell();
            if (well.isDeprecated()) {
                wellDeprecations.put(well.getDeprecationActivity(), well.getWellKey());
            }
            well = labCherryPick.getScreenerCherryPick().getScreenedWell();
            if (well.isDeprecated()) {
                wellDeprecations.put(well.getDeprecationActivity(), well.getWellKey());
            }
        }
        for (AdministrativeActivity deprecationActivity : wellDeprecations.keySet()) {
            showMessage("cherryPicks.deprecatedWells", deprecationActivity.getComments(),
                    Joiner.on(", ").join(wellDeprecations.values()));
            return true;
        }
        return false;
    }

    private boolean doWarnOnLibraryScreeningStatus(CherryPickRequest cherryPickRequest) {
        Set<Library> libraries = new LinkedHashSet<Library>();
        for (LabCherryPick labCherryPick : cherryPickRequest.getLabCherryPicks()) {
            libraries.add(labCherryPick.getSourceWell().getLibrary());
            libraries.add(labCherryPick.getScreenerCherryPick().getScreenedWell().getLibrary());
        }
        for (Library library : libraries) {
            if (library.getScreeningStatus() != LibraryScreeningStatus.ALLOWED) {
                if (!cherryPickRequest.getScreen().getLibrariesPermitted().contains(library)) {
                    showMessage("libraries.libraryUsageConflict", library.getShortName(),
                            library.getScreeningStatus().getValue());
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    protected String postEditAction(EditResult editResult) {
        switch (editResult) {
        case CANCEL_EDIT:
            return _cherryPickRequestViewer.reload();
        case SAVE_EDIT:
            return _cherryPickRequestViewer.reload();
        case CANCEL_NEW:
            return _screenViewer.reload();
        case SAVE_NEW:
            return _screenViewer.reload();
        default:
            return null;
        }
    }
}