package edu.harvard.med.lincs.screensaver.ui.libraries;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import edu.harvard.med.screensaver.db.Criterion;
import edu.harvard.med.screensaver.db.DAOTransaction;
import edu.harvard.med.screensaver.db.GenericEntityDAO;
import edu.harvard.med.screensaver.db.LibrariesDAO;
import edu.harvard.med.screensaver.db.Criterion.Operator;
import edu.harvard.med.screensaver.db.datafetcher.DataFetcher;
import edu.harvard.med.screensaver.db.datafetcher.DataFetcherUtil;
import edu.harvard.med.screensaver.db.datafetcher.Tuple;
import edu.harvard.med.screensaver.db.datafetcher.TupleDataFetcher;
import edu.harvard.med.screensaver.db.hqlbuilder.HqlBuilder;
import edu.harvard.med.screensaver.io.DataExporter;
import edu.harvard.med.screensaver.io.libraries.smallmolecule.LibraryContentsVersionReference;
import edu.harvard.med.screensaver.io.libraries.smallmolecule.StructureImageLocator;
import edu.harvard.med.screensaver.model.libraries.Well;
import edu.harvard.med.screensaver.model.meta.PropertyPath;
import edu.harvard.med.screensaver.policy.EntityViewPolicy;
import edu.harvard.med.screensaver.ui.arch.datatable.column.TableColumn;
import edu.harvard.med.screensaver.ui.arch.datatable.model.InMemoryEntityDataModel;
import edu.harvard.med.screensaver.ui.arch.util.servlet.ImageProviderServlet;
import edu.harvard.med.screensaver.ui.libraries.LibraryViewer;
import edu.harvard.med.screensaver.ui.libraries.WellSearchResults;
/**
* LINCS-specific WellSearchResults that:
* <ul>
* <li>Uses an InMemoryEntityDataModel, required by its use of "virtual" columns (e.g. "Facility-Salt-Batch ID")</li>
* <li>Coordinates with another "Unique Reagents" browser (also a LincsWellSearchResults) by initializing it with data that is based upon the current search results
* </ul>
* @author <a mailto="andrew_tolopko@hms.harvard.edu">Andrew Tolopko</a>
*/
public class LincsWellSearchResults extends WellSearchResults
{
private static final Logger log = Logger.getLogger(LincsWellSearchResults.class);
private LincsWellSearchResults _reagentsBrowser;
private GenericEntityDAO _dao;
private LibrariesDAO _librariesDao;
protected LincsWellSearchResults()
{
super();
}
public LincsWellSearchResults(GenericEntityDAO dao,
LibrariesDAO librariesDao,
EntityViewPolicy entityViewPolicy,
LibraryViewer libraryViewer,
WellViewer wellViewer,
StructureImageLocator structureImageLocator,
LibraryContentsVersionReference libraryContentsVersionRef,
List<DataExporter<Tuple<String>>> dataExporters,
ImageProviderServlet imageProviderServlet)
{
super(dao, librariesDao, entityViewPolicy, libraryViewer, wellViewer, structureImageLocator, libraryContentsVersionRef, dataExporters, imageProviderServlet);
_dao = dao;
_librariesDao = librariesDao;
}
public LincsWellSearchResults getReagentsBrowser()
{
return _reagentsBrowser;
}
public void setReagentsBrowser(LincsWellSearchResults reagentsBrowser)
{
_reagentsBrowser = reagentsBrowser;
}
@Override
protected void initialize(DataFetcher<Tuple<String>,String,PropertyPath<Well>> dataFetcher)
{
InMemoryEntityDataModel<Well,String,Tuple<String>> dataModel = new InMemoryEntityDataModel<Well,String,Tuple<String>>(dataFetcher)
{
@Override
public void filter(List<? extends TableColumn<Tuple<String>,?>> columns)
{
if(((Collection)getWrappedData()).isEmpty())
{
refetch();
}
super.filter(columns);
}
};
initialize(dataModel);
if (!!!isNested() && _reagentsBrowser != null ) {
assert _reagentsBrowser.getReagentsBrowser() == null : "infinite recursion error in reagents browser";
_reagentsBrowser.searchCanonicalReagentsOfWellsBrowser(this, getTitle().replaceFirst("(Reagent )?Wells", "Unique Reagents"));
}
}
@Override
public void searchAll()
{
setTitle("Wells Search Result");
setMode(WellSearchResultMode.SET_OF_CANONICAL_REAGENT_WELLS);
// initially, show an empty search result, but with all columns available
TupleDataFetcher<Well,String> dataFetcher = new TupleDataFetcher<Well,String>(Well.class, _dao)
{
@Override
public List<Tuple<String>> fetchAllData()
{
//log.info("fetchAllData: " + hasCriteriaDefined(getCriterion(getColumnManager().getAllColumns())) );
if (!hasCriteriaDefined(getCriterion(getColumnManager().getAllColumns()))) {
return Collections.emptyList();
}
return super.fetchAllData();
}
private List<? extends Criterion<?>> getCriterion(List<TableColumn<Tuple<String>,?>> columns)
{
List<Criterion<?>> criterion = Lists.newArrayList();
for(TableColumn<Tuple<String>,?> column:columns) {
criterion.add(column.getCriterion());
}
return criterion;
}
private boolean hasCriteriaDefined(List<? extends Criterion<?>> criteria)
{
for (Criterion<?> c : criteria) {
if (!c.isUndefined()) {
return true;
}
}
return false;
}
@Override
public void addDomainRestrictions(final HqlBuilder hql)
{
hql.from(getRootAlias(), Well.reagents, "r").where("r", "vendorId.vendorIdentifier", Operator.NOT_EMPTY, null);
}
};
initialize(dataFetcher);
// start with search panel open
setTableFilterMode(true);
adjustVisibleColumnsForLincs();
}
public void searchCanonicalReagentsOfWellsBrowser(final WellSearchResults fullWellSearchResults,
String title)
{
setTitle(title);
setMode(WellSearchResultMode.SET_OF_CANONICAL_REAGENT_WELLS);
//_screenTypes = _librariesDao.findScreenTypesForWells(wellKeys);
TupleDataFetcher<Well,String> dataFetcher =
new TupleDataFetcher<Well,String>(Well.class, _dao) {
@Override
public void addDomainRestrictions(final HqlBuilder hql)
{
_dao.doInTransaction(new DAOTransaction() {
@Override
public void runTransaction()
{
log.debug("initializing unique reagent search result");
fullWellSearchResults.getRowCount(); // force initialization
Iterable<String> fullReagentWellIds = Iterables.transform(fullWellSearchResults.getDataTableModel(), Tuple.<String>toKey());
Set<String> canonicalReagentWellIds = _librariesDao.findCanonicalReagentWellIds(Sets.newHashSet(fullReagentWellIds));
DataFetcherUtil.addDomainRestrictions(hql, getRootAlias(), canonicalReagentWellIds);
}
});
}
};
initialize(dataFetcher);
// start with search panel closed
setTableFilterMode(false);
adjustVisibleColumnsForLincs();
}
private void adjustVisibleColumnsForLincs()
{
getColumnManager().setVisibilityOfColumnsInGroup("Compound Reagent Columns", false);
getColumnManager().setVisibilityOfColumnsInGroup("Well Columns", false);
getColumnManager().getColumn("Facility ID").setVisible(true);
getColumnManager().getColumn("Primary Compound Name").setVisible(true);
getColumnManager().getColumn("Compound Names").setVisible(true);
getColumnManager().getColumn("Plate").setVisible(false);
getColumnManager().getColumn("Well").setVisible(false);
}
/**
* For LINCS, it does not make sense to show study annotation data in Well Search Results, as these data only apply to
* a single compound, and so these data are better viewed in the Study Viewer itself
*/
protected void buildAnnotationTypeColumns(List<TableColumn<Tuple<String>,?>> columns)
{
return;
}
}