/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, 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.util.Iterator;
import org.geotools.filter.Expression;
import org.geotools.filter.FilterCapabilities;
import org.geotools.filter.FunctionExpression;
import org.geotools.filter.RegisteredFunction;
import org.geotools.filter.SQLEncoder;
import org.geotools.filter.SQLEncoderPostgis;
/**
* SQL encoder with support for registered functions (on PostGIS).
*
* <p>
*
* This class adds {@link RegisteredFunction} to the filter capabilities for this encoder, and
* implements the method required to encode a {@link FunctionExpression} as SQL.
*
* <p>
*
* TODO: everything here should be pulled up into {@link SQLEncoder}.
*
* @author Ben Caradoc-Davies, CSIRO Exploration and Mining
* @version $Id$
* @source $URL$
* @since 2.4
*/
public class RegfuncSQLEncoderPostgis extends SQLEncoderPostgis {
/**
* Empty constructor
*
* <p>
*
* TODO: rethink empty constructor, as BBOXes _need_ an SRID, must make client set it somehow.
* Maybe detect when encode is called?
*/
public RegfuncSQLEncoderPostgis() {
}
/**
* @param looseBbox
* Whether the BBOX filter should be strict (using the exact geom), or loose
* (using the envelopes)
*
*/
public RegfuncSQLEncoderPostgis(boolean looseBbox) {
super(looseBbox);
}
/**
* Constructor with srid.
*
* @param srid
* spatial reference id to encode geometries with.
*/
public RegfuncSQLEncoderPostgis(int srid) {
super(srid);
}
/**
* Extends super by adding support for registered functions to the filter capabilities.
*
* @see org.geotools.filter.SQLEncoderPostgis#createFilterCapabilities()
*/
protected FilterCapabilities createFilterCapabilities() {
FilterCapabilities filterCapabilities = super.createFilterCapabilities();
filterCapabilities.addType(RegisteredFunction.class);
return filterCapabilities;
}
/**
* Writes SQL for a function expression.
*
* @see org.geotools.filter.SQLEncoder#visit(org.geotools.filter.FunctionExpression)
*/
// @Override
public void visit(FunctionExpression expression) {
try {
String name = expression.getName();
/*
* SECURITY: protect against SQL injection attacks. SQL identifiers are similar to Java,
* and testing for Java form should give sufficient protection as quotes and whitespace
* are excluded.
*/
if (!name.matches("\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*")) {
throw new RuntimeException("Function expression name \"" + name
+ "\" is not a valid SQL identifier");
}
out.write(escapeName(name) + "(");
boolean isFirstParameter = true;
for (Iterator parameterIterator = expression.getParameters().iterator(); parameterIterator
.hasNext();) {
Expression parameter = (Expression) parameterIterator.next();
if (isFirstParameter) {
isFirstParameter = false;
} else {
out.write(", ");
}
parameter.accept(this);
}
out.write(")");
} catch (IOException e) {
throw new RuntimeException("IO problems writing function expression", e);
}
}
}