Package org.pentaho.platform.plugin.action.jfreechart

Source Code of org.pentaho.platform.plugin.action.jfreechart.ChartComponent

/*!
* 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 (c) 2002-2013 Pentaho Corporation..  All rights reserved.
*/

package org.pentaho.platform.plugin.action.jfreechart;

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.engine.IApplicationContext;
import org.pentaho.platform.api.engine.IPentahoRequestContext;
import org.pentaho.platform.api.repository.IContentItem;
import org.pentaho.platform.api.util.XmlParseException;
import org.pentaho.platform.engine.core.system.PentahoRequestContextHolder;
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;

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;

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 CONTEXT_PATH_OUTPUT = "context-path"; //$NON-NLS-1$

  private static final String FULLY_QUALIFIED_SERVER_URL_OUTPUT = "fully-qualified-server-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 );
    if ( !data.isScrollable() ) {
      getLogger().debug( "ResultSet is not scrollable. Copying into memory" ); //$NON-NLS-1$
      IPentahoResultSet memSet = data.memoryCopy();
      data.close();
      data = memSet;
    }

    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 ) ) {
              IPentahoRequestContext requestContext = PentahoRequestContextHolder.getRequestContext();
              outputValue = requestContext.getContextPath();

            } else if ( outputName.equals( ChartComponent.CONTEXT_PATH_OUTPUT ) ) {
              IPentahoRequestContext requestContext = PentahoRequestContextHolder.getRequestContext();
              outputValue = requestContext.getContextPath();
            } else if ( outputName.equals( ChartComponent.FULLY_QUALIFIED_SERVER_URL_OUTPUT ) ) {

              IApplicationContext applicationContext = PentahoSystem.getApplicationContext();
              if ( applicationContext != null ) {
                outputValue = applicationContext.getFullyQualifiedServerURL();
              } else {
                IPentahoRequestContext requestContext = PentahoRequestContextHolder.getRequestContext();
                outputValue = requestContext.getContextPath();
              }
            } 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$
              }
              IPentahoRequestContext requestContext = PentahoRequestContextHolder.getRequestContext();
              String contextPath = requestContext.getContextPath();
              outputValue +=
                  "src=\"" + contextPath + "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;
  }
}
TOP

Related Classes of org.pentaho.platform.plugin.action.jfreechart.ChartComponent

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.