Package org.pentaho.reporting.ui.datasources.scriptable

Source Code of org.pentaho.reporting.ui.datasources.scriptable.ScriptableDataSourceEditor$ScriptablePreviewWorker

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

package org.pentaho.reporting.ui.datasources.scriptable;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;

import org.apache.bsf.BSFManager;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.pentaho.reporting.engine.classic.core.AbstractReportDefinition;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.DefaultReportEnvironment;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException;
import org.pentaho.reporting.engine.classic.core.ReportEnvironment;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeContext;
import org.pentaho.reporting.engine.classic.core.designtime.DesignTimeUtil;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.ExceptionDialog;
import org.pentaho.reporting.engine.classic.core.modules.gui.commonswing.SwingUtil;
import org.pentaho.reporting.engine.classic.core.util.ReportParameterValues;
import org.pentaho.reporting.engine.classic.extensions.datasources.scriptable.ScriptableDataFactory;
import org.pentaho.reporting.libraries.base.config.Configuration;
import org.pentaho.reporting.libraries.base.util.StringUtils;
import org.pentaho.reporting.libraries.designtime.swing.BorderlessButton;
import org.pentaho.reporting.libraries.designtime.swing.background.CancelEvent;
import org.pentaho.reporting.libraries.designtime.swing.background.DataPreviewDialog;
import org.pentaho.reporting.libraries.designtime.swing.background.PreviewWorker;
import org.pentaho.reporting.libraries.resourceloader.ResourceKey;

/**
* @author David Kincade
*/
public class ScriptableDataSourceEditor extends JDialog
{
  private class UpdateLanguageHandler implements ActionListener, ListSelectionListener
  {
    private UpdateLanguageHandler()
    {
    }

    public void actionPerformed(final ActionEvent e)
    {
      updateComponents();
    }

    /**
     * Called whenever the value of the selection changes.
     *
     * @param e the event that characterizes the change.
     */
    public void valueChanged(final ListSelectionEvent e)
    {
      updateComponents();
    }
  }

  private static class InternalBSFManager extends BSFManager
  {
    private InternalBSFManager()
    {
    }

    public static String[] getRegisteredLanguages()
    {
      final ArrayList<String> list = new ArrayList<String>();
      final Iterator iterator = registeredEngines.entrySet().iterator();
      while (iterator.hasNext())
      {
        final Map.Entry entry = (Map.Entry) iterator.next();
        final String lang = (String) entry.getKey();
        final String className = (String) entry.getValue();

        try
        {
          // this is how BSH will load the class
          Class.forName(className, false, Thread.currentThread().getContextClassLoader());
          list.add(lang);
        }
        catch (Throwable t)
        {
          // ignored.
        }

      }
      return list.toArray(new String[list.size()]);
    }
  }


  private class QueryRemoveAction extends AbstractAction implements ListSelectionListener
  {
    private QueryRemoveAction()
    {
      final URL resource = ScriptableDataSourceEditor.class.getResource
          ("/org/pentaho/reporting/ui/datasources/scriptable/resources/Remove.png");
      if (resource != null)
      {
        putValue(Action.SMALL_ICON, new ImageIcon(resource));
      }
      else
      {
        putValue(Action.NAME, Messages.getString("ScriptableDataSourceEditor.RemoveQuery.Name"));
      }
      putValue(Action.SHORT_DESCRIPTION, Messages.getString("ScriptableDataSourceEditor.RemoveQuery.Description"));
    }

    public void actionPerformed(final ActionEvent e)
    {
      final DataSetQuery query = (DataSetQuery) queryNameList.getSelectedValue();
      if (query != null)
      {
        queries.remove(query.getQueryName());
      }

      inModifyingQueryNameList = true;
      updateQueryList();
      queryNameList.clearSelection();
      inModifyingQueryNameList = false;
      updateComponents();
    }

    public void valueChanged(final ListSelectionEvent e)
    {
      setEnabled(queryNameList.isSelectionEmpty() == false);
    }
  }

  private class QueryNameTextFieldDocumentListener implements DocumentListener
  {
    public void insertUpdate(final DocumentEvent e)
    {
      update();
    }

    public void removeUpdate(final DocumentEvent e)
    {
      update();
    }

    public void changedUpdate(final DocumentEvent e)
    {
      update();
    }

