/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI 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 at gnu.org.
*/
package com.eviware.soapui.impl.wsdl.panels.loadtest;
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.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
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 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 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.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.jgoodies.forms.builder.ButtonBarBuilder;
/**
* 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 = new JXTable( 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 SimpleDateFormat sdf;
private TimestampTableCellRenderer()
{
sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss:SSS" );
}
public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column )
{
if( value != null )
setText( sdf.format( 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 );
}
}