package org.geotools.data.ingres; import java.io.IOException; import org.geotools.data.jdbc.FilterToSQL; import org.geotools.filter.FilterCapabilities; import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.PreparedFilterToSQL; 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; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LinearRing; public class IngresFilterToSQL extends PreparedFilterToSQL { boolean looseBBOXEnabled; public IngresFilterToSQL(IngresDialect dialect) { } public boolean isLooseBBOXEnabled() { return looseBBOXEnabled; } public void setLooseBBOXEnabled(boolean looseBBOXEnabled) { this.looseBBOXEnabled = looseBBOXEnabled; } @Override protected void visitLiteralGeometry(Literal expression) throws IOException { // evaluate the literal and store it for later Geometry geom = (Geometry) evaluateLiteral(expression, Geometry.class); if ( geom instanceof LinearRing ) { //ingres does not handle linear rings, convert to just a line string geom = geom.getFactory().createLineString(((LinearRing) geom).getCoordinateSequence()); } out.write("ST_GeomFromText('"); out.write(geom.toText()); if(currentSRID == null && currentGeometry != null) { // if we don't know at all, use the srid of the geometry we're comparing against // (much slower since that has to be extracted record by record as opposed to // being a constant) out.write("', ST_SRID(\"" + currentGeometry.getLocalName() + "\"))"); } else { out.write("', " + currentSRID + ")"); } } @Override protected 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(Within.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(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(this, extraData); out.write(","); geometry.accept(this, 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(this, extraData); out.write(","); geometry.accept(this, extraData); out.write(") > "); out.write(Double.toString(filter.getDistance())); } } void visitComparisonSpatialOperator(BinarySpatialOperator filter, PropertyName property, Literal geometry, boolean swapped, Object extraData) throws IOException { String closingParenthesis = ")"; // if(!(filter instanceof Disjoint)) { // out.write("ST_Disjoint "); // } if (filter instanceof Equals) { out.write("ST_Equals"); } else if (filter instanceof Disjoint) { out.write("NOT (ST_Intersects"); closingParenthesis += ")"; } else if (filter instanceof Intersects || filter instanceof BBOX) { out.write("ST_Intersects"); } else if (filter instanceof Crosses) { out.write("ST_Crosses"); } else if (filter instanceof Within) { if(swapped) out.write("ST_Within"); else out.write("ST_Contains"); } else if (filter instanceof Contains) { if(swapped) out.write("ST_Contains"); else out.write("ST_Within"); } else if (filter instanceof Overlaps) { out.write("ST_Overlaps"); } else if (filter instanceof Touches) { out.write("ST_Touches"); } else { throw new RuntimeException("Unsupported filter type " + filter.getClass()); } out.write("("); property.accept(this, extraData); out.write(", GeomFromWKB("); geometry.accept(this, extraData); out.write(")"); out.write(closingParenthesis); out.write(" = 1"); } }