/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.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 General Public License for more details. * * * Copyright 2005 - 2008 Pentaho Corporation. All rights reserved. * * Created Nov 17, 2005 * @author wseyler */ package org.pentaho.platform.uifoundation.chart; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Array; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.commons.connection.IPentahoResultSet; import org.pentaho.platform.api.engine.IActionParameter; import org.pentaho.platform.api.engine.ILogger; import org.pentaho.platform.api.engine.IPentahoUrlFactory; import org.pentaho.platform.api.engine.IRuntimeContext; import org.pentaho.platform.api.engine.ISolutionEngine; import org.pentaho.platform.engine.core.output.SimpleOutputHandler; import org.pentaho.platform.engine.core.solution.ActionInfo; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.services.runtime.TemplateUtil; import org.pentaho.platform.uifoundation.component.xml.XmlComponent; import org.pentaho.platform.uifoundation.messages.Messages; import org.pentaho.platform.util.messages.LocaleHelper; // ESCA-JAVA0100: // ESCA-JAVA0136: // ESCA-JAVA0054: public abstract class AbstractChartComponent extends XmlComponent { private static final long serialVersionUID = -3700747149855352376L; /** * XML Node for the chart configuration */ public static final String CHART_NODE_NAME = "chart"; //$NON-NLS-1$ /** * XML node for the URL Template */ public static final String URLTEMPLATE_NODE_NAME = "url-template"; //$NON-NLS-1$ /** * XML node for the series name */ public static final String PARAM2_NODE_NAME = "series-name"; //$NON-NLS-1$ /** * Index into array of the filename */ public static final int FILENAME_INDEX = 0; /** * Index into array of the filename without the extension */ public static final int FILENAME_WITHOUT_EXTENSION_INDEX = 1; protected String definitionPath; protected int width = -1; protected int height = -1; protected String title; protected Object values; protected boolean byRow = true; protected String solution; protected String actionPath; protected String actionName; protected String actionOutput; protected String instanceId = null; protected IRuntimeContext context; protected String urlTemplate = null; protected List<String> outerParamNames = new ArrayList<String>(); protected String paramName; // Assumes 1 parameter subclasses may need more protected static int chartCount = 0; protected static Log logger = null; protected AbstractChartComponent(final String definitionPath, final int width, final int height, final IPentahoUrlFactory urlFactory, final List messages) { this(urlFactory, messages); this.definitionPath = definitionPath; this.width = width; this.height = height; ActionInfo info = ActionInfo.parseActionString(definitionPath); if (info != null) { setSourcePath(info.getSolutionName() + File.separator + info.getPath()); } } /** * @param definitionPath * @param urlFactory * @param messages */ protected AbstractChartComponent(final String definitionPath, final IPentahoUrlFactory urlFactory, final ArrayList messages) { this(urlFactory, messages); this.definitionPath = definitionPath; ActionInfo info = ActionInfo.parseActionString(definitionPath); if (info != null) { setSourcePath(info.getSolutionName() + File.separator + info.getPath()); } } protected AbstractChartComponent(final IPentahoUrlFactory urlFactory, final List messages) { super(urlFactory, messages, null); setXsl("text/html", "Chart.xsl"); //$NON-NLS-1$ //$NON-NLS-2$ AbstractChartComponent.logger = LogFactory.getLog(this.getClass()); } /** * @param chartDefinition * String that represents a file in the solution to create the * chart from. * @return */ public abstract boolean setDataAction(String chartDefinition); /** * Sets the action to be executed to get the data for the pies * * @param solution * @param actionPath * @param actionName * @param actionOutput */ public void setDataAction(final String solution, final String actionPath, final String actionName, final String actionOutput) { this.solution = solution; this.actionPath = actionPath; this.actionName = actionName; this.actionOutput = actionOutput; } /** * Gets a IPentahoResultSet from the action output * * @return IPentahoResultSet */ public IPentahoResultSet getActionData() { // create an instance of the solution engine to execute the specified // action ISolutionEngine solutionEngine = PentahoSystem.get(ISolutionEngine.class, getSession()); solutionEngine.setLoggingLevel(ILogger.DEBUG); solutionEngine.init(getSession()); HashMap parameterProviders = getParameterProviders(); OutputStream outputStream = null; SimpleOutputHandler outputHandler = null; outputHandler = new SimpleOutputHandler(outputStream, false); ArrayList messages = new ArrayList(); String processId = this.getClass().getName(); context = solutionEngine.execute(solution, actionPath, actionName, processId, false, true, instanceId, false, parameterProviders, outputHandler, null, urlFactory, messages); if (context == null) { // this went badly wrong return null; } if (actionOutput != null) { if (context.getOutputNames().contains(actionOutput)) { IActionParameter output = context.getOutputParameter(actionOutput); IPentahoResultSet results = output.getValueAsResultSet(); if (results != null) { results = results.memoryCopy(); } return results; } else { // this is an error return null; } } else { for (Object objAp : context.getOutputNames()) { IActionParameter output = (IActionParameter) objAp; if (output.getType().equalsIgnoreCase(IActionParameter.TYPE_RESULT_SET)) { IPentahoResultSet results = output.getValueAsResultSet(); if (results != null) { results = results.memoryCopy(); } return results; } } } return null; } @Override public Log getLogger() { return AbstractChartComponent.logger; } /** * @return String that represents the file path to a temporary file */ protected String[] createTempFile() { // create temporary file names String solutionDir = "system/tmp/"; //$NON-NLS-1$ String fileNamePrefix = "tmp_chart_"; //$NON-NLS-1$ String extension = ".png"; //$NON-NLS-1$ String fileName = null; String filePathWithoutExtension = null; try { File file = PentahoSystem.getApplicationContext().createTempFile(getSession(), fileNamePrefix, extension, true); fileName = file.getName(); filePathWithoutExtension = solutionDir + fileName.substring(0, fileName.indexOf('.')); } catch (IOException e) { getLogger().error(Messages.getInstance().getErrorString("AbstractChartComponent.ERROR_0001_CANT_CREATE_TEMP_CHART"), e); //$NON-NLS-1$ } String[] value = new String[2]; value[AbstractChartComponent.FILENAME_INDEX] = fileName; value[AbstractChartComponent.FILENAME_WITHOUT_EXTENSION_INDEX] = filePathWithoutExtension; return value; } protected void applyOuterURLTemplateParam() { if (outerParamNames == null) { return; } for (String outerParamName : outerParamNames) { Object value = null; if ((context != null) && context.getInputNames().contains(outerParamName)) { value = context.getInputParameterValue(outerParamName); } if (value == null) { return; } try { if (value.getClass().isArray()) { if (Array.getLength(value) > 0) { String[] encodedVals = new String[Array.getLength(value)]; for (int i = 0; i < Array.getLength(value); ++i) // ESCA-JAVA0049: { encodedVals[i] = URLEncoder.encode(Array.get(value, i).toString(), LocaleHelper.getSystemEncoding()); } // TODO Sleeze Alert!!! This is a temporary hack for making the // URLs generated support multiple selections. A JIRA case PLATFORM-393 // has been generated to address this issue. // // For now, applyTemplate looks for an "&" or "?" preceding and following the param, uses all // the characters between them as the template and repeats it once for each param value // separating them with '&' urlTemplate = TemplateUtil.applyTemplate(urlTemplate, outerParamName, encodedVals); } } else { String encodedVal = URLEncoder.encode(value.toString(), LocaleHelper.getSystemEncoding()); urlTemplate = TemplateUtil.applyTemplate(urlTemplate, outerParamName, encodedVal); } //encodedVal = URLEncoder.encode(stringVal, LocaleHelper.getSystemEncoding()); //$NON-NLS-1$ } catch (UnsupportedEncodingException e) { getLogger().error(Messages.getInstance().getErrorString("AbstractChartComponent.ERROR_0002_URL_ENCODE_FAILED"), e); //$NON-NLS-1$ } } } /** * */ public void dispose() { if (context != null) { context.dispose(); } } /** * @return Returns the actionName. */ public String getActionName() { return actionName; } /** * @param actionName * The actionName to set. */ public void setActionName(final String actionName) { this.actionName = actionName; } /** * @return Returns the actionOutput. */ public String getActionOutput() { return actionOutput; } /** * @param actionOutput * The actionOutput to set. */ public void setActionOutput(final String actionOutput) { this.actionOutput = actionOutput; } /** * @return Returns the actionPath. */ public String getActionPath() { return actionPath; } /** * @param actionPath * The actionPath to set. */ public void setActionPath(final String actionPath) { this.actionPath = actionPath; } /** * @return Returns the context. */ public IRuntimeContext getContext() { return context; } /** * @param context * The context to set. */ public void setContext(final IRuntimeContext context) { this.context = context; } /** * @return Returns the definitionPath. */ public String getDefinitionPath() { return definitionPath; } /** * @param definitionPath * The definitionPath to set. */ public void setDefinitionPath(final String definitionPath) { this.definitionPath = definitionPath; } /** * @return Returns the height. */ public int getHeight() { return height; } /** * @param height * The height to set. */ public void setHeight(final int height) { this.height = height; } /** * @return Returns the instanceId. */ public String getInstanceId() { return instanceId; } /** * @param instanceId * The instanceId to set. */ public void setInstanceId(final String instanceId) { this.instanceId = instanceId; } /** * @return Returns the solution. */ public String getSolution() { return solution; } /** * @param solution * The solution to set. */ public void setSolution(final String solution) { this.solution = solution; } /** * @return Returns the title. */ public String getTitle() { return title; } /** * @param title * The title to set. */ public void setTitle(final String title) { this.title = title; } /** * @return Returns the urlTemplate. */ public String getUrlTemplate() { return urlTemplate; } /** * @param urlTemplate * The urlTemplate to set. */ public void setUrlTemplate(final String urlTemplate) { this.urlTemplate = urlTemplate; } /** * @return Returns the values. */ public Object getValues() { return values; } /** * @param values * The values to set. */ public void setValues(final Object values) { this.values = values; } /** * @return Returns the width. */ public int getWidth() { return width; } /** * @param width * The width to set. */ public void setWidth(final int width) { this.width = width; } /** * @param logger * The logger to set. */ public void setLogger(final Log logger) { AbstractChartComponent.logger = logger; } /** * @return Returns the byRow. */ public boolean isByRow() { return byRow; } /** * @param byRow * The byRow to set. */ public void setByRow(final boolean byRow) { this.byRow = byRow; } /** * @return Returns the paramName. */ public String getParamName() { return paramName; } /** * @param paramName * The paramName to set. */ public void setParamName(final String paramName) { this.paramName = paramName; } /** * @return Returns the outerParamNames. private List getOuterParamNames() { return outerParamNames; } */ /** * @param outerParamName * The outerParamNames name to add to the outParamNames list. */ public void addOuterParamName(final String outerParamName) { outerParamNames.add(outerParamName); } }