package mil.nga.giat.geowave.examples.query; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; import org.apache.accumulo.minicluster.impl.MiniAccumuloClusterImpl; import org.apache.accumulo.minicluster.impl.MiniAccumuloConfigImpl; import org.apache.commons.io.FileUtils; import org.geotools.feature.AttributeTypeBuilder; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.filter.text.cql2.CQLException; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import com.google.common.io.Files; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import mil.nga.giat.geowave.adapter.vector.FeatureDataAdapter; import mil.nga.giat.geowave.adapter.vector.index.TextSecondaryIndexConfiguration; import mil.nga.giat.geowave.adapter.vector.query.cql.CQLQuery; import mil.nga.giat.geowave.core.geotime.GeometryUtils; import mil.nga.giat.geowave.core.geotime.ingest.SpatialDimensionalityTypeProvider; 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.index.PrimaryIndex; import mil.nga.giat.geowave.core.store.query.QueryOptions; import mil.nga.giat.geowave.core.store.util.DataStoreUtils; import mil.nga.giat.geowave.datastore.accumulo.AccumuloDataStore; import mil.nga.giat.geowave.datastore.accumulo.BasicAccumuloOperations; import mil.nga.giat.geowave.datastore.accumulo.minicluster.MiniAccumuloClusterFactory; /** * This class is intended to provide a self-contained, easy-to-follow example of * a few GeoTools queries against GeoWave. For simplicity, a MiniAccumuloCluster * is spun up and a few points from the DC area are ingested (Washington * Monument, White House, FedEx Field). Two queries are executed against this * data set. */ public class CQLQueryExample { private static File tempAccumuloDir; private static MiniAccumuloClusterImpl accumulo; private static DataStore dataStore; private static final PrimaryIndex index = new SpatialDimensionalityTypeProvider().createPrimaryIndex(); // Points (to be ingested into GeoWave Data Store) private static final Coordinate washingtonMonument = new Coordinate( -77.0352, 38.8895); private static final Coordinate whiteHouse = new Coordinate( -77.0366, 38.8977); private static final Coordinate fedexField = new Coordinate( -76.8644, 38.9078); private static final Coordinate bayBridgeAirport = new Coordinate( -76.350677, 38.9641511); private static final Coordinate wideWater = new Coordinate( -77.3384112, 38.416091); private static final Map<String, Coordinate> cannedData = new HashMap<>(); static { cannedData.put( "Washington Monument", washingtonMonument); cannedData.put( "White House", whiteHouse); cannedData.put( "FedEx Field", fedexField); cannedData.put( "Bay Bridge Airport", bayBridgeAirport); cannedData.put( "Wide Water Beach", wideWater); } final static FeatureDataAdapter ADAPTER = new FeatureDataAdapter( getPointSimpleFeatureType()); public static void main( final String[] args ) throws AccumuloException, AccumuloSecurityException, InterruptedException, IOException, CQLException { // spin up a MiniAccumuloCluster and initialize the DataStore setup(); // ingest 3 points represented as SimpleFeatures: Washington Monument, // White House, FedEx Field ingestCannedData(); // execute a query for a bounding box executeCQLuery(); // stop MiniAccumuloCluster and delete temporary files cleanup(); } private static void executeCQLuery() throws IOException, CQLException { System.out.println("Executing query, expecting to match two points..."); try (final CloseableIterator<SimpleFeature> iterator = dataStore.query( new QueryOptions( ADAPTER, index), CQLQuery.createOptimalQuery( "BBOX(geometry,-77.6167,38.6833,-76.6,38.9200) and locationName like 'W%'", ADAPTER, index))) { while (iterator.hasNext()) { System.out.println("Query match: " + iterator.next().getID()); } } } private static void setup() throws AccumuloException, AccumuloSecurityException, IOException, InterruptedException { final String ACCUMULO_USER = "root"; final String ACCUMULO_PASSWORD = "Ge0wave"; final String TABLE_NAMESPACE = ""; tempAccumuloDir = Files.createTempDir(); accumulo = MiniAccumuloClusterFactory.newAccumuloCluster( new MiniAccumuloConfigImpl( tempAccumuloDir, ACCUMULO_PASSWORD), CQLQueryExample.class); accumulo.start(); dataStore = new AccumuloDataStore( new BasicAccumuloOperations( accumulo.getZooKeepers(), accumulo.getInstanceName(), ACCUMULO_USER, ACCUMULO_PASSWORD, TABLE_NAMESPACE)); } private static void ingestCannedData() throws IOException { final List<SimpleFeature> points = new ArrayList<>(); System.out.println("Building SimpleFeatures from canned data set..."); for (final Entry<String, Coordinate> entry : cannedData.entrySet()) { System.out.println("Added point: " + entry.getKey()); points.add(buildSimpleFeature( entry.getKey(), entry.getValue())); } System.out.println("Ingesting canned data..."); try (IndexWriter indexWriter = dataStore.createWriter( ADAPTER, index)) { for (final SimpleFeature sf : points) { // indexWriter.write(sf); } } System.out.println("Ingest complete."); } private static void cleanup() throws IOException, InterruptedException { try { accumulo.stop(); } finally { FileUtils.deleteDirectory(tempAccumuloDir); } } private static SimpleFeatureType getPointSimpleFeatureType() { final String NAME = "PointSimpleFeatureType"; final SimpleFeatureTypeBuilder sftBuilder = new SimpleFeatureTypeBuilder(); final AttributeTypeBuilder atBuilder = new AttributeTypeBuilder(); sftBuilder.setName(NAME); sftBuilder.add(atBuilder.binding( String.class).nillable( false).buildDescriptor( "locationName")); sftBuilder.add(atBuilder.binding( Geometry.class).nillable( false).buildDescriptor( "geometry")); // TURN ON SECONDARY INDEXING final SimpleFeatureType type = sftBuilder.buildFeatureType(); type.getDescriptor( "locationName").getUserData().put( TextSecondaryIndexConfiguration.INDEX_KEY, "FULL"); return type; } private static SimpleFeature buildSimpleFeature( final String locationName, final Coordinate coordinate ) { final SimpleFeatureBuilder builder = new SimpleFeatureBuilder( getPointSimpleFeatureType()); builder.set( "locationName", locationName); builder.set( "geometry", GeometryUtils.GEOMETRY_FACTORY.createPoint(coordinate)); return builder.buildFeature(locationName); } }