package mil.nga.giat.geowave.adapter.vector.export;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.avro.file.CodecFactory;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.generic.GenericDatumWriter;
import org.geotools.filter.text.cql2.CQLException;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.beust.jcommander.ParametersDelegate;
import mil.nga.giat.geowave.adapter.vector.AvroFeatureUtils;
import mil.nga.giat.geowave.adapter.vector.GeotoolsFeatureDataAdapter;
import mil.nga.giat.geowave.adapter.vector.avro.AttributeValues;
import mil.nga.giat.geowave.adapter.vector.avro.AvroSimpleFeatureCollection;
import mil.nga.giat.geowave.adapter.vector.cli.VectorSection;
import mil.nga.giat.geowave.adapter.vector.query.cql.CQLQuery;
import mil.nga.giat.geowave.core.cli.annotations.GeowaveOperation;
import mil.nga.giat.geowave.core.cli.api.Command;
import mil.nga.giat.geowave.core.cli.api.DefaultOperation;
import mil.nga.giat.geowave.core.cli.api.OperationParams;
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.adapter.AdapterStore;
import mil.nga.giat.geowave.core.store.adapter.DataAdapter;
import mil.nga.giat.geowave.core.store.index.Index;
import mil.nga.giat.geowave.core.store.index.IndexStore;
import mil.nga.giat.geowave.core.store.index.PrimaryIndex;
import mil.nga.giat.geowave.core.store.operations.remote.options.DataStorePluginOptions;
import mil.nga.giat.geowave.core.store.operations.remote.options.StoreLoader;
import mil.nga.giat.geowave.core.store.query.Query;
import mil.nga.giat.geowave.core.store.query.QueryOptions;
@GeowaveOperation(name = "localexport", parentOperation = VectorSection.class)
@Parameters(commandDescription = "Export data directly")
public class VectorLocalExportCommand extends
DefaultOperation implements
Command
{
@Parameter(description = "<store name>")
private List<String> parameters = new ArrayList<String>();
@ParametersDelegate
private VectorLocalExportOptions options = new VectorLocalExportOptions();
private DataStorePluginOptions inputStoreOptions = null;
public void execute(
OperationParams params )
throws IOException,
CQLException {
// Ensure we have all the required arguments
if (parameters.size() != 1) {
throw new ParameterException(
"Requires arguments: <store name>");
}
String storeName = parameters.get(0);
// Config file
File configFile = getGeoWaveConfigFile(params);
// Attempt to load input store.
if (inputStoreOptions == null) {
StoreLoader inputStoreLoader = new StoreLoader(
storeName);
if (!inputStoreLoader.loadFromConfig(configFile)) {
throw new ParameterException(
"Cannot find store name: " + inputStoreLoader.getStoreName());
}
inputStoreOptions = inputStoreLoader.getDataStorePlugin();
}
AdapterStore adapterStore = inputStoreOptions.createAdapterStore();
IndexStore indexStore = inputStoreOptions.createIndexStore();
DataStore dataStore = inputStoreOptions.createDataStore();
try (final DataFileWriter<AvroSimpleFeatureCollection> dfw = new DataFileWriter<AvroSimpleFeatureCollection>(
new GenericDatumWriter<AvroSimpleFeatureCollection>(
AvroSimpleFeatureCollection.SCHEMA$))) {
dfw.setCodec(CodecFactory.snappyCodec());
dfw.create(
AvroSimpleFeatureCollection.SCHEMA$,
options.getOutputFile());
// get appropriate feature adapters
final List<GeotoolsFeatureDataAdapter> featureAdapters = new ArrayList<GeotoolsFeatureDataAdapter>();
if ((options.getAdapterIds() != null) && !options.getAdapterIds().isEmpty()) {
for (final String adapterId : options.getAdapterIds()) {
final DataAdapter<?> adapter = adapterStore.getAdapter(new ByteArrayId(
adapterId));
if (adapter == null) {
JCommander.getConsole().println(
"Type '" + adapterId + "' not found");
continue;
}
else if (!(adapter instanceof GeotoolsFeatureDataAdapter)) {
JCommander.getConsole().println(
"Type '" + adapterId + "' does not support vector export. Instance of "
+ adapter.getClass());
continue;
}
featureAdapters.add((GeotoolsFeatureDataAdapter) adapter);
}
}
else {
final CloseableIterator<DataAdapter<?>> adapters = adapterStore.getAdapters();
while (adapters.hasNext()) {
final DataAdapter<?> adapter = adapters.next();
if (adapter instanceof GeotoolsFeatureDataAdapter) {
featureAdapters.add((GeotoolsFeatureDataAdapter) adapter);
}
}
adapters.close();
}
if (featureAdapters.isEmpty()) {
JCommander.getConsole().println(
"Unable to find any vector data types in store");
}
PrimaryIndex queryIndex = null;
if (options.getIndexId() != null) {
final Index index = indexStore.getIndex(new ByteArrayId(
options.getIndexId()));
if (index == null) {
JCommander.getConsole().println(
"Unable to find index '" + options.getIndexId() + "' in store");
return;
}
if (index instanceof PrimaryIndex) {
queryIndex = (PrimaryIndex) index;
}
else {
JCommander.getConsole().println(
"Index '" + options.getIndexId() + "' is not a primary index");
return;
}
}
for (final GeotoolsFeatureDataAdapter adapter : featureAdapters) {
final SimpleFeatureType sft = adapter.getFeatureType();
JCommander.getConsole().println(
"Exporting type '" + sft.getTypeName() + "'");
final QueryOptions queryOptions = new QueryOptions();
if (queryIndex != null) {
queryOptions.setIndex(queryIndex);
}
Query queryConstraints = null;
if (options.getCqlFilter() != null) {
queryConstraints = CQLQuery.createOptimalQuery(
options.getCqlFilter(),
adapter,
queryIndex,
null);
}
queryOptions.setAdapter(adapter);
final CloseableIterator<Object> it = dataStore.query(
queryOptions,
queryConstraints);
int iteration = 0;
while (it.hasNext()) {
final AvroSimpleFeatureCollection simpleFeatureCollection = new AvroSimpleFeatureCollection();
simpleFeatureCollection.setFeatureType(AvroFeatureUtils.buildFeatureDefinition(
null,
sft,
null,
""));
final List<AttributeValues> avList = new ArrayList<AttributeValues>(
options.getBatchSize());
while (it.hasNext() && (avList.size() < options.getBatchSize())) {
final Object obj = it.next();
if (obj instanceof SimpleFeature) {
final AttributeValues av = AvroFeatureUtils.buildAttributeValue(
(SimpleFeature) obj,
sft);
avList.add(av);
}
}
JCommander.getConsole().println(
"Exported " + (avList.size() + (iteration * options.getBatchSize())) + " features from '"
+ sft.getTypeName() + "'");
iteration++;
simpleFeatureCollection.setSimpleFeatureCollection(avList);
dfw.append(simpleFeatureCollection);
dfw.flush();
}
JCommander.getConsole().println(
"Finished exporting '" + sft.getTypeName() + "'");
}
}
}
public List<String> getParameters() {
return parameters;
}
public void setParameters(
String storeName ) {
this.parameters = new ArrayList<String>();
this.parameters.add(storeName);
}
public DataStorePluginOptions getInputStoreOptions() {
return inputStoreOptions;
}
public void setInputStoreOptions(
DataStorePluginOptions inputStoreOptions ) {
this.inputStoreOptions = inputStoreOptions;
}
public void setOptions(
VectorLocalExportOptions options ) {
this.options = options;
}
public VectorLocalExportOptions getOptions() {
return options;
}
}