/*!
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2002-2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.ui.datasources.kettle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.openformula.ui.DefaultFieldDefinition;
import org.pentaho.openformula.ui.FieldDefinition;
import org.pentaho.reporting.engine.classic.core.DataFactoryContext;
import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeContext;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeUtil;
import org.pentaho.reporting.engine.classic.core.designtime.datafactory.DataFactoryEditorSupport;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.ExceptionDialog;
import org.pentaho.reporting.engine.classic.core.util.ReportParameterValues;
import org.pentaho.reporting.engine.classic.core.wizard.DataSchemaModel;
import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.FormulaArgument;
import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.FormulaParameter;
import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.KettleDataFactory;
import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.KettleTransformationProducer;
import org.pentaho.reporting.libraries.base.util.FilesystemFilter;
import org.pentaho.reporting.libraries.base.util.IOUtils;
import org.pentaho.reporting.libraries.base.util.ObjectUtilities;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.designtime.swing.BorderlessButton;
import org.pentaho.reporting.libraries.designtime.swing.CommonDialog;
import org.pentaho.reporting.libraries.designtime.swing.background.CancelEvent;
import org.pentaho.reporting.libraries.designtime.swing.background.DataPreviewDialog;
import org.pentaho.reporting.libraries.designtime.swing.background.PreviewWorker;
import org.pentaho.reporting.libraries.designtime.swing.filechooser.CommonFileChooser;
import org.pentaho.reporting.libraries.designtime.swing.filechooser.FileChooserService;
import org.pentaho.reporting.libraries.designtime.swing.icons.IconLoader;
import org.pentaho.reporting.ui.datasources.kettle.embedded.KettleParameterInfo;
import org.pentaho.reporting.ui.datasources.kettle.parameter.FormulaParameterDialog;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.HashSet;
import java.util.List;
/**
* @author Ezequiel Cuellar
*/
public class KettleDataSourceDialog extends CommonDialog {
private class BrowseAction extends AbstractAction implements ListSelectionListener {
private BrowseAction() {
putValue( Action.NAME, Messages.getString( "KettleDataSourceDialog.Browse.Name" ) );
setEnabled( false );
}
public void actionPerformed( final ActionEvent e ) {
final FileFilter[] fileFilters = new FileFilter[] { new FilesystemFilter( new String[] { ".ktr" },
Messages.getString( "KettleDataSourceDialog.KtrFileDescription" ) + " (*.ktr)", true ) };
final File reportContextFile = DesignTimeUtil.getContextAsFile( designTimeContext.getReport() );
final CommonFileChooser fileChooser = FileChooserService.getInstance().getFileChooser( "kettle" );
final String fileText = fileTextField.getText();
if ( StringUtils.isEmpty( fileText ) == false ) {
if ( reportContextFile != null ) {
fileChooser.setSelectedFile( new File( reportContextFile.getParentFile(), fileTextField.getText() ) );
} else {
fileChooser.setSelectedFile( new File( fileTextField.getText() ) );
}
}
fileChooser.setFilters( fileFilters );
if ( fileChooser.showDialog( KettleDataSourceDialog.this, JFileChooser.OPEN_DIALOG ) == false ) {
return;
}
final File file = fileChooser.getSelectedFile();
if ( file == null ) {
return;
}
final String path;
if ( reportContextFile != null ) {
path = IOUtils.getInstance().createRelativePath( file.getPath(), reportContextFile.getAbsolutePath() );
} else {
path = file.getPath();
}
final KettleQueryEntry queryEntry = (KettleQueryEntry) queryNameList.getSelectedValue();
if ( queryEntry instanceof FileKettleQueryEntry ) {
FileKettleQueryEntry fe = (FileKettleQueryEntry) queryEntry;
fe.setFile( path );
}
fileTextField.setText( path );
}
/**
* Called whenever the value of the selection changes.
*
* @param e the event that characterizes the change.
*/
public void valueChanged( final ListSelectionEvent e ) {
setEnabled( queryNameList.getSelectedValue() != null );
}
}
private class NameSyncHandler implements DocumentListener {
private NameSyncHandler() {
}
/**
* Gives notification that there was an insert into the document. The range given by the DocumentEvent bounds the
* freshly inserted region.
*
* @param e the document event
*/
public void insertUpdate( final DocumentEvent e ) {
update();
}
/**
* Gives notification that a portion of the document has been removed. The range is given in terms of what the view
* last saw (that is, before updating sticky positions).
*
* @param e the document event
*/
public void removeUpdate( final DocumentEvent e ) {
update();
}
/**
* Gives notification that an attribute or set of attributes changed.
*
* @param e the document event
*/
public void changedUpdate( final DocumentEvent e ) {
update();
}
private void update() {
if ( inUpdateFromList ) {
return;
}
final String queryName = nameTextField.getText();
final KettleQueryEntry selectedQuery = (KettleQueryEntry) queryNameList.getSelectedValue();
selectedQuery.setName( queryName );
queryNameList.repaint();
}
}
private class FileSyncHandler implements DocumentListener, Runnable {
private boolean armed;
private FileSyncHandler() {
}
/**
* Gives notification that there was an insert into the document. The range given by the DocumentEvent bounds the
* freshly inserted region.
*
* @param e the document event
*/
public void insertUpdate( final DocumentEvent e ) {
update();
}
/**
* Gives notification that a portion of the document has been removed. The range is given in terms of what the view
* last saw (that is, before updating sticky positions).
*
* @param e the document event
*/
public void removeUpdate( final DocumentEvent e ) {
update();
}
/**
* Gives notification that an attribute or set of attributes changed.
*
* @param e the document event
*/
public void changedUpdate( final DocumentEvent e ) {
update();
}
private void update() {
if ( armed ) {
return;
}
armed = true;
SwingUtilities.invokeLater( this );
}
public void run() {
final String fileName = fileTextField.getText();
final KettleQueryEntry selectedQuery = (KettleQueryEntry) queryNameList.getSelectedValue();
if ( selectedQuery instanceof FileKettleQueryEntry == false ) {
return;
}
FileKettleQueryEntry fe = (FileKettleQueryEntry) selectedQuery;
fe.setFile( fileName );
try {
inUpdateFromList = true;
refreshStepList( fe );
stepsList.setEnabled( true );
editParameterAction.setEnabled( true );
stopOnErrorsCheckBox.setEnabled( true );
} catch ( final ReportDataFactoryException rdfe ) {
logger.warn( "Non-critical failure while executing the query", rdfe );
stepsList.setEnabled( false );
editParameterAction.setEnabled( false );
stopOnErrorsCheckBox.setEnabled( false );
} catch ( final Exception e1 ) {
designTimeContext.error( e1 );
stepsList.setEnabled( false );
editParameterAction.setEnabled( false );
stopOnErrorsCheckBox.setEnabled( false );
} catch ( final Throwable t1 ) {
designTimeContext.error( new RuntimeException( "Fatal error", t1 ) );
stepsList.setEnabled( false );
editParameterAction.setEnabled( false );
stopOnErrorsCheckBox.setEnabled( false );
} finally {
inUpdateFromList = false;
armed = false;
}
}
}
private void refreshStepList( final FileKettleQueryEntry fe ) throws KettleException, ReportDataFactoryException {
DataFactoryContext dataFactoryContext = getDesignTimeContext().getDataFactoryContext();
final List<StepMeta> data = fe.getSteps( dataFactoryContext );
stepsList.setListData( data.toArray( new StepMeta[ data.size() ] ) );
final String selectedStepName = fe.getSelectedStep();
if ( selectedStepName != null ) {
for ( final StepMeta stepMeta : data ) {
if ( selectedStepName.equals( stepMeta.getName() ) ) {
stepsList.setSelectedValue( stepMeta, true );
break;
}
}
}
}
private class StepsListListener implements ListSelectionListener {
private StepsListListener() {
}
public void valueChanged( final ListSelectionEvent aEvt ) {
final KettleQueryEntry queryEntry = (KettleQueryEntry) queryNameList.getSelectedValue();
if ( queryEntry instanceof FileKettleQueryEntry ) {
FileKettleQueryEntry fe = (FileKettleQueryEntry) queryEntry;
final StepMeta selectedValue = (StepMeta) stepsList.getSelectedValue();
if ( selectedValue != null ) {
fe.setSelectedStep( selectedValue.getName() );
}
}
}
}
protected class QueryNameListSelectionListener implements ListSelectionListener {
protected QueryNameListSelectionListener() {
}
public void valueChanged( final ListSelectionEvent e ) {
final KettleQueryEntry value = getSelectedQuery();
if ( value == null ) {
nameTextField.setEnabled( false );
fileTextField.setEnabled( false );
stepsList.setEnabled( false );
editParameterAction.setEnabled( false );
stopOnErrorsCheckBox.setEnabled( false );
stopOnErrorsCheckBox.setSelected( false );
handleSelection( value );
return;
}
inUpdateFromList = true;
nameTextField.setEnabled( true );
fileTextField.setEnabled( true );
try {
nameTextField.setText( value.getName() );
editParameterAction.setEnabled( true );
stopOnErrorsCheckBox.setSelected( value.isStopOnErrors() );
stopOnErrorsCheckBox.setEnabled( true );
handleSelection( value );
} finally {
inUpdateFromList = false;
}
}
protected void handleSelection( final KettleQueryEntry value ) {
if ( value instanceof FileKettleQueryEntry ) {
handleSelection( (FileKettleQueryEntry) value );
}
}
protected void handleSelection( final FileKettleQueryEntry selectedQuery ) {
try {
fileTextField.setText( selectedQuery.getFile() );
refreshStepList( selectedQuery );
stepsList.setEnabled( true );
editParameterAction.setEnabled( true );
stopOnErrorsCheckBox.setEnabled( true );
} catch ( final ReportDataFactoryException rdfe ) {
logger.warn( "Non-critical failure while executing the query", rdfe );
stepsList.setEnabled( false );
editParameterAction.setEnabled( false );
stopOnErrorsCheckBox.setEnabled( false );
} catch ( final Exception e1 ) {
designTimeContext.error( e1 );
stepsList.setEnabled( false );
editParameterAction.setEnabled( false );
stopOnErrorsCheckBox.setEnabled( false );
} catch ( final Throwable t1 ) {
designTimeContext.error( new RuntimeException( "Fatal error", t1 ) );
stepsList.setEnabled( false );
editParameterAction.setEnabled( false );
stopOnErrorsCheckBox.setEnabled( false );
}
}
}
private class AddQueryAction extends AbstractAction {
public AddQueryAction() {
putValue( Action.SMALL_ICON, IconLoader.getInstance().getAddIcon() );
putValue( Action.SHORT_DESCRIPTION, Messages.getString( "KettleDataSourceDialog.AddQuery.Description" ) );
}
public void actionPerformed( final ActionEvent e ) {
String queryName = findNextName();
try {
final KettleQueryEntry newQuery = createNewQueryEntry( queryName );
queryListModel.addElement( newQuery );
queryNameList.setSelectedValue( newQuery, true );
} catch ( final KettleException e1 ) {
getDesignTimeContext().error( e1 );
}
}
}
private class RemoveQueryAction extends AbstractAction implements ListSelectionListener {
public RemoveQueryAction() {
putValue( Action.SMALL_ICON, IconLoader.getInstance().getDeleteIcon() );
putValue( Action.SHORT_DESCRIPTION, Messages.getString( "KettleDataSourceDialog.RemoveQuery.Description" ) );
setEnabled( false );
}
public void actionPerformed( final ActionEvent e ) {
final Object selectedValue = queryNameList.getSelectedValue();
if ( selectedValue == null ) {
return;
}
inUpdateFromList = true;
try {
clearComponents();
queryListModel.removeElement( selectedValue );
} finally {
inUpdateFromList = false;
}
}
/**
* Called whenever the value of the selection changes.
*
* @param e the event that characterizes the change.
*/
public void valueChanged( final ListSelectionEvent e ) {
setEnabled( queryNameList.getSelectedValue() != null );
}
}
private class PreviewAction extends AbstractAction implements ListSelectionListener {
private PreviewAction() {
putValue( Action.NAME, Messages.getString( "KettleDataSourceDialog.Preview.Name" ) );
setEnabled( false );
}
public void actionPerformed( final ActionEvent e ) {
try {
final KettleQueryEntry kettleQueryEntry = (KettleQueryEntry) queryNameList.getSelectedValue();
final KettleTransformationProducer fileProducer = kettleQueryEntry.createProducer();
final KettleDataFactory dataFactory = new KettleDataFactory();
dataFactory.setQuery( kettleQueryEntry.getName(), fileProducer );
DataFactoryEditorSupport.configureDataFactoryForPreview( dataFactory, designTimeContext );
final DataPreviewDialog previewDialog = new DataPreviewDialog( KettleDataSourceDialog.this );
final KettlePreviewWorker worker = new KettlePreviewWorker( dataFactory, kettleQueryEntry.getName() );
previewDialog.showData( worker );
final ReportDataFactoryException factoryException = worker.getException();
if ( factoryException != null ) {
ExceptionDialog.showExceptionDialog( KettleDataSourceDialog.this,
Messages.getString( "KettleDataSourceDialog.PreviewError.Title" ),
Messages.getString( "KettleDataSourceDialog.PreviewError.Message" ), factoryException );
}
} catch ( final Exception ex ) {
ExceptionDialog.showExceptionDialog( KettleDataSourceDialog.this,
Messages.getString( "KettleDataSourceDialog.PreviewError.Title" ),
Messages.getString( "KettleDataSourceDialog.PreviewError.Message" ), ex );
}
}
/**
* Called whenever the value of the selection changes.
*
* @param e the event that characterizes the change.
*/
public void valueChanged( final ListSelectionEvent e ) {
setEnabled( stepsList.getSelectedValue() != null );
}
}
private static class KettlePreviewWorker implements PreviewWorker {
private KettleDataFactory dataFactory;
private TableModel resultTableModel;
private ReportDataFactoryException exception;
private String query;
private KettlePreviewWorker( final KettleDataFactory dataFactory,
final String query ) {
if ( dataFactory == null ) {
throw new NullPointerException();
}
this.query = query;
this.dataFactory = dataFactory;
}
public ReportDataFactoryException getException() {
return exception;
}
public TableModel getResultTableModel() {
return resultTableModel;
}
public void close() {
}
/**
* Requests that the thread stop processing as soon as possible.
*/
public void cancelProcessing( final CancelEvent event ) {
dataFactory.cancelRunningQuery();
}
/**
* When an object implementing interface <code>Runnable</code> is used to create a thread, starting the thread
* causes the object's <code>run</code> method to be called in that separately executing thread.
* <p/>
* The general contract of the method <code>run</code> is that it may take any action whatsoever.
*
* @see Thread#run()
*/
public void run() {
try {
resultTableModel = dataFactory.queryData( query, new ReportParameterValues() );
} catch ( final ReportDataFactoryException e ) {
exception = e;
} finally {
dataFactory.close();
}
}
}
private class EditParameterAction extends AbstractAction {
/**
* Defines an <code>Action</code> object with a default description string and default icon.
*/
private EditParameterAction() {
putValue( Action.NAME, Messages.getString( "KettleDataSourceDialog.EditParameter.Name" ) );
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed( final ActionEvent e ) {
final KettleQueryEntry queryEntry = (KettleQueryEntry) queryNameList.getSelectedValue();
if ( queryEntry == null ) {
return;
}
try {
final FormulaParameterDialog dialog =
new FormulaParameterDialog( KettleDataSourceDialog.this, designTimeContext );
FieldDefinition[] fields = createFieldDefinitions();
FormulaParameter[] parameters = queryEntry.getParameters();
FormulaArgument[] arguments = queryEntry.getArguments();
KettleParameterInfo[] declaredParameters =
queryEntry.getDeclaredParameters( getDesignTimeContext().getDataFactoryContext() );
final FormulaParameterDialog.EditResult editResult = dialog.performEdit
( arguments, parameters, fields, declaredParameters );
if ( editResult == null ) {
return;
}
queryEntry.setArguments( editResult.getArgumentNames() );
queryEntry.setParameters( editResult.getParameterMappings() );
} catch ( final Exception e1 ) {
designTimeContext.error( e1 );
} catch ( final Throwable t1 ) {
designTimeContext.error( new RuntimeException( "Fatal error", t1 ) );
}
}
private FieldDefinition[] createFieldDefinitions() {
DataSchemaModel dataSchemaModel = designTimeContext.getDataSchemaModel();
String[] reportFields = dataSchemaModel.getColumnNames();
FieldDefinition[] fields = new FieldDefinition[ reportFields.length ];
for ( int i = 0; i < reportFields.length; i++ ) {
String reportField = reportFields[ i ];
fields[ i ] = new DefaultFieldDefinition( reportField );
}
return fields;
}
}
private class StopOnErrorSync implements ActionListener {
public void actionPerformed( final ActionEvent e ) {
KettleQueryEntry selectedQuery = getSelectedQuery();
if ( selectedQuery != null ) {
selectedQuery.setStopOnErrors( stopOnErrorsCheckBox.isSelected() );
}
}
}
private static final Log logger = LogFactory.getLog( KettleDataSourceDialog.class );
private DesignTimeContext designTimeContext;
private JTextField fileTextField;
private JTextField nameTextField;
private JList stepsList;
private JList queryNameList;
private DefaultListModel queryListModel;
private boolean inUpdateFromList;
private Action editParameterAction;
private PreviewAction previewAction;
private JCheckBox stopOnErrorsCheckBox;
public KettleDataSourceDialog( final DesignTimeContext designTimeContext, final JDialog parent ) {
super( parent );
initDialog( designTimeContext );
}
public KettleDataSourceDialog( final DesignTimeContext designTimeContext, final JFrame parent ) {
super( parent );
initDialog( designTimeContext );
}
public KettleDataSourceDialog( final DesignTimeContext designTimeContext ) {
initDialog( designTimeContext );
}
private void initDialog( final DesignTimeContext designTimeContext ) {
if ( designTimeContext == null ) {
throw new NullPointerException();
}
this.designTimeContext = designTimeContext;
stopOnErrorsCheckBox = new JCheckBox( Messages.getString( "KettleDataSourceDialog.StopOnErrors" ) );
stopOnErrorsCheckBox.setEnabled( false );
stopOnErrorsCheckBox.addActionListener( new StopOnErrorSync() );
editParameterAction = new EditParameterAction();
editParameterAction.setEnabled( false );
queryListModel = new DefaultListModel();
queryNameList = new JList( queryListModel );
queryNameList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
queryNameList.setVisibleRowCount( 5 );
queryNameList.addListSelectionListener( getQueryNameListener() );
previewAction = new PreviewAction();
fileTextField = new JTextField( 30 );
fileTextField.setEnabled( false );
fileTextField.getDocument().addDocumentListener( new FileSyncHandler() );
stepsList = new JList();
stepsList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
stepsList.addListSelectionListener( new StepsListListener() );
stepsList.addListSelectionListener( previewAction );
nameTextField = new JTextField( 30 );
nameTextField.setEnabled( false );
nameTextField.getDocument().addDocumentListener( new NameSyncHandler() );
setTitle( getDialogTitle() );
setDefaultCloseOperation( JDialog.DISPOSE_ON_CLOSE );
setModal( true );
super.init();
}
protected JCheckBox getStopOnErrorsCheckBox() {
return stopOnErrorsCheckBox;
}
protected Action getPreviewAction() {
return previewAction;
}
protected Action getEditParameterAction() {
return editParameterAction;
}
protected DesignTimeContext getDesignTimeContext() {
return designTimeContext;
}
protected KettleQueryEntry getSelectedQuery() {
return (KettleQueryEntry) queryNameList.getSelectedValue();
}
protected void updateQueryName( final String name ) {
nameTextField.setText( name );
}
protected String getDialogTitle() {
return Messages.getString( "KettleDataSourceDialog.Title" );
}
protected String getDialogId() {
return "KettleDataSourceDialog";
}
protected Component createContentPane() {
final JPanel previewAndParameterPanel = createTransformParameterPanel();
final JPanel queryListPanel = createQueryListPanel();
final JPanel mainPanel = new JPanel( new GridBagLayout() );
mainPanel.setBorder( new EmptyBorder( 5, 5, 0, 5 ) );
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
mainPanel.add( new JLabel( Messages.getString( "KettleDataSourceDialog.QueryName" ) ), gbc );
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 1;
mainPanel.add( nameTextField, gbc );
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 3;
gbc.gridwidth = 3;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.WEST;
mainPanel.add( createDatasourcePanel(), gbc );
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 4;
gbc.gridwidth = 3;
gbc.anchor = GridBagConstraints.WEST;
mainPanel.add( previewAndParameterPanel, gbc );
final JSplitPane panel = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
panel.setLeftComponent( queryListPanel );
panel.setRightComponent( mainPanel );
panel.setDividerLocation( 250 );
return panel;
}
private JPanel createQueryListPanel() {
final RemoveQueryAction removeQueryAction = new RemoveQueryAction();
queryNameList.addListSelectionListener( removeQueryAction );
final JPanel queryListButtonsPanel = new JPanel( new FlowLayout( FlowLayout.RIGHT ) );
queryListButtonsPanel.add( new BorderlessButton( new AddQueryAction() ) );
queryListButtonsPanel.add( new BorderlessButton( removeQueryAction ) );
final JPanel queryListPanel = new JPanel( new BorderLayout() );
queryListPanel.setBorder( BorderFactory.createEmptyBorder( 0, 5, 5, 0 ) );
queryListPanel.add( new JScrollPane( queryNameList ), BorderLayout.CENTER );
queryListPanel.add( queryListButtonsPanel, BorderLayout.NORTH );
return queryListPanel;
}
private JPanel createTransformParameterPanel() {
final JPanel stopOnErrorsPanel = new JPanel( new FlowLayout( FlowLayout.RIGHT, 5, 5 ) );
stopOnErrorsPanel.add( stopOnErrorsCheckBox );
final JPanel previewAndParameterPanel = new JPanel( new FlowLayout( FlowLayout.RIGHT, 5, 5 ) );
previewAndParameterPanel.add( new JButton( editParameterAction ) );
previewAndParameterPanel.add( new JButton( previewAction ) );
final JPanel transParameterPanel = new JPanel( new BorderLayout() );
transParameterPanel.add( stopOnErrorsPanel, BorderLayout.NORTH );
transParameterPanel.add( previewAndParameterPanel, BorderLayout.CENTER );
return transParameterPanel;
}
protected JPanel createDatasourcePanel() {
JPanel panel = new JPanel( new GridBagLayout() );
final BrowseAction browseAction = new BrowseAction();
queryNameList.addListSelectionListener( browseAction );
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets( 0, 0, 0, 13 );
panel.add( new JLabel( Messages.getString( "KettleDataSourceDialog.FileName" ) ), gbc );
gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
panel.add( fileTextField, gbc );
gbc = new GridBagConstraints();
gbc.gridx = 2;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
panel.add( new JButton( browseAction ), gbc );
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets( 0, 0, 5, 0 );
panel.add( new JLabel( Messages.getString( "KettleDataSourceDialog.Steps" ) ), gbc );
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 3;
gbc.gridwidth = 3;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.WEST;
panel.add( new JScrollPane( stepsList ), gbc );
return panel;
}
public KettleDataFactory performConfiguration( final DesignTimeContext context,
final KettleDataFactory dataFactory,
final String queryName ) throws KettleException {
configureFromDataFactory( dataFactory, queryName );
if ( performEdit() == false ) {
return null;
}
final KettleDataFactory kettleDataFactory = new KettleDataFactory();
for ( final KettleQueryEntry queryEntry : getQueryEntries() ) {
final KettleTransformationProducer producer = queryEntry.createProducer();
kettleDataFactory.setQuery( queryEntry.getName(), producer );
}
return kettleDataFactory;
}
protected KettleQueryEntry[] getQueryEntries() {
final KettleQueryEntry[] data = new KettleQueryEntry[ queryListModel.size() ];
queryListModel.copyInto( data );
return data;
}
protected void configureFromDataFactory( final KettleDataFactory dataFactory, final String selectedQueryName )
throws KettleException {
queryListModel.clear();
if ( dataFactory == null ) {
return;
}
KettleQueryEntry selectedDataSet = null;
final String[] queryNames = dataFactory.getQueryNames();
for ( int i = 0; i < queryNames.length; i++ ) {
final String queryName = queryNames[ i ];
final KettleTransformationProducer producer = dataFactory.getQuery( queryName );
final KettleQueryEntry dataSet = createQueryEntry( queryName, producer );
queryListModel.addElement( dataSet );
if ( ObjectUtilities.equal( selectedQueryName, queryName ) ) {
selectedDataSet = dataSet;
}
}
queryNameList.setSelectedValue( selectedDataSet, true );
}
protected boolean validateInputs( final boolean onConfirm ) {
getConfirmAction().setEnabled( queryNameList.getModel().getSize() > 0 );
if ( queryNameList.getModel().getSize() == 0 ) {
return false;
}
return true;
}
protected KettleQueryEntry createNewQueryEntry( final String queryName ) throws KettleException {
return new FileKettleQueryEntry( queryName );
}
protected KettleQueryEntry createQueryEntry( final String queryName,
final KettleTransformationProducer producer )
throws KettleException {
return new FileKettleQueryEntry( queryName, producer );
}
protected ListSelectionListener getQueryNameListener() {
return new QueryNameListSelectionListener();
}
protected void clearComponents() {
nameTextField.setText( "" );
fileTextField.setText( "" );
stepsList.setListData( new StepMeta[ 0 ] );
}
protected String findNextName() {
final HashSet<String> names = new HashSet<String>();
for ( int i = 0; i < queryListModel.getSize(); i++ ) {
final KettleQueryEntry o = (KettleQueryEntry) queryListModel.getElementAt( i );
names.add( o.getName() );
}
String queryName = Messages.getString( "KettleDataSourceDialog.Query" );
for ( int i = 1; i < 1000; ++i ) {
final String newQuery = Messages.getString( "KettleDataSourceDialog.Query" ) + " " + i;
if ( names.contains( newQuery ) == false ) {
queryName = newQuery;
break;
}
}
return queryName;
}
}