/*
* SoapUI, Copyright (C) 2004-2016 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.impl.wsdl.panels.loadtest;
import com.eviware.soapui.impl.wsdl.loadtest.LoadTestAssertion;
import com.eviware.soapui.impl.wsdl.loadtest.data.actions.ExportLoadTestLogAction;
import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLogEntry;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.support.DateUtil;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.action.swing.ActionList;
import com.eviware.soapui.support.action.swing.ActionSupport;
import com.eviware.soapui.support.components.JXToolBar;
import com.eviware.soapui.support.swing.JTableFactory;
import com.jgoodies.forms.builder.ButtonBarBuilder;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.Filter;
import org.jdesktop.swingx.decorator.FilterPipeline;
import org.jdesktop.swingx.decorator.PatternFilter;
import org.jdesktop.swingx.decorator.SortOrder;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Compound component for showing a LoadTestLog
*
* @author Ole.Matzura
*/
public class JLoadTestLogTable extends JPanel {
private final LoadTestLog loadTestLog;
private JXTable logTable;
private PatternFilter stepFilter;
private PatternFilter typeFilter;
private JComboBox typesFilterComboBox;
private JComboBox stepsFilterComboBox;
private JButton clearErrorsButton;
private JLabel rowCountLabel;
@SuppressWarnings("unused")
private JPopupMenu popup;
private LoadTestLogTableModel logTableModel;
private JButton exportButton;
private LogTableModelListener logTableModelListener;
public JLoadTestLogTable(LoadTestLog log) {
super(new BorderLayout());
loadTestLog = log;
logTableModel = new LoadTestLogTableModel();
logTable = JTableFactory.getInstance().makeJXTable(logTableModel);
logTable.setHorizontalScrollEnabled(true);
logTable.setColumnControlVisible(true);
logTable.addMouseListener(new LoadTestLogTableMouseListener());
TableColumnModel columnModel = logTable.getColumnModel();
columnModel.getColumn(0).setMaxWidth(5);
columnModel.getColumn(0).setCellRenderer(new IconTableCellRenderer());
columnModel.getColumn(1).setPreferredWidth(120);
columnModel.getColumn(1).setCellRenderer(new TimestampTableCellRenderer());
columnModel.getColumn(2).setPreferredWidth(110);
columnModel.getColumn(3).setPreferredWidth(110);
columnModel.getColumn(4).setPreferredWidth(250);
typeFilter = new PatternFilter(".*", 0, 2);
typeFilter.setAcceptNull(true);
stepFilter = new PatternFilter(".*", 0, 3);
stepFilter.setAcceptNull(true);
Filter[] filters = new Filter[]{typeFilter, // regex, matchflags, column
stepFilter // regex, matchflags, column
};
FilterPipeline pipeline = new FilterPipeline(filters);
logTable.setFilters(pipeline);
JScrollPane scrollPane = new JScrollPane(logTable);
add(scrollPane, BorderLayout.CENTER);
add(buildToolbar(), BorderLayout.NORTH);
add(buildStatus(), BorderLayout.SOUTH);
logTableModelListener = new LogTableModelListener();
logTable.getModel().addTableModelListener(logTableModelListener);
logTable.setSortOrder(1, SortOrder.ASCENDING);
}
public void addNotify() {
super.addNotify();
if (logTableModelListener != null) {
logTableModel.addTableModelListener(logTableModelListener);
}
loadTestLog.addListDataListener(logTableModel);
}
public void removeNotify() {
super.removeNotify();
logTableModel.removeTableModelListener(logTableModelListener);
loadTestLog.removeListDataListener(logTableModel);
}
private JComponent buildStatus() {
ButtonBarBuilder builder = new ButtonBarBuilder();
rowCountLabel = new JLabel("0 entries");
builder.addFixed(rowCountLabel);
builder.addGlue();
builder.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
return builder.getPanel();
}
protected void updateRowCountLabel() {
int c = logTableModel.getRowCount();
rowCountLabel.setText(c == 1 ? "1 entry" : c + " entries");
}
private JComponent buildToolbar() {
JXToolBar toolbar = UISupport.createToolbar();
clearErrorsButton = UISupport.createToolbarButton(new ClearErrorsAction());
exportButton = UISupport.createToolbarButton(new ExportLoadTestLogAction(loadTestLog, logTable));
toolbar.add(clearErrorsButton);
toolbar.add(exportButton);
toolbar.addGlue();
List<Object> steps = new ArrayList<Object>();
steps.add("- All -");
steps.add("Message");
for (LoadTestAssertion assertion : loadTestLog.getLoadTest().getAssertionList()) {
steps.add(assertion.getName());
}
toolbar.add(new JLabel("Show Types:"));
toolbar.addSeparator();
typesFilterComboBox = new JComboBox(steps.toArray());
typesFilterComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
int ix = typesFilterComboBox.getSelectedIndex();
if (ix == -1) {
return;
}
typeFilter.setAcceptNull(ix == 0);
if (ix == 0) {
typeFilter.setPattern(".*", 0);
} else {
typeFilter.setPattern(typesFilterComboBox.getSelectedItem().toString(), 0);
}
updateRowCountLabel();
}
});
toolbar.add(typesFilterComboBox);
toolbar.addSeparator();
List<Object> types = new ArrayList<Object>();
types.add("- All -");
for (TestStep testStep : loadTestLog.getLoadTest().getTestCase().getTestStepList()) {
types.add(testStep.getName());
}
toolbar.addFixed(new JLabel("Show Steps:"));
toolbar.addSeparator();
stepsFilterComboBox = new JComboBox(types.toArray());
stepsFilterComboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
int ix = stepsFilterComboBox.getSelectedIndex();
if (ix == -1) {
return;
}
stepFilter.setAcceptNull(ix == 0);
if (ix == 0) {
stepFilter.setPattern(".*", 0);
} else {
stepFilter.setPattern(stepsFilterComboBox.getSelectedItem().toString(), 0);
}
updateRowCountLabel();
}
});
toolbar.addFixed(stepsFilterComboBox);
// toolbar.setBorder( BorderFactory.createEmptyBorder( 0, 0, 2, 0 ));
return toolbar; // builder.getPanel();
}
private final class LogTableModelListener implements TableModelListener {
public void tableChanged(TableModelEvent e) {
updateRowCountLabel();
}
}
/*
*
* private class SelectStepFilterAction extends AbstractAction { private
* final String filter;
*
* public SelectStepFilterAction(String name, String filter) { super(name);
* this.filter = filter; }
*
* public void actionPerformed(ActionEvent e) { stepFilter.setPattern(
* filter, 0 ); } }
*
* private class SelectTypeFilterAction extends AbstractAction { private
* final String filter;
*
* public SelectTypeFilterAction(String name, String filter) { super(name);
* this.filter = filter; }
*
* public void actionPerformed(ActionEvent e) { typeFilter.setPattern(
* filter, 0 ); } }
*/
private class LoadTestLogTableModel extends AbstractTableModel implements ListDataListener {
public LoadTestLogTableModel() {
}
public int getRowCount() {
return loadTestLog.getSize();
}
public int getColumnCount() {
return 5;
}
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return ImageIcon.class;
case 1:
return Date.class;
default:
return String.class;
}
}
public String getColumnName(int column) {
switch (column) {
case 0:
return " ";
case 1:
return "time";
case 2:
return "type";
case 3:
return "step";
case 4:
return "message";
}
return null;
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex == -1) {
return null;
}
LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt(rowIndex);
switch (columnIndex) {
case 0:
return entry.getIcon();
case 1:
return entry.getTimeStamp();
case 2:
return entry.getType();
case 3:
return entry.getTargetStepName();
case 4:
return entry.getMessage();
}
return null;
}
public void intervalAdded(ListDataEvent e) {
fireTableRowsInserted(e.getIndex0(), e.getIndex1());
}
public void intervalRemoved(ListDataEvent e) {
fireTableRowsDeleted(e.getIndex0(), e.getIndex1());
}
public void contentsChanged(ListDataEvent e) {
fireTableDataChanged();
}
}
private static final class IconTableCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
if (value != null) {
setIcon((Icon) value);
}
if (isSelected) {
setBackground(table.getSelectionBackground());
setForeground(table.getSelectionForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return this;
}
}
private static final class TimestampTableCellRenderer extends DefaultTableCellRenderer {
private TimestampTableCellRenderer() {
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
if (value != null) {
setText(DateUtil.formatExtraFull(new Date((Long) value)));
}
if (isSelected) {
setBackground(table.getSelectionBackground());
setForeground(table.getSelectionForeground());
} else {
setBackground(table.getBackground());
setForeground(table.getForeground());
}
return this;
}
}
public class ClearErrorsAction extends AbstractAction {
public ClearErrorsAction() {
putValue(Action.SMALL_ICON, UISupport.createImageIcon("/clear_errors.gif"));
putValue(Action.SHORT_DESCRIPTION, "Removes all errors from the LoadTest log");
}
public void actionPerformed(ActionEvent e) {
loadTestLog.clearErrors();
}
}
private final class LoadTestLogTableMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() > 1) {
int selectedRow = logTable.getSelectedRow();
if (selectedRow < 0) {
return;
}
int row = logTable.convertRowIndexToModel(selectedRow);
if (row < 0) {
return;
}
LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt(row);
ActionList actions = entry.getActions();
if (actions != null) {
actions.performDefaultAction(new ActionEvent(logTable, 0, null));
}
}
}
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopup(e);
}
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showPopup(e);
}
}
}
public void showPopup(MouseEvent e) {
int selectedRow = logTable.rowAtPoint(e.getPoint());
if (selectedRow == -1) {
return;
}
if (logTable.getSelectedRow() != selectedRow) {
logTable.getSelectionModel().setSelectionInterval(selectedRow, selectedRow);
}
int row = logTable.convertRowIndexToModel(selectedRow);
if (row < 0) {
return;
}
LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt(row);
ActionList actions = entry.getActions();
if (actions == null || actions.getActionCount() == 0) {
return;
}
JPopupMenu popup = ActionSupport.buildPopup(actions);
popup.setInvoker(logTable);
popup.setLocation((int) (logTable.getLocationOnScreen().getX() + e.getPoint().getX()), (int) (logTable
.getLocationOnScreen().getY() + e.getPoint().getY()));
popup.setVisible(true);
}
}