package jas.hist;
import jas.util.xml.XMLNodeTraverser;
import jas.util.xml.XMLNodeTraverser.BadXMLException;
import java.util.StringTokenizer;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
/**
* Build a DataSource from a DOM node
*/
class Data2DTraverser extends XMLNodeTraverser
{
Data2DTraverser(Node node) throws BadXMLException
{
traverse(node);
}
protected void handleElement(Element node, String name) throws BadXMLException
{
if (name.equals("bins2d")) b2d = new Bins2DNodeTraverser(node);
else if (name.equals("points")) p2d = new Points2DNodeTraverser(node);
else if(name.equals("pointDataAxisAttributes")) paa[paxis++] = new PointDataAxisAttributesNodeTraverser(node);//bug? axis++ ???
else if (name.equals("binnedDataAxisAttributes")) baa[baxis++] = new BinnedDataAxisAttributesNodeTraverser(node);
else if (name.equals("class")) ct = new ClassNodeTraverser(node);
else if (name.equals("datasource")) ct = new DataSourceNodeTraverser(node);
else if (name.equals("statistics")) stats = new StatisticsTraverser(node);
else if (name.equals("style2d")) {
if(type.equals("scatter2d")){
JASHistScatterPlotStyle scatstyle=new JASHistScatterPlotStyle();
this.style = scatstyle;
scst.traverse(node,scatstyle);
}
else if(type.equals("histogram2d")) st.traverse(node,style=new JASHist2DHistogramStyle());
else throw new BadXMLException("type attribute for data2d element must be scatter2d of histogram2d.");
}
else super.handleElement(node,name);
}
protected void handleAttributeNode(Attr node, String name, String value) throws BadXMLException
{
if (name.equals("type")) type = value;
else if (name.equals("name")) refName = value;
else super.handleAttributeNode(node,name,value);
}
DataSource getDataSource() throws BadXMLException
{
if (ct != null) return ct.getDataSource();
else if(b2d != null) return new XML2DHistDataSource(b2d,baa[0],baa[1],stats);
else return new XML2DScatterDataSource(paa[0].getType(),paa[1].getType(),p2d.getTitle(),p2d.getData());
}
JASHistStyle getStyle()
{
return style;
}
String getRefName()
{
return refName;
}
private String type;
private int paxis = 0;//will this counting work?
private int baxis = 0;//will this counting work?
private JASHist2DHistogramStyle style;
private ConstructorNodeTraverser ct = null;
private StatisticsTraverser stats = null;
private Style2DNodeTraverser st = new Style2DNodeTraverser();
private ScatterStyleNodeTraverser scst = new ScatterStyleNodeTraverser();
private Bins2DNodeTraverser b2d;
private BinnedDataAxisAttributesNodeTraverser[] baa = new BinnedDataAxisAttributesNodeTraverser[2];
private PointDataAxisAttributesNodeTraverser[] paa = new PointDataAxisAttributesNodeTraverser[2];
private Points2DNodeTraverser p2d;
private String refName;
}
class Bins2DNodeTraverser extends XMLNodeTraverser
{
Bins2DNodeTraverser(Node node) throws BadXMLException
{
traverse(node);
}
protected void handleAttributeNode(Attr node, String name, String value) throws BadXMLException
{
if (name.equals("title")) title = value;
else if (name.equals("xSize")) xSize = toInt(value);
else if (name.equals("ySize")) ySize = toInt(value);
else super.handleAttributeNode(node,name,value);
}
protected void handleTextNode(Text node, String name) throws BadXMLException
{
StringTokenizer lineTokens = new StringTokenizer(node.getData(),"\n\r");
int lines = lineTokens.countTokens();
if (lines < xSize * ySize || lines > xSize*ySize + 1) throw new BadXMLException("Inconsistent data length for bins2d (lines="+lines+")");
int x = 0;
int y = 0;
for (int l=0; l<xSize*ySize; l++)
{
StringTokenizer valueTokens = new StringTokenizer(lineTokens.nextToken().trim(),",");
int n = valueTokens.countTokens();
if (data == null) data = new double[n][xSize][ySize];
else if (n != data.length) throw new BadXMLException("Inconsistent number of entries in bins2d data at line "+l);
for (int i=0; i<n; i++) data[i][x][y] = toDouble(valueTokens.nextToken());
if (++y == ySize) { y = 0; x++; }
}
}
String getTitle()
{
return title;
}
double[][][] getData()
{
return data;
}
private String title;
private double[][][] data;
private int xSize, ySize;
}
class XML2DHistDataSource implements Rebinnable2DHistogramData, HasStatistics
{
XML2DHistDataSource(Bins2DNodeTraverser b2d,
BinnedDataAxisAttributesNodeTraverser xba,
BinnedDataAxisAttributesNodeTraverser yba, Statistics stats) throws BadXMLException
{
this.xba = xba;
this.yba = yba;
this.b2d = b2d;
this.stats =stats;
}
public double[][][] rebin(int xbins, double xmin, double xmax,
int ybins, double ymin, double ymax,
boolean wantErrors, boolean hurry, boolean xxx)
{
return b2d.getData();
}
public double getXMin()
{
return xba.getMin();
}
public double getXMax()
{
return xba.getMax();
}
public double getYMin()
{
return yba.getMin();
}
public double getYMax()
{
return yba.getMax();
}
public int getXBins()
{
return b2d.getData()[0].length;
}
public int getYBins()
{
return b2d.getData()[0][0].length;
}
public boolean isRebinnable()
{
return false;
}
public int getXAxisType()
{
return xba.getType();
}
public int getYAxisType()
{
return yba.getType();
}
public String[] getXAxisLabels()
{
return null;
}
public String[] getYAxisLabels()
{
return null;
}
public String getTitle()
{
return b2d.getTitle();
}
public Statistics getStatistics()
{
return stats;
}
private BinnedDataAxisAttributesNodeTraverser xba;
private BinnedDataAxisAttributesNodeTraverser yba;
private Bins2DNodeTraverser b2d;
private Statistics stats;
}