/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
* (C) 2009, Geomatys
*
* 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.geotoolkit.filter;
import java.io.Serializable;
import org.apache.sis.util.ObjectConverters;
import org.geotoolkit.util.StringUtilities;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.PropertyIsBetween;
import org.opengis.filter.expression.Expression;
import static org.apache.sis.util.ArgumentChecks.*;
/**
* Immutable "is between" filter.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class DefaultPropertyIsBetween implements PropertyIsBetween,Serializable{
private final Expression candidate;
private final Expression lower;
private final Expression upper;
public DefaultPropertyIsBetween(final Expression candidate, final Expression lower, final Expression upper) {
ensureNonNull("candidate", candidate);
ensureNonNull("lower", lower);
ensureNonNull("upper", upper);
this.candidate = candidate;
this.lower = lower;
this.upper = upper;
}
/**
* {@inheritDoc }
*/
@Override
public Expression getExpression() {
return candidate;
}
/**
* {@inheritDoc }
*/
@Override
public Expression getLowerBoundary() {
return lower;
}
/**
* {@inheritDoc }
*/
@Override
public Expression getUpperBoundary() {
return upper;
}
/**
* {@inheritDoc }
*/
@Override
public boolean evaluate(final Object feature) {
Object value = candidate.evaluate(feature);
if (value == null) {
return false;
}
if(!(value instanceof Comparable)){
//object class is not comparable
return false;
}
Class<?> valueClass = value.getClass();
if(Number.class.isAssignableFrom(valueClass)){
//we better compare with double to avoid truncations
valueClass = Double.class;
}
final Comparable test = (Comparable) ObjectConverters.convert(value, valueClass);
final Comparable down = (Comparable) lower.evaluate(feature,valueClass);
final Comparable up = (Comparable) upper.evaluate(feature,valueClass);
if(down == null || up == null){
//we could not obtain 3 same class objects to compare.
return false;
}
return down.compareTo(test) < 0 && up.compareTo(test) >= 0;
}
/**
* {@inheritDoc }
*/
@Override
public Object accept(final FilterVisitor visitor, final Object extraData) {
return visitor.visit(this, extraData);
}
/**
* {@inheritDoc }
*/
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DefaultPropertyIsBetween other = (DefaultPropertyIsBetween) obj;
if (this.candidate != other.candidate && (this.candidate == null || !this.candidate.equals(other.candidate))) {
return false;
}
if (this.lower != other.lower && (this.lower == null || !this.lower.equals(other.lower))) {
return false;
}
if (this.upper != other.upper && (this.upper == null || !this.upper.equals(other.upper))) {
return false;
}
return true;
}
/**
* {@inheritDoc }
*/
@Override
public int hashCode() {
int hash = 5;
hash = 97 * hash + (this.candidate != null ? this.candidate.hashCode() : 0);
hash = 97 * hash + (this.lower != null ? this.lower.hashCode() : 0);
hash = 97 * hash + (this.upper != null ? this.upper.hashCode() : 0);
return hash;
}
/**
* {@inheritDoc }
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Between\n");
sb.append(StringUtilities.toStringTree("Exp : "+ candidate,"Lower : "+lower, "Upper : "+upper));
return sb.toString();
}
}