    private void update()
    {
      if (inModifyingQueryNameList)
      {
        return;
      }
      final String queryName = queryNameTextField.getText();
      final DataSetQuery currentQuery = (DataSetQuery) queryNameList.getSelectedValue();
      if (currentQuery == null)
      {
        return;
      }

      if (queryName.equals(currentQuery.getQueryName()))
      {
        return;
      }
      if (queries.containsKey(queryName))
      {
        return;
      }

      inQueryNameUpdate = true;
      queries.remove(currentQuery.getQueryName());
      currentQuery.setQueryName(queryName);
      queries.put(currentQuery.getQueryName(), currentQuery);
      updateQueryList();
      queryNameList.setSelectedValue(currentQuery, true);
      inQueryNameUpdate = false;
    }
  }

  private static class QueryNameListCellRenderer extends DefaultListCellRenderer
  {
    public Component getListCellRendererComponent(final JList list,
                                                  final Object value,
                                                  final int index,
                                                  final boolean isSelected,
                                                  final boolean cellHasFocus)
    {
      final JLabel listCellRendererComponent =
          (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
      if (value != null)
      {
        final String queryName = ((DataSetQuery) value).getQueryName();
        if (StringUtils.isEmpty(queryName) == false)
        {
          listCellRendererComponent.setText(queryName);
        }
        else
        {
          listCellRendererComponent.setText(" ");
        }
      }
      return listCellRendererComponent;
    }
  }

  private class QueryNameListSelectionListener implements ListSelectionListener
  {
    public void valueChanged(final ListSelectionEvent e)
    {
      if (!inQueryNameUpdate)
      {
        final DataSetQuery query = (DataSetQuery) queryNameList.getSelectedValue();
        if (query != null)
        {
          queryNameTextField.setText(query.getQueryName());
          queryTextArea.setText(query.getQuery());
          updateComponents();
        }
        else
        {
          queryNameTextField.setText("");
          queryTextArea.setText("");
          updateComponents();
        }
      }
    }
  }

  private class CancelAction extends AbstractAction
  {
    private CancelAction()
    {
      putValue(Action.NAME, Messages.getString("ScriptableDataSourceEditor.Cancel.Name"));
    }

    public void actionPerformed(final ActionEvent e)
    {
      dispose();
    }
  }

  private class OKAction extends AbstractAction
  {
    private OKAction()
    {
      putValue(Action.NAME, Messages.getString("ScriptableDataSourceEditor.OK.Name"));
    }

    public void actionPerformed(final ActionEvent e)
    {
      confirmed = true;
      dispose();
    }
  }

  private class QueryAddAction extends AbstractAction
  {
    private QueryAddAction()
    {
      final URL resource = ScriptableDataSourceEditor.class.getResource
          ("/org/pentaho/reporting/ui/datasources/scriptable/resources/Add.png");
      if (resource != null)
      {
        putValue(Action.SMALL_ICON, new ImageIcon(resource));
      }
      else
      {
        putValue(Action.NAME, Messages.getString("ScriptableDataSourceEditor.AddQuery.Name"));
      }
      putValue(Action.SHORT_DESCRIPTION, Messages.getString("ScriptableDataSourceEditor.AddQuery.Description"));
    }

    public void actionPerformed(final ActionEvent e)
    {
      // Find a unique query name
      String queryName = Messages.getString("ScriptableDataSourceEditor.Query");
      for (int i = 1; i < 1000; ++i)
      {
        final String newQueryName = Messages.getString("ScriptableDataSourceEditor.Query") + ' ' + i;
        if (!queries.containsKey(newQueryName))
        {
          queryName = newQueryName;
          break;
        }
      }

      final DataSetQuery newQuery = new DataSetQuery(queryName, "");
      queries.put(newQuery.getQueryName(), newQuery);

      inModifyingQueryNameList = true;
      updateQueryList();
      queryNameList.setSelectedValue(newQuery, true);
      inModifyingQueryNameList = false;
      updateComponents();
    }
  }

  private class QueryDocumentListener implements DocumentListener
  {
    private QueryDocumentListener()
    {
    }

    public void insertUpdate(final DocumentEvent e)
    {
      update();
    }

    public void removeUpdate(final DocumentEvent e)
    {
      update();
    }

    public void changedUpdate(final DocumentEvent e)
    {
      update();
    }

