// $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.db.datafetcher;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.log4j.Logger;
import edu.harvard.med.screensaver.db.Criterion;
import edu.harvard.med.screensaver.db.Criterion.Operator;
import edu.harvard.med.screensaver.db.Criterion.OperatorClass;
import edu.harvard.med.screensaver.db.DAOTransaction;
import edu.harvard.med.screensaver.db.hqlbuilder.HqlBuilder;
import edu.harvard.med.screensaver.model.Entity;
import edu.harvard.med.screensaver.model.libraries.Gene;
import edu.harvard.med.screensaver.model.libraries.Library;
import edu.harvard.med.screensaver.model.libraries.Reagent;
import edu.harvard.med.screensaver.model.libraries.SilencingReagent;
import edu.harvard.med.screensaver.model.libraries.Well;
import edu.harvard.med.screensaver.model.libraries.WellKey;
import edu.harvard.med.screensaver.model.meta.PropertyPath;
import edu.harvard.med.screensaver.model.meta.RelationshipPath;
import edu.harvard.med.screensaver.model.screenresults.AnnotationType;
import edu.harvard.med.screensaver.model.screenresults.AnnotationValue;
import edu.harvard.med.screensaver.model.screenresults.AssayWell;
import edu.harvard.med.screensaver.model.screenresults.DataColumn;
import edu.harvard.med.screensaver.model.screenresults.PartitionedValue;
import edu.harvard.med.screensaver.model.screenresults.ResultValue;
import edu.harvard.med.screensaver.model.screenresults.ScreenResult;
import edu.harvard.med.screensaver.model.screens.Screen;
import edu.harvard.med.screensaver.model.screens.ScreenType;
import edu.harvard.med.screensaver.test.AbstractSpringPersistenceTest;
import edu.harvard.med.screensaver.test.MakeDummyEntities;
public class EntityDataFetcherTest extends AbstractSpringPersistenceTest
{
// static members
private static Logger log = Logger.getLogger(EntityDataFetcherTest.class);
// instance data members
private EntityDataFetcher<Well,String> _screenResultWellFetcher;
private EntityDataFetcher<Well,String> _wellSetFetcher;
private EntityDataFetcher<Well,String> _allWellsFetcher;
private List<PropertyPath<Well>> _pathsToFetch = Lists.newArrayList();
private List<PropertyPath<Well>> _sortProperties = Lists.newArrayList();
private Map<PropertyPath<Well>,List<? extends Criterion<?>>> _criteria = new HashMap<PropertyPath<Well>,List<? extends Criterion<?>>>();;
private PropertyPath<Well> _plateNumberPropPath;
private PropertyPath<Well> _wellNamePropPath;
private static boolean oneTimeDataSetup = false;
private static Screen _rnaiScreen;
private static Screen _study;
private static Library _rnaiLibrary;
private static ScreenResult _screenResult;
private static int _plates = 2;
// public constructors and methods
@Override
protected void setUp() throws Exception
{
if (!oneTimeDataSetup) {
oneTimeDataSetup = true;
super.setUp();
genericEntityDao.doInTransaction(new DAOTransaction() {
public void runTransaction()
{
_rnaiScreen = MakeDummyEntities.makeDummyScreen(2, ScreenType.RNAI);
_rnaiLibrary = MakeDummyEntities.makeDummyLibrary(2,
_rnaiScreen.getScreenType(),
_plates);
genericEntityDao.saveOrUpdateEntity(_rnaiLibrary.getContentsVersions().first().getLoadingActivity().getCreatedBy());
genericEntityDao.saveOrUpdateEntity(_rnaiLibrary);
_screenResult = MakeDummyEntities.makeDummyScreenResult(_rnaiScreen,
_rnaiLibrary);
genericEntityDao.saveOrUpdateEntity(_rnaiScreen.getLeadScreener());
genericEntityDao.saveOrUpdateEntity(_rnaiScreen.getLabHead());
genericEntityDao.saveOrUpdateEntity(_rnaiScreen);
// make a study, for its annotations
_study = MakeDummyEntities.makeDummyStudy(_rnaiLibrary);
genericEntityDao.persistEntity(_study.getLeadScreener());
genericEntityDao.persistEntity(_study.getLabHead());
genericEntityDao.persistEntity(_study);
// make another screen result, to ensure tests that are looking for
// the data from a particular screen result are not also retrieving
// data from another screen result
Screen otherRnaiScreen = MakeDummyEntities.makeDummyScreen(3,
ScreenType.RNAI);
MakeDummyEntities.makeDummyScreenResult(otherRnaiScreen, _rnaiLibrary);
genericEntityDao.saveOrUpdateEntity(otherRnaiScreen.getLeadScreener());
genericEntityDao.saveOrUpdateEntity(otherRnaiScreen.getLabHead());
genericEntityDao.saveOrUpdateEntity(otherRnaiScreen);
}
});
}
// note: we reload everything, even if it was just created (above), since we
// want entity-ID-based hashCodes, not Object hashCodes
genericEntityDao.doInTransaction(new DAOTransaction() {
public void runTransaction()
{
_rnaiScreen = genericEntityDao.reloadEntity(_rnaiScreen, true);
_screenResult = _rnaiScreen.getScreenResult();
genericEntityDao.needReadOnly(_screenResult, ScreenResult.dataColumns.to(DataColumn.resultValues));
genericEntityDao.needReadOnly(_screenResult, ScreenResult.assayWells);
_study = genericEntityDao.reloadEntity(_study, true, Screen.annotationTypes.to(AnnotationType.annotationValues));
_rnaiLibrary = genericEntityDao.reloadEntity(_rnaiLibrary, true, Library.wells);
}
});
_plateNumberPropPath = RelationshipPath.from(Well.class).toProperty("plateNumber");
_wellNamePropPath = RelationshipPath.from(Well.class).toProperty("wellName");
_sortProperties.add(_plateNumberPropPath);
_sortProperties.add(_wellNamePropPath);
_pathsToFetch.add(_plateNumberPropPath);
_pathsToFetch.add(_wellNamePropPath);
_screenResultWellFetcher = new EntityDataFetcher<Well,String>(Well.class, genericEntityDao) {
@Override
public void addDomainRestrictions(HqlBuilder hql)
{
hql.from(AssayWell.class, "aw");
hql.where(getRootAlias(), "wellId", Operator.EQUAL, "aw", "libraryWell");
hql.where("aw", "screenResult", Operator.EQUAL, _screenResult);
}
};
final Set<String> wellKeys = Sets.newHashSet("02000:A01", "02001:P24");
_wellSetFetcher = new EntityDataFetcher<Well,String>(Well.class, genericEntityDao) {
@Override
public void addDomainRestrictions(HqlBuilder hql)
{
DataFetcherUtil.addDomainRestrictions(hql, getRootAlias(), wellKeys);
}
};
_allWellsFetcher = new EntityDataFetcher<Well,String>(Well.class, genericEntityDao);
}
/**
* Test fetching all data of a single-entity (shallow) entity network.
*/
public void testShallowFetchAllData()
{
_screenResultWellFetcher.setPropertiesToFetch(_pathsToFetch);
_wellSetFetcher.setPropertiesToFetch(_pathsToFetch);
_allWellsFetcher.setPropertiesToFetch(_pathsToFetch);
assertEquals("fetch parented",
384 * _plates,
_screenResultWellFetcher.fetchAllData().size());
assertEquals("fetch set", 2, _wellSetFetcher.fetchAllData().size());
assertEquals("fetch all", 384 * _plates, _allWellsFetcher.fetchAllData().size());
}
/**
* Test fetching a subset (data range) of a single-entity (shallow) entity network,
* unrestricted, sorted by ID.
*/
@SuppressWarnings("unchecked")
public void testShallowFetchDataRange()
{
_screenResultWellFetcher.setPropertiesToFetch(_pathsToFetch);
_screenResultWellFetcher.setOrderBy(_sortProperties);
AssayWell[] assayWells = Iterables.toArray(_screenResult.getAssayWells(), AssayWell.class);
Set<String> wellIds = Sets.newHashSet();
for (int i = 24; i < 48; i++) {
wellIds.add(assayWells[i].getLibraryWell().getWellId());
}
List<String> foundKeys = _screenResultWellFetcher.findAllKeys();
assertEquals("size", 384 * _plates, foundKeys.size());
isSorted(foundKeys);
Map<String,Well> data = _screenResultWellFetcher.fetchData(wellIds);
assertEquals(wellIds, data.keySet());
assertEquals(wellIds, Sets.newHashSet(Iterables.transform(data.values(), Entity.ToEntityId)));
}
/**
* Test fetching a subset (data range) of a single-entity (shallow) entity network,
* with filtering criteria, sorted by ID.
*/
public void testShallowFetchDataRangeFiltered()
{
_screenResultWellFetcher.setPropertiesToFetch(_pathsToFetch);
_screenResultWellFetcher.setOrderBy(_sortProperties);
_criteria.put(_wellNamePropPath, Collections.singletonList(new Criterion<String>(Operator.TEXT_STARTS_WITH, "B2")));
_criteria.put(_plateNumberPropPath, Collections.singletonList(new Criterion<Integer>(Operator.EQUAL, 2001)));
_screenResultWellFetcher.setFilteringCriteria(_criteria);
List<String> expectedWellKeys = new ArrayList<String>();
expectedWellKeys.add(new WellKey(2001, "B20").toString());
expectedWellKeys.add(new WellKey(2001, "B21").toString());
expectedWellKeys.add(new WellKey(2001, "B22").toString());
expectedWellKeys.add(new WellKey(2001, "B23").toString());
expectedWellKeys.add(new WellKey(2001, "B24").toString());
List<String> foundKeys = _screenResultWellFetcher.findAllKeys();
assertEquals("keys", expectedWellKeys, foundKeys);
Map<String,Well> data = _screenResultWellFetcher.fetchData(new HashSet<String>(expectedWellKeys));
assertEquals("size", expectedWellKeys.size(), data.size());
for (String expectedWellKey : expectedWellKeys) {
assertTrue(data.containsKey(expectedWellKey));
assertEquals(expectedWellKey, data.get(expectedWellKey).getWellKey().toString());
}
}
/**
* Test fetching a subset (data range) of a multiple-entity (deep) entity network,
* with filtering criteria on 2 properties of restricted collections.
*/
public void testDeepFetchDataRangeFiltered()
{
DataColumn col1 = _screenResult.getDataColumnsList().get(0);
DataColumn col2 = _screenResult.getDataColumnsList().get(2);
DataColumn col3 = _screenResult.getDataColumnsList().get(6);
DataColumn col4 = _screenResult.getDataColumnsList().get(7); // "comments", with sparse result values
PropertyPath<Well> propertyPath1 = Well.resultValues.restrict("dataColumn", col1).toProperty("value");
PropertyPath<Well> propertyPath2 = Well.resultValues.restrict("dataColumn", col2).toProperty("value");
PropertyPath<Well> propertyPath3 = Well.resultValues.restrict("dataColumn", col3).toProperty("positive");
PropertyPath<Well> propertyPath4 = Well.resultValues.restrict("dataColumn", col4).toProperty("value");
_pathsToFetch.add(propertyPath1);
_pathsToFetch.add(propertyPath2);
_pathsToFetch.add(propertyPath3);
_pathsToFetch.add(propertyPath4);
_criteria.put(propertyPath3, Collections.singletonList(new Criterion<Boolean>(Operator.EQUAL, true)));
_criteria.put(propertyPath4, Collections.singletonList(new Criterion<String>(Operator.NOT_EMPTY, null)));
_screenResultWellFetcher.setPropertiesToFetch(_pathsToFetch);
_screenResultWellFetcher.setFilteringCriteria(_criteria);
Set<String> expectedWellIds = Sets.newHashSet();
for (ResultValue rv : col3.getResultValues()) {
if (rv.isPositive()) {
expectedWellIds.add(rv.getWell().getWellId());
}
}
for (ResultValue rv : col4.getResultValues()) {
if (rv.isNull() || rv.getValue().isEmpty()) {
expectedWellIds.remove(rv.getWell().getWellId());
}
}
Set<String> foundWellIds = Sets.newHashSet(_screenResultWellFetcher.findAllKeys());
log.debug("not found: " + Sets.difference(expectedWellIds, foundWellIds));
log.debug("found unexpectedly: " + Sets.difference(foundWellIds, expectedWellIds));
assertEquals("findAllKeys", expectedWellIds, foundWellIds);
Map<String,Well> data = _screenResultWellFetcher.fetchData(new HashSet<String>(expectedWellIds));
assertEquals("fetchData", expectedWellIds.size(), data.size());
for (String expectedWellKey : expectedWellIds) {
assertTrue("fetchData", data.containsKey(expectedWellKey));
assertEquals("fetchData", expectedWellKey, data.get(expectedWellKey).getWellKey().toString());
}
}
public void testEagerFetchCollections()
{
_allWellsFetcher.setPropertiesToFetch(Lists.newArrayList(Well.resultValues.toFullEntity(), Well.library.to(Library.contentsVersions).toFullEntity()));
List<Well> allData = _allWellsFetcher.fetchAllData();
Collections.sort(allData);
Well well = allData.get(0);
assertEquals("well.resultValues unrestricted size",
_screenResult.getDataColumns().size() /*DataColumns per screen result*/ * 2 /* screen results*/,
well.getResultValues().size());
_allWellsFetcher.setPropertiesToFetch(Lists.newArrayList(Well.latestReleasedReagent.to(Reagent.annotationValues).toFullEntity(), Well.library.to(Library.contentsVersions).toFullEntity()));
allData = _allWellsFetcher.fetchAllData();
Collections.sort(allData);
well = allData.get(0);
assertEquals("well.reagent.annotationValues restricted size",
_study.getAnnotationTypes().size() /*ATs per study*/ * 1 /*study*/,
well.<Reagent>getLatestReleasedReagent().getAnnotationValues().size());
_pathsToFetch.add(Well.resultValues.to(ResultValue.DataColumn).restrict(DataColumn.ScreenResult.getLeaf(), _screenResult).toFullEntity());
_allWellsFetcher.setPropertiesToFetch(_pathsToFetch);
allData = _allWellsFetcher.fetchAllData();
Collections.sort(allData);
// test a well that has a RV for every DataColumn
well = allData.get(0);
assertEquals("expected well", "02000:A01", well.getWellKey().toString());
assertEquals("well.resultValues restricted size",
// NOTE: Expected size is non-restricted size. We gave up on
// trying to filter collections when eager fetching; Hibernate
// does not naturally support this via
// EntityDataFetcher.getOrCreateFetchJoin()
16, //_screenResult.getDataColumns().size(),
well.getResultValues().size());
// test a well that does not have a RV for every DataColumn
well = allData.get(3);
assertEquals("expected well", "02000:A04", well.getWellKey().toString());
assertEquals("well.resultValues restricted size",
// NOTE: Expected size is non-restricted size. We gave up on
// trying to filter collections when eager fetching; Hibernate
// does not naturally support this via
// EntityDataFetcher.getOrCreateFetchJoin()
16 - 2 /*_screenResult.getDataColumns().size() - 1*/,
well.getResultValues().size());
}
/**
* Test eager fetching of restricted collections that are empty when restricted,
* verifying that all root entities are still returned in the result.
*/
public void testEagerFetchEmptyRestrictedCollection()
{
final Set<String> wellKeys = Sets.newHashSet("02000:A04", "02000:A08", "02000:A12");
EntityDataFetcher<Well,String> wellSetFetcher = new EntityDataFetcher<Well,String>(Well.class, genericEntityDao) {
@Override
public void addDomainRestrictions(HqlBuilder hql)
{
DataFetcherUtil.addDomainRestrictions(hql, getRootAlias(), wellKeys);
}
};
DataColumn commentsCol = _screenResult.getDataColumnsList().get(7); // has with sparse result values
_pathsToFetch.add(Well.latestReleasedReagent.to(Reagent.annotationValues).toFullEntity());
_pathsToFetch.add(Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), commentsCol).toFullEntity());
wellSetFetcher.setPropertiesToFetch(_pathsToFetch);
List<Well> allData = wellSetFetcher.fetchAllData();
assertEquals("fetch all data size", 3, allData.size());
for (Well well : allData) {
assertTrue("expected well", wellKeys.contains(well.getWellKey().toString()));
// NOTE: We gave up on trying to filter collections when eager fetching;
// Hibernate does not naturally support this via
// EntityDataFetcher.getOrCreateFetchJoin()
// assertEquals("empty restricted collection (resultValues)", 0, well.getResultValues().size());
// assertEquals("empty restricted collection (annotationValues)", 0, well.<Reagent>getLatestReleasedReagent().getAnnotationValues().size());
}
}
/**
* Test eager fetching of multiple restricted collections, of same entity type
* but with different restriction values, with restriction at path depth 1
*/
public void testEagerFetchMultipleRestrictedCollectionsOfSameType()
{
_pathsToFetch.add(Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), _screenResult.getDataColumnsList().get(0)).toFullEntity());
_pathsToFetch.add(Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), _screenResult.getDataColumnsList().get(2)).toFullEntity());
_allWellsFetcher.setPropertiesToFetch(_pathsToFetch);
List<Well> allData = _allWellsFetcher.fetchAllData();
Collections.sort(allData);
Well well = allData.get(0);
assertEquals("well.resultValues restricted size",
// NOTE: Expected size is non-restricted size. We gave up on
// trying to filter collections when eager fetching; Hibernate
// does not naturally support this via
// EntityDataFetcher.getOrCreateFetchJoin()
16, // 2 /* selected DataColumns */,
well.getResultValues().size());
}
/**
* Test eager fetching of multiple restricted collections, of different entity
* types, with at least one of the collections having "sparse" (undefined)
* values for the root entity
*/
public void testEagerFetchMultipleRestrictedSparseCollectionsOfDifferentTypes()
{
_pathsToFetch.add(Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), _screenResult.getDataColumnsList().get(0)).toFullEntity());
_pathsToFetch.add(Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), _screenResult.getDataColumnsList().get(2)).toFullEntity());
_pathsToFetch.add(Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), _screenResult.getDataColumnsList().get(7)).toFullEntity());
Iterator<AnnotationType> annotationTypesIter = _study.getAnnotationTypes().iterator();
AnnotationType annotationType1 = annotationTypesIter.next();
AnnotationType annotationType2 = annotationTypesIter.next();
_pathsToFetch.add(Well.latestReleasedReagent.to(Reagent.annotationValues).restrict(AnnotationValue.annotationType.getLeaf(), annotationType1).toFullEntity());
_pathsToFetch.add(Well.latestReleasedReagent.to(Reagent.annotationValues).restrict(AnnotationValue.annotationType.getLeaf(), annotationType2).toFullEntity());
_pathsToFetch.add(Well.library.to(Library.contentsVersions).toFullEntity());
_allWellsFetcher.setPropertiesToFetch(_pathsToFetch);
List<Well> allData = _allWellsFetcher.fetchAllData();
Collections.sort(allData);
assertEquals("full data size",
_screenResult.getAssayWells().size(),
allData.size());
// NOTE: In below asserts, for restricted collections expected size is
// non-restricted size. We gave up on trying to filter collections when
// eager fetching; Hibernate does not naturally support this via
// EntityDataFetcher.getOrCreateFetchJoin()
// this well should have values defined for each property
Well well = allData.get(0);
assertEquals("expected well", "02000:A01", well.getWellKey().toString());
assertEquals("well.resultValues restricted size",
16, //3 /* selected DataColumns */,
well.getResultValues().size());
assertEquals("well.reagent.annotationValues restricted size",
2 /* selected annotationTypes */,
well.<Reagent>getLatestReleasedReagent().getAnnotationValues().size());
// this well should have values for all DataColumns, but undefined values for all AnnotTypes
well = allData.get(2);
assertEquals("expected well", "02000:A03", well.getWellKey().toString());
assertEquals("well.resultValues restricted size",
16, //3 /* selected DataColumns */,
well.getResultValues().size());
assertEquals("well.reagent.annotationValues restricted size",
0 /* selected annotationTypes */,
well.<Reagent>getLatestReleasedReagent().getAnnotationValues().size());
// this well should have undefined values for one DataColumn and all AnnotTypes
well = allData.get(3);
assertEquals("expected well", "02000:A04", well.getWellKey().toString());
assertEquals("well.resultValues restricted size",
14, //2 /* selected DataColumns */,
well.getResultValues().size());
assertEquals("well.reagent.annotationValues restricted size",
0 /* selected annotationTypes */,
well.<Reagent>getLatestReleasedReagent().getAnnotationValues().size());
}
/**
* Tests database-level filtering of EntityDataFetcher. The test is performed
* by comparing the result of in-memory filtering of full result (the
* "expected" result) to the restricted result returned by the database. So note
* that this test is only verifying that the restricted result matches the
* behavior of Criterion.match(). But this is okay, since we have explicit
* tests for Criterion.match().
*/
public void testAllFilterOperators()
{
final DataColumn numericCol = _screenResult.getDataColumnsList().get(0);
final DataColumn textCol = _screenResult.getDataColumnsList().get(2);
final DataColumn positiveCol = _screenResult.getDataColumnsList().get(6);
final DataColumn commentCol = _screenResult.getDataColumnsList().get(7);
PropertyPath<Well> numericColPropPath = Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), numericCol).toProperty("numericValue");
PropertyPath<Well> textColPropPath = Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), textCol).toProperty("value");
PropertyPath<Well> positiveColPropPath = Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), positiveCol).toProperty("value");
// the "comments" DataColumn contains blank and missing (null) resultValues, allowing us to test the EMPTY and NOT_EMPTY operators
PropertyPath<Well> commentColPropPath = Well.resultValues.restrict(ResultValue.DataColumn.getLeaf(), commentCol).toProperty("value");
_pathsToFetch.add(numericColPropPath);
_pathsToFetch.add(textColPropPath);
_pathsToFetch.add(positiveColPropPath);
_pathsToFetch.add(commentColPropPath);
_allWellsFetcher.setPropertiesToFetch(_pathsToFetch);
List<Well> allData = _allWellsFetcher.fetchAllData();
assertEquals("sanity check that we're testing filtering against full data set", _screenResult.getAssayWells().size(), allData.size());
Getter<Well,String> wellNameGetter = new Getter<Well,String>() { public String get(Well well) { return well.getWellName(); } };
Getter<Well,Double> rvNumericValueGetter = new Getter<Well,Double>() { public Double get(Well well) { return well.getResultValues().get(numericCol).getNumericValue(); } };
Getter<Well,String> ColextValueGetter = new Getter<Well,String>() { public String get(Well well) { return well.getResultValues().get(textCol).getValue(); } };
Getter<Well,String> positiveValueGetter = new Getter<Well,String>() { public String get(Well well) { return well.getResultValues().get(positiveCol).getValue(); } };
Getter<Well,String> commentValueGetter = new Getter<Well,String>() {
public String get(Well well) {
ResultValue rv = well.getResultValues().get(commentCol);
return rv == null ? null : rv.getValue();
}
};
for (Operator operator : Operator.ALL_OPERATORS) {
doTestFilterOperator(RelationshipPath.from(Well.class).toProperty("wellName"), new Criterion<String>(operator, "B18"), wellNameGetter, allData);
if (operator.getOperatorClass() == OperatorClass.EQUALITY ||
operator.getOperatorClass() == OperatorClass.RANKING) {
doTestFilterOperator(numericColPropPath, new Criterion<Double>(operator, new Double(1.0)), rvNumericValueGetter, allData);
doTestFilterOperator(textColPropPath, new Criterion<String>(operator, "text00100"), ColextValueGetter, allData);
doTestFilterOperator(positiveColPropPath, new Criterion<String>(operator, PartitionedValue.MEDIUM.getValue()), positiveValueGetter, allData);
}
else if (operator.getOperatorClass() == OperatorClass.EXTANT) {
// note: main purpose of next line is to test the empty/not-empty operators, since this col will have some empty-string values and some null values
doTestFilterOperator(commentColPropPath, new Criterion<String>(operator, "so so"), commentValueGetter, allData);
}
else if (operator.getOperatorClass() == OperatorClass.TEXT) {
doTestFilterOperator(textColPropPath, new Criterion<String>(operator, "text*"), ColextValueGetter, allData);
doTestFilterOperator(textColPropPath, new Criterion<String>(operator, "*100"), ColextValueGetter, allData);
doTestFilterOperator(textColPropPath, new Criterion<String>(operator, "*xt*"), ColextValueGetter, allData);
doTestFilterOperator(textColPropPath, new Criterion<String>(operator, "t*1"), ColextValueGetter, allData);
doTestFilterOperator(textColPropPath, new Criterion<String>(operator, "*"), ColextValueGetter, allData);
}
else {
fail("unhandled operator class: " + operator.getOperatorClass());
}
}
}
/**
* Tests that collection of elements can be eager fetched just like collection
* of entities. Thought this was a problem at one point, but isn't, but
* keeping test around anyway.
*/
public void testFetchCollectionOfElements()
{
_wellSetFetcher.setPropertiesToFetch(Lists.newArrayList(Well.latestReleasedReagent.to(SilencingReagent.facilityGenes).to(Gene.genbankAccessionNumbers),
Well.library.to(Library.contentsVersions).toFullEntity()));
List<Well> data = _wellSetFetcher.fetchAllData();
assertEquals("well.reagents.facilityGene.genbankAccessionNumbers size", 1, data.get(0).<SilencingReagent>getLatestReleasedReagent().getFacilityGene().getGenbankAccessionNumbers().size());
}
/**
* Tests that collection of elements can be filtered, using an empty string
* for PropertyPath.propertyName.
*/
public void testFilterCollectionOfElements()
{
PropertyPath<Well> propPath = Well.latestReleasedReagent.to(SilencingReagent.facilityGenes).to(Gene.genbankAccessionNumbers);
_wellSetFetcher.setPropertiesToFetch(Collections.singletonList(propPath));
Map<PropertyPath<Well>,List<? extends Criterion<?>>> filteringCriteria = new HashMap<PropertyPath<Well>,List<? extends Criterion<?>>>();
filteringCriteria.put(propPath, Collections.singletonList(new Criterion<String>(Operator.EQUAL, "GB3074279")));
_wellSetFetcher.setFilteringCriteria(filteringCriteria);
List<String> keys = _wellSetFetcher.findAllKeys();
assertEquals("result size", 1, keys.size());
assertEquals("filtered result", "02001:P24", keys.get(0));
}
public void testFetchEmptySet()
{
_wellSetFetcher = new EntityDataFetcher<Well,String>(Well.class, genericEntityDao) {
@Override
public void addDomainRestrictions(HqlBuilder hql)
{
DataFetcherUtil.addDomainRestrictions(hql, getRootAlias(), Collections.<String>emptySet());
}
};
List<String> keys = _wellSetFetcher.findAllKeys();
assertEquals("result size", 0, keys.size());
}
// private methods
private void doTestFilterOperator(PropertyPath<Well> propertyPath,
Criterion<?> criterion,
Getter<Well,?> getter,
List<Well> allData)
{
log.debug("testing criterion " + criterion + " against property " + propertyPath);
Set<String> expectedKeys = new HashSet<String>();
for (Well well : allData) {
if (criterion.matches(getter.get(well))) {
expectedKeys.add(well.getWellKey().toString());
}
}
log.debug("expected data size = " + expectedKeys.size());
Map<PropertyPath<Well>,List<? extends Criterion<?>>> criteria = new HashMap<PropertyPath<Well>,List<? extends Criterion<?>>>();
criteria.put(propertyPath, Collections.singletonList(criterion));
_allWellsFetcher.setFilteringCriteria(criteria);
Set<String> actualKeys = new HashSet<String>(_allWellsFetcher.findAllKeys());
assertEquals(expectedKeys, actualKeys);
}
@SuppressWarnings("unchecked")
private <T extends Comparable> void isSorted(List<T> data)
{
T last = null;
for (T item : data) {
if (last != null) {
assertTrue("sorted values", last.compareTo(item) <= 0);
}
last = item;
}
}
}