package context.arch.discoverer.query;
import java.util.List;
import context.arch.comm.DataObject;
import context.arch.comm.DataObjects;
import context.arch.discoverer.component.AbstractElement;
import context.arch.discoverer.query.comparison.AbstractComparison;
/**
* QueryItem that can handle multiple dimensions (or attributes or element), rather than just one.
* Useful for cases such as calculating distance based on latitude and longitude,
* with a third attribute for error margin.
*
* TODO: rename to MultiQueryItem?
*
* @author Brian Y. Lim
*
*/
public abstract class RuleQueryItemND<C1,C2> extends AbstractQueryItem<C1,C2> {
private static final long serialVersionUID = -3647103054483435901L;
/**
* Stores internally as an array of abstract elements.
* Up to subclasses to make sense of it with specifics.
*/
protected AbstractElement<?,?,?>[] elementsToMatch;
protected AbstractComparison<C1,C2> comparison;
public RuleQueryItemND(AbstractComparison<C1,C2> comparison, AbstractElement<?,?,?> ... elements) {
this.elementsToMatch = elements;
this.comparison = comparison;
}
public AbstractElement<?,?,?>[] getElementsToMatch() {
return elementsToMatch;
}
public AbstractComparison<C1,C2> getComparison() {
return comparison;
}
public abstract String getName();
@Override
public DataObject toDataObject() {
DataObjects v = new DataObjects();
// add comparison first
DataObject comp = comparison.toDataObject ();
v.add (comp);
// then add elements as remainder
for (AbstractElement<?,?,?> elementToMatch : elementsToMatch) {
DataObject elementToMatchDO = elementToMatch.toDataObject ();
v.add (elementToMatchDO);
}
return new DataObject(getName(), v);
}
/**
* Maybe use this as a reference implementation for subclasses to override.
* @param data
* @return
*/
public static AbstractQueryItem<?,?> fromDataObject(DataObject data) {
String name = data.getName();
AbstractComparison<?,?> comp = getComparison(data);
AbstractElement<?,?,?>[] elementsToMatch = getElementsToMatch(data);
return RuleQueryItemND.factory(name, comp, elementsToMatch);
}
public static AbstractQueryItem<?,?> factory(String name, AbstractComparison<?,?> comparison, AbstractElement<?,?,?> ... elements) {
assert false; // I don't expect this to be called if not used in subscription
System.out.println("QueryItemND.factory name: " + name);
return null; // TODO: do I need to implement this?
}
@Override
public String toString(){
String s = "QueryItemND : ";
for (AbstractElement<?,?,?> elementToMatch : elementsToMatch) {
s += elementToMatch.toString() + " ";
}
s += comparison.toString();
return s;
}
/* -------------------------------------------------------------------------------------------
* Convenience methods
* These methods can be used by subclasses to retrieve the object from a DataObject.
* ------------------------------------------------------------------------------------------- */
protected static AbstractComparison<?,?> getComparison(DataObject data) {
DataObject compDO = data.getDataObject(AbstractComparison.ABSTRACT_COMPARISON);
AbstractComparison<?,?> comp = AbstractComparison.fromDataObject(compDO);
return comp;
}
protected static AbstractElement<?,?,?>[] getElementsToMatch(DataObject data) {
List<DataObject> descDOs = data.getDataObjects(AbstractElement.ABSTRACT_DESCRIPTION_ELEMENT);
AbstractElement<?,?,?>[] elementsToMatch = new AbstractElement[descDOs.size()];
for (int i = 0; i < elementsToMatch.length; i++) {
elementsToMatch[i] = AbstractElement.fromDataObject(descDOs.get(i));
}
return elementsToMatch;
}
}