    private void update()
    {
      final DataSetQuery currentQuery = (DataSetQuery) queryNameList.getSelectedValue();
      if (currentQuery == null)
      {
        return;
      }

      currentQuery.setQuery(queryTextArea.getText());
    }
  }

  private class PreviewAction extends AbstractAction
  {
    private PreviewAction()
    {
      putValue(Action.NAME, Messages.getString("ScriptableDataSourceEditor.Preview.Name"));
    }

    public void actionPerformed(final ActionEvent aEvt)
    {
      try
      {
        final ScriptableDataFactory dataFactory = produceFactory();
        final AbstractReportDefinition report = designTimeContext.getReport();
        final MasterReport masterReport = DesignTimeUtil.getMasterReport(report);
        final Configuration configuration;
        final ResourceKey contentBase;
        final ReportEnvironment reportEnvironment;
        if (masterReport == null)
        {
          contentBase = null;
          configuration = ClassicEngineBoot.getInstance().getGlobalConfig();
          reportEnvironment = new DefaultReportEnvironment(configuration);
        }
        else
        {
          contentBase = masterReport.getContentBase();
          configuration = masterReport.getConfiguration();
          reportEnvironment = masterReport.getReportEnvironment();
        }
        dataFactory.initialize(configuration,
            report.getResourceManager(), contentBase, MasterReport.computeAndInitResourceBundleFactory
                (report.getResourceBundleFactory(), reportEnvironment));

        final DataPreviewDialog previewDialog = new DataPreviewDialog(ScriptableDataSourceEditor.this);

        final ScriptablePreviewWorker worker = new ScriptablePreviewWorker(dataFactory, queryNameTextField.getText());
        previewDialog.showData(worker);

        final ReportDataFactoryException factoryException = worker.getException();
        if (factoryException != null)
        {
          ExceptionDialog.showExceptionDialog(ScriptableDataSourceEditor.this,
              Messages.getString("ScriptableDataSourceEditor.PreviewError.Title"),
              Messages.getString("ScriptableDataSourceEditor.PreviewError.Message"), factoryException);
        }
      }
      catch (Exception e)
      {
        ExceptionDialog.showExceptionDialog(ScriptableDataSourceEditor.this,
            Messages.getString("ScriptableDataSourceEditor.PreviewError.Title"),
            Messages.getString("ScriptableDataSourceEditor.PreviewError.Message"), e);
      }
    }
  }

  private static class ScriptablePreviewWorker implements PreviewWorker
  {
    private ScriptableDataFactory dataFactory;
    private TableModel resultTableModel;
    private ReportDataFactoryException exception;
    private String query;

    private ScriptablePreviewWorker(final ScriptableDataFactory dataFactory,
                                    final String query)
    {
      if (dataFactory == null)
      {
        throw new NullPointerException();
      }
      this.query = query;
      this.dataFactory = dataFactory;
    }

    public ReportDataFactoryException getException()
    {
      return exception;
    }

    public TableModel getResultTableModel()
    {
      return resultTableModel;
    }

    public void close()
    {
    }

    /**
     * Requests that the thread stop processing as soon as possible.
     */
    public void cancelProcessing(final CancelEvent event)
    {
      dataFactory.cancelRunningQuery();
    }

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p/>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    public void run()
    {
      try
      {
        dataFactory.open();
        resultTableModel = dataFactory.queryData(query, new ReportParameterValues());
        dataFactory.close();
      }
      catch (ReportDataFactoryException e)
      {
        exception = e;
      }
    }
  }

  private boolean confirmed;
  private JList queryNameList;
  private JTextField queryNameTextField;
  private JList languageField;
  private RSyntaxTextArea queryTextArea;
  private Map<String, DataSetQuery> queries;
  private boolean inQueryNameUpdate;
  private boolean inModifyingQueryNameList;
  private OKAction okAction;
  private PreviewAction previewAction;
  private DesignTimeContext designTimeContext;

  public ScriptableDataSourceEditor(final DesignTimeContext designTimeContext)
  {
    init(designTimeContext);
  }

  public ScriptableDataSourceEditor(final DesignTimeContext designTimeContext, final Dialog owner)
  {
    super(owner);
    init(designTimeContext);
  }

