package org.geotools.data.complex.filter;
import java.util.List;
import org.geotools.filter.BinaryComparisonAbstract;
import org.geotools.filter.LikeFilterImpl;
import org.geotools.filter.NestedAttributeExpression;
import org.geotools.filter.OrImpl;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
/**
* A wrapper filter for filters involving nested features. Such filter involves nested attributes
* that come from a different type/table, and is evaluated on the simple feature level (expecting a
* single value), and join queries aren't supported. Therefore it won't work for multi-valued
* attributes.. this is why NestedAttributeExpression is used to return all the possible values
* (multi-valued). This wrapper filter will then get all the possible values from
* NestedAttributeExpression and applies the filter for each value.
*
* @author Rini Angreani, CSIRO Earth Science and Resource Engineering
*
*
* @source $URL$
*/
public class MultiValuedOrImpl extends OrImpl {
private Filter filter;
private NestedAttributeExpression expression;
public MultiValuedOrImpl(FilterFactory ff, Filter filter, NestedAttributeExpression expression) {
super(ff, null);
this.filter = filter;
this.expression = expression;
}
@SuppressWarnings("unchecked")
@Override
public boolean evaluate(Object feature) {
Object value = expression.evaluate(feature);
if (value != null) {
List<Object> values = (List<Object>) value;
if (filter instanceof BinaryComparisonAbstract) {
BinaryComparisonAbstract compFilter = ((BinaryComparisonAbstract) filter);
Expression exp1 = compFilter.getExpression1();
Expression exp2 = compFilter.getExpression2();
boolean isLeftAttributeExp = false;
if (exp1 == null) {
if (exp2 == null) {
return true;
}
} else if (exp2 == null) {
isLeftAttributeExp = true;
} else {
if (!(exp2 instanceof Literal) && !(exp1 instanceof Literal)) {
// unsupported
throw new UnsupportedOperationException(
"Comparison filters involving attributes of nested features are only supported if "
+ "only one of the expressions compared is a literal.");
}
}
if (exp2 instanceof Literal) {
isLeftAttributeExp = true;
}
if (isLeftAttributeExp) {
for (Object val : values) {
compFilter.setExpression1(this.factory.literal(val));
if (compFilter.evaluate(null)) {
((BinaryComparisonAbstract) filter).setExpression1(exp1);
return true;
}
}
((BinaryComparisonAbstract) filter).setExpression1(exp1);
} else {
for (Object val : values) {
compFilter.setExpression2(this.factory.literal(val));
if (compFilter.evaluate(null)) {
((BinaryComparisonAbstract) filter).setExpression2(exp2);
return true;
}
}
((BinaryComparisonAbstract) filter).setExpression2(exp2);
}
} else if (filter instanceof LikeFilterImpl) {
// PropertyIsLike can only have 1 attribute on LHS, and 1 literal on RHS
for (Object val : values) {
((LikeFilterImpl) filter).setExpression(this.factory.literal(val));
if (filter.evaluate(null)) {
return true;
}
}
}
}
return false;
}
@Override
public Object accept(FilterVisitor visitor, Object extraData) {
return null;
}
}