Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Next »

Pentaho ChartBeans

In this article, the Pentaho ChartBeans project is introduced. Pentaho ChartBeans is a wrapper around other chart engines (such as JFreeChart and Open Flash Chart). Wrapping these "chart engines" creates a single way of expressing charts.

Prerequisites

Charting Terminology

To eliminate confusion in documentation, the Pentaho ChartBeans project has documented its preferred charting terminology. In addition to standardizing on terms for the purpose of the Pentaho ChartBeans project, this terminology page provides an excellent introduction to charting in general. Please review this page before proceeding.

ChartBeans

Pentaho ChartBeans requires three inputs: the data to be charted, the structure of the chart, and the styling of the chart.

Chart Data: the Chart Table Model

The org.pentaho.chart.ChartData interface is the format for data that is passed to Pentaho ChartBeans. ChartData extends javax.swing.table.TableModel to add row, column, and cell metadata. For example, ChartData allows you to set row and column names. Row and column names are useful for giving meaningful names to series and categories. A single implementation, org.pentaho.chart.data.ChartTableModel, is provided.

Chart Structure: the Chart Document

The org.pentaho.chart.core.ChartDocument class is a Java representation of a Pentaho ChartBeans XML document. It is a tree of org.pentaho.chart.core.ChartElement instances. A chart document includes elements like title, series, and plot. Note that the chart document references (or inlines) style information--see next section.

Chart Styling: the Chart CSS

Pentaho ChartBeans uses Cascading Style Sheets (CSS) to style charts. Pentaho ChartBeans is not limited to the W3C's style attributes (although it attempts to use them where appropriate, for familiarity). By using CSS, Pentaho ChartBeans allows you to completely separate chart structure and style. You can use external style sheets, inline selectors, as well as class and style attributes. Using an external style sheet would allow an organization to create a consistent look to all of its charts.

Example

Chart Data

In this example, we create a ChartTableModel consisting of 21 rows and 3 columns. In addition, we add some row and column metadata.

createChartTableModel: Dummy Data
  private static ChartTableModel createChartTableModel() {
    // 21 rows and 3 columns
    Object[][] dataArray = { { 5.55, 10.11, 20.22 }, { 30.33, 40.44, 50.55 }, { 31.33, 99.44, 150.55 },
        { 32.33, 1.44, 30.55 }, { 34.33, 88.44, 77.55 }, { 35.33, 22.44, 54.55 }, { 36.33, 33.44, 52.55 },
        { 37.33, 76.44, 54.55 }, { 38.33, 7.44, 59.55 }, { 39.33, 48.44, 56.55 }, { 40.33, 19.44, 57.55 },
        { 50.33, 104.44, 36.55 }, { 60.33, 23.44, 74.55 }, { 20.33, 90.44, 80.55 }, { 60.33, 18.44, 27.55 },
        { 10.33, 22.44, 97.55 }, { 20.33, 59.44, 55.55 }, { 90.33, 140.44, 22.55 }, { 100.33, 56.44, 76.55 },
        { 40.33, 50.44, 50.55 }, { 60.66, 70.77, 80.88 } };

    ChartTableModel data = new ChartTableModel();
    data.setData(dataArray);

    // give names to the categories
    data.setColumnName(0, "budget");
    data.setColumnName(1, "sales");
    data.setColumnName(2, "forecast");

    // give names to the series
    final String ROW_NAME_KEY = "row-name";
    data.setRowMetadata(0, ROW_NAME_KEY, "1");
    data.setRowMetadata(1, ROW_NAME_KEY, "2");
    // ----- lines omitted -----
    data.setRowMetadata(20, ROW_NAME_KEY, "21");
    return data;
  }

Chart Structure

The ChartBeans XML document for this example is below. Its relatively brief because our data and styling is separate from the chart structure. The elements in this document define a stylesheet reference, a chart title, the series, and the chart orientation.

Bar.xml: The Chart Document
<chart xmlns="http://reporting.pentaho.org/namespaces/charting/1.0">

  <!-- external style sheet -->
  <stylesheet href="theme.css" />

  <!-- chart title -->
  <title>Bar Chart Using Pentaho ChartBeans</title>
      
  <!-- styling on individual series using style and class attributes -->
  <series style="-x-pentaho-chart-series-type: bar; -x-pentaho-chart-bar-style: bar;" class="series1" />
  <series class="series2" />
  <!-- lines omitted -->
  <series class="series18" />
  
  <!-- wrap colors because there are more series than colors in the theme -->
  <series class="series1" />
  <series class="series2" />
  <series class="series3" />

  <!-- styling on plot using style attribute -->
  <plot style="-x-pentaho-chart-orientation: horizontal"/>
</chart>

Chart Styling

Here is the external style sheet referenced above. Here we're using class selectors. Note the W3C standard color property as well as a custom Pentaho ChartBeans' -x-pentaho-chart-line-width property.

theme.css
.series1 {
  color: #2D00FF;
  -x-pentaho-chart-line-width: 2px;
}

.series2 {
  color: #11FFE4;
  -x-pentaho-chart-line-width: 2px;
}

/* lines omitted */

.series18 {
  color: #B7FFE5;
  -x-pentaho-chart-line-width: 2px;
}

