package mil.nga.giat.geowave.adapter.vector.ingest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.geotools.filter.text.cql2.CQL; import org.geotools.filter.text.cql2.CQLException; import org.opengis.filter.Filter; import org.opengis.filter.FilterVisitor; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import mil.nga.giat.geowave.core.cli.converters.GeoWaveBaseConverter; import mil.nga.giat.geowave.core.index.Persistable; import mil.nga.giat.geowave.core.index.StringUtils; /** * Supports converting the filter string to Filter object. */ public class CQLFilterOptionProvider implements Filter, Persistable { private final static Logger LOGGER = LoggerFactory.getLogger(CQLFilterOptionProvider.class); @Parameter(names = "--cql", description = "A CQL filter, only data matching this filter will be ingested", converter = ConvertCQLStrToFilterConverter.class) private FilterParameter convertedFilter = new FilterParameter( null, null); public String getCqlFilterString() { return convertedFilter.getCqlFilterString(); } @Override public byte[] toBinary() { if (convertedFilter.getCqlFilterString() == null) { return new byte[] {}; } return StringUtils.stringToBinary(convertedFilter.getCqlFilterString()); } @Override public void fromBinary( final byte[] bytes ) { if (bytes.length > 0) { // This has the side-effect of setting the 'filter' member // variable. convertedFilter = new ConvertCQLStrToFilterConverter().convert(StringUtils.stringFromBinary(bytes)); } else { convertedFilter.setCqlFilterString(null); convertedFilter.setFilter(null); } } @Override public boolean evaluate( final Object object ) { if (convertedFilter.getFilter() == null) { return true; } return convertedFilter.getFilter().evaluate( object); } @Override public Object accept( final FilterVisitor visitor, final Object extraData ) { if (convertedFilter.getFilter() == null) { if (visitor != null) { return visitor.visitNullFilter(extraData); } return extraData; } return convertedFilter.getFilter().accept( visitor, extraData); } private static Filter asFilter( final String cqlPredicate ) throws CQLException { return CQL.toFilter(cqlPredicate); } /** * This class will ensure that as the CQLFilterString is read in and * converted to a filter. */ public static class ConvertCQLStrToFilterConverter extends GeoWaveBaseConverter<FilterParameter> { public ConvertCQLStrToFilterConverter() { super( ""); } public ConvertCQLStrToFilterConverter( String optionName ) { super( optionName); } @Override public FilterParameter convert( String value ) { Filter convertedFilter = null; if (value != null) { try { convertedFilter = asFilter(value); } catch (final CQLException e) { LOGGER.error( "Cannot parse CQL expression '" + value + "'", e); // value = null; // convertedFilter = null; throw new ParameterException( "Cannot parse CQL expression '" + value + "'", e); } } else { value = null; } return new FilterParameter( value, convertedFilter); } } public static class FilterParameter { private String cqlFilterString; private Filter filter; public FilterParameter( String cqlFilterString, Filter filter ) { super(); this.cqlFilterString = cqlFilterString; this.filter = filter; } public String getCqlFilterString() { return cqlFilterString; } public void setCqlFilterString( String cqlFilterString ) { this.cqlFilterString = cqlFilterString; } public Filter getFilter() { return filter; } public void setFilter( Filter filter ) { this.filter = filter; } public String toString() { return cqlFilterString; } } }