/*
* 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 2006 - 2008 Pentaho Corporation. All rights reserved.
*
* @created May 1, 2006
* @author James Dixon
*/
package org.pentaho.platform.uifoundation.chart;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Node;
import org.pentaho.commons.connection.IPentahoMetaData;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.platform.api.engine.IActionSequenceResource;
import org.pentaho.platform.api.engine.IPentahoUrlFactory;
import org.pentaho.platform.api.repository.ISolutionRepository;
import org.pentaho.platform.engine.core.solution.ActionInfo;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.services.actionsequence.ActionSequenceResource;
import org.pentaho.platform.uifoundation.messages.Messages;
import org.pentaho.platform.util.xml.XmlHelper;
import org.pentaho.platform.util.xml.dom4j.XmlDom4JHelper;
public class FlashChartComponent extends AbstractChartComponent {
private static final long serialVersionUID = 925147871232129020L;
protected Node chartNode;
protected Node chartTemplate;
protected String backgroundColor;
protected String chartType = "bar"; //$NON-NLS-1$
private String valueItem = null;
private String nameItem = null;
private int topX = -1;
public FlashChartComponent(final String definitionPath, final int width, final int height,
final IPentahoUrlFactory urlFactory, final List messages) {
super(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());
}
AbstractChartComponent.logger = LogFactory.getLog(this.getClass());
}
@Override
public Log getLogger() {
return AbstractChartComponent.logger;
}
@Override
public boolean validate() {
return true;
}
@Override
public Document getXmlContent() {
return null;
}
public void setTopX(final int topX) {
this.topX = topX;
}
@Override
public boolean setDataAction(final String chartDefinition) {
IActionSequenceResource resource = new ActionSequenceResource(
"", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
chartDefinition);
try {
Document dataActionDocument = PentahoSystem.get(ISolutionRepository.class, getSession()).getResourceAsDocument(resource, ISolutionRepository.ACTION_EXECUTE);
if (dataActionDocument == null) {
return false;
}
Node dataNode = dataActionDocument.selectSingleNode("chart/data"); //$NON-NLS-1$
chartNode = dataActionDocument.selectSingleNode("chart"); //$NON-NLS-1$
title = XmlDom4JHelper.getNodeText("title", chartNode); //$NON-NLS-1$
chartType = XmlDom4JHelper.getNodeText("chart_type", chartNode, "bar"); //$NON-NLS-1$ //$NON-NLS-2$
boolean isGauge = chartType.toLowerCase().startsWith("dial"); //$NON-NLS-1$
chartTemplate = chartNode.selectSingleNode(isGauge ? "template/gauge" : "template/chart"); //$NON-NLS-1$ //$NON-NLS-2$
if (chartTemplate == null) {
String templatePath = XmlDom4JHelper.getNodeText("template-file", chartNode); //$NON-NLS-1$
if (templatePath != null) {
// we have a reference to a document to look up
IActionSequenceResource templateResource = new ActionSequenceResource(
"", IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ //$NON-NLS-2$
templatePath);
try {
Document templateDocument = PentahoSystem.get(ISolutionRepository.class, getSession()).getResourceAsDocument(
templateResource, ISolutionRepository.ACTION_EXECUTE);
chartTemplate = templateDocument.getRootElement();
} catch (Exception e) {
// the chart template document is not valid
error(Messages.getInstance().getErrorString("FlashChartComponent.ERROR_0001_CHART_TEMPLATE_INVALID"), e); //$NON-NLS-1$
}
}
}
solution = XmlDom4JHelper.getNodeText("data-solution", dataNode); //$NON-NLS-1$
actionPath = XmlDom4JHelper.getNodeText("data-path", dataNode); //$NON-NLS-1$
actionName = XmlDom4JHelper.getNodeText("data-action", dataNode); //$NON-NLS-1$
actionOutput = XmlDom4JHelper.getNodeText("data-output", dataNode); //$NON-NLS-1$
valueItem = XmlDom4JHelper.getNodeText("data-value", dataNode); //$NON-NLS-1$
nameItem = XmlDom4JHelper.getNodeText("data-name", dataNode); //$NON-NLS-1$
backgroundColor = XmlDom4JHelper.getNodeText("chart/background-color", dataActionDocument, "#ffffff"); //$NON-NLS-1$ //$NON-NLS-2$
byRow = XmlDom4JHelper.getNodeText("data-orientation", dataNode, "rows").equals("rows"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (width == -1) {
width = (int) XmlDom4JHelper.getNodeText("chart/width", dataActionDocument, 400); //$NON-NLS-1$
}
if (height == -1) {
height = (int) XmlDom4JHelper.getNodeText("chart/height", dataActionDocument, 300); //$NON-NLS-1$
}
} catch (Exception e) {
error(Messages.getInstance().getErrorString(
"CategoryDatasetChartComponent.ERROR_0001_INVALID_CHART_DEFINITION", chartDefinition), e); //$NON-NLS-1$
return false;
}
return true;
}
@Override
public String getContent(final String mimeType) {
if (chartType.toLowerCase().startsWith("dial")) { //$NON-NLS-1$
return getDialContent(mimeType);
} else {
return getChartContent(mimeType);
}
}
protected Object[] getValue() {
Object result[] = new Object[2];
IPentahoResultSet resultSet = null;
try {
resultSet = getActionData();
if (resultSet == null) {
return null;
}
IPentahoMetaData metaData = resultSet.getMetaData();
// TODO support multiple column headers / row headers
// TODO support an iteration across columns for a given row
// find the column that we have been told to you
Object columnHeaders[][] = metaData.getColumnHeaders();
int nameColumnNo = -1;
int valueColumnNo = -1;
for (int idx = 0; idx < columnHeaders[0].length; idx++) {
if (columnHeaders[0][idx].toString().equalsIgnoreCase(nameItem)) {
nameColumnNo = idx;
}
if (columnHeaders[0][idx].toString().equalsIgnoreCase(valueItem)) {
valueColumnNo = idx;
}
}
if (nameColumnNo == -1) {
// we did not find the specified name column
error(Messages.getInstance().getErrorString("FlashDial.ERROR_0001_NAME_COLUMN_MISSING", nameItem)); //$NON-NLS-1$
return null;
}
if (valueColumnNo == -1) {
// we did not find the specified name column
error(Messages.getInstance().getErrorString("FlashDial.ERROR_0002_VALUE_COLUMN_MISSING", valueItem)); //$NON-NLS-1$
return null;
}
Object row[] = resultSet.next();
while (row != null) {
result[0] = row[nameColumnNo].toString();
try {
result[1] = new Double(row[valueColumnNo].toString());
} catch (Exception e) {
}
row = resultSet.next();
}
} finally {
if (resultSet != null) {
resultSet.dispose();
}
}
return result;
}
public String getDialContent(final String mimeType) {
return getDialContent(mimeType, true);
}
public String getDialContent(final String mimeType, boolean objectWrapper) {
Object data[] = null;
Object tmpVal = getParameter("value", null); //$NON-NLS-1$
if (tmpVal != null) {
data = fixupDialData(getParameter("title", title), tmpVal); //$NON-NLS-1$
} else {
data = getValue();
if ((data != null) && (data.length > 0)) {
if (data.length == 1) {
tmpVal = data[0];
data = fixupDialData(getParameter("title", title), data[0]); //$NON-NLS-1$
} else {
tmpVal = data[1];
data = fixupDialData(data[0], data[1]);
}
}
if (data == null) {
return Messages.getInstance().getErrorString("FlashChartComponent.ERROR_0002_DIAL_DATA_INVALID", String.valueOf(tmpVal)); //$NON-NLS-1$
}
}
title = (String) data[0];
double value = ((Double) data[1]).doubleValue();
double span = 0;
if (chartType.equalsIgnoreCase("DialPct")) { //$NON-NLS-1$
double fullSpan = XmlDom4JHelper.getNodeText("dial_limits/@full-span", chartNode, 360.0); //$NON-NLS-1$
double minClamp = XmlDom4JHelper.getNodeText("dial_limits/@min-clamp", chartNode, 0); //$NON-NLS-1$
double maxClamp = XmlDom4JHelper.getNodeText("dial_limits/@max-clamp", chartNode, 360.0); //$NON-NLS-1$
span = value / 100.0 * fullSpan;
span = Math.max(minClamp, Math.min(maxClamp, span));
} else {
span = value;
}
// String solutionDir = "system/tmp/"; //$NON-NLS-1$
String fileNamePrefix = "tmp_flash_"; //$NON-NLS-1$
String extension = ".xml"; //$NON-NLS-1$
String fileName = null;
String template = ""; //$NON-NLS-1$
String gaugeLicense = PentahoSystem.getSystemSetting("FlashChart/GaugeLicense", ""); //$NON-NLS-1$ //$NON-NLS-2$
if (gaugeLicense.length() > 0) {
gaugeLicense = "license=" + gaugeLicense + "&"; //$NON-NLS-1$ //$NON-NLS-2$
}
if (chartTemplate != null) {
template = chartTemplate.asXML().replace('"', '\'');
template = template.replaceFirst("\\{title\\}", title); //$NON-NLS-1$
template = template.replaceFirst("\\{span\\}", String.valueOf(span).replace('"', '\'')); //$NON-NLS-1$
template = template.replaceFirst("\\{data\\}", String.valueOf(value).replace('"', '\'')); //$NON-NLS-1$
if (urlTemplate != null) {
template = template.replaceFirst("\\{drill-url\\}", urlTemplate); //$NON-NLS-1$
}
// Do tick marks
List nodeList = chartNode.selectNodes("radial_ticks"); //$NON-NLS-1$
for (int i = 0; i < nodeList.size(); ++i) {
template = setRadialTicks((Node) nodeList.get(i), template);
}
nodeList = chartNode.selectNodes("radial_numbers"); //$NON-NLS-1$
for (int i = 0; i < nodeList.size(); ++i) {
template = setRadialNumbers((Node) nodeList.get(i), template);
}
} else {
StringBuffer sb = new StringBuffer();
sb.append("<gauge>"); //$NON-NLS-1$
sb
.append(" <rotate x='").append(width / 2).append("' y='").append(height / 2).append("' span='").append(String.valueOf(span)).append("'>\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
sb
.append(" <line x1='").append(width / 2).append("' y1='0' x2='").append(width / 2).append("' y2='").append(height / 2).append("' />\n"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
sb.append(" </rotate>\n"); //$NON-NLS-1$
sb.append("</gauge>"); //$NON-NLS-1$
template = sb.toString();
}
if (!objectWrapper) {
return template;
}
// create a temporary file
try {
File file = PentahoSystem.getApplicationContext().createTempFile(getSession(), fileNamePrefix, extension, true);
fileName = file.getName();
if (file.canWrite()) {
Writer out = new FileWriter(file);
out.write(template);
out.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String baseUrl = PentahoSystem.getApplicationContext().getBaseUrl();
StringBuffer sb = new StringBuffer();
sb
.append("<OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n") //$NON-NLS-1$
.append("codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" ") //$NON-NLS-1$
.append("WIDTH=\"").append(width).append("\" HEIGHT=\"").append(height).append("\" id=\"charts\" ALIGN=\"\">") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
.append("<PARAM NAME=\"movie\" VALUE=\"").append(baseUrl).append("chart/gauge.swf?").append(gaugeLicense).append("xml_source=").append(baseUrl).append("getImage?image=").append(fileName).append("\">") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
.append("<PARAM NAME=\"quality\" VALUE=\"high\"> ") //$NON-NLS-1$
.append("<PARAM NAME=\"bgcolor\" VALUE=\"").append(backgroundColor).append("\"> ") //$NON-NLS-1$ //$NON-NLS-2$
.append("<EMBED src=\"").append(baseUrl).append("chart/gauge.swf?").append(gaugeLicense).append("xml_source=").append(baseUrl).append("getImage?image=").append(fileName).append("\" ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
.append("quality=\"high\" bgcolor=\"").append(backgroundColor).append("\" WIDTH=\"").append(width).append("\" HEIGHT=\"").append(height).append("\" NAME=\"charts\" ALIGN=\"\" ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
.append(
"TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\"></EMBED>") //$NON-NLS-1$
.append(" </OBJECT>"); //$NON-NLS-1$
return sb.toString();
}
private Object[] fixupDialData(Object inTitle, final Object value) {
Object[] data = null;
if (value == null) {
return data;
}
if (inTitle == null) {
inTitle = ""; //$NON-NLS-1$
}
inTitle = inTitle.toString();
try {
if (value instanceof Double) {
data = new Object[] { inTitle, value };
} else {
data = new Object[] { inTitle, new Double(value.toString()) };
}
} catch (Throwable t) {
error(Messages.getInstance().getErrorString("FlashChartComponent.ERROR_0002_DIAL_DATA_INVALID", value.toString())); //$NON-NLS-1$
}
return (data);
}
//function that generates the XML code to draw radial ticks
private String setRadialTicks(final Node node, final String template) {
try {
String xml = setRadialTicks(XmlDom4JHelper.getNodeText("@x", node, (width / 2.0)), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@y", node, (height / 2.0)), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@radius", node, (height / 2.0)), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@length", node, 8.0), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@start_angle", node, 0.0), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@end_angle", node, 350.0), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@tick_count", node, 36), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@thickness", node, 2), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@color", node, "000000") //$NON-NLS-1$ //$NON-NLS-2$
);
String param_name = XmlDom4JHelper.getNodeText("@param_name", node, null); //$NON-NLS-1$
return (template.replaceAll("\\{" + param_name + "\\}", xml)); //$NON-NLS-1$ //$NON-NLS-2$
} catch (Throwable t) {
error(Messages.getInstance().getString(
"FlashChartComponent.ERROR_0003_INVALID_XML_ATTRIBUTES_FOR_DIAL", "radial_ticks", node.asXML())); //$NON-NLS-1$ //$NON-NLS-2$
}
return (template);
}
private String setRadialTicks(final double x_center, final double y_center, final double radius, final double length,
final double start_angle, final double end_angle, final long ticks_count, final long thickness, final String color) {
StringBuffer sb = new StringBuffer();
for (double i = start_angle; i <= end_angle; i += (end_angle - start_angle) / (ticks_count - 1)) {
sb
.append("<line x1='").append(x_center + Math.sin(Math.toRadians(i)) * radius).append("' y1='").append(y_center - Math.cos(Math.toRadians(i)) * radius).append("'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
sb
.append(" x2='").append(x_center + Math.sin(Math.toRadians(i)) * (radius + length)).append("' y2='").append(y_center - Math.cos(Math.toRadians(i)) * (radius + length)).append("'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
sb.append(" thickness='").append(thickness).append("' color='").append(color).append("' />\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
return (sb.toString());
}
//function that generates the XML code to draw radial ticks
private String setRadialNumbers(final Node node, final String template) {
try {
String xml = setRadialNumbers(XmlDom4JHelper.getNodeText("@x", node, (width / 2.0)), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@y", node, (height / 2.0)), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@radius", node, (height / 2.0)), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@start_angle", node, 0.0), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@end_angle", node, 350.0), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@start_number", node, 0), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@end_number", node, 340), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@tick_count", node, 18), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@font_size", node, 12), //$NON-NLS-1$
XmlDom4JHelper.getNodeText("@color", node, "000000") //$NON-NLS-1$ //$NON-NLS-2$
);
String param_name = XmlDom4JHelper.getNodeText("@param_name", node, null); //$NON-NLS-1$
return (template.replaceAll("\\{" + param_name + "\\}", xml)); //$NON-NLS-1$ //$NON-NLS-2$
} catch (Throwable t) {
error(Messages.getInstance().getString(
"FlashChartComponent.ERROR_0003_INVALID_XML_ATTRIBUTES_FOR_DIAL", "radial_numbers", node.asXML())); //$NON-NLS-1$ //$NON-NLS-2$
}
return (template);
}
//function that generates the XML code to draw radial numbers
private String setRadialNumbers(final double x_center, final double y_center, final double radius,
final double start_angle, final double end_angle, final long start_number, final long end_number,
final long ticks_count, final long font_size, final String color) {
StringBuffer sb = new StringBuffer();
long number = start_number;
for (double i = start_angle; i <= end_angle; i += (end_angle - start_angle) / (ticks_count - 1)) {
sb
.append("<text x='").append(x_center + Math.sin(Math.toRadians(i)) * radius).append("' y='").append(y_center - Math.cos(Math.toRadians(i)) * radius).append("'"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
sb
.append(" width='200' size='").append(font_size).append("' color='").append(color).append("' align='left' rotation='").append(i).append("'>"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
sb.append(number).append("</text>\n"); //$NON-NLS-1$
number += (end_number - start_number) / (ticks_count - 1);
}
return (sb.toString());
}
public String getChartContent(final String mimeType) {
return getChartContent(mimeType, true);
}
public String getChartContent(final String mimeType, boolean objectWrapper) {
IPentahoResultSet data = getActionData();
if ((data == null) || (data.getRowCount() == 0)) {
// there is no data to display, prevent the default chart from showing
// TODO surface any error to the UI
return Messages.getInstance().getString("FlashChartComponent.USER_NO_DATA"); //$NON-NLS-1$
}
ArrayList nameList = new ArrayList();
ArrayList series1 = new ArrayList();
ArrayList series2 = new ArrayList();
ArrayList series3 = new ArrayList();
ArrayList series4 = new ArrayList();
StringBuffer dataXml = new StringBuffer();
Object row[];
if (data != null) {
row = data.next();
int n = 0;
while (row != null) {
if (row[0] == null) {
nameList.add("null"); //$NON-NLS-1$
} else {
nameList.add(row[0].toString());
}
if (row.length > 1) {
if (row[1] == null) {
series1.add("<null/>"); //$NON-NLS-1$
} else {
series1.add(row[1].toString());
}
}
if (row.length > 2) {
if (row[2] == null) {
series2.add("<null/>"); //$NON-NLS-1$
} else {
series2.add(row[2].toString());
}
}
if (row.length > 3) {
if (row[3] == null) {
series3.add("<null/>"); //$NON-NLS-1$
} else {
series3.add(row[3].toString());
}
}
if (row.length > 4) {
if (row[4] == null) {
series4.add("<null/>"); //$NON-NLS-1$
} else {
series4.add(row[4].toString());
}
}
row = data.next();
n++;
if (n == topX) {
row = null;
}
}
dataXml.append("<row>"); //$NON-NLS-1$
dataXml.append("<null/>"); //$NON-NLS-1$
int start = 0;
int end = nameList.size();
int step = 1;
if (topX != -1) {
start = end - 1;
end = -1;
step = -1;
}
if (data != null) {
for (int i = start; i != end; i += step) {
dataXml.append("<string>"); //$NON-NLS-1$
dataXml.append(XmlHelper.encode((String) nameList.get(i)));
dataXml.append("</string>"); //$NON-NLS-1$
}
}
dataXml.append("</row>"); //$NON-NLS-1$
if (series1.size() > 0) {
dataXml.append("<row>"); //$NON-NLS-1$
dataXml.append("<string>"); //$NON-NLS-1$
dataXml.append(XmlHelper.encode((String) data.getMetaData().getColumnHeaders()[0][1]));
dataXml.append("</string>"); //$NON-NLS-1$
for (int i = start; i != end; i += step) {
dataXml.append("<number>"); //$NON-NLS-1$
dataXml.append((String) series1.get(i));
dataXml.append("</number>"); //$NON-NLS-1$
}
dataXml.append("</row>"); //$NON-NLS-1$
}
if (series2.size() > 0) {
dataXml.append("<row>"); //$NON-NLS-1$
dataXml.append("<string>"); //$NON-NLS-1$
dataXml.append(XmlHelper.encode((String) data.getMetaData().getColumnHeaders()[0][2]));
dataXml.append("</string>"); //$NON-NLS-1$
for (int i = start; i != end; i += step) {
dataXml.append("<number>"); //$NON-NLS-1$
dataXml.append((String) series2.get(i));
dataXml.append("</number>"); //$NON-NLS-1$
}
dataXml.append("</row>"); //$NON-NLS-1$
}
if (series3.size() > 0) {
dataXml.append("<row>"); //$NON-NLS-1$
dataXml.append("<string>"); //$NON-NLS-1$
dataXml.append(XmlHelper.encode((String) data.getMetaData().getColumnHeaders()[0][3]));
dataXml.append("</string>"); //$NON-NLS-1$
for (int i = start; i != end; i += step) {
dataXml.append("<number>"); //$NON-NLS-1$
dataXml.append((String) series3.get(i));
dataXml.append("</number>"); //$NON-NLS-1$
}
dataXml.append("</row>"); //$NON-NLS-1$
}
if (series4.size() > 0) {
dataXml.append("<row>"); //$NON-NLS-1$
dataXml.append("<string>"); //$NON-NLS-1$
dataXml.append(XmlHelper.encode((String) data.getMetaData().getColumnHeaders()[0][4]));
dataXml.append("</string>"); //$NON-NLS-1$
for (int i = start; i != end; i += step) {
dataXml.append("<number>"); //$NON-NLS-1$
dataXml.append((String) series4.get(i));
dataXml.append("</number>"); //$NON-NLS-1$
}
dataXml.append("</row>"); //$NON-NLS-1$
}
}
String baseUrl = PentahoSystem.getApplicationContext().getBaseUrl();
// String solutionDir = "system/tmp/"; //$NON-NLS-1$
String fileNamePrefix = "tmp_flash_"; //$NON-NLS-1$
String extension = ".xml"; //$NON-NLS-1$
String fileName = null;
String template = ""; //$NON-NLS-1$
String chartLicense = PentahoSystem.getSystemSetting("FlashChart/ChartLicense", ""); //$NON-NLS-1$ //$NON-NLS-2$
if (chartLicense.length() > 0) {
chartLicense = "license=" + chartLicense + "&"; //$NON-NLS-1$ //$NON-NLS-2$
}
if (chartTemplate != null) {
template = chartTemplate.asXML().replace('"', '\'');
if (title != null) {
template = template.replaceFirst("\\{title\\}", title); //$NON-NLS-1$
} else {
template = template.replaceFirst("\\{title\\}", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
template = template.replaceFirst("\\{data\\}", dataXml.toString().replace('"', '\'')); //$NON-NLS-1$
if (urlTemplate != null) {
template = template.replaceFirst("\\{drill-url\\}", urlTemplate); //$NON-NLS-1$
}
} else {
StringBuffer sb = new StringBuffer();
sb.append("<chart>"); //$NON-NLS-1$
sb.append("<chart_data>"); //$NON-NLS-1$
sb.append(dataXml.toString().replace('"', '\''));
sb.append("</chart_data>"); //$NON-NLS-1$
sb.append("<chart_grid_h alpha='20' color='000000' thickness='1' type='solid' />"); //$NON-NLS-1$
sb
.append("<chart_rect positive_color='ffffff' positive_alpha='20' negative_color='ff0000' negative_alpha='10' />"); //$NON-NLS-1$
sb.append("<chart_type>"); //$NON-NLS-1$
sb.append(chartType);
sb.append("</chart_type>"); //$NON-NLS-1$
sb
.append("<chart_value color='ffffff' alpha='90' font='arial' bold='true' size='12' position='inside' prefix='' suffix='' decimals='0' separator='' as_percentage='true' />"); //$NON-NLS-1$
sb
.append("<legend_label layout='horizontal' bullet='circle' font='arial' bold='true' size='13' color='ffffff' alpha='85' />"); //$NON-NLS-1$
sb
.append("<legend_rect fill_color='aaaaaa' fill_alpha='100' line_color='000000' line_alpha='0' line_thickness='0' />"); //$NON-NLS-1$
sb.append("</chart>"); //$NON-NLS-1$
template = sb.toString();
}
if (!objectWrapper) {
return template;
}
/*
<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0"
WIDTH="400"
HEIGHT="250"
id="gauge"
ALIGN="">
<PARAM NAME=movie VALUE="gauge.swf?xml_source=sample.xml&license=XXXXXXXXXXXXXXXXXX.XXXXXXXXXXX">
<PARAM NAME=quality VALUE=high>
<PARAM NAME=bgcolor VALUE=#888888>
<EMBED src="gauge.swf?xml_source=sample.xml&license=XXXXXXXXXXXXXXXXXX.XXXXXXXXXXX"
quality=high
bgcolor=#888888
WIDTH="400"
HEIGHT="250"
NAME="gauge"
ALIGN=""
TYPE="application/x-shockwave-flash"
PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer">
</EMBED>
</OBJECT>
*/
if (template.length() < 0) {
// this is a small chart file, lets assume all the browsers are ok with this size
// TODO verify the maximum size of parameters for the major browsers
StringBuffer sb = new StringBuffer();
sb
.append("<OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n") //$NON-NLS-1$
.append("codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" ") //$NON-NLS-1$
.append("WIDTH=\"").append(width).append("\" HEIGHT=\"").append(height).append("\" id=\"charts\" ALIGN=\"\">") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
.append("<PARAM NAME=\"movie\" VALUE=\"").append(baseUrl).append("chart/charts.swf?").append(chartLicense).append("library_path=").append(baseUrl).append("chart/charts_library\">") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
.append("<PARAM NAME=\"quality\" VALUE=\"high\"> ") //$NON-NLS-1$
.append("<PARAM NAME=\"bgcolor\" VALUE=\"").append(backgroundColor).append("\"> ") //$NON-NLS-1$ //$NON-NLS-2$
.append("<PARAM NAME=\"FlashVars\" VALUE=\"source_data=").append(template).append("\">") //$NON-NLS-1$ //$NON-NLS-2$
.append("<EMBED src=\"").append(baseUrl).append("chart/charts.swf?").append(chartLicense).append("library_path=").append(baseUrl).append("chart/charts_library\" ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
.append("FlashVars=\"source_data=").append(template).append("\" ") //$NON-NLS-1$ //$NON-NLS-2$
.append("quality=\"high\" bgcolor=\"").append(backgroundColor).append("\" WIDTH=\"").append(width).append("\" HEIGHT=\"").append(height).append("\" NAME=\"charts\" ALIGN=\"\" ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
.append(
"TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\"></EMBED>") //$NON-NLS-1$
.append(" </OBJECT>"); //$NON-NLS-1$
return sb.toString();
} else {
// create a temporary file
try {
File file = PentahoSystem.getApplicationContext().createTempFile(getSession(), fileNamePrefix, extension, true);
fileName = file.getName();
if (file.canWrite()) {
Writer out = new FileWriter(file);
out.write(template);
out.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringBuffer sb = new StringBuffer();
sb
.append("<OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"\n") //$NON-NLS-1$
.append("codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" ") //$NON-NLS-1$
.append("WIDTH=\"").append(width).append("\" HEIGHT=\"").append(height).append("\" id=\"charts\" ALIGN=\"\">") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
.append("<PARAM NAME=\"movie\" VALUE=\"").append(baseUrl).append("chart/charts.swf?").append(chartLicense).append("library_path=").append(baseUrl).append("chart/charts_library&xml_source=").append(baseUrl).append("getImage?image=").append(fileName).append("\">") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
.append("<PARAM NAME=\"quality\" VALUE=\"high\"> ") //$NON-NLS-1$
.append("<PARAM NAME=\"bgcolor\" VALUE=\"").append(backgroundColor).append("\"> ") //$NON-NLS-1$ //$NON-NLS-2$
.append("<EMBED src=\"").append(baseUrl).append("chart/charts.swf?").append(chartLicense).append("library_path=").append(baseUrl).append("chart/charts_library&xml_source=").append(baseUrl).append("getImage?image=").append(fileName).append("\" ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
.append("quality=\"high\" bgcolor=\"").append(backgroundColor).append("\" WIDTH=\"").append(width).append("\" HEIGHT=\"").append(height).append("\" NAME=\"charts\" ALIGN=\"\" ") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
.append(
"TYPE=\"application/x-shockwave-flash\" PLUGINSPAGE=\"http://www.macromedia.com/go/getflashplayer\"></EMBED>") //$NON-NLS-1$
.append(" </OBJECT>"); //$NON-NLS-1$
return sb.toString();
}
}
@Override
public void dispose() {
}
}