/*! * 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.extensions.legacycharts; import org.jfree.chart.JFreeChart; import org.pentaho.reporting.designer.core.settings.WorkspaceSettings; import org.pentaho.reporting.designer.core.util.exceptions.UncaughtExceptionsModel; import org.pentaho.reporting.engine.classic.core.function.Expression; import org.pentaho.reporting.engine.classic.core.function.StructureFunction; import org.pentaho.reporting.engine.classic.core.metadata.ExpressionMetaData; import org.pentaho.reporting.engine.classic.core.metadata.ExpressionRegistry; import org.pentaho.reporting.engine.classic.core.metadata.GroupedMetaDataComparator; import org.pentaho.reporting.engine.classic.core.util.beans.BeanException; import org.pentaho.reporting.engine.classic.core.util.beans.BeanUtility; import javax.swing.*; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.Arrays; public class LegacyChartEditModel { private class PrimaryDataSourceSelectionHandler implements ListDataListener { private PrimaryDataSourceSelectionHandler() { } public void intervalAdded( final ListDataEvent e ) { // ignored } public void intervalRemoved( final ListDataEvent e ) { // ignored } public void contentsChanged( final ListDataEvent e ) { final ExpressionMetaData o = (ExpressionMetaData) getPrimaryDataSourcesModel().getSelectedItem(); if ( o == null ) { setPrimaryDataSource( null ); return; } final Expression primaryDataSourceExpression = getPrimaryDataSource(); if ( primaryDataSourceExpression != null && primaryDataSourceExpression.getClass() .equals( o.getExpressionType() ) ) { // no need to change anything .. return; } try { final Expression expression = (Expression) o.getExpressionType().newInstance(); if ( primaryDataSourceExpression != null ) { propagateExpressionSettings( primaryDataSourceExpression, expression ); } setPrimaryDataSource( expression.getInstance() ); } catch ( final Exception e1 ) { // ignore the exception .. UncaughtExceptionsModel.getInstance().addException( e1 ); setPrimaryDataSource( null ); } } } private class SecondaryDataSourceSelectionHandler implements ListDataListener { private SecondaryDataSourceSelectionHandler() { } public void intervalAdded( final ListDataEvent e ) { // ignored } public void intervalRemoved( final ListDataEvent e ) { // ignored } public void contentsChanged( final ListDataEvent e ) { final ExpressionMetaData o = (ExpressionMetaData) getSecondaryDataSourcesModel().getSelectedItem(); if ( o == null ) { setSecondaryDataSource( null ); return; } final Expression secondaryDataSourceExpression = getSecondaryDataSource(); if ( secondaryDataSourceExpression != null && secondaryDataSourceExpression.getClass() .equals( o.getExpressionType() ) ) { // no need to change anything .. return; } try { final Expression expression = (Expression) o.getExpressionType().newInstance(); if ( secondaryDataSourceExpression != null ) { propagateExpressionSettings( secondaryDataSourceExpression, expression ); } setSecondaryDataSource( expression.getInstance() ); } catch ( final Exception e1 ) { // ignore the exception .. UncaughtExceptionsModel.getInstance().addException( e1 ); setSecondaryDataSource( null ); } } } private class ChartExpressionTypeSelectionHandler implements ListDataListener { private ChartExpressionTypeSelectionHandler() { } public void intervalAdded( final ListDataEvent e ) { // ignored } public void intervalRemoved( final ListDataEvent e ) { // ignored } public void contentsChanged( final ListDataEvent e ) { final ExpressionMetaData o = (ExpressionMetaData) getChartExpressionsModel().getSelectedItem(); if ( o == null ) { setChartExpression( null ); return; } final Expression chartExpression = getChartExpression(); if ( chartExpression != null && chartExpression.getClass().equals( o.getExpressionType() ) ) { // no need to change anything .. return; } try { final Expression primaryDSExpression = getPrimaryDataSource(); final Expression secondaryDSExpression = getSecondaryDataSource(); final Expression newChartExpression = (Expression) o.getExpressionType().newInstance(); propagateExpressionSettings( chartExpression, newChartExpression ); setChartExpression( newChartExpression ); final ExpressionMetaData thePrimaryModel = (ExpressionMetaData) getPrimaryDataSourcesModel().getSelectedItem(); if ( thePrimaryModel != null && primaryDSExpression != null ) { if ( thePrimaryModel.getExpressionType().equals( primaryDSExpression.getClass() ) ) { setPrimaryDataSource( primaryDSExpression ); } else { final Expression newPrimaryDataSource = (Expression) thePrimaryModel.getExpressionType().newInstance(); propagateExpressionSettings( primaryDSExpression, newPrimaryDataSource ); setPrimaryDataSource( newPrimaryDataSource ); } } final ExpressionMetaData theSecondaryModel = (ExpressionMetaData) getSecondaryDataSourcesModel().getSelectedItem(); if ( theSecondaryModel != null && secondaryDSExpression != null ) { if ( theSecondaryModel.getExpressionType().equals( secondaryDSExpression.getClass() ) ) { setSecondaryDataSource( secondaryDSExpression ); } else { final Expression newSecondaryDataSource = (Expression) theSecondaryModel.getExpressionType().newInstance(); propagateExpressionSettings( secondaryDSExpression, newSecondaryDataSource ); setSecondaryDataSource( newSecondaryDataSource ); } } } catch ( final Exception e1 ) { // ignore the exception .. UncaughtExceptionsModel.getInstance().addException( e1 ); setChartExpression( null ); } } } public static final String PRIMARY_DATA_SOURCE_PROPERTY = "primaryDataSource"; public static final String SECONDARY_DATA_SOURCE_PROPERTY = "secondaryDataSource"; public static final String CHART_EXPRESSION_PROPERTY = "chartExpression"; private PropertyChangeSupport propertyChangeSupport; private Expression chartExpression; private Expression primaryDataSource; private Expression secondaryDataSource; private ChartType currentChartType; private DefaultComboBoxModel primaryDataSourcesModel; private DefaultComboBoxModel secondaryDataSourcesModel; private DefaultComboBoxModel chartExpressionsModel; public LegacyChartEditModel() { propertyChangeSupport = new PropertyChangeSupport( this ); chartExpressionsModel = new DefaultComboBoxModel(); chartExpressionsModel.addListDataListener( new ChartExpressionTypeSelectionHandler() ); primaryDataSourcesModel = new DefaultComboBoxModel(); primaryDataSourcesModel.addListDataListener( new PrimaryDataSourceSelectionHandler() ); secondaryDataSourcesModel = new DefaultComboBoxModel(); secondaryDataSourcesModel.addListDataListener( new SecondaryDataSourceSelectionHandler() ); populateExpressionSelectorModel( chartExpressionsModel, JFreeChart.class ); } public void addPropertyChangeListener( final PropertyChangeListener listener ) { propertyChangeSupport.addPropertyChangeListener( listener ); } public void removePropertyChangeListener( final PropertyChangeListener listener ) { propertyChangeSupport.removePropertyChangeListener( listener ); } public void addPropertyChangeListener( final String propertyName, final PropertyChangeListener listener ) { propertyChangeSupport.addPropertyChangeListener( propertyName, listener ); } public void removePropertyChangeListener( final String propertyName, final PropertyChangeListener listener ) { propertyChangeSupport.removePropertyChangeListener( propertyName, listener ); } public Expression getChartExpression() { return chartExpression; } public void setChartExpression( final Expression chartExpression ) { final Expression oldChartExpression = this.chartExpression; this.chartExpression = chartExpression; this.currentChartType = null; propertyChangeSupport.firePropertyChange( CHART_EXPRESSION_PROPERTY, oldChartExpression, chartExpression ); if ( this.chartExpression != null ) { final String key = this.chartExpression.getClass().getName(); final ExpressionMetaData newMetaData = ExpressionRegistry.getInstance().getExpressionMetaData( key ); if ( newMetaData == null ) { chartExpressionsModel.setSelectedItem( null ); } else { final Object selectedMetaData = chartExpressionsModel.getSelectedItem(); if ( selectedMetaData instanceof ExpressionMetaData ) { final ExpressionMetaData metaData = (ExpressionMetaData) selectedMetaData; if ( metaData.getExpressionType().equals( newMetaData.getExpressionType() ) == false ) { chartExpressionsModel.setSelectedItem( newMetaData ); } } else { chartExpressionsModel.setSelectedItem( newMetaData ); } } } else { chartExpressionsModel.setSelectedItem( null ); } updateExpressionDataSources(); } private void updateExpressionDataSources() { final ChartType type = getCurrentChartType(); if ( type == null ) { populateExpressionSelectorModel( primaryDataSourcesModel, null ); populateExpressionSelectorModel( secondaryDataSourcesModel, null ); setPrimaryDataSource( null ); setSecondaryDataSource( null ); return; } final ChartDataSource datasource = type.getDatasource(); if ( datasource != null ) { final Expression primaryDataSource = getPrimaryDataSource(); if ( isValidType( primaryDataSource, datasource.getResultType() ) == false ) { populateExpressionSelectorModel( primaryDataSourcesModel, datasource.getResultType() ); final ExpressionMetaData data = ExpressionRegistry.getInstance().getExpressionMetaData ( type.getPreferredPrimaryDataSourceImplementation().getName() ); primaryDataSourcesModel.setSelectedItem( data ); } } else { populateExpressionSelectorModel( primaryDataSourcesModel, null ); setPrimaryDataSource( null ); } final ChartDataSource secondaryDataSource = type.getSecondaryDataSource(); if ( secondaryDataSource != null ) { final Expression dataSource = getSecondaryDataSource(); if ( isValidType( dataSource, secondaryDataSource.getResultType() ) == false ) { populateExpressionSelectorModel( secondaryDataSourcesModel, secondaryDataSource.getResultType() ); final ExpressionMetaData data = ExpressionRegistry.getInstance().getExpressionMetaData ( type.getPreferredSecondaryDataSourceImplementation().getName() ); secondaryDataSourcesModel.setSelectedItem( data ); } } else { populateExpressionSelectorModel( secondaryDataSourcesModel, null ); setSecondaryDataSource( null ); } } private boolean isValidType( final Expression expression, final Class resultType ) { if ( expression == null ) { return false; } if ( ExpressionRegistry.getInstance().isExpressionRegistered( expression.getClass().getName() ) == false ) { return false; } final ExpressionMetaData metaData = ExpressionRegistry.getInstance().getExpressionMetaData( expression.getClass().getName() ); if ( resultType.isAssignableFrom( metaData.getResultType() ) ) { return true; } return false; } public Expression getPrimaryDataSource() { return primaryDataSource; } public void setPrimaryDataSource( final Expression primaryDataSource ) { final Expression oldExpression = this.primaryDataSource; this.primaryDataSource = primaryDataSource; propertyChangeSupport.firePropertyChange( PRIMARY_DATA_SOURCE_PROPERTY, oldExpression, primaryDataSource ); if ( primaryDataSource != null ) { final ExpressionMetaData data = ExpressionRegistry.getInstance().getExpressionMetaData( primaryDataSource.getClass().getName() ); primaryDataSourcesModel.setSelectedItem( data ); } else { primaryDataSourcesModel.setSelectedItem( null ); } } public Expression getSecondaryDataSource() { return secondaryDataSource; } public void setSecondaryDataSource( final Expression secondaryDataSource ) { final Expression oldExpression = this.secondaryDataSource; this.secondaryDataSource = secondaryDataSource; propertyChangeSupport.firePropertyChange( SECONDARY_DATA_SOURCE_PROPERTY, oldExpression, secondaryDataSource ); if ( secondaryDataSource != null ) { final ExpressionMetaData data = ExpressionRegistry.getInstance().getExpressionMetaData( secondaryDataSource.getClass().getName() ); secondaryDataSourcesModel.setSelectedItem( data ); } else { secondaryDataSourcesModel.setSelectedItem( null ); } } public ChartType getCurrentChartType() { if ( currentChartType == null && chartExpression != null ) { currentChartType = ChartType.getTypeByChartExpression( chartExpression.getClass() ); } return currentChartType; } public ComboBoxModel getPrimaryDataSourcesModel() { return primaryDataSourcesModel; } public ComboBoxModel getSecondaryDataSourcesModel() { return secondaryDataSourcesModel; } public ComboBoxModel getChartExpressionsModel() { return chartExpressionsModel; } private void propagateExpressionSettings( final Expression source, final Expression destination ) { if ( source == null || destination == null ) { return; } try { final BeanUtility buSource = new BeanUtility( source ); final BeanUtility buDest = new BeanUtility( destination ); final String[] strings = buSource.getProperties(); for ( int i = 0; i < strings.length; i++ ) { try { final String propertyName = strings[ i ]; final Object value = buSource.getProperty( propertyName ); buDest.setProperty( propertyName, value ); } catch ( BeanException e ) { // ignore .. } } } catch ( Exception e ) { // ignore .. } /* // We do not need to set a name, names get autogenerated later .. final String name = source.getName(); if (name == null) { final ExpressionCollection expressionCollection = activeContext.getReportDefinition().getExpressions(); final int expressionIndex = expressionCollection.size() + 1; destination.setName("Chart Function " + expressionIndex); } else { destination.setName(name); } */ } private void populateExpressionSelectorModel( final DefaultComboBoxModel model, final Class resultType ) { model.removeAllElements(); if ( resultType == null ) { model.setSelectedItem( null ); return; } final ExpressionMetaData[] allExpressionMetaDatas = ExpressionRegistry.getInstance().getAllExpressionMetaDatas(); Arrays.sort( allExpressionMetaDatas, new GroupedMetaDataComparator() ); for ( int i = 0; i < allExpressionMetaDatas.length; i++ ) { final ExpressionMetaData data = allExpressionMetaDatas[ i ]; if ( data.isHidden() ) { continue; } if ( !WorkspaceSettings.getInstance().isVisible( data ) ) { continue; } if ( StructureFunction.class.isAssignableFrom( data.getExpressionType() ) ) { continue; } if ( resultType.isAssignableFrom( data.getResultType() ) ) { model.addElement( data ); } } model.setSelectedItem( null ); } }