  public ScriptableDataSourceEditor(final DesignTimeContext designTimeContext, final Frame owner)
  {
    super(owner);
    init(designTimeContext);
  }

  private void init(final DesignTimeContext designTimeContext)
  {
    if (designTimeContext == null)
    {
      throw new NullPointerException();
    }
    this.designTimeContext = designTimeContext;

    setTitle(Messages.getString("ScriptableDataSourceEditor.Title"));
    setModal(true);

    okAction = new OKAction();
    previewAction = new PreviewAction();

    queryNameTextField = new JTextField(null, 0);
    queryNameTextField.setColumns(35);
    queryNameTextField.getDocument().addDocumentListener(new QueryNameTextFieldDocumentListener());

    queryTextArea = new RSyntaxTextArea();
    queryTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_NONE);
    queryTextArea.getDocument().addDocumentListener(new QueryDocumentListener());

    languageField = new JList(new DefaultComboBoxModel(InternalBSFManager.getRegisteredLanguages()));
    languageField.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    languageField.getSelectionModel().addListSelectionListener(new UpdateLanguageHandler());

    queryNameList = new JList();
    queryNameList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    queryNameList.setVisibleRowCount(5);
    queryNameList.addListSelectionListener(new QueryNameListSelectionListener());
    queryNameList.setCellRenderer(new QueryNameListCellRenderer());

    final QueryRemoveAction removeQueryAction = new QueryRemoveAction();
    queryNameList.addListSelectionListener(removeQueryAction);


    final JPanel queryDetailsNamePanel = new JPanel(new BorderLayout());
    queryDetailsNamePanel.add(new JLabel(Messages.getString("ScriptableDataSourceEditor.QueryName")), BorderLayout.NORTH);
    queryDetailsNamePanel.add(queryNameTextField, BorderLayout.CENTER);

    final JPanel queryContentHolder = new JPanel(new BorderLayout());
    queryContentHolder.add(BorderLayout.NORTH, new JLabel(Messages.getString("ScriptableDataSourceEditor.QueryLabel")));
    queryContentHolder.add(BorderLayout.CENTER, new RTextScrollPane(500, 300, queryTextArea, true));

    // Create the query details panel
    final JPanel queryDetailsPanel = new JPanel(new BorderLayout());
    queryDetailsPanel.setBorder(new EmptyBorder(0, 8, 8, 8));
    queryDetailsPanel.add(BorderLayout.NORTH, queryDetailsNamePanel);
    queryDetailsPanel.add(BorderLayout.CENTER, queryContentHolder);

    final JPanel previewButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    previewButtonPanel.add(new JButton(previewAction));

    final JPanel queryContentPanel = new JPanel(new BorderLayout());
    queryContentPanel.add(BorderLayout.NORTH, createQueryListPanel());
    queryContentPanel.add(BorderLayout.CENTER, queryDetailsPanel);

    final JLabel languageLabel = new JLabel(Messages.getString("ScriptableDataSourceEditor.Language"));
    languageLabel.setBorder(new EmptyBorder(0, 0, 3, 0));

    final JPanel languagesPanel = new JPanel(new BorderLayout());
    languagesPanel.setBorder(new EmptyBorder(8, 8, 8, 0));
    languagesPanel.add(BorderLayout.NORTH, languageLabel);
    languagesPanel.add(BorderLayout.CENTER, new JScrollPane(languageField));

    final JPanel contentPanel = new JPanel(new BorderLayout());
    contentPanel.add(BorderLayout.WEST, languagesPanel);
    contentPanel.add(BorderLayout.CENTER, queryContentPanel);
    contentPanel.add(BorderLayout.SOUTH, previewButtonPanel);

    final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
    buttonPanel.add(new JButton(okAction));
    buttonPanel.add(new JButton(new CancelAction()));

    setLayout(new BorderLayout());
    add(BorderLayout.CENTER, contentPanel);
    add(BorderLayout.SOUTH, buttonPanel);

    pack();
    SwingUtil.centerDialogInParent(this);
  }

