Taglib support for overlaid category plots?

Help
2006-07-06
2013-01-13
  • Dave Seagraves
    Dave Seagraves
    2006-07-06

    I am creating an overlaid chart with a bar char plot appearing behind a shapesandlines plot, both plotted against a category axis. The taglib documentation for <overlaidchart> says, for the "type" parameter, "In this version only overlaidxy is supported". Does this mean I cannot create an overlaid category chart with cewolf?

     
    • Zoltan Luspai
      Zoltan Luspai
      2006-07-10

      Hi,

      You can create an overlaid chart, but you have to build the whole chart now yourself; the tool does not give you a help for that. So if you've figured out how to do an overlaid-category chart in pure jfreechart code (like an java application), put that code in a factory method and register it, like:

          CewolfChartFactory.registerFactory(new CewolfChartFactory("histogram", IntervalXYDataset.class) {
              public JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data) throws IncompatibleDatasetException {
                  return ....
               }
          });

      This is a bit ugly though...
      Cheers,
      Zoltan

       
      • Dave Seagraves
        Dave Seagraves
        2006-07-20

        Zoltan,

        Thank you for your response, but with my limited experience with cewolf and jfreechart, I do not yet have enough information to go forward. Would you be kind enough to answer a few more questions?

        I believe I can follow the overlaid chart examples provided with the demo that comes with the JFreeChart Developer Guide to create the chart itself.

        Will I still use the cewolf XML to incorporate the chart into my jsp file?

        Do I still need the DataProducer and PostProcess methods? (It seems that the code for creating the chart that I got from the demo duplicates a lot of these functions.)

        Where does the code you suggested (CewolfChartFactory.registerFactory....) go, and how does it relate to my jsp?

        Thank you for your continued indulgence.

        Cheers,
        Dave

         
    • Zoltan Luspai
      Zoltan Luspai
      2006-07-27

      Hi,

      Sorry for the late reply; I've got busy these days.
      You say; you're able to crete your chart - that's great; you can recognize what you create there is a JFreeChart instance. Now the whole customized code which creates the JFreeChart instance can be integrated into the Cewolf charting by wrapping that code in a factory pattern , and registering it into the Cewolf.
      So for example you have a custom way of creating some chart, in a method, for example:

      JFreeChart createMyChart(DataSet data) {...};

      Then you can register this as a new "chart type" in cewolf, by:

      ----------------
      CewolfChartFactory.registerFactory(new CewolfChartFactory("myChartType", IntervalXYDataset.class) {
      public JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data) throws IncompatibleDatasetException {
      return createMyChart(data);
      }
      });
      ----------------

      By this call you registered a new chart type, which you can then use to create your custom chart any time, with the usual way, like:

      ----------------
      <cewolf:chart type="myChartType" title="" xaxislabel="">
        <cewolf:data>
          <cewolf:producer id="ganttData" />
          <cewolf:chartpostprocessor id="postProcessor" />
        </cewolf:data>
      </cewolf:chart>
      ----------------

      Everything else is works as usual; your data producer needed to produce your chart data, your chart post processor can customize the JFreeChart intance you've created in the createMyChart method, etc...

      So in short again:
      - you have a method to create custom JFreeChart
      - wrap it in a CewolfChartFactory factory method, and register ONCE before use in anywhere in your code (typically a static method will do)
      - use the new chart type as usual

      I hope that was clear.
      Cheers,
      Zoltan

       
      • Dave Seagraves
        Dave Seagraves
        2006-08-17

        Zoltan,

        Did you see my recent response (8/12)? I am surprised you have not responded. I had to do it in two posts (plus an ammendment) because it was too long. Could you have a look at it?

        Thanks,
        Dave

         
    • Dave Seagraves
      Dave Seagraves
      2006-08-09

      Hi Zoltan,

      Thanks again for the clarification.

      I am having compile problems with the suggested code:

      ----------------
      CewolfChartFactory.registerFactory(new CewolfChartFactory("myChartType",
      IntervalXYDataset.class) {
      public JFreeChart getChartInstance(String title, String xAxisLabel, String
      yAxisLabel, Dataset data) throws IncompatibleDatasetException {
      return createMyChart(data);
      }
      });
      ----------------

      Here is my implementation:

      ----------------
          CewolfChartFactory.registerFactory(new CewolfChartFactory("barOverlayXY", IntervalXYDataset.class)
          {
              public JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data)
              throws IncompatibleDatasetException
              {
                  return createChart(data);
              }
          });
      ----------------

      I have inserted this code into my JSP. At the beginning of the file, I have included the following line:

      <%@ page contentType="text/html; charset=iso-8859-1" language="java" import="java.io.*, java.util.*, de.laures.cewolf.taglib.CewolfChartFactory.*, org.jfree.chart.JFreeChart.*" %>

      In spite of this, the compiler does not recognize the variable CewolfChartFactory (used to invoke registerFactory) or the constructor CewolfChartFactory("barOverlayXY", IntervalXYDataset.class).

      As I look at the API documentation, it appears that the class CewolfChartFactory does not define a constructor, but rather methods get[...]ChartInstance. Furthermore, there is no mention of the method registerFactory.

      What am I missing?

      Cheers,
      Dave Seagraves

       
    • Zoltan Luspai
      Zoltan Luspai
      2006-08-10

      Hi,

      I think you will need to build the latest cewolf package for being able to use registerfactory. That code contains the necessary methods for registering a new factory, as can be seen here from the svn repository: http://svn.sourceforge.net/viewvc/cewolf/trunk/cewolf/src/main/java/de/laures/cewolf/taglib/CewolfChartFactory.java?revision=295&view=markup

      Also note that CewolfChartFactory is NOT a variable, but the CewolfChartFactor.registerFactory is a static call. So your import in JSP should rather be like:
      import=" ...
      de.laures.cewolf.taglib.*,
      de.laures.cewolf.taglib.CewolfChartFactory,
      ..."

      Regards,
      Zoltan

       
    • Dave Seagraves
      Dave Seagraves
      2006-08-12

      Hi Zoltan,

      I think I am almost there. For some reason, the software is not recognizing my newly defined chart type. When I try to run it, I get the error message:

      java.lang.RuntimeException raised:
      unsupported chart type barOverlayXY

      Can you tell from the sample below why the type is not being defined?

      Cheers,
      Dave

      Here is my JSP:

      <jsp:useBean id="SPRC_OverlaidBarChart" class="com.webfeetcreations.charting.SPRC_OverlaidBarChart"/>
      <jsp:useBean id="SPRC_APBarChartDP" class="com.webfeetcreations.charting.SPRC_APBarChartDP"/>
      <jsp:useBean id="SPRC_APLineChartDP" class="com.webfeetcreations.charting.SPRC_APLineChartDP"/>
      <jsp:useBean id="SPRC_APChartPP" class="com.webfeetcreations.charting.SPRC_APChartPP"/>
      <%
          CewolfChartFactory.registerFactory(new CewolfChartFactory("barOverlayXY", IntervalXYDataset.class)
          {
              public JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data)
              throws IncompatibleDatasetException
              {
                  return com.webfeetcreations.charting.SPRC_OverlaidBarChart.createChart("Goal Points", ap_goal, "Days Goal Met", ap_days_goal_met, schedule_dates);
              }
          });
      //    SPRC_OverlaidBarChart.registerBarSeries("Days Goal Met", schedule_dates, ap_days_goal_met);
      //    SPRC_OverlaidBarChart.registerLineSeries("Goal Points", schedule_dates, ap_goal);
          SPRC_APChartPP.addNameToTitle(name);
      %>
      <cewolf:overlaidchart
          id="AP"
          type="barOverlayXY"
          title="Activity Points Chart for "
          yaxislabel="Pounds"
          xaxistype="number">
              <cewolf:plot type="shapesandlines">
                  <cewolf:data>
                      <cewolf:producer id="SPRC_APLineChartDP"/>
                  </cewolf:data>
              </cewolf:plot>
              <cewolf:plot type="verticalbar">
                  <cewolf:data>
                      <cewolf:producer id="SPRC_APBarChartDP"/>
                  </cewolf:data>
              </cewolf:plot>
          <cewolf:chartpostprocessor id="SPRC_APChartPP"/>
      </cewolf:overlaidchart>
      <cewolf:img chartid="AP" renderer="cewolf" width="545" height="300">
      </cewolf:img>

      (I tried using the exact syntax you gave me:

      CewolfChartFactory.registerFactory(new CewolfChartFactory("barOverlayXY", IntervalXYDataset.class) {...});

      but this constructor is not recognized. The documentation at

      http://www.docjar.com/docs/api/de/laures/cewolf/taglib/CewolfChartFactory.html#registerFactory\(de.laures.cewolf.taglib.CewolfChartFactory)

      suggests that the second parameter of the constructor is not allowed.)

      (Continued in next post)

       
      • Dave Seagraves
        Dave Seagraves
        2006-08-12

        Oops, sorry, I meant to edit the JSP code in the 10:03 message. The actual syntax I am using for the registerFactory call is:

        CewolfChartFactory.registerFactory(new CewolfChartFactory("barOverlayXY")
        {
        public JFreeChart getChartInstance(String title, String xAxisLabel, String yAxisLabel, Dataset data)
        throws IncompatibleDatasetException
        {
        return com.webfeetcreations.charting.SPRC_OverlaidBarChart.createChart("Goal Points", ap_goal, "Days Goal Met", ap_days_goal_met, schedule_dates);

        }); 

         
    • Dave Seagraves
      Dave Seagraves
      2006-08-12

      (Continued from previous post)

      Here is the Java that creates the chart of type barOverlayXY:

      /* -------------------------
      * SPRC_OverlaidBarChart.java
      * -------------------------
      */

      package com.webfeetcreations.charting;

      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;

      import org.jfree.chart.JFreeChart;
      import org.jfree.chart.axis.CategoryAxis;
      import org.jfree.chart.axis.CategoryLabelPositions;
      import org.jfree.chart.axis.NumberAxis;
      import org.jfree.chart.axis.ValueAxis;
      import org.jfree.chart.labels.CategoryItemLabelGenerator;
      import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
      import org.jfree.chart.plot.CategoryPlot;
      import org.jfree.chart.plot.DatasetRenderingOrder;
      import org.jfree.chart.plot.PlotOrientation;
      import org.jfree.chart.renderer.category.BarRenderer;
      import org.jfree.chart.renderer.category.CategoryItemRenderer;
      import org.jfree.chart.renderer.category.LineAndShapeRenderer;
      import org.jfree.data.category.DefaultCategoryDataset;

      public class SPRC_OverlaidBarChart {

          static final Log log = LogFactory.getLog(SPRC_OverlaidBarChart.class);

          static protected DefaultCategoryDataset lineDataset = new DefaultCategoryDataset(){
              /**
               * @see java.lang.Object#finalize()
               */
              protected void finalize() throws Throwable {
                  super.finalize();
                  log.debug(this +" finalized.");
              }
          };
         
          static protected DefaultCategoryDataset barDataset = new DefaultCategoryDataset(){
              /**
               * @see java.lang.Object#finalize()
               */
              protected void finalize() throws Throwable {
                  super.finalize();
                  log.debug(this +" finalized.");
              }
          };

          /**
           *  Sets up the data for one series at a time
           */
          public static void registerLineSeries(String series_name, String[] x_data, Number[] y_data) {
              for (int i = 0; i < y_data.length; i++) {
                  if (y_data[i]!=null)
                  {
                      int ydata = y_data[i].intValue();
                      if (ydata>0)
                      {
                          lineDataset.addValue(ydata, series_name, x_data[i]);
                      }
                      else
                      {
                          lineDataset.addValue(null, series_name, x_data[i]);
                      }
                  }
                  else
                  {
                      lineDataset.addValue(null, series_name, x_data[i]);
                  }
              }
              log.debug("Series " + series_name + " registered.");
              return;
          }

          /**
           *  Sets up the data for one series at a time
           */
          public static void registerBarSeries(String series_name, String[] x_data, Number[] y_data) {
              for (int i = 0; i < y_data.length; i++) {
                  if (y_data[i]!=null)
                  {
                      int ydata = y_data[i].intValue();
                      if (ydata>0)
                      {
                          barDataset.addValue(ydata, series_name, x_data[i]);
                      }
                      else
                      {
                          barDataset.addValue(null, series_name, x_data[i]);
                      }
                  }
                  else
                  {
                      barDataset.addValue(null, series_name, x_data[i]);
                  }
              }
              log.debug("Series " + series_name + " registered.");
              return;
          }

          /**
           * Creates a chart.
           *
           * @return A chart.
           */
         
          public static JFreeChart createChart(String line_series_name, Number[] line_data, String bar_series_name, Number[] bar_data, String[] x_data) {
             
              // create the datasets...
             
              registerLineSeries(line_series_name, x_data, line_data);
              registerBarSeries(bar_series_name, x_data, bar_data);
             
              // create the renderers...
             
              CategoryItemRenderer lineRenderer = new LineAndShapeRenderer();
              CategoryItemRenderer barRenderer = new BarRenderer();
              CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator();
              barRenderer.setItemLabelGenerator(generator);
              barRenderer.setItemLabelsVisible(true);
             
              // create the plot and assign datasets and renderers
             
              CategoryPlot plot = new CategoryPlot();
              plot.setDataset(barDataset);
              plot.setRenderer(barRenderer);
              plot.setDataset(1, lineDataset);
              plot.setRenderer(1, lineRenderer);
             
              // set up plot axes and gridlines

              plot.setDomainAxis(new CategoryAxis("Category"));
              plot.setRangeAxis(new NumberAxis("Value"));

              plot.setOrientation(PlotOrientation.VERTICAL);
              plot.setRangeGridlinesVisible(true);
              plot.setDomainGridlinesVisible(true);

              ValueAxis rangeAxis2 = new NumberAxis("Axis 2");
              plot.setRangeAxis(1, rangeAxis2);

      //        plot.mapDatasetToRangeAxis(2, 1);  this seems to fail

              // change the rendering order so the primary dataset appears "behind" the
              // other datasets...
             
              plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
             
              // create the chart
             
              JFreeChart chart = new JFreeChart(plot);
              chart.setTitle("Activity Chart for ");
              return chart;
          }
      }