/*!
* 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.core.parameters;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.pentaho.reporting.engine.classic.core.ReportEnvironmentDataRow;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime;
import org.pentaho.reporting.engine.classic.core.function.FormulaExpression;
import org.pentaho.reporting.engine.classic.core.util.ReportParameterValues;
import org.pentaho.reporting.engine.classic.core.util.beans.BeanException;
import org.pentaho.reporting.engine.classic.core.util.beans.ConverterRegistry;
import org.pentaho.reporting.engine.classic.core.util.beans.ValueConverter;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.formula.ErrorValue;
import java.util.Locale;
public class FormulaParameterEvaluator {
private static final Log logger = LogFactory.getLog( FormulaParameterEvaluator.class );
private FormulaParameterEvaluator() {
}
/**
* @param result
* @param parameterDefinition
* @param parameterContext
* @return
* @deprecated This method is unsafe. Do not use it or you may open up your application to all kinds of security
* risks. The method will be removed in the next release.
*/
public static ReportParameterValues evaluate( final ValidationResult result,
final ReportParameterDefinition parameterDefinition, final ParameterContext parameterContext ) {
final ReportParameterValues parameterValues = new ReportParameterValues();
parameterValues.putAll( parameterContext.getParameterData() );
final ParameterDefinitionEntry[] entries = parameterDefinition.getParameterDefinitions();
for ( int i = 0; i < entries.length; i++ ) {
final ParameterDefinitionEntry entry = entries[i];
try {
final Object o =
computePostProcessingValue( result, parameterContext, parameterValues, entry, parameterValues.get( entry
.getName() ), entry.getDefaultValue( parameterContext ) );
parameterValues.put( entry.getName(), o );
} catch ( ReportProcessingException e ) {
if ( logger.isDebugEnabled() ) {
logger.debug( "Unable to compute default value for parameter '" + entry.getName() + "'", e );
}
if ( result != null ) {
result.addError( entry.getName(), new ValidationMessage( Messages.getInstance().formatMessage(
"FormulaParameterEvaluator.PostProcessingInitFailed", e.getLocalizedMessage() ) ) );
}
}
}
return parameterValues;
}
public static Object computePostProcessingValue( final ValidationResult result,
final ParameterContext parameterContext, final ReportParameterValues parameterValues,
final ParameterDefinitionEntry entry, final Object untrustedValue, final Object defaultValue )
throws ReportProcessingException {
final ReportEnvironmentDataRow envDataRow = new ReportEnvironmentDataRow( parameterContext.getReportEnvironment() );
final String formula =
entry.getParameterAttribute( ParameterAttributeNames.Core.NAMESPACE,
ParameterAttributeNames.Core.POST_PROCESSOR_FORMULA, parameterContext );
if ( StringUtils.isEmpty( formula, true ) ) {
return untrustedValue;
}
final ParameterExpressionRuntime runtime =
new ParameterExpressionRuntime( parameterContext, new CompoundDataRow( envDataRow, parameterValues ) );
return computeValue( runtime, formula, result, entry, defaultValue );
}
public static Object computeValue( final ExpressionRuntime runtime, final String formula,
final ValidationResult result, final ParameterDefinitionEntry entry, final Object defaultValue ) {
final FormulaExpression fe = new FormulaExpression();
fe.setFormula( formula );
fe.setRuntime( runtime );
final Object value = fe.getValue();
if ( value == null ) {
final Exception error = fe.getFormulaError();
if ( error != null ) {
if ( result != null ) {
result.addError( entry.getName(), new ValidationMessage( Messages.getInstance().formatMessage(
"FormulaParameterEvaluator.PostProcessingFormulaFailed", error.getLocalizedMessage() ) ) );
}
if ( logger.isDebugEnabled() ) {
logger.debug( "Unable to compute default value for parameter '" + entry.getName() + "'", error );
}
// if the value is a hard error, we return <null> instead of the default value.
// This way, a mandatory parameter will not continue in case of eval-errors.
return null;
}
return defaultValue;
} else if ( entry.getValueType().isInstance( value ) ) {
return value;
} else if ( value instanceof ErrorValue ) {
final ErrorValue errorValue = (ErrorValue) value;
if ( result != null ) {
result.addError( entry.getName(),
new ValidationMessage( Messages.getInstance().formatMessage(
"FormulaParameterEvaluator.PostProcessingFormulaFailed",
errorValue.getErrorMessage( Locale.getDefault() ) ) ) );
}
// if the value is a hard error, we return <null> instead of the default value.
// This way, a mandatory parameter will not continue in case of eval-errors.
return null;
} else {
final ValueConverter valueConverter = ConverterRegistry.getInstance().getValueConverter( entry.getValueType() );
if ( valueConverter != null ) {
// try to convert it; if this conversion fails we resort to String.valueOf,
// but it will take care of converting dates and number subtypes correctly ..
String textValue;
try {
textValue = ConverterRegistry.toAttributeValue( value );
} catch ( BeanException be ) {
textValue = String.valueOf( value );
}
try {
return ConverterRegistry.toPropertyValue( textValue, entry.getValueType() );
} catch ( BeanException e ) {
if ( logger.isDebugEnabled() ) {
logger.debug( "Unable to convert computed default value for parameter '" + entry.getName() + "'", e );
}
if ( result != null ) {
result.addError( entry.getName(), new ValidationMessage( Messages.getInstance().getString(
"FormulaParameterEvaluator.ErrorConvertingValue" ) ) );
result.addError( entry.getName(), new ValidationMessage(
"The post-processing result cannot be converted into the target-type." ) );
}
return null;
}
}
return defaultValue;
}
}
}