/*
* AbstractComparison.java
*
* Created on July 5, 2001, 11:16 AM
*/
package context.arch.discoverer.query.comparison;
import context.arch.comm.DataObject;
import context.arch.comm.DataObjects;
/**
* Abstract class to represent a comparison to the discovery subscription and query system in the context toolkit.
* Comparisons could be simple like an equality test or a distance calculation.
* Comparisons may even be on objects of different classes, specified by the C1 and C2 type parameters.
*
* @param <C1> class of the first comparison entity
* @param <C2> class of the second comparison entity
*
* @author Agathe
* @author Brian Y. Lim
*/
public abstract class AbstractComparison<C1, C2> {
public static final String ABSTRACT_COMPARISON = "abComp";
/** Tag for the C1 generics class parameter of AbstractComparison */
public static final String ABSTRACT_COMPARISON_C1 = "abCompC1";
/** Tag for the C2 generics class parameter of AbstractComparison */
public static final String ABSTRACT_COMPARISON_C2 = "abCompC2";
/*
* c1 and c2 are a hack to be able to retain knowledge of which class C1 and C2 are at runtime, after generics erasure.
*/
private Class<C1> c1;
private Class<C2> c2;
public Class<?> getC1() { return c1; }
public Class<?> getC2() { return c2; }
/**
* The comparison type
*/
private String comparisonName;
/**
* Creates new AbstractComparison
*/
public AbstractComparison(String comparisonName,
Class<C1> c1, Class<C2> c2) {
this.comparisonName = comparisonName;
this.c1 = c1;
this.c2 = c2;
}
/**
* Returns the comparison name
*
* return String
*/
public String getComparisonName() {
return comparisonName;
}
/**
* Compares 2 objects
*
* @param o1 The first object
* @param o2 The second object
* @return boolean The result of the comparison
*/
public abstract Boolean compare(C1 o1, C2 o2);
public String toString(){
return getComparisonName();
}
public DataObject toDataObject() {
DataObjects v = new DataObjects();
// add parameter class types
v.add(new DataObject(ABSTRACT_COMPARISON_C1, getC1().getName()));
v.add(new DataObject(ABSTRACT_COMPARISON_C2, getC2().getName()));
DataObject data = new DataObject(
ABSTRACT_COMPARISON,
getComparisonName(),
v);
return data;
}
@SuppressWarnings("unchecked")
public static <C1,C2> AbstractComparison<C1,C2> fromDataObject(DataObject data) {
String c1 = data.getDataObject(ABSTRACT_COMPARISON_C1).getValue();
String c2 = data.getDataObject(ABSTRACT_COMPARISON_C2).getValue();
try {
return (AbstractComparison<C1, C2>)
AbstractComparison.fromDataObject(data,
// use Reflection to get classes
(Class<C1>) Class.forName(c1),
(Class<C2>) Class.forName(c2));
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
@SuppressWarnings("unchecked")
public static <C1,C2> AbstractComparison<C1,C2> fromDataObject(DataObject data, Class<C1> c1, Class<C2> c2) {
String name = data.getDataObject(AbstractComparison.ABSTRACT_COMPARISON).getValue();
/*
* Iterate through possibilities of ValueComparison
*/
for (ValueComparison.Comparison comparison : ValueComparison.Comparison.values()) {
if (name.equals(comparison.toString())) {
return (AbstractComparison<C1, C2>) ValueComparison.instance(comparison, c1);
}
}
/*
* Iterate through possibilities of AttributeComparison
*/
for (AttributeComparison.Comparison comparison : AttributeComparison.Comparison.values()) {
if (name.equals(comparison.toString())) {
return (AbstractComparison<C1, C2>) new AttributeComparison(comparison);
}
}
/*
* some other comparison type not defined by the existing library
*/
// use reflections to initialize
// TODO: this seems brittle
try {
AbstractComparison<C1,C2> instance =
(AbstractComparison<C1,C2>) Class.forName(name)
.getConstructor(c1,c2)
.newInstance();
return instance;
} catch (Exception e) {
e.printStackTrace();
return null;
}
/*
* As long as custom queries are checked as rule queries (vs. subscription queries)
* They do not seem to need to be initiated here
*/
// else if (name.startsWith(WithinThresholdComparison.WITHIN_THRESHOLD)){
// String thresholdStr = name.substring(name.lastIndexOf('_')+1); // format e.g.: WithinThreshold_class java.lang.Double_0.0018
// Number threshold = Double.parseDouble(thresholdStr);
// return new WithinThresholdComparison(threshold);
// }
// else if (name.startsWith(NotWithinThresholdComparison.NOT_WITHIN_THRESHOLD)){
// String thresholdStr = name.substring(name.lastIndexOf('_')+1); // format e.g.: NotWithinThreshold_class java.lang.Double_0.0018
// Number threshold = Double.parseDouble(thresholdStr);
// return new NotWithinThresholdComparison(threshold);
// }
}
}