Monday, October 27, 2008

BIRT Properties

If you have done much API level programming with BIRT you have probably found yourself in need of the name and values for a property.  This happens if you are working with either the Java or JavaScript modes of BIRT.

The good thing is that the properties that are used in BIRT are defined someplace in the Java code.  The hard part is finding exactly where the definition has been placed.  I have created a crib sheet with the classes that contain the most common property names on the wiki.  You can take a look here .

If you have been working with the BIRT APIs and have found similar information that might be useful, please feel free to update the wiki with your hints.

Monday, October 20, 2008

Dynamically adding a series to a BIRT Chart

Often it is a requirement to customize report output for specific users. Generally this is accomplished with parameters and some form of conditional logic within the report itself. This approach can be used with BIRT as well. BIRT supports JavaScript expressions and has an event model that allows report customization with handlers written in either Java or JavaScript. For more information on the event model see the scripting primer.

To illustrate modifying a BIRT chart at runtime, assume we have a bar chart that we wish to add additional line series to, based on some report parameter. This can be accomplished by creating an event handler for the beforeFactory event and modifying the report prior to it running.


cht = reportContext.getDesignHandle().findElement(“MyChart”);

This line of code requires that the chart be named MyChart in the General tab of the Properties View. This line of code gets a handle to the Chart report item. Once the chart report item is located we then can retrieve the actual chart model. The chart model is de-serialized from the xml within the report design and stored in a property called chart.instance. So to get the model, you can use code like the following:

mychart = cht.getReportItem().getProperty(“chart.instance”);

Now that we have the actual chart model, we can use standard chart engine API calls to modify it prior to the report running. Remember to import the CE API packages prior to using them. See the final example for more details.

Since we have a bar chart, the chart model will be an instance of the ChartWithAxesImpl class. This class has methods for getting the chart axes and adding series definitions. If we define a static report parameter that allows multi-selection, with values that correspond to the row values we want to map with line series, the following code will add the appropriate series.



//Get the x axis
xAxis =mychart.getAxes().get(0);
//Get the first y axis
yAxis1 = xAxis.getAssociatedAxes().get(0);
alternate_label_position = false;

for( i=0; i < params["SelectSeriesToAdd"].value.length; i++){
var sdNew = SeriesDefinitionImpl.create();
var ls = LineSeriesImpl.create();
ls.getLabel().setVisible(true);
if( alternate_label_position ){
ls.setLabelPosition( Position.BELOW_LITERAL );
alternate_label_position = false;
}else{
ls.setLabelPosition( Position.ABOVE_LITERAL );
alternate_label_position = true;
}
var qry = QueryImpl.create("row[\"" + params["SelectSeriesToAdd"].value[i] + "\"]" );
ls.getDataDefinition().add(qry)
sdNew.getSeries().add( ls );
yAxis1.getSeriesDefinitions().add( sdNew );


The for-loop iterates over the selected values within the parameter and creates a Line series for each value. The value of each parameter is used as the query for the new series. Finally the new series definition is added to the first y axis.

The final code the beforeFactory event handler looks like:

importPackage(Packages.org.eclipse.birt.chart.model.data.impl);
importPackage(Packages.org.eclipse.birt.chart.model.component.impl);
importPackage(Packages.org.eclipse.birt.chart.model.type.impl);
importPackage(Packages.org.eclipse.birt.chart.model.attribute);

//Chart must be named
cht = reportContext.getDesignHandle().findElement("MyChart");
mychart = cht.getReportItem().getProperty( "chart.instance" );


//Get the x axis
xAxis =mychart.getAxes().get(0);

//Get the first y axis
yAxis1 = xAxis.getAssociatedAxes().get(0);

//alternate the series label position of each new series
alternate_label_position = false;

for( i=0; i < params["SelectSeriesToAdd"].value.length; i++){

//create a new series definition for each new series
var sdNew = SeriesDefinitionImpl.create();
//create a new series for each parameter selection
var ls = LineSeriesImpl.create();
ls.getLabel().setVisible(true);
if( alternate_label_position ){
ls.setLabelPosition( Position.BELOW_LITERAL );
alternate_label_position = false;
}else{
ls.setLabelPosition( Position.ABOVE_LITERAL );
alternate_label_position = true;
}
//Create the query. The row value must correlate with the data set row value
var qry = QueryImpl.create("row[\"" + params["SelectSeriesToAdd"].value[i] + "\"]" );
ls.getDataDefinition().add(qry)
sdNew.getSeries().add( ls );
//Add the new series definition to the first y axis
yAxis1.getSeriesDefinitions().add( sdNew );
}




The complete example is located here.

For an example of resizing a chart dynamically see
this.