// $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.searchresults;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.faces.model.DataModel;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import edu.harvard.med.screensaver.db.DAOTransaction;
import edu.harvard.med.screensaver.db.LibrariesDAO;
import edu.harvard.med.screensaver.model.Volume;
import edu.harvard.med.screensaver.model.cherrypicks.CherryPickRequest;
import edu.harvard.med.screensaver.model.cherrypicks.LabCherryPick;
import edu.harvard.med.screensaver.model.cherrypicks.ScreenerCherryPick;
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.PlateSize;
import edu.harvard.med.screensaver.model.libraries.Well;
import edu.harvard.med.screensaver.model.libraries.WellCopy;
import edu.harvard.med.screensaver.model.libraries.WellKey;
import edu.harvard.med.screensaver.model.libraries.WellVolume;
import edu.harvard.med.screensaver.model.libraries.WellVolumeAdjustment;
import edu.harvard.med.screensaver.model.users.AdministratorUser;
import edu.harvard.med.screensaver.test.MakeDummyEntities;
import edu.harvard.med.screensaver.ui.arch.datatable.column.TableColumn;
import edu.harvard.med.screensaver.ui.arch.view.AbstractBackingBeanTest;
import edu.harvard.med.screensaver.ui.libraries.WellCopyVolumeSearchResults;
import edu.harvard.med.screensaver.ui.libraries.WellVolumeSearchResults;
public class WellVolumeSearchResultsTest extends AbstractBackingBeanTest
{
private static Logger log = Logger.getLogger(WellVolumeSearchResultsTest.class);
@Autowired
protected LibrariesDAO librariesDao;
@Autowired
protected WellCopyVolumeSearchResults wellCopyVolumesBrowser;
@Autowired
protected WellVolumeSearchResults wellVolumesBrowser;
private Library _library;
private CherryPickRequest _cherryPickRequest;
private Map<WellCopy,Volume> _expectedRemainingWellCopyVolume = Maps.newHashMap();
private Map<WellKey,Volume> _expectedRemainingWellVolume = Maps.newHashMap();
@Override
protected void setUp() throws Exception
{
super.setUp();
initializeWellCopyVolumes();
}
public void testWellVolumeSearchResults()
{
wellCopyVolumesBrowser.searchWellsForLibrary(_library);
doTestWellCopyVolumeSearchResult(makeWellCopies(_library));
doTestWellVolumeSearchResult(makeWellVolumeKeys(makeWellCopies(_library)));
List<Well> wells = new ArrayList<Well>(_library.getWells()).subList(24, 96);
wellCopyVolumesBrowser.searchWells(makeWellKeys(wells));
doTestWellCopyVolumeSearchResult(makeWellCopies(wells));
doTestWellVolumeSearchResult(makeWellVolumeKeys(makeWellCopies(wells)));
wellCopyVolumesBrowser.searchWellsForCherryPickRequest(_cherryPickRequest, false);
doTestWellCopyVolumeSearchResult(makeWellCopies(_cherryPickRequest));
doTestWellVolumeSearchResult(makeWellVolumeKeys(makeWellCopies(_cherryPickRequest)));
}
private void doTestWellCopyVolumeSearchResult(SortedSet<WellCopy> expectedWellCopies)
{
DataModel model = wellCopyVolumesBrowser.getDataTableModel();
assertEquals("row count", expectedWellCopies.size(), model.getRowCount());
int j = 0;
for (WellCopy expectedWellCopy : expectedWellCopies) {
model.setRowIndex(j++);
//assertEquals("row data " + j, expectedWellCopy, ((WellCopy) model.getRowData()));
int columnsTested = 0;
WellCopy rowData = (WellCopy) model.getRowData();
for (TableColumn<WellCopy,?> column : wellCopyVolumesBrowser.getColumnManager().getAllColumns()) {
if (column.isVisible()) {
Object cellValue = column.getCellValue(rowData);
if (column.getName().equals("Library")) {
assertEquals("row " + j + ", " + expectedWellCopy + ":Library",
librariesDao.findLibraryWithPlate(expectedWellCopy.getWell().getPlateNumber()).getLibraryName(),
(String) cellValue);
++columnsTested;
}
else if (column.getName().equals("Plate")) {
assertEquals("row " + j + ", " + expectedWellCopy.getEntityId() + ":Plate",
(Integer) expectedWellCopy.getWell().getPlateNumber(),
(Integer) cellValue);
++columnsTested;
}
else if (column.getName().equals("Well")) {
assertEquals("row " + j + ", " + expectedWellCopy.getEntityId() + ":Well",
expectedWellCopy.getWell().getWellKey().getWellName().toString(),
(String) cellValue);
++columnsTested;
}
else if (column.getName().equals("Initial Volume")) {
assertEquals("row " + j + ", " + expectedWellCopy + ":Initial Volume",
expectedWellCopy.getCopy().getName().equals("C") ? new Volume(10) : new Volume(20),
(Volume) cellValue);
++columnsTested;
}
else if (column.getName().equals("Remaining Volume")) {
// this tests aggregation of WVAs
assertEquals("row " + j + ", " + expectedWellCopy + ":Remaining Volume",
_expectedRemainingWellCopyVolume.get(expectedWellCopy),
(Volume) cellValue);
++columnsTested;
}
// TODO: test all aggregation columns!
}
}
assertEquals("tested all columns for row " + j, 5, columnsTested);
}
}
private void doTestWellVolumeSearchResult(SortedSet<WellKey> expectedWellKeys)
{
DataModel model = wellVolumesBrowser.getDataTableModel();
assertEquals("row count", expectedWellKeys.size(), model.getRowCount());
int j = 0;
for (WellKey expectedKey : expectedWellKeys) {
model.setRowIndex(j++);
assertEquals("row data " + j,
expectedKey,
((WellVolume) model.getRowData()).getWell().getWellKey());
int columnsTested = 0;
WellVolume rowData = (WellVolume) model.getRowData();
for (TableColumn<WellVolume,?> column : wellVolumesBrowser.getColumnManager().getAllColumns()) {
if (column.isVisible()) {
Object cellValue = column.getCellValue(rowData);
if (column.getName().equals("Library")) {
assertEquals("row " + j + ", " + expectedKey + ":Library",
librariesDao.findLibraryWithPlate(expectedKey.getPlateNumber()).getLibraryName(),
(String) cellValue);
++columnsTested;
}
else if (column.getName().equals("Plate")) {
assertEquals("row " + j + ", " + expectedKey + ":Plate",
(Integer) expectedKey.getPlateNumber(),
(Integer) cellValue);
++columnsTested;
}
else if (column.getName().equals("Well")) {
assertEquals("row " + j + ", " + expectedKey + ":Well",
expectedKey.getWellName(),
(String) cellValue);
++columnsTested;
}
else if (column.getName().equals("Total Initial Copy Volume")) {
assertEquals("row " + j + ", " + expectedKey + ":Total Initial Copy Volume",
new Volume(30),
(Volume) cellValue);
++columnsTested;
}
else if (column.getName().equals("Consumed Volume")) {
// this tests aggregation of WVAs
assertEquals("row " + j + ", " + expectedKey + ":Consumed Volume",
new Volume(30).subtract((Volume) _expectedRemainingWellVolume.get(expectedKey)),
(Volume) cellValue);
++columnsTested;
}
else if (column.getName().equals("Copies")) {
// this tests aggregation of WVAs
assertEquals("row " + j + ", " + expectedKey + ":Copies",
ImmutableSortedSet.of("C", "D"),
cellValue);
++columnsTested;
}
// TODO: test all aggregation columns!
}
}
assertEquals("tested all columns for row " + j, 6, columnsTested);
}
}
/**
* 00001:A01:C: 1 lcp
* 00001:A01:D: 1 lcp
* 00001:A02:C: -
* 00001:A02:D: -
* 00001:B01:C: 2 wvas
* 00001:B01:D: -
* 00001:B02:C: 1 wva
* 00001:B02:D: 1 wva
* 00002:A01:C: 1 lcp
* 00002:A01:D: -
* 00002:B01:C: -
* 00002:B01:D: 1 lcp, 1 wva
*/
private void initializeWellCopyVolumes()
{
genericEntityDao.doInTransaction(new DAOTransaction() {
public void runTransaction() {
_library = MakeDummyEntities.makeRNAiDuplexLibrary("library", 1, 2, PlateSize.WELLS_384);
Copy copyC = _library.createCopy((AdministratorUser) _library.getCreatedBy(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES, "C");
Copy copyD = _library.createCopy((AdministratorUser) _library.getCreatedBy(), CopyUsageType.CHERRY_PICK_SOURCE_PLATES, "D");
copyC.findPlate(1).setWellVolume(new Volume(10));
copyC.findPlate(2).setWellVolume(new Volume(10));
copyD.findPlate(1).setWellVolume(new Volume(20));
copyD.findPlate(2).setWellVolume(new Volume(20));
genericEntityDao.saveOrUpdateEntity(_library);
Well plate1WellA01 = genericEntityDao.findEntityById(Well.class, "00001:A01");
Well plate1WellB01 = genericEntityDao.findEntityById(Well.class, "00001:B01");
Well plate1WellB02 = genericEntityDao.findEntityById(Well.class, "00001:B02");
Well plate2WellA01 = genericEntityDao.findEntityById(Well.class, "00002:A01");
Well plate2WellB01 = genericEntityDao.findEntityById(Well.class, "00002:B01");
_cherryPickRequest = MakeDummyEntities.createRNAiCherryPickRequest(1, new Volume(3));
ScreenerCherryPick dummyScreenerCherryPick = _cherryPickRequest.createScreenerCherryPick(plate1WellA01);
// note: 2 LCPs for the same well (which have to be in 2 separate CPRs) to test aggregation of 2 LCPs in the same well
CherryPickRequest cherryPickRequest2 = MakeDummyEntities.createRNAiCherryPickRequest(2, new Volume(3));
ScreenerCherryPick dummyScreenerCherryPick2 = cherryPickRequest2.createScreenerCherryPick(plate1WellA01);
dummyScreenerCherryPick.createLabCherryPick(plate1WellA01).setAllocated(copyC);
dummyScreenerCherryPick2.createLabCherryPick(plate1WellA01).setAllocated(copyD);
dummyScreenerCherryPick.createLabCherryPick(plate2WellA01).setAllocated(copyC);
dummyScreenerCherryPick.createLabCherryPick(plate2WellB01).setAllocated(copyD);
genericEntityDao.saveOrUpdateEntity(_cherryPickRequest.getScreen().getLeadScreener());
genericEntityDao.saveOrUpdateEntity(_cherryPickRequest.getScreen().getLabHead());
genericEntityDao.saveOrUpdateEntity(_cherryPickRequest.getScreen());
genericEntityDao.saveOrUpdateEntity(cherryPickRequest2.getScreen());
genericEntityDao.persistEntity(new WellVolumeAdjustment(copyC, plate1WellB01, new Volume(-1), null));
genericEntityDao.persistEntity(new WellVolumeAdjustment(copyC, plate1WellB01, new Volume(-1), null));
genericEntityDao.persistEntity(new WellVolumeAdjustment(copyC, plate1WellB02, new Volume(-1), null));
genericEntityDao.persistEntity(new WellVolumeAdjustment(copyD, plate1WellB02, new Volume(-1), null));
genericEntityDao.persistEntity(new WellVolumeAdjustment(copyD, plate2WellB01, new Volume(-1), null));
_expectedRemainingWellCopyVolume.put(new WellCopy(plate1WellA01, copyC), new Volume(7));
_expectedRemainingWellCopyVolume.put(new WellCopy(plate1WellA01, copyD), new Volume(17));
_expectedRemainingWellCopyVolume.put(new WellCopy(plate1WellB01, copyC), new Volume(8));
_expectedRemainingWellCopyVolume.put(new WellCopy(plate1WellB02, copyC), new Volume(9));
_expectedRemainingWellCopyVolume.put(new WellCopy(plate1WellB02, copyD), new Volume(19));
_expectedRemainingWellCopyVolume.put(new WellCopy(plate2WellA01, copyC), new Volume(7));
_expectedRemainingWellCopyVolume.put(new WellCopy(plate2WellB01, copyD), new Volume(16));
for (Well well : _library.getWells()) {
Volume expectedRemainingWellVolume = new Volume(0);
for (Copy copy : _library.getCopies()) {
WellCopy wellCopy = new WellCopy(well, copy);
if (!_expectedRemainingWellCopyVolume.containsKey(wellCopy)) {
Volume expectedRemainingWellCopyVolume = copy.getPlates().values().iterator().next().getWellVolume();
_expectedRemainingWellCopyVolume.put(wellCopy, expectedRemainingWellCopyVolume);
expectedRemainingWellVolume = expectedRemainingWellVolume.add(expectedRemainingWellCopyVolume);
}
else {
expectedRemainingWellVolume = expectedRemainingWellVolume.add((Volume) _expectedRemainingWellCopyVolume.get(wellCopy));
}
}
_expectedRemainingWellVolume.put(well.getWellKey(), expectedRemainingWellVolume);
}
}
});
}
private static Set<WellKey> makeWellKeys(List<Well> wells)
{
Set<WellKey> wellKeys = new HashSet<WellKey>();
for (Well well : wells) {
wellKeys.add(well.getWellKey());
}
return wellKeys;
}
private static SortedSet<WellCopy> makeWellCopies(Library library)
{
SortedSet<WellCopy> wellCopies = Sets.newTreeSet();
for (Well well : library.getWells()) {
for (Copy copy : library.getCopies()) {
wellCopies.add(new WellCopy(well, copy));
}
}
return wellCopies;
}
private static SortedSet<WellCopy> makeWellCopies(List<Well> wells)
{
SortedSet<WellCopy> wellCopies = Sets.newTreeSet();
for (Well well : wells) {
for (Copy copy : well.getLibrary().getCopies()) {
wellCopies.add(new WellCopy(well, copy));
}
}
return wellCopies;
}
private static SortedSet<WellCopy> makeWellCopies(CherryPickRequest cherryPickRequest)
{
SortedSet<WellCopy> wellCopies = Sets.newTreeSet();
for (LabCherryPick labCherryPick : cherryPickRequest.getLabCherryPicks()) {
Well well = labCherryPick.getSourceWell();
for (Copy copy : well.getLibrary().getCopies()) {
wellCopies.add(new WellCopy(well, copy));
}
}
return wellCopies;
}
private SortedSet<WellKey> makeWellVolumeKeys(SortedSet<WellCopy> wellCopies)
{
SortedSet<WellKey> wellKeys = new TreeSet<WellKey>();
for (WellCopy wellCopy : wellCopies) {
wellKeys.add(wellCopy.getWell().getWellKey());
}
return wellKeys;
}
}