Charting in Citrus - hardened and extended Chart-Expressions
As we are now reaching RC stage within the next week or so, I think its time to spread some light on the new stuff to come for our Charting.
The charting in Pentaho Reporting was always a very delicate matter. Charting was (and is) implemented via a dual system of Chart-Expressions and Data-Collector functions. The data-collectors are responsible to produce the datasets, while the chart-expressions consume the data-set and produce a JFreeChart object. As JFreeChart-objects are Drawable-implementations, the engine can render them as vector-image for high-quality output.
But until recently, there was a creepy pattern when using our chart-related expressions. Make an error in the data-collector configuration, and you are killed. Define an invalid value - killed. Null values - killed. A invalid property in the chart-expression? Kaboom. Killed big time. An invalid combination of otherwise valid properties? Bloody nightmare. You are dead. Over time, we caused more dead developers than the browser wars at the beginning of the century. Many of these bloody incidents would have been avoidable by just applying defensive programming patterns. The old code behaved generally very unfriendly and rough. Wild casts, no check for invalid values or null-pointers caused all kind of funny exceptions. When asked what is wrong with a certain report-definition, I usually fired up the debugger to understand why an - from the outside - perfectly sane chart-definition failed to produce a chart. (Yeah, I could have resorted to guessing, but you can’t come up with the illogical and arcane rules needed to understand what’s going on.)
As the Citrus release is our big-overhaul, and everything is under revision and no back-pocket of insanity is left untouched. It was not surprising to find charting on the list of things to work on.
Now when creating new charts in Citrus, the first thing you will notice is that the beast (yes, beast!) no longer bites. The majority of properties has been hardened against invalid or missing values, and once arcane “free-form-text” properties are now equipped with real property-editors to guide you towards the few acceptable inputs.
When you create a chart, you first have to set-up the data-collector. There are currently 5 types available:
- a Categorical-DataSet-Collector for Bar-Charts,
- a Pivoting Categorical DataSet Collector, which reads series data by rows, instead by column
- a XY-DataSetCollector, for numeric data charts
- TimeSeries Collector, for plotting Date-Values on the X-Axis
- a XYZ-DataSet-Collector for 3-Dimensional charts.
Thanks to the backward-compatibility promise, we cannot go in an change the old collectors without breaking existing reports. So we decided that creating new collectors was the smartest option. May the old code rot in hell. In most cases, the new collectors produce the same results as the old ones. As part of the hardening, they react differently to invalid types and null-values, as they now ignore the invalid values instead of crashing the whole chart-creation process. The Pivoting-Collector was built from scratch, based on how the original one was expected to work originally. The collectors now have a greatly reduced complexity and a smaller set of properties needed to configure them. And while we were at it, we removed the Number One trouble maker, the “summary-only” flag, as this can be safely deducted from other properties.
The Chart-Expressions themselves have seen a bit of change as well. WebDetails, the creators of the Community Dashboard Project, contributed logarithmic axes and a smarter way to generate human readable labels for them. Roman Wild contributed a Radar-Chart implementation. And finally we went through our own support-cases bucket and addressed many of the issues reported there. As a result, Citrus-PRD now allows to configure the tick-mark generation on the axes, the Bar-Line chart can have shared y-axis and the percentage-mode on stacked-area-charts finally works too.
Oh, and the chart-editor looks a lot better now, thanks to the hard work of our UI-designer Brett.