package mil.nga.giat.geowave.adapter.vector.plugin; import java.io.IOException; import java.util.Map; import org.geotools.data.FeatureReader; import org.geotools.data.FeatureWriter; import org.geotools.data.Query; import org.geotools.data.store.ContentEntry; import org.geotools.data.store.ContentFeatureStore; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.geometry.BoundingBox; import mil.nga.giat.geowave.adapter.vector.GeotoolsFeatureDataAdapter; import mil.nga.giat.geowave.adapter.vector.plugin.transaction.GeoWaveEmptyTransaction; import mil.nga.giat.geowave.adapter.vector.plugin.transaction.GeoWaveTransactionState; import mil.nga.giat.geowave.adapter.vector.plugin.transaction.TransactionsAllocator; import mil.nga.giat.geowave.adapter.vector.stats.FeatureBoundingBoxStatistics; import mil.nga.giat.geowave.core.geotime.store.statistics.BoundingBoxDataStatistics; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.store.adapter.statistics.CountDataStatistics; import mil.nga.giat.geowave.core.store.adapter.statistics.DataStatistics; @SuppressWarnings("unchecked") public class GeoWaveFeatureSource extends ContentFeatureStore { private final GeoWaveDataStoreComponents components; public GeoWaveFeatureSource( final ContentEntry entry, final Query query, final GeotoolsFeatureDataAdapter adapter, final TransactionsAllocator transactionAllocator ) { super( entry, query); components = new GeoWaveDataStoreComponents( getDataStore().getDataStore(), getDataStore().getDataStatisticsStore(), getDataStore().getIndexStore(), adapter, getDataStore(), transactionAllocator); } public GeoWaveDataStoreComponents getComponents() { return components; } @SuppressWarnings("rawtypes") @Override protected ReferencedEnvelope getBoundsInternal( final Query query ) throws IOException { double minx = -90.0, maxx = 90.0, miny = -180.0, maxy = 180.0; DataStatistics<SimpleFeature> bboxStats = null; if (query.getFilter().equals( Filter.INCLUDE)) { final Map<ByteArrayId, DataStatistics<SimpleFeature>> stats = new GeoWaveEmptyTransaction( components).getDataStatistics(); bboxStats = stats.get(FeatureBoundingBoxStatistics.composeId(getFeatureType() .getGeometryDescriptor() .getLocalName())); } if (bboxStats != null) { minx = ((BoundingBoxDataStatistics) bboxStats).getMinX(); maxx = ((BoundingBoxDataStatistics) bboxStats).getMaxX(); miny = ((BoundingBoxDataStatistics) bboxStats).getMinY(); maxy = ((BoundingBoxDataStatistics) bboxStats).getMaxY(); } else { final FeatureReader<SimpleFeatureType, SimpleFeature> reader = new GeoWaveFeatureReader( query, new GeoWaveEmptyTransaction( components), components); if (reader.hasNext()) { minx = 90.0; maxx = -90.0; miny = 180.0; maxy = -180.0; while (reader.hasNext()) { final BoundingBox bbox = reader.next().getBounds(); minx = Math.min( bbox.getMinX(), minx); maxx = Math.max( bbox.getMaxX(), maxx); miny = Math.min( bbox.getMinY(), miny); maxy = Math.max( bbox.getMaxY(), maxy); } } reader.close(); } return new ReferencedEnvelope( minx, maxx, miny, maxy, GeoWaveGTDataStore.DEFAULT_CRS); } @SuppressWarnings("rawtypes") @Override protected int getCountInternal( final Query query ) throws IOException { final Map<ByteArrayId, DataStatistics<SimpleFeature>> stats = new GeoWaveEmptyTransaction( components).getDataStatistics(); final DataStatistics<SimpleFeature> countStats = stats.get(CountDataStatistics.STATS_TYPE); if ((countStats != null) && query.getFilter().equals( Filter.INCLUDE)) { return (int) ((CountDataStatistics) countStats).getCount(); } else { try (GeoWaveFeatureReader reader = new GeoWaveFeatureReader( query, new GeoWaveEmptyTransaction( components), components)) { return (int) reader.getCount(); } } } public SimpleFeatureType getFeatureType() { return components.getAdapter().getFeatureType(); } @Override protected FeatureReader<SimpleFeatureType, SimpleFeature> getReaderInternal( final Query query ) throws IOException { final GeoWaveTransactionState state = getDataStore().getMyTransactionState( transaction, this); return new GeoWaveFeatureReader( query, state.getGeoWaveTransaction(query.getTypeName()), components); } @Override protected FeatureWriter<SimpleFeatureType, SimpleFeature> getWriterInternal( final Query query, final int flags ) throws IOException { final GeoWaveTransactionState state = getDataStore().getMyTransactionState( transaction, this); return new GeoWaveFeatureWriter( components, state.getGeoWaveTransaction(query.getTypeName()), (GeoWaveFeatureReader) getReaderInternal(query)); } @Override protected SimpleFeatureType buildFeatureType() throws IOException { return components.getAdapter().getFeatureType(); } @Override public GeoWaveGTDataStore getDataStore() { // type narrow this method to prevent a lot of casts resulting in more // readable code. return (GeoWaveGTDataStore) super.getDataStore(); } @Override protected boolean canTransact() { // tell GeoTools that we natively handle this return true; } @Override protected boolean canLock() { // tell GeoTools that we natively handle this return true; } @Override protected boolean canFilter() { return true; } @Override protected void doLockInternal( final String typeName, final SimpleFeature feature ) throws IOException { getDataStore().getLockingManager().lockFeatureID( typeName, feature.getID(), transaction, lock); } @Override protected void doUnlockInternal( final String typeName, final SimpleFeature feature ) throws IOException { getDataStore().getLockingManager().unLockFeatureID( typeName, feature.getID(), transaction, lock); } }