/* * 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) 2006 - 2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.ui.datasources.kettle.embedded; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.step.BaseStepMeta; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.di.ui.trans.step.BaseStepGenericXulDialog; import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException; import org.pentaho.reporting.engine.classic.extensions.datasources.kettle.EmbeddedKettleDataFactoryMetaData; import org.pentaho.ui.xul.XulComponent; import org.pentaho.ui.xul.swing.tags.SwingDialog; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.UnsupportedEncodingException; import java.lang.reflect.Constructor; import java.util.ArrayList; public class XulDialogHelper { private static final Log logger = LogFactory.getLog( XulDialogHelper.class ); private class ChangeHandler implements PropertyChangeListener { public void propertyChange( final PropertyChangeEvent evt ) { // regardless what the input is, forward it to check whether the dialog is valid. ChangeEvent event = new ChangeEvent( this ); for ( int i = 0; i < changeListeners.size(); i++ ) { ChangeListener listener = changeListeners.get( i ); listener.stateChanged( event ); } } } private BaseStepGenericXulDialog dialog; private TransMeta transformation; private ArrayList<ChangeListener> changeListeners; private JComponent editor; public XulDialogHelper( final TransMeta transformation ) { this.transformation = transformation; this.changeListeners = new ArrayList<ChangeListener>(); } public void addChangeListener( ChangeListener l ) { this.changeListeners.add( l ); } public void removeChangeListener( ChangeListener l ) { this.changeListeners.remove( l ); } public JComponent createEditor() throws ReportDataFactoryException { if ( editor != null ) { return editor; } dialog = createDialog(); if ( dialog == null ) { editor = new JPanel(); return editor; } // validate is a hardcoded name inside the xul dialogs dialog.addPropertyChangeListener( new ChangeHandler() ); dialog.validate(); XulComponent root = dialog.getXulDomContainer().getDocumentRoot().getElementById( "root" ); // Without the following two lines of code, message boxes and prompts will freeze the dialog... // There must be a better way. SwingDialog parent = (SwingDialog) root.getParent(); JComponent panel = parent.getContainer(); dialog.setModalParent( panel ); editor = panel; return panel; } private BaseStepGenericXulDialog createDialog() throws ReportDataFactoryException { final StepMeta step = findInputStep(); if ( step == null ) { return null; } // Render datasource specific dialog for editing step details... try { final String dlgClassName = step.getStepMetaInterface().getDialogClassName().replace( "Dialog", "XulDialog" ); ClassLoader pluginClassLoader = step.getStepMetaInterface().getClass().getClassLoader(); final Class<BaseStepGenericXulDialog> dialog = (Class<BaseStepGenericXulDialog>) Class.forName( dlgClassName, true, pluginClassLoader ); final Constructor<BaseStepGenericXulDialog> constructor = dialog.getDeclaredConstructor( Object.class, BaseStepMeta.class, TransMeta.class, String.class ); return constructor.newInstance( null, step.getStepMetaInterface(), step.getParentTransMeta(), EmbeddedKettleDataFactoryMetaData.DATA_CONFIGURATION_STEP ); } catch ( Exception e ) { logger .error( "Critical error attempting to dynamically create dialog. This datasource will not be available.", e ); throw new ReportDataFactoryException( "Error attempting to dynamically create dialog. Abort dialog rendering." ); } } private StepMeta findInputStep() { return transformation.findStep( EmbeddedKettleDataFactoryMetaData.DATA_CONFIGURATION_STEP ); } public boolean validate() { if ( dialog != null ) { return dialog.validate(); } return true; } public void accept() { if ( dialog != null ) { dialog.onAccept(); } } public byte[] getRawData() throws KettleException { accept(); try { return transformation.getXML().getBytes( "UTF8" ); } catch ( UnsupportedEncodingException e ) { throw new KettleException( e ); } } public void clear() { if ( dialog != null ) { dialog.clear(); } } }