/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2009 Jaspersoft Corporation. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.jasperreports.engine.fill;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TimeZone;
import net.sf.jasperreports.engine.JRAbstractScriptlet;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRDataset;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExpression;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRGroup;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JRPropertiesHolder;
import net.sf.jasperreports.engine.JRPropertiesMap;
import net.sf.jasperreports.engine.JRQuery;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.JRScriptlet;
import net.sf.jasperreports.engine.JRSortField;
import net.sf.jasperreports.engine.JRVariable;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.design.JRDesignVariable;
import net.sf.jasperreports.engine.query.JRQueryExecuter;
import net.sf.jasperreports.engine.query.JRQueryExecuterFactory;
import net.sf.jasperreports.engine.scriptlets.ScriptletFactory;
import net.sf.jasperreports.engine.scriptlets.ScriptletFactoryContext;
import net.sf.jasperreports.engine.type.CalculationEnum;
import net.sf.jasperreports.engine.type.IncrementTypeEnum;
import net.sf.jasperreports.engine.type.ResetTypeEnum;
import net.sf.jasperreports.engine.type.WhenResourceMissingTypeEnum;
import net.sf.jasperreports.engine.util.JRQueryExecuterUtils;
import net.sf.jasperreports.engine.util.JRResourcesUtil;
import net.sf.jasperreports.extensions.ExtensionsEnvironment;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Lucian Chirita (lucianc@users.sourceforge.net)
* @version $Id: JRFillDataset.java 3960 2010-09-22 11:27:59Z teodord $
*/
public class JRFillDataset implements JRDataset
{
private static final Log log = LogFactory.getLog(JRFillDataset.class);
/**
* The filler that created this object.
*/
private final JRBaseFiller filler;
/**
* The template dataset.
*/
private final JRDataset parent;
/**
* Whether this is the main dataset of the report.
*/
private final boolean isMain;
/**
* The dataset query.
*/
protected JRQuery query;
private boolean useDatasourceParamValue;
private boolean useConnectionParamValue;
/**
* The dataset parameters.
*/
protected JRFillParameter[] parameters;
/**
* The dataset parameters indexed by name.
*/
protected Map parametersMap;
/**
* The dataset fields.
*/
protected JRFillField[] fields;
/**
* The dataset fields indexed by name.
*/
protected Map fieldsMap;
/**
* The dataset variables.
*/
protected JRFillVariable[] variables;
/**
* The dataset variables indexed by name.
*/
protected Map variablesMap;
/**
* Set of {@link VariableCalculationReq VariableCalculationReq} objects.
*/
protected Set variableCalculationReqs;
/**
* The element datasets.
*/
protected JRFillElementDataset[] elementDatasets;
/**
* Used to save the original element datasets when
* {@link #filterElementDatasets(JRFillElementDataset) filterElementDatasets} is called.
*/
protected JRFillElementDataset[] origElementDatasets;
/**
* The dataset groups.
*/
protected JRFillGroup[] groups;
/**
* The resource bundle base name.
*/
protected String resourceBundleBaseName;
/**
* The resource missing handle type.
*/
protected WhenResourceMissingTypeEnum whenResourceMissingType;
/**
* The scriptlet class name.
*/
protected String scriptletClassName;
/**
* The data source.
*/
protected JRDataSource dataSource;
/**
* The {@link Locale Locale} to be used by the dataset.
*/
protected Locale locale;
/**
* The loaded resource bundle.
*/
protected ResourceBundle resourceBundle;
/**
* The {@link TimeZone TimeZone} to be used by the dataset.
*/
protected TimeZone timeZone;
/**
* The cursor used when iterating the data source.
*/
protected int reportCount;
/**
* The calculator used by the dataset.
*/
protected JRCalculator calculator;
/**
* The scriptlets used by the dataset.
*/
protected List scriptlets;
/**
*
*/
protected JRAbstractScriptlet delegateScriptlet = new JRFillDatasetScriptlet(this);
/**
* The value of the {@link JRParameter#REPORT_MAX_COUNT max count} parameter.
*/
protected Integer reportMaxCount;
private JRQueryExecuter queryExecuter;
/**
* Creates a fill dataset object.
* @param filler the filler
* @param dataset the template dataset
* @param factory the fill object factory
*/
public JRFillDataset(JRBaseFiller filler, JRDataset dataset, JRFillObjectFactory factory)
{
factory.put(dataset, this);
this.filler = filler;
this.parent = dataset;
this.isMain = dataset.isMainDataset();
scriptletClassName = dataset.getScriptletClass();
resourceBundleBaseName = dataset.getResourceBundle();
whenResourceMissingType = dataset.getWhenResourceMissingTypeValue();
query = dataset.getQuery();
setParameters(dataset, factory);
setFields(dataset, factory);
setVariables(dataset, factory);
setGroups(dataset, factory);
}
private void setParameters(JRDataset dataset, JRFillObjectFactory factory)
{
JRParameter[] jrParameters = dataset.getParameters();
if (jrParameters != null && jrParameters.length > 0)
{
parameters = new JRFillParameter[jrParameters.length];
parametersMap = new HashMap();
for (int i = 0; i < parameters.length; i++)
{
parameters[i] = factory.getParameter(jrParameters[i]);
parametersMap.put(parameters[i].getName(), parameters[i]);
}
}
}
private void setGroups(JRDataset dataset, JRFillObjectFactory factory)
{
JRGroup[] jrGroups = dataset.getGroups();
if (jrGroups != null && jrGroups.length > 0)
{
groups = new JRFillGroup[jrGroups.length];
for (int i = 0; i < groups.length; i++)
{
groups[i] = factory.getGroup(jrGroups[i]);
}
}
}
private void setVariables(JRDataset dataset, JRFillObjectFactory factory)
{
JRVariable[] jrVariables = dataset.getVariables();
if (jrVariables != null && jrVariables.length > 0)
{
List variableList = new ArrayList(jrVariables.length * 3);
variablesMap = new HashMap();
for (int i = 0; i < jrVariables.length; i++)
{
addVariable(jrVariables[i], variableList, factory);
}
setVariables(variableList);
}
}
private JRFillVariable addVariable(JRVariable parentVariable, List variableList, JRFillObjectFactory factory)
{
JRFillVariable variable = factory.getVariable(parentVariable);
CalculationEnum calculation = variable.getCalculationValue();
switch (calculation)
{
case AVERAGE:
case VARIANCE:
{
JRVariable countVar = createHelperVariable(parentVariable, "_COUNT", CalculationEnum.COUNT);
JRFillVariable fillCountVar = addVariable(countVar, variableList, factory);
variable.setHelperVariable(fillCountVar, JRCalculable.HELPER_COUNT);
JRVariable sumVar = createHelperVariable(parentVariable, "_SUM", CalculationEnum.SUM);
JRFillVariable fillSumVar = addVariable(sumVar, variableList, factory);
variable.setHelperVariable(fillSumVar, JRCalculable.HELPER_SUM);
break;
}
case STANDARD_DEVIATION:
{
JRVariable varianceVar = createHelperVariable(parentVariable, "_VARIANCE", CalculationEnum.VARIANCE);
JRFillVariable fillVarianceVar = addVariable(varianceVar, variableList, factory);
variable.setHelperVariable(fillVarianceVar, JRCalculable.HELPER_VARIANCE);
break;
}
case DISTINCT_COUNT:
{
JRVariable countVar = createDistinctCountHelperVariable(parentVariable);
JRFillVariable fillCountVar = addVariable(countVar, variableList, factory);
variable.setHelperVariable(fillCountVar, JRCalculable.HELPER_COUNT);
break;
}
}
variableList.add(variable);
return variable;
}
private JRVariable createHelperVariable(JRVariable variable, String nameSuffix, CalculationEnum calculation)
{
JRDesignVariable helper = new JRDesignVariable();
helper.setName(variable.getName() + nameSuffix);
helper.setValueClassName(variable.getValueClassName());
helper.setIncrementerFactoryClassName(variable.getIncrementerFactoryClassName());
helper.setResetType(variable.getResetTypeValue());
helper.setResetGroup(variable.getResetGroup());
helper.setIncrementType(variable.getIncrementTypeValue());
helper.setIncrementGroup(variable.getIncrementGroup());
helper.setCalculation(calculation);
helper.setSystemDefined(true);
helper.setExpression(variable.getExpression());
return helper;
}
private JRVariable createDistinctCountHelperVariable(JRVariable variable)
{
JRDesignVariable helper = new JRDesignVariable();
helper.setName(variable.getName() + "_DISTINCT_COUNT");
helper.setValueClassName(variable.getValueClassName());
helper.setIncrementerFactoryClassName(JRDistinctCountIncrementerFactory.class.getName());
helper.setResetType(ResetTypeEnum.REPORT);
if (variable.getIncrementTypeValue() != IncrementTypeEnum.NONE)
{
helper.setResetType(ResetTypeEnum.getByValue(variable.getIncrementTypeValue().getValue()));
}
helper.setResetGroup(variable.getIncrementGroup());
helper.setCalculation(CalculationEnum.NOTHING);
helper.setSystemDefined(true);
helper.setExpression(variable.getExpression());
return helper;
}
private void setVariables(List variableList)
{
variables = new JRFillVariable[variableList.size()];
variables = (JRFillVariable[]) variableList.toArray(variables);
for (int i = 0; i < variables.length; i++)
{
variablesMap.put(variables[i].getName(), variables[i]);
}
}
private void setFields(JRDataset dataset, JRFillObjectFactory factory)
{
JRField[] jrFields = dataset.getFields();
if (jrFields != null && jrFields.length > 0)
{
fields = new JRFillField[jrFields.length];
fieldsMap = new HashMap();
for (int i = 0; i < fields.length; i++)
{
fields[i] = factory.getField(jrFields[i]);
fieldsMap.put(fields[i].getName(), fields[i]);
}
}
}
/**
* Creates the calculator
* @param jasperReport the report
* @throws JRException
*/
public void createCalculator(JasperReport jasperReport) throws JRException
{
setCalculator(createCalculator(jasperReport, this));
}
protected void setCalculator(JRCalculator calculator)
{
this.calculator = calculator;
}
protected static JRCalculator createCalculator(JasperReport jasperReport, JRDataset dataset) throws JRException
{
JREvaluator evaluator = JasperCompileManager.loadEvaluator(jasperReport, dataset);
return new JRCalculator(evaluator);
}
/**
* Initializes the calculator.
*
* @throws JRException
*/
public void initCalculator() throws JRException
{
calculator.init(this);
}
/**
* Inherits properties from the report.
*/
protected void inheritFromMain()
{
if (resourceBundleBaseName == null && !isMain)
{
resourceBundleBaseName = filler.mainDataset.resourceBundleBaseName;
whenResourceMissingType = filler.mainDataset.whenResourceMissingType;
}
}
/**
* Creates the scriptlets.
*
* @return the scriptlets list
* @throws JRException
*/
protected List createScriptlets(Map parameterValues) throws JRException
{
ScriptletFactoryContext context = new ScriptletFactoryContext(parameterValues, this);
scriptlets = new ArrayList();
List factories = ExtensionsEnvironment.getExtensionsRegistry().getExtensions(ScriptletFactory.class);
for (Iterator it = factories.iterator(); it.hasNext();)
{
ScriptletFactory factory = (ScriptletFactory)it.next();
List tmpScriptlets = factory.getScriplets(context);
if (tmpScriptlets != null)
{
scriptlets.addAll(tmpScriptlets);
}
}
if (scriptlets.size() == 0)
{
scriptlets.add(0, new JRDefaultScriptlet());
}
return scriptlets;
}
/**
* Initializes the element datasets.
*
* @param factory the fill object factory used by the filler
*/
protected void initElementDatasets(JRFillObjectFactory factory)
{
elementDatasets = factory.getElementDatasets(this);
}
/**
* Filters the element datasets, leaving only one.
* <p>
* This method is used when a dataset is instantiated by a chart or crosstab.
*
* @param elementDataset the element dataset that should remain
*/
protected void filterElementDatasets(JRFillElementDataset elementDataset)
{
origElementDatasets = elementDatasets;
elementDatasets = new JRFillElementDataset[]{elementDataset};
}
/**
* Restores the original element datasets.
* <p>
* This method should be called after {@link #filterElementDatasets(JRFillElementDataset) filterElementDatasets}.
*/
protected void restoreElementDatasets()
{
if (origElementDatasets != null)
{
elementDatasets = origElementDatasets;
origElementDatasets = null;
}
}
/**
* Loads the resource bundle corresponding to the resource bundle base name and locale.
*/
protected ResourceBundle loadResourceBundle()
{
ResourceBundle loadedBundle;
if (resourceBundleBaseName == null)
{
loadedBundle = null;
}
else
{
loadedBundle = JRResourcesUtil.loadResourceBundle(resourceBundleBaseName, locale);
}
return loadedBundle;
}
/**
* Reads built-in parameter values from the value map.
*
* @param parameterValues the parameter values
* @throws JRException
*/
public void setParameterValues(Map parameterValues) throws JRException
{
parameterValues.put(JRParameter.REPORT_PARAMETERS_MAP, parameterValues);
if (filler != null)
{
// the only case when this filler is null is when called from JRParameterDefaultValuesEvaluator
// and that utility method already sets the report object in the map
parameterValues.put(JRParameter.JASPER_REPORT, filler.getJasperReport());
}
reportMaxCount = (Integer) parameterValues.get(JRParameter.REPORT_MAX_COUNT);
locale = (Locale) parameterValues.get(JRParameter.REPORT_LOCALE);
if (locale == null)
{
locale = Locale.getDefault();
parameterValues.put(JRParameter.REPORT_LOCALE, locale);
}
resourceBundle = (ResourceBundle) parameterValues.get(JRParameter.REPORT_RESOURCE_BUNDLE);
if (resourceBundle == null)
{
resourceBundle = loadResourceBundle();
if (resourceBundle != null)
{
parameterValues.put(JRParameter.REPORT_RESOURCE_BUNDLE, resourceBundle);
}
}
timeZone = (TimeZone) parameterValues.get(JRParameter.REPORT_TIME_ZONE);
if (timeZone == null)
{
timeZone = TimeZone.getDefault();
parameterValues.put(JRParameter.REPORT_TIME_ZONE, timeZone);
}
scriptlets = createScriptlets(parameterValues);
delegateScriptlet.setData(parametersMap, fieldsMap, variablesMap, groups);//FIXMESCRIPTLET use some context
setFillParameterValues(parameterValues);
}
/**
* Initializes the data source which will be used by this dataset.
*
* If the dataset includes a query, this involves invoking the appropriate
* query executer to execute the query and create a data source from the
* results.
*
* @throws JRException
*/
public void initDatasource() throws JRException
{
queryExecuter = null;
dataSource = (JRDataSource) getParameterValue(JRParameter.REPORT_DATA_SOURCE);
if (!useDatasourceParamValue && (useConnectionParamValue || dataSource == null))
{
dataSource = createQueryDatasource();
setParameter(JRParameter.REPORT_DATA_SOURCE, dataSource);
}
if (DatasetSortUtil.needSorting(this))
{
dataSource = DatasetSortUtil.getSortedDataSource(filler, this, locale);
setParameter(JRParameter.REPORT_DATA_SOURCE, dataSource);
}
}
/**
* Sets the parameter values from the values map.
*
* @param parameterValues the values map
* @throws JRException
*/
private void setFillParameterValues(Map parameterValues) throws JRException
{
if (parameters != null && parameters.length > 0)
{
for (int i = 0; i < parameters.length; i++)
{
Object value = null;
if (parameterValues.containsKey(parameters[i].getName()))
{
value = parameterValues.get(parameters[i].getName());
}
else if (!parameters[i].isSystemDefined())
{
value = calculator.evaluate(parameters[i].getDefaultValueExpression(), JRExpression.EVALUATION_DEFAULT);
if (value != null)
{
parameterValues.put(parameters[i].getName(), value);
}
}
setParameter(parameters[i], value);
}
}
}
/**
* Returns the map of parameter values.
*
* @return the map of parameter values
*/
protected Map getParameterValuesMap()
{
JRFillParameter paramValuesParameter = (JRFillParameter) parametersMap.get(
JRParameter.REPORT_PARAMETERS_MAP);
return (Map) paramValuesParameter.getValue();
}
/**
* Creates the data source from a connection.
*
* @return the data source to be used
* @throws JRException
*/
private JRDataSource createQueryDatasource() throws JRException
{
if (query == null)
{
return null;
}
try
{
if (log.isDebugEnabled())
{
log.debug("Fill " + filler.fillerId + ": Creating " + query.getLanguage() + " query executer");
}
JRQueryExecuterFactory queryExecuterFactory = JRQueryExecuterUtils.getQueryExecuterFactory(query.getLanguage());
queryExecuter = queryExecuterFactory.createQueryExecuter(parent, parametersMap);
filler.fillContext.setRunningQueryExecuter(queryExecuter);
return queryExecuter.createDatasource();
}
finally
{
filler.fillContext.clearRunningQueryExecuter();
}
}
protected void reset()
{
useDatasourceParamValue = false;
useConnectionParamValue = false;
}
/**
* Sets the data source to be used.
*
* @param parameterValues the parameter values
* @param ds the data source
*/
public void setDatasourceParameterValue(Map parameterValues, JRDataSource ds)
{
useDatasourceParamValue = true;
if (ds != null)
{
parameterValues.put(JRParameter.REPORT_DATA_SOURCE, ds);
}
}
/**
* Sets the JDBC connection to be used.
*
* @param parameterValues the parameter values
* @param conn the connection
*/
public void setConnectionParameterValue(Map parameterValues, Connection conn)
{
useConnectionParamValue = true;
if (conn != null)
{
parameterValues.put(JRParameter.REPORT_CONNECTION, conn);
}
}
/**
* Closes the data source used by this dataset if this data source was
* obtained via a query executer.
*
* @see JRQueryExecuter#close()
*/
public void closeDatasource()
{
if (queryExecuter != null)
{
if (log.isDebugEnabled())
{
log.debug("Fill " + filler.fillerId + ": closing query executer");
}
queryExecuter.close();
queryExecuter = null;
}
reset();
}
/**
* Starts the iteration on the data source.
*/
public void start()
{
reportCount = 0;
}
/**
* Moves to the next record in the data source.
*
* @return <code>true</code> if the data source was not exhausted
* @throws JRException
*/
public boolean next() throws JRException
{
boolean hasNext = false;
if (dataSource != null)
{
boolean includeRow = true;
JRExpression filterExpression = getFilterExpression();
do
{
hasNext = advanceDataSource();
if (hasNext)
{
setOldValues();
calculator.estimateVariables();
if (filterExpression != null)
{
Boolean filterExprResult = (Boolean) calculator.evaluate(filterExpression, JRExpression.EVALUATION_ESTIMATED);
includeRow = filterExprResult != null && filterExprResult.booleanValue();
}
if (!includeRow)
{
revertToOldValues();
}
}
}
while(hasNext && !includeRow);
if (hasNext)
{
++reportCount;
}
}
return hasNext;
}
protected void setOldValues() throws JRException
{
if (fields != null && fields.length > 0)
{
for (int i = 0; i < fields.length; i++)
{
JRFillField field = fields[i];
field.setPreviousOldValue(field.getOldValue());
field.setOldValue(field.getValue());
field.setValue(dataSource.getFieldValue(field));
}
}
if (variables != null && variables.length > 0)
{
for (int i = 0; i < variables.length; i++)
{
JRFillVariable variable = variables[i];
variable.setPreviousOldValue(variable.getOldValue());
variable.setOldValue(variable.getValue());
}
}
}
protected void revertToOldValues()
{
if (fields != null && fields.length > 0)
{
for (int i = 0; i < fields.length; i++)
{
JRFillField field = fields[i];
field.setValue(field.getOldValue());
field.setOldValue(field.getPreviousOldValue());
}
}
if (variables != null && variables.length > 0)
{
for (int i = 0; i < variables.length; i++)
{
JRFillVariable variable = variables[i];
variable.setValue(variable.getOldValue());
variable.setOldValue(variable.getPreviousOldValue());
}
}
}
protected boolean advanceDataSource() throws JRException
{
boolean hasNext;
hasNext = (reportMaxCount == null || reportMaxCount.intValue() > reportCount) && dataSource.next();
return hasNext;
}
/**
* Sets the value of a parameter.
*
* @param parameterName the parameter name
* @param value the value
* @throws JRException
*/
protected void setParameter(String parameterName, Object value) throws JRException
{
JRFillParameter parameter = (JRFillParameter) parametersMap.get(parameterName);
if (parameter != null)
{
setParameter(parameter, value);
}
}
/**
* Sets the value of the parameter.
*
* @param parameter the parameter
* @param value the value
* @throws JRException
*/
protected void setParameter(JRFillParameter parameter, Object value) throws JRException
{
if (value != null)
{
if (parameter.getValueClass().isInstance(value))
{
parameter.setValue(value);
}
else
{
throw new JRException(
"Incompatible "
+ value.getClass().getName()
+ " value assigned to parameter "
+ parameter.getName()
+ " in the " + getName() + " dataset."
);
}
}
else
{
parameter.setValue(value);
}
}
/**
* Returns the value of a variable.
*
* @param variableName the variable name
* @return the variable value
*/
public Object getVariableValue(String variableName)
{
JRFillVariable var = (JRFillVariable) variablesMap.get(variableName);
if (var == null)
{
throw new JRRuntimeException("No such variable " + variableName);
}
return var.getValue();
}
/**
* Returns the value of a parameter.
*
* @param parameterName the parameter name
* @return the parameter value
*/
public Object getParameterValue(String parameterName)
{
return getParameterValue(parameterName, false);
}
/**
* Returns the value of a parameter.
*
* @param parameterName the parameter name
* @param ignoreMissing if set, <code>null</code> will be returned for inexisting parameters
* @return the parameter value
*/
public Object getParameterValue(String parameterName, boolean ignoreMissing)
{
JRFillParameter param = (JRFillParameter) parametersMap.get(parameterName);
Object value;
if (param == null)
{
if (!ignoreMissing)
{
throw new JRRuntimeException("No such parameter " + parameterName);
}
value = null;//FIXME look into REPORT_PARAMETERS_MAP? not yet required.
}
else
{
value = param.getValue();
}
return value;
}
/**
* Returns the value of a field.
*
* @param fieldName the field name
* @return the field value
*/
public Object getFieldValue(String fieldName)
{
JRFillField var = (JRFillField) fieldsMap.get(fieldName);
if (var == null)
{
throw new JRRuntimeException("No such field " + fieldName);
}
return var.getValue();
}
/**
* Class used to hold expression calculation requirements.
*/
protected static class VariableCalculationReq
{
String variableName;
CalculationEnum calculation;
VariableCalculationReq(String variableName, CalculationEnum calculation)
{
this.variableName = variableName;
this.calculation = calculation;
}
public boolean equals(Object o)
{
if (o == null || !(o instanceof VariableCalculationReq))
{
return false;
}
VariableCalculationReq r = (VariableCalculationReq) o;
return variableName.equals(r.variableName) && calculation == r.calculation;
}
public int hashCode()
{
return 31 * calculation.getValue() + variableName.hashCode();
}
}
/**
* Adds a variable calculation requirement.
*
* @param variableName the variable name
* @param calculation the required calculation
*/
protected void addVariableCalculationReq(String variableName, CalculationEnum calculation)
{
if (variableCalculationReqs == null)
{
variableCalculationReqs = new HashSet();
}
variableCalculationReqs.add(new VariableCalculationReq(variableName, calculation));
}
/**
* Checks if there are variable calculation requirements and creates the required variables.
*
* @param factory the fill object factory
*/
protected void checkVariableCalculationReqs(JRFillObjectFactory factory)
{
if (variableCalculationReqs != null && !variableCalculationReqs.isEmpty())
{
List variableList = new ArrayList(variables.length * 2);
for (int i = 0; i < variables.length; i++)
{
JRFillVariable variable = variables[i];
checkVariableCalculationReq(variable, variableList, factory);
}
setVariables(variableList);
}
}
private void checkVariableCalculationReq(JRFillVariable variable, List variableList, JRFillObjectFactory factory)
{
if (hasVariableCalculationReq(variable, CalculationEnum.AVERAGE) || hasVariableCalculationReq(variable, CalculationEnum.VARIANCE))
{
if (variable.getHelperVariable(JRCalculable.HELPER_COUNT) == null)
{
JRVariable countVar = createHelperVariable(variable, "_COUNT", CalculationEnum.COUNT);
JRFillVariable fillCountVar = factory.getVariable(countVar);
checkVariableCalculationReq(fillCountVar, variableList, factory);
variable.setHelperVariable(fillCountVar, JRCalculable.HELPER_COUNT);
}
if (variable.getHelperVariable(JRCalculable.HELPER_SUM) == null)
{
JRVariable sumVar = createHelperVariable(variable, "_SUM", CalculationEnum.SUM);
JRFillVariable fillSumVar = factory.getVariable(sumVar);
checkVariableCalculationReq(fillSumVar, variableList, factory);
variable.setHelperVariable(fillSumVar, JRCalculable.HELPER_SUM);
}
}
if (hasVariableCalculationReq(variable, CalculationEnum.STANDARD_DEVIATION))
{
if (variable.getHelperVariable(JRCalculable.HELPER_VARIANCE) == null)
{
JRVariable varianceVar = createHelperVariable(variable, "_VARIANCE", CalculationEnum.VARIANCE);
JRFillVariable fillVarianceVar = factory.getVariable(varianceVar);
checkVariableCalculationReq(fillVarianceVar, variableList, factory);
variable.setHelperVariable(fillVarianceVar, JRCalculable.HELPER_VARIANCE);
}
}
if (hasVariableCalculationReq(variable, CalculationEnum.DISTINCT_COUNT))
{
if (variable.getHelperVariable(JRCalculable.HELPER_COUNT) == null)
{
JRVariable countVar = createDistinctCountHelperVariable(variable);
JRFillVariable fillCountVar = factory.getVariable(countVar);
checkVariableCalculationReq(fillCountVar, variableList, factory);
variable.setHelperVariable(fillCountVar, JRCalculable.HELPER_COUNT);
}
}
variableList.add(variable);
}
private boolean hasVariableCalculationReq(JRVariable var, CalculationEnum calculation)
{
return variableCalculationReqs.contains(new VariableCalculationReq(var.getName(), calculation));
}
public String getName()
{
return parent.getName();
}
public String getScriptletClass()
{
return parent.getScriptletClass();
}
public JRScriptlet[] getScriptlets()
{
return parent.getScriptlets();
}
public JRParameter[] getParameters()
{
return parameters;
}
public Map getParametersMap()
{
return parametersMap;
}
public JRQuery getQuery()
{
return query;
}
public JRField[] getFields()
{
return fields;
}
public JRSortField[] getSortFields()
{
return parent.getSortFields();
}
public JRVariable[] getVariables()
{
return variables;
}
public JRGroup[] getGroups()
{
return groups;
}
public boolean isMainDataset()
{
return isMain;
}
public String getResourceBundle()
{
return parent.getResourceBundle();
}
/**
* @deprecated Replaced by {@link #getWhenResourceMissingType()}.
*/
public byte getWhenResourceMissingType()
{
return getWhenResourceMissingTypeValue().getValue();
}
public WhenResourceMissingTypeEnum getWhenResourceMissingTypeValue()
{
return whenResourceMissingType;
}
/**
* @deprecated Replaced by {@link #setWhenResourceMissingType(WhenResourceMissingTypeEnum)}.
*/
public void setWhenResourceMissingType(byte whenResourceMissingType)
{
setWhenResourceMissingType(WhenResourceMissingTypeEnum.getByValue(whenResourceMissingType));
}
public void setWhenResourceMissingType(WhenResourceMissingTypeEnum whenResourceMissingType)
{
this.whenResourceMissingType = whenResourceMissingType;
}
public boolean hasProperties()
{
return parent.hasProperties();
}
public JRPropertiesMap getPropertiesMap()
{
return parent.getPropertiesMap();
}
public JRPropertiesHolder getParentProperties()
{
// report properties propagate to subdatasets
return isMain ? null : filler.getJasperReport();
}
public JRExpression getFilterExpression()
{
return parent.getFilterExpression();
}
/**
*
*/
public Object clone()
{
throw new UnsupportedOperationException();
}
/**
* Evaluates an expression
* @param expression the expression
* @param evaluation the evaluation type
* @return the evaluation result
* @throws JRException
*/
public Object evaluateExpression(JRExpression expression, byte evaluation) throws JRException
{
return calculator.evaluate(expression, evaluation);
}
}