java/cewolf-1.0/src/main/java/de/laures/cewolf/taglib/CewolfChartFactory.java
author František Kučera <franta-hg@frantovo.cz>
Sat, 28 Feb 2009 21:31:02 +0100
changeset 1 639991d0808a
permissions -rw-r--r--
Rozbalená knihovna verze 1.0
     1 /* ================================================================
     2  * Cewolf : Chart enabling Web Objects Framework
     3  * ================================================================
     4  *
     5  * Project Info:  http://cewolf.sourceforge.net
     6  * Project Lead:  Guido Laures (guido@laures.de);
     7  *
     8  * (C) Copyright 2002, by Guido Laures
     9  *
    10  * This library is free software; you can redistribute it and/or modify it under the terms
    11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
    12  * either version 2.1 of the License, or (at your option) any later version.
    13  *
    14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
    15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    16  * See the GNU Lesser General Public License for more details.
    17  *
    18  * You should have received a copy of the GNU Lesser General Public License along with this
    19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
    20  * Boston, MA 02111-1307, USA.
    21  */
    22 
    23 package de.laures.cewolf.taglib;
    24 
    25 import java.util.HashMap;
    26 import java.util.List;
    27 import java.util.Map;
    28 
    29 import org.jfree.chart.ChartFactory;
    30 import org.jfree.chart.JFreeChart;
    31 import org.jfree.chart.axis.CategoryAxis;
    32 import org.jfree.chart.axis.DateAxis;
    33 import org.jfree.chart.axis.NumberAxis;
    34 import org.jfree.chart.axis.ValueAxis;
    35 import org.jfree.chart.plot.CategoryPlot;
    36 import org.jfree.chart.plot.CombinedDomainXYPlot;
    37 import org.jfree.chart.plot.CombinedRangeXYPlot;
    38 import org.jfree.chart.plot.MeterPlot;
    39 import org.jfree.chart.plot.Plot;
    40 import org.jfree.chart.plot.PlotOrientation;
    41 import org.jfree.chart.plot.XYPlot;
    42 import org.jfree.chart.renderer.category.CategoryItemRenderer;
    43 import org.jfree.chart.renderer.xy.XYItemRenderer;
    44 import org.jfree.data.category.CategoryDataset;
    45 import org.jfree.data.category.IntervalCategoryDataset;
    46 import org.jfree.data.general.Dataset;
    47 import org.jfree.data.general.PieDataset;
    48 import org.jfree.data.general.ValueDataset;
    49 import org.jfree.data.xy.IntervalXYDataset;
    50 import org.jfree.data.xy.OHLCDataset;
    51 import org.jfree.data.xy.WindDataset;
    52 import org.jfree.data.xy.XYDataset;
    53 import org.jfree.data.xy.XYZDataset;
    54 
    55 import de.laures.cewolf.ChartValidationException;
    56 import de.laures.cewolf.DatasetProduceException;
    57 
    58 /**
    59  * Chart factory creates Jfreechart instances. To add a new factory use the
    60  * <code>
    61  * 		CewolfChartFactory.registerFactory(new CewolfChartFactory() {...});
    62  * </code>
    63  * method.
    64  *
    65  * @author  Guido Laures
    66  */
    67 public abstract class CewolfChartFactory implements ChartConstants, AxisConstants, LayoutConstants {
    68 
    69     // chart type string
    70   protected String chartType;
    71   // map contains registered factories, (String) chartType->CewolfChartFactory mappings
    72   private static Map factories = new HashMap();
    73 
    74     /** Creates a new instance of ChartFactory */
    75   protected CewolfChartFactory(String chartType) {
    76       this.chartType = chartType;
    77   }
    78 
    79   /**
    80    * Callback when the chart instance to be created.
    81      * @param title The title of chart
    82      * @param xAxisLabel label on x axis
    83      * @param yAxisLabel label on y axis
    84      * @param data The dataset to create chart for
    85      * @return The newly created JFreeChart instance
    86      *
    87      * @throws IncompatibleDatasetException If the incoming data is not compatible with this factory
    88      */
    89     public abstract JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data) throws IncompatibleDatasetException;
    90 
    91     //////////////// static part ///////////////////////
    92 
    93   /**
    94    * Register a new chart factory instance.
    95    * @param factory The factory to register
    96    */
    97   public static void registerFactory(CewolfChartFactory factory) {
    98       factories.put(factory.chartType, factory);
    99   }
   100 
   101   private static final int getChartTypeConstant(String type) {
   102     final int res = ChartTypes.typeList.indexOf(type.toLowerCase());
   103     if (res < 0) {
   104       throw new RuntimeException("unsupported chart type " + type);
   105     }
   106     return res;
   107   }
   108 
   109   private static final int getLayoutConstant(String layout) {
   110     return LayoutTypes.typeList.indexOf(layout.toLowerCase());
   111   }
   112   
   113   static {
   114     // histogram chart type
   115     registerFactory(new CewolfChartFactory("histogram") {
   116 	    public JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data) throws IncompatibleDatasetException {
   117 	        check(data, IntervalXYDataset.class, this.chartType);
   118 	        return ChartFactory.createHistogram(title, xAxisLabel, yAxisLabel, (IntervalXYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   119 	     }
   120     });
   121   }
   122 
   123   public static JFreeChart getChartInstance(String chartType, String title, String xAxisLabel, String yAxisLabel, Dataset data) throws ChartValidationException {
   124       // first check the dynamically registered chart types
   125       CewolfChartFactory factory = (CewolfChartFactory) factories.get(chartType);
   126       if (factory != null) {
   127           // custom factory found, use it
   128           return factory.getChartInstance(title, xAxisLabel, yAxisLabel, data);
   129       }
   130 
   131     switch (getChartTypeConstant(chartType)) {
   132       case XY :
   133         check(data, XYDataset.class, chartType);
   134         return ChartFactory.createXYLineChart(title, xAxisLabel, yAxisLabel, (XYDataset) data, PlotOrientation.VERTICAL, true, true, true);
   135       case PIE :
   136         check(data, PieDataset.class, chartType);
   137         return ChartFactory.createPieChart(title, (PieDataset) data, true, true, true);
   138       case AREA_XY :
   139         check(data, XYDataset.class, chartType);
   140         return ChartFactory.createXYAreaChart(title, xAxisLabel, yAxisLabel, (XYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   141       case SCATTER :
   142         check(data, XYDataset.class, chartType);
   143         return ChartFactory.createScatterPlot(title, xAxisLabel, yAxisLabel, (XYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   144       case AREA :
   145         check(data, CategoryDataset.class, chartType);
   146         return ChartFactory.createAreaChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   147       case HORIZONTAL_BAR :
   148         check(data, CategoryDataset.class, chartType);
   149         return ChartFactory.createBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.HORIZONTAL, true, false, false);
   150       case HORIZONTAL_BAR_3D :
   151         check(data, CategoryDataset.class, chartType);
   152         return ChartFactory.createBarChart3D(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.HORIZONTAL, true, false, false);
   153       case LINE :
   154         check(data, CategoryDataset.class, chartType);
   155         return ChartFactory.createLineChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   156       case STACKED_HORIZONTAL_BAR :
   157         check(data, CategoryDataset.class, chartType);
   158         return ChartFactory.createStackedBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.HORIZONTAL, true, false, false);
   159       case STACKED_VERTICAL_BAR :
   160         check(data, CategoryDataset.class, chartType);
   161         return ChartFactory.createStackedBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   162       case STACKED_VERTICAL_BAR_3D :
   163         check(data, CategoryDataset.class, chartType);
   164         return ChartFactory.createStackedBarChart3D(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   165       case VERTICAL_BAR :
   166         check(data, CategoryDataset.class, chartType);
   167         return ChartFactory.createBarChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   168       case VERTICAL_BAR_3D :
   169         check(data, CategoryDataset.class, chartType);
   170         return ChartFactory.createBarChart3D(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   171       case TIME_SERIES :
   172         check(data, XYDataset.class, chartType);
   173         return ChartFactory.createTimeSeriesChart(title, xAxisLabel, yAxisLabel, (XYDataset) data, true, false, false);
   174       case CANDLE_STICK :
   175         check(data, OHLCDataset.class, chartType);
   176         return ChartFactory.createCandlestickChart(title, xAxisLabel, yAxisLabel, (OHLCDataset) data, true);
   177       case HIGH_LOW :
   178         check(data, OHLCDataset.class, chartType);
   179         return ChartFactory.createHighLowChart(title, xAxisLabel, yAxisLabel, (OHLCDataset) data, true);
   180       case GANTT :
   181         check(data, IntervalCategoryDataset.class, chartType);
   182         return ChartFactory.createGanttChart(title, xAxisLabel, yAxisLabel, (IntervalCategoryDataset) data, true, false, false);
   183       case WIND :
   184         check(data, WindDataset.class, chartType);
   185         return ChartFactory.createWindPlot(title, xAxisLabel, yAxisLabel, (WindDataset) data, true, false, false);
   186       //case SIGNAL :
   187       //  check(data, SignalsDataset.class, chartType);
   188       //  return ChartFactory.createSignalChart(title, xAxisLabel, yAxisLabel, (SignalsDataset) data, true);
   189       case VERRTICAL_XY_BAR :
   190         check(data, IntervalXYDataset.class, chartType);
   191         return ChartFactory.createXYBarChart(title, xAxisLabel, true,yAxisLabel, (IntervalXYDataset) data, PlotOrientation.VERTICAL, true, false, false);
   192       case PIE_3D :
   193         check(data, PieDataset.class, chartType);
   194         return ChartFactory.createPieChart3D(title, (PieDataset) data, true, false, false);
   195       case METER :
   196         check(data, ValueDataset.class, chartType);
   197         MeterPlot plot = new MeterPlot((ValueDataset) data);
   198         JFreeChart chart = new JFreeChart(title, plot);
   199         return chart;
   200       case STACKED_AREA :
   201         check(data, CategoryDataset.class, chartType);
   202         return ChartFactory.createStackedAreaChart(title, xAxisLabel, yAxisLabel, (CategoryDataset) data, PlotOrientation.VERTICAL, true, false, false);
   203       case BUBBLE :
   204         check(data, XYZDataset.class, chartType);
   205         return ChartFactory.createBubbleChart(title, xAxisLabel, yAxisLabel, (XYZDataset) data, PlotOrientation.VERTICAL, true, false, false);
   206       default :
   207         throw new UnsupportedChartTypeException(chartType + " is not supported.");
   208     }
   209   }
   210 
   211     public static JFreeChart getOverlaidChartInstance(String chartType, String title, String xAxisLabel, String yAxisLabel, int xAxisType, int yAxisType, List plotDefinitions)
   212     throws ChartValidationException, DatasetProduceException {
   213     final int chartTypeConst = getChartTypeConstant(chartType);
   214     final AxisFactory axisFactory = AxisFactory.getInstance();
   215     switch (chartTypeConst) {
   216       case OVERLAY_XY :
   217         ValueAxis domainAxis = (ValueAxis) axisFactory.createAxis(ORIENTATION_HORIZONTAL, xAxisType, xAxisLabel);
   218         // get main plot
   219         PlotDefinition mainPlotDef = (PlotDefinition) plotDefinitions.get(0);
   220         check((Dataset) mainPlotDef.getDataset(), XYDataset.class, chartType);
   221         XYPlot plot = (XYPlot) mainPlotDef.getPlot(chartTypeConst);
   222         plot.setDomainAxis(domainAxis);
   223         plot.setRangeAxis((ValueAxis) axisFactory.createAxis(ORIENTATION_VERTICAL, yAxisType, yAxisLabel));
   224         //plot.setRenderer(new StandardXYItemRenderer());
   225         // add second and later datasets to main plot
   226         for (int plotidx = 1;plotidx<plotDefinitions.size();plotidx++) {
   227           PlotDefinition subPlotDef = (PlotDefinition) plotDefinitions.get(plotidx);
   228           check((Dataset) subPlotDef.getDataset(), XYDataset.class, chartType);
   229           plot.setDataset(plotidx, (XYDataset)subPlotDef.getDataset());
   230 
   231           int rendererIndex = PlotTypes.getRendererIndex(subPlotDef.getType());
   232           XYItemRenderer rend = (XYItemRenderer) PlotTypes.getRenderer(rendererIndex);
   233           plot.setRenderer(plotidx, rend);
   234         }
   235         return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
   236       case OVERLAY_CATEGORY ://added by lrh 2005-07-11
   237         CategoryAxis domainAxis2 = (CategoryAxis)axisFactory.createAxis(ORIENTATION_HORIZONTAL, xAxisType, xAxisLabel);
   238         // get main plot
   239         mainPlotDef = (PlotDefinition) plotDefinitions.get(0);
   240         check((Dataset) mainPlotDef.getDataset(), CategoryDataset.class, chartType);
   241         CategoryPlot plot2 = (CategoryPlot) mainPlotDef.getPlot(chartTypeConst);
   242         plot2.setDomainAxis(domainAxis2);
   243         plot2.setRangeAxis((ValueAxis)axisFactory.createAxis(ORIENTATION_VERTICAL, yAxisType, yAxisLabel));
   244         //plot.setRenderer(new StandardXYItemRenderer());
   245         // add second and later datasets to main plot
   246         for (int plotidx = 1;plotidx<plotDefinitions.size();plotidx++) {
   247           PlotDefinition subPlotDef = (PlotDefinition) plotDefinitions.get(plotidx);
   248           check((Dataset) subPlotDef.getDataset(), CategoryDataset.class, chartType);
   249           plot2.setDataset(plotidx, (CategoryDataset)subPlotDef.getDataset());
   250 
   251           int rendererIndex = PlotTypes.getRendererIndex(subPlotDef.getType()); 
   252           CategoryItemRenderer rend2 = (CategoryItemRenderer) PlotTypes.getRenderer(rendererIndex);
   253           plot2.setRenderer(plotidx, rend2);
   254         }
   255         return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot2, true);
   256       default :
   257         throw new UnsupportedChartTypeException(chartType + " is not supported.");
   258     }
   259   }
   260 
   261   // [tb]
   262   public static JFreeChart getCombinedChartInstance(String chartType, String title, String xAxisLabel, String yAxisLabel, List plotDefinitions, String layout)
   263     throws ChartValidationException, DatasetProduceException {
   264     final int chartTypeConst = getChartTypeConstant(chartType);
   265     switch (chartTypeConst) {
   266       case COMBINED_XY :
   267         final int layoutConst = getLayoutConstant(layout);
   268         Plot plot = null;
   269         switch (layoutConst) {
   270           case DOMAIN :
   271             ValueAxis domainAxis = new DateAxis(xAxisLabel);
   272             plot = new CombinedDomainXYPlot(domainAxis);
   273             for (int i = 0; i < plotDefinitions.size(); i++) {
   274               PlotDefinition pd = (PlotDefinition) plotDefinitions.get(i);
   275               check((Dataset) pd.getDataset(), XYDataset.class, chartType);
   276               XYPlot temp = (XYPlot) pd.getPlot(chartTypeConst);
   277               temp.setRangeAxis(new NumberAxis(pd.getYaxislabel()));
   278               ((CombinedDomainXYPlot) plot).add(temp);
   279             }
   280             return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
   281           case RANGE :
   282             ValueAxis rangeAxis = new NumberAxis(yAxisLabel);
   283             plot = new CombinedRangeXYPlot(rangeAxis);
   284             for (int i = 0; i < plotDefinitions.size(); i++) {
   285               PlotDefinition pd = (PlotDefinition) plotDefinitions.get(i);
   286               check((Dataset) pd.getDataset(), XYDataset.class, chartType);
   287               XYPlot temp = (XYPlot) pd.getPlot(chartTypeConst);
   288               temp.setDomainAxis(new DateAxis(pd.getXaxislabel()));
   289               ((CombinedRangeXYPlot) plot).add(temp);
   290             }
   291             return new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true);
   292           default :
   293             throw new AttributeValidationException(layout, " any value");
   294         }
   295       default :
   296         throw new UnsupportedChartTypeException(chartType);
   297     }
   298   }
   299 
   300   /**
   301    * Helper to check if the given dataset is the expected type.
   302    * @param data The dataset
   303    * @param clazz Expected type (class)
   304    * @param chartType The chart type string
   305    * @throws IncompatibleDatasetException If not the expected class
   306    */
   307   public static void check(Dataset data, Class clazz, String chartType) throws IncompatibleDatasetException {
   308     if (!clazz.isInstance(data)) {
   309       throw new IncompatibleDatasetException("Charts of type " + chartType + " " + "need datasets of type " + clazz.getName());
   310     }
   311   }
   312 
   313 }