View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.panels.loadtest;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.event.ActionEvent;
18  import java.awt.event.ItemEvent;
19  import java.awt.event.ItemListener;
20  import java.awt.event.MouseAdapter;
21  import java.awt.event.MouseEvent;
22  import java.text.SimpleDateFormat;
23  import java.util.ArrayList;
24  import java.util.Date;
25  import java.util.List;
26  
27  import javax.swing.AbstractAction;
28  import javax.swing.Action;
29  import javax.swing.BorderFactory;
30  import javax.swing.Icon;
31  import javax.swing.ImageIcon;
32  import javax.swing.JButton;
33  import javax.swing.JComboBox;
34  import javax.swing.JComponent;
35  import javax.swing.JLabel;
36  import javax.swing.JPanel;
37  import javax.swing.JPopupMenu;
38  import javax.swing.JScrollPane;
39  import javax.swing.JTable;
40  import javax.swing.event.ListDataEvent;
41  import javax.swing.event.ListDataListener;
42  import javax.swing.event.TableModelEvent;
43  import javax.swing.event.TableModelListener;
44  import javax.swing.table.AbstractTableModel;
45  import javax.swing.table.DefaultTableCellRenderer;
46  import javax.swing.table.TableColumnModel;
47  
48  import org.jdesktop.swingx.JXTable;
49  import org.jdesktop.swingx.decorator.Filter;
50  import org.jdesktop.swingx.decorator.FilterPipeline;
51  import org.jdesktop.swingx.decorator.PatternFilter;
52  import org.jdesktop.swingx.decorator.SortOrder;
53  
54  import com.eviware.soapui.impl.wsdl.loadtest.LoadTestAssertion;
55  import com.eviware.soapui.impl.wsdl.loadtest.data.actions.ExportLoadTestLogAction;
56  import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLog;
57  import com.eviware.soapui.impl.wsdl.loadtest.log.LoadTestLogEntry;
58  import com.eviware.soapui.model.testsuite.TestStep;
59  import com.eviware.soapui.support.UISupport;
60  import com.eviware.soapui.support.action.swing.ActionList;
61  import com.eviware.soapui.support.action.swing.ActionSupport;
62  import com.eviware.soapui.support.components.JXToolBar;
63  import com.jgoodies.forms.builder.ButtonBarBuilder;
64  
65  /***
66   * Compound component for showing a LoadTestLog
67   * 
68   * @author Ole.Matzura
69   */
70  
71  public class JLoadTestLogTable extends JPanel
72  {
73  	private final LoadTestLog loadTestLog;
74  	private JXTable logTable;
75  	private PatternFilter stepFilter;
76  	private PatternFilter typeFilter;
77  	private JComboBox typesFilterComboBox;
78  	private JComboBox stepsFilterComboBox;
79  	private JButton clearErrorsButton;
80  	private JLabel rowCountLabel;
81  	@SuppressWarnings( "unused" )
82  	private JPopupMenu popup;
83  	private LoadTestLogTableModel logTableModel;
84  	private JButton exportButton;
85  	private LogTableModelListener logTableModelListener;
86  
87  	public JLoadTestLogTable( LoadTestLog log )
88  	{
89  		super( new BorderLayout() );
90  
91  		loadTestLog = log;
92  
93  		logTableModel = new LoadTestLogTableModel();
94  		logTable = new JXTable( logTableModel );
95  		logTable.setHorizontalScrollEnabled( true );
96  		logTable.setColumnControlVisible( true );
97  		logTable.addMouseListener( new LoadTestLogTableMouseListener() );
98  
99  		TableColumnModel columnModel = logTable.getColumnModel();
100 		columnModel.getColumn( 0 ).setMaxWidth( 5 );
101 		columnModel.getColumn( 0 ).setCellRenderer( new IconTableCellRenderer() );
102 
103 		columnModel.getColumn( 1 ).setPreferredWidth( 120 );
104 		columnModel.getColumn( 1 ).setCellRenderer( new TimestampTableCellRenderer() );
105 
106 		columnModel.getColumn( 2 ).setPreferredWidth( 110 );
107 		columnModel.getColumn( 3 ).setPreferredWidth( 110 );
108 		columnModel.getColumn( 4 ).setPreferredWidth( 250 );
109 
110 		typeFilter = new PatternFilter( ".*", 0, 2 );
111 		typeFilter.setAcceptNull( true );
112 		stepFilter = new PatternFilter( ".*", 0, 3 );
113 		stepFilter.setAcceptNull( true );
114 
115 		Filter[] filters = new Filter[] { typeFilter, // regex, matchflags, column
116 				stepFilter // regex, matchflags, column
117 		};
118 
119 		FilterPipeline pipeline = new FilterPipeline( filters );
120 		logTable.setFilters( pipeline );
121 
122 		JScrollPane scrollPane = new JScrollPane( logTable );
123 		add( scrollPane, BorderLayout.CENTER );
124 		add( buildToolbar(), BorderLayout.NORTH );
125 		add( buildStatus(), BorderLayout.SOUTH );
126 
127 		logTableModelListener = new LogTableModelListener();
128 		logTable.getModel().addTableModelListener( logTableModelListener );
129 
130 		logTable.setSortOrder( 1, SortOrder.ASCENDING );
131 	}
132 
133 	public void addNotify()
134 	{
135 		super.addNotify();
136 		if( logTableModelListener != null )
137 			logTableModel.addTableModelListener( logTableModelListener );
138 
139 		loadTestLog.addListDataListener( logTableModel );
140 	}
141 
142 	public void removeNotify()
143 	{
144 		super.removeNotify();
145 		logTableModel.removeTableModelListener( logTableModelListener );
146 		loadTestLog.removeListDataListener( logTableModel );
147 	}
148 
149 	private JComponent buildStatus()
150 	{
151 		ButtonBarBuilder builder = new ButtonBarBuilder();
152 		rowCountLabel = new JLabel( "0 entries" );
153 		builder.addFixed( rowCountLabel );
154 		builder.addGlue();
155 		builder.setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
156 		return builder.getPanel();
157 	}
158 
159 	protected void updateRowCountLabel()
160 	{
161 		int c = logTableModel.getRowCount();
162 		rowCountLabel.setText( c == 1 ? "1 entry" : c + " entries" );
163 	}
164 
165 	private JComponent buildToolbar()
166 	{
167 		JXToolBar toolbar = UISupport.createToolbar();
168 
169 		clearErrorsButton = UISupport.createToolbarButton( new ClearErrorsAction() );
170 		exportButton = UISupport.createToolbarButton( new ExportLoadTestLogAction( loadTestLog, logTable ) );
171 
172 		toolbar.add( clearErrorsButton );
173 		toolbar.add( exportButton );
174 		toolbar.addGlue();
175 
176 		List<Object> steps = new ArrayList<Object>();
177 		steps.add( "- All -" );
178 		steps.add( "Message" );
179 		for( LoadTestAssertion assertion : loadTestLog.getLoadTest().getAssertionList() )
180 		{
181 			steps.add( assertion.getName() );
182 		}
183 
184 		toolbar.add( new JLabel( "Show Types:" ) );
185 		toolbar.addSeparator();
186 		typesFilterComboBox = new JComboBox( steps.toArray() );
187 		typesFilterComboBox.addItemListener( new ItemListener()
188 		{
189 
190 			public void itemStateChanged( ItemEvent e )
191 			{
192 				int ix = typesFilterComboBox.getSelectedIndex();
193 				if( ix == -1 )
194 					return;
195 
196 				typeFilter.setAcceptNull( ix == 0 );
197 
198 				if( ix == 0 )
199 					typeFilter.setPattern( ".*", 0 );
200 				else
201 					typeFilter.setPattern( typesFilterComboBox.getSelectedItem().toString(), 0 );
202 
203 				updateRowCountLabel();
204 			}
205 		} );
206 
207 		toolbar.add( typesFilterComboBox );
208 		toolbar.addSeparator();
209 
210 		List<Object> types = new ArrayList<Object>();
211 		types.add( "- All -" );
212 		for( TestStep testStep : loadTestLog.getLoadTest().getTestCase().getTestStepList() )
213 		{
214 			types.add( testStep.getName() );
215 		}
216 
217 		toolbar.addFixed( new JLabel( "Show Steps:" ) );
218 		toolbar.addSeparator();
219 		stepsFilterComboBox = new JComboBox( types.toArray() );
220 		stepsFilterComboBox.addItemListener( new ItemListener()
221 		{
222 
223 			public void itemStateChanged( ItemEvent e )
224 			{
225 				int ix = stepsFilterComboBox.getSelectedIndex();
226 				if( ix == -1 )
227 					return;
228 
229 				stepFilter.setAcceptNull( ix == 0 );
230 
231 				if( ix == 0 )
232 					stepFilter.setPattern( ".*", 0 );
233 				else
234 					stepFilter.setPattern( stepsFilterComboBox.getSelectedItem().toString(), 0 );
235 
236 				updateRowCountLabel();
237 			}
238 		} );
239 
240 		toolbar.addFixed( stepsFilterComboBox );
241 		// toolbar.setBorder( BorderFactory.createEmptyBorder( 0, 0, 2, 0 ));
242 
243 		return toolbar; // builder.getPanel();
244 	}
245 
246 	private final class LogTableModelListener implements TableModelListener
247 	{
248 		public void tableChanged( TableModelEvent e )
249 		{
250 			updateRowCountLabel();
251 		}
252 	}
253 
254 	/*
255 	 * 
256 	 * private class SelectStepFilterAction extends AbstractAction { private
257 	 * final String filter;
258 	 * 
259 	 * public SelectStepFilterAction(String name, String filter) { super(name);
260 	 * this.filter = filter; }
261 	 * 
262 	 * public void actionPerformed(ActionEvent e) { stepFilter.setPattern(
263 	 * filter, 0 ); } }
264 	 * 
265 	 * private class SelectTypeFilterAction extends AbstractAction { private
266 	 * final String filter;
267 	 * 
268 	 * public SelectTypeFilterAction(String name, String filter) { super(name);
269 	 * this.filter = filter; }
270 	 * 
271 	 * public void actionPerformed(ActionEvent e) { typeFilter.setPattern(
272 	 * filter, 0 ); } }
273 	 */
274 
275 	private class LoadTestLogTableModel extends AbstractTableModel implements ListDataListener
276 	{
277 		public LoadTestLogTableModel()
278 		{
279 		}
280 
281 		public int getRowCount()
282 		{
283 			return loadTestLog.getSize();
284 		}
285 
286 		public int getColumnCount()
287 		{
288 			return 5;
289 		}
290 
291 		public Class<?> getColumnClass( int columnIndex )
292 		{
293 			switch( columnIndex )
294 			{
295 			case 0 :
296 				return ImageIcon.class;
297 			case 1 :
298 				return Date.class;
299 			default :
300 				return String.class;
301 			}
302 		}
303 
304 		public String getColumnName( int column )
305 		{
306 			switch( column )
307 			{
308 			case 0 :
309 				return " ";
310 			case 1 :
311 				return "time";
312 			case 2 :
313 				return "type";
314 			case 3 :
315 				return "step";
316 			case 4 :
317 				return "message";
318 			}
319 
320 			return null;
321 		}
322 
323 		public Object getValueAt( int rowIndex, int columnIndex )
324 		{
325 			if( rowIndex == -1 )
326 				return null;
327 
328 			LoadTestLogEntry entry = ( LoadTestLogEntry )loadTestLog.getElementAt( rowIndex );
329 
330 			switch( columnIndex )
331 			{
332 			case 0 :
333 				return entry.getIcon();
334 			case 1 :
335 				return entry.getTimeStamp();
336 			case 2 :
337 				return entry.getType();
338 			case 3 :
339 				return entry.getTargetStepName();
340 			case 4 :
341 				return entry.getMessage();
342 			}
343 
344 			return null;
345 		}
346 
347 		public void intervalAdded( ListDataEvent e )
348 		{
349 			fireTableRowsInserted( e.getIndex0(), e.getIndex1() );
350 		}
351 
352 		public void intervalRemoved( ListDataEvent e )
353 		{
354 			fireTableRowsDeleted( e.getIndex0(), e.getIndex1() );
355 		}
356 
357 		public void contentsChanged( ListDataEvent e )
358 		{
359 			fireTableDataChanged();
360 		}
361 	}
362 
363 	private static final class IconTableCellRenderer extends DefaultTableCellRenderer
364 	{
365 		public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus,
366 				int row, int column )
367 		{
368 			if( value != null )
369 				setIcon( ( Icon )value );
370 
371 			if( isSelected )
372 			{
373 				setBackground( table.getSelectionBackground() );
374 				setForeground( table.getSelectionForeground() );
375 			}
376 			else
377 			{
378 				setBackground( table.getBackground() );
379 				setForeground( table.getForeground() );
380 			}
381 
382 			return this;
383 		}
384 	}
385 
386 	private static final class TimestampTableCellRenderer extends DefaultTableCellRenderer
387 	{
388 		private SimpleDateFormat sdf;
389 
390 		private TimestampTableCellRenderer()
391 		{
392 			sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss:SSS" );
393 		}
394 
395 		public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus,
396 				int row, int column )
397 		{
398 			if( value != null )
399 				setText( sdf.format( new Date( ( Long )value ) ) );
400 
401 			if( isSelected )
402 			{
403 				setBackground( table.getSelectionBackground() );
404 				setForeground( table.getSelectionForeground() );
405 			}
406 			else
407 			{
408 				setBackground( table.getBackground() );
409 				setForeground( table.getForeground() );
410 			}
411 
412 			return this;
413 		}
414 	}
415 
416 	public class ClearErrorsAction extends AbstractAction
417 	{
418 		public ClearErrorsAction()
419 		{
420 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_errors.gif" ) );
421 			putValue( Action.SHORT_DESCRIPTION, "Removes all errors from the LoadTest log" );
422 		}
423 
424 		public void actionPerformed( ActionEvent e )
425 		{
426 			loadTestLog.clearErrors();
427 		}
428 	}
429 
430 	private final class LoadTestLogTableMouseListener extends MouseAdapter
431 	{
432 		public void mouseClicked( MouseEvent e )
433 		{
434 			if( e.getClickCount() > 1 )
435 			{
436 				int selectedRow = logTable.getSelectedRow();
437 				if( selectedRow < 0 )
438 					return;
439 
440 				int row = logTable.convertRowIndexToModel( selectedRow );
441 				if( row < 0 )
442 					return;
443 
444 				LoadTestLogEntry entry = ( LoadTestLogEntry )loadTestLog.getElementAt( row );
445 				ActionList actions = entry.getActions();
446 				if( actions != null )
447 					actions.performDefaultAction( new ActionEvent( logTable, 0, null ) );
448 			}
449 		}
450 
451 		public void mousePressed( MouseEvent e )
452 		{
453 			if( e.isPopupTrigger() )
454 			{
455 				showPopup( e );
456 			}
457 		}
458 
459 		public void mouseReleased( MouseEvent e )
460 		{
461 			if( e.isPopupTrigger() )
462 			{
463 				showPopup( e );
464 			}
465 		}
466 	}
467 
468 	public void showPopup( MouseEvent e )
469 	{
470 		int selectedRow = logTable.rowAtPoint( e.getPoint() );
471 		if( selectedRow == -1 )
472 			return;
473 
474 		if( logTable.getSelectedRow() != selectedRow )
475 		{
476 			logTable.getSelectionModel().setSelectionInterval( selectedRow, selectedRow );
477 		}
478 
479 		int row = logTable.convertRowIndexToModel( selectedRow );
480 		if( row < 0 )
481 			return;
482 
483 		LoadTestLogEntry entry = ( LoadTestLogEntry )loadTestLog.getElementAt( row );
484 		ActionList actions = entry.getActions();
485 
486 		if( actions == null || actions.getActionCount() == 0 )
487 			return;
488 
489 		JPopupMenu popup = ActionSupport.buildPopup( actions );
490 		popup.setInvoker( logTable );
491 
492 		popup.setLocation( ( int )( logTable.getLocationOnScreen().getX() + e.getPoint().getX() ), ( int )( logTable
493 				.getLocationOnScreen().getY() + e.getPoint().getY() ) );
494 		popup.setVisible( true );
495 	}
496 }