/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2006-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.filter;
import java.util.Collection;
import java.util.Collections;
import org.geotools.util.Converters;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.MultiValuedFilter.MatchAction;
import org.opengis.filter.expression.Expression;
/**
* Straight implementation of GeoAPI interface.
*
* @author Justin Deoliveira, The Open Planning Project
*
*
* @source $URL$
*/
public class IsBetweenImpl extends CompareFilterImpl implements BetweenFilter {
private Expression expression;
protected MatchAction matchAction;
protected IsBetweenImpl(org.opengis.filter.FilterFactory factory, Expression lower, Expression expression, Expression upper, MatchAction matchAction ){
super( factory, lower, upper );
this.expression = expression;
this.matchAction = matchAction;
//backwards compatability
filterType = FilterType.BETWEEN;
}
protected IsBetweenImpl(org.opengis.filter.FilterFactory factory, Expression lower, Expression expression, Expression upper ){
this( factory, lower, expression, upper, MatchAction.ANY );
}
public Expression getExpression() {
return expression;
}
public void setExpression(Expression expression) {
this.expression = expression;
}
public MatchAction getMatchAction() {
return matchAction;
}
//@Override
public boolean evaluate(Object feature) {
//NC - support for multiple values
final Object object0 = eval(expression, feature);
final Object object1 = eval(expression1, feature);
final Object object2 = eval(expression2, feature);
if (!(object0 instanceof Collection) && !(object1 instanceof Collection) && !(object2 instanceof Collection)) {
return evaluateInternal(object0, object1, object2);
}
Collection<Object> oValues = object0 instanceof Collection ? (Collection<Object>) object0
: Collections.<Object>singletonList(object0);
Collection<Object> leftValues = object1 instanceof Collection ? (Collection<Object>) object1
: Collections.<Object>singletonList(object1);
Collection<Object> rightValues = object2 instanceof Collection ? (Collection<Object>) object2
: Collections.<Object>singletonList(object2);
int count = 0;
for (Object value1 : leftValues) {
for (Object value2 : rightValues) {
for (Object value0 : oValues) {
boolean temp = evaluateInternal(value0, value1, value2);
if (temp) {
count++;
}
switch (matchAction){
case ONE: if (count > 1) return false; break;
case ALL: if (!temp) return false; break;
case ANY: if (temp) return true; break;
}
}
}
}
switch (matchAction){
case ONE: return (count == 1);
case ALL: return true;
case ANY: return false;
default: return false;
}
}
public boolean evaluateInternal(Object value, Object lower, Object upper) {
//first try to evaluate the bounds in terms of the middle
Object o = value;
Object l = Converters.convert(lower, o.getClass());
Object u = Converters.convert(upper, o.getClass());
if ( l == null || u == null ) {
//that didn't work try converting all to same type as lower
l = lower;
o = Converters.convert(value, l.getClass());
u = Converters.convert(upper, l.getClass());
if ( o == null || u == null ) {
//ok last try, try evaluating all in terms of upper
u = upper;
o = Converters.convert(value, u.getClass());
l = Converters.convert(lower, u.getClass());
if ( o == null || l == null ) {
//no dice
return false;
}
}
}
Comparable lc = comparable( l );
Comparable uc = comparable( u );
return lc.compareTo( o ) <= 0 && uc.compareTo( o ) >= 0;
}
public Object accept(FilterVisitor visitor, Object extraData) {
return visitor.visit( this, extraData );
}
public Expression getLowerBoundary() {
return getExpression1();
}
public void setLowerBoundary(Expression lowerBoundary) {
setExpression1( lowerBoundary );
}
public Expression getUpperBoundary() {
return getExpression2();
}
public void setUpperBoundary(Expression upperBoundary) {
setExpression2( upperBoundary );
}
/**
* @deprecated use {@link #getExpression()}
*/
public final org.geotools.filter.Expression getMiddleValue() {
return (org.geotools.filter.Expression) getExpression();
}
/**
* @deprecated use {@link #setExpression(Expression) }
*/
public void addMiddleValue(org.geotools.filter.Expression middleValue) {
setExpression( middleValue );
}
public String toString() {
return "[ " + expression + " BETWEEN " + expression1 + " AND " + expression2 + " ]";
}
}