package org.geoserver.function;
import java.util.ArrayList;
import java.util.List;
import org.geoserver.catalog.Predicates;
import org.geotools.filter.capability.FunctionNameImpl;
import org.geotools.util.Converters;
import org.opengis.filter.capability.FunctionName;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.ExpressionVisitor;
import org.opengis.filter.expression.Function;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.VolatileFunction;
/**
* This class implements the {@link Function} interface and can be used for checking if an object is an instance of the provided input class.
*
* Users can call this function using the {@link Predicates} class:
*
* Predicates.isInstanceOf(Class clazz);
*
* @author Nicola Lagomarsini geosolutions
*/
public class IsInstanceOf implements VolatileFunction, Function {
/** Function name and related parameters */
public static FunctionName NAME = new FunctionNameImpl("isInstanceOf", Boolean.class,
FunctionNameImpl.parameter("class", Class.class));
/** Function parameters */
private List<Expression> parameters;
/** Fallback value used as default */
private Literal fallback;
public IsInstanceOf() {
this.parameters = new ArrayList<Expression>();
this.fallback = null;
}
protected IsInstanceOf(List<Expression> parameters, Literal fallback) {
this.parameters = parameters;
this.fallback = fallback;
// Check on the parameters
if (parameters == null) {
throw new NullPointerException("parameter required");
}
if (parameters.size() != 1) {
throw new IllegalArgumentException("isInstanceOf(class) requires one parameter only");
}
}
@Override
public Object evaluate(Object object) {
return evaluate(object, Boolean.class);
}
@Override
public <T> T evaluate(Object object, Class<T> context) {
// Selection of the first expression
Expression clazzExpression = parameters.get(0);
// Getting the defined class
Class clazz = clazzExpression.evaluate(object, Class.class);
// Checking the result
boolean result = false;
// If the input class is Object, the function always returns true
if (clazz != null) {
if (clazz == Object.class) {
result = true;
} else {
// Otherwise the function checks if the class is an instance of the
// input class
result = clazz.isAssignableFrom(object.getClass());
}
}
// Finally the result is converted to the defined context class
return Converters.convert(result, context);
}
@Override
public Object accept(ExpressionVisitor visitor, Object extraData) {
return visitor.visit(this, extraData);
}
@Override
public String getName() {
return NAME.getName();
}
@Override
public FunctionName getFunctionName() {
return NAME;
}
@Override
public List<Expression> getParameters() {
return parameters;
}
@Override
public Literal getFallbackValue() {
return fallback;
}
@Override
public String toString() {
List<Expression> params = getParameters();
if (params == null || params.size() == 0) {
return "IsInstanceOf([INVALID])";
} else {
return "IsInstanceOf(" + params.get(0) + ")";
}
}
}