The sample CSV ODA user interface extension
The CSV ODA user interface extension described in this section illustrates how to create an ODA user interface plug-in using the Eclipse PDE. The following section describes the code-based extensions a developer must make to complete the development of the CSV ODA user interface extension, after defining the plug-in framework in the Eclipse PDE.
The CSV ODA user interface plug-in contains the following packages:
*org.eclipse.birt.report.data.oda.csv.ui
Contains the UiPlugin class, which is automatically generated by the PDE Manifest Editor when you create the plug-in project.
*org.eclipse.birt.report.data.oda.csv.ui.i18n
Contains the Messages class and the messages.properties properties file to generate the messages displayed in the user interface. Localized versions of these messages are in files that use the following naming syntax:
messages_<locale>.msg
*org.eclipse.birt.report.data.oda.csv.ui.impl
Contains the CustomDataSetWizardPage class, an automatically generated implementation of an ODA data set designer page, which supports creating or editing an ODA data set.
*org.eclipse.birt.report.data.oda.csv.ui.wizards
The wizards package contains the classes that create the user interface pages used to choose a data source and data set in BIRT Report Designer.
Implementing the ODA data source and data set wizards
BIRT Report Designer uses the Eclipse Data Tools Platform (DTP) ODA design‑time framework and offers wizards that automatically generate customizable implementations. The DTP ODA framework defines two of the three extension points used in the CSV ODA user interface plug‑in:
*Connection profile
Defined in org.eclipse.datatools.connectivity.connectionProfile
*Data source and data set wizards
Defined in org.eclipse.datatools.connectivity.oda.design.ui.dataSource
The CSV ODA user interface plug-in also must implement the extension point for property pages defined in org.eclipse.ui.propertyPages.
The CSV ODA user interface plug-in uses the following abstract base classes in the org.eclipse.datatools.connectivity.oda.design.ui.wizards package to create the wizards that specify the data source and data set pages. An ODA user interface plug-in must extend these classes to provide the wizard pages with page control and related behavior:
*DataSourceEditorPage
Provides the framework to implement an ODA data source property page
*DataSourceWizardPage
Provides the framework to implement an ODA data source wizard page
*DataSetWizardPage
Provides the framework to implement an ODA data set wizard page
org.eclipse.birt.report.data.oda.csv.ui.impl package
This customizable page provides a simple Query Text control for user input. The page extends org.eclipse.datatools.connectivity.oda.design.ui.wizards
.DataSetWizardPage in the DTP ODA design-time framework to support updating an ODA data set design instance using query metadata.
org.eclipse.birt.report.data.oda.csv.ui.wizards package
The org.eclipse.birt.report.data.oda.csv.ui.wizards package in the CSV ODA user interface extension example implements the following classes:
*Constants
Defines the constants for the data source connection properties defined in the run-time drive implementation, org.eclipse.birt.report.data.oda.csv.
*CSVFilePropertyPage
Extends DataSourceEditorPage to create and initialize the editor controls for the property page used to specify the ODA data source. The class updates connection profile properties with values collected from the page.
*CSVFileSelectionPageHelper
Specifies the page layout and sets up the control that listens for user input and verifies the location of the CSV data source file.
*CSVFileSelectionWizardPage
Extends DataSourceWizardPage. This class creates and initializes the controls for the data source wizard page. The class sets the select file message and collects the property values.
*FileSelectionWizardPage
Extends DataSetWizardPage. This class creates and initializes the controls for the data set wizard page and specifies the page layout. The class connects to the data source, executes a query, retrieves the metadata and result set, and updates the data set design.
Constants class
The Constants class defines the following variables for the data source connection properties defined in org.eclipse.birt.report.data.oda.csv:
*ODAHOME specifies the CSV ODA file path constant, HOME.
*ODA_DEFAULT_CHARSET specifies the default character set as 8-bit Unicode Transformation Format (UTF-8).
*DEFAULT_MAX_ROWS sets the default maximum number of rows that can be retrieved from the data source.
Listing 25‑18 shows the code for the Constants class.
Listing 25‑18 The Constants class
public class Constants {
public static String ODAHOME="HOME";
public static String ODA_DEFAULT_CHARSET = "UTF-8";
public static int DEFAULT_MAX_ROWS = 1000;
}
CSVFilePropertyPage class
CSVFilePropertyPage extends the DataSourceEditorPage class, implementing the following methods to provide page editing functionality for the CSV ODA data source property page:
*The createAndInitCustomControl( ) method performs the following tasks:
*Instantiates a CSVFileSelectionPageHelper object
*Specifies the page layout and sets up the editing control by calling the CSVFileSelectionPageHelper.createCustomControl( ) and initCustomControl( ) methods
Listing 25‑19 shows the code for createAndInitCustomControl( ).
Listing 25‑19 The createAndInitCustomControl( ) method
protected void createAndInitCustomControl
( Composite parent, Properties profileProps )
{
if( m_pageHelper == null )
{
m_pageHelper = new CSVFileSelectionPageHelper( this );
}
m_pageHelper.createCustomControl( parent );
m_pageHelper.initCustomControl( profileProps );
if( ! isSessionEditable( ) )
{
getControl( ).setEnabled( false );
}
}
*collectCustomProperties( ) updates the connection profile properties with the values collected from the page by calling CSVFileSelectionPageHelper
.collectCustomProperties( ) method, as shown in Listing 25‑20.
Listing 25‑20 The collectCustomProperties( ) method
public Properties collectCustomProperties
( Properties profileProps )
{
if( m_pageHelper == null )
{
return profileProps;
}
return m_pageHelper.collectCustomProperties
( profileProps );
}
CSVFileSelectionPageHelper class
CSVFileSelectionPageHelper provides auxiliary processing for the CSVFilePropertyPage and CSVFileSelectionWizardPage classes.
CSVFileSelectionPageHelper implements the following methods:
*createCustomControl( ) performs the following tasks:
*Sets up the composite page layout
*Calls the setupFileLocation( ) method that sets up a control to listen for user input and verify the location of the CSV data source file
Listing 25‑21 shows the code for the createCustomControl( ) method.
Listing 25‑21 The createCustomControl( ) method
void createCustomControl( Composite parent )
{
Composite content = new Composite( parent, SWT.NULL );
GridLayout layout = new GridLayout( 2, false );
content.setLayout(layout);
setupFileLocation( content );
}
*setupFileLocation( ) performs the following tasks:
*Sets up the label and the grid data object in the page layout
*Sets up the control that listens for user input and verifies the location of the CSV data source file
Listing 25‑22 shows the code for the setupFileLocation( ) method.
Listing 25‑22 The setupFileLocation( ) method
private void setupFileLocation( Composite composite )
{
Label label = new Label( composite, SWT.NONE );
label.setText( Messages.getString( "label.selectFile" ) );
 
GridData data = new GridData( GridData.FILL_HORIZONTAL );
 
fileName = new Text( composite, SWT.BORDER );
fileName.setLayoutData( data );
setPageComplete( false );
 
fileName.addModifyListener( new ModifyListener( )
{
public void modifyText( ModifyEvent e )
{
verifyFileLocation();
}
} );
}
*collectCustomProperties( ) sets the data source directory property in the connection profile, as shown in Listing 25‑23.
Listing 25‑23 The collectCustomProperties( ) method
Properties collectCustomProperties( Properties props )
{
if( props == null )
{
props = new Properties( );
}
props.setProperty( CommonConstants.CONN_HOME_DIR_PROP,
getFolderLocation( ) );
return props;
}
*initCustomControl( ) initializes the data source wizard control to the location of the data source file, as shown in Listing 25‑24.
Listing 25‑24 The initCustomControl( ) method
void initCustomControl( Properties profileProps )
{
if( profileProps == null || profileProps.isEmpty( ) ||
fileName == null )
{
return;
}
String folderPath = profileProps.getProperty(
CommonConstants.CONN_HOME_DIR_PROP );
if( folderPath == null )
{
folderPath = EMPTY_STRING;
}
fileName.setText( folderPath );
verifyFileLocation( );
}
Understanding CSVFileSelectionWizardPage
The CSVFileSelectionWizardPage class extends the DataSourceWizardPage class, implementing the following methods to provide the functionality for the CSV ODA data source wizard page:
*The createPageCustomControl( ) method performs the following tasks:
*Instantiates a CSVFileSelectionPageHelper object
*Specifies the page layout and sets up the wizard page control by calling CSVFileSelectionPageHelper.createCustomControl( ) method
*Calls CSVFileSelectionPageHelper.initCustomControl( ) to initialize the control to the location of the data source file
Listing 25‑25 shows the code for the createPageCustomControl( ) method.
Listing 25‑25 The createPageCustomControl( ) method
public void createPageCustomControl( Composite parent )
{
if( m_pageHelper == null )
{
m_pageHelper = new CSVFileSelectionPageHelper( this );
}
m_pageHelper.createCustomControl( parent );
m_pageHelper.initCustomControl( m_csvFileProperties );
}
*The collectCustomProperties( ) method instantiates a Properties object to contain the CSV data source properties information, as shown in Listing 25‑26.
Listing 25‑26 The collectCustomProperties( ) method
public Properties collectCustomProperties( )
{
if( m_pageHelper != null )
{
return m_pageHelper.collectCustomProperties(
m_csvFileProperties );
}
return ( m_csvFileProperties != null ) ?
m_csvFileProperties : new Properties( );
}
Understanding FileSelectionWizardPage
The FileSelectionWizardPage class extends the DataSetWizardPage class, implementing the following methods to provide the functionality for the CSV ODA data set wizard page:
*The createPageControl( ) method performs the following tasks:
*Specifies the page layout and sets up the wizard page control
*Gets the data source properties
*Calls populateAvailableList( ) to update the data set design
Listing 25‑27 shows the code for the createPageControl( ) method.
Listing 25‑27 The createPageControl( ) method
private Control createPageControl( Composite parent )
{
Composite composite = new Composite( parent, SWT.NULL );
FormLayout layout = new FormLayout( );
composite.setLayout( layout );
FormData data = new FormData( );
data.left = new FormAttachment( 0, 5 );
data.top = new FormAttachment( 0, 5 );
fileName = new Text( composite, SWT.BORDER );
fileName.setLayoutData( data );
Properties dataSourceProps = getInitializationDesign( )
.getDataSourceDesign( ).getPublicProperties( );
fileName.setText( ( String )(
dataSourceProps.getProperty( Constants.ODAHOME )));
data = new FormData( );
data.top = new FormAttachment( fileName, 10, SWT.BOTTOM );
data.left = new FormAttachment( 0, 5 );
data.right = new FormAttachment( 47, -5 );
data.bottom = new FormAttachment( 100, -5 );
data.width = DEFAULT_WIDTH;
data.height = DEFAULT_HEIGHT;
m_availableList = new List( composite,
SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL );
m_availableList.setLayoutData( data );
m_selectedFile = new File(( String )(
dataSourceProps.getProperty( Constants.ODAHOME )));
populateAvailableList( );
return composite;
}
*getQuery( ) method builds the query for the data set by performing the following tasks:
*Gets the table name from the file object
*Appends the table name to a query that selects all the columns using a wildcard
*Appends the column list, then the table name, to a query that selects specific columns
*Returns the query text
Listing 25‑28 shows the code for the getQuery( ) method.
Listing 25‑28 The getQuery( ) method
private String getQuery( )
{
String tableName = null;
StringBuffer buf = new StringBuffer( );
File file = m_selectedFile;
if(file != null)
{
tableName = file.getName( );
}
if(tableName != null)
{
if(m_availableList.getItemCount( ) == 0)
{
buf.append("select * from ").append(tableName);
}
else
{
buf.append("select ");
String[ ] columns = m_availableList.getItems( );
for(int n = 0; n < columns.length; n++)
{
buf.append(columns[n]);
if(n < columns.length - 1)
{
buf.append(", ");
}
}
buf.append(" from ").append(tableName);
}
}
return buf.toString( );
}
*getQueryColumnNames( ) method performs the following tasks:
*Instantiates the CSVFileDriver
*Prepares the query and gets the results set metadata using the CSV ODA run-time driver and data source connection properties settings
*Gets the column count
*Iterates through the metadata results to get the column names and return the results
Listing 25‑29 shows the code for the getQueryColumnNames( ) method.
Listing 25‑29 The getQueryColumnNames( ) method
private String[ ] getQueryColumnNames(
String queryText, File file )
{
 
IDriver ffDriver = new CSVFileDriver( );
IConnection conn = null;
 
try {
conn = ffDriver.getConnection( null );
IResultSetMetaData metadata =
getResultSetMetaData( queryText, file, conn );
int columnCount = metadata.getColumnCount( );
 
if( columnCount == 0 )
{
return null;
}
String[ ] result = new String[columnCount];
 
for( int i = 0; i < columnCount; i++)
{
result[i] = metadata.getColumnName( i + 1 );
}
return result;
}
catch( OdaException e ) {
setMessage( e.getLocalizedMessage( ), ERROR );
disableAll( );
return null;
}
finally {
closeConnection( conn );
}
}
*getResultSetMetaData( ) method performs the following tasks:
*Sets up the Properties object with the location of the data source file
*Opens the connection to the data source
*Sets up a Query object and prepares the query text
*Executes the query
*Returns the metadata
Listing 25‑30 shows the code for the getResultSetMetaData( ) method.
Listing 25‑30 The getResultSetMetaData( ) method
private IResultSetMetaData getResultSetMetaData( String queryText, File file, IConnection conn ) throws OdaException
{
java.util.Properties prop = new java.util.Properties( );
prop.put( CommonConstants.CONN_HOME_DIR_PROP,
file.getParent( ) );
conn.open( prop );
IQuery query = conn.newQuery( null );
query.setMaxRows( Constants.DEFAULT_MAX_ROWS );
query.prepare( queryText );
query.executeQuery( );
return query.getMetaData( );
}
*setResultSetMetaData( ) method updates the data set page design with metadata returned by the query by performing the following tasks:
*Calls the DesignSessionUtil.toResultSetColumnsDesign( ) method to convert run-time metadata to a design-time ResultSetColumns object
*Obtains a ResultSetDefinition object from the design factory to use in populating the data set page design with the metadata definitions
*Calls the resultSetDefn.setResultSetColumns( ) method to set the reference to ResultSetColumns object, containing the metadata content
*Assigns the result set definition to the data set design
Listing 25‑31 shows the code for the setResultSetMetaData( ) method.
Listing 25‑31 The setResultSetMetaData( ) method
private void setResultSetMetaData( DataSetDesign dataSetDesign,IResultSetMetaData md ) throws OdaException
{
ResultSetColumns columns =
DesignSessionUtil.toResultSetColumnsDesign( md );
ResultSetDefinition resultSetDefn =
DesignFactory.eINSTANCE.createResultSetDefinition( );
resultSetDefn.setResultSetColumns( columns );
dataSetDesign.setPrimaryResultSet( resultSetDefn );
dataSetDesign.getResultSets().setDerivedMetaData( true );
}
*savePage( ) method performs the following tasks:
*Instantiates the CSVFileDriver
*Gets the result set metadata
*Updates the data set design with the metadata
*Closes the connection
Listing 25‑32 shows the code for the savePage( ) method.
Listing 25‑32 The savePage( ) method
private void savePage( DataSetDesign dataSetDesign )
{
String queryText = getQuery( );
dataSetDesign.setQueryText( queryText );
IConnection conn = null;
try {
IDriver ffDriver = new CSVFileDriver( );
conn = ffDriver.getConnection( null );
IResultSetMetaData metadata = getResultSetMetaData(
queryText, m_selectedFile, conn );
setResultSetMetaData( dataSetDesign, metadata );
}
catch( OdaException e ) {
dataSetDesign.setResultSets( null );
}
finally {
closeConnection( conn );
}
}