package org.commcare.suite.model.graph;
import org.commcare.suite.model.Text;
import org.javarosa.core.model.condition.EvaluationContext;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.ExtWrapList;
import org.javarosa.core.util.externalizable.ExtWrapMap;
import org.javarosa.core.util.externalizable.Externalizable;
import org.javarosa.core.util.externalizable.PrototypeFactory;
import org.javarosa.xpath.XPathParseTool;
import org.javarosa.xpath.expr.XPathExpression;
import org.javarosa.xpath.parser.XPathSyntaxException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
/**
* Single series (line) on an xy graph.
*
* @author jschweers
*/
public class XYSeries implements Externalizable, Configurable {
private String mNodeSet;
private Hashtable<String, Text> mConfiguration;
// Some configurations need to be evaluated for each point (at the moment, only "bar color"
// We store the Text paths here and they will be evaluated each time a Graph is instantiated
// Once instantiated, the evaluated values are stored in mConfiguration for usage.
// When a graph is displayed again, the mConfiguration values will be wiped and replaced.
private Hashtable<String, Text> mPointConfiguration;
private String mX;
private String mY;
private XPathExpression mXParse;
private XPathExpression mYParse;
/*
* Deserialization only!
*/
public XYSeries() {
}
public XYSeries(String nodeSet) {
mNodeSet = nodeSet;
mConfiguration = new Hashtable<>();
mPointConfiguration = new Hashtable<>();
mPointConfiguration.put("bar-color", new Text());
}
public String getNodeSet() {
return mNodeSet;
}
public String getX() {
return mX;
}
public void setX(String x) {
mX = x;
mXParse = null;
}
public String getY() {
return mY;
}
public void setY(String y) {
mY = y;
mYParse = null;
}
public void removeConfiguration(String key) {
mConfiguration.remove(key);
}
@Override
public void setConfiguration(String key, Text value) {
if (mPointConfiguration.keySet().contains(key)) {
mPointConfiguration.put(key, value);
} else {
mConfiguration.put(key, value);
}
}
@Override
public Text getConfiguration(String key) {
return mConfiguration.get(key);
}
public void setExpandedConfiguration(String key, Text value) {
mConfiguration.put(key, value);
}
public Enumeration getPointConfigurationKeys() {
return mPointConfiguration.keys();
}
public Text getPointConfiguration(String key) {
return mPointConfiguration.get(key);
}
@Override
public Enumeration getConfigurationKeys() {
return mConfiguration.keys();
}
@Override
public void readExternal(DataInputStream in, PrototypeFactory pf)
throws IOException, DeserializationException {
mX = ExtUtil.readString(in);
mY = ExtUtil.readString(in);
mNodeSet = ExtUtil.readString(in);
mConfiguration = (Hashtable<String, Text>)ExtUtil.read(in, new ExtWrapMap(String.class, Text.class), pf);
mPointConfiguration = (Hashtable<String, Text>)ExtUtil.read(in, new ExtWrapMap(String.class, Text.class), pf);
}
@Override
public void writeExternal(DataOutputStream out) throws IOException {
ExtUtil.writeString(out, mX);
ExtUtil.writeString(out, mY);
ExtUtil.writeString(out, mNodeSet);
ExtUtil.write(out, new ExtWrapMap(mConfiguration));
ExtUtil.write(out, new ExtWrapMap(mPointConfiguration));
}
/*
* Parse all not-yet-parsed functions in this object.
*/
protected void parse() throws XPathSyntaxException {
if (mXParse == null) {
mXParse = parse(mX);
}
if (mYParse == null) {
mYParse = parse(mY);
}
}
/*
* Helper function to parse a single piece of XPath.
*/
protected XPathExpression parse(String function) throws XPathSyntaxException {
if (function == null) {
return null;
}
return XPathParseTool.parseXPath("string(" + function + ")");
}
/*
* Get the actual x value within a given EvaluationContext.
*/
public String evaluateX(EvaluationContext context) throws XPathSyntaxException {
parse();
return evaluateExpression(mXParse, context);
}
/*
* Get the actual y value within a given EvaluationContext.
*/
public String evaluateY(EvaluationContext context) throws XPathSyntaxException {
parse();
return evaluateExpression(mYParse, context);
}
/*
* Helper for evaluateX and evaluateY.
*/
protected String evaluateExpression(XPathExpression expression, EvaluationContext context) {
if (expression != null) {
String value = (String)expression.eval(context.getMainInstance(), context);
if (value.length() > 0) {
return value;
}
}
return null;
}
}