/* * 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 - 2015 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.designer.extensions.pentaho.drilldown.swing; import org.apache.commons.lang.ObjectUtils; import org.pentaho.reporting.designer.core.ReportDesignerContext; import org.pentaho.reporting.designer.core.auth.AuthenticationData; import org.pentaho.reporting.designer.core.auth.AuthenticationStore; import org.pentaho.reporting.designer.core.editor.ReportDocumentContext; import org.pentaho.reporting.designer.core.editor.drilldown.DrillDownParameterRefreshEvent; import org.pentaho.reporting.designer.core.editor.drilldown.DrillDownParameterRefreshListener; import org.pentaho.reporting.designer.core.editor.drilldown.DrillDownParameterTable; import org.pentaho.reporting.designer.core.editor.drilldown.basic.DrillDownModelWrapper; import org.pentaho.reporting.designer.core.editor.drilldown.model.DrillDownParameter; import org.pentaho.reporting.designer.core.editor.drilldown.swing.DocumentBindingListener; import org.pentaho.reporting.designer.extensions.pentaho.drilldown.PentahoParameterRefreshHandler; import org.pentaho.reporting.designer.extensions.pentaho.drilldown.PentahoPathModel; import org.pentaho.reporting.designer.extensions.pentaho.drilldown.SelectDrillTargetTask; import org.pentaho.reporting.designer.extensions.pentaho.repository.actions.AuthenticatedServerTask; import org.pentaho.reporting.designer.extensions.pentaho.repository.actions.LoginTask; import org.pentaho.reporting.engine.classic.core.MasterReport; import org.pentaho.reporting.engine.classic.core.parameters.ParameterDefinitionEntry; import org.pentaho.reporting.engine.classic.core.parameters.ReportParameterDefinition; import org.pentaho.reporting.engine.classic.extensions.drilldown.DrillDownProfile; import org.pentaho.reporting.engine.classic.extensions.drilldown.DrillDownProfileMetaData; import org.pentaho.reporting.libraries.base.util.StringUtils; import org.pentaho.reporting.libraries.formula.util.FormulaUtil; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JTextField; import javax.swing.SwingUtilities; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashMap; /** * Controller of the Swing analog for sugar-xaction-drilldown.xul dialog. * * @author Aleksandr Kozlov */ public class SwingRemoteDrillDownController { /* Dialog itself. */ private final SwingRemoteDrillDownUi drillDownUi; /* Model */ private final DrillDownModelWrapper modelWrapper; /* Context of the report designer. */ private final ReportDesignerContext reportDesignerContext; /* Xul-based class that contains login data (maybe rewrite too). --Kaa */ private final PentahoPathModel pentahoPathWrapper; /* PropertyChangeListener for model. */ private ModelWrapperUpdateHandler modelWrapperUpdateHandler; /* PropertyChangeListener for path wrapper. */ private PathWrapperUpdateHandler pathWrapperUpdateHandler; /** * Create controller of the Swing analog for sugar-xaction-drilldown.xul dialog. * @param drillDownUi dialog itself. * @param reportDesignerContext context of the report designer. * @param modelWrapper model. */ public SwingRemoteDrillDownController( SwingRemoteDrillDownUi drillDownUi, ReportDesignerContext reportDesignerContext, DrillDownModelWrapper modelWrapper ) { this.drillDownUi = drillDownUi; this.reportDesignerContext = reportDesignerContext; this.modelWrapper = modelWrapper; pentahoPathWrapper = new PentahoPathModel( reportDesignerContext ); } /** * Initialize component of the controller. */ public void init() { // Listeners modelWrapperUpdateHandler = new ModelWrapperUpdateHandler(); pathWrapperUpdateHandler = new PathWrapperUpdateHandler(); modelWrapper.addPropertyChangeListener( modelWrapperUpdateHandler ); pentahoPathWrapper.addPropertyChangeListener( pathWrapperUpdateHandler ); // Report extensions initExtensionsMap( pentahoPathWrapper ); // Server URL check box final JCheckBox includeServerUrl = drillDownUi.getComponent( SwingRemoteDrillDownUi.ComponentLookup.SERVER_URL_CHECKBOX ); includeServerUrl.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent e ) { pentahoPathWrapper.setUseRemoteServer( includeServerUrl.isSelected() ); } } ); // Server URL field JTextField serverUrlField = drillDownUi.getComponent( SwingRemoteDrillDownUi.ComponentLookup.SERVER_URL_FIELD ); serverUrlField.getDocument().addDocumentListener( new DocumentBindingListener() { @Override protected void setData( String data ) { pentahoPathWrapper.setLocalPath( data ); } } ); // Login button JButton loginButton = drillDownUi.getComponent( SwingRemoteDrillDownUi.ComponentLookup.LOGIN_BUTTON ); loginButton.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent e ) { final LoginTask loginTask = new LoginTask( reportDesignerContext, drillDownUi.getEditorPanel().getParent(), new LoginCompleteTask( null ) ); SwingUtilities.invokeLater( loginTask ); } } ); // Path field JTextField pathField = drillDownUi.getComponent( SwingRemoteDrillDownUi.ComponentLookup.PATH_FIELD ); serverUrlField.getDocument().addDocumentListener( new DocumentBindingListener() { @Override protected void setData( String data ) { pentahoPathWrapper.setServerPath( data ); } } ); // Browse button JButton browseButton = drillDownUi.getComponent( SwingRemoteDrillDownUi.ComponentLookup.BROWSE_BUTTON ); browseButton.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent e ) { final ReportDocumentContext activeContext = reportDesignerContext.getActiveContext(); if ( pentahoPathWrapper.getLoginData() == null ) { final String path = modelWrapper.getDrillDownPath(); if ( path != null ) { final AuthenticationStore authStore = activeContext.getAuthenticationStore(); final String username = authStore.getUsername( path ); final String password = authStore.getPassword( path ); final int timeout = authStore.getIntOption( path, "timeout", 0 ); pentahoPathWrapper.setLoginData( new AuthenticationData( path, username, password, timeout ) ); } } final LoginTask loginTask = new LoginTask( reportDesignerContext, drillDownUi.getEditorPanel().getParent(), new LoginCompleteTask( new SelectDrillTargetTask( pentahoPathWrapper, drillDownUi.getEditorPanel().getParent(), new RefreshParameterTask(), activeContext ) ), pentahoPathWrapper.getLoginData() ); SwingUtilities.invokeLater( loginTask ); } } ); // Parameter Table DrillDownParameterTable table = drillDownUi.getComponent( SwingRemoteDrillDownUi.ComponentLookup.PARAMETER_TABLE ); table.addDrillDownParameterRefreshListener( new UpdateParametersHandler() ); table.addPropertyChangeListener( DrillDownParameterTable.DRILL_DOWN_PARAMETER_PROPERTY, new TableModelBinding() ); PentahoParameterRefreshHandler parameterRefreshHandler = new PentahoParameterRefreshHandler( pentahoPathWrapper, reportDesignerContext, drillDownUi.getEditorPanel() ); table.addDrillDownParameterRefreshListener( parameterRefreshHandler ); parameterRefreshHandler.setParameterTable( table ); pentahoPathWrapper.addPropertyChangeListener( PentahoPathModel.LOCAL_PATH_PROPERTY, new CheckEmptyPathHandler( table ) ); SwingUtilities.invokeLater( new RefreshParameterTask() ); // restore any parameters that might have been lost while initializing the UI. modelWrapper.setDrillDownParameter( modelWrapper.getDrillDownParameter() ); pentahoPathWrapper.setLocalPathFromParameter( modelWrapper.getDrillDownParameter() ); if ( StringUtils.isEmpty( modelWrapper.getDrillDownPath() ) ) { pentahoPathWrapper.setUseRemoteServer( false ); final ReportDocumentContext reportRenderContext = reportDesignerContext.getActiveContext(); if ( reportRenderContext != null ) { final Object o = reportRenderContext.getProperties().get( "pentaho-login-url" ); if ( o != null ) { pentahoPathWrapper.setServerPath( String.valueOf( o ) ); } else { pentahoPathWrapper.setServerPath( null ); } } else { pentahoPathWrapper.setServerPath( null ); } } else { pentahoPathWrapper.setUseRemoteServer( true ); pentahoPathWrapper.setServerPath( modelWrapper.getDrillDownPath() ); } } /** * Initialize file extensions map for the path wrapper. * * @param pentahoPathWrapper path wrapper. */ private void initExtensionsMap( PentahoPathModel pentahoPathWrapper ) { final DrillDownProfile[] drillDownProfileByGroup = DrillDownProfileMetaData.getInstance().getDrillDownProfileByGroup( "pentaho-sugar" ); // pentaho-sugar for ( int i = 0; i < drillDownProfileByGroup.length; i++ ) { final DrillDownProfile profile = drillDownProfileByGroup[i]; final String profileName = profile.getName(); final String extension = profile.getAttribute( "extension" ); final boolean noParameter = profileName.endsWith( "-no-parameter" ); final boolean local = profileName.startsWith( "local-" ); if ( StringUtils.isEmpty( extension ) ) { pentahoPathWrapper.registerExtension( null, local, noParameter, profileName ); } else { pentahoPathWrapper.registerExtension( "." + extension, local, noParameter, profileName ); } } } /** * Deactivate controller. */ public void deactivate() { modelWrapper.removePropertyChangeListener( modelWrapperUpdateHandler ); pentahoPathWrapper.removePropertyChangeListener( pathWrapperUpdateHandler ); } /** * Filter parameters of the drilldown parameter table. * (Copied from superclass) * * @param parameters parameters array. * @return filtered parameters array. */ private DrillDownParameter[] filterParameterSuper( final DrillDownParameter[] parameters ) { final ArrayList<DrillDownParameter> list = new ArrayList<DrillDownParameter>( parameters.length ); for ( int i = 0; i < parameters.length; i++ ) { final DrillDownParameter downParameter = parameters[ i ]; if ( StringUtils.isEmpty( downParameter.getFormulaFragment() ) ) { continue; } list.add( downParameter ); } return list.toArray( new DrillDownParameter[ list.size() ] ); } /** * Filter parameters of the drilldown parameter table. * * @param parameters parameters array. * @return filtered parameters array. */ protected DrillDownParameter[] filterParameter( final DrillDownParameter[] parameters ) { // modify the parameter model. final ArrayList<DrillDownParameter> list = new ArrayList<DrillDownParameter>(); boolean pathAdded = false; for ( int i = 0; i < parameters.length; i++ ) { final DrillDownParameter drillDownParameter = parameters[i]; if ( "::pentaho-path".equals( drillDownParameter.getName() ) && pathAdded == false ) { list.add( new DrillDownParameter( "::pentaho-path", FormulaUtil.quoteString( pentahoPathWrapper.getLocalPath() ) ) ); pathAdded = true; } else { if ( !( "solution".equals( drillDownParameter.getName() ) || "path".equals( drillDownParameter.getName() ) || "name" .equals( drillDownParameter.getName() ) ) ) { list.add( drillDownParameter ); } } } if ( pathAdded == false ) { list.add( 0, new DrillDownParameter( "::pentaho-path", FormulaUtil .quoteString( pentahoPathWrapper.getLocalPath() ) ) ); } return filterParameterSuper( list.toArray( new DrillDownParameter[list.size()] ) ); } /** * Service task to perform after BI-server authentication. */ private class LoginCompleteTask implements AuthenticatedServerTask { private AuthenticationData loginData; private boolean storeUpdates; private AuthenticatedServerTask nextTask; private LoginCompleteTask( final AuthenticatedServerTask nextTask ) { this.nextTask = nextTask; } public void setLoginData( final AuthenticationData loginData, final boolean storeUpdates ) { this.loginData = loginData; this.storeUpdates = storeUpdates; } public void run() { pentahoPathWrapper.setLoginData( loginData ); final ReportDocumentContext reportRenderContext = reportDesignerContext.getActiveContext(); final Object o = reportRenderContext.getProperties().get( "pentaho-login-url" ); if ( o == null ) { reportRenderContext.getProperties().put( "pentaho-login-url", loginData.getUrl() ); } if ( nextTask != null ) { nextTask.setLoginData( loginData, storeUpdates ); SwingUtilities.invokeLater( nextTask ); } } } /** * PropertyChangeListener for model wrapper. */ private class ModelWrapperUpdateHandler implements PropertyChangeListener { @Override public void propertyChange( PropertyChangeEvent evt ) { AuthenticationData loginData = pentahoPathWrapper.getLoginData(); String serverUrl = loginData == null ? "" : loginData.getUrl(); JTextField serverUrlField = drillDownUi.<JTextField>getComponent( SwingRemoteDrillDownUi.ComponentLookup.SERVER_URL_FIELD ); if ( !ObjectUtils.equals( serverUrlField.getText(), serverUrl ) ) { serverUrlField.setText( serverUrl ); } String path = pentahoPathWrapper.getLocalPath(); JTextField pathField = drillDownUi.<JTextField>getComponent( SwingRemoteDrillDownUi.ComponentLookup.PATH_FIELD ); if ( !ObjectUtils.equals( pathField.getText(), path ) ) { pathField.setText( path ); } } } /** * PropertyChangeListener for drill down parameter table (empty check). */ private class CheckEmptyPathHandler implements PropertyChangeListener { private DrillDownParameterTable paramTableElement; private CheckEmptyPathHandler( final DrillDownParameterTable paramTableElement ) { this.paramTableElement = paramTableElement; propertyChange( null ); } public void propertyChange( final PropertyChangeEvent evt ) { if ( StringUtils.isEmpty( pentahoPathWrapper.getLocalPath() ) ) { paramTableElement.setEnabled( false ); } else { paramTableElement.setEnabled( true ); } } } /** * PropertyChangeListener for path wrapper. */ private class PathWrapperUpdateHandler implements PropertyChangeListener { private PathWrapperUpdateHandler() { } public void propertyChange( final PropertyChangeEvent evt ) { if ( PentahoPathModel.LOCAL_PATH_PROPERTY.equals( evt.getPropertyName() ) ) { modelWrapper.setDrillDownParameter( filterParameter( modelWrapper.getDrillDownParameter() ) ); modelWrapper.setDrillDownConfig( pentahoPathWrapper.getDrillDownProfile() ); } else if ( PentahoPathModel.USE_REMOTE_SERVER_PROPERTY.equals( evt.getPropertyName() ) ) { modelWrapper.setDrillDownConfig( pentahoPathWrapper.getDrillDownProfile() ); if ( pentahoPathWrapper.isUseRemoteServer() == false ) { modelWrapper.setDrillDownPath( null ); } else { modelWrapper.setDrillDownPath( pentahoPathWrapper.getServerPath() ); } } else if ( PentahoPathModel.HIDE_PARAMETER_UI_PROPERTY.equals( evt.getPropertyName() ) ) { modelWrapper.setDrillDownConfig( pentahoPathWrapper.getDrillDownProfile() ); } else if ( PentahoPathModel.LOGIN_DATA_PROPERTY.equals( evt.getPropertyName() ) ) { if ( pentahoPathWrapper.isUseRemoteServer() == false ) { modelWrapper.setDrillDownPath( null ); } else { modelWrapper.setDrillDownPath( pentahoPathWrapper.getServerPath() ); } } } } /** * PropertyChangeListener for drill down parameter table. */ private class TableModelBinding implements PropertyChangeListener { /** * {@inheritDoc} */ public void propertyChange( final PropertyChangeEvent evt ) { modelWrapper.setDrillDownParameter( filterParameter( ( drillDownUi.<DrillDownParameterTable>getComponent( SwingRemoteDrillDownUi.ComponentLookup.PARAMETER_TABLE ) ).getDrillDownParameter() ) ); } } /** * ParameterRefreshListener for drill down parameter table. */ private class UpdateParametersHandler implements DrillDownParameterRefreshListener { /** * {@inheritDoc} */ public void requestParameterRefresh( final DrillDownParameterRefreshEvent event ) { final HashMap<String, DrillDownParameter> entries = new HashMap<String, DrillDownParameter>(); final DrillDownParameter[] originalParams = event.getParameter(); for ( int i = 0; i < originalParams.length; i++ ) { final DrillDownParameter param = originalParams[ i ]; param.setType( DrillDownParameter.Type.MANUAL ); entries.put( param.getName(), param ); } final ReportDocumentContext activeContext = reportDesignerContext.getActiveContext(); final MasterReport masterReportElement = activeContext.getContextRoot(); final ReportParameterDefinition reportParams = masterReportElement.getParameterDefinition(); final ParameterDefinitionEntry[] parameterDefinitionEntries = reportParams.getParameterDefinitions(); for ( int i = 0; i < parameterDefinitionEntries.length; i++ ) { final ParameterDefinitionEntry entry = parameterDefinitionEntries[i]; if ( entries.containsKey( entry.getName() ) == false ) { entries.put( entry.getName(), new DrillDownParameter( entry.getName(), null, DrillDownParameter.Type.PREDEFINED, false, false ) ); } else { final DrillDownParameter parameter = entries.get( entry.getName() ); parameter.setType( DrillDownParameter.Type.PREDEFINED ); } } final DrillDownParameter[] parameters = entries.values().toArray( new DrillDownParameter[ entries.size() ] ); modelWrapper.setDrillDownParameter( parameters ); ( drillDownUi.<DrillDownParameterTable>getComponent( SwingRemoteDrillDownUi.ComponentLookup.PARAMETER_TABLE ) ).setDrillDownParameter( parameters ); } } /** * Service task to refresh drill down parameters table. */ protected class RefreshParameterTask implements Runnable { public void run() { ( (DrillDownParameterTable) drillDownUi.getComponent( SwingRemoteDrillDownUi.ComponentLookup.PARAMETER_TABLE ) ).refreshParameterData(); } } }