  private JPanel createQueryListPanel()
  {
    final QueryRemoveAction queryRemoveAction = new QueryRemoveAction();
    queryNameList.addListSelectionListener(queryRemoveAction);

    final JPanel theQueryButtonsPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    theQueryButtonsPanel.add(new BorderlessButton(new QueryAddAction()));
    theQueryButtonsPanel.add(new BorderlessButton(queryRemoveAction));

    final JPanel theQueryControlsPanel = new JPanel(new BorderLayout());
    theQueryControlsPanel.add(BorderLayout.WEST, new JLabel(Messages.getString("ScriptableDataSourceEditor.AvailableQueries")));
    theQueryControlsPanel.add(BorderLayout.EAST, theQueryButtonsPanel);

    final JPanel queryListPanel = new JPanel(new BorderLayout());
    queryListPanel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 8));
    queryListPanel.add(BorderLayout.NORTH, theQueryControlsPanel);
    queryListPanel.add(BorderLayout.CENTER, new JScrollPane(queryNameList));
    return queryListPanel;
  }

  public ScriptableDataFactory performConfiguration(final ScriptableDataFactory dataFactory, final String selectedQuery)
  {
    // Reset the confirmed / cancel flag
    confirmed = false;

    // Initialize the internal storage
    queries = new TreeMap<String, DataSetQuery>();

    // Load the current configuration
    if (dataFactory != null)
    {
      languageField.setSelectedValue(dataFactory.getLanguage(), true);

      final String[] queryNames = dataFactory.getQueryNames();
      for (int i = 0; i < queryNames.length; i++)
      {
        final String queryName = queryNames[i];
        final String query = dataFactory.getQuery(queryName);
        queries.put(queryName, new DataSetQuery(queryName, query));
      }
    }

    // Prepare the data and the enable the proper buttons
    updateComponents();
    updateQueryList();
    setSelectedQuery(selectedQuery);

    // Enable the dialog

    setVisible(true);

    if (!confirmed)
    {
      return null;
    }

    return produceFactory();
  }

  private ScriptableDataFactory produceFactory()
  {
    final ScriptableDataFactory returnDataFactory = new ScriptableDataFactory();
    returnDataFactory.setLanguage((String) languageField.getSelectedValue());

    final DataSetQuery[] queries = this.queries.values().toArray(new DataSetQuery[this.queries.size()]);
    for (int i = 0; i < queries.length; i++)
    {
      final DataSetQuery query = queries[i];
      returnDataFactory.setQuery(query.getQueryName(), query.getQuery());
    }
    return returnDataFactory;
  }

  protected void updateQueryList()
  {
    queryNameList.removeAll();
    queryNameList.setListData(queries.values().toArray(new DataSetQuery[queries.size()]));
  }

  private void setSelectedQuery(final String aQuery)
  {
    final ListModel theModel = queryNameList.getModel();
    for (int i = 0; i < theModel.getSize(); i++)
    {
      final DataSetQuery theDataSet = (DataSetQuery) theModel.getElementAt(i);
      if (theDataSet.getQueryName().equals(aQuery))
      {
        queryNameList.setSelectedValue(theDataSet, true);
        break;
      }
    }
  }

  protected void updateComponents()
  {
    final boolean querySelected = queryNameList.getSelectedIndex() != -1;
    final boolean hasQueries = queryNameList.getModel().getSize() > 0;

    queryNameTextField.setEnabled(querySelected);
    queryTextArea.setEnabled(querySelected);

    okAction.setEnabled(hasQueries && languageField.getSelectedIndex() != -1);
    queryTextArea.setSyntaxEditingStyle(mapLanguageToSyntaxHighlighting((String) languageField.getSelectedValue()));
    previewAction.setEnabled(querySelected);
  }

  private String mapLanguageToSyntaxHighlighting(final String language)
  {
    if ("beanshell".equals(language))
    {
      return SyntaxConstants.SYNTAX_STYLE_JAVA;
    }
    if ("groovy".equals(language))
    {
      return SyntaxConstants.SYNTAX_STYLE_GROOVY;
    }
    if ("javascript".equals(language))
    {
      return SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT;
    }
    if ("jython".equals(language))
    {
      return SyntaxConstants.SYNTAX_STYLE_PYTHON;
    }
    if ("xslt".equals(language))
    {
      return SyntaxConstants.SYNTAX_STYLE_XML;
    }

    return SyntaxConstants.SYNTAX_STYLE_NONE;
  }
}
TOP

Related Classes of org.pentaho.reporting.ui.datasources.scriptable.ScriptableDataSourceEditor$ScriptablePreviewWorker

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.