Bug 131186 Enhance birt.data.aggregation extension point to support multipass
The current org.eclipse.birt.data.aggregation extension point ( and associated org.eclipse.birt.data.engine.api.aggregation classes) can only support single-pass aggregates. We need to extend this framework to support custom multi-pass aggregates. One example: a percentage-to-total aggregate ( x/SUM(x) ) will require two passes over the series. A prelimary design of the new extension point: Introduce a new Aggregation abstract class in birt.data.engine.api: public abstract class Aggregation implements IAggregation { /** Returns the number of passes over the data series that the accumulator of this aggregate requires. For SUMMARY aggregates, the accumulator returns a value after all passes are complete. For RUNNING aggregates, the accumulator returns data in the last pass. */ public int getNumberOfPasses() { return 1; } } The Accumulator class can remain as is. However the comment to indicate that for multipass aggregates, start() and finish() will be called at the beginning and end of each pass. The aggregation extension point's aggregateClass element should indicate that the class needs to subclass Aggregation. Also, this element's kind should be changed to "java" and its "Based On" changed to "org.eclipse.birt.data.engine.api.aggregation.Aggregation".
data/org.eclipse.birt.data/src/org/eclipse/birt/data/engine/api/aggregation/Accumulator.java
* <p>
 * (1) Start: the Data Engine calls the start() method of the Accumulator upon 
 *  the start of a new range of data rows on which an aggregation is requested<br>
 * (2) OnRow: for each data row in range (after applying the optional filtering condition), the onRow()
 * method is called with values calculated based on the data row. <br>
 * (3) Finish: After the onRow call for the last data row in range, the Data Engine calls the finish()
 * method. <br>
 * <p>
 * For SUMMARY_AGGR type aggregation, the Data Engine calls getValue() after the finish() call to obtain 
 * the value of the aggregation. For RUNNING_AGGR type aggregation, it calls getValue() after each onRow()
 * call. <p>
 * Each instance of the accumulator can be used to calculate aggregations over multiple groups of data. The 
 * implementation should re-initialize the class for a new group in the start() method.
 */
abstract public class Accumulator
{
    
    /**
     * This method is called before the the first onRow() call. This is an opportunity to 
     * initialize any internal data structure. 
     * @throws DataException 
     */
    public void start() throws DataException
    {}
    
    /**
     * This method is called after the last onRow() call. This is an opportunity for the Accumulator 
     * to finalize its calculation, and to release any resource allocated to facilitate the calcuation.
     * getValue() may be called after finish() for SUMMARY_AGGR type of aggregation.
     * @throws DataException