/*!
* 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.engine.classic.extensions.drilldown;
import org.pentaho.reporting.engine.classic.core.DataRow;
import org.pentaho.reporting.engine.classic.core.StaticDataRow;
import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime;
import org.pentaho.reporting.engine.classic.core.function.GenericExpressionRuntime;
import org.pentaho.reporting.engine.classic.core.function.ReportFormulaContext;
import org.pentaho.reporting.engine.classic.core.function.WrapperExpressionRuntime;
import org.pentaho.reporting.engine.classic.core.layout.output.DefaultProcessingContext;
import org.pentaho.reporting.engine.classic.core.parameters.CompoundDataRow;
import org.pentaho.reporting.engine.classic.core.util.beans.BeanException;
import org.pentaho.reporting.libraries.formula.ErrorValue;
import org.pentaho.reporting.libraries.formula.EvaluationException;
import org.pentaho.reporting.libraries.formula.Formula;
import org.pentaho.reporting.libraries.formula.FormulaContext;
import org.pentaho.reporting.libraries.formula.LibFormulaErrorValue;
import org.pentaho.reporting.libraries.formula.parser.ParseException;
import javax.swing.table.DefaultTableModel;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class FormulaLinkCustomizer implements LinkCustomizer {
private static final String TAB_ACTIVE_PARAMETER = "::TabActive";
private static final String TAB_NAME_PARAMETER = "::TabName";
public FormulaLinkCustomizer() {
}
private String computeMantleTabActive( final FormulaContext formulaContext,
final ParameterEntry[] entries ) throws EvaluationException {
for ( int i = 0; i < entries.length; i++ ) {
final ParameterEntry parameterEntry = entries[ i ];
final String parameterName = parameterEntry.getParameterName();
if ( TAB_ACTIVE_PARAMETER.equals( parameterName ) ) {
final Object o = parameterEntry.getParameterValue();
if ( o != null ) {
return String.valueOf( o );
}
}
}
final Object o = formulaContext.resolveReference( TAB_ACTIVE_PARAMETER );
if ( o != null ) {
return String.valueOf( o );
}
return null;
}
private String computeMantleTabName( final FormulaContext formulaContext,
final ParameterEntry[] entries ) throws EvaluationException {
for ( int i = 0; i < entries.length; i++ ) {
final ParameterEntry parameterEntry = entries[ i ];
final String parameterName = parameterEntry.getParameterName();
if ( TAB_NAME_PARAMETER.equals( parameterName ) ) {
final Object o = parameterEntry.getParameterValue();
if ( o != null ) {
return String.valueOf( o );
}
}
}
final Object o = formulaContext.resolveReference( TAB_NAME_PARAMETER );
if ( o != null ) {
return String.valueOf( o );
}
return null;
}
private ParameterEntry[] filterEntries( final ParameterEntry[] entries ) {
final ArrayList<ParameterEntry> list = new ArrayList<ParameterEntry>();
for ( int i = 0; i < entries.length; i++ ) {
final ParameterEntry entry = entries[ i ];
if ( isFiltered( entry ) ) {
continue;
}
list.add( entry );
}
return list.toArray( new ParameterEntry[ list.size() ] );
}
protected boolean isFiltered( final ParameterEntry entry ) {
if ( TAB_NAME_PARAMETER.equals( entry.getParameterName() ) ) {
return true;
}
if ( TAB_ACTIVE_PARAMETER.equals( entry.getParameterName() ) ) {
return true;
}
return false;
}
private Object[][] createEntryTable( final ParameterEntry[] entries ) {
final Object[][] values = new Object[ entries.length ][ 2 ];
for ( int i = 0; i < entries.length; i++ ) {
final ParameterEntry entry = entries[ i ];
values[ i ][ 0 ] = ( entry.getParameterName() );
values[ i ][ 1 ] = ( entry.getParameterValue() );
}
return values;
}
public String format( final FormulaContext formulaContext,
final String configIndicator,
final String reportPath,
final ParameterEntry[] entries ) throws EvaluationException {
try {
final Map<String, Object> parameterValues =
createParameterMap( formulaContext, configIndicator, reportPath, entries );
final StaticDataRow staticDataRow = new StaticDataRow( parameterValues );
final ExpressionRuntime expressionRuntime;
if ( formulaContext instanceof ReportFormulaContext ) {
final ReportFormulaContext rfc = (ReportFormulaContext) formulaContext;
expressionRuntime = new WrapperExpressionRuntime( staticDataRow, rfc.getRuntime() );
} else {
expressionRuntime = new GenericExpressionRuntime
( new CompoundDataRow( staticDataRow, createDataRow( entries ) ),
new DefaultTableModel(), -1, new DefaultProcessingContext() );
}
final String formula = computeFormula( configIndicator );
final Formula compiledFormula = new Formula( formula );
compiledFormula.initialize( new ReportFormulaContext( formulaContext, expressionRuntime ) );
final Object o = compiledFormula.evaluate();
if ( o instanceof ErrorValue ) {
throw EvaluationException.getInstance( (ErrorValue) o );
}
if ( o == null ) {
throw EvaluationException.getInstance( LibFormulaErrorValue.ERROR_NA_VALUE );
}
return String.valueOf( o );
} catch ( final UnsupportedEncodingException e ) {
throw EvaluationException.getInstance( LibFormulaErrorValue.ERROR_UNEXPECTED_VALUE );
} catch ( final BeanException e ) {
throw EvaluationException.getInstance( LibFormulaErrorValue.ERROR_UNEXPECTED_VALUE );
} catch ( ParseException e ) {
throw EvaluationException.getInstance( LibFormulaErrorValue.ERROR_UNEXPECTED_VALUE );
} catch ( EvaluationException e ) {
throw e;
} catch ( Exception e ) {
e.printStackTrace();
throw EvaluationException.getInstance( LibFormulaErrorValue.ERROR_UNEXPECTED_VALUE );
}
}
protected Map<String, Object> createParameterMap( final FormulaContext formulaContext,
final String configIndicator,
final String reportPath,
final ParameterEntry[] entries )
throws UnsupportedEncodingException, BeanException, EvaluationException {
final String parameter = PatternLinkCustomizer.computeParameter( formulaContext, filterEntries( entries ) );
final HashMap<String, Object> parameterValues = new HashMap<String, Object>();
if ( reportPath == null || reportPath.endsWith( "/" ) ) {
parameterValues.put( "::path", reportPath );
} else {
// make sure the path ends in slash for consistency
parameterValues.put( "::path", reportPath + "/" );
}
parameterValues.put( "::parameter", parameter );
parameterValues.put( "::config", configIndicator );
parameterValues.put( "::entries", createEntryTable( entries ) );
parameterValues.put( TAB_NAME_PARAMETER, computeMantleTabName( formulaContext, entries ) );
parameterValues.put( TAB_ACTIVE_PARAMETER, computeMantleTabActive( formulaContext, entries ) );
return parameterValues;
}
private String computeFormula( final String configIndicator ) throws EvaluationException {
final DrillDownProfile downProfile = DrillDownProfileMetaData.getInstance().getDrillDownProfile( configIndicator );
return downProfile.getAttribute( "formula" );
}
private DataRow createDataRow( final ParameterEntry[] parameterEntries ) {
final String[] parameterNames = new String[ parameterEntries.length ];
final Object[] parameterValues = new Object[ parameterEntries.length ];
for ( int i = 0; i < parameterEntries.length; i++ ) {
final ParameterEntry entry = parameterEntries[ i ];
parameterNames[ i ] = entry.getParameterName();
parameterValues[ i ] = entry.getParameterValue();
}
return new StaticDataRow( parameterNames, parameterValues );
}
}