// BasicAccumuloOperations ops = new BasicAccumuloOperations(zookeeper, accumuloInstance, accumuloUser, accumuloPassword, "");
// ops.insureAuthorization(accumuloUser, "a","b","c");
package mil.nga.giat.geowave.test.basic;
import java.io.IOException;
import java.util.Arrays;
import org.geotools.feature.AttributeTypeBuilder;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import mil.nga.giat.geowave.adapter.vector.FeatureDataAdapter;
import mil.nga.giat.geowave.core.geotime.store.dimension.GeometryAdapter;
import mil.nga.giat.geowave.core.geotime.store.query.SpatialQuery;
import mil.nga.giat.geowave.core.index.ByteArrayId;
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.adapter.exceptions.MismatchedIndexToAdapterMapping;
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.DifferingFieldVisibilityEntryCount;
import mil.nga.giat.geowave.core.store.operations.remote.options.DataStorePluginOptions;
import mil.nga.giat.geowave.core.store.query.QueryOptions;
import mil.nga.giat.geowave.core.store.query.aggregate.CountAggregation;
import mil.nga.giat.geowave.core.store.query.aggregate.CountResult;
import mil.nga.giat.geowave.test.GeoWaveITRunner;
import mil.nga.giat.geowave.test.TestUtils;
import mil.nga.giat.geowave.test.annotation.GeoWaveTestStore;
import mil.nga.giat.geowave.test.annotation.GeoWaveTestStore.GeoWaveStoreType;
@RunWith(GeoWaveITRunner.class)
public class GeoWaveVisibilityIT
{
@GeoWaveTestStore({
GeoWaveStoreType.ACCUMULO,
GeoWaveStoreType.BIGTABLE,
GeoWaveStoreType.HBASE
})
protected DataStorePluginOptions dataStore;
// because there are 8 we want to make
// sure it is properly truncated
private static final int TOTAL_FEATURES = 800;
@Test
public void testIngestAndQueryMixedVisibilityFields()
throws MismatchedIndexToAdapterMapping,
IOException {
final SimpleFeatureBuilder bldr = new SimpleFeatureBuilder(
getType());
final FeatureDataAdapter adapter = new FeatureDataAdapter(
getType());
final DataStore store = dataStore.createDataStore();
try (IndexWriter writer = store.createWriter(
adapter,
TestUtils.DEFAULT_SPATIAL_INDEX)) {
for (int i = 0; i < TOTAL_FEATURES; i++) {
bldr.set(
"a",
Integer.toString(i));
bldr.set(
"b",
Integer.toString(i));
bldr.set(
"c",
Integer.toString(i));
bldr.set(
"geometry",
new GeometryFactory().createPoint(new Coordinate(
0,
0)));
writer.write(
bldr.buildFeature(Integer.toString(i)),
new VisibilityWriter<SimpleFeature>() {
@Override
public FieldVisibilityHandler<SimpleFeature, Object> getFieldVisibilityHandler(
final ByteArrayId fieldId ) {
return new FieldVisibilityHandler<SimpleFeature, Object>() {
@Override
public byte[] getVisibility(
final SimpleFeature rowValue,
final ByteArrayId fieldId,
final Object fieldValue ) {
final boolean isGeom = fieldId
.equals(GeometryAdapter.DEFAULT_GEOMETRY_FIELD_ID);
final int fieldValueInt;
if (isGeom) {
fieldValueInt = Integer.parseInt(rowValue.getID());
}
else {
fieldValueInt = Integer.parseInt(fieldValue.toString());
}
// just make half of them varied and
// half of them the same
if ((fieldValueInt % 2) == 0) {
if (isGeom) {
return new byte[] {};
}
return fieldId.getBytes();
}
else {
// of the ones that are the same,
// make some no bytes, some a, some
// b, and some c
final int switchValue = (fieldValueInt / 2) % 4;
switch (switchValue) {
case 0:
return new ByteArrayId(
"a").getBytes();
case 1:
return new ByteArrayId(
"b").getBytes();
case 2:
return new ByteArrayId(
"c").getBytes();
case 3:
default:
return new byte[] {};
}
}
}
};
}
});
}
}
final DifferingFieldVisibilityEntryCount differingVisibilities = (DifferingFieldVisibilityEntryCount) dataStore
.createDataStatisticsStore()
.getDataStatistics(
adapter.getAdapterId(),
DifferingFieldVisibilityEntryCount.composeId(TestUtils.DEFAULT_SPATIAL_INDEX.getId()));
Assert.assertEquals(
"Exactly half the entries should have differing visibility",
TOTAL_FEATURES / 2,
differingVisibilities.getEntriesWithDifferingFieldVisibilities());
testQuery(
store,
false);
testQuery(
store,
true);
}
private static void testQuery(
final DataStore store,
boolean spatial )
throws IOException {
// you have to at least be able to see the geometry field which is wide
// open for exactly (5 * total_Features / 8)
// for other fields there is exactly
testQuery(
store,
new String[] {},
spatial,
(5 * TOTAL_FEATURES) / 8,
((TOTAL_FEATURES / 8) * 4) + (TOTAL_FEATURES / 2));
for (String auth : new String[] {
"a",
"b",
"c"
}) {
testQuery(
store,
new String[] {
auth
},
spatial,
(6 * TOTAL_FEATURES) / 8,
((2 * TOTAL_FEATURES / 8) * 4) + (2 * TOTAL_FEATURES / 2));
}
// order shouldn't matter, but let's make sure here
for (String[] auths : new String[][] {
new String[] {
"a",
"b"
},
new String[] {
"b",
"a"
},
new String[] {
"a",
"c"
},
new String[] {
"c",
"a"
},
new String[] {
"b",
"c"
},
new String[] {
"c",
"b"
}
}) {
testQuery(
store,
auths,
spatial,
(7 * TOTAL_FEATURES) / 8,
((3 * TOTAL_FEATURES / 8) * 4) + (3 * TOTAL_FEATURES / 2));
}
testQuery(
store,
new String[] {
"a",
"b",
"c"
},
spatial,
TOTAL_FEATURES,
TOTAL_FEATURES * 4);
}
private static void testQuery(
final DataStore store,
final String[] auths,
final boolean spatial,
final int expectedResultCount,
final int expectedNonNullFieldCount )
throws IOException {
final QueryOptions queryOpts = new QueryOptions();
queryOpts.setAuthorizations(auths);
try (CloseableIterator<SimpleFeature> it = (CloseableIterator) store.query(
queryOpts,
spatial ? new SpatialQuery(
new GeometryFactory().toGeometry(new Envelope(
-1,
1,
-1,
1))) : null)) {
int resultCount = 0;
int nonNullFieldsCount = 0;
while (it.hasNext()) {
final SimpleFeature feature = it.next();
for (int a = 0; a < feature.getAttributeCount(); a++) {
if (feature.getAttribute(a) != null) {
nonNullFieldsCount++;
}
}
resultCount++;
}
Assert.assertEquals(
"Unexpected result count for " + (spatial ? "spatial query" : "full table scan") + " with auths "
+ Arrays.toString(auths),
expectedResultCount,
resultCount);
Assert.assertEquals(
"Unexpected non-null field count for " + (spatial ? "spatial query" : "full table scan")
+ " with auths " + Arrays.toString(auths),
expectedNonNullFieldCount,
nonNullFieldsCount);
}
queryOpts.setAggregation(
new CountAggregation(),
new FeatureDataAdapter(
getType()));
try (CloseableIterator<CountResult> it = (CloseableIterator) store.query(
queryOpts,
spatial ? new SpatialQuery(
new GeometryFactory().toGeometry(new Envelope(
-1,
1,
-1,
1))) : null)) {
CountResult result = it.next();
long count = 0;
if (result != null) {
count = result.getCount();
}
Assert.assertEquals(
"Unexpected aggregation result count for " + (spatial ? "spatial query" : "full table scan")
+ " with auths " + Arrays.toString(auths),
expectedResultCount,
count);
}
}
private static SimpleFeatureType getType() {
final SimpleFeatureTypeBuilder bldr = new SimpleFeatureTypeBuilder();
bldr.setName("testvis");
final AttributeTypeBuilder attributeTypeBuilder = new AttributeTypeBuilder();
bldr.add(attributeTypeBuilder.binding(
String.class).buildDescriptor(
"a"));
bldr.add(attributeTypeBuilder.binding(
String.class).buildDescriptor(
"b"));
bldr.add(attributeTypeBuilder.binding(
String.class).buildDescriptor(
"c"));
bldr.add(attributeTypeBuilder.binding(
Point.class).nillable(
false).buildDescriptor(
"geometry"));
return bldr.buildFeatureType();
}
}