package uk.ac.imperial.lsds.streamsql.predicates;
import java.util.ArrayList;
import java.util.List;
import uk.ac.imperial.lsds.seep.comm.serialization.DataTuple;
import uk.ac.imperial.lsds.streamsql.expressions.IValueExpression;
import uk.ac.imperial.lsds.streamsql.visitors.PredicateVisitor;
public class ComparisonPredicate<T extends Comparable<T>> implements IPredicate {
/*
* Values compared by this predicate
*/
IValueExpression<T> v1;
IValueExpression<T> v2;
/*
* Code of the comparison operator
*/
int comparisonOperation;
/*
* Codes of available comparison operator
*/
public static final int EQUAL_OP = 0;
public static final int NONEQUAL_OP = 1;
public static final int LESS_OP = 2;
public static final int NONLESS_OP = 3;
public static final int GREATER_OP = 4;
public static final int NONGREATER_OP = 5;
public ComparisonPredicate(int comparisonOperation, IValueExpression<T> v1, IValueExpression<T> v2) {
this.comparisonOperation = comparisonOperation;
this.v1 = v1;
this.v2 = v2;
}
public ComparisonPredicate(IValueExpression<T> v1, IValueExpression<T> v2) {
this(EQUAL_OP, v1, v2);
}
public int getOperator(boolean inverse) {
int result = 0;
if (inverse)
switch (this.comparisonOperation) {
case NONEQUAL_OP:
result = NONEQUAL_OP;
break;
case EQUAL_OP:
result = EQUAL_OP;
break;
case LESS_OP:
result = GREATER_OP;
break;
case NONLESS_OP:
result = NONGREATER_OP;
break;
case GREATER_OP:
result = LESS_OP;
break;
case NONGREATER_OP:
result = NONLESS_OP;
break;
}
else
result = this.comparisonOperation;
return result;
}
@Override
public boolean satisfied(DataTuple tuple) {
Comparable val1 = v1.eval(tuple);
Comparable val2 = v2.eval(tuple);
// All the Numeric types are converted to double,
// because different types cannot be compared
if (val1 instanceof Long)
val1 = (((Long) val1).doubleValue());
if (val2 instanceof Long)
val2 = (((Long) val2).doubleValue());
final int compared = val1.compareTo(val2);
boolean result = false;
switch (this.comparisonOperation) {
case EQUAL_OP:
result = (compared == 0);
break;
case NONEQUAL_OP:
result = (compared != 0);
break;
case LESS_OP:
result = (compared < 0);
break;
case NONLESS_OP:
result = (compared >= 0);
break;
case GREATER_OP:
result = (compared > 0);
break;
case NONGREATER_OP:
result = (compared <= 0);
break;
default:
throw new RuntimeException("Unsupported operation " + this.comparisonOperation);
}
return result;
}
@Override
public boolean satisfied(DataTuple firstTuple, DataTuple secondTuple) {
final Comparable val1 = v1.eval(firstTuple);
final Comparable val2 = v2.eval(secondTuple);
final int compared = val1.compareTo(val2);
boolean result = false;
switch (this.comparisonOperation) {
case EQUAL_OP:
result = (compared == 0);
break;
case NONEQUAL_OP:
result = (compared != 0);
break;
case LESS_OP:
result = (compared < 0);
break;
case NONLESS_OP:
result = (compared >= 0);
break;
case GREATER_OP:
result = (compared > 0);
break;
case NONGREATER_OP:
result = (compared <= 0);
break;
default:
throw new RuntimeException("Unsupported operation " + this.comparisonOperation);
}
return result;
}
// used for direct key comparison
public boolean test(T key1, T key2){
final int compared = key1.compareTo(key2);
boolean result = false;
switch (this.comparisonOperation) {
case EQUAL_OP:
result = (compared == 0);
break;
case NONEQUAL_OP:
result = (compared != 0);
break;
case LESS_OP:
result = (compared < 0);
break;
case NONLESS_OP:
result = (compared >= 0);
break;
case GREATER_OP:
result = (compared > 0);
break;
case NONGREATER_OP:
result = (compared <= 0);
break;
default:
throw new RuntimeException("Unsupported operation " + this.comparisonOperation);
}
return result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append(v1.toString());
sb.append(getOperationString());
sb.append(v2.toString());
return sb.toString();
}
private String getOperationString() {
String result = null;
switch (this.comparisonOperation) {
case NONEQUAL_OP:
result = " != ";
break;
case EQUAL_OP:
result = " = ";
break;
case LESS_OP:
result = " < ";
break;
case NONLESS_OP:
result = " >= ";
break;
case GREATER_OP:
result = " > ";
break;
case NONGREATER_OP:
result = " <= ";
break;
}
return result;
}
@Override
public void accept(PredicateVisitor pv) {
pv.visit(this);
}
@Override
public List<IPredicate> getInnerPredicates() {
return new ArrayList<IPredicate>();
}
}