Aggregation Extension Point
BIRT provides a special report item that aggregates data after retrieving it from a data source. The aggregation report item currently supports 30 functions; Figure 6 shows part of the list.
Figure 6 Viewing the Aggregation Builder function list.
These aggregate functions include Sum, Standard Deviation, and Max and Min values. While this list is extensive, you may want to extend the list, and BIRT provides an extension point for this type of customization.
Aggregate functions typically process data one or more times. The aggregation extension point offers additional flexibility if the standard functions don't meet the application requirements.
For example, suppose you need access to the previous row value to calculate the value for a specific column in a detail row. You can use the aggregate extension point to create a function to implement this feature.
Listing 4 shows the plugin.xml required to implement this feature.
Listing 4
<?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.4"?> <plugin> <extension point="org.eclipse.birt.data.aggregation"> <Aggregations> <AggregationFactory class="org.eclipse.birt.aggregate.previousvalue .PVAggregationFactory"/> </Aggregations> </extension> </plugin>
The extension point, org.eclipse.birt.data.aggregation, requires one or more nested AggregationFactory elements in the Aggregations node. The AggregationFactory node specifies a class that implements the IAggregationFactory interface.
This interface contains two methods declarations: getAggregations and getAggregation. The getAggregations method returns the list of aggregation functions that the factory supports. The getAggregation method takes a string parameter that is the name of a specific aggregate function, and it returns an instance of a class that implements the IAggrFunction, which matches the aggregate function name.
The IAggrFunction interface contains several method declarations that describe how a specific aggregate function behaves in the BIRT framework. For example, the getType method returns RUNNING_AGGR or SUMMARY_AGGR. For running aggregates, the calculated value is returned for every row processed. For summary aggregates, the calculated value for the complete dataset is returned.
The getParameterDefn method defines what types of parameters and how many are passed to the aggregate function. This interface also contains a method declaration for instantiating an instance of an Accumulator, which is an abstract class that can be extended. This class contains four methods and is the main class for implementing a specific aggregate function.
This class has start and finish methods that are called before and after the aggregate function processes data rows. The class also has a getValue method that's called whenever the framework requires the calculated value, such as after every row when using a running aggregate or at completion after processing the entire dataset when calculating a summary aggregate.
Finally, this class has an onRow method that is called for every row processed in the dataset. The method receives an Object array that is created based on the implementation of the getParameterDefn method described earlier. Listing 5 shows the code for the extended Accumulator class.
Listing 5
package org.eclipse.birt.aggregate.previousvalue; import org.eclipse.birt.data.engine.api.aggregation.Accumulator; import org.eclipse.birt.data.engine.core.DataException; import org.eclipse.birt.data.engine.i18n.ResourceConstants; public class PrevValAcum extends Accumulator { private Object prev = null; private Object calc = null; private boolean firstrow = true; public void finish() throws DataException { super.finish(); firstrow = false; } public void start() throws DataException { super.start(); firstrow = true; } //In this example called every row public Object getValue() throws DataException { if( firstrow ){ firstrow = false; return null; }else{ return calc; } } public void onRow(Object[] args) throws DataException { if (args[0] != null) { try { Object rawValue = args[0]; if( !firstrow ){ calc = prev; } prev = rawValue; } catch (Exception e) { throw new DataException( ResourceConstants.DATATYPEUTIL_ERROR, e); } } } }
The onRow method stores the previous row value of an object in a private member variable. The getValue method returns this saved value. The first row calculation returns null. The onRow method receives one parameter, which contains the value to be saved (see Figure 7).
Figure 7 Viewing the aggregated output.
Refer to the earlier section "Exporting and Deploying an Extension Point Plug-in" for information on how to deploy the aggregate extension.