package mil.nga.giat.geowave.core.store.memory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.junit.Test; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.index.NumericIndexStrategy; import mil.nga.giat.geowave.core.index.sfc.data.BasicNumericDataset; import mil.nga.giat.geowave.core.index.sfc.data.MultiDimensionalNumericData; import mil.nga.giat.geowave.core.index.sfc.data.NumericData; import mil.nga.giat.geowave.core.index.sfc.data.NumericRange; import mil.nga.giat.geowave.core.store.CloseableIterator; import mil.nga.giat.geowave.core.store.DataStore; import mil.nga.giat.geowave.core.store.IndexWriter; import mil.nga.giat.geowave.core.store.StoreFactoryFamilySpi; import mil.nga.giat.geowave.core.store.adapter.MockComponents; import mil.nga.giat.geowave.core.store.adapter.MockComponents.IntegerRangeDataStatistics; import mil.nga.giat.geowave.core.store.adapter.MockComponents.TestIndexModel; import mil.nga.giat.geowave.core.store.adapter.WritableDataAdapter; import mil.nga.giat.geowave.core.store.adapter.exceptions.MismatchedIndexToAdapterMapping; import mil.nga.giat.geowave.core.store.adapter.statistics.CountDataStatistics; import mil.nga.giat.geowave.core.store.adapter.statistics.DataStatistics; import mil.nga.giat.geowave.core.store.adapter.statistics.DataStatisticsStore; import mil.nga.giat.geowave.core.store.adapter.statistics.RowRangeDataStatistics; import mil.nga.giat.geowave.core.store.adapter.statistics.RowRangeHistogramStatistics; import mil.nga.giat.geowave.core.store.data.CommonIndexedPersistenceEncoding; import mil.nga.giat.geowave.core.store.data.IndexedPersistenceEncoding; import mil.nga.giat.geowave.core.store.data.VisibilityWriter; import mil.nga.giat.geowave.core.store.data.field.FieldVisibilityHandler; import mil.nga.giat.geowave.core.store.data.visibility.GlobalVisibilityHandler; import mil.nga.giat.geowave.core.store.filter.QueryFilter; import mil.nga.giat.geowave.core.store.index.CommonIndexModel; import mil.nga.giat.geowave.core.store.index.Index; import mil.nga.giat.geowave.core.store.index.PrimaryIndex; import mil.nga.giat.geowave.core.store.memory.MemoryRequiredOptions; import mil.nga.giat.geowave.core.store.memory.MemoryStoreFactoryFamily; import mil.nga.giat.geowave.core.store.query.DataIdQuery; import mil.nga.giat.geowave.core.store.query.Query; import mil.nga.giat.geowave.core.store.query.QueryOptions; public class MemoryDataStoreTest { @Test public void test() throws IOException, MismatchedIndexToAdapterMapping { final PrimaryIndex index = new PrimaryIndex( new MockComponents.MockIndexStrategy(), new MockComponents.TestIndexModel()); final String namespace = "test_" + getClass().getName(); final StoreFactoryFamilySpi storeFamily = new MemoryStoreFactoryFamily(); MemoryRequiredOptions reqOptions = new MemoryRequiredOptions(); reqOptions.setGeowaveNamespace(namespace); final DataStore dataStore = storeFamily.getDataStoreFactory().createStore( reqOptions); final DataStatisticsStore statsStore = storeFamily.getDataStatisticsStoreFactory().createStore( reqOptions); final WritableDataAdapter<Integer> adapter = new MockComponents.MockAbstractDataAdapter(); final VisibilityWriter<Integer> visWriter = new VisibilityWriter<Integer>() { @Override public FieldVisibilityHandler<Integer, Object> getFieldVisibilityHandler( ByteArrayId fieldId ) { return new GlobalVisibilityHandler( "aaa&bbb"); } }; try (final IndexWriter indexWriter = dataStore.createWriter( adapter, index)) { indexWriter.write( new Integer( 25), visWriter); indexWriter.flush(); indexWriter.write( new Integer( 35), visWriter); indexWriter.flush(); } // authorization check try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index, new String[] { "aaa" }), new TestQuery( 23, 26))) { assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index, new String[] { "aaa", "bbb" }), new TestQuery( 23, 26))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 25), itemIt.next()); assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index, new String[] { "aaa", "bbb" }), new TestQuery( 23, 36))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 25), itemIt.next()); assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); assertFalse(itemIt.hasNext()); } final Iterator<DataStatistics<?>> statsIt = statsStore.getAllDataStatistics(); assertTrue(checkStats( statsIt, 2, new NumericRange( 25, 35))); dataStore.delete( new QueryOptions( adapter, index, new String[] { "aaa", "bbb" }), new TestQuery( 23, 26)); try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index, new String[] { "aaa", "bbb" }), new TestQuery( 23, 36))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index, new String[] { "aaa", "bbb" }), new TestQuery( 23, 26))) { assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index, new String[] { "aaa", "bbb" }), new DataIdQuery( adapter.getAdapterId(), adapter.getDataId(new Integer( 35))))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); } } @Test public void testMultipleIndices() throws IOException, MismatchedIndexToAdapterMapping { final PrimaryIndex index1 = new PrimaryIndex( new MockComponents.MockIndexStrategy(), new MockComponents.TestIndexModel( "tm1")); final PrimaryIndex index2 = new PrimaryIndex( new MockComponents.MockIndexStrategy(), new MockComponents.TestIndexModel( "tm2")); final String namespace = "test2_" + getClass().getName(); final StoreFactoryFamilySpi storeFamily = new MemoryStoreFactoryFamily(); MemoryRequiredOptions opts = new MemoryRequiredOptions(); opts.setGeowaveNamespace(namespace); final DataStore dataStore = storeFamily.getDataStoreFactory().createStore( opts); final DataStatisticsStore statsStore = storeFamily.getDataStatisticsStoreFactory().createStore( opts); final WritableDataAdapter<Integer> adapter = new MockComponents.MockAbstractDataAdapter(); final VisibilityWriter<Integer> visWriter = new VisibilityWriter<Integer>() { @Override public FieldVisibilityHandler<Integer, Object> getFieldVisibilityHandler( ByteArrayId fieldId ) { return new GlobalVisibilityHandler( "aaa&bbb"); } }; try (final IndexWriter indexWriter = dataStore.createWriter( adapter, index1, index2)) { indexWriter.write( new Integer( 25), visWriter); indexWriter.flush(); indexWriter.write( new Integer( 35), visWriter); indexWriter.flush(); } // authorization check try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index2, new String[] { "aaa" }), new TestQuery( 23, 26))) { assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index1, new String[] { "aaa", "bbb" }), new TestQuery( 23, 26))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 25), itemIt.next()); assertFalse(itemIt.hasNext()); } // pick an index try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, new String[] { "aaa", "bbb" }), new TestQuery( 23, 36))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 25), itemIt.next()); assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); assertFalse(itemIt.hasNext()); } final Iterator<DataStatistics<?>> statsIt = statsStore.getAllDataStatistics(); assertTrue(checkStats( statsIt, 2, new NumericRange( 25, 35))); dataStore.delete( new QueryOptions( adapter, new String[] { "aaa", "bbb" }), new TestQuery( 23, 26)); try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index1, new String[] { "aaa", "bbb" }), new TestQuery( 23, 36))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index2, new String[] { "aaa", "bbb" }), new TestQuery( 23, 36))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index1, new String[] { "aaa", "bbb" }), new TestQuery( 23, 26))) { assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index2, new String[] { "aaa", "bbb" }), new TestQuery( 23, 26))) { assertFalse(itemIt.hasNext()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index1, new String[] { "aaa", "bbb" }), new DataIdQuery( adapter.getAdapterId(), adapter.getDataId(new Integer( 35))))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); } try (CloseableIterator<?> itemIt = dataStore.query( new QueryOptions( adapter, index2, new String[] { "aaa", "bbb" }), new DataIdQuery( adapter.getAdapterId(), adapter.getDataId(new Integer( 35))))) { assertTrue(itemIt.hasNext()); assertEquals( new Integer( 35), itemIt.next()); } } private boolean checkStats( final Iterator<DataStatistics<?>> statIt, final int count, final NumericRange range ) { while (statIt.hasNext()) { DataStatistics<Integer> stat = (DataStatistics<Integer>) statIt.next(); if (stat instanceof CountDataStatistics && ((CountDataStatistics) stat).getCount() != count) return false; else if (stat instanceof IntegerRangeDataStatistics && (((IntegerRangeDataStatistics) stat).getMin() != range.getMin() || ((IntegerRangeDataStatistics) stat) .getMax() != range.getMax())) return false; } return true; } private class TestQueryFilter implements QueryFilter { final CommonIndexModel indexModel; final double min, max; public TestQueryFilter( final CommonIndexModel indexModel, final double min, final double max ) { super(); this.indexModel = indexModel; this.min = min; this.max = max; } @Override public boolean accept( final CommonIndexModel indexModel, final IndexedPersistenceEncoding<?> persistenceEncoding ) { final double min = ((CommonIndexedPersistenceEncoding) persistenceEncoding).getNumericData( indexModel.getDimensions()).getDataPerDimension()[0].getMin(); final double max = ((CommonIndexedPersistenceEncoding) persistenceEncoding).getNumericData( indexModel.getDimensions()).getDataPerDimension()[0].getMax(); return !((this.max <= min) || (this.min > max)); } } private class TestQuery implements Query { final double min, max; public TestQuery( final double min, final double max ) { super(); this.min = min; this.max = max; } @Override public List<QueryFilter> createFilters( final CommonIndexModel indexModel ) { return Arrays.asList((QueryFilter) new TestQueryFilter( indexModel, min, max)); } @Override public boolean isSupported( final Index<?, ?> index ) { return ((PrimaryIndex) index).getIndexModel() instanceof TestIndexModel; } @Override public List<MultiDimensionalNumericData> getIndexConstraints( final NumericIndexStrategy indexStrategy ) { return Collections.<MultiDimensionalNumericData> singletonList(new BasicNumericDataset( new NumericData[] { new NumericRange( min, max) })); } } }