/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, 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.binarycomparison;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import org.apache.sis.util.ArgumentChecks;
import static org.apache.sis.util.ArgumentChecks.*;
import org.apache.sis.util.ObjectConverters;
import org.opengis.filter.BinaryComparisonOperator;
import org.opengis.filter.MatchAction;
import org.opengis.filter.expression.Expression;
/**
* Immutable abstract "binary comparison operator".
*
* @author Johann Sorel (Geomatys)
* @param <E> Expression or subclass
* @param <F> Expression or subclass
* @module
*/
public abstract class AbstractBinaryComparisonOperator<E extends Expression,F extends Expression>
implements BinaryComparisonOperator,Serializable{
protected final E left;
protected final F right;
protected final boolean match;
protected final MatchAction matchAction;
public AbstractBinaryComparisonOperator(final E left, final F right, final boolean match, final MatchAction matchAction) {
ensureNonNull("left", left);
ensureNonNull("right", right);
this.left = left;
this.right = right;
this.match = match;
this.matchAction = matchAction;
ArgumentChecks.ensureNonNull("matchAction", matchAction);
}
/**
* {@inheritDoc }
*/
@Override
public E getExpression1() {
return left;
}
/**
* {@inheritDoc }
*/
@Override
public F getExpression2() {
return right;
}
/**
* {@inheritDoc }
*/
@Override
public boolean isMatchingCase() {
return match;
}
@Override
public MatchAction getMatchAction() {
return matchAction;
}
/**
* {@inheritDoc }
*/
@Override
public final boolean evaluate(final Object candidate) {
final Object objleft = left.evaluate(candidate);
final Object objright = right.evaluate(candidate);
if (objleft instanceof Collection && objright instanceof Collection) {
return evaluateOne(objleft, objright);
} else if (objleft instanceof Collection) {
final Collection col = (Collection) objleft;
if(col.isEmpty()) return false;
switch(matchAction){
case ALL:
for(Object o : col){
if(!evaluateOne(o, objright)) return false;
}
return true;
case ANY:
for(Object o : col){
if(evaluateOne(o, objright)) return true;
}
return false;
case ONE:
boolean found = false;
for(Object o : col){
if(evaluateOne(o, objright)){
if(found) return false;
found = true;
}
}
return found;
default: return false;
}
} else if (objright instanceof Collection) {
final Collection col = (Collection) objright;
if(col.isEmpty()) return false;
switch(matchAction){
case ALL:
for(Object o : col){
if(!evaluateOne(objleft,o)) return false;
}
return true;
case ANY:
for(Object o : col){
if(evaluateOne(objleft,o)) return true;
}
return false;
case ONE:
boolean found = false;
for(Object o : col){
if(evaluateOne(objleft,o)){
if(found) return false;
found = true;
}
}
return found;
default: return false;
}
} else {
return evaluateOne(objleft, objright);
}
}
protected abstract boolean evaluateOne(Object objleft,Object objright);
protected Integer compare(Object objleft, Object objright){
if(!(objleft instanceof Comparable)){
return null;
}
//see if the right type might be more appropriate for test
if( !(objleft instanceof Date) ){
if(objright instanceof Date){
//object right class is more appropriate
Object cdLeft = ObjectConverters.convert(objleft, Date.class);
if(cdLeft != null){
return ((Comparable)cdLeft).compareTo(objright);
}
}
}
objright = ObjectConverters.convert(objright, objleft.getClass());
if (objleft instanceof java.sql.Date && objright instanceof java.sql.Date) {
final Calendar cal1 = Calendar.getInstance();
cal1.setTime((java.sql.Date)objleft);
cal1.set(Calendar.HOUR_OF_DAY, 0);
cal1.set(Calendar.MINUTE, 0);
cal1.set(Calendar.SECOND, 0);
cal1.set(Calendar.MILLISECOND, 0);
final Calendar cal2 = Calendar.getInstance();
cal2.setTime((java.sql.Date)objright);
cal2.set(Calendar.HOUR_OF_DAY, 0);
cal2.set(Calendar.MINUTE, 0);
cal2.set(Calendar.SECOND, 0);
cal2.set(Calendar.MILLISECOND, 0);
return cal1.compareTo(cal2);
}
if(objright == null){
return null;
}
return ((Comparable)objleft).compareTo(objright);
}
@Override
public int hashCode() {
int hash = 7;
hash = 61 * hash + (this.left != null ? this.left.hashCode() : 0);
hash = 61 * hash + (this.right != null ? this.right.hashCode() : 0);
hash = 61 * hash + (this.match ? 1 : 0);
return hash;
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final AbstractBinaryComparisonOperator<E, F> other = (AbstractBinaryComparisonOperator<E, F>) obj;
if (this.left != other.left && (this.left == null || !this.left.equals(other.left))) {
return false;
}
if (this.right != other.right && (this.right == null || !this.right.equals(other.right))) {
return false;
}
if (this.match != other.match) {
return false;
}
return true;
}
}