001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: *
013: * Created Nov 17, 2005
014: * @author wseyler
015: */
016:
017: package org.pentaho.ui.component.charting;
018:
019: import java.io.IOException;
020: import java.io.PrintWriter;
021: import java.io.StringWriter;
022: import java.io.UnsupportedEncodingException;
023: import java.net.URLEncoder;
024: import java.util.ArrayList;
025: import java.util.Iterator;
026: import java.util.List;
027:
028: import org.dom4j.Document;
029: import org.dom4j.DocumentHelper;
030: import org.dom4j.Element;
031: import org.dom4j.Node;
032: import org.jfree.chart.ChartRenderingInfo;
033: import org.jfree.chart.entity.CategoryItemEntity;
034: import org.jfree.chart.entity.ChartEntity;
035: import org.jfree.chart.entity.PieSectionEntity;
036: import org.jfree.chart.entity.StandardEntityCollection;
037: import org.jfree.chart.imagemap.ImageMapUtilities;
038: import org.jfree.data.general.Dataset;
039: import org.jfree.data.general.DefaultPieDataset;
040: import org.pentaho.commons.connection.IPentahoResultSet;
041: import org.pentaho.core.solution.ActionResource;
042: import org.pentaho.core.solution.IActionResource;
043: import org.pentaho.core.system.PentahoSystem;
044: import org.pentaho.core.ui.IPentahoUrlFactory;
045: import org.pentaho.core.util.TemplateUtil;
046: import org.pentaho.messages.Messages;
047: import org.pentaho.messages.util.LocaleHelper;
048: import org.pentaho.plugin.jfreechart.JFreeChartEngine;
049: import org.pentaho.plugin.jfreechart.PieDatasetChartDefinition;
050:
051: public class PieDatasetChartComponent extends
052: AbstractJFreeChartComponent {
053: private static final long serialVersionUID = -6268840271596447555L;
054:
055: protected String paramName2 = null;
056:
057: protected String dataAction = null;
058:
059: public PieDatasetChartComponent(int chartType,
060: String definitionPath, int width, int height,
061: IPentahoUrlFactory urlFactory, List messages) {
062: super (chartType, definitionPath, width, height, urlFactory,
063: messages);
064: // Set the XSL file to be used to generate the HTML
065: setXsl("text/html", "Chart.xsl"); //$NON-NLS-1$ //$NON-NLS-2$
066: }
067:
068: public PieDatasetChartComponent(String definitionPath,
069: IPentahoUrlFactory urlFactory, ArrayList messages) {
070: super (definitionPath, urlFactory, messages);
071: // Set the XSL file to be used to generate the HTML
072: setXsl("text/html", "Chart.xsl"); //$NON-NLS-1$ //$NON-NLS-2$
073: }
074:
075: public PieDatasetChartComponent(IPentahoUrlFactory urlFactory,
076: List messages) {
077: super (urlFactory, messages);
078: // Set the XSL file to be used to generate the HTML
079: setXsl("text/html", "Chart.xsl"); //$NON-NLS-1$ //$NON-NLS-2$
080: }
081:
082: public Dataset createChart(Document doc) {
083: if (solution != null) { // if we have a solution then get the values
084: values = getActionData();
085: } else {
086: // TODO support other methods of getting data
087: }
088:
089: if (values == null) {
090: // we could not get any data
091: return null;
092: }
093:
094: // get the chart node from the document
095: Node chartAttributes = doc
096: .selectSingleNode("//" + CHART_NODE_NAME); //$NON-NLS-1$
097: // create the definition
098: PieDatasetChartDefinition chartDefinition = new PieDatasetChartDefinition(
099: (IPentahoResultSet) values, byRow, chartAttributes,
100: getSession());
101:
102: setTitle(chartDefinition.getTitle());
103:
104: // get the URL template
105: Node urlTemplateNode = chartAttributes
106: .selectSingleNode(URLTEMPLE_NODE_NAME);
107: if (urlTemplateNode != null) {
108: setUrlTemplate(urlTemplateNode.getText());
109: }
110:
111: // get the additional parameter
112: Node paramName2Node = chartAttributes
113: .selectSingleNode(PARAM2_NODE_NAME);
114: if (paramName2Node != null) {
115: paramName2 = paramName2Node.getText();
116: }
117:
118: if (width == -1)
119: setWidth(chartDefinition.getWidth());
120: if (height == -1)
121: setHeight(chartDefinition.getHeight());
122:
123: return chartDefinition;
124: }
125:
126: public Document getXmlContent() {
127:
128: // Create a document that describes the result
129: Document result = DocumentHelper.createDocument();
130: String baseUrl = PentahoSystem.getApplicationContext()
131: .getBaseUrl();
132: setXslProperty("baseUrl", baseUrl); //$NON-NLS-1$
133:
134: // load the XML document that defines the pie
135: ActionResource resource = new ActionResource(title,
136: IActionResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$
137: definitionPath);
138: Document chartDefinition = null;
139: String mapName = "chart" + chartCount++; //$NON-NLS-1$
140: try {
141: chartDefinition = getResourceAsDocument(getSession(),
142: resource);
143: } catch (IOException e) {
144: }
145: if (chartDefinition == null) {
146: Element errorElement = result.addElement("error"); //$NON-NLS-1$
147: errorElement
148: .addElement("title").setText(Messages.getString("ABSTRACTCHARTEXPRESSION.ERROR_0001_ERROR_GENERATING_CHART")); //$NON-NLS-1$ //$NON-NLS-2$
149: String message = Messages
150: .getString(
151: "CHARTS.ERROR_0001_CHART_DEFINIION_MISSING", definitionPath); //$NON-NLS-1$
152: errorElement.addElement("message").setText(message); //$NON-NLS-1$
153: error(message);
154: return result;
155: }
156: // create a pie definition from the XML definition
157: dataDefinition = createChart(chartDefinition);
158: if (dataDefinition == null) {
159: Element errorElement = result.addElement("error"); //$NON-NLS-1$
160: errorElement
161: .addElement("title").setText(Messages.getString("ABSTRACTCHARTEXPRESSION.ERROR_0001_ERROR_GENERATING_CHART")); //$NON-NLS-1$ //$NON-NLS-2$
162: String message = Messages
163: .getString(
164: "CHARTS.ERROR_0002_CHART_DATA_MISSING", solution + "/" + actionPath + "/" + actionName); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
165: errorElement.addElement("message").setText(message); //$NON-NLS-1$
166: // System .out.println( result.asXML() );
167: return result;
168: }
169:
170: // create an image for the dial using the JFreeChart engine
171: PrintWriter printWriter = new PrintWriter(new StringWriter());
172: // we'll dispay the title in HTML so that the dial image does not have
173: // to
174: // accommodate it
175: String chartTitle = ""; //$NON-NLS-1$
176: try {
177: if (height == -1)
178: height = Integer.parseInt(chartDefinition
179: .selectSingleNode("/chart/height").getText()); //$NON-NLS-1$
180: if (width == -1)
181: width = Integer.parseInt(chartDefinition
182: .selectSingleNode("/chart/width").getText()); //$NON-NLS-1$
183: } catch (Exception e) {
184: // go with the default
185: }
186: if (chartDefinition.selectSingleNode("/chart/urlTemplate") != null) { //$NON-NLS-1$
187: urlTemplate = chartDefinition.selectSingleNode(
188: "/chart/urlTemplate").getText(); //$NON-NLS-1$
189: }
190:
191: if (chartDefinition.selectSingleNode("/chart/paramName") != null) { //$NON-NLS-1$
192: paramName = chartDefinition.selectSingleNode(
193: "/chart/paramName").getText(); //$NON-NLS-1$
194: }
195:
196: Element root = result.addElement("charts"); //$NON-NLS-1$
197: DefaultPieDataset chartDataDefinition = (DefaultPieDataset) dataDefinition;
198: // if (chartDataDefinition.getRowCount() > 0) {
199: // create temporary file names
200: String[] tempFileInfo = createTempFile();
201: String fileName = tempFileInfo[AbstractChartComponent.FILENAME_INDEX];
202: String filePathWithoutExtension = tempFileInfo[AbstractChartComponent.FILENAME_WITHOUT_EXTENSION_INDEX];
203:
204: ChartRenderingInfo info = new ChartRenderingInfo(
205: new StandardEntityCollection());
206: JFreeChartEngine
207: .saveChart(
208: chartDataDefinition,
209: chartTitle,
210: "", filePathWithoutExtension, width, height, JFreeChartEngine.OUTPUT_PNG, printWriter, info, this ); //$NON-NLS-1$
211: applyOuterURLTemplateParam();
212: populateInfo(info);
213: Element chartElement = root.addElement("chart"); //$NON-NLS-1$
214: chartElement.addElement("mapName").setText(mapName); //$NON-NLS-1$
215: chartElement
216: .addElement("width").setText(Integer.toString(width)); //$NON-NLS-1$
217: chartElement
218: .addElement("height").setText(Integer.toString(height)); //$NON-NLS-1$
219: // for (int row = 0; row < chartDataDefinition.getRowCount(); row++) {
220: // for (int column = 0; column < chartDataDefinition.getColumnCount();
221: // column++) {
222: // Number value = chartDataDefinition.getValue(row, column);
223: // Comparable rowKey = chartDataDefinition.getRowKey(row);
224: // Comparable columnKey = chartDataDefinition.getColumnKey(column);
225: // Element valueElement = chartElement.addElement("value2D");
226: // //$NON-NLS-1$
227: // valueElement.addElement("value").setText(value.toString());
228: // //$NON-NLS-1$
229: // valueElement.addElement("row-key").setText(rowKey.toString());
230: // //$NON-NLS-1$
231: // valueElement.addElement("column-key").setText(columnKey.toString());
232: // //$NON-NLS-1$
233: // }
234: // }
235: String mapString = ImageMapUtilities.getImageMap(mapName, info);
236: chartElement.addElement("imageMap").setText(mapString); //$NON-NLS-1$
237: chartElement.addElement("image").setText(fileName); //$NON-NLS-1$
238: // }
239: return result;
240: }
241:
242: private void populateInfo(ChartRenderingInfo info) {
243: ArrayList keyListArray = null;
244: int keyListIndex = 0;
245: Iterator iter = info.getEntityCollection().iterator();
246: while (iter.hasNext()) {
247: ChartEntity entity = (ChartEntity) iter.next();
248: if (entity instanceof PieSectionEntity) {
249: PieSectionEntity pieSectionEntity = (PieSectionEntity) entity;
250: String value = pieSectionEntity.getSectionKey()
251: .toString();
252: if (paramName == null) {
253: pieSectionEntity.setURLText(value);
254: } else {
255: try {
256: String encodedVal = URLEncoder.encode(value,
257: LocaleHelper.getSystemEncoding());
258: String drillURL = TemplateUtil.applyTemplate(
259: urlTemplate, paramName, encodedVal);
260: pieSectionEntity.setURLText(drillURL);
261:
262: } catch (UnsupportedEncodingException e) {
263: // TODO Auto-generated catch block
264: e.printStackTrace();
265: }
266: }
267: } else if (entity instanceof CategoryItemEntity) {
268: CategoryItemEntity categoryItemEntity = (CategoryItemEntity) entity;
269: if (keyListArray == null) {
270: keyListArray = new ArrayList(categoryItemEntity
271: .getDataset().getRowKeys());
272: }
273: String category = categoryItemEntity.getCategory()
274: .toString();
275: if (paramName == null) {
276: categoryItemEntity.setURLText(category);
277: } else {
278: try {
279: String encodedVal = URLEncoder.encode(category,
280: LocaleHelper.getSystemEncoding());
281: String drillURL = TemplateUtil.applyTemplate(
282: urlTemplate, paramName, encodedVal);
283: if (keyListIndex >= keyListArray.size()) {
284: keyListIndex = 0;
285: }
286: encodedVal = URLEncoder.encode(keyListArray
287: .get(keyListIndex).toString(),
288: LocaleHelper.getSystemEncoding());
289: keyListIndex++;
290: drillURL = TemplateUtil.applyTemplate(drillURL,
291: paramName2, encodedVal);
292: categoryItemEntity.setURLText(drillURL);
293:
294: } catch (UnsupportedEncodingException e) {
295: // TODO Auto-generated catch block
296: e.printStackTrace();
297: }
298: }
299: }
300: }
301: }
302:
303: public boolean validate() {
304: // TODO Auto-generated method stub
305: return false;
306: }
307: }
|