Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.ow2.opensuit.xml.chart.XYChart Maven / Gradle / Ivy
/**
* Open SUIT - Simple User Interface Toolkit
*
* Copyright (c) 2009 EBM Websourcing, http://www.ebmwebsourcing.com/
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.ow2.opensuit.xml.chart;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.labels.XYToolTipGenerator;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.DefaultPolarItemRenderer;
import org.jfree.chart.renderer.xy.XYAreaRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.renderer.xy.XYStepAreaRenderer;
import org.jfree.chart.renderer.xy.XYStepRenderer;
import org.jfree.chart.urls.XYURLGenerator;
import org.jfree.data.xy.DefaultXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleInsets;
import org.ow2.opensuit.core.session.OpenSuitSession;
import org.ow2.opensuit.core.util.ReflectionHelper;
import org.ow2.opensuit.xml.base.action.IAction;
import org.ow2.opensuit.xml.base.binding.Expression;
import org.ow2.opensuit.xml.interfaces.IBeanProvider;
import org.ow2.opensuit.xmlmap.annotations.XmlAttribute;
import org.ow2.opensuit.xmlmap.annotations.XmlChild;
import org.ow2.opensuit.xmlmap.annotations.XmlDoc;
import org.ow2.opensuit.xmlmap.annotations.XmlElement;
import org.ow2.opensuit.xmlmap.interfaces.IInitializationSupport;
import org.ow2.opensuit.xmlmap.interfaces.IInstantiationContext;
@XmlElement
public class XYChart extends BaseChart implements IBeanProvider
{
@XmlDoc("The name of the serie contextual bean. " +
"This bean is available at render-time only. " +
"Default: $serie.")
@XmlAttribute(name="SerieVar", required=false)
private String serieVar= "$serie";
@XmlDoc("The name of the x value contextual bean. " +
"This bean is available at render-time only. " +
"Default: $x.")
@XmlAttribute(name="XVar", required=false)
private String xVar= "$x";
@XmlDoc("The name of the y value contextual bean. " +
"This bean is available at render-time only. " +
"Default: $y.")
@XmlAttribute(name="YVar", required=false)
private String yVar= "$y";
@XmlDoc("Determines the chart style. " +
"Default: XYLine.")
@XmlAttribute(name="Style", required=false)
private XYChartStyle style= XYChartStyle.XYLine;
@XmlDoc("Determines the chart orientation. " +
"Default: horizontal.")
@XmlAttribute(name="Orientation", required=false)
private Orientation orientation= Orientation.Horizontal;
@XmlDoc("Defines the x axis label.")
@XmlChild(name="XAxisLabel")
protected Expression xAxisLabel;
@XmlDoc("Defines the y axis label.")
@XmlChild(name="YAxisLabel")
protected Expression yAxisLabel;
@XmlDoc("Gives a vector of items representing x,y series to display.")
@XmlChild(name="Series")
protected Expression series;
@XmlDoc("Evaluates the name of a given serie. " +
"Supported contextual beans: $serie")
@XmlChild(name="SerieName")
protected Expression serieName;
@XmlDoc("Returns the x,y values of a given serie. " +
"The expected return type is double[2][]." +
"Must be an array with length 2, containing two arrays of equal length, the first containing the x-values and the second containing the y-values" +
"Supported contextual beans: $serie")
@XmlChild(name="SerieValues")
protected Expression serieValues;
@XmlDoc("Defines the tooltip for a given x,y value. " +
"Supported contextual beans: $serie, $x, $y")
@XmlChild(name = "ValueTooltip", required = false)
protected Expression valueTooltip;
@XmlDoc("Defines the action to perform when a given x,y value is clicked. " +
"Supported contextual beans: $serie, $x, $y")
@XmlChild(name = "OnClickValue", required = false)
protected IAction onClickValue;
private Type itemType;
private Class> itemClass;
public void initialize(IInitializationSupport initSupport, IInstantiationContext instContext)
{
super.initialize(initSupport, instContext);
if(initSupport.initialize(series))
{
itemClass = ReflectionHelper.getVectorElementClass(series.getGenericType());
if(itemClass == null)
{
initSupport.addValidationMessage(this, "IterateOn", IInitializationSupport.ERROR, "Expression 'IterateOn' must return vector data.");
}
else
{
itemType = ReflectionHelper.getVectorElementType(series.getGenericType());
// --- check itemValue return a double[][]
/*
if(serieValues != null && initSupport.initialize(serieValues))
{
if(!serieValues.isConvertible(Number.class))
{
initSupport.addValidationMessage(this, "SerieValues", IInitializationSupport.ERROR, "Expression 'SerieValues' must return a Number.");
}
else
{
valueType = serieValues.getGenericType();
valueClass = serieValues.getType();
}
}
*/
}
}
}
@Override
public Plot makePlot(HttpServletRequest request) throws Exception
{
// --- 1: make dataset
Collection> itemObjs = ReflectionHelper.obj2Collection(series.invoke(request));
if(itemObjs == null){
return null;
}
String xAxisLabel = this.xAxisLabel.invoke(request, String.class);
String yAxisLabel = this.yAxisLabel.invoke(request, String.class);
PlotOrientation orientation = this.orientation.getPlotOrientation();
DefaultXYDataset dataset = new DefaultXYDataset();
int i=0;
for(Object item : itemObjs)
{
// --- set iterator var
request.setAttribute(serieVar, item);
Key key = new Key();
key.item = item;
key.name = serieName.invoke(request, String.class);
key.index = i++;
double[][] values = (double[][])serieValues.invoke(request);
dataset.addSeries(key, values);
}
// --- 2: make plot
// Polar, Scatter, TimeSeries, XYArea, XYLine, XYStepArea, XYStep
if(style == XYChartStyle.Polar)
{
// return ChartFactory.createPolarChart(title, dataSet, showLegend, renderTooltips, renderUrls);
PolarPlot pplot = new PolarPlot();
pplot.setDataset(dataset);
NumberAxis rangeAxis = new NumberAxis();
rangeAxis.setAxisLineVisible(false);
rangeAxis.setTickMarksVisible(false);
rangeAxis.setTickLabelInsets(new RectangleInsets(0.0, 0.0, 0.0, 0.0));
pplot.setAxis(rangeAxis);
pplot.setRenderer(new DefaultPolarItemRenderer());
// --- no tooltip nor url
return pplot;
}
XYPlot plot = null;
if(style == XYChartStyle.Scatter)
{
// return ChartFactory.createScatterPlot(title, xAxisLabel, yAxisLabel, dataset, orientation.getPlotOrientation(), showLegend, renderTooltips, renderUrls);
NumberAxis xAxis = new NumberAxis(xAxisLabel);
xAxis.setAutoRangeIncludesZero(false);
NumberAxis yAxis = new NumberAxis(yAxisLabel);
yAxis.setAutoRangeIncludesZero(false);
plot = new XYPlot(dataset, xAxis, yAxis, null);
XYItemRenderer renderer = new XYLineAndShapeRenderer(false, true);
plot.setRenderer(renderer);
plot.setOrientation(orientation);
}
else if(style == XYChartStyle.TimeSeries)
{
// return ChartFactory.createTimeSeriesChart(title, xAxisLabel, yAxisLabel, dataset, showLegend, renderTooltips, renderUrls);
ValueAxis timeAxis = new DateAxis(xAxisLabel);
timeAxis.setLowerMargin(0.02); // reduce the default margins
timeAxis.setUpperMargin(0.02);
NumberAxis valueAxis = new NumberAxis(yAxisLabel);
valueAxis.setAutoRangeIncludesZero(false); // override default
plot = new XYPlot(dataset, timeAxis, valueAxis, null);
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false);
plot.setRenderer(renderer);
}
else if(style == XYChartStyle.XYArea)
{
// return ChartFactory.createXYAreaChart(title, xAxisLabel, yAxisLabel, dataset, orientation.getPlotOrientation(), showLegend, renderTooltips, renderUrls);
NumberAxis xAxis = new NumberAxis(xAxisLabel);
xAxis.setAutoRangeIncludesZero(false);
NumberAxis yAxis = new NumberAxis(yAxisLabel);
plot = new XYPlot(dataset, xAxis, yAxis, null);
plot.setOrientation(orientation);
plot.setForegroundAlpha(0.5f);
plot.setRenderer(new XYAreaRenderer(XYAreaRenderer.AREA));
}
else if(style == XYChartStyle.XYLine)
{
NumberAxis xAxis = new NumberAxis(xAxisLabel);
xAxis.setAutoRangeIncludesZero(false);
NumberAxis yAxis = new NumberAxis(yAxisLabel);
XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
plot = new XYPlot(dataset, xAxis, yAxis, renderer);
plot.setOrientation(orientation);
}
else if(style == XYChartStyle.XYStepArea)
{
// return ChartFactory.createXYStepAreaChart(title, xAxisLabel, yAxisLabel, dataset, orientation.getPlotOrientation(), showLegend, renderTooltips, renderUrls);
NumberAxis xAxis = new NumberAxis(xAxisLabel);
xAxis.setAutoRangeIncludesZero(false);
NumberAxis yAxis = new NumberAxis(yAxisLabel);
XYItemRenderer renderer = new XYStepAreaRenderer(XYStepAreaRenderer.AREA_AND_SHAPES);
plot = new XYPlot(dataset, xAxis, yAxis, null);
plot.setRenderer(renderer);
plot.setOrientation(orientation);
plot.setDomainCrosshairVisible(false);
plot.setRangeCrosshairVisible(false);
}
else // XYStep
{
// return ChartFactory.createXYStepChart(title, xAxisLabel, yAxisLabel, dataset, orientation.getPlotOrientation(), showLegend, renderTooltips, renderUrls);
DateAxis xAxis = new DateAxis(xAxisLabel);
NumberAxis yAxis = new NumberAxis(yAxisLabel);
yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
XYItemRenderer renderer = new XYStepRenderer();
plot = new XYPlot(dataset, xAxis, yAxis, null);
plot.setRenderer(renderer);
plot.setOrientation(orientation);
plot.setDomainCrosshairVisible(false);
plot.setRangeCrosshairVisible(false);
}
// --- 3: apply generators
// --- add the tooltip generator
if (valueTooltip != null)
{
plot.getRenderer().setBaseToolTipGenerator(new TooltipGenerator());
}
else
{
// --- apply default tooltip generator
plot.getRenderer().setBaseToolTipGenerator(new StandardXYToolTipGenerator());
}
// --- add the url generator
if (onClickValue != null){
plot.getRenderer().setURLGenerator(new URLGenerator());
}
return plot;
}
// ==========================================================================
// === Key
// ==========================================================================
private static class Key implements Comparable
{
private String name;
private Object item;
private int index;
public int compareTo(Key o)
{
return index - o.index;
}
@Override
public String toString()
{
return name;
}
@Override
public boolean equals(Object obj)
{
if(obj == null || !(obj instanceof Key)){
return false;
}
return item.equals(((Key)obj).item);
}
@Override
public int hashCode()
{
return item.hashCode();
}
}
// ==========================================================================
// === TooltipGenerator
// ==========================================================================
private class TooltipGenerator implements XYToolTipGenerator
{
public String generateToolTip(XYDataset dataset, int series, int item)
{
HttpServletRequest request = OpenSuitSession.getCurrentRequest();
Key serieKey = (Key) dataset.getSeriesKey(series);
Number x = dataset.getX(series, item);
Number y = dataset.getY(series, item);
// --- set contextual beans
request.setAttribute(serieVar, serieKey.item);
request.setAttribute(xVar, x);
request.setAttribute(yVar, y);
// --- then eval tooltip
try
{
return valueTooltip.invoke(request, String.class);
}
catch (Exception e)
{
logger.error("Error while evaluating item tooltip.", e);
return null;
}
}
}
// ==========================================================================
// === UrlGenerator
// ==========================================================================
private class URLGenerator implements XYURLGenerator
{
public String generateURL(XYDataset dataset, int series, int item)
{
HttpServletRequest request = OpenSuitSession.getCurrentRequest();
Key serieKey = (Key) dataset.getSeriesKey(series);
Number x = dataset.getX(series, item);
Number y = dataset.getY(series, item);
// --- set contextual beans
request.setAttribute(serieVar, serieKey.item);
request.setAttribute(xVar, x);
request.setAttribute(yVar, y);
// --- then eval url
try
{
return onClickValue.getURL(request, true);
}
catch (Exception e)
{
logger.error("Error while evaluating onclick action.", e);
return null;
}
}
}
// =================================================================================
// === IBeanProvider
// =================================================================================
@Override
public Class> getBeanType(String iName) throws UnresolvedBeanError
{
if(serieVar.equals(iName))
{
if(itemClass == null){
throw new UnresolvedBeanError();
}
return itemClass;
}
else if(xVar.equals(iName) || yVar.equals(iName))
{
return Number.class;
}
return super.getBeanType(iName);
}
@Override
public Type getBeanGenericType(String iName) throws UnresolvedBeanError
{
if(serieVar.equals(iName))
{
if(itemType == null){
throw new UnresolvedBeanError();
}
return itemType;
}
else if(xVar.equals(iName) || yVar.equals(iName))
{
return Number.class;
}
return super.getBeanGenericType(iName);
}
@Override
public Object getBeanValue(HttpServletRequest iRequest, String iName) throws Exception
{
if(serieVar.equals(iName)){
return iRequest.getAttribute(iName);
}else if(xVar.equals(iName) || yVar.equals(iName)){
return iRequest.getAttribute(iName);
}
return super.getBeanValue(iRequest, iName);
}
@Override
public List getBeanNames() {
List names = super.getBeanNames();
names.add(serieVar);
names.add(xVar);
names.add(yVar);
return names;
}
@Override
public String getBeanDescription(String name) {
if(serieVar.equals(name))
{
return "The <XYChart> series contextual bean. " +
"This bean is available at render-time only. " +
"Class: "+(itemClass == null ? "unresolved!" : itemClass.getName());
}
else if (xVar.equals(name))
{
return "The <XYChart> X contextual bean. " +
"This bean is available at render-time only. " +
"Class: java.lang.Number";
}
else if (yVar.equals(name))
{
return "The <XYChart> Y contextual bean. " +
"This bean is available at render-time only. " +
"Class: java.lang.Number";
}
// TODO Auto-generated method stub
return super.getBeanDescription(name);
}
}