View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.addMouseListener( new LoadTestLogTableMouseListener() );
97  		
98  		TableColumnModel columnModel = logTable.getColumnModel();
99  		columnModel.getColumn( 0 ).setMaxWidth( 5 );
100 		columnModel.getColumn( 0 ).setCellRenderer( new IconTableCellRenderer() );
101 		
102 		columnModel.getColumn( 1 ).setPreferredWidth( 120 );
103 		columnModel.getColumn( 1 ).setCellRenderer( new TimestampTableCellRenderer() );
104 		
105 		columnModel.getColumn( 2 ).setPreferredWidth( 110 );
106 		columnModel.getColumn( 3 ).setPreferredWidth( 110 );
107 		columnModel.getColumn( 4 ).setPreferredWidth( 250 );
108 		
109 		typeFilter = new PatternFilter(".*", 0, 2);
110 		typeFilter.setAcceptNull( true );
111 		stepFilter = new PatternFilter(".*", 0, 3);
112 		stepFilter.setAcceptNull( true );
113 
114 		Filter[]   filters = new Filter[] {
115 		      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 			public void itemStateChanged(ItemEvent e)
190 			{
191 				int ix = typesFilterComboBox.getSelectedIndex();
192 				if( ix == -1 )
193 					return;
194 				
195 				typeFilter.setAcceptNull( ix == 0 );
196 				
197 				if( ix == 0 )
198 					typeFilter.setPattern( ".*", 0 );
199 				else
200 					typeFilter.setPattern( typesFilterComboBox.getSelectedItem().toString(), 0 );
201 				
202 				updateRowCountLabel();
203 			}} );
204 		
205 		toolbar.add( typesFilterComboBox );
206 		toolbar.addSeparator();
207 		
208 		List<Object> types = new ArrayList<Object>();
209 		types.add( "- All -" );
210 		for( TestStep testStep : loadTestLog.getLoadTest().getTestCase().getTestStepList() )
211 		{
212 			types.add( testStep.getName() );
213 		}
214 		
215 		toolbar.addFixed( new JLabel( "Show Steps:"));
216 		toolbar.addSeparator();
217 		stepsFilterComboBox = new JComboBox( types.toArray() );
218 		stepsFilterComboBox.addItemListener( new ItemListener()  {
219 
220 			public void itemStateChanged(ItemEvent e)
221 			{
222 				int ix = stepsFilterComboBox.getSelectedIndex();
223 				if( ix == -1 )
224 					return;
225 				
226 				stepFilter.setAcceptNull( ix == 0 );
227 				
228 				if( ix == 0 )
229 					stepFilter.setPattern( ".*", 0 );
230 				else
231 					stepFilter.setPattern( stepsFilterComboBox.getSelectedItem().toString(), 0 );
232 				
233 				updateRowCountLabel();
234 			}} );
235 		
236 		toolbar.addFixed( stepsFilterComboBox );
237 //		toolbar.setBorder( BorderFactory.createEmptyBorder( 0, 0, 2, 0 ));
238 		
239 		return toolbar; //builder.getPanel();
240 	}
241 
242 	private final class LogTableModelListener implements TableModelListener
243 	{
244 		public void tableChanged(TableModelEvent e)
245 		{
246 			updateRowCountLabel();
247 		}
248 	}
249 	
250 	/*
251 
252 	private class SelectStepFilterAction extends AbstractAction
253 	{
254 		private final String filter;
255 
256 		public SelectStepFilterAction(String name, String filter)
257 		{
258 			super(name);
259 			this.filter = filter;
260 		}
261 
262 		public void actionPerformed(ActionEvent e)
263 		{
264 			stepFilter.setPattern( filter, 0 );
265 		}
266 	}
267 	
268 	private class SelectTypeFilterAction extends AbstractAction
269 	{
270 		private final String filter;
271 
272 		public SelectTypeFilterAction(String name, String filter)
273 		{
274 			super(name);
275 			this.filter = filter;
276 		}
277 
278 		public void actionPerformed(ActionEvent e)
279 		{
280 			typeFilter.setPattern( filter, 0 );
281 		}
282 	}
283 	*/
284 	
285 	private class LoadTestLogTableModel extends AbstractTableModel implements ListDataListener
286 	{
287 		public LoadTestLogTableModel()
288 		{
289 		}
290 		
291 		public int getRowCount()
292 		{
293 			return loadTestLog.getSize();
294 		}
295 
296 		public int getColumnCount()
297 		{
298 			return 5;
299 		}
300 		
301 		public Class<?> getColumnClass(int columnIndex)
302 		{
303 			switch( columnIndex )
304 			{
305 			case 0 : return ImageIcon.class;
306 			case 1 : return Date.class;
307 			default : return String.class;
308 			}
309 		}
310 
311 		public String getColumnName(int column)
312 		{
313 			switch( column )
314 			{
315 			case 0 : return " ";
316 			case 1 : return "time"; 
317 			case 2 : return "type";
318 			case 3 : return "step";
319 			case 4 : return "message";
320 			}
321 			
322 			return null;
323 		}
324 
325 		public Object getValueAt(int rowIndex, int columnIndex)
326 		{
327 			if( rowIndex == -1 )
328 				return null;
329 			
330 			LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( rowIndex );
331 			
332 			switch( columnIndex )
333 			{
334 				case 0 : return entry.getIcon();
335 				case 1 : return entry.getTimeStamp();
336 				case 2 : return entry.getType();
337 				case 3 : return entry.getTargetStepName();
338 				case 4 : return entry.getMessage();
339 			}
340 
341 			return null;
342 		}
343 
344 		public void intervalAdded(ListDataEvent e)
345 		{
346 			fireTableRowsInserted( e.getIndex0(), e.getIndex1() );
347 		}
348 
349 		public void intervalRemoved(ListDataEvent e)
350 		{
351 			fireTableRowsDeleted( e.getIndex0(), e.getIndex1() );
352 		}
353 
354 		public void contentsChanged(ListDataEvent e)
355 		{
356 			fireTableDataChanged();
357 		}}
358 
359 	private static final class IconTableCellRenderer extends DefaultTableCellRenderer
360 	{
361 		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
362 		{
363 			if( value != null )
364 				setIcon( (Icon) value );
365 			
366 			if (isSelected) 
367          {
368             setBackground(table.getSelectionBackground());
369             setForeground(table.getSelectionForeground());
370          }
371          else 
372          {
373             setBackground(table.getBackground());
374             setForeground(table.getForeground());
375          }
376 			
377 			return this;
378 		}
379 	}
380 	
381 	private static final class TimestampTableCellRenderer extends DefaultTableCellRenderer
382 	{
383 		private SimpleDateFormat sdf;
384 
385       private TimestampTableCellRenderer()
386       {
387          sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
388       }
389 		
390 		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
391 		{
392 			if( value != null )
393 				setText( sdf.format( new Date( (Long)value ))); 
394 			
395 			if (isSelected) 
396          {
397             setBackground(table.getSelectionBackground());
398             setForeground(table.getSelectionForeground());
399          }
400          else 
401          {
402             setBackground(table.getBackground());
403             setForeground(table.getForeground());
404          }
405 			
406 			return this;
407 		}
408 	}
409 	
410    public class ClearErrorsAction extends AbstractAction
411    {
412 		public ClearErrorsAction()
413       {
414          putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/clear_errors.gif"));
415          putValue( Action.SHORT_DESCRIPTION, "Removes all errors from the LoadTest log" );
416       }
417 
418 		public void actionPerformed(ActionEvent e)
419 		{
420 			loadTestLog.clearErrors();
421 		}
422    }
423    
424    private final class LoadTestLogTableMouseListener extends MouseAdapter
425 	{
426    	public void mouseClicked(MouseEvent e)
427 		{
428 			if( e.getClickCount() > 1 )
429 			{
430 				int selectedRow = logTable.getSelectedRow();
431 				if( selectedRow < 0 )
432 					return;
433 				
434 				int row = logTable.convertRowIndexToModel( selectedRow );
435 				if( row < 0 )
436 					return;
437 				
438 				LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( row );
439 				ActionList actions = entry.getActions();
440 				if( actions != null )
441 					actions.performDefaultAction( new ActionEvent( logTable, 0, null ));
442 			}
443 		}
444    	
445 		public void mousePressed(MouseEvent e)
446 		{
447 			if( e.isPopupTrigger() )
448 			{
449 				showPopup( e );
450 			}
451 		}
452 
453 		public void mouseReleased(MouseEvent e)
454 		{
455 			if( e.isPopupTrigger() )
456 			{
457 				showPopup( e );
458 			}
459 		}
460 	}
461    
462    public void showPopup(MouseEvent e)
463 	{
464 		int selectedRow = logTable.rowAtPoint( e.getPoint() );
465 		if( selectedRow == -1 )
466 			return;
467 		
468 		if( logTable.getSelectedRow() != selectedRow )
469 		{
470 			logTable.getSelectionModel().setSelectionInterval( selectedRow, selectedRow );
471 		}
472 		
473 		int row = logTable.convertRowIndexToModel( selectedRow );
474 		if( row < 0 )
475 			return;
476 		
477 		LoadTestLogEntry entry = (LoadTestLogEntry) loadTestLog.getElementAt( row );
478 		ActionList actions = entry.getActions();
479 		
480 		if( actions == null || actions.getActionCount() == 0 )
481 			return;
482 		
483 		JPopupMenu popup = ActionSupport.buildPopup( actions );
484 		popup.setInvoker( logTable );
485 		
486 		popup.setLocation( (int)(logTable.getLocationOnScreen().getX() + e.getPoint().getX()), 
487 				(int)(logTable.getLocationOnScreen().getY() + e.getPoint().getY()));
488 		popup.setVisible( true );
489 	}
490 }