/**
*
*/
package org.saiku.adhoc.service.cda;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.swing.table.TableModel;
import org.pentaho.platform.engine.core.solution.SimpleParameterProvider;
import org.pentaho.reporting.engine.classic.core.DataRow;
import org.pentaho.reporting.engine.classic.core.ParameterMapping;
import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException;
import org.pentaho.reporting.engine.classic.core.util.TypedTableModel;
import org.pentaho.reporting.engine.classic.extensions.datasources.cda.CdaQueryBackend;
import org.pentaho.reporting.engine.classic.extensions.datasources.cda.CdaQueryEntry;
import org.pentaho.reporting.engine.classic.extensions.datasources.cda.CdaResponseParser;
import pt.webdetails.cda.dataaccess.InvalidParameterException;
import pt.webdetails.cda.utils.FormulaEvaluator;
import pt.webdetails.cda.utils.Util;
/**
* @author mg
*
*/
public class SaikuCdaQueryBackend extends CdaQueryBackend
{
private final static String FORMULA_BEGIN = "${";
private final static String FORMULA_END = "}";
public SaikuCdaQueryBackend()
{
}
public TypedTableModel fetchData(final DataRow dataRow, final String method,
final Map<String, String> extraParameter)
throws ReportDataFactoryException
{
{
try
{
final Map<String, Object> parameters = new HashMap<String, Object>();
final Set<Entry<String, String>> paramterSet = extraParameter.entrySet();
for (final Entry<String, String> entry : paramterSet)
{
parameters.put(entry.getKey(), entry.getValue());
}
parameters.put("outputType", "xml");
parameters.put("solution", encodeParameter(getSolution()));
parameters.put("path", encodeParameter(getPath()));
parameters.put("file", encodeParameter(getFile()));
final String responseBody = PluginUtils.callPlugin("cda", method, new SimpleParameterProvider(parameters));
// convert String into InputStream
final InputStream responseBodyIs = new ByteArrayInputStream(responseBody.getBytes("UTF-8"));
return CdaResponseParser.performParse(responseBodyIs);
}
catch (UnsupportedEncodingException use)
{
throw new ReportDataFactoryException("Failed to encode parameter", use);
}
catch (Exception e)
{
throw new ReportDataFactoryException("Failed to send request", e);
}
}
}
//TODO: Remove this after the official jar has been patched
@Override
public synchronized TableModel queryData(final CdaQueryEntry realQuery, final DataRow parameters)
throws ReportDataFactoryException
{
if (realQuery == null)
{
throw new NullPointerException("Query is null."); //$NON-NLS-1$
}
final TypedTableModel parameterModel = fetchParameter(parameters, realQuery);
// name = 0
// type = 1
// defaultValue = 2
// pattern = 3
final HashMap<String, String> extraParams = new HashMap<String, String>();
extraParams.put("dataAccessId", realQuery.getId());
final int nameIdx = parameterModel.findColumn("name");
final int typeIdx = parameterModel.findColumn("type");
final int defaultValueIdx = parameterModel.findColumn("defaultValue");
final int patternIdx = parameterModel.findColumn("pattern");
for (int p = 0; p < parameterModel.getRowCount(); p++)
{
final String alias = (String) parameterModel.getValueAt(p, nameIdx);
final String type = (String) parameterModel.getValueAt(p, typeIdx);
final String pattern = (String) parameterModel.getValueAt(p, patternIdx);
final ParameterMapping[] parameterMapping = realQuery.getParameters();
int i = 0;
while ((i < parameterMapping.length) && !(parameterMapping[i].getAlias().contentEquals(alias))) {
/* loop over till we find the right alias for name */
i+=1;
}
String name = alias; /* alias not found , set to alias for backward compatibility*/
if (i < parameterMapping.length) {
name = parameterMapping[i].getName();
}
// final String alias = realQuery.getDeclaredParameters();
// if parameter is null, use default value from cda
Object value;
try {
value = parameters.get(name) == null ? getRealDefaultValue(parameterModel.getValueAt(p, defaultValueIdx)) : parameters.get(name);
} catch (InvalidParameterException e) {
throw new ReportDataFactoryException("Malformed formula expression in cda defaultvalue");
}
final String param = parameterToString(alias, type, pattern, value);
//set parameter like CDA Style "param<parameterName>"
extraParams.put("param" + alias, param);
}
return fetchData(parameters, "doQuery", extraParams);
}
public Object getRealDefaultValue(Object objValue) throws InvalidParameterException
{
if(objValue instanceof String){//may be a string or a parsed value
final String strValue = (String) objValue;
//check if it is a formula
if(strValue != null && strValue.trim().startsWith(FORMULA_BEGIN))
{
String formula = Util.getContentsBetween(strValue, FORMULA_BEGIN, FORMULA_END);
if(formula == null)
{
throw new InvalidParameterException("Malformed formula expression", null);
}
Object value = FormulaEvaluator.processFormula(formula);
return value;
}
return strValue;
}
else return objValue;
}
}