Skip to content

Instantly share code, notes, and snippets.

@jericks
Created November 13, 2010 22:20
Show Gist options
  • Save jericks/675700 to your computer and use it in GitHub Desktop.
Save jericks/675700 to your computer and use it in GitHub Desktop.
A GeoScript Function implementation in Groovy
import geoscript.feature.Field
import org.geotools.factory.CommonFactoryFinder
import org.opengis.filter.expression.Function as GtFunction
import org.geotools.filter.FunctionImpl
import org.opengis.filter.expression.Expression
/**
* A GeoScript Function either wraps an existing GeoTools Function or
* can easily create a new Function by passing in a Closure.
* @author Jared Erickson
*/
class Function extends FunctionImpl {
/**
* The GeoTools CommonFactoryFinder for finding GeoTools Functions
*/
private static def ff = CommonFactoryFinder.getFilterFactory2(null)
/**
* The GeoTools Functions
*/
private GtFunction function = null
/**
* The Groovy Closure
*/
private Closure closure = null
/**
* Create a new Function by looking up an existing GeoTools Function by name
* and a List of parameters
* @param name The name of the existing Function
* @param parameters The List of parameters
*/
Function(String name, List parameters) {
function = ff.function(name, convertParametersToExpressions(parameters).toArray() as Expression[])
}
/**
* Create a new Function with a name, a List of parameters, and a Closure
* @param name The name of the new Function
* @param parameters The List of parameters
* @param closure The Closure
*/
Function(String name, List parameters, Closure closure) {
setName(name)
setParameters(convertParametersToExpressions(parameters))
this.closure = closure
}
/**
* Convert the List of parameters to a List of org.opengis.filter.expression.Expression's.
* All geoscript.feature.Fields are encoded as Properties and everything
* else if a Literal
* @param parameters The List of parameters
* @return A List of org.opengis.filter.expression.Expression's
*/
private static List<Expression> convertParametersToExpressions(List parameters) {
parameters.collect{param ->
if (param instanceof Field) {
return ff.property(param.name)
}
else {
return ff.literal(param)
}
}
}
/**
* Evaluate the Function
* @param object The Object (may be null)
* @return An Object
*/
def evaluate(Object object) {
if (function != null) {
// A GeoScript Layer == GeoTools FeatureCollection
if (object instanceof geoscript.layer.Layer) {
object = object.fs.features
}
return function.evaluate(object)
}
else {
// Unwrap Expression (Property => Field, Literal => .literal)
return closure(parameters, object)
}
}
/**
* Evaluate the Function
* @return An Object
*/
def evaluate() {
evaluate(null)
}
/**
* A Groovyism that allows function() instead of function.evaluate()
* @return An Object
*/
def call() {
evaluate()
}
/**
* A Groovyism that allows function(obj) instead of function.evaluate(obj)
* @param obj The parameter
* @return An Object
*/
def call(Object obj) {
evaluate(obj)
}
/**
* The string presentation
* @return The name of the Function
*/
String toString() {
name
}
}
// Create a Function from an existing Function
def shp = new geoscript.layer.Shapefile("states.shp")
def quantileFunction = new Function("Quantile", [new Field("PERSONS", "Double"), 5])
def quantiles = quantileFunction.evaluate(shp)
println(quantiles.titles)
// Create a Function from an existing Function
def maxFunction = new Function("max", [2,4])
println(maxFunction.evaluate())
// Create a Function from an existing Function
def minFunction = new Function("min", [2,4])
println(minFunction.evaluate())
// Create a new Function using a Closure
def addFunction = new Function("add", [2,5], {params, obj ->
params[0].literal + params[1].literal
})
println(addFunction.evaluate())
println(addFunction())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment