/*! * 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.reporting.engine.classic.core.ReportDataFactoryException; import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeContext; import org.pentaho.reporting.engine.classic.core.metadata.DataFactoryMetaData; import org.pentaho.reporting.engine.classic.core.metadata.DataFactoryRegistry; import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.EmbeddedKettleTransformationProducer; import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.KettleDataFactory; import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.KettleTransformationProducer; import javax.swing.*; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; /** * @author Gretchen Moran */ public class EmbeddedKettleDataSourceDialog extends KettleDataSourceDialog { private static final long serialVersionUID = 5030572665265231736L; private static final Log logger = LogFactory.getLog( EmbeddedKettleDataSourceDialog.class ); private String datasourceId = null; private JPanel datasourcePanel; private EmbeddedKettleQueryEntry lastSelectedQuery = null; /** * This listener is registered with the XUL dialog. * * @author gmoran */ protected class PreviewChangeListener implements PropertyChangeListener { @Override public void propertyChange( PropertyChangeEvent evt ) { if ( evt.getPropertyName().equals( "validated" ) ) { if ( lastSelectedQuery == null ) { getPreviewAction().setEnabled( false ); } else { getPreviewAction().setEnabled( Boolean.TRUE.equals( evt.getNewValue() ) ); } } } } private class EmbeddedQueryNameListSelectionListener extends QueryNameListSelectionListener { private EmbeddedQueryNameListSelectionListener() { } protected void handleSelection( final KettleQueryEntry value ) { if ( value == null ) { setPanelEnabled( false, datasourcePanel ); lastSelectedQuery = null; return; } final DesignTimeContext designTimeContext = getDesignTimeContext(); final Action editParameterAction = getEditParameterAction(); try { final EmbeddedKettleQueryEntry selectedQuery = (EmbeddedKettleQueryEntry) value; setPanelEnabled( true, datasourcePanel ); // This change event gets fired twice, causing the dialog to update twice.. let's stop that. if ( ( lastSelectedQuery == null ) || ( selectedQuery != lastSelectedQuery ) ) { lastSelectedQuery = selectedQuery; updateQueryName( selectedQuery.getName() ); datasourcePanel.removeAll(); datasourcePanel.add( selectedQuery.createUI(), BorderLayout.CENTER ); datasourcePanel.revalidate(); datasourcePanel.repaint(); } getStopOnErrorsCheckBox().setSelected( selectedQuery.isStopOnErrors() ); editParameterAction.setEnabled( true ); } catch ( Exception e1 ) { designTimeContext.error( e1 ); editParameterAction.setEnabled( false ); } catch ( Throwable t1 ) { designTimeContext.error( new RuntimeException( "Fatal error", t1 ) ); editParameterAction.setEnabled( false ); } } } public EmbeddedKettleDataSourceDialog( final DesignTimeContext designTimeContext, final JDialog parent, String id ) { super( designTimeContext, parent ); datasourceId = id; setTitle( getDialogTitle() ); } public EmbeddedKettleDataSourceDialog( final DesignTimeContext designTimeContext, final JFrame parent, String id ) { super( designTimeContext, parent ); datasourceId = id; setTitle( getDialogTitle() ); } public EmbeddedKettleDataSourceDialog( final DesignTimeContext designTimeContext, String id ) { super( designTimeContext ); datasourceId = id; setTitle( getDialogTitle() ); } @Override protected JPanel createDatasourcePanel() { datasourcePanel = new JPanel( new BorderLayout() ); return datasourcePanel; } private void refreshQueryUIComponents() throws KettleException, ReportDataFactoryException { if ( datasourcePanel.getComponentCount() <= 0 ) { EmbeddedKettleQueryEntry entry = createNewQueryEntry( findNextName() ); datasourcePanel.removeAll(); datasourcePanel.add( entry.createUI(), BorderLayout.CENTER ); datasourcePanel.revalidate(); setPanelEnabled( false, datasourcePanel ); } } protected String getDialogTitle() { if ( datasourceId == null ) { return ""; } DataFactoryMetaData meta = DataFactoryRegistry.getInstance().getMetaData( datasourceId ); String displayName = meta.getDisplayName( getLocale() ); return Messages.getString( "KettleEmbeddedDataSourceDialog.Title", displayName ); } protected String getDialogId() { return "EmbeddedKettleDataSourceDialog"; } @Override protected boolean validateInputs( boolean onConfirm ) { boolean valid = true; for ( final KettleQueryEntry queryEntry : getQueryEntries() ) { valid = queryEntry.isValidated(); if ( !valid ) { break; } } if ( valid == false && onConfirm == true ) { int val = JOptionPane.showConfirmDialog( this, Messages.getString( "EmbeddedKettleDataSourceDialog.QueryErrorWarning" ), Messages.getString( "EmbeddedKettleDataSourceDialog.QueryErrorTitle" ), JOptionPane.OK_CANCEL_OPTION ); valid = ( val == JOptionPane.OK_OPTION ); } return valid && super.validateInputs( onConfirm ); } public KettleDataFactory performConfiguration( DesignTimeContext context, final KettleDataFactory dataFactory, final String queryName ) throws KettleException { configureFromDataFactory( dataFactory, queryName ); if ( ( dataFactory == null ) || ( !dataFactory.queriesAreHomogeneous() ) ) { // allow caller to render the default dialog... we are done here return super.performConfiguration( context, dataFactory, queryName ); } else { try { refreshQueryUIComponents(); if ( performEdit() == false ) { return null; } } catch ( Exception e ) { // attempt to fall back to the default dialog... //TODO: LOG SOMETHING USEFUL HERE return super.performConfiguration( context, dataFactory, queryName ); } } final KettleDataFactory kettleDataFactory = new KettleDataFactory(); kettleDataFactory.setMetadata( dataFactory.getMetaData() ); for ( final KettleQueryEntry queryEntry : getQueryEntries() ) { final KettleTransformationProducer producer = queryEntry.createProducer(); kettleDataFactory.setQuery( queryEntry.getName(), producer ); } return kettleDataFactory; } protected EmbeddedKettleQueryEntry createNewQueryEntry( String queryName ) throws KettleException { EmbeddedKettleQueryEntry entry = EmbeddedKettleQueryEntry.createFromTemplate( queryName, datasourceId ); entry.addPropertyChangeListener( "validated", new PreviewChangeListener() ); return entry; } protected KettleQueryEntry createQueryEntry( String queryName, KettleTransformationProducer producer ) throws KettleException { if ( datasourceId == null || producer instanceof EmbeddedKettleTransformationProducer == false ) { return new FileKettleQueryEntry( queryName ); } try { EmbeddedKettleTransformationProducer prod = (EmbeddedKettleTransformationProducer) producer; EmbeddedKettleQueryEntry entry = EmbeddedKettleQueryEntry.createFromExisting( queryName, prod, getDesignTimeContext().getDataFactoryContext() ); entry.addPropertyChangeListener( "validated", new PreviewChangeListener() ); return entry; } catch ( ReportDataFactoryException e ) { throw new KettleException( e ); } } protected ListSelectionListener getQueryNameListener() { return new EmbeddedQueryNameListSelectionListener(); } /** * This method makes it possible to control any panel that gets rendered via XUL, without having to create hooks or * listeners into the XUL dialog. The presence of a query object dictates whether the panel should be enabled or * disabled. * * @param enable enable/disable the configuration panel * @param c */ private void setPanelEnabled( boolean enable, Component c ) { if ( null == c ) { return; } Container container = null; if ( c instanceof Container ) { container = (Container) c; } if ( container != null ) { Component[] components = container.getComponents(); for ( int i = 0; i < container.getComponentCount(); i++ ) { Component component = components[ i ]; setPanelEnabled( enable, component ); } } c.setEnabled( enable ); } @Override protected void clearComponents() { final EmbeddedKettleQueryEntry kettleQueryEntry = (EmbeddedKettleQueryEntry) getSelectedQuery(); kettleQueryEntry.clear(); super.clearComponents(); } }