/** SpagoBI, the Open Source Business Intelligence suite Copyright (C) 2012 Engineering Ingegneria Informatica S.p.A. - SpagoBI Competency Center This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. **/ package it.eng.spagobi.studio.oda.design.impl; import org.eclipse.datatools.connectivity.oda.IConnection; import org.eclipse.datatools.connectivity.oda.IDriver; import org.eclipse.datatools.connectivity.oda.IParameterMetaData; import org.eclipse.datatools.connectivity.oda.IQuery; import org.eclipse.datatools.connectivity.oda.IResultSetMetaData; import org.eclipse.datatools.connectivity.oda.OdaException; import org.eclipse.datatools.connectivity.oda.design.DataSetDesign; import org.eclipse.datatools.connectivity.oda.design.DataSetParameters; import org.eclipse.datatools.connectivity.oda.design.DesignFactory; import org.eclipse.datatools.connectivity.oda.design.ParameterDefinition; import org.eclipse.datatools.connectivity.oda.design.ResultSetColumns; import org.eclipse.datatools.connectivity.oda.design.ResultSetDefinition; import org.eclipse.datatools.connectivity.oda.design.ui.designsession.DesignSessionUtil; import org.eclipse.datatools.connectivity.oda.design.ui.wizards.DataSetWizardPage; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; /** * Auto-generated implementation of an ODA data set designer page * for an user to create or edit an ODA data set design instance. * This custom page provides a simple Query Text control for user input. * It further extends the DTP design-time framework to update * an ODA data set design instance based on the query's derived meta-data. * <br> * A custom ODA designer is expected to change this exemplary implementation * as appropriate. */ public class SpagoBIDataSetWizardPage extends DataSetWizardPage { private static String DEFAULT_MESSAGE = "Set the data set label"; private transient Text m_queryTextField; /** * Constructor * @param pageName */ public SpagoBIDataSetWizardPage( String pageName ) { super( pageName ); setTitle( pageName ); setMessage( DEFAULT_MESSAGE ); setPageComplete( false ); } /** * Constructor * @param pageName * @param title * @param titleImage */ public SpagoBIDataSetWizardPage( String pageName, String title, ImageDescriptor titleImage ) { super( pageName, title, titleImage ); setMessage( DEFAULT_MESSAGE ); setPageComplete( false ); } /* (non-Javadoc) * @see org.eclipse.datatools.connectivity.oda.design.ui.wizards.DataSetWizardPage#createPageCustomControl(org.eclipse.swt.widgets.Composite) */ public void createPageCustomControl( Composite parent ) { setControl( createPageControl( parent ) ); initializeControl(); } /** * Creates custom control for user-defined query text. */ private Control createPageControl( Composite parent ) { Composite composite = new Composite( parent, SWT.NONE ); composite.setLayout( new GridLayout( 1, false ) ); GridData gridData = new GridData( GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL ); composite.setLayoutData( gridData ); Label fieldLabel = new Label( composite, SWT.NONE ); fieldLabel.setText( "Dataset Label:" ); m_queryTextField = new Text( composite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL ); GridData data = new GridData( GridData.FILL_HORIZONTAL ); data.heightHint = 20; m_queryTextField.setLayoutData( data ); m_queryTextField.addModifyListener( new ModifyListener( ) { public void modifyText( ModifyEvent e ) { validateData(); } } ); Table dataset = new Table(composite, SWT.BORDER); TableColumn tc1 = new TableColumn(dataset, SWT.LEFT); TableColumn tc2 = new TableColumn(dataset, SWT.LEFT); TableColumn tc3 = new TableColumn(dataset, SWT.LEFT); tc1.setText("First Name"); tc2.setText("Last Name"); tc3.setText("Address"); tc1.setWidth(70); tc2.setWidth(70); tc3.setWidth(80); dataset.setHeaderVisible(true); GridData gdL = new GridData(GridData.FILL_BOTH); dataset.setLayoutData(gdL); TableItem ti = new TableItem(dataset, 0); ti.setText(new String[]{"dtaset name1", "dtaset name2", "dtaset name3"}); ti = new TableItem(dataset, 2); ti.setText(new String[]{"dtaset name4", "dtaset name5", "dtaset name6"}); setPageComplete( true ); return composite; } /** * Initializes the page control with the last edited data set design. */ private void initializeControl( ) { DataSetDesign dataSetDesign = getInitializationDesign(); if( dataSetDesign == null ) return; // nothing to initialize String queryText = dataSetDesign.getQueryText(); if( queryText == null ) return; // nothing to initialize // initialize control m_queryTextField.setText( queryText ); validateData(); setMessage( DEFAULT_MESSAGE ); } /** * Obtains the user-defined query text of this data set from page control. * @return query text */ private String getQueryText( ) { return m_queryTextField.getText(); } /* * (non-Javadoc) * @see org.eclipse.datatools.connectivity.oda.design.ui.wizards.DataSetWizardPage#collectDataSetDesign(org.eclipse.datatools.connectivity.oda.design.DataSetDesign) */ protected DataSetDesign collectDataSetDesign( DataSetDesign design ) { if( getControl() == null ) // page control was never created return design; // no editing was done if( ! hasValidData() ) return null; // to trigger a design session error status savePage( design ); return design; } /* * (non-Javadoc) * @see org.eclipse.datatools.connectivity.oda.design.ui.wizards.DataSetWizardPage#collectResponseState() */ protected void collectResponseState( ) { super.collectResponseState( ); /* * To optionally assign a custom response state, for inclusion in the ODA * design session response, use * setResponseSessionStatus( SessionStatus status ); * setResponseDesignerState( DesignerState customState ); */ } /* * (non-Javadoc) * @see org.eclipse.datatools.connectivity.oda.design.ui.wizards.DataSetWizardPage#canLeave() */ protected boolean canLeave( ) { return isPageComplete(); } /** * Validates the user-defined value in the page control exists * and not a blank text. * Set page message accordingly. */ private void validateData( ) { boolean isValid = ( m_queryTextField != null && getQueryText() != null && getQueryText().trim().length() > 0 ); if( isValid ) setMessage( DEFAULT_MESSAGE ); else setMessage( "Requires input value.", ERROR ); setPageComplete( isValid ); } /** * Indicates whether the custom page has valid data to proceed * with defining a data set. */ private boolean hasValidData( ) { validateData( ); return canLeave(); } /** * Saves the user-defined value in this page, and updates the specified * dataSetDesign with the latest design definition. */ private void savePage( DataSetDesign dataSetDesign ) { // save user-defined query text String queryText = getQueryText(); dataSetDesign.setQueryText( queryText ); // obtain query's current runtime metadata, and maps it to the dataSetDesign IConnection customConn = null; try { // instantiate your custom ODA runtime driver class /* Note: You may need to manually update your ODA runtime extension's * plug-in manifest to export its package for visibility here. */ IDriver customDriver = new it.eng.spagobi.studio.oda.impl.Driver(); // obtain and open a live connection customConn = customDriver.getConnection( null ); java.util.Properties connProps = DesignSessionUtil.getEffectiveDataSourceProperties( getInitializationDesign().getDataSourceDesign() ); customConn.open( connProps ); // update the data set design with the // query's current runtime metadata updateDesign( dataSetDesign, customConn, queryText ); } catch( OdaException e ) { // not able to get current metadata, reset previous derived metadata dataSetDesign.setResultSets( null ); dataSetDesign.setParameters( null ); e.printStackTrace(); } finally { closeConnection( customConn ); } } /** * Updates the given dataSetDesign with the queryText and its derived metadata * obtained from the ODA runtime connection. */ private void updateDesign( DataSetDesign dataSetDesign, IConnection conn, String queryText ) throws OdaException { IQuery query = conn.newQuery( null ); query.prepare( queryText ); // TODO a runtime driver might require a query to first execute before // its metadata is available // query.setMaxRows( 1 ); // query.executeQuery(); try { IResultSetMetaData md = query.getMetaData(); updateResultSetDesign( md, dataSetDesign ); } catch( OdaException e ) { // no result set definition available, reset previous derived metadata dataSetDesign.setResultSets( null ); e.printStackTrace(); } // proceed to get parameter design definition try { IParameterMetaData paramMd = query.getParameterMetaData(); updateParameterDesign( paramMd, dataSetDesign ); } catch( OdaException ex ) { // no parameter definition available, reset previous derived metadata dataSetDesign.setParameters( null ); ex.printStackTrace(); } /* * See DesignSessionUtil for more convenience methods * to define a data set design instance. */ } /** * Updates the specified data set design's result set definition based on the * specified runtime metadata. * @param md runtime result set metadata instance * @param dataSetDesign data set design instance to update * @throws OdaException */ private void updateResultSetDesign( IResultSetMetaData md, DataSetDesign dataSetDesign ) throws OdaException { ResultSetColumns columns = DesignSessionUtil.toResultSetColumnsDesign( md ); ResultSetDefinition resultSetDefn = DesignFactory.eINSTANCE .createResultSetDefinition(); // resultSetDefn.setName( value ); // result set name resultSetDefn.setResultSetColumns( columns ); // no exception in conversion; go ahead and assign to specified dataSetDesign dataSetDesign.setPrimaryResultSet( resultSetDefn ); dataSetDesign.getResultSets().setDerivedMetaData( true ); } /** * Updates the specified data set design's parameter definition based on the * specified runtime metadata. * @param paramMd runtime parameter metadata instance * @param dataSetDesign data set design instance to update * @throws OdaException */ private void updateParameterDesign( IParameterMetaData paramMd, DataSetDesign dataSetDesign ) throws OdaException { DataSetParameters paramDesign = DesignSessionUtil.toDataSetParametersDesign( paramMd, DesignSessionUtil.toParameterModeDesign( IParameterMetaData.parameterModeIn ) ); // no exception in conversion; go ahead and assign to specified dataSetDesign dataSetDesign.setParameters( paramDesign ); if( paramDesign == null ) return; // no parameter definitions; done with update paramDesign.setDerivedMetaData( true ); // TODO replace below with data source specific implementation; // hard-coded parameter's default value for demo purpose if( paramDesign.getParameterDefinitions().size() > 0 ) { ParameterDefinition paramDef = (ParameterDefinition) paramDesign.getParameterDefinitions().get( 0 ); if( paramDef != null ) paramDef.setDefaultScalarValue( "dummy default value" ); } } /** * Attempts to close given ODA connection. */ private void closeConnection( IConnection conn ) { try { if( conn != null && conn.isOpen() ) conn.close(); } catch ( OdaException e ) { // ignore e.printStackTrace(); } } }