View Javadoc

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