JFreeChart

Some time ago two interesting articles have been posted about creating dashboards in XQuery. One of the articles makes use of the Google Chart API to render graphs and inspired me to add a charting facility to eXist-db using the JFreeChart library.

sbc3d.png

this article is a reconstruction of an article originally written on 14 april 2009

JFreeChart

Getting Started

The new module is made available as an extension module and is not built by default. To enable the extension perform the following steps:

  • Edit extensions/build.properties and follow the instructions
  • Change include.module.jfreechart = false to true
  • Change include.module.fop = false to true for SVG support (new)
  • Uncomment the module in conf.xml (conf.xml.tmpl)
  • Run build.sh

All required files are downloaded as the module is built. After the build completes the new module's functions are available for use.

How to use

The module provides two functions:

jfreechart:render($a as xs:string, $b as node(), $c as node()) xs:base64Binary?

This function renders the image into a base64 encoded blob, while -

jfreechart:stream-render($a as xs:string, $b as node(), $c as node()) empty()

renders the image directly to the HTTP response (via. the servlet output stream). This function can only be used in the REST interface.

Both functions accept the same set of parameters: a is the chart type, b are the chart settings and c is the chart data.

a : chart type

Not all JFreeChart types are available (yet). At present the following charts are available:

LineChart, LineChart3D, MultiplePieChart, MultiplePieChart3D, PieChart, PieChart3D, RingChart, StackedAreaChart, StackedBarChart, StackedBarChart3D, WaterfallChart.

b : chart settings

Parameters are passed as a node, with the element names reflecting the parameters of the original JFreeChart classes:

ParameterDescription
categoryAxisColor the color of the category axis (#)
categoryAxisLabel the label for the category axis
categoryItemLabelGeneratorClass Set implementing class (see javadoc) (#)
categoryItemLabelGeneratorNumberFormat (see constructors implementing class in javadoc) (#)
categoryItemLabelGeneratorParameter (see constructors implementing class in javadoc) (#)
chartBackgroundColor -
domainAxisLabel the label for the category axis
height Height of chart, default is 300
imageType type of image: "png", "svg" or "svgz"
legend a flag specifying whether or not a legend is required
order the order that the data is extracted; "Column" (default) or "Row"
orientation the plot orientation; "Horizontal" (default) or "Vertical"
pieSectionLabel (see javadoc)
pieSectionNumberFormat (see javadoc)
pieSectionPercentFormat (see javadoc)
plotBackgroundColor (#)
rangeAxisLabel the label for the value axis
rangeLowerBound (#)
rangeUpperBound (#)
sectionColors list of colors, applied sequentially to setSectionPaint (#)
sectionColorsDelimiter delimiter character for sectionColor
seriesColors (#)
tableOrder value "column" or "row" (see javadoc) (#)
timeAxisColor (#)
timeAxisLabel (#)
title the chart title
titleColor (#)
tooltips configure chart to generate tool tips?
urls configure chart to generate URLs?
valueAxisColor (#)
valueAxisLabel the label for the value axis
width Width of chart, default is 400

(#) indicates new added parameters. A small example:

<configuration> <orientation>Horizontal</orientation> <height>500</height> <width>500</width> <title>Example 1</title> </configuration>

c : chart data

Two of the JFreeChart datatypes can be used : CategoryDataset and PieDataset. The module attempts to determine and read the correct Dataset for a graph.

For most of the charts the CategoryDataset is used. The structure of the data is as follows:

<?xml version="1.0" encoding="UTF-8"?> <!-- Sample data for JFreeChart. $Id: categorydata.xml 8835 2009-04-13 19:07:15Z dizzzz $ --> <CategoryDataset> <Series name="Series 1"> <Item> <Key>Category 1</Key> <Value>15.4</Value> </Item> <Item> <Key>Category 2</Key> <Value>12.7</Value> </Item> <Item> <Key>Category 3</Key> <Value>5.7</Value> </Item> <Item> <Key>Category 4</Key> <Value>9.1</Value> </Item> </Series> <Series name="Series 2"> <Item> <Key>Category 1</Key> <Value>45.4</Value> </Item> <Item> <Key>Category 2</Key> <Value>73.7</Value> </Item> <Item> <Key>Category 3</Key> <Value>23.7</Value> </Item> <Item> <Key>Category 4</Key> <Value>19.4</Value> </Item> </Series> </CategoryDataset>

For a subset of charts the PieDataset is used:

<?xml version="1.0" encoding="UTF-8"?> <!-- A sample pie dataset for JFreeChart. $Id: piedata.xml 8835 2009-04-13 19:07:15Z dizzzz $ --> <PieDataset> <Item> <Key>Java</Key> <Value>15.4</Value> </Item> <Item> <Key>C++</Key> <Value>12.7</Value> </Item> <Item> <Key>PHP</Key> <Value>5.7</Value> </Item> <Item> <Key>Python</Key> <Value>9.1</Value> </Item> </PieDataset>

Example

Putting it all together:

categorydata.png
(: Example code for jfreechart module :) (: Load the data files into /db :) (: $Id: categorydata.xq 8838 2009-04-14 18:01:51Z dizzzz $ :) declare namespace jfreechart = "http://exist-db.org/xquery/jfreechart"; jfreechart:stream-render("BarChart", <configuration> <orientation>Horizontal</orientation> <height>300</height> <width>400</width> <title>BarChart Example</title> </configuration>, doc('/db/categorydata.xml'))

and

piedata.png
(: Example code for jfreechart module :) (: Load the data files into /db :) (: $Id: piedata.xq 8838 2009-04-14 18:01:51Z dizzzz $ :) declare namespace jfreechart = "http://exist-db.org/xquery/jfreechart"; jfreechart:stream-render("PieChart", <configuration> <orientation>Horizontal</orientation> <height>300</height> <width>400</width> <title>PieChart Example</title> </configuration>, doc('/db/piedata.xml'))

More info

Todo's

Code is never finished. Although in trunk the code has been reworked, there are always things that could be added....

  • Add more charts
  • Add further Dataset types
  • Make direct use of eXistdb nodes, instead of serializing data first to a data stream and have it parsed by the JFreechart parser. Current solution is multi-threaded though (serialize and parse on 2 separate threads)
  • Add function for showing all supported Graphs
  • Set parameters as provided by JFreeChart.class
  • Transparency etc etc