Generating Charts

Now lets pull all of the pieces together. First we have a main method that "boots" Pentaho ChartBeans. This reads various configuration files and otherwise readies the system for chart processing requests. Next we render one chart using the JFreeChart plugin for Pentaho ChartBeans and then we render another chart using the Open Flash Chart plugin for Pentaho ChartBeans. Note that both use the same chart document (and referenced stylesheet) as well as the same chart data.

main method
  public static void main(String[] args) throws Exception {
    // "boot" ChartBeans
    ChartBoot.getInstance().start();

    // render chart using JFreeChart plugin for Pentaho ChartBeans
    renderUsingJFreeChartPlugin("chartdocs/Bar.xml", createChartTableModel());

    // render same chart using Open Flash Chart plugin for Pentaho ChartBeans
    renderUsingOpenFlashChartPlugin("chartdocs/Bar.xml", createChartTableModel());
  }

See how we specify the plugin class in the first line?

renderUsingJFreeChartPlugin method
  private static void renderUsingJFreeChartPlugin(final String chartDocFilename, final ChartTableModel chartTableModel)
      throws Exception {
    final IChartPlugin plugin = ChartPluginFactory.getInstance("org.pentaho.chart.plugin.jfreechart.JFreeChartPlugin");
    // use the same filename as the chartDocFilename except with a different extension
    String chartOutputFilename = "chartoutput/"
        + chartDocFilename.substring(chartDocFilename.indexOf(File.separatorChar), chartDocFilename.indexOf('.'))
        + ".png";
    URL chartURL = new File(chartDocFilename).toURL();
    ChartDocumentContext cdc = ChartFactory.generateChart(chartURL, chartTableModel);
    IOutput output = plugin.renderChartDocument(cdc, chartTableModel);
    OutputUtils.persistChart(output, chartOutputFilename, IOutput.OutputTypes.FILE_TYPE_PNG, 400, 400); // 400px x 400px
  }

The Open Flash Chart example is a little more complicated because we have to embed the chart data in an HTML document.

renderUsingOpenFlashChartPlugin method
  private static void renderUsingOpenFlashChartPlugin(final String chartDocFilename,
      final ChartTableModel chartTableModel) throws Exception {
    final IChartPlugin plugin = ChartPluginFactory
        .getInstance("org.pentaho.chart.plugin.openflashchart.OpenFlashChartPlugin");
    URL chartURL = new File(chartDocFilename).toURL();
    ChartDocumentContext cdc = ChartFactory.generateChart(chartURL, chartTableModel);
    IOutput output = plugin.renderChartDocument(cdc, chartTableModel);

    ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();
    output.persistChart(tmpOut, IOutput.OutputTypes.DATA_TYPE_STREAM, 400, 400);
    final String ENCODING = "UTF-8";
    ByteArrayInputStream in = new ByteArrayInputStream(tmpOut.toByteArray());
    IOUtils.closeQuietly(tmpOut);
    String openFlashChartJson = IOUtils.toString(in, ENCODING);
    IOUtils.closeQuietly(in);

    final String HTML_TEMPLATE = "<html>\n" + "  <head>\n"
        + "    <title>Bar Chart Using Open Flash Chart Plugin</title>\n"
        + "    <script type=\"text/javascript\">window.getChartData = function() '{' return ''{0}''; '}'</script>\n"
        + "  </head>\n" + "  <body>\n"
        + "    <object id=\"ofco00b1c87708fe11dea97da1e1ba5b86bc\" height=\"100%\" align=\"middle\" width=\"100%\" \n"
        + "    codebase=\"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0\" \n"
        + "    classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"> \n"
        + "    <param value=\"sameDomain\" name=\"allowScriptAccess\"/><param value=\"opaque\" name=\"wmode\"/> \n"
        + "    <param value=\"open-flash-chart.swf?get-data=getChartData\" name=\"movie\"/> \n"
        + "    <param value=\"high\" name=\"quality\"/><embed id=\"ofce00b1c87708fe11dea97da1e1ba5b86bc\" \n"
        + "    height=\"100%\" align=\"middle\" width=\"100%\" \n"
        + "    pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" \n"
        + "    allowscriptaccess=\"sameDomain\" bgcolor=\"#FFFFFF\" quality=\"high\" wmode=\"opaque\" \n"
        + "    src=\"open-flash-chart.swf?get-data=getChartData\"/></object>\n" + "  </body>\n" + "</html>";

    String html = MessageFormat.format(HTML_TEMPLATE, new String[] { openFlashChartJson });
    String chartOutputFilename = "chartoutput/"
        + chartDocFilename.substring(chartDocFilename.indexOf(File.separatorChar), chartDocFilename.indexOf('.'))
        + ".html";
    FileUtils.writeStringToFile(new File(chartOutputFilename), html, "UTF-8");
  }

And here is the result using the JFreeChart plugin for Pentaho ChartBeans:

Bar chart using JFreeChart plugin for Pentaho ChartBeans

And here is the result using the Open Flash Chart plugin for Pentaho ChartBeans:

Bar chart using Open Flash Chart plugin for Pentaho ChartBeans

Summary

Related Items

  • No labels