All Downloads are FREE. Search and download functionalities are using the official Maven repository.

kg.apc.jmeter.vizualizers.MergeResultsGui Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package kg.apc.jmeter.vizualizers;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellEditor;

import kg.apc.charting.GraphPanelChart;
import kg.apc.jmeter.JMeterPluginsUtils;
import kg.apc.jmeter.graphs.AbstractGraphPanelVisualizer;
import kg.apc.jmeter.vizualizers.CorrectedResultCollector;
import kg.apc.jmeter.vizualizers.JSettingsPanel;

import org.apache.jmeter.gui.GuiPackage;
import org.apache.jmeter.gui.SavePropertyDialog;
import org.apache.jmeter.gui.util.FilePanel;
import org.apache.jmeter.gui.util.MenuFactory;
import org.apache.jmeter.gui.util.PowerTableModel;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.apache.jmeter.testelement.property.NullProperty;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.ComponentUtil;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import org.jmeterplugins.save.MergeResultsService;

/**
 *
 * @author Felix Henry
 * @author Vincent Daburon
 */
public class MergeResultsGui extends AbstractGraphPanelVisualizer implements
        TableModelListener, CellEditorListener, ChangeListener, ActionListener {

    private static final long serialVersionUID = 240L;

    private static final Logger log = LoggingManager.getLoggerForClass();

    public static final String WIKIPAGE = "MergeResults";

    public static final String[] columnIdentifiers = new String[] {
            "Input File Name", "Prefix label", "Offset start (sec)",
            "Offset end (sec)", "Include label", "RegExp Inc.",
            "Exclude label", "RegExp Exc." };

    public static final Class[] columnClasses = { String.class,
            String.class, String.class, String.class, String.class,
            Boolean.class, String.class, Boolean.class };

    public static final Object[] defaultValues = { "", "", "", "", "", false,
            "", false };

    /** File Extensions */
    private static final String[] EXTS = { ".jtl", ".csv" }; // $NON-NLS-1$
                                                             // $NON-NLS-2$

    public static final String DEFAULT_FILENAME = "";
    public static final String FILENAME = "MergeResultsControlGui.filename"; // $NON-NLS-1$
    public static final String DATA_PROPERTY = "MergeResultsControlGui.data"; // $NON-NLS-1$

    public static final int INPUT_FILE_NAME = 0;
    public static final int PREFIX_LABEL = 1;
    public static final int OFFSET_START = 2;
    public static final int OFFSET_END = 3;
    public static final int INCLUDE_LABEL = 4;
    public static final int REGEX_INCLUDE = 5;
    public static final int EXCLUDE_LABEL = 6;
    public static final int REGEX_EXCLUDE = 7;

    private static final int MAX_FILE_HANDLES = 4;
    private static final long REF_START_TIME = 946681200000L; // 2000-01-01 00:00:00.000

    private static final String ACTION_ADD = "add"; // $NON-NLS-1$
    private static final String ACTION_COPY = "copy"; // $NON-NLS-1$
    private static final String ACTION_DELETE = "delete"; // $NON-NLS-1$
    private static final String ACTION_MERGE = "merge"; // $NON-NLS-1$
    private static final String ACTION_SAVE_CONFIG = "save_config"; // $NON-NLS-1$

    protected PowerTableModel tableModel;
    protected JTable grid;
    protected JButton addRowButton;
    protected JButton copyRowButton;
    protected JButton deleteRowButton;
    protected JButton mergeButton;
    private FilePanel mergeAndWritePanel;

    private String prefixLabel = "";

    private List samples = new ArrayList(0);
    private MergeResultsService mergeService;

    public MergeResultsGui() {
        super();
        init();
    }

    @Override
    public String getLabelResource() {
        return this.getClass().getSimpleName(); //$NON-NLS-1$
    }

    @Override
    public String getStaticLabel() {
        return JMeterPluginsUtils.prefixLabel("Merge Results");
    }

    @Override
    public Collection getMenuCategories() {
        return Arrays.asList(new String[] { MenuFactory.NON_TEST_ELEMENTS });
    }

    protected Component getMergeAndWritePanel() {
        return mergeAndWritePanel;
    }

    public void setFile(String filename) {
        mergeAndWritePanel.setFilename(filename);
    }

    public String getFile() {
        return mergeAndWritePanel.getFilename();
    }

    public String getWikiPage() {
        return "MergeResults";
    }

    /** Only for use in testing */
    public JTable getGrid() {
        return grid;
    }

    /**
     * Modifies a given TestElement to mirror the data in the gui components.
     *
     * @see org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(TestElement)
     */
    @Override
    public void modifyTestElement(TestElement c) {
        super.modifyTestElement(c);
        if (c instanceof ResultCollector) {
            ResultCollector rc = (ResultCollector) c;
            rc.setFilename(getFile());

            rc.setProperty(new StringProperty(
                    CorrectedResultCollector.FILENAME, getFile()));
            CollectionProperty rows = JMeterPluginsUtils
                    .tableModelRowsToCollectionProperty(tableModel,
                            DATA_PROPERTY);
            rc.setProperty(rows);
            collector = rc;
        }
    }

    @Override
    public void configure(TestElement el) {
        super.configure(el);
        setFile(el.getPropertyAsString(CorrectedResultCollector.FILENAME));
        JMeterProperty fileValues = el.getProperty(DATA_PROPERTY);

        if (!(fileValues instanceof NullProperty)) {
            CollectionProperty columns = (CollectionProperty) fileValues;

            tableModel.removeTableModelListener(this);
            JMeterPluginsUtils.collectionPropertyToTableModelRows(columns,
                    tableModel, columnClasses);
            tableModel.addTableModelListener(this);
            updateUI();
        } else {
            log.warn("Received null property instead of collection");
        }
        checkDeleteButtonStatus();
        checkMergeButtonStatus();

        startTimeRef = 0;
    }

    @Override
    public void updateUI() {
        super.updateUI();

        if (tableModel != null) {
            CorrectedResultCollector crc = new CorrectedResultCollector();
            crc.setProperty(JMeterPluginsUtils
                    .tableModelRowsToCollectionPropertyEval(tableModel,
                            DATA_PROPERTY));
        }
    }

    private void init() {
        this.setLayout(new BorderLayout());

        // MAIN PANEL
        JPanel mainPanel = new JPanel();
        Border margin = new EmptyBorder(10, 10, 5, 10);

        mainPanel.setBorder(margin);
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        mainPanel.add(JMeterPluginsUtils.addHelpLinkToPanel(makeTitlePanel(),
                WIKIPAGE));

        JPanel containerPanel = new VerticalPanel();

        JButton saveConfigButton = new JButton(
                JMeterUtils.getResString("config_save_settings")); // $NON-NLS-1$
        saveConfigButton.addActionListener(this);
        saveConfigButton.setActionCommand(ACTION_SAVE_CONFIG);

        mergeAndWritePanel = new FilePanel(
                "Merge and write results to output file", EXTS); // $NON-NLS-1$
        mergeAndWritePanel.addChangeListener(this);
        mergeAndWritePanel.add(saveConfigButton);

        mergeButton = new JButton("Merge");
        mergeButton.addActionListener(this);
        mergeButton.setActionCommand(ACTION_MERGE);

        JPanel controlPanel = new JPanel();
        controlPanel.add(mergeButton);

        containerPanel.add(createParamsPanel());
        containerPanel.add(getMergeAndWritePanel());
        containerPanel.add(controlPanel);

        add(mainPanel, BorderLayout.NORTH);
        add(containerPanel, BorderLayout.CENTER);

        hideFilePanel();
        enableMaximize(false);
    }

    private boolean loadFilesFromTable(CorrectedResultCollector crc) {
        for (int row = 0; row < tableModel.getRowCount(); row++) {
            startTimeRef = 0;
            crc.setFilename(String.valueOf(tableModel.getValueAt(row,
                    INPUT_FILE_NAME)));
            if (crc.getFilename().isEmpty()) {
                GuiPackage.showErrorMessage(
                        "Error merging results files - could not open file [row: "
                                + row + ";filename: " + collector.getFilename()
                                + "]", "Input file error");
                return false;
            }
            crc.setStartOffset(String.valueOf(tableModel.getValueAt(row,
                    OFFSET_START)));
            crc.setEndOffset(String.valueOf(tableModel.getValueAt(row,
                    OFFSET_END)));
            crc.setIncludeLabels(String.valueOf(tableModel.getValueAt(row,
                    INCLUDE_LABEL)));
            crc.setExcludeLabels(String.valueOf(tableModel.getValueAt(row,
                    EXCLUDE_LABEL)));
            crc.setEnabledIncludeRegex(Boolean.valueOf(String
                    .valueOf((tableModel.getValueAt(row, REGEX_INCLUDE)))));
            crc.setEnabledExcludeRegex(Boolean.valueOf(String
                    .valueOf((tableModel.getValueAt(row, REGEX_EXCLUDE)))));
            crc.setPrefixLabel(String.valueOf((tableModel.getValueAt(row,
                    PREFIX_LABEL))));
            setUpFiltering(crc);
            crc.loadExistingFile();
        }
        return true;
    }

    @Override
    public void add(SampleResult res) {
        if (!isSampleIncluded(res)) {
            return;
        }

        res.setSaveConfig(collector.getSaveConfig());
        if (!prefixLabel.isEmpty()) {
            String resLabel = res.getSampleLabel();
            res.setSampleLabel(prefixLabel + resLabel);
        }
        res.setTimeStamp(res.getTimeStamp() - startTimeRef + REF_START_TIME);
        samples.add(res);
    }

    @Override
    public void setUpFiltering(CorrectedResultCollector rc) {
        super.setUpFiltering(rc);
        prefixLabel = rc.getPrefixLabel(CorrectedResultCollector.PREFIX_LABEL);
    }

    protected JPanel createParamsPanel() {
        JPanel panel = new JPanel(new BorderLayout(5, 5));
        panel.setBorder(BorderFactory.createTitledBorder("Merge Options"));
        panel.setPreferredSize(new Dimension(200, 200));

        JScrollPane scroll = new JScrollPane(createGrid());
        scroll.setPreferredSize(scroll.getMinimumSize());

        JPanel buttonsPanel = new JPanel(new GridLayout(1, 2));
        addRowButton = new JButton("Add Row");
        copyRowButton = new JButton("Copy Row");
        deleteRowButton = new JButton("Delete Row");

        addRowButton.addActionListener(this);
        addRowButton.setActionCommand(ACTION_ADD);
        copyRowButton.addActionListener(this);
        copyRowButton.setActionCommand(ACTION_COPY);
        deleteRowButton.addActionListener(this);
        deleteRowButton.setActionCommand(ACTION_DELETE);

        buttonsPanel.add(addRowButton);
        buttonsPanel.add(copyRowButton);
        buttonsPanel.add(deleteRowButton);

        panel.add(scroll, BorderLayout.CENTER);
        panel.add(buttonsPanel, BorderLayout.SOUTH);

        return panel;
    }

    public void actionPerformed(ActionEvent action) {
        String command = action.getActionCommand();

        if (grid.isEditing()) {
            TableCellEditor cellEditor = grid.getCellEditor(
                    grid.getEditingRow(), grid.getEditingColumn());
            cellEditor.stopCellEditing();
        }

        if (command.equals(ACTION_ADD)) {
            tableModel.addRow(defaultValues);
            tableModel.fireTableDataChanged();

            if (tableModel.getRowCount() >= MAX_FILE_HANDLES) {
                addRowButton.setEnabled(false);
                copyRowButton.setEnabled(false);
            }
            // Enable DELETE and MERGE
            deleteRowButton.setEnabled(true);
            mergeButton.setEnabled(true);

            // Highlight (select) the appropriate row.
            int rowToSelect = tableModel.getRowCount() - 1;
            if (rowToSelect < grid.getRowCount()) {
                grid.setRowSelectionInterval(rowToSelect, rowToSelect);
            }
            updateUI();

        } else if (command.equals(ACTION_COPY)) {
            final int selectedRow = grid.getSelectedRow();

            if (tableModel.getRowCount() == 0 || selectedRow < 0) {
                return;
            }

            tableModel.addRow(tableModel.getRowData(selectedRow));
            tableModel.fireTableDataChanged();

            if (tableModel.getRowCount() >= MAX_FILE_HANDLES) {
                addRowButton.setEnabled(false);
                copyRowButton.setEnabled(false);
            }
            // Enable DELETE and MERGE
            deleteRowButton.setEnabled(true);
            mergeButton.setEnabled(true);

            // Highlight (select) the appropriate row.
            int rowToSelect = selectedRow + 1;
            grid.setRowSelectionInterval(rowToSelect, rowToSelect);
            updateUI();

        } else if (command.equals(ACTION_DELETE)) {
            final int rowSelected = grid.getSelectedRow();
            if (rowSelected >= 0) {
                tableModel.removeRow(rowSelected);
                tableModel.fireTableDataChanged();

                if (tableModel.getRowCount() < MAX_FILE_HANDLES) {
                    addRowButton.setEnabled(true);
                    copyRowButton.setEnabled(true);
                }
                // Disable DELETE and MERGE if there are no rows in the
                // table to delete.
                if (tableModel.getRowCount() == 0) {
                    deleteRowButton.setEnabled(false);
                    mergeButton.setEnabled(false);
                }
                // Table still contains one or more rows, so highlight
                // (select) the appropriate one.
                else {
                    int rowToSelect = rowSelected;

                    if (rowSelected >= tableModel.getRowCount()) {
                        rowToSelect = rowSelected - 1;
                    }

                    grid.setRowSelectionInterval(rowToSelect, rowToSelect);
                }
                updateUI();
            }

        } else if (command.equals(ACTION_MERGE)) {
            String output = getFile();
            if (output.isEmpty()) {
                GuiPackage.showErrorMessage(
                        "Error merging results files - empty output filename",
                        "Output file error");
                return;
            }
            boolean isSuccess = loadFilesFromTable((CorrectedResultCollector) collector);

            if (isSuccess) {
                mergeService = new MergeResultsService();
                collector.setFilename(output);
                mergeService.mergeSamples((CorrectedResultCollector) collector,
                        samples);
            }
            samples.clear();

        } else if (command.equals(ACTION_SAVE_CONFIG)) {
            SavePropertyDialog d = new SavePropertyDialog(GuiPackage
                    .getInstance().getMainFrame(),
                    JMeterUtils
                            .getResString("sample_result_save_configuration"), // $NON-NLS-1$
                    true, collector.getSaveConfig());
            d.pack();
            ComponentUtil.centerComponentInComponent(GuiPackage.getInstance()
                    .getMainFrame(), d);
            d.setVisible(true);
        }
    }

    public void checkDeleteButtonStatus() {
        deleteRowButton.setEnabled(tableModel != null
                && tableModel.getRowCount() > 0);
    }

    public void checkMergeButtonStatus() {
        mergeButton.setEnabled(tableModel != null
                && tableModel.getRowCount() > 0);
    }

    private JTable createGrid() {
        grid = new JTable();
        grid.getDefaultEditor(String.class).addCellEditorListener(this);
        createTableModel();
        grid.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        grid.setMinimumSize(new Dimension(200, 100));

        return grid;
    }

    private void createTableModel() {
        tableModel = new PowerTableModel(columnIdentifiers, columnClasses);
        tableModel.addTableModelListener(this);
        grid.setModel(tableModel);
    }

    public void tableChanged(TableModelEvent e) {
        // log.info("Model changed");
        updateUI();
    }

    public void editingStopped(ChangeEvent e) {
        // log.info("Editing stopped");
        updateUI();
    }

    public void editingCanceled(ChangeEvent e) {
        // no action needed
    }

    @Override
    public void stateChanged(ChangeEvent e) {
        log.debug("getting new collector");
        collector = (ResultCollector) createTestElement();
    }

    @Override
    public Dimension getPreferredSize() {
        return getMinimumSize();
    }

    /**
     * Implements JMeterGUIComponent.clearGui
     */
    @Override
    public void clearGui() {
        super.clearGui();
        tableModel.clearData();
        mergeAndWritePanel.clearGui();
    }

    @Override
    protected JSettingsPanel createSettingsPanel() {
        return new JSettingsPanel(this, 0);
    }

    @Override
    public GraphPanelChart getGraphPanelChart() {
        return new FakeGraphPanelChart();
    }

    private class FakeGraphPanelChart extends GraphPanelChart {

        public FakeGraphPanelChart() {
            super(false);
        }

        @Override
        public void saveGraphToCSV(File file) throws IOException {
            log.info("Saving CSV to " + file.getAbsolutePath());
            mergeService = new MergeResultsService();
            collector.setFilename(file.getName());
            mergeService.mergeSamples((CorrectedResultCollector) collector,
                    samples);
        }

        @Override
        public void saveGraphToPNG(File file, int w, int h) throws IOException {
            throw new UnsupportedOperationException(
                    "This plugin type cannot be saved as image");
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy