package mil.nga.giat.geowave.adapter.vector.query.cql; import mil.nga.giat.geowave.adapter.vector.plugin.GeoWaveGTDataStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.geotools.filter.FilterFactoryImpl; import org.geotools.filter.IllegalFilterException; import org.geotools.filter.LiteralExpressionImpl; import org.geotools.filter.spatial.DWithinImpl; import org.geotools.filter.spatial.IntersectsImpl; import org.geotools.filter.text.cql2.CQLException; import org.geotools.filter.text.ecql.ECQL; import org.opengis.filter.Filter; import org.opengis.filter.MultiValuedFilter.MatchAction; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.PropertyName; import org.opengis.filter.spatial.DWithin; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.TransformException; public class FilterToCQLTool { private static Logger LOGGER = LoggerFactory.getLogger(FilterToCQLTool.class); /** * Corrects any function issues. * * @param filter * @return */ public static String toCQL( Filter filter ) { FilterToECQLExtension toCQL = new FilterToECQLExtension(); StringBuilder output = (StringBuilder) filter.accept( toCQL, new StringBuilder()); return output.toString(); } public static Filter toFilter( String expression ) throws CQLException { return ECQL.toFilter( expression, new FilterFactoryImpl() { @Override public DWithin dwithin( Expression geometry1, Expression geometry2, double distance, String units, MatchAction matchAction ) { try { return matchAction == null ? new FixedDWithinImpl( geometry1, geometry2, units, distance) : new FixedDWithinImpl( geometry1, geometry2, units, distance, matchAction); } catch (IllegalFilterException | TransformException e) { LOGGER.warn( "Cannot convert DWithin Expression to work with WSG84", e); } final DWithinImpl impl = matchAction == null ? new DWithinImpl( geometry1, geometry2) : new DWithinImpl( geometry1, geometry2, matchAction); impl.setDistance(distance); impl.setUnits(units); return impl; } @Override public DWithin dwithin( Expression geometry1, Expression geometry2, double distance, String units ) { return dwithin( geometry1, geometry2, distance, units, (MatchAction) null); } }); } public static final class FixedDWithinImpl extends IntersectsImpl implements DWithin { private double distance; private String units; public FixedDWithinImpl( Expression e1, Expression e2, String units, double distance ) throws IllegalFilterException, TransformException { super( new LiteralExpressionImpl( mil.nga.giat.geowave.adapter.vector.utils.GeometryUtils.buffer( getCRS( e1, e2), e1 instanceof PropertyName ? e2.evaluate( null, com.vividsolutions.jts.geom.Geometry.class) : e1.evaluate( null, com.vividsolutions.jts.geom.Geometry.class), units, distance).getLeft()), e1 instanceof PropertyName ? e1 : e2); this.units = units; this.distance = distance; } private static CoordinateReferenceSystem getCRS( Expression e1, Expression e2 ) { return GeoWaveGTDataStore.DEFAULT_CRS; } public FixedDWithinImpl( Expression e1, Expression e2, String units, double distance, MatchAction matchAction ) throws IllegalFilterException, TransformException { super( new LiteralExpressionImpl( mil.nga.giat.geowave.adapter.vector.utils.GeometryUtils.buffer( getCRS( e1, e2), e1.evaluate( null, com.vividsolutions.jts.geom.Geometry.class), units, distance).getLeft()), e2, matchAction); this.units = units; this.distance = distance; } @Override public double getDistance() { return distance; } @Override public String getDistanceUnits() { return units; } } }