Package org.pentaho.platform.uifoundation.component.xml

Source Code of org.pentaho.platform.uifoundation.component.xml.WidgetGridComponent

/*
* 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 - 2013 Pentaho Corporation.  All rights reserved.
*/

package org.pentaho.platform.uifoundation.component.xml;

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.dom4j.Node;
import org.pentaho.commons.connection.IPentahoMetaData;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.platform.api.engine.IActionParameter;
import org.pentaho.platform.api.engine.ILogger;
import org.pentaho.platform.api.engine.IPentahoRequestContext;
import org.pentaho.platform.api.engine.IPentahoUrlFactory;
import org.pentaho.platform.api.engine.IRuntimeContext;
import org.pentaho.platform.api.engine.ISolutionEngine;
import org.pentaho.platform.engine.core.output.SimpleOutputHandler;
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.engine.services.runtime.TemplateUtil;
import org.pentaho.platform.uifoundation.chart.DialWidgetDefinition;
import org.pentaho.platform.uifoundation.chart.JFreeChartEngine;
import org.pentaho.platform.uifoundation.chart.WidgetDefinition;
import org.pentaho.platform.uifoundation.messages.Messages;
import org.pentaho.platform.util.messages.LocaleHelper;
import org.pentaho.platform.util.xml.dom4j.XmlDom4JHelper;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class WidgetGridComponent extends XmlComponent {

  /**
   *
   */
  private static final long serialVersionUID = -3952161695550067971L;

  private String definitionPath;

  private int widgetWidth;

  private int widgetHeight;

  private String solution = null;

  private String actionPath = null;

  private String actionName = null;

  private String valueItem = null;

  private String nameItem = null;

  private int columns = 0;

  private String instanceId = null;

  private String actionOutput = null;

  private String urlTemplate = null;

  private String style = null;

  private IRuntimeContext context;

  private static final Log logger = LogFactory.getLog( WidgetGridComponent.class );

  @Override
  public Log getLogger() {
    return WidgetGridComponent.logger;
  }

  /**
   * Creates a WidgetGrid
   * <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 widgetWidth
   *          The width of the image to be created
   * @param widgetHeight
   *          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 WidgetGridComponent( final String definitionPath, final IPentahoUrlFactory urlFactory, final List messages ) {
    super( urlFactory, messages, null );
    this.definitionPath = definitionPath;
    ActionInfo info = ActionInfo.parseActionString( definitionPath );
    if ( info != null ) {
      setSourcePath( info.getSolutionName() + File.separator + info.getPath() );
    }
    setXsl( "text/html", "DialWidget.xsl" ); //$NON-NLS-1$ //$NON-NLS-2$   
  }

  /**
   * Sets the width (in pixels) of the widget images that will be created
   *
   * @param widgetWidth
   */
  public void setWidgetWidth( final int widgetWidth ) {
    this.widgetWidth = widgetWidth;
  }

  /**
   * Sets the height (in pixels) of the widget images that will be created
   *
   * @param widgetHeight
   */
  public void setWidgetHeight( final int widgetHeight ) {
    this.widgetHeight = widgetHeight;
  }

  /**
   * Sets the number of widgets that will be dispayed in a row before another row of widgets is created
   *
   * @param instanceId
   */
  public void setColumns( final int columns ) {
    this.columns = columns;
  }

  /**
   * Sets the instance id for this execution
   *
   * @param instanceId
   *          The instance id of the parent object or process
   */
  public void setInstanceId( final String instanceId ) {
    this.instanceId = instanceId;
  }

  public boolean setDataAction( final String widgetGridDataDefinition ) {
    try {
      Document dataActionDocument = null;
      try {
        org.dom4j.io.SAXReader reader = new org.dom4j.io.SAXReader();
        reader.setEntityResolver( new SolutionURIResolver() );
        dataActionDocument =
            reader.read( ActionSequenceResource.getInputStream( widgetGridDataDefinition, LocaleHelper.getLocale() ) );
      } catch ( Throwable t ) {
        return false;
      }
      Node dataNode = dataActionDocument.selectSingleNode( "widgetgrid/data" ); //$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$
      widgetWidth = (int) XmlDom4JHelper.getNodeText( "widgetgrid/width", dataActionDocument, 125 ); //$NON-NLS-1$
      widgetHeight = (int) XmlDom4JHelper.getNodeText( "widgetgrid/height", dataActionDocument, 125 ); //$NON-NLS-1$
      columns = (int) XmlDom4JHelper.getNodeText( "widgetgrid/columns", dataActionDocument, 2 ); //$NON-NLS-1$
      style = XmlDom4JHelper.getNodeText( "widgetgrid/style", dataActionDocument ); //$NON-NLS-1$
    } catch ( Exception e ) {
      error( Messages.getInstance().getErrorString(
          "WidgetGrid.ERROR_0003_DEFINITION_NOT_VALID", widgetGridDataDefinition ), e ); //$NON-NLS-1$
      return false;
    }
    return true;
  }

  /**
   * Sets the action to be executed to get the data for the widgets
   *
   * @param solution
   * @param actionPath
   * @param actionName
   * @param actionOutput
   * @param nameItem
   * @param valueItem
   */
  public void setDataAction( final String solution, final String actionPath, final String actionName,
      final String actionOutput, final String nameItem, final String valueItem ) {
    this.solution = solution;
    this.actionPath = actionPath;
    this.actionName = actionName;
    this.actionOutput = actionOutput;
    this.valueItem = valueItem;
    this.nameItem = nameItem;
  }

  public void setDrillUrlTemplate( final String urlTemplate ) {
    this.urlTemplate = urlTemplate;
  }

  @Override
  public boolean validate() {
    return true;
  }

  @Override
  public Document getXmlContent() {

    // get the data to populate the widgets
    IPentahoResultSet resultSet = null;
    if ( solution != null ) {
      resultSet = getActionData();
    }

    // create the widget to use
    // load the XML document that defines the dial
    Document dialDefinition = null;
    try {
      org.dom4j.io.SAXReader reader = new org.dom4j.io.SAXReader();
      reader.setEntityResolver( new SolutionURIResolver() );
      dialDefinition = reader.read( ActionSequenceResource.getInputStream( definitionPath, LocaleHelper.getLocale() ) );
    } catch ( Throwable t ) {
      // XML document can't be read. We'll just return a null document.
    }

    // create a dial definition from the XML definition
    WidgetDefinition widgetDefinition =
        new DialWidgetDefinition( dialDefinition, 0, widgetWidth, widgetHeight, getSession() );

    return createDials( resultSet, widgetDefinition );
  }

  protected Document createDials( final IPentahoResultSet resultSet, final WidgetDefinition widgetDefinition ) {

    if ( resultSet == null ) {
      error( Messages.getInstance().getErrorString( "WidgetGrid.ERROR_0001_NO_RESULTS_FROM_ACTION" ) ); //$NON-NLS-1$
      return null;
    }

    if ( valueItem == null ) {
      error( Messages.getInstance().getErrorString( "WidgetGrid.ERROR_0002_NO_VALUE_ITEM" ) ); //$NON-NLS-1$
    }

    // 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( "widgets" ); //$NON-NLS-1$

    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( "WidgetGrid.ERROR_0004_NAME_COLUMN_MISSING", nameItem ) ); //$NON-NLS-1$
      return null;
    }

    if ( valueColumnNo == -1 ) {
      // we did not find the specified name column
      error( Messages.getInstance().getErrorString( "WidgetGrid.ERROR_0005_VALUE_COLUMN_MISSING", valueItem ) ); //$NON-NLS-1$
      return null;
    }

    double value;
    String name;
    Object[] row = resultSet.next();
    while ( row != null ) {
      name = row[nameColumnNo].toString();
      try {
        value = Double.parseDouble( row[valueColumnNo].toString() );
        createDial( value, name, root, widgetDefinition );
      } catch ( Exception e ) {
        //ignore
      }

      row = resultSet.next();
    }
    setXslProperty( "urlTarget", "pentaho_popup" ); //$NON-NLS-1$ //$NON-NLS-2$
    setXslProperty( "columns", Integer.toString( columns ) ); //$NON-NLS-1$
    if ( style != null ) {
      setXslProperty( "style", style ); //$NON-NLS-1$
    }
    return result;
  }

  protected void createDial( final double value, final String name, final Element root,
      final WidgetDefinition widgetDefinition ) {

    widgetDefinition.setValue( new Double( value ) );

    StringWriter stringWriter = new StringWriter();
    PrintWriter printWriter = new PrintWriter( stringWriter );

    // TODO get units from somewhere
    String units = ""; //$NON-NLS-1$
    String dialName = ""; //$NON-NLS-1$
    // 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();
    }
    JFreeChartEngine.saveChart( widgetDefinition, dialName, units, filePathWithoutExtension, widgetWidth, widgetHeight,
        JFreeChartEngine.OUTPUT_PNG, printWriter, this );

    Element widgetNode = root.addElement( "widget" ); //$NON-NLS-1$

    widgetNode.addElement( "title" ).setText( name ); //$NON-NLS-1$
    widgetNode.addElement( "units" ).setText( units ); //$NON-NLS-1$
    widgetNode.addElement( "width" ).setText( Integer.toString( widgetWidth ) ); //$NON-NLS-1$
    widgetNode.addElement( "height" ).setText( Integer.toString( widgetHeight ) ); //$NON-NLS-1$
    Element valueNode = widgetNode.addElement( "value" ); //$NON-NLS-1$
    valueNode.setText( Double.toString( value ) );
    valueNode.addAttribute( "in-image", Boolean.toString( widgetDefinition.getValueFont() != null ) ); //$NON-NLS-1$
    root.addElement( "image" ).setText( fileName ); //$NON-NLS-1$
    widgetNode.addElement( "image" ).setText( fileName ); //$NON-NLS-1$

    // apply the current data item name to the URL template
    String drillUrl = TemplateUtil.applyTemplate( urlTemplate, nameItem, name );

    // now apply any parameters to the URL template
    drillUrl = TemplateUtil.applyTemplate( drillUrl, context );

    widgetNode.addElement( "urlDrill" ).setText( drillUrl ); //$NON-NLS-1$

  }

  public void dispose() {
    if ( context != null ) {
      context.dispose();
    }
  }

  protected IPentahoResultSet getActionData() {
    // create an instance of the solution engine to execute the specified
    // action

    ISolutionEngine solutionEngine = PentahoSystem.get( ISolutionEngine.class, getSession() );
    solutionEngine.setLoggingLevel( ILogger.DEBUG );
    solutionEngine.init( getSession() );

    HashMap parameterProviders = getParameterProviders();

    OutputStream outputStream = null;
    SimpleOutputHandler outputHandler = null;
    outputHandler = new SimpleOutputHandler( outputStream, false );

    ArrayList messages = new ArrayList();
    String processId = this.getClass().getName();

    String actionSeqPath = ActionInfo.buildSolutionPath( solution, actionPath, actionName );

    context =
        solutionEngine.execute( actionSeqPath, processId, false, true, instanceId, false, parameterProviders,
            outputHandler, null, urlFactory, messages );

    if ( actionOutput != null ) {
      if ( context.getOutputNames().contains( actionOutput ) ) {
        IActionParameter output = context.getOutputParameter( actionOutput );
        IPentahoResultSet results = output.getValueAsResultSet();
        if ( results != null ) {
          results = results.memoryCopy();
        }
        return results;
      } else {
        // this is an error
        return null;
      }
    } else {
      // return the first list that we find...
      Iterator it = context.getOutputNames().iterator();
      while ( it.hasNext() ) {
        IActionParameter output = (IActionParameter) it.next();
        if ( output.getType().equalsIgnoreCase( IActionParameter.TYPE_RESULT_SET ) ) {
          IPentahoResultSet results = output.getValueAsResultSet();
          if ( results != null ) {
            results = results.memoryCopy();
          }
          return results;
        }
      }
    }
    return null;
  }

}
TOP

Related Classes of org.pentaho.platform.uifoundation.component.xml.WidgetGridComponent

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.