/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2009, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.data.postgis; import java.io.IOException; import java.io.Writer; import org.geotools.data.jdbc.FilterToSQL; import org.geotools.filter.FilterCapabilities; import org.geotools.jdbc.SQLDialect; import org.opengis.filter.expression.Literal; 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.DistanceBufferOperator; 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; class FilterToSqlHelper { protected static final String IO_ERROR = "io problem writing filter"; FilterToSQL delegate; Writer out; boolean looseBBOXEnabled; public FilterToSqlHelper(FilterToSQL delegate) { this.delegate = delegate; } public static FilterCapabilities createFilterCapabilities() { FilterCapabilities caps = new FilterCapabilities(); caps.addAll(SQLDialect.BASE_DBMS_CAPABILITIES); // adding the spatial filters support caps.addType(BBOX.class); caps.addType(Contains.class); caps.addType(Crosses.class); caps.addType(Disjoint.class); caps.addType(Equals.class); caps.addType(Intersects.class); caps.addType(Overlaps.class); caps.addType(Touches.class); caps.addType(Within.class); caps.addType(DWithin.class); caps.addType(Beyond.class); return caps; } protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, PropertyName property, Literal geometry, boolean swapped, Object extraData) { try { if (filter instanceof DistanceBufferOperator) { visitDistanceSpatialOperator((DistanceBufferOperator) filter, property, geometry, swapped, extraData); } else { visitComparisonSpatialOperator(filter, property, geometry, swapped, extraData); } } catch (IOException e) { throw new RuntimeException(IO_ERROR, e); } return extraData; } void visitDistanceSpatialOperator(DistanceBufferOperator filter, PropertyName property, Literal geometry, boolean swapped, Object extraData) throws IOException { if ((filter instanceof DWithin && !swapped) || (filter instanceof Beyond && swapped)) { out.write("ST_DWITHIN("); property.accept(delegate, extraData); out.write(","); geometry.accept(delegate, extraData); out.write(","); out.write(Double.toString(filter.getDistance())); out.write(")"); } if ((filter instanceof DWithin && swapped) || (filter instanceof Beyond && !swapped)) { out.write("ST_DISTANCE("); property.accept(delegate, extraData); out.write(","); geometry.accept(delegate, extraData); out.write(") > "); out.write(Double.toString(filter.getDistance())); } } void visitComparisonSpatialOperator(BinarySpatialOperator filter, PropertyName property, Literal geometry, boolean swapped, Object extraData) throws IOException { if(!(filter instanceof Disjoint)) { property.accept(delegate, extraData); out.write(" && "); geometry.accept(delegate, extraData); // if we're just encoding a bbox in loose mode, we're done if(filter instanceof BBOX && looseBBOXEnabled) return; out.write(" AND "); } String closingParenthesis = ")"; if (filter instanceof Equals) { out.write("equals"); } else if (filter instanceof Disjoint) { out.write("NOT (intersects"); closingParenthesis += ")"; } else if (filter instanceof Intersects || filter instanceof BBOX) { out.write("intersects"); } else if (filter instanceof Crosses) { out.write("crosses"); } else if (filter instanceof Within) { if(swapped) out.write("contains"); else out.write("within"); } else if (filter instanceof Contains) { if(swapped) out.write("within"); else out.write("contains"); } else if (filter instanceof Overlaps) { out.write("overlaps"); } else if (filter instanceof Touches) { out.write("touches"); } else { throw new RuntimeException("Unsupported filter type " + filter.getClass()); } out.write("("); property.accept(delegate, extraData); out.write(", "); geometry.accept(delegate, extraData); out.write(closingParenthesis); } }