/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.csw.records;
import org.geoserver.platform.ServiceException;
import org.geotools.filter.visitor.DefaultFilterVisitor;
import org.opengis.feature.type.FeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.BBOX;
import org.opengis.filter.spatial.Beyond;
import org.opengis.filter.spatial.BinarySpatialOperator;
import org.opengis.filter.spatial.Contains;
import org.opengis.filter.spatial.Crosses;
import org.opengis.filter.spatial.DWithin;
import org.opengis.filter.spatial.Disjoint;
import org.opengis.filter.spatial.Equals;
import org.opengis.filter.spatial.Intersects;
import org.opengis.filter.spatial.Overlaps;
import org.opengis.filter.spatial.Touches;
import org.opengis.filter.spatial.Within;
/**
* Checks if spatial filters are used against non spatial properties, if so, throws a ServiceException
* (mandated for CSW cite compliance). Works fine for simple data models, but you might need
* to use a custom one for more complex models (e.g., SpatialFilterChecker is known not to work with ebRIM)
*
* @author Andrea Aime - GeoSolutions
*/
public class SpatialFilterChecker extends DefaultFilterVisitor {
FeatureType schema;
public SpatialFilterChecker(FeatureType schema) {
this.schema = schema;
}
private void checkBinarySpatialOperator(BinarySpatialOperator filter) {
verifyGeometryProperty(filter.getExpression1());
verifyGeometryProperty(filter.getExpression2());
}
private void verifyGeometryProperty(Expression expression) {
if(expression instanceof PropertyName) {
PropertyName pn = ((PropertyName) expression);
if (! (pn.evaluate(schema) instanceof GeometryDescriptor)) {
throw new ServiceException("Invalid spatial filter, property " + pn.getPropertyName() + " is not a geometry");
}
}
}
public Object visit( final BBOX filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Beyond filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Contains filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Crosses filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Disjoint filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( DWithin filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Equals filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Intersects filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Overlaps filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Touches filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
public Object visit( Within filter, Object data ) {
checkBinarySpatialOperator(filter);
return data;
}
}