/* * 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 - 2016 Pentaho Corporation. All rights reserved. */ package org.pentaho.platform.uifoundation.chart; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.pentaho.platform.api.engine.IActionSequenceResource; import org.pentaho.platform.api.engine.IPentahoRequestContext; import org.pentaho.platform.api.engine.IPentahoUrlFactory; import org.pentaho.platform.api.repository2.unified.RepositoryFilePermission; import org.pentaho.platform.engine.core.solution.ActionInfo; import org.pentaho.platform.engine.core.system.PentahoRequestContextHolder; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.services.SolutionURIResolver; import org.pentaho.platform.engine.services.actionsequence.ActionSequenceResource; import org.pentaho.platform.uifoundation.component.xml.XmlComponent; import org.pentaho.platform.uifoundation.messages.Messages; import org.pentaho.platform.util.messages.LocaleHelper; import org.pentaho.platform.util.xml.XMLParserFactoryProducer; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; /** * This class is a Pentaho user interface component. * <p/> * It generates dial images that can be embedded into JSPs, portals or other HTML supporting user interface. * <p/> * <ol> * <li>The creating object sets the width, height, the type of the dial, and the name of the dial.xml file that * contains the definition of the dial.</li> * <li>This class creates an instance of a DialWidgetDefinition using the specified XML definition file. The XML * files are located in the solution folders and have .dial.xml extenstions. The dial XML files define the * attributes that define how the dial looks.</li> * <li>It uses the JFreeChartEngine to create an image of the dial.</li> * <li>Once the image has been created this class creates an XML document describing the dial * <li>It uses an XSL to tranforms the XML description into HTML. * </ol> * This is an example image */ public class DashboardWidgetComponent extends XmlComponent { /** * */ private static final long serialVersionUID = 3060729271469984040L; public static final int TYPE_DIAL = 1; public static final int TYPE_THERMOMETER = 2; private static final Log logger = LogFactory.getLog( DashboardWidgetComponent.class ); private int type; private double value = DashboardWidgetComponent.TYPE_DIAL; private String definitionPath; private String title = ""; //$NON-NLS-1$ private String units = ""; //$NON-NLS-1$ private int width; private int height; /** * Creates a DashboardWidgetComponent. * <p> * After creating an instance of this class <CODE>validate</CODE> should be called. * * @param type * The type of the widget, currently only TYPE_DIAL is supported * @param definitionPath * The path and name of the XML definition of the dial * @param width * The width of the image to be created * @param height * The height of the image to be created * @param urlFactory * The urlFactory for the content * @param messages * The messages list for any logger messages */ public DashboardWidgetComponent( final int type, final String definitionPath, final int width, final int height, final IPentahoUrlFactory urlFactory, final List messages ) { super( urlFactory, messages, null ); this.type = type; this.definitionPath = definitionPath; this.width = width; this.height = height; ActionInfo info = ActionInfo.parseActionString( definitionPath ); if ( info != null ) { setSourcePath( info.getSolutionName() + File.separator + info.getPath() ); } // Set the XSL file to be used to generate the HTML setXsl( "text/html", "DialWidget.xsl" ); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Sets the value to be displayed by the dial. * * @param value * The dial value */ public void setValue( final double value ) { this.value = value; } /** * Sets the title for the dial * * @param title * The title of the dial */ public void setTitle( final String title ) { this.title = title; } /** * Sets the unit for the dial value * * @param units * The dial units */ public void setUnits( final String units ) { this.units = units; } /** * Gets the logger for his component. * * @return logger This component's logger */ @Override public Log getLogger() { return DashboardWidgetComponent.logger; } /** * Validate that this component can generate the requested dial */ @Override public boolean validate() { // TODO return true; } /** * Create a dial image. * <ul> * <li>Load the specified XML document describing the dial definition</li> * <li>Create a dial definition object from the XML definition</li> * <li>Use the JFreeChartEngine to create a dial image</li> * <li>Create an XML document describing the dial</li> * <li>Return the XML document</li> * </ul> * * @return The XML document describing this dial */ @Override public Document getXmlContent() { WidgetDefinition widget = null; if ( type == DashboardWidgetComponent.TYPE_DIAL ) { // load the XML document that defines the dial IActionSequenceResource resource = new ActionSequenceResource( title, IActionSequenceResource.SOLUTION_FILE_RESOURCE, "text/xml", //$NON-NLS-1$ definitionPath ); Document dialDefinition = null; try { org.dom4j.io.SAXReader reader = XMLParserFactoryProducer.getSAXReader( new SolutionURIResolver() ); dialDefinition = reader.read( resource.getInputStream( RepositoryFilePermission.READ, LocaleHelper.getLocale() ) ); } catch ( Throwable t ) { // XML document can't be read. We'll just return a null document. } if ( dialDefinition == null ) { error( Messages.getInstance().getErrorString( "Widget.ERROR_0002_INVALID_RESOURCE", definitionPath ) ); //$NON-NLS-1$ return null; } // create a dial definition from the XML definition widget = new DialWidgetDefinition( dialDefinition, 0, width, height, getSession() ); if ( widget != null ) { // set the value to be displayed on the dial widget.setValue( new Double( value ) ); } } /* * else if( type == TYPE_THERMOMETER ) { // load the XML document that defines the thermometer * * ActionResource resource = new ActionResource( title, IActionResource.SOLUTION_FILE_RESOURCE, "text/xml", * //$NON-NLS-1$ PentahoSystem.getApplicationContext().getSolutionPath( definitionPath ) ); //$NON-NLS-1$ * Document thermometerDefinition = null; try { thermometerDefinition = PentahoSystem.getResourceAsDocument( * resource ); } catch (IOException e) {} // create a dial definition from the XML definition widget = * createThermometer( thermometerDefinition ); * * if( widget != null ) { // set the value to be displayed on the dial widget.setValue( new Double(value) ); // * Set the XSL file to be used to generate the HTML setXsl( "text/html", "DialWidget.xsl" ); //$NON-NLS-1$ * //$NON-NLS-2$ } else { error( Messages.getInstance().getString("Widget.ERROR_0001_COULD_NOT_CREATE") ); * //$NON-NLS-1$ return null; } } */ if ( widget == null ) { error( Messages.getInstance().getString( "Widget.ERROR_0001_COULD_NOT_CREATE" ) ); //$NON-NLS-1$ return null; } // create an image for the dial using the JFreeChart engine StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter( stringWriter ); // create temporary file names String solutionDir = "system/tmp/"; //$NON-NLS-1$ String fileNamePrefix = "tmp_pie_"; //$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 ) { // TODO Auto-generated catch block e.printStackTrace(); } String dialTitle = ""; //$NON-NLS-1$ JFreeChartEngine.saveChart( widget, dialTitle, units, filePathWithoutExtension, width, height, JFreeChartEngine.OUTPUT_PNG, printWriter, this ); // Create a document that describes the result Document result = DocumentHelper.createDocument(); IPentahoRequestContext requestContext = PentahoRequestContextHolder.getRequestContext(); setXslProperty( "baseUrl", requestContext.getContextPath() ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ setXslProperty( "fullyQualifiedServerUrl", PentahoSystem.getApplicationContext().getFullyQualifiedServerURL() ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Element root = result.addElement( "widget" ); //$NON-NLS-1$ root.addElement( "title" ).setText( title ); //$NON-NLS-1$ root.addElement( "units" ).setText( units ); //$NON-NLS-1$ root.addElement( "width" ).setText( Integer.toString( width ) ); //$NON-NLS-1$ root.addElement( "height" ).setText( Integer.toString( height ) ); //$NON-NLS-1$ Element valueNode = root.addElement( "value" ); //$NON-NLS-1$ valueNode.setText( Double.toString( value ) ); valueNode.addAttribute( "in-image", Boolean.toString( widget.getValueFont() != null ) ); //$NON-NLS-1$ root.addElement( "image" ).setText( fileName ); //$NON-NLS-1$ return result; } public void dispose() { } }