java/cewolf-1.0/src/main/java/de/laures/cewolf/taglib/CewolfChartFactory.java
changeset 1 639991d0808a
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/java/cewolf-1.0/src/main/java/de/laures/cewolf/taglib/CewolfChartFactory.java	Sat Feb 28 21:31:02 2009 +0100
     1.3 @@ -0,0 +1,313 @@
     1.4 +/* ================================================================
     1.5 + * Cewolf : Chart enabling Web Objects Framework
     1.6 + * ================================================================
     1.7 + *
     1.8 + * Project Info:  http://cewolf.sourceforge.net
     1.9 + * Project Lead:  Guido Laures (guido@laures.de);
    1.10 + *
    1.11 + * (C) Copyright 2002, by Guido Laures
    1.12 + *
    1.13 + * This library is free software; you can redistribute it and/or modify it under the terms
    1.14 + * of the GNU Lesser General Public License as published by the Free Software Foundation;
    1.15 + * either version 2.1 of the License, or (at your option) any later version.
    1.16 + *
    1.17 + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
    1.18 + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    1.19 + * See the GNU Lesser General Public License for more details.
    1.20 + *
    1.21 + * You should have received a copy of the GNU Lesser General Public License along with this
    1.22 + * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    1.23 + * Boston, MA 02111-1307, USA.
    1.24 + */
    1.25 +
    1.26 +package de.laures.cewolf.taglib;
    1.27 +
    1.28 +import java.util.HashMap;
    1.29 +import java.util.List;
    1.30 +import java.util.Map;
    1.31 +
    1.32 +import org.jfree.chart.ChartFactory;
    1.33 +import org.jfree.chart.JFreeChart;
    1.34 +import org.jfree.chart.axis.CategoryAxis;
    1.35 +import org.jfree.chart.axis.DateAxis;
    1.36 +import org.jfree.chart.axis.NumberAxis;
    1.37 +import org.jfree.chart.axis.ValueAxis;
    1.38 +import org.jfree.chart.plot.CategoryPlot;
    1.39 +import org.jfree.chart.plot.CombinedDomainXYPlot;
    1.40 +import org.jfree.chart.plot.CombinedRangeXYPlot;
    1.41 +import org.jfree.chart.plot.MeterPlot;
    1.42 +import org.jfree.chart.plot.Plot;
    1.43 +import org.jfree.chart.plot.PlotOrientation;
    1.44 +import org.jfree.chart.plot.XYPlot;
    1.45 +import org.jfree.chart.renderer.category.CategoryItemRenderer;
    1.46 +import org.jfree.chart.renderer.xy.XYItemRenderer;
    1.47 +import org.jfree.data.category.CategoryDataset;
    1.48 +import org.jfree.data.category.IntervalCategoryDataset;
    1.49 +import org.jfree.data.general.Dataset;
    1.50 +import org.jfree.data.general.PieDataset;
    1.51 +import org.jfree.data.general.ValueDataset;
    1.52 +import org.jfree.data.xy.IntervalXYDataset;
    1.53 +import org.jfree.data.xy.OHLCDataset;
    1.54 +import org.jfree.data.xy.WindDataset;
    1.55 +import org.jfree.data.xy.XYDataset;
    1.56 +import org.jfree.data.xy.XYZDataset;
    1.57 +
    1.58 +import de.laures.cewolf.ChartValidationException;
    1.59 +import de.laures.cewolf.DatasetProduceException;
    1.60 +
    1.61 +/**
    1.62 + * Chart factory creates Jfreechart instances. To add a new factory use the
    1.63 + * <code>
    1.64 + * 		CewolfChartFactory.registerFactory(new CewolfChartFactory() {...});
    1.65 + * </code>
    1.66 + * method.
    1.67 + *
    1.68 + * @author  Guido Laures
    1.69 + */
    1.70 +public abstract class CewolfChartFactory implements ChartConstants, AxisConstants, LayoutConstants {
    1.71 +
    1.72 +    // chart type string
    1.73 +  protected String chartType;
    1.74 +  // map contains registered factories, (String) chartType->CewolfChartFactory mappings
    1.75 +  private static Map factories = new HashMap();
    1.76 +
    1.77 +    /** Creates a new instance of ChartFactory */
    1.78 +  protected CewolfChartFactory(String chartType) {
    1.79 +      this.chartType = chartType;
    1.80 +  }
    1.81 +
    1.82 +  /**
    1.83 +   * Callback when the chart instance to be created.
    1.84 +     * @param title The title of chart
    1.85 +     * @param xAxisLabel label on x axis
    1.86 +     * @param yAxisLabel label on y axis
    1.87 +     * @param data The dataset to create chart for
    1.88 +     * @return The newly created JFreeChart instance
    1.89 +     *
    1.90 +     * @throws IncompatibleDatasetException If the incoming data is not compatible with this factory
    1.91 +     */
    1.92 +    public abstract JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data) throws IncompatibleDatasetException;
    1.93 +
    1.94 +    //////////////// static part ///////////////////////
    1.95 +
    1.96 +  /**
    1.97 +   * Register a new chart factory instance.
    1.98 +   * @param factory The factory to register
    1.99 +   */
   1.100 +  public static void registerFactory(CewolfChartFactory factory) {
   1.101 +      factories.put(factory.chartType, factory);
   1.102 +  }
   1.103 +
   1.104 +  private static final int getChartTypeConstant(String type) {
   1.105 +    final int res = ChartTypes.typeList.indexOf(type.toLowerCase());
   1.106 +    if (res < 0) {
   1.107 +      throw new RuntimeException("unsupported chart type " + type);
   1.108 +    }
   1.109 +    return res;
   1.110 +  }
   1.111 +
   1.112 +  private static final int getLayoutConstant(String layout) {
   1.113 +    return LayoutTypes.typeList.indexOf(layout.toLowerCase());
   1.114 +  }
   1.115 +  
   1.116 +  static {
   1.117 +    // histogram chart type
   1.118 +    registerFactory(new CewolfChartFactory("histogram") {
   1.119 +	    public JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data) throws IncompatibleDatasetException {
   1.120 +	        check(data, IntervalXYDataset.class, this.chartType);
   1.121 +	        return ChartFactory.createHistogram(title, xAxisLabel, yAxisLabel, (IntervalXYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.122 +	     }
   1.123 +    });
   1.124 +  }
   1.125 +
   1.126 +  public static JFreeChart getChartInstance(String chartType, String title, String xAxisLabel, String yAxisLabel, Dataset data) throws ChartValidationException {
   1.127 +      // first check the dynamically registered chart types
   1.128 +      CewolfChartFactory factory = (CewolfChartFactory) factories.get(chartType);
   1.129 +      if (factory != null) {
   1.130 +          // custom factory found, use it
   1.131 +          return factory.getChartInstance(title, xAxisLabel, yAxisLabel, data);
   1.132 +      }
   1.133 +
   1.134 +    switch (getChartTypeConstant(chartType)) {
   1.135 +      case XY :
   1.136 +        check(data, XYDataset.class, chartType);
   1.137 +        return ChartFactory.createXYLineChart(title, xAxisLabel, yAxisLabel, (XYDataset) data, PlotOrientation.VERTICAL, true, true, true);
   1.138 +      case PIE :
   1.139 +        check(data, PieDataset.class, chartType);
   1.140 +        return ChartFactory.createPieChart(title, (PieDataset) data, true, true, true);
   1.141 +      case AREA_XY :
   1.142 +        check(data, XYDataset.class, chartType);
   1.143 +        return ChartFactory.createXYAreaChart(title, xAxisLabel, yAxisLabel, (XYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.144 +      case SCATTER :
   1.145 +        check(data, XYDataset.class, chartType);
   1.146 +        return ChartFactory.createScatterPlot(title, xAxisLabel, yAxisLabel, (XYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.147 +      case AREA :
   1.148 +        check(data, CategoryDataset.class, chartType);
   1.149 +        return ChartFactory.createAreaChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.150 +      case HORIZONTAL_BAR :
   1.151 +        check(data, CategoryDataset.class, chartType);
   1.152 +        return ChartFactory.createBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.HORIZONTAL, true, false, false);
   1.153 +      case HORIZONTAL_BAR_3D :
   1.154 +        check(data, CategoryDataset.class, chartType);
   1.155 +        return ChartFactory.createBarChart3D(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.HORIZONTAL, true, false, false);
   1.156 +      case LINE :
   1.157 +        check(data, CategoryDataset.class, chartType);
   1.158 +        return ChartFactory.createLineChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.159 +      case STACKED_HORIZONTAL_BAR :
   1.160 +        check(data, CategoryDataset.class, chartType);
   1.161 +        return ChartFactory.createStackedBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.HORIZONTAL, true, false, false);
   1.162 +      case STACKED_VERTICAL_BAR :
   1.163 +        check(data, CategoryDataset.class, chartType);
   1.164 +        return ChartFactory.createStackedBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.165 +      case STACKED_VERTICAL_BAR_3D :
   1.166 +        check(data, CategoryDataset.class, chartType);
   1.167 +        return ChartFactory.createStackedBarChart3D(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.168 +      case VERTICAL_BAR :
   1.169 +        check(data, CategoryDataset.class, chartType);
   1.170 +        return ChartFactory.createBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.171 +      case VERTICAL_BAR_3D :
   1.172 +        check(data, CategoryDataset.class, chartType);
   1.173 +        return ChartFactory.createBarChart3D(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.174 +      case TIME_SERIES :
   1.175 +        check(data, XYDataset.class, chartType);
   1.176 +        return ChartFactory.createTimeSeriesChart(title, xAxisLabel, yAxisLabel, (XYDataset) data, true, false, false);
   1.177 +      case CANDLE_STICK :
   1.178 +        check(data, OHLCDataset.class, chartType);
   1.179 +        return ChartFactory.createCandlestickChart(title, xAxisLabel, yAxisLabel, (OHLCDataset) data, true);
   1.180 +      case HIGH_LOW :
   1.181 +        check(data, OHLCDataset.class, chartType);
   1.182 +        return ChartFactory.createHighLowChart(title, xAxisLabel, yAxisLabel, (OHLCDataset) data, true);
   1.183 +      case GANTT :
   1.184 +        check(data, IntervalCategoryDataset.class, chartType);
   1.185 +        return ChartFactory.createGanttChart(title, xAxisLabel, yAxisLabel, (IntervalCategoryDataset) data, true, false, false);
   1.186 +      case WIND :
   1.187 +        check(data, WindDataset.class, chartType);
   1.188 +        return ChartFactory.createWindPlot(title, xAxisLabel, yAxisLabel, (WindDataset) data, true, false, false);
   1.189 +      //case SIGNAL :
   1.190 +      //  check(data, SignalsDataset.class, chartType);
   1.191 +      //  return ChartFactory.createSignalChart(title, xAxisLabel, yAxisLabel, (SignalsDataset) data, true);
   1.192 +      case VERRTICAL_XY_BAR :
   1.193 +        check(data, IntervalXYDataset.class, chartType);
   1.194 +        return ChartFactory.createXYBarChart(title, xAxisLabel, true,yAxisLabel, (IntervalXYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.195 +      case PIE_3D :
   1.196 +        check(data, PieDataset.class, chartType);
   1.197 +        return ChartFactory.createPieChart3D(title, (PieDataset) data, true, false, false);
   1.198 +      case METER :
   1.199 +        check(data, ValueDataset.class, chartType);
   1.200 +        MeterPlot plot = new MeterPlot((ValueDataset) data);
   1.201 +        JFreeChart chart = new JFreeChart(title, plot);
   1.202 +        return chart;
   1.203 +      case STACKED_AREA :
   1.204 +        check(data, CategoryDataset.class, chartType);
   1.205 +        return ChartFactory.createStackedAreaChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.206 +      case BUBBLE :
   1.207 +        check(data, XYZDataset.class, chartType);
   1.208 +        return ChartFactory.createBubbleChart(title, xAxisLabel, yAxisLabel, (XYZDataset) data, PlotOrientation.VERTICAL, true, false, false);
   1.209 +      default :
   1.210 +        throw new UnsupportedChartTypeException(chartType + " is not supported.");
   1.211 +    }
   1.212 +  }
   1.213 +
   1.214 +    public static JFreeChart getOverlaidChartInstance(String chartType, String title, String xAxisLabel, String yAxisLabel, int xAxisType, int yAxisType, List plotDefinitions)
   1.215 +    throws ChartValidationException, DatasetProduceException {
   1.216 +    final int chartTypeConst = getChartTypeConstant(chartType);
   1.217 +    final AxisFactory axisFactory = AxisFactory.getInstance();
   1.218 +    switch (chartTypeConst) {
   1.219 +      case OVERLAY_XY :
   1.220 +        ValueAxis domainAxis = (ValueAxis) axisFactory.createAxis(ORIENTATION_HORIZONTAL, xAxisType, xAxisLabel);
   1.221 +        // get main plot
   1.222 +        PlotDefinition mainPlotDef = (PlotDefinition) plotDefinitions.get(0);
   1.223 +        check((Dataset) mainPlotDef.getDataset(), XYDataset.class, chartType);
   1.224 +        XYPlot plot = (XYPlot) mainPlotDef.getPlot(chartTypeConst);
   1.225 +        plot.setDomainAxis(domainAxis);
   1.226 +        plot.setRangeAxis((ValueAxis) axisFactory.createAxis(ORIENTATION_VERTICAL, yAxisType, yAxisLabel));
   1.227 +        //plot.setRenderer(new StandardXYItemRenderer());
   1.228 +        // add second and later datasets to main plot
   1.229 +        for (int plotidx = 1;plotidx<plotDefinitions.size();plotidx++) {
   1.230 +          PlotDefinition subPlotDef = (PlotDefinition) plotDefinitions.get(plotidx);
   1.231 +          check((Dataset) subPlotDef.getDataset(), XYDataset.class, chartType);
   1.232 +          plot.setDataset(plotidx, (XYDataset)subPlotDef.getDataset());
   1.233 +
   1.234 +          int rendererIndex = PlotTypes.getRendererIndex(subPlotDef.getType());
   1.235 +          XYItemRenderer rend = (XYItemRenderer) PlotTypes.getRenderer(rendererIndex);
   1.236 +          plot.setRenderer(plotidx, rend);
   1.237 +        }
   1.238 +        return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
   1.239 +      case OVERLAY_CATEGORY ://added by lrh 2005-07-11
   1.240 +        CategoryAxis domainAxis2 = (CategoryAxis)axisFactory.createAxis(ORIENTATION_HORIZONTAL, xAxisType, xAxisLabel);
   1.241 +        // get main plot
   1.242 +        mainPlotDef = (PlotDefinition) plotDefinitions.get(0);
   1.243 +        check((Dataset) mainPlotDef.getDataset(), CategoryDataset.class, chartType);
   1.244 +        CategoryPlot plot2 = (CategoryPlot) mainPlotDef.getPlot(chartTypeConst);
   1.245 +        plot2.setDomainAxis(domainAxis2);
   1.246 +        plot2.setRangeAxis((ValueAxis)axisFactory.createAxis(ORIENTATION_VERTICAL, yAxisType, yAxisLabel));
   1.247 +        //plot.setRenderer(new StandardXYItemRenderer());
   1.248 +        // add second and later datasets to main plot
   1.249 +        for (int plotidx = 1;plotidx<plotDefinitions.size();plotidx++) {
   1.250 +          PlotDefinition subPlotDef = (PlotDefinition) plotDefinitions.get(plotidx);
   1.251 +          check((Dataset) subPlotDef.getDataset(), CategoryDataset.class, chartType);
   1.252 +          plot2.setDataset(plotidx, (CategoryDataset)subPlotDef.getDataset());
   1.253 +
   1.254 +          int rendererIndex = PlotTypes.getRendererIndex(subPlotDef.getType()); 
   1.255 +          CategoryItemRenderer rend2 = (CategoryItemRenderer) PlotTypes.getRenderer(rendererIndex);
   1.256 +          plot2.setRenderer(plotidx, rend2);
   1.257 +        }
   1.258 +        return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot2, true);
   1.259 +      default :
   1.260 +        throw new UnsupportedChartTypeException(chartType + " is not supported.");
   1.261 +    }
   1.262 +  }
   1.263 +
   1.264 +  // [tb]
   1.265 +  public static JFreeChart getCombinedChartInstance(String chartType, String title, String xAxisLabel, String yAxisLabel, List plotDefinitions, String layout)
   1.266 +    throws ChartValidationException, DatasetProduceException {
   1.267 +    final int chartTypeConst = getChartTypeConstant(chartType);
   1.268 +    switch (chartTypeConst) {
   1.269 +      case COMBINED_XY :
   1.270 +        final int layoutConst = getLayoutConstant(layout);
   1.271 +        Plot plot = null;
   1.272 +        switch (layoutConst) {
   1.273 +          case DOMAIN :
   1.274 +            ValueAxis domainAxis = new DateAxis(xAxisLabel);
   1.275 +            plot = new CombinedDomainXYPlot(domainAxis);
   1.276 +            for (int i = 0; i < plotDefinitions.size(); i++) {
   1.277 +              PlotDefinition pd = (PlotDefinition) plotDefinitions.get(i);
   1.278 +              check((Dataset) pd.getDataset(), XYDataset.class, chartType);
   1.279 +              XYPlot temp = (XYPlot) pd.getPlot(chartTypeConst);
   1.280 +              temp.setRangeAxis(new NumberAxis(pd.getYaxislabel()));
   1.281 +              ((CombinedDomainXYPlot) plot).add(temp);
   1.282 +            }
   1.283 +            return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
   1.284 +          case RANGE :
   1.285 +            ValueAxis rangeAxis = new NumberAxis(yAxisLabel);
   1.286 +            plot = new CombinedRangeXYPlot(rangeAxis);
   1.287 +            for (int i = 0; i < plotDefinitions.size(); i++) {
   1.288 +              PlotDefinition pd = (PlotDefinition) plotDefinitions.get(i);
   1.289 +              check((Dataset) pd.getDataset(), XYDataset.class, chartType);
   1.290 +              XYPlot temp = (XYPlot) pd.getPlot(chartTypeConst);
   1.291 +              temp.setDomainAxis(new DateAxis(pd.getXaxislabel()));
   1.292 +              ((CombinedRangeXYPlot) plot).add(temp);
   1.293 +            }
   1.294 +            return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
   1.295 +          default :
   1.296 +            throw new AttributeValidationException(layout, " any value");
   1.297 +        }
   1.298 +      default :
   1.299 +        throw new UnsupportedChartTypeException(chartType);
   1.300 +    }
   1.301 +  }
   1.302 +
   1.303 +  /**
   1.304 +   * Helper to check if the given dataset is the expected type.
   1.305 +   * @param data The dataset
   1.306 +   * @param clazz Expected type (class)
   1.307 +   * @param chartType The chart type string
   1.308 +   * @throws IncompatibleDatasetException If not the expected class
   1.309 +   */
   1.310 +  public static void check(Dataset data, Class clazz, String chartType) throws IncompatibleDatasetException {
   1.311 +    if (!clazz.isInstance(data)) {
   1.312 +      throw new IncompatibleDatasetException("Charts of type " + chartType + " " + "need datasets of type " + clazz.getName());
   1.313 +    }
   1.314 +  }
   1.315 +
   1.316 +}