/*! * 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.designer.core.editor.parameters; import org.pentaho.reporting.designer.core.ReportDesignerContext; import org.pentaho.reporting.designer.core.ReportDesignerDocumentContext; import org.pentaho.reporting.designer.core.actions.global.DeleteAction; import org.pentaho.reporting.designer.core.actions.report.AddDataFactoryAction; import org.pentaho.reporting.designer.core.actions.report.EditQueryAction; import org.pentaho.reporting.designer.core.settings.WorkspaceSettings; import org.pentaho.reporting.designer.core.util.IconLoader; import org.pentaho.reporting.designer.core.util.exceptions.UncaughtExceptionsModel; import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition; import org.pentaho.reporting.engine.classic.core.CompoundDataFactory; import org.pentaho.reporting.engine.classic.core.DataFactory; import org.pentaho.reporting.engine.classic.core.DataFactoryContext; import org.pentaho.reporting.engine.classic.core.designtime.DataFactoryChange; import org.pentaho.reporting.engine.classic.core.designtime.DataSourcePlugin; import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeContext; import org.pentaho.reporting.engine.classic.core.designtime.datafactory.DesignTimeDataFactoryContext; import org.pentaho.reporting.engine.classic.core.metadata.DataFactoryMetaData; import org.pentaho.reporting.engine.classic.core.metadata.DataFactoryRegistry; import org.pentaho.reporting.engine.classic.core.metadata.GroupedMetaDataComparator; import org.pentaho.reporting.engine.classic.core.metadata.MaturityLevel; import org.pentaho.reporting.engine.classic.core.wizard.DataSchemaModel; import org.pentaho.reporting.libraries.base.util.ObjectUtilities; import org.pentaho.reporting.libraries.designtime.swing.BorderlessButton; import org.pentaho.reporting.libraries.designtime.swing.LibSwingUtil; import org.pentaho.reporting.libraries.designtime.swing.settings.LocaleSettings; import javax.swing.*; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import java.awt.*; import java.awt.event.ActionEvent; import java.beans.BeanInfo; import java.util.Arrays; import java.util.HashMap; import java.util.Locale; import java.util.Map; public class ProvisionDataSourcePanel extends JPanel { private class RemoveDataSourceAction extends AbstractAction implements TreeSelectionListener { public RemoveDataSourceAction() { putValue( Action.SMALL_ICON, IconLoader.getInstance().getRemoveIcon() ); putValue( Action.SHORT_DESCRIPTION, Messages.getString( "ParameterDialog.DeleteDataSourceAction" ) ); setEnabled( false ); } public void valueChanged( final TreeSelectionEvent e ) { setEnabled( isDataSourceSelected() ); } public void actionPerformed( final ActionEvent e ) { final int result = JOptionPane.showConfirmDialog( ProvisionDataSourcePanel.this, Messages.getString( "ParameterDialog.DeleteDataSourceWarningMessage" ), Messages.getString( "ParameterDialog.DeleteDataSourceWarningTitle" ), JOptionPane.YES_NO_OPTION ); if ( result == JOptionPane.YES_OPTION ) { final DataFactory theSelectedDataFactory = getSelectedDataSource(); // Delete data-source from structure panel reportDesignerContext.getActiveContext().getSelectionModel() .setSelectedElements( new Object[] { theSelectedDataFactory } ); final DeleteAction deleteAction = new DeleteAction(); deleteAction.setReportDesignerContext( reportDesignerContext ); deleteAction.actionPerformed( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, "" ) ); // Delete data-source from the Select data-source dialog availableDataSourcesModel.remove( theSelectedDataFactory ); } } } private class EditDataSourceAction extends AbstractAction implements TreeSelectionListener { private EditDataSourceAction() { putValue( Action.SMALL_ICON, IconLoader.getInstance().getEditIcon() ); putValue( Action.SHORT_DESCRIPTION, Messages.getString( "ParameterDialog.EditDataSourceAction" ) ); setEnabled( false ); } public void valueChanged( final TreeSelectionEvent e ) { if ( getSelectedDataSource() == null ) { setEnabled( false ); return; } setEnabled( true ); } public void actionPerformed( final ActionEvent e ) { final DataFactory dataFactory = getSelectedDataSource(); if ( dataFactory == null ) { return; } final DataFactoryMetaData metadata = dataFactory.getMetaData(); if ( metadata.isEditable() == false ) { return; } // Edit data-source from structure panel reportDesignerContext.getActiveContext().getSelectionModel().setSelectedElements( new Object[] { dataFactory } ); final EditQueryAction editQueryAction = new EditQueryAction(); editQueryAction.setReportDesignerContext( reportDesignerContext ); editQueryAction.actionPerformed( new ActionEvent( this, ActionEvent.ACTION_PERFORMED, "" ) ); final int idx = availableDataSourcesModel.indexOf( dataFactory ); if ( idx == -1 ) { throw new IllegalStateException( "DataSource Model is out of sync with the GUI" ); } if ( editQueryAction.getEditedDataFactory() != null ) { availableDataSourcesModel.edit( idx, editQueryAction.getEditedDataFactory() ); } } } private final class ShowAddDataSourcePopupAction extends AbstractAction { public ShowAddDataSourcePopupAction() { putValue( Action.SMALL_ICON, IconLoader.getInstance().getAddIcon() ); } public void actionPerformed( final ActionEvent e ) { final JPopupMenu menu = new JPopupMenu(); createDataSourceMenu( menu ); final Object source = e.getSource(); if ( source instanceof Component ) { final Component c = (Component) source; menu.show( c, 0, c.getHeight() ); } else { menu.show( ProvisionDataSourcePanel.this, 0, 0 ); } } } public boolean isDataSourceSelected() { final TreePath selectionPath = availableDataSources.getSelectionPath(); if ( selectionPath == null ) { return false; } return selectionPath.getLastPathComponent() instanceof DataFactoryWrapper; } public DataFactory getSelectedDataSource() { final TreePath selectionPath = availableDataSources.getSelectionPath(); if ( selectionPath == null ) { return null; } final int size = selectionPath.getPathCount(); if ( size >= 2 ) { final DataFactoryWrapper dataFactoryWrapper = (DataFactoryWrapper) selectionPath.getPathComponent( 1 ); return dataFactoryWrapper.getEditedDataFactory(); } return null; } private void createDataSourceMenu( final JComponent insertDataSourcesMenu ) { final DataFactoryMetaData[] datas = DataFactoryRegistry.getInstance().getAll(); final Map<String, Boolean> groupMap = new HashMap<String, Boolean>(); for ( int i = 0; i < datas.length; i++ ) { final DataFactoryMetaData data = datas[ i ]; if ( data.isHidden() ) { continue; } if ( data.isEditorAvailable() == false ) { continue; } final String currentGrouping = data.getGrouping( Locale.getDefault() ); groupMap.put( currentGrouping, groupMap.containsKey( currentGrouping ) ); } Arrays.sort( datas, new GroupedMetaDataComparator() ); Object grouping = null; JMenu subMenu = null; boolean firstElement = true; for ( int i = 0; i < datas.length; i++ ) { final DataFactoryMetaData data = datas[ i ]; if ( data.isHidden() ) { continue; } if ( data.isEditorAvailable() == false ) { continue; } if ( !WorkspaceSettings.getInstance().isVisible( data ) ) { continue; } final String currentGrouping = data.getGrouping( Locale.getDefault() ); final Boolean isMultiGrouping = groupMap.get( currentGrouping ); if ( firstElement == false ) { if ( ObjectUtilities.equal( currentGrouping, grouping ) == false ) { grouping = currentGrouping; if ( isMultiGrouping ) { subMenu = new JMenu( currentGrouping ); insertDataSourcesMenu.add( subMenu ); } } } else { firstElement = false; grouping = currentGrouping; if ( isMultiGrouping ) { subMenu = new JMenu( currentGrouping ); insertDataSourcesMenu.add( subMenu ); } } final AddDataSourceAction action = new AddDataSourceAction( data ); if ( isMultiGrouping ) { //noinspection ConstantConditions subMenu.add( new JMenuItem( action ) ); } else { insertDataSourcesMenu.add( new JMenuItem( action ) ); } } } private class AddDataSourceAction extends AbstractAction { private DataFactoryMetaData dataSourcePlugin; private AddDataSourceAction( final DataFactoryMetaData dataSourcePlugin ) { this.dataSourcePlugin = dataSourcePlugin; putValue( Action.NAME, dataSourcePlugin.getDisplayName( Locale.getDefault() ) ); putValue( Action.SHORT_DESCRIPTION, dataSourcePlugin.getDescription( Locale.getDefault() ) ); final Image image = dataSourcePlugin.getIcon( Locale.getDefault(), BeanInfo.ICON_COLOR_32x32 ); if ( image != null ) { putValue( Action.SMALL_ICON, new ImageIcon( image ) ); } } public void actionPerformed( final ActionEvent e ) { final DataSourcePlugin editor = dataSourcePlugin.createEditor(); if ( editor == null ) { return; } final DataFactory dataFactory = editor.performEdit( new DataSourceDesignTimeContext(), null, null, null ); if ( dataFactory == null ) { return; } // Add data-source factory into Structure panel. // This happens after user adds a new data source from the Edit DataSource dialog AddDataFactoryAction .addDataFactory( reportDesignerContext.getActiveContext(), dataFactory, new DataFactoryChange[ 0 ] ); availableDataSourcesModel.add( new DataFactoryWrapper( null, dataFactory ) ); expandAllNodes(); SwingUtilities .invokeLater( new DataTabSetVisible( reportDesignerContext, reportDesignerContext.getActiveContext() ) ); } } private static class DataTabSetVisible implements Runnable { private ReportDesignerContext designerContext; private ReportDesignerDocumentContext<?> activeContext; public DataTabSetVisible( final ReportDesignerContext designerContext, final ReportDesignerDocumentContext<?> activeContext ) { this.designerContext = designerContext; this.activeContext = activeContext; } public void run() { if ( this.activeContext == null ) { return; } designerContext.setActiveDocument( activeContext ); designerContext.getView().showDataTree(); } } private class DataSourceDesignTimeContext implements DesignTimeContext { public DataSourceDesignTimeContext() { } /** * The currently active report (or subreport). * * @return the active report. */ public AbstractReportDefinition getReport() { return reportDesignerContext.getActiveContext().getContextRoot(); } /** * The parent window in the GUI for showing modal dialogs. * * @return the window or null, if there is no parent. */ public Window getParentWindow() { return LibSwingUtil.getWindowAncestor( ProvisionDataSourcePanel.this ); } public DataSchemaModel getDataSchemaModel() { // todo: Filter so that only env- and parameter are visible here. return reportDesignerContext.getActiveContext().getReportDataSchemaModel(); } public void error( final Exception e ) { UncaughtExceptionsModel.getInstance().addException( e ); } public void userError( final Exception e ) { UncaughtExceptionsModel.getInstance().addException( e ); } public LocaleSettings getLocaleSettings() { return WorkspaceSettings.getInstance(); } public boolean isShowExpertItems() { return WorkspaceSettings.getInstance().isShowExpertItems(); } public boolean isShowDeprecatedItems() { return WorkspaceSettings.getInstance().isShowDeprecatedItems(); } public DataFactoryContext getDataFactoryContext() { return new DesignTimeDataFactoryContext( reportDesignerContext.getActiveContext().getContextRoot() ); } public MaturityLevel getMaturityLevel() { return WorkspaceSettings.getInstance().getMaturityLevel(); } } private JTree availableDataSources; private DataFactoryTreeModel availableDataSourcesModel; private ReportDesignerContext reportDesignerContext; public ProvisionDataSourcePanel() { availableDataSourcesModel = new DataFactoryTreeModel(); availableDataSources = new JTree( availableDataSourcesModel ); availableDataSources.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION ); availableDataSources.setCellRenderer( new DataFactoryTreeCellRenderer() ); availableDataSources.setRootVisible( false ); init(); } public ReportDesignerContext getReportDesignerContext() { return reportDesignerContext; } public void setReportDesignerContext( final ReportDesignerContext reportDesignerContext ) { this.reportDesignerContext = reportDesignerContext; } public void importDataSourcesFromMaster( final CompoundDataFactory cdf ) { availableDataSourcesModel.importFromReport( cdf ); } public DataFactoryTreeModel getDataFactoryTreeModel() { return availableDataSourcesModel; } public JTree getDataSourcesTree() { return availableDataSources; } public String getSelectedQueryName() { final Object node = availableDataSources.getLastSelectedPathComponent(); if ( node != null ) { return node.toString(); } return ""; } public void expandAllNodes() { for ( int i = 0; i < availableDataSources.getRowCount(); i++ ) { availableDataSources.expandRow( i ); } } protected void init() { final RemoveDataSourceAction removeAction = new RemoveDataSourceAction(); final EditDataSourceAction editDataSourceAction = new EditDataSourceAction(); final ShowAddDataSourcePopupAction showAddDataSourcePopupAction = new ShowAddDataSourcePopupAction(); availableDataSources.addTreeSelectionListener( editDataSourceAction ); availableDataSources.addTreeSelectionListener( removeAction ); final JScrollPane theScrollPanel = new JScrollPane( availableDataSources ); theScrollPanel.setAutoscrolls( true ); final JPanel theDataSetsButtonPanel = new JPanel(); theDataSetsButtonPanel.setLayout( new FlowLayout( FlowLayout.RIGHT ) ); theDataSetsButtonPanel.add( new BorderlessButton( showAddDataSourcePopupAction ) ); theDataSetsButtonPanel.add( new BorderlessButton( editDataSourceAction ) ); theDataSetsButtonPanel.add( new BorderlessButton( removeAction ) ); final JPanel theControlsPanel = new JPanel( new BorderLayout() ); theControlsPanel.add( new JLabel( Messages.getString( "ParameterDialog.DataSources" ) ), BorderLayout.WEST ); theControlsPanel.add( theDataSetsButtonPanel, BorderLayout.EAST ); final JPanel dataSetsPanel = new JPanel( new BorderLayout() ); dataSetsPanel.setBorder( BorderFactory.createEmptyBorder( 8, 8, 8, 8 ) ); dataSetsPanel.add( theScrollPanel, BorderLayout.CENTER ); dataSetsPanel.add( theControlsPanel, BorderLayout.NORTH ); setLayout( new BorderLayout() ); add( dataSetsPanel, BorderLayout.CENTER ); } }