// $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.Iterator; import java.util.List; import java.util.Map; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.apache.log4j.Logger; import org.joda.time.LocalDate; import org.springframework.beans.factory.annotation.Autowired; import edu.harvard.med.screensaver.ScreensaverConstants; import edu.harvard.med.screensaver.db.DAOTransaction; import edu.harvard.med.screensaver.db.LibrariesDAO; import edu.harvard.med.screensaver.db.UsersDAO; import edu.harvard.med.screensaver.model.Volume; import edu.harvard.med.screensaver.model.VolumeUnit; import edu.harvard.med.screensaver.model.activities.AdministrativeActivityType; import edu.harvard.med.screensaver.model.cherrypicks.CherryPickAssayPlate; import edu.harvard.med.screensaver.model.cherrypicks.CherryPickRequest; import edu.harvard.med.screensaver.model.cherrypicks.LabCherryPick; import edu.harvard.med.screensaver.model.libraries.Copy; import edu.harvard.med.screensaver.model.libraries.CopyUsageType; import edu.harvard.med.screensaver.model.libraries.Library; import edu.harvard.med.screensaver.model.libraries.Plate; import edu.harvard.med.screensaver.model.libraries.PlateStatus; import edu.harvard.med.screensaver.model.libraries.Well; import edu.harvard.med.screensaver.model.libraries.WellVolumeAdjustment; import edu.harvard.med.screensaver.model.screens.CherryPickScreening; import edu.harvard.med.screensaver.model.screens.Screen; import edu.harvard.med.screensaver.model.screens.ScreenType; import edu.harvard.med.screensaver.model.users.LabHead; import edu.harvard.med.screensaver.model.users.ScreeningRoomUser; import edu.harvard.med.screensaver.model.users.ScreensaverUserRole; import edu.harvard.med.screensaver.service.libraries.PlateUpdater; import edu.harvard.med.screensaver.test.MakeDummyEntities; import edu.harvard.med.screensaver.ui.activities.ActivityViewer; import edu.harvard.med.screensaver.ui.arch.datatable.column.entity.TextEntityColumn; import edu.harvard.med.screensaver.ui.arch.view.AbstractBackingBeanTest; public class CherryPickRequestViewerTest extends AbstractBackingBeanTest { private static Logger log = Logger.getLogger(CherryPickRequestViewerTest.class); @Autowired protected UsersDAO usersDao; @Autowired protected CherryPickRequestViewer cherryPickRequestViewer; @Autowired protected ActivityViewer activityViewer; @Autowired protected PlateUpdater _plateUpdater; @Autowired protected LibrariesDAO _librariesDao; private ScreeningRoomUser _screener; private CherryPickRequest _cpr; private Library _library; protected void setUp() throws Exception { super.setUp(); genericEntityDao.doInTransaction(new DAOTransaction() { @Override public void runTransaction() { _admin.addScreensaverUserRole(ScreensaverUserRole.LIBRARIES_ADMIN); _admin = genericEntityDao.mergeEntity(_admin); currentScreensaverUser.setScreensaverUser(_admin); _screener = new LabHead(_admin); _screener.setFirstName("Lab"); _screener.setLastName("Head"); genericEntityDao.persistEntity(_screener); _library = MakeDummyEntities.makeDummyLibrary(1, ScreenType.SMALL_MOLECULE, 1); Plate plate = _library.createCopy(_admin, CopyUsageType.CHERRY_PICK_SOURCE_PLATES, "A").findPlate(1000).withWellVolume(new Volume(1000)); genericEntityDao.persistEntity(_library); genericEntityDao.flush(); _plateUpdater.updatePlateStatus(plate, PlateStatus.AVAILABLE, _admin, _admin, new LocalDate()); Screen screen = MakeDummyEntities.makeDummyScreen(1, ScreenType.SMALL_MOLECULE); _cpr = screen.createCherryPickRequest(_admin, _screener, new LocalDate()); _cpr.setTransferVolumePerWellApproved(new Volume(1)); genericEntityDao.persistEntity(screen); } }); } public void testCherryPickPlatesPlatedAndScreened() { initializeAssayPlates(); cherryPickRequestViewer.selectAllAssayPlates(); cherryPickRequestViewer.recordSuccessfulCreationOfAssayPlates(); assertEquals(ScreensaverConstants.BROWSE_CHERRY_PICK_REQUESTS, activityViewer.save()); genericEntityDao.doInTransaction(new DAOTransaction() { @Override public void runTransaction() { CherryPickRequest cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity()); assertTrue(cpr.getCherryPickAssayPlates().first().isPlated()); assertTrue(Iterables.all(cpr.getLabCherryPicks(), new Predicate<LabCherryPick>() { public boolean apply(LabCherryPick lcp) { return lcp.isPlated(); }; })); } }); cherryPickRequestViewer.viewEntity(_cpr); cherryPickRequestViewer.selectAllAssayPlates(); cherryPickRequestViewer.recordScreeningOfAssayPlates(); List<SelectableRow<CherryPickAssayPlate>> cpapRows = (List<SelectableRow<CherryPickAssayPlate>>) activityViewer.getCherryPickPlatesDataModel().getWrappedData(); assertEquals(1, cpapRows.size()); assertEquals("Lab Head (1) CP" + _cpr.getEntityId() + " Plate 01 of 1", cpapRows.get(0).getData().getName()); activityViewer.getEntity().setDateOfActivity(new LocalDate(2010, 1, 1)); assertEquals(ScreensaverConstants.BROWSE_CHERRY_PICK_REQUESTS, activityViewer.save()); genericEntityDao.doInTransaction(new DAOTransaction() { @Override public void runTransaction() { CherryPickRequest cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity()); assertTrue(cpr.getCherryPickAssayPlates().first().isPlatedAndScreened()); List<CherryPickScreening> screenings = Lists.newArrayList(cpr.getCherryPickAssayPlates().first().getCherryPickScreenings()); assertEquals(1, screenings.size()); assertEquals(new LocalDate(2010, 1, 1), screenings.get(0).getDateOfActivity()); } }); // test multiple screening of a CPAP cherryPickRequestViewer.viewEntity(_cpr); cherryPickRequestViewer.selectAllAssayPlates(); cherryPickRequestViewer.recordScreeningOfAssayPlates(); activityViewer.getEntity().setDateOfActivity(new LocalDate(2011, 1, 1)); assertEquals(ScreensaverConstants.BROWSE_CHERRY_PICK_REQUESTS, activityViewer.save()); genericEntityDao.doInTransaction(new DAOTransaction() { @Override public void runTransaction() { CherryPickRequest cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity()); assertTrue(cpr.getCherryPickAssayPlates().first().isPlatedAndScreened()); List<CherryPickScreening> screenings = Lists.newArrayList(cpr.getCherryPickAssayPlates().first().getCherryPickScreenings()); assertEquals(2, screenings.size()); assertEquals(new LocalDate(2010, 1, 1), screenings.get(0).getDateOfActivity()); assertEquals(new LocalDate(2011, 1, 1), screenings.get(1).getDateOfActivity()); } }); } public void testCherryPickPlatesCanceled() { initializeAssayPlates(); cherryPickRequestViewer.selectAllAssayPlates(); cherryPickRequestViewer.deallocateCherryPicksByPlate(); assertEquals(ScreensaverConstants.BROWSE_CHERRY_PICK_REQUESTS, activityViewer.save()); genericEntityDao.doInTransaction(new DAOTransaction() { @Override public void runTransaction() { CherryPickRequest cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity()); assertTrue(cpr.getCherryPickAssayPlates().first().isCancelled()); assertTrue(Iterables.all(cpr.getLabCherryPicks(), new Predicate<LabCherryPick>() { public boolean apply(LabCherryPick lcp) { return lcp.isCancelled() && lcp.getWellVolumeAdjustments().isEmpty(); }; })); } }); } public void testCherryPickPlatesFailedAndRecreated() { initializeAssayPlates(); final int lastAssayPlateCount = cherryPickRequestViewer.getEntity().getCherryPickAssayPlates().size(); final int lastLabCherryPickCount = cherryPickRequestViewer.getEntity().getLabCherryPicks().size(); cherryPickRequestViewer.selectAllAssayPlates(); cherryPickRequestViewer.recordFailedCreationOfAssayPlates(); assertEquals(ScreensaverConstants.BROWSE_CHERRY_PICK_REQUESTS, activityViewer.save()); genericEntityDao.doInTransaction(new DAOTransaction() { @Override public void runTransaction() { CherryPickRequest cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity()); assertEquals(lastAssayPlateCount * 2, cpr.getCherryPickAssayPlates().size()); assertEquals(lastLabCherryPickCount * 2, cpr.getLabCherryPicks().size()); assertTrue(cpr.getCherryPickAssayPlates().first().isFailed()); assertEquals(Integer.valueOf(0), cpr.getCherryPickAssayPlates().first().getPlateOrdinal()); assertEquals(Integer.valueOf(0), cpr.getCherryPickAssayPlates().first().getAttemptOrdinal()); assertTrue(Iterables.all(cpr.getCherryPickAssayPlates().first().getLabCherryPicks(), new Predicate<LabCherryPick>() { public boolean apply(LabCherryPick lcp) { return lcp.isFailed(); }; })); assertFalse(cpr.getCherryPickAssayPlates().last().isPlated()); assertEquals(Integer.valueOf(0), cpr.getCherryPickAssayPlates().last().getPlateOrdinal()); assertEquals(Integer.valueOf(1), cpr.getCherryPickAssayPlates().last().getAttemptOrdinal()); assertTrue(Iterables.all(cpr.getCherryPickAssayPlates().last().getLabCherryPicks(), new Predicate<LabCherryPick>() { public boolean apply(LabCherryPick lcp) { return lcp.isMapped(); }; })); } }); } private void initializeAssayPlates() { initializeLabCherryPicks(); cherryPickRequestViewer.plateMapCherryPicks(); CherryPickRequest cpr = genericEntityDao.reloadEntity(_cpr, true, CherryPickRequest.cherryPickAssayPlates); assertEquals(1, cpr.getCherryPickAssayPlates().size()); } protected void initializeLabCherryPicks() { String input = Joiner.on("\n").appendTo(new StringBuilder(), Iterables.transform(_library.getWells(), Well.ToEntityId)).toString(); log.info("cherry picks: " + input); cherryPickRequestViewer.viewEntity(_cpr); cherryPickRequestViewer.setCherryPicksInput(input); cherryPickRequestViewer.addCherryPicksForWells(); CherryPickRequest cpr = genericEntityDao.reloadEntity(_cpr, true, CherryPickRequest.screenerCherryPicks); assertEquals(384, cpr.getScreenerCherryPicks().size()); cherryPickRequestViewer.allocateCherryPicks(); cpr = genericEntityDao.reloadEntity(_cpr, true, CherryPickRequest.labCherryPicks); assertEquals(384, cpr.getLabCherryPicks().size()); assertEquals(0, cpr.getNumberUnfulfilledLabCherryPicks()); } public void testEditLabCherryPickSourceCopy() { initializeLabCherryPicks(); _library.createCopy(_admin, CopyUsageType.CHERRY_PICK_SOURCE_PLATES, "B").findPlate(1000).withWellVolume(new Volume(500)); _library.createCopy(_admin, CopyUsageType.LIBRARY_SCREENING_PLATES, "C").findPlate(1000).withWellVolume(new Volume(1000)); _library = genericEntityDao.mergeEntity(_library); _plateUpdater.updatePlateStatus(_library.getCopy("B").findPlate(1000), PlateStatus.AVAILABLE, _admin, _admin, new LocalDate()); Iterator<LabCherryPick> iter = cherryPickRequestViewer.getEntity().getLabCherryPicks().iterator(); LabCherryPick lcp1 = iter.next(); LabCherryPick lcp2 = iter.next(); Copy copyA = _library.getCopy("A"); Copy copyB = _library.getCopy("B"); // edit LCP 1 source copy from A to B cherryPickRequestViewer.getLabCherryPicksSearchResult().edit(); assertEquals("A", genericEntityDao.reloadEntity(lcp1, true, LabCherryPick.wellVolumeAdjustments.to(WellVolumeAdjustment.copy)).getSourceCopy().getName()); ((TextEntityColumn<LabCherryPick>) cherryPickRequestViewer.getLabCherryPicksSearchResult().getColumnManager().getColumn("Source Copy")).setCellValue(lcp1, "B"); cherryPickRequestViewer.getLabCherryPicksSearchResult().setLabCherryPickSourceCopyUpdateComments("update1"); cherryPickRequestViewer.getLabCherryPicksSearchResult().save(); assertEquals("B", genericEntityDao.reloadEntity(lcp1, true, LabCherryPick.wellVolumeAdjustments.to(WellVolumeAdjustment.copy)).getSourceCopy().getName()); CherryPickRequest cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity(), true, CherryPickRequest.updateActivities.castToSubtype(CherryPickRequest.class)); assertEquals("updated source copy for lab cherry pick(s): " + lcp1.getSourceWell().getWellKey() + " from A to B", cpr.getUpdateActivitiesOfType(AdministrativeActivityType.LAB_CHERRY_PICK_SOURCE_COPY_OVERRIDE).last().getComments()); assertEquals("update1", cpr.getUpdateActivitiesOfType(AdministrativeActivityType.COMMENT).last().getComments()); Map<Copy,Volume> wellCopyVolumes = _librariesDao.findRemainingVolumesInWellCopies(lcp1.getSourceWell(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES); assertEquals("Copy A well volume reverted", new Volume(1000, VolumeUnit.DEFAULT), wellCopyVolumes.get(copyA)); assertEquals("Copy B well volume decreased", new Volume(499, VolumeUnit.DEFAULT), wellCopyVolumes.get(copyB)); // edit LCP 1 source copy from B to none cherryPickRequestViewer.getLabCherryPicksSearchResult().edit(); ((TextEntityColumn<LabCherryPick>) cherryPickRequestViewer.getLabCherryPicksSearchResult().getColumnManager().getColumn("Source Copy")).setCellValue(lcp1, null); cherryPickRequestViewer.getLabCherryPicksSearchResult().setLabCherryPickSourceCopyUpdateComments("update2"); cherryPickRequestViewer.getLabCherryPicksSearchResult().save(); assertFalse(genericEntityDao.reloadEntity(lcp1, true, LabCherryPick.wellVolumeAdjustments.to(WellVolumeAdjustment.copy)).isAllocated()); cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity(), true, CherryPickRequest.updateActivities.castToSubtype(CherryPickRequest.class)); assertEquals("updated source copy for lab cherry pick(s): " + lcp1.getSourceWell().getWellKey() + " from B to <none>", cpr.getUpdateActivitiesOfType(AdministrativeActivityType.LAB_CHERRY_PICK_SOURCE_COPY_OVERRIDE).last().getComments()); assertEquals("update2", cpr.getUpdateActivitiesOfType(AdministrativeActivityType.COMMENT).last().getComments()); wellCopyVolumes = _librariesDao.findRemainingVolumesInWellCopies(lcp1.getSourceWell(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES); assertEquals("Copy B well volume reverted", new Volume(500, VolumeUnit.DEFAULT), wellCopyVolumes.get(copyB)); // edit LCP 1 source copy from none to A, LCP 2 source copy from A to B cherryPickRequestViewer.getLabCherryPicksSearchResult().edit(); ((TextEntityColumn<LabCherryPick>) cherryPickRequestViewer.getLabCherryPicksSearchResult().getColumnManager().getColumn("Source Copy")).setCellValue(lcp1, "A"); ((TextEntityColumn<LabCherryPick>) cherryPickRequestViewer.getLabCherryPicksSearchResult().getColumnManager().getColumn("Source Copy")).setCellValue(lcp2, "B"); cherryPickRequestViewer.getLabCherryPicksSearchResult().setLabCherryPickSourceCopyUpdateComments("update3"); cherryPickRequestViewer.getLabCherryPicksSearchResult().save(); assertEquals("A", genericEntityDao.reloadEntity(lcp1, true, LabCherryPick.wellVolumeAdjustments.to(WellVolumeAdjustment.copy)).getSourceCopy().getName()); assertEquals("B", genericEntityDao.reloadEntity(lcp2, true, LabCherryPick.wellVolumeAdjustments.to(WellVolumeAdjustment.copy)).getSourceCopy().getName()); cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity(), true, CherryPickRequest.updateActivities.castToSubtype(CherryPickRequest.class)); // note: the ordering of the lab cherry pick comments is not deterministic so need to assert as follows: String comments = cpr.getUpdateActivitiesOfType(AdministrativeActivityType.LAB_CHERRY_PICK_SOURCE_COPY_OVERRIDE).last().getComments(); assertTrue(comments.contains(lcp1.getSourceWell().getWellKey() + " from <none> to A")); assertTrue(comments.contains(lcp2.getSourceWell().getWellKey() + " from A to B")); assertEquals("update3", cpr.getUpdateActivitiesOfType(AdministrativeActivityType.COMMENT).last().getComments()); wellCopyVolumes = _librariesDao.findRemainingVolumesInWellCopies(lcp1.getSourceWell(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES); assertEquals("Copy A well volume decreased", new Volume(999, VolumeUnit.DEFAULT), wellCopyVolumes.get(copyA)); wellCopyVolumes = _librariesDao.findRemainingVolumesInWellCopies(lcp2.getSourceWell(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES); assertEquals("Copy A well volume reverted", new Volume(1000, VolumeUnit.DEFAULT), wellCopyVolumes.get(copyA)); assertEquals("Copy B well volume decreased", new Volume(499, VolumeUnit.DEFAULT), wellCopyVolumes.get(copyB)); // test RecordOriginalSourceCopyWellsAsEmpty option // edit LCP 1 source copy from A to B cherryPickRequestViewer.getLabCherryPicksSearchResult().edit(); assertEquals("A", genericEntityDao.reloadEntity(lcp1, true, LabCherryPick.wellVolumeAdjustments.to(WellVolumeAdjustment.copy)).getSourceCopy().getName()); ((TextEntityColumn<LabCherryPick>) cherryPickRequestViewer.getLabCherryPicksSearchResult().getColumnManager().getColumn("Source Copy")).setCellValue(lcp1, "B"); cherryPickRequestViewer.getLabCherryPicksSearchResult().setLabCherryPickSourceCopyUpdateComments("update4"); cherryPickRequestViewer.getLabCherryPicksSearchResult().setRecordOriginalSourceCopyWellsAsEmpty(true); cherryPickRequestViewer.getLabCherryPicksSearchResult().save(); assertEquals("B", genericEntityDao.reloadEntity(lcp1, true, LabCherryPick.wellVolumeAdjustments.to(WellVolumeAdjustment.copy)).getSourceCopy().getName()); cpr = genericEntityDao.reloadEntity(cherryPickRequestViewer.getEntity(), true, CherryPickRequest.updateActivities.castToSubtype(CherryPickRequest.class)); assertEquals("updated source copy for lab cherry pick(s): " + lcp1.getSourceWell().getWellKey() + " from A to B", cpr.getUpdateActivitiesOfType(AdministrativeActivityType.LAB_CHERRY_PICK_SOURCE_COPY_OVERRIDE).last().getComments()); assertEquals("update4", cpr.getUpdateActivitiesOfType(AdministrativeActivityType.COMMENT).last().getComments()); wellCopyVolumes = _librariesDao.findRemainingVolumesInWellCopies(lcp1.getSourceWell(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES); assertTrue("Copy A well volume depleted", wellCopyVolumes.get(copyA).compareTo(new Volume(0, VolumeUnit.DEFAULT)) < 0); assertEquals("Copy B well volume decreased", new Volume(499, VolumeUnit.DEFAULT), wellCopyVolumes.get(copyB)); cherryPickRequestViewer.getMessages().getQueuedMessages().clear(); cherryPickRequestViewer.getLabCherryPicksSearchResult().edit(); ((TextEntityColumn<LabCherryPick>) cherryPickRequestViewer.getLabCherryPicksSearchResult().getColumnManager().getColumn("Source Copy")).setCellValue(lcp1, "E"); cherryPickRequestViewer.getLabCherryPicksSearchResult().save(); assertEquals("No copy E for plate 1000", cherryPickRequestViewer.getMessages().getQueuedMessages().get(0).getSecond().getSummary()); } }