package hep.aida.web.taglib; import hep.aida.IAnalysisFactory; import hep.aida.IDataPoint; import hep.aida.IDataPointSet; import hep.aida.IDataPointSetFactory; import hep.aida.ITree; import hep.aida.ITreeFactory; import hep.aida.ITuple; import hep.aida.web.taglib.util.PlotUtils; import jas.hist.Rebinnable1DHistogramData; import javax.servlet.jsp.JspException; import javax.servlet.jsp.PageContext; /** * The implementation class for all {@link DataPointSetTag}classes. * * @author The AIDA Team @ SLAC * */ public class DataPointSetTagSupport implements DataPointSetTag { private String var; private String scope = "page"; private Object tuple; private String xAxisColumn; private String yAxisColumn; private String title = null; private IAnalysisFactory analysisFactory = IAnalysisFactory.create(); private ITreeFactory treeFactory = analysisFactory.createTreeFactory(); public void doStartTag() throws JspException { if (var == null || var.length() == 0) { throw new JspException("var must not be null"); } if (tuple == null) { throw new JspException("tuple must not be null"); } if (xAxisColumn == null || xAxisColumn.length() == 0) { throw new JspException("xAxisColumn must not be null"); } if (yAxisColumn == null || yAxisColumn.length() == 0) { throw new JspException("yAxisColumn must not be null"); } } public void doEndTag(PageContext pageContext) throws JspException { String scopeName = getScope(); if (scopeName == null) { scopeName = "page"; } int scope = PlotUtils.getScope(scopeName); ITuple ntuple = null; if (tuple instanceof ITuple) { ntuple = (ITuple) tuple; } else if (tuple instanceof String) { // If tuple is a string, then search all JSP scopes for a // an ITuple with that name. String attributeName = (String) tuple; ntuple = findTuple(attributeName, pageContext); if (ntuple == null) { throw new JspException("Could not fined tuple " + tuple); } } else { // We don't know how to handle objects of this type. throw new JspException("don't know how to handle query " + tuple); } String dataPointSetPath = getVar(); String dataPointSetTitle = getVar(); if (getTitle() != null) dataPointSetTitle = getTitle(); Object dataPointSet; if (ntuple.columnType(ntuple.findColumn(xAxisColumn)).isPrimitive()) dataPointSet = toDataPointSet(ntuple, dataPointSetPath, dataPointSetTitle, xAxisColumn, yAxisColumn); else dataPointSet = toDataSource(ntuple, dataPointSetTitle, xAxisColumn, yAxisColumn); // Store the IDataPointSet in a JSP scope. pageContext.setAttribute(getVar(), dataPointSet, scope); } IDataPointSet toDataPointSet(ITuple tuple, String dataPointSetPath, String dataPointSetTitle, String xAxisColumn, String yAxisColumn) throws JspException { ITree tree = treeFactory.create(); IDataPointSetFactory dataPointSetFactory = analysisFactory .createDataPointSetFactory(tree); // Create a two dimensional IDataPointSet. IDataPointSet dataPointSet = dataPointSetFactory.create( dataPointSetPath, dataPointSetTitle, 2); int xAxisColumnIndex = tuple.findColumn(xAxisColumn); int yAxisColumnIndex = tuple.findColumn(yAxisColumn); tuple.start(); while (tuple.next()) { IDataPoint datapoint = dataPointSet.addPoint(); datapoint.coordinate(0).setValue( getTupleColumnAsDouble(tuple, xAxisColumnIndex, -1.0)); datapoint.coordinate(1).setValue( getTupleColumnAsDouble(tuple, yAxisColumnIndex, -1.0)); } return dataPointSet; } /** * Convert the next value of the column at the specified index in the * {@link ITuple}to a double if the column's type is a numeric type. A * numeric type is defined to be boolean, byte, character, short, int, long, * float or double. If the column's type is any other type, then the * specified default value is returned. A boolean value 'true' is converted * to 1.0, and a boolean 'false' is converted to 0.0. * * @param tuple * the {@link ITuple}to read the next value from * @param columnIndex * the column index (0-based) into the {@link ITuple} * @param defaultValue * the default value to use if the column at the specifed index * is not a numeric value * @return the value of the column at the specified index in the * {@link ITuple}converted to a double */ private double getTupleColumnAsDouble(ITuple tuple, int columnIndex, double defaultValue) { Class clazz = tuple.columnType(columnIndex); double value = defaultValue; if (Boolean.TYPE.equals(clazz)) { value = tuple.getBoolean(columnIndex) ? 1.0 : 0.0; } else if (Byte.TYPE.equals(clazz)) { value = tuple.getByte(columnIndex); } else if (Character.TYPE.equals(clazz)) { value = tuple.getChar(columnIndex); } else if (Short.TYPE.equals(clazz)) { value = tuple.getShort(columnIndex); } else if (Integer.TYPE.equals(clazz)) { value = tuple.getInt(columnIndex); } else if (Long.TYPE.equals(clazz)) { value = tuple.getLong(columnIndex); } else if (Float.TYPE.equals(clazz)) { value = tuple.getFloat(columnIndex); } else if (Double.TYPE.equals(clazz)) { value = tuple.getDouble(columnIndex); } return value; } Rebinnable1DHistogramData toDataSource(ITuple tuple, String dataPointSetTitle, String xAxisColumn, String yAxisColumn) throws JspException { int xAxisColumnIndex = tuple.findColumn(xAxisColumn); int yAxisColumnIndex = tuple.findColumn(yAxisColumn); int rows = tuple.rows(); String[] labels = new String[rows]; double[] yData = new double[rows]; tuple.start(); for (int i = 0; i < rows; i++) { tuple.next(); labels[i] = getTupleColumnAsString(tuple, xAxisColumnIndex); yData[i] = getTupleColumnAsDouble(tuple, yAxisColumnIndex, -1.0); } return new DataPointSetWithString(dataPointSetTitle, labels, yData); } private String getTupleColumnAsString(ITuple tuple, int columnIndex) { Class clazz = tuple.columnType(columnIndex); String value = "null"; if (String.class.equals(clazz)) { value = tuple.getString(columnIndex); } else if (Object.class.equals(clazz)) { value = tuple.getObject(columnIndex).toString(); } return value; } /* * (non-Javadoc) * * @see hep.aida.web.taglib.DataPointSetTagg#setVar(java.lang.String) */ public void setVar(String var) { this.var = var; } public String getVar() { return var; } /* * (non-Javadoc) * * @see hep.aida.web.taglib.DataPointSetTag#setScope(java.lang.String) */ public void setScope(String scope) { this.scope = scope; } public String getScope() { return scope; } /* * (non-Javadoc) * * @see hep.aida.web.taglib.DataPointSetTagg#setTuple(java.lang.Object) */ public void setTuple(Object tuple) { this.tuple = tuple; } public Object getTuple() { return tuple; } /* * (non-Javadoc) * * @see hep.aida.web.taglib.DataPointSetTag#setXaxisColumn(java.lang.String) */ public void setXaxisColumn(String xAxisColumn) { this.xAxisColumn = xAxisColumn; } public String getXaxisColumn() { return xAxisColumn; } /* * (non-Javadoc) * * @see hep.aida.web.taglib.DataPointSetTag#setYaxisColumn(java.lang.String) */ public void setYaxisColumn(String yAxisColumn) { this.yAxisColumn = yAxisColumn; } public String getYaxisColumn() { return yAxisColumn; } /* * (non-Javadoc) * * @see hep.aida.web.taglib.DataPointSetTag#setTitle(java.lang.String) */ public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } /** * Find a {@link ITuple}in a JSP scope under the given attribute name. If * nothing is found then return null. * * @param attributeName * the name of the {@link ITuple}in a JSP scope * @return the {@link ITuple}if it is found, otherwise null */ private ITuple findTuple(String attributeName, PageContext pageContext) { ITuple tuple = null; // There is a bug in ColdFusion MX 6.1 on JRun4 whereby a // request scope attribute exists but its value is always null. // Therefore, we simply search the scopes ourselves. // resultSet = (ResultSet) // pageContext.findAttribute(attributeName); int[] scope = { PageContext.PAGE_SCOPE, PageContext.REQUEST_SCOPE, PageContext.SESSION_SCOPE, PageContext.APPLICATION_SCOPE }; for (int i = 0; i < scope.length; ++i) { tuple = (ITuple) pageContext.getAttribute(attributeName, scope[i]); if (tuple != null) { break; } } return tuple; } /** * Private class for dataPointSets with string as axis. * */ private class DataPointSetWithString implements Rebinnable1DHistogramData { private String[] xLabels; private double[] yData; private String title; DataPointSetWithString(String title, String[] xLabels, double[] yData) { this.yData = yData; this.xLabels = xLabels; this.title = title; } public String[] getAxisLabels() { return xLabels; } public int getAxisType() { return Rebinnable1DHistogramData.STRING; } public int getBins() { return getAxisLabels().length; } public double getMax() { return getBins(); } public double getMin() { return 0; } public String getTitle() { return title; } public boolean isRebinnable() { return false; } public double[][] rebin(int param, double param1, double param2, boolean param3, boolean param4) { return new double[][] { yData }; } } }