package mil.nga.giat.geowave.adapter.vector.delete;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.geotools.filter.text.cql2.CQLException;
import com.beust.jcommander.IStringConverter;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.google.common.base.Stopwatch;
import mil.nga.giat.geowave.adapter.vector.GeotoolsFeatureDataAdapter;
import mil.nga.giat.geowave.adapter.vector.cli.VectorSection;
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.cli.operations.config.options.ConfigOptions;
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.operations.remote.options.StoreLoader;
import mil.nga.giat.geowave.core.store.query.QueryOptions;
@GeowaveOperation(name = "cqldelete", parentOperation = VectorSection.class)
@Parameters(commandDescription = "Delete data that matches a CQL filter")
public class CQLDelete extends
DefaultOperation implements
Command
{
private static Logger LOGGER = LoggerFactory.getLogger(CQLDelete.class);
@Parameter(description = "<storename>")
private List<String> parameters = new ArrayList<String>();
@Parameter(names = "--cql", required = true, description = "CQL Filter for delete")
private String cqlStr;
@Parameter(names = "--indexId", required = false, description = "The name of the index (optional)", converter = StringToByteArrayConverter.class)
private ByteArrayId indexId;
@Parameter(names = "--adapterId", required = false, description = "Optional ability to provide an adapter ID", converter = StringToByteArrayConverter.class)
private ByteArrayId adapterId;
@Parameter(names = "--debug", required = false, description = "Print out additional info for debug purposes")
private boolean debug = false;
@Override
public void execute(
OperationParams params )
throws ParseException {
if (debug) {
org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.DEBUG);
}
final Stopwatch stopWatch = new Stopwatch();
// Ensure we have all the required arguments
if (parameters.size() != 1) {
throw new ParameterException(
"Requires arguments: <storename>");
}
String storeName = parameters.get(0);
// Config file
File configFile = (File) params.getContext().get(
ConfigOptions.PROPERTIES_FILE_CONTEXT);
// Attempt to load store.
StoreLoader storeOptions = new StoreLoader(
storeName);
if (!storeOptions.loadFromConfig(configFile)) {
throw new ParameterException(
"Cannot find store name: " + storeOptions.getStoreName());
}
DataStore dataStore;
AdapterStore adapterStore;
try {
dataStore = storeOptions.createDataStore();
adapterStore = storeOptions.createAdapterStore();
final GeotoolsFeatureDataAdapter adapter;
if (adapterId != null) {
adapter = (GeotoolsFeatureDataAdapter) adapterStore.getAdapter(adapterId);
}
else {
final CloseableIterator<DataAdapter<?>> it = adapterStore.getAdapters();
adapter = (GeotoolsFeatureDataAdapter) it.next();
it.close();
}
if (debug && (adapter != null)) {
LOGGER.debug(adapter.toString());
}
stopWatch.start();
final long results = delete(
adapter,
adapterId,
indexId,
dataStore,
debug);
stopWatch.stop();
if (debug) {
LOGGER.debug(results + " results remaining after delete; time = " + stopWatch.toString());
}
}
catch (IOException e) {
LOGGER.warn(
"Unable to read adapter",
e);
}
}
protected long delete(
final GeotoolsFeatureDataAdapter adapter,
final ByteArrayId adapterId,
final ByteArrayId indexId,
final DataStore dataStore,
final boolean debug ) {
long missed = 0;
try {
boolean success = dataStore.delete(
new QueryOptions(
adapterId,
indexId),
mil.nga.giat.geowave.adapter.vector.query.cql.CQLQuery.createOptimalQuery(
cqlStr,
adapter,
null,
null));
if (debug) {
LOGGER.debug("CQL Delete " + (success ? "Success" : "Failure"));
}
}
catch (CQLException e2) {
LOGGER.warn(
"Error parsing CQL",
e2);
}
// Verify delete by running the CQL query
if (debug) {
try (final CloseableIterator<Object> it = dataStore.query(
new QueryOptions(
adapterId,
indexId),
mil.nga.giat.geowave.adapter.vector.query.cql.CQLQuery.createOptimalQuery(
cqlStr,
adapter,
null,
null))) {
while (it.hasNext()) {
it.next();
missed++;
}
}
catch (final IOException e) {
LOGGER.warn(
"Unable to read result",
e);
}
catch (final CQLException e1) {
LOGGER.error(
"Unable to create optimal query",
e1);
}
}
return missed;
}
public static class StringToByteArrayConverter implements
IStringConverter<ByteArrayId>
{
@Override
public ByteArrayId convert(
String value ) {
return new ByteArrayId(
value);
}
}
}