package mil.nga.giat.geowave.adapter.vector.plugin;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.text.ParseException;
import java.util.UUID;
import org.geotools.data.DataStore;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FeatureWriter;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;
import org.geotools.filter.text.cql2.CQL;
import org.geotools.filter.text.cql2.CQLException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.junit.Test;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import mil.nga.giat.geowave.adapter.vector.BaseDataStoreTest;
import mil.nga.giat.geowave.adapter.vector.stats.FeatureNumericRangeStatistics;
import mil.nga.giat.geowave.adapter.vector.stats.FeatureTimeRangeStatistics;
import mil.nga.giat.geowave.adapter.vector.utils.DateUtilities;
import mil.nga.giat.geowave.core.geotime.store.statistics.BoundingBoxDataStatistics;
import mil.nga.giat.geowave.core.index.ByteArrayId;
import mil.nga.giat.geowave.core.index.StringUtils;
import mil.nga.giat.geowave.core.store.CloseableIterator;
import mil.nga.giat.geowave.core.store.adapter.statistics.CountDataStatistics;
import mil.nga.giat.geowave.core.store.adapter.statistics.DataStatistics;
public class GeoWaveFeatureSourceTest extends
BaseDataStoreTest
{
static final GeometryFactory factory = new GeometryFactory(
new PrecisionModel(
PrecisionModel.FIXED));
@Test
public void test()
throws Exception {
testEmpty();
testFull(
new FWPopulater(),
"fw");
testPartial(
new FWPopulater(),
"fw");
// test different populate methods
testFull(
new SourcePopulater(),
"s");
testPartial(
new SourcePopulater(),
"s");
}
public void testEmpty()
throws Exception {
final SimpleFeatureType type = DataUtilities.createType(
"GeoWaveFeatureSourceTest_e",
"geometry:Geometry:srid=4326,pop:java.lang.Long,pid:String,when:Date");
final DataStore dataStore = createDataStore();
dataStore.createSchema(type);
final SimpleFeatureSource source = dataStore.getFeatureSource("GeoWaveFeatureSourceTest_e");
final ReferencedEnvelope env = source.getBounds();
assertEquals(
90.0,
env.getMaxX(),
0.0001);
assertEquals(
-180.0,
env.getMinY(),
0.0001);
final Query query = new Query(
"GeoWaveFeatureSourceTest_e",
Filter.INCLUDE);
assertEquals(
0,
source.getCount(query));
}
public void testFull(
Populater populater,
String ext )
throws Exception {
final String typeName = "GeoWaveFeatureSourceTest_full" + ext;
final SimpleFeatureType type = DataUtilities.createType(
typeName,
"geometry:Geometry:srid=4326,pop:java.lang.Long,pid:String,when:Date");
final DataStore dataStore = createDataStore();
populater.populate(
type,
dataStore);
final SimpleFeatureSource source = dataStore.getFeatureSource(typeName);
final ReferencedEnvelope env = source.getBounds();
assertEquals(
43.454,
env.getMaxX(),
0.0001);
assertEquals(
27.232,
env.getMinY(),
0.0001);
assertEquals(
28.242,
env.getMaxY(),
0.0001);
final Query query = new Query(
typeName,
Filter.INCLUDE);
assertTrue(source.getCount(query) > 2);
try (final CloseableIterator<DataStatistics<?>> stats = ((GeoWaveGTDataStore) dataStore)
.getDataStatisticsStore()
.getDataStatistics(
new ByteArrayId(
(typeName).getBytes(StringUtils.GEOWAVE_CHAR_SET)))) {
assertTrue(stats.hasNext());
int count = 0;
BoundingBoxDataStatistics<SimpleFeature> bboxStats = null;
CountDataStatistics<SimpleFeature> cStats = null;
FeatureTimeRangeStatistics timeRangeStats = null;
FeatureNumericRangeStatistics popStats = null;
while (stats.hasNext()) {
final DataStatistics<?> statsData = stats.next();
System.out.println(statsData.toString());
if (statsData instanceof BoundingBoxDataStatistics) {
bboxStats = (BoundingBoxDataStatistics<SimpleFeature>) statsData;
}
else if (statsData instanceof CountDataStatistics) {
cStats = (CountDataStatistics<SimpleFeature>) statsData;
}
else if (statsData instanceof FeatureTimeRangeStatistics) {
timeRangeStats = (FeatureTimeRangeStatistics) statsData;
}
else if (statsData instanceof FeatureNumericRangeStatistics) {
popStats = (FeatureNumericRangeStatistics) statsData;
}
count++;
}
// rather than maintain an exact count on stats as we should be able
// to add them more dynamically, just make sure that there is some
// set of base stats found
assertTrue(
"Unexpectedly few stats found",
count > 5);
assertEquals(
66,
popStats.getMin(),
0.001);
assertEquals(
100,
popStats.getMax(),
0.001);
assertEquals(
DateUtilities.parseISO("2005-05-17T20:32:56Z"),
timeRangeStats.asTemporalRange().getStartTime());
assertEquals(
DateUtilities.parseISO("2005-05-19T20:32:56Z"),
timeRangeStats.asTemporalRange().getEndTime());
assertEquals(
43.454,
bboxStats.getMaxX(),
0.0001);
assertEquals(
27.232,
bboxStats.getMinY(),
0.0001);
assertEquals(
3,
cStats.getCount());
}
}
public void testPartial(
Populater populater,
String ext )
throws CQLException,
Exception {
final String typeName = "GeoWaveFeatureSourceTest_p" + ext;
final SimpleFeatureType type = DataUtilities.createType(
typeName,
"geometry:Geometry:srid=4326,pop:java.lang.Long,pid:String,when:Date");
final DataStore dataStore = createDataStore();
populater.populate(
type,
dataStore);
final SimpleFeatureSource source = dataStore.getFeatureSource(typeName);
final Query query = new Query(
typeName,
CQL.toFilter("BBOX(geometry,42,28,44,30) and when during 2005-05-01T20:32:56Z/2005-05-29T21:32:56Z"),
new String[] {
"geometry",
"pid"
});
final ReferencedEnvelope env = source.getBounds(query);
assertEquals(
43.454,
env.getMaxX(),
0.0001);
assertEquals(
28.232,
env.getMinY(),
0.0001);
assertEquals(
28.242,
env.getMaxY(),
0.0001);
assertEquals(
2,
source.getCount(query));
}
public interface Populater
{
void populate(
final SimpleFeatureType type,
final DataStore dataStore )
throws IOException,
CQLException,
ParseException;
}
private static class FWPopulater implements
Populater
{
public void populate(
final SimpleFeatureType type,
final DataStore dataStore )
throws IOException,
CQLException,
ParseException {
dataStore.createSchema(type);
final Transaction transaction1 = new DefaultTransaction();
final FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriter(
type.getTypeName(),
transaction1);
assertFalse(writer.hasNext());
SimpleFeature newFeature = writer.next();
newFeature.setAttribute(
"pop",
Long.valueOf(77));
newFeature.setAttribute(
"pid",
UUID.randomUUID().toString());
newFeature.setAttribute(
"when",
DateUtilities.parseISO("2005-05-19T20:32:56Z"));
newFeature.setAttribute(
"geometry",
factory.createPoint(new Coordinate(
43.454,
28.232)));
writer.write();
newFeature = writer.next();
newFeature.setAttribute(
"pop",
Long.valueOf(66));
newFeature.setAttribute(
"pid",
UUID.randomUUID().toString());
newFeature.setAttribute(
"when",
DateUtilities.parseISO("2005-05-18T20:32:56Z"));
newFeature.setAttribute(
"geometry",
factory.createPoint(new Coordinate(
43.454,
27.232)));
writer.write();
newFeature = writer.next();
newFeature.setAttribute(
"pop",
Long.valueOf(100));
newFeature.setAttribute(
"pid",
UUID.randomUUID().toString());
newFeature.setAttribute(
"when",
DateUtilities.parseISO("2005-05-17T20:32:56Z"));
newFeature.setAttribute(
"geometry",
factory.createPoint(new Coordinate(
43.454,
28.242)));
writer.write();
writer.close();
transaction1.commit();
transaction1.close();
}
}
private static class SourcePopulater implements
Populater
{
public void populate(
final SimpleFeatureType type,
final DataStore dataStore )
throws IOException,
CQLException,
ParseException {
dataStore.createSchema(type);
final Transaction transaction1 = new DefaultTransaction();
SimpleFeatureStore source = (SimpleFeatureStore) dataStore.getFeatureSource(type.getName());
final FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriter(
type.getTypeName(),
transaction1);
assertFalse(writer.hasNext());
SimpleFeature newFeature = writer.next();
newFeature.setAttribute(
"pop",
Long.valueOf(77));
newFeature.setAttribute(
"pid",
UUID.randomUUID().toString());
newFeature.setAttribute(
"when",
DateUtilities.parseISO("2005-05-19T20:32:56Z"));
newFeature.setAttribute(
"geometry",
factory.createPoint(new Coordinate(
43.454,
28.232)));
source.addFeatures(DataUtilities.collection(newFeature));
newFeature = writer.next();
newFeature.setAttribute(
"pop",
Long.valueOf(66));
newFeature.setAttribute(
"pid",
UUID.randomUUID().toString());
newFeature.setAttribute(
"when",
DateUtilities.parseISO("2005-05-18T20:32:56Z"));
newFeature.setAttribute(
"geometry",
factory.createPoint(new Coordinate(
43.454,
27.232)));
source.addFeatures(DataUtilities.collection(newFeature));
newFeature = writer.next();
newFeature.setAttribute(
"pop",
Long.valueOf(100));
newFeature.setAttribute(
"pid",
UUID.randomUUID().toString());
newFeature.setAttribute(
"when",
DateUtilities.parseISO("2005-05-17T20:32:56Z"));
newFeature.setAttribute(
"geometry",
factory.createPoint(new Coordinate(
43.454,
28.242)));
source.addFeatures(DataUtilities.collection(newFeature));
transaction1.commit();
transaction1.close();
}
}
}