/*
* 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 2005 - 2009 Pentaho Corporation. All rights reserved.
*
*
* @created Nov 17, 2005
* @author William Seyler
*/
package org.pentaho.platform.plugin.action.jfreechart;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Element;
import org.dom4j.Node;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.entity.StandardEntityCollection;
import org.jfree.chart.imagemap.ImageMapUtilities;
import org.jfree.chart.imagemap.StandardToolTipTagFragmentGenerator;
import org.jfree.data.general.Dataset;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.platform.api.engine.IActionSequenceResource;
import org.pentaho.platform.api.repository.IContentItem;
import org.pentaho.platform.api.util.XmlParseException;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.services.solution.ComponentBase;
import org.pentaho.platform.engine.services.solution.PentahoEntityResolver;
import org.pentaho.platform.plugin.action.messages.Messages;
import org.pentaho.platform.uifoundation.chart.BarLineChartDefinition;
import org.pentaho.platform.uifoundation.chart.CategoryDatasetChartDefinition;
import org.pentaho.platform.uifoundation.chart.ChartDefinition;
import org.pentaho.platform.uifoundation.chart.DialWidgetDefinition;
import org.pentaho.platform.uifoundation.chart.JFreeChartEngine;
import org.pentaho.platform.uifoundation.chart.PentahoChartURLTagFragmentGenerator;
import org.pentaho.platform.uifoundation.chart.PieDatasetChartDefinition;
import org.pentaho.platform.uifoundation.chart.TimeSeriesCollectionChartDefinition;
import org.pentaho.platform.uifoundation.chart.TimeTableXYDatasetChartDefinition;
import org.pentaho.platform.uifoundation.chart.XYSeriesCollectionChartDefinition;
import org.pentaho.platform.uifoundation.chart.XYZSeriesCollectionChartDefinition;
import org.pentaho.platform.util.xml.dom4j.XmlDom4JHelper;
public class ChartComponent extends ComponentBase {
private static final long serialVersionUID = 9050456842938084174L;
private static final String CHART_NAME_PROP = "chart-name"; //$NON-NLS-1$
private static final String CHART_OUTPUT = "chart-object"; //$NON-NLS-1$
private static final String CHART_TYPE = "CHART-OBJECT"; //$NON-NLS-1$
private static final String CHART_DATA_PROP = "chart-data"; //$NON-NLS-1$
// Root xml tag for chart attributes when chart is generated via an action sequence
private static final String CHART_ATTRIBUTES_PROP = "chart-attributes"; //$NON-NLS-1$
// This member added for compatibility to dashboard chart definitions
// Root xml tag for chart attributes when chart is generated via a dashboard
private static final String ALTERNATIVE_CHART_ATTRIBUTES_PROP = "chart"; //$NON-NLS-1$
private static final String BY_ROW_PROP = "by-row"; //$NON-NLS-1$
private static final String URL_TEMPLATE = "url-template"; //$NON-NLS-1$
private static final String PARAMETER_NAME = "paramName"; //$NON-NLS-1$
private static final String OUTER_PARAMETER_NAME = "series-name"; //$NON-NLS-1$
private static final String OUTPUT_TYPE_PROP = "output-type"; //$NON-NLS-1$
private static final String CHART_FILE_NAME_OUTPUT = "chart-filename"; //$NON-NLS-1$
private static final String HTML_MAPPING_OUTPUT = "chart-mapping"; //$NON-NLS-1$
private static final String HTML_MAPPING_HTML = "chart-map-html"; //$NON-NLS-1$
private static final String BASE_URL_OUTPUT = "base-url"; //$NON-NLS-1$
private static final String HTML_IMG_TAG = "image-tag"; //$NON-NLS-1$
private static final String SVG_TYPE = "SVG"; //$NON-NLS-1$
private static final String PNG_BYTES_TYPE = "png-bytes"; //$NON-NLS-1$
private static final String TEMP_DIRECTORY = "system/tmp/"; //$NON-NLS-1$
private static final String FILENAME_PREFIX = "tmp_chart_"; //$NON-NLS-1$
private static final String USE_BASE_URL_TAG = "use-base-url"; //$NON-NLS-1$
private static final String URL_TARGET_TAG = "url-target"; //$NON-NLS-1$
private static final String PNG_EXTENSION = ".png"; //$NON-NLS-1$
private static final String SVG_EXTENSION = ".svg"; //$NON-NLS-1$
private static final String MAP_EXTENSION = ".map"; //$NON-NLS-1$
private static final String KEEP_TEMP_FILE_PROP = "keep_temp_file"; //$NON-NLS-1$
private static final int FILE_NAME = 0;
private static final int MAP_NAME = 1;
public static final String FOREGROUND_ALPHA = "foreground-alpha"; //$NON-NLS-1$
public static final String BACKGROUND_ALPHA = "background-alpha"; //$NON-NLS-1$
@Override
public Log getLogger() {
return LogFactory.getLog(ChartComponent.class);
}
@Override
protected boolean validateSystemSettings() {
// This component does not have any system settings to validate
return true;
}
@Override
protected boolean validateAction() {
// See if we have chart data
if (!isDefinedInput(ChartComponent.CHART_DATA_PROP)) {
inputMissingError(ChartComponent.CHART_DATA_PROP);
return false;
}
// See if we have chart attributes
if (!isDefinedInput(ChartComponent.CHART_ATTRIBUTES_PROP)) {
if (!isDefinedResource(ChartComponent.CHART_ATTRIBUTES_PROP)) {
inputMissingError(ChartComponent.CHART_ATTRIBUTES_PROP);
return false;
}
}
// Anything else should be optional
return true;
}
@Override
public void done() {
}
@Override
protected boolean executeAction() {
int height = -1;
int width = -1;
String title = "";//$NON-NLS-1$
Node chartDocument = null;
IPentahoResultSet data = (IPentahoResultSet) getInputValue(ChartComponent.CHART_DATA_PROP);
String urlTemplate = (String) getInputValue(ChartComponent.URL_TEMPLATE);
Node chartAttributes = null;
String chartAttributeString = null;
// Attempt to get chart attributes as an input string or as a resource file
// If these don't trip, then we assume the chart attributes are defined in
// the component-definition of the chart action.
if (getInputNames().contains(ChartComponent.CHART_ATTRIBUTES_PROP)) {
chartAttributeString = getInputStringValue(ChartComponent.CHART_ATTRIBUTES_PROP);
} else if (isDefinedResource(ChartComponent.CHART_ATTRIBUTES_PROP)) {
IActionSequenceResource resource = getResource(ChartComponent.CHART_ATTRIBUTES_PROP);
chartAttributeString = getResourceAsString(resource);
}
// Realize chart attributes as an XML document
if (chartAttributeString != null) {
try {
chartDocument = XmlDom4JHelper.getDocFromString(chartAttributeString, new PentahoEntityResolver());
} catch(XmlParseException e) {
getLogger().error(Messages.getInstance().getString("ChartComponent.ERROR_0005_CANT_DOCUMENT_FROM_STRING"), e);//$NON-NLS-1$
return false;
}
chartAttributes = chartDocument.selectSingleNode(ChartComponent.CHART_ATTRIBUTES_PROP);
// This line of code handles a discrepancy between the schema of a chart definition
// handed to a dashboard versus a ChartComponent schema. The top level node for the dashboard charts
// is <chart>, whereas the ChartComponent expects <chart-attributes>.
// TODO:
// This discrepancy should be resolved when we have ONE chart solution.
if (chartAttributes == null) {
chartAttributes = chartDocument.selectSingleNode(ChartComponent.ALTERNATIVE_CHART_ATTRIBUTES_PROP);
}
}
// Default chart attributes are in the component-definition section of the action definition.
if (chartAttributes == null) {
chartAttributes = getComponentDefinition(true).selectSingleNode(ChartComponent.CHART_ATTRIBUTES_PROP);
}
// URL click-through attributes (useBaseURL, target) are only processed IF we
// have an urlTemplate attribute
if ((urlTemplate == null) || (urlTemplate.length() == 0)) {
if (chartAttributes.selectSingleNode(ChartComponent.URL_TEMPLATE) != null) {
urlTemplate = chartAttributes.selectSingleNode(ChartComponent.URL_TEMPLATE).getText();
}
}
// These parameters are replacement variables parsed into the
// urlTemplate specifically when we have a URL that is a drill-through
// link in a chart intended to drill down into the chart data.
String parameterName = (String) getInputValue(ChartComponent.PARAMETER_NAME);
if ((parameterName == null) || (parameterName.length() == 0)) {
if (chartAttributes.selectSingleNode(ChartComponent.PARAMETER_NAME) != null) {
parameterName = chartAttributes.selectSingleNode(ChartComponent.PARAMETER_NAME).getText();
}
}
// These parameters are replacement variables parsed into the
// urlTemplate specifically when we have a URL that is a drill-through
// link in a chart intended to drill down into the chart data.
String outerParameterName = (String) getInputValue(ChartComponent.OUTER_PARAMETER_NAME);
if ((outerParameterName == null) || (outerParameterName.length() == 0)) {
if (chartAttributes.selectSingleNode(ChartComponent.OUTER_PARAMETER_NAME) != null) {
outerParameterName = chartAttributes.selectSingleNode(ChartComponent.OUTER_PARAMETER_NAME).getText();
}
}
String chartType = chartAttributes.selectSingleNode(ChartDefinition.TYPE_NODE_NAME).getText();
// --------------- This code allows inputs to override the chartAttributes
// of width, height, and title
Object widthObj = getInputValue(ChartDefinition.WIDTH_NODE_NAME);
if (widthObj != null) {
width = Integer.parseInt(widthObj.toString());
if (width != -1) {
if (chartAttributes.selectSingleNode(ChartDefinition.WIDTH_NODE_NAME) == null) {
((Element) chartAttributes).addElement(ChartDefinition.WIDTH_NODE_NAME);
}
chartAttributes.selectSingleNode(ChartDefinition.WIDTH_NODE_NAME).setText(Integer.toString(width));
}
}
Object heightObj = getInputValue(ChartDefinition.HEIGHT_NODE_NAME);
if (heightObj != null) {
height = Integer.parseInt(heightObj.toString());
if (height != -1) {
if (chartAttributes.selectSingleNode(ChartDefinition.HEIGHT_NODE_NAME) == null) {
((Element) chartAttributes).addElement(ChartDefinition.HEIGHT_NODE_NAME);
}
chartAttributes.selectSingleNode(ChartDefinition.HEIGHT_NODE_NAME).setText(Integer.toString(height));
}
}
Object titleObj = getInputValue(ChartDefinition.TITLE_NODE_NAME);
if (titleObj != null) {
if (chartAttributes.selectSingleNode(ChartDefinition.TITLE_NODE_NAME) == null) {
((Element) chartAttributes).addElement(ChartDefinition.TITLE_NODE_NAME);
}
chartAttributes.selectSingleNode(ChartDefinition.TITLE_NODE_NAME).setText(titleObj.toString());
}
// ----------------End of Override
// ---------------Feed the Title and Subtitle information through the input substitution
Node titleNode = chartAttributes.selectSingleNode(ChartDefinition.TITLE_NODE_NAME);
if (titleNode != null) {
String titleStr = titleNode.getText();
if (titleStr != null) {
title = titleStr;
String newTitle = applyInputsToFormat(titleStr);
titleNode.setText(newTitle);
}
}
List subtitles = chartAttributes.selectNodes(ChartDefinition.SUBTITLE_NODE_NAME);
if ((subtitles == null) || (subtitles.isEmpty())) {
Node subTitlesNode = chartAttributes.selectSingleNode(ChartDefinition.SUBTITLES_NODE_NAME);
if (subTitlesNode != null) {
subtitles = chartAttributes.selectNodes(ChartDefinition.SUBTITLE_NODE_NAME);
}
} else {
// log a deprecation warning for this property...
getLogger().warn(
Messages.getInstance().getString(
"CHART.WARN_DEPRECATED_CHILD", ChartDefinition.SUBTITLE_NODE_NAME, ChartDefinition.SUBTITLES_NODE_NAME));//$NON-NLS-1$
getLogger().warn(Messages.getInstance().getString("CHART.WARN_PROPERTY_WILL_NOT_VALIDATE", ChartDefinition.SUBTITLE_NODE_NAME));//$NON-NLS-1$
}
if (subtitles != null) {
for (Iterator iter = subtitles.iterator(); iter.hasNext();) {
Node subtitleNode = (Node) iter.next();
if (subtitleNode != null) {
String subtitleStr = subtitleNode.getText();
if (subtitleStr != null) {
String newSubtitle = applyInputsToFormat(subtitleStr);
subtitleNode.setText(newSubtitle);
}
}
}
}
//----------------End of Format
// Determine if we are going to read the chart data set by row or by column
boolean byRow = false;
if (getInputStringValue(ChartComponent.BY_ROW_PROP) != null) {
byRow = Boolean.valueOf(getInputStringValue(ChartComponent.BY_ROW_PROP)).booleanValue();
}
// TODO Figure out why these overrides are called here. Seems like we are doing the same thing we just did above, but
// could possibly step on the height and width values set previously.
if (height == -1) {
height = (int) getInputLongValue(
ChartComponent.CHART_ATTRIBUTES_PROP + "/" + ChartDefinition.HEIGHT_NODE_NAME, 50); //$NON-NLS-1$
}
if (width == -1) {
width = (int) getInputLongValue(ChartComponent.CHART_ATTRIBUTES_PROP + "/" + ChartDefinition.WIDTH_NODE_NAME, 100); //$NON-NLS-1$
}
if (title.length() <= 0) {
title = getInputStringValue(ChartComponent.CHART_ATTRIBUTES_PROP + "/" + ChartDefinition.TITLE_NODE_NAME); //$NON-NLS-1$
}
// Select the right dataset to use based on the chart type
// Default to category dataset
String datasetType = ChartDefinition.CATEGORY_DATASET_STR;
boolean isStacked = false;
Node datasetTypeNode = chartAttributes.selectSingleNode(ChartDefinition.DATASET_TYPE_NODE_NAME);
if (datasetTypeNode != null) {
datasetType = datasetTypeNode.getText();
}
Dataset dataDefinition = null;
if (ChartDefinition.XY_SERIES_COLLECTION_STR.equalsIgnoreCase(datasetType)) {
dataDefinition = new XYSeriesCollectionChartDefinition(data, byRow, chartAttributes, getSession());
} else if (ChartDefinition.TIME_SERIES_COLLECTION_STR.equalsIgnoreCase(datasetType)) {
Node stackedNode = chartAttributes.selectSingleNode(ChartDefinition.STACKED_NODE_NAME);
if (stackedNode != null) {
isStacked = Boolean.valueOf(stackedNode.getText()).booleanValue();
}
if ((isStacked) && (ChartDefinition.AREA_CHART_STR.equalsIgnoreCase(chartType))) {
dataDefinition = new TimeTableXYDatasetChartDefinition(data, byRow, chartAttributes, getSession());
} else {
dataDefinition = new TimeSeriesCollectionChartDefinition(data, byRow, chartAttributes, getSession());
}
} else if (ChartDefinition.PIE_CHART_STR.equalsIgnoreCase(chartType)) {
dataDefinition = new PieDatasetChartDefinition(data, byRow, chartAttributes, getSession());
} else if (ChartDefinition.DIAL_CHART_STR.equalsIgnoreCase(chartType)) {
dataDefinition = new DialWidgetDefinition(data, byRow, chartAttributes, width, height, getSession());
} else if (ChartDefinition.BAR_LINE_CHART_STR.equalsIgnoreCase(chartType)) {
dataDefinition = new BarLineChartDefinition(data, byRow, chartAttributes, getSession());
} else if (ChartDefinition.BUBBLE_CHART_STR.equalsIgnoreCase(chartType)) {
dataDefinition = new XYZSeriesCollectionChartDefinition(data, byRow, chartAttributes, getSession());
} else {
dataDefinition = new CategoryDatasetChartDefinition(data, byRow, chartAttributes, getSession());
}
// Determine what we are sending back - Default to OUTPUT_PNG output
// OUTPUT_PNG = the chart gets written to a file in .png format
// OUTPUT_SVG = the chart gets written to a file in .svg (XML) format
// OUTPUT_CHART = the chart in a byte stream gets stored as as an IContentItem
// OUTPUT_PNG_BYTES = the chart gets sent as a byte stream in .png format
int outputType = JFreeChartEngine.OUTPUT_PNG;
if (getInputStringValue(ChartComponent.OUTPUT_TYPE_PROP) != null) {
if (ChartComponent.SVG_TYPE.equalsIgnoreCase(getInputStringValue(ChartComponent.OUTPUT_TYPE_PROP))) {
outputType = JFreeChartEngine.OUTPUT_SVG;
} else if (ChartComponent.CHART_TYPE.equalsIgnoreCase(getInputStringValue(ChartComponent.OUTPUT_TYPE_PROP))) {
outputType = JFreeChartEngine.OUTPUT_CHART;
} else if (ChartComponent.PNG_BYTES_TYPE.equalsIgnoreCase(getInputStringValue(ChartComponent.OUTPUT_TYPE_PROP))) {
outputType = JFreeChartEngine.OUTPUT_PNG_BYTES;
}
}
boolean keepTempFile = false;
if ( isDefinedInput(KEEP_TEMP_FILE_PROP) ) {
keepTempFile = getInputBooleanValue(KEEP_TEMP_FILE_PROP, false);
}
JFreeChart chart = null;
switch (outputType) {
/**************************** OUTPUT_PNG_BYTES *********************************************/
case JFreeChartEngine.OUTPUT_PNG_BYTES:
chart = JFreeChartEngine.getChart(dataDefinition, title, "", width, height, this); //$NON-NLS-1$
// TODO Shouldn't the mime types and other strings here be constant somewhere? Where do we
// put this type of general info ?
String mimeType = "image/png"; //$NON-NLS-1$
IContentItem contentItem = getOutputItem("chartdata", mimeType, ".png"); //$NON-NLS-1$ //$NON-NLS-2$
contentItem.setMimeType(mimeType);
try {
OutputStream output = contentItem.getOutputStream(getActionName());
ChartUtilities.writeChartAsPNG(output, chart, width, height);
} catch (Exception e) {
error(Messages.getInstance().getErrorString("ChartComponent.ERROR_0004_CANT_CREATE_IMAGE"), e); //$NON-NLS-1$
return false;
}
break;
/**************************** OUTPUT_SVG && OUTPUT_PNG *************************************/
case JFreeChartEngine.OUTPUT_SVG:
// intentionally fall through to PNG
case JFreeChartEngine.OUTPUT_PNG:
// Don't include the map in a file if HTML_MAPPING_HTML is specified, as that
// param sends the map back on the outputstream as a string
boolean createMapFile = !isDefinedOutput(ChartComponent.HTML_MAPPING_HTML);
boolean hasTemplate = urlTemplate != null && urlTemplate.length() > 0;
File[] fileResults = createTempFile(outputType, hasTemplate, !keepTempFile);
if (fileResults == null) {
error(Messages.getInstance().getErrorString("ChartComponent.ERROR_0003_CANT_CREATE_TEMP_FILES")); //$NON-NLS-1$
return false;
}
String chartId = fileResults[ChartComponent.FILE_NAME].getName().substring(0,
fileResults[ChartComponent.FILE_NAME].getName().indexOf('.'));
String filePathWithoutExtension = ChartComponent.TEMP_DIRECTORY + chartId;
PrintWriter printWriter = new PrintWriter(new StringWriter());
ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
JFreeChartEngine.saveChart(dataDefinition, title,
"", filePathWithoutExtension, width, height, outputType, printWriter, info, this); //$NON-NLS-1$
//Creating the image map
boolean useBaseUrl = true;
String urlTarget = "pentaho_popup"; //$NON-NLS-1$
// Prepend the base url to the front of every drill through link
if (chartAttributes.selectSingleNode(ChartComponent.USE_BASE_URL_TAG) != null) {
Boolean booleanValue = new Boolean(chartAttributes.selectSingleNode(ChartComponent.USE_BASE_URL_TAG)
.getText());
useBaseUrl = booleanValue.booleanValue();
}
// What target for link? _parent, _blank, etc.
if (chartAttributes.selectSingleNode(ChartComponent.URL_TARGET_TAG) != null) {
urlTarget = chartAttributes.selectSingleNode(ChartComponent.URL_TARGET_TAG).getText();
}
String mapString = null;
if (hasTemplate) {
try {
String mapId = fileResults[ChartComponent.MAP_NAME].getName().substring(0,
fileResults[ChartComponent.MAP_NAME].getName().indexOf('.'));
mapString = ImageMapUtilities.getImageMap(mapId, info, new StandardToolTipTagFragmentGenerator(),
new PentahoChartURLTagFragmentGenerator(urlTemplate, urlTarget, useBaseUrl, dataDefinition,
parameterName, outerParameterName));
if (createMapFile) {
BufferedWriter out = new BufferedWriter(new FileWriter(fileResults[ChartComponent.MAP_NAME]));
out.write(mapString);
out.flush();
out.close();
}
} catch (IOException e) {
error(Messages.getInstance().getErrorString(
"ChartComponent.ERROR_0001_CANT_WRITE_MAP", fileResults[ChartComponent.MAP_NAME].getPath())); //$NON-NLS-1$
return false;
} catch (Exception e) {
error(e.getLocalizedMessage(), e);
return false;
}
}
/*******************************************************************************************************
* Legitimate outputs for the ChartComponent in an action sequence:
*
* CHART_OUTPUT (chart-output)
* Stores the chart in the content repository as an IContentItem.
*
* CHART_FILE_NAME_OUTPUT (chart-filename)
* Returns the name of the chart file, including the file extension (with no path information)
* as a String.
*
* HTML_MAPPING_OUTPUT (chart-mapping)
* Returns the name of the file that the map has been saved to, including the file extension
* (with no path information) as a String. Will be empty if url-template is undefined
*
* HTML_MAPPING_HTML (chart-map-html)
* Returns the chart image map HTML as a String. Will be empty if url-template is undefined
*
* BASE_URL_OUTPUT (base-url)
* Returns the web app's base URL (ie., http://localhost:8080/pentaho) as a String.
*
* HTML_IMG_TAG (image-tag)
* Returns the HTML snippet including the image map, image (<IMG />) tag for the chart image
* with src, width, height and usemap attributes defined. Usemap will not be included if url-template
* is undefined.
*
*******************************************************************************************************/
// Now set the outputs
Set outputs = getOutputNames();
if ((outputs != null) && (outputs.size() > 0)) {
Iterator iter = outputs.iterator();
while (iter.hasNext()) {
String outputName = (String) iter.next();
String outputValue = null;
if (outputName.equals(ChartComponent.CHART_FILE_NAME_OUTPUT)) {
outputValue = fileResults[ChartComponent.FILE_NAME].getName();
} else if (outputName.equals(ChartComponent.HTML_MAPPING_OUTPUT)) {
if (hasTemplate) {
outputValue = fileResults[ChartComponent.MAP_NAME].getName();
}
} else if (outputName.equals(ChartComponent.HTML_MAPPING_HTML)) {
outputValue = mapString;
} else if (outputName.equals(ChartComponent.BASE_URL_OUTPUT)) {
outputValue = PentahoSystem.getApplicationContext().getBaseUrl();
} else if (outputName.equals(ChartComponent.HTML_IMG_TAG)) {
outputValue = hasTemplate ? mapString : ""; //$NON-NLS-1$
outputValue += "<img border=\"0\" "; //$NON-NLS-1$
outputValue += "width=\"" + width + "\" "; //$NON-NLS-1$//$NON-NLS-2$
outputValue += "height=\"" + height + "\" "; //$NON-NLS-1$//$NON-NLS-2$
if (hasTemplate) {
outputValue += "usemap=\"#" + fileResults[ChartComponent.MAP_NAME].getName().substring(0, fileResults[ChartComponent.MAP_NAME].getName().indexOf('.')) + "\" "; //$NON-NLS-1$//$NON-NLS-2$
}
outputValue += "src=\"" + PentahoSystem.getApplicationContext().getBaseUrl() + "getImage?image=" + fileResults[ChartComponent.FILE_NAME].getName() + "\"/>"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
}
if (outputValue != null) {
setOutputValue(outputName, outputValue);
}
}
}
break;
/************************** OUTPUT_CHART && DEFAULT *************************************/
case JFreeChartEngine.OUTPUT_CHART:
// intentionally fall through to default
default:
String chartName = ChartComponent.CHART_OUTPUT;
if (isDefinedInput(ChartComponent.CHART_NAME_PROP)) {
chartName = getInputStringValue(ChartComponent.CHART_NAME_PROP);
}
chart = JFreeChartEngine.getChart(dataDefinition, title, "", width, height, this); //$NON-NLS-1$
setOutputValue(chartName, chart);
break;
}
return true;
}
@Override
public boolean init() {
// nothing to do here really
return true;
}
/**
* @return String that represents the file path to a temporary file
*/
protected File[] createTempFile(final int outputType, final boolean includeMapFile, boolean trackFile) {
File[] results;
if (includeMapFile) {
results = new File[2];
} else {
results = new File[1];
}
String extension = outputType == JFreeChartEngine.OUTPUT_SVG ? ChartComponent.SVG_EXTENSION
: ChartComponent.PNG_EXTENSION;
try {
File file = PentahoSystem.getApplicationContext().createTempFile(getSession(), ChartComponent.FILENAME_PREFIX, extension, trackFile);
results[ChartComponent.FILE_NAME] = file;
if (includeMapFile) {
file = PentahoSystem.getApplicationContext().createTempFile(getSession(), ChartComponent.FILENAME_PREFIX,ChartComponent.MAP_EXTENSION, trackFile);
results[ChartComponent.MAP_NAME] = file;
}
} catch (IOException e) {
return null;
}
return results;
}
protected String getSolutionRelativePath(final String fullPath) {
String prefix = PentahoSystem.getApplicationContext().getSolutionPath(""); //$NON-NLS-1$
// Next line was added for PLATFORM-828
prefix = prefix.replaceAll("\\\\", "\\\\\\\\"); //$NON-NLS-1$ //$NON-NLS-2$
String result = fullPath.replaceFirst(prefix, ""); //$NON-NLS-1$
return result;
}
}