package context.arch.intelligibility.expression;
import context.arch.intelligibility.DescriptiveExplainerDelegate;
/**
* This only deals with numeric values that can be subjected to inequalities.
* @author Brian Y. Lim
*/
public class Comparison<T extends Comparable<? super T>> extends Parameter<T> {
private static final long serialVersionUID = -3714993009026305198L;
public enum Relation {
NO_RELATION("no-relation"),
EQUALS("="),
NOT_EQUALS("is not"), // TODO consider not supporting this; just negate Equals; it is quite troublesome
LESS_THAN_OR_EQUAL("<="),
GREATER_THAN_OR_EQUAL(">="),
LESS_THAN("<"),
GREATER_THAN(">");
private String toString;
private Relation(String toString) {
this.toString = toString;
}
public static Relation toRelation(String relation) {
if (relation.equals(NO_RELATION.toString)) {
return Relation.NO_RELATION;
}
else if (relation.equals(EQUALS.toString)) {
return Relation.EQUALS;
}
else if (relation.equals(LESS_THAN_OR_EQUAL.toString)) {
return Relation.LESS_THAN_OR_EQUAL;
}
else if (relation.equals(GREATER_THAN_OR_EQUAL.toString)) {
return Relation.GREATER_THAN_OR_EQUAL;
}
else if (relation.equals(LESS_THAN.toString)) {
return Relation.LESS_THAN;
}
else if (relation.equals(GREATER_THAN.toString)) {
return Relation.GREATER_THAN;
}
else {
return Relation.NO_RELATION;
}
}
@Override
public String toString() {
return toString;
}
}
protected Relation relationship;
protected ComparableRange<T> range;
public Comparison(String name, T value, Relation relationship) {
super(name, value);
this.relationship = relationship;
range = new ComparableRange<T>(name);
range.setBound(value, relationship);
}
public static <T extends Comparable<? super T>> Comparison<T> instance(String name, T value, Relation relationship) {
return new Comparison<T>(name, value, relationship);
}
@Override
public Comparison<T> clone() {
return new Comparison<T>(name, value, relationship);
}
public boolean setBound(T bound, Relation relationship) {
return range.setBound(bound, relationship);
}
@SuppressWarnings("unchecked")
public boolean setRange(Comparison<?> other) {
return range.setRange(((Comparison<T>) other).range);
}
public Relation getRelationship() {
if (range.getMax() == null) {
return Negation.negateRelation(getRelationship1());
}
else {
if (range.isMaxInclusive()) { return Relation.LESS_THAN_OR_EQUAL; }
else { return Relation.LESS_THAN; }
}
}
public Relation getRelationship1() {
if (range.isMinInclusive()) { return Relation.LESS_THAN_OR_EQUAL; }
else { return Relation.LESS_THAN; }
}
@Override
public T getValue() {
if (range.getMax() == null) { return getValue1(); }
else { return range.getMax(); }
}
@SuppressWarnings("unchecked")
public T getValue1() {
T value1 = range.getMin();
return value1 != null ? value1 :
(T) new Double(Double.NEGATIVE_INFINITY); // TODO: this assumption that T is Double is bad
}
@SuppressWarnings("unchecked")
@Override
public boolean isSatisfiedBy(Expression other) {
if (other instanceof Comparison<?>) {
Comparison<? super T> c = (Comparison<? super T>) other;
return this.name.equals(c.name) &&
// compare range in range
this.range.containsRange(c.range);
}
else if (other instanceof Parameter<?>) {
Parameter<?> p = (Parameter<?>) other;
return this.name.equals(p.name) &&
// different from Parameter, by checking if in range
this.range.containsValue((Comparable<? super T>) p.getValue());
}
else {
return false;
}
}
@Override
public String toString() {
return range.toString();
}
public String toPrettyString(DescriptiveExplainerDelegate descExplainer) {
return range.toPrettyString(descExplainer);
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object o) {
if (o instanceof Comparison<?>) {
Comparison<T> c2 = (Comparison<T>)o;
return this.name.equals(c2.name) &&
this.value.equals(c2.value) &&
this.relationship.equals(c2.relationship);
}
else {
return false;
}
}
}