package org.hivedb.hibernate.simplified;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.shards.strategy.access.SequentialShardAccessStrategy;
import org.hivedb.Lockable;
import org.hivedb.hibernate.simplified.session.HiveSessionFactory;
import org.hivedb.hibernate.simplified.session.SingletonHiveSessionFactoryBuilder;
import org.hivedb.util.Lists;
import org.hivedb.util.classgen.ReflectionTools;
import org.hivedb.util.database.test.*;
import org.hivedb.util.functional.Filter;
import static org.junit.Assert.*;
import org.junit.Test;
import java.util.Collection;
import java.util.List;
@HiveTest.Config("hive_default")
public class ErrorCorrectingDataAccessObjectRetrievalTest extends HiveTest {
private final static Log log = LogFactory.getLog(ErrorCorrectingDataAccessObjectRetrievalTest.class);
private HiveSessionFactory hiveSessionFactory;
@Test
public void shouldRetrieveAnExistingEntity() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
WeatherReport original = getPersistentInstance(dao);
WeatherReport report = dao.get(original.getReportId());
assertEquals(ReflectionTools.getDifferingFields(original, report, WeatherReport.class).toString(), original.hashCode(), report.hashCode());
}
@Test
public void shouldDetectChangesInPrimaryIndexKey() throws Exception {
ErrorCorrectingDataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
WeatherReport original = getPersistentInstance(dao);
assertFalse(dao.hasPartitionDimensionKeyChanged(original));
String newContinent = original.getContinent().equals("Asia") ? "Australia" : "Asia";
hive.directory().insertPrimaryIndexKey(newContinent);
hive.directory().updatePrimaryIndexKeyOfResourceId("WeatherReport", original.getReportId(), newContinent);
assertTrue(dao.hasPartitionDimensionKeyChanged(original));
}
@Test
public void shouldIndicateThatThePartitionKeyHasNotChangedForUnsaveRecords() throws Exception {
ErrorCorrectingDataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
WeatherReport original = WeatherReportImpl.generate();
assertFalse(dao.hasPartitionDimensionKeyChanged(original));
}
@Test
public void shouldDeleteTheDirectoryEntryIfTheEntityIsNotPresentOnTheDataNode() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
WeatherReport original = getPersistentInstance(dao);
dao.delete(original.getReportId());
String resourceName = getEntityHiveConfig().getEntityConfig(WeatherReport.class).getResourceName();
getHive().directory().insertResourceId(resourceName, original.getReportId(), original.getContinent());
assertTrue(getHive().directory().doesResourceIdExist(resourceName, original.getReportId()));
WeatherReport report = dao.get(original.getReportId());
assertTrue(report == null);
assertFalse(getHive().directory().doesResourceIdExist(resourceName, original.getReportId()));
}
@Test
public void shouldReturnNullIfTheRecordDoesNotExist() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
WeatherReport report = dao.get(777777);
assertTrue(report == null);
}
@Test
public void shouldReturnNullIfTheRecordExistsButHasNoDirectoryEntry() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
WeatherReport original = getPersistentInstance(dao);
String resourceName = getEntityHiveConfig().getEntityConfig(WeatherReport.class).getResourceName();
getHive().directory().deleteResourceId(resourceName, original.getReportId());
assertFalse(dao.exists(original.getReportId()));
WeatherReport report = dao.get(original.getReportId());
assertTrue(report == null);
}
@Test
public void shouldOnlyWarnIfTheHiveIsLockedForWrites() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
WeatherReport original = getPersistentInstance(dao);
dao.delete(original.getReportId());
String resourceName = getEntityHiveConfig().getEntityConfig(WeatherReport.class).getResourceName();
getHive().directory().insertResourceId(resourceName, original.getReportId(), original.getContinent());
assertTrue(getHive().directory().doesResourceIdExist(resourceName, original.getReportId()));
getHive().updateHiveStatus(Lockable.Status.readOnly);
WeatherReport report = dao.get(original.getReportId());
assertTrue(report == null);
assertTrue(getHive().directory().doesResourceIdExist(resourceName, original.getReportId()));
}
@Test
public void shouldFindAllItemsInAPropertyRange() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
report.setRegionCode(i);
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Collection<WeatherReport> reports = dao.findInRange("regionCode",2,5);
assertEquals(4,Filter.grepUnique(reports).size());
for(WeatherReport report : reports) {
assertTrue(report.getRegionCode() >= 2);
assertTrue(report.getRegionCode() <= 5);
}
}
@Test
public void shouldFindByRangeWithAssociatedObjectCollectionss() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
WeatherEvent event = WeatherEventImpl.generate();
event.setEventId(i);
report.setWeatherEvents(Lists.newList(event));
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Collection<WeatherReport> reports = dao.findInRange("weatherEvents",2,5);
assertEquals(4,Filter.grepUnique(reports).size());
}
@Test
public void shouldFindByRangeWithAssociatedObjects() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
report.setTemperature(i);
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Collection<WeatherReport> reports = dao.findInRange("temperature",2,5);
assertEquals(4,Filter.grepUnique(reports).size());
}
@Test
public void shouldReturnAnEmptyListIfFindByRangeReturnsNoResults() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
Collection<WeatherReport> reports = dao.findInRange("regionCode",2,5);
assertEquals(0,Filter.grepUnique(reports).size());
}
@Test
public void shouldThrowIfFindByRangeIsCalledOnAnUnindexedProperty() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
try {
dao.findInRange("longitude",2,5);
fail("No exception thrown");
} catch (UnsupportedOperationException o ) {
//pass
}
}
@Test
public void shouldCountResultsInARange() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
report.setRegionCode(i);
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Integer count = dao.getCountInRange("regionCode",2,5);
assertEquals(new Integer(4),count);
}
@Test
public void shouldReturnZeroIfNoRecordsExist() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
report.setRegionCode(i);
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Integer count = dao.getCountInRange("regionCode",22,55);
assertEquals(new Integer(0),count);
}
@Test
public void shouldCountPropertiesThatAreAssociatedObjects() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
report.setTemperature(i);
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Integer count = dao.getCountInRange("temperature",2,5);
assertEquals(new Integer(4), count);
}
@Test
public void shouldCountPropertiesThatAreAssociatedCollections() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
WeatherEvent event = WeatherEventImpl.generate();
event.setEventId(i);
report.setWeatherEvents(Lists.newList(event));
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Integer count = dao.getCountInRange("weatherEvents",2,5);
assertEquals(new Integer(4), count);
}
@Test
public void shouldFindAllItemsInAPropertyRangePage() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
report.setRegionCode(i);
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Collection<WeatherReport> page1 = dao.findInRange("regionCode",2,5,0,2);
Collection<WeatherReport> page2 = dao.findInRange("regionCode",2,5,2,2);
assertEquals(2,Filter.grepUnique(page1).size());
assertEquals(2,Filter.grepUnique(page2).size());
for(WeatherReport report : page2) {
assertFalse(page1.contains(report));
}
}
@Test
public void shouldFindByRangePagedWithAssociatedObjectCollections() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
WeatherEvent event = WeatherEventImpl.generate();
event.setEventId(i);
report.setWeatherEvents(Lists.newList(event));
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Collection<WeatherReport> reports = dao.findInRange("weatherEvents",2,5,0,2);
assertEquals(2,Filter.grepUnique(reports).size());
}
@Test
public void shouldFindByRangePagedWithAssociatedObjects() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
for(int i=0; i<10; i++) {
WeatherReport report = WeatherReportImpl.generate();
report.setTemperature(i);
dao.save(report);
assertTrue(dao.exists(report.getReportId()));
}
Collection<WeatherReport> reports = dao.findInRange("temperature",2,5,2,2);
assertEquals(2,Filter.grepUnique(reports).size());
}
@Test
public void shouldReturnAnEmptyListIfFindByRangePagedReturnsNoResults() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
Collection<WeatherReport> reports = dao.findInRange("regionCode",2,5,1,1);
assertEquals(0,Filter.grepUnique(reports).size());
}
@Test
public void shouldThrowIfFindByRangePagedIsCalledOnAnUnindexedProperty() throws Exception {
DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
try {
dao.findInRange("longitude",2,5,1,4);
fail("No exception thrown");
} catch (UnsupportedOperationException o ) {
//pass
}
}
// @Test
// public void shouldPerformCriteriaQueries() throws Exception {
// DataAccessObject<WeatherReport, Integer> dao = new ErrorCorrectingDataAccessObject<WeatherReport, Integer>(WeatherReport.class, getEntityHiveConfig().getEntityConfig(WeatherReport.class),getHive(), getSessionFactory());
// for(int i=0; i<10; i++) {
// WeatherReport report = WeatherReportImpl.generate();
// WeatherEvent event = WeatherEventImpl.generate();
// event.setEventId(i);
// report.setWeatherEvents(Lists.newList(event));
// report.setRegionCode(i);
// report.setSources(Lists.newList(i,i,i));
// dao.save(report);
// assertTrue(dao.exists(report.getReportId()));
// }
// Session session = hiveSessionFactory.openSession();
// Criteria regionCodeSearch = session.createCriteria(WeatherReport.class).add(Restrictions.between("regionCode", 2, 5));
// assertEquals(4,regionCodeSearch.list().size());
// Criteria eventSearch = session.createCriteria(WeatherReport.class).createCriteria("weatherEvents").add(Restrictions.between("eventId",2,5));
// assertEquals(4,eventSearch.list().size());
//
// session.close();
// }
private HiveSessionFactory getSessionFactory() {
if(hiveSessionFactory==null)
hiveSessionFactory = new SingletonHiveSessionFactoryBuilder(getHive(), (List<Class<?>>) getMappedClasses(),new SequentialShardAccessStrategy()).getSessionFactory();
return hiveSessionFactory;
}
private WeatherReport getPersistentInstance(DataAccessObject<WeatherReport, Integer> dao) {
return dao.save(WeatherReportImpl.generate());
}
}