View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 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.teststeps;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Toolkit;
18  import java.awt.event.ActionEvent;
19  import java.awt.event.KeyAdapter;
20  import java.awt.event.KeyEvent;
21  import java.awt.event.MouseAdapter;
22  import java.awt.event.MouseEvent;
23  import java.beans.PropertyChangeEvent;
24  import java.beans.PropertyChangeListener;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import javax.swing.AbstractAction;
29  import javax.swing.AbstractListModel;
30  import javax.swing.Action;
31  import javax.swing.JComponent;
32  import javax.swing.JLabel;
33  import javax.swing.JList;
34  import javax.swing.JPanel;
35  import javax.swing.JPopupMenu;
36  import javax.swing.JScrollPane;
37  import javax.swing.ListCellRenderer;
38  import javax.swing.SwingUtilities;
39  import javax.swing.event.ListSelectionEvent;
40  import javax.swing.event.ListSelectionListener;
41  import javax.swing.event.PopupMenuEvent;
42  import javax.swing.event.PopupMenuListener;
43  
44  import com.eviware.soapui.SoapUI;
45  import com.eviware.soapui.impl.support.actions.ShowOnlineHelpAction;
46  import com.eviware.soapui.impl.wsdl.support.HelpUrls;
47  import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
48  import com.eviware.soapui.model.testsuite.Assertable;
49  import com.eviware.soapui.model.testsuite.AssertionError;
50  import com.eviware.soapui.model.testsuite.AssertionsListener;
51  import com.eviware.soapui.model.testsuite.TestAssertion;
52  import com.eviware.soapui.support.UISupport;
53  import com.eviware.soapui.support.action.swing.ActionList;
54  import com.eviware.soapui.support.action.swing.ActionListBuilder;
55  import com.eviware.soapui.support.action.swing.ActionSupport;
56  import com.eviware.soapui.support.components.JXToolBar;
57  
58  /***
59   * Seperate panel for holding/managing assertions
60   * 
61   * @author ole.matzura
62   */
63  
64  public class AssertionsPanel extends JPanel
65  {
66  	private AssertionListModel assertionListModel;
67  	private JList assertionList;
68  	private JPopupMenu assertionListPopup;
69  	private final Assertable assertable;
70  	private AddAssertionAction addAssertionAction;
71  	private ConfigureAssertionAction configureAssertionAction;
72  	private RemoveAssertionAction removeAssertionAction;
73  
74  	public AssertionsPanel( Assertable assertable )
75  	{
76  		super( new BorderLayout() );
77  		this.assertable = assertable;
78  		
79        assertionListModel = new AssertionListModel();
80        assertionList = new JList( assertionListModel );
81        assertionList.setToolTipText( "Assertions for this request" );
82        assertionList.setCellRenderer( new AssertionCellRenderer() );
83        
84        assertionListPopup = new JPopupMenu();
85        addAssertionAction = new AddAssertionAction( assertable );
86  		assertionListPopup.add( addAssertionAction);
87        
88        assertionListPopup.addPopupMenuListener( new PopupMenuListener(){
89  
90           public void popupMenuWillBecomeVisible(PopupMenuEvent e)
91           {
92              while( assertionListPopup.getComponentCount() > 1 ) 
93                 assertionListPopup.remove( 1 );
94              
95              int ix = assertionList.getSelectedIndex();
96              if( ix == -1 ) 
97              {
98              	assertionListPopup.addSeparator();
99              	assertionListPopup.add( new ShowOnlineHelpAction( HelpUrls.RESPONSE_ASSERTIONS_HELP_URL ) );
100             	return;
101             }
102             
103             TestAssertion assertion = assertionListModel.getAssertionAt( ix );
104             ActionSupport.addActions( 
105             			ActionListBuilder.buildActions( assertion ), assertionListPopup );
106          }
107 
108          public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
109          {
110          }
111 
112          public void popupMenuCanceled(PopupMenuEvent e)
113          {
114          }});
115       
116       assertionList.setComponentPopupMenu( assertionListPopup );
117       
118       assertionList.addMouseListener( new MouseAdapter() {
119 
120 			public void mouseClicked(MouseEvent e)
121          {
122             if( e.getClickCount() < 2 ) return;
123 
124             int ix = assertionList.getSelectedIndex();
125             if( ix == -1 ) return;
126             
127             Object obj = assertionList.getModel().getElementAt( ix );
128             if( obj instanceof TestAssertion )
129             {
130             	TestAssertion assertion = (TestAssertion) obj;
131 	            if( assertion.isConfigurable() )
132 	               assertion.configure();
133 	            
134 	            return;
135             }
136             
137    		   if( obj instanceof AssertionError )
138    		   {
139    		   	AssertionError error = (AssertionError) obj;
140    		   	if( error.getLineNumber() >= 0 )
141    		   	{
142    		   		selectError(error);
143    		   	}
144    		   	else Toolkit.getDefaultToolkit().beep();
145    		   }
146    		   else Toolkit.getDefaultToolkit().beep();
147          }});
148       
149       assertionList.addKeyListener( new KeyAdapter() 
150       {
151       	public void keyPressed(KeyEvent e)
152    		{
153       		int ix = assertionList.getSelectedIndex();
154             if( ix == -1 ) return;
155             
156             TestAssertion assertion = assertionListModel.getAssertionAt( ix );
157             if( e.getKeyChar() == KeyEvent.VK_ENTER )
158             {
159 	            if( assertion.isConfigurable() )
160 	               assertion.configure();
161             }
162             else
163             {
164 					ActionList actions = ActionListBuilder.buildActions( assertion );
165 					if( actions != null )
166 					{
167 						actions.dispatchKeyEvent( e );
168 					}
169             }
170    		}
171       } );
172       
173       add( new JScrollPane( assertionList ), BorderLayout.CENTER );
174       add( buildToolbar(), BorderLayout.NORTH );
175    }
176 	
177 	private JComponent buildToolbar()
178 	{
179 		configureAssertionAction = new ConfigureAssertionAction();
180 		removeAssertionAction = new RemoveAssertionAction();
181 		
182 		JXToolBar toolbar = UISupport.createToolbar();
183 		addToolbarButtons( toolbar );
184 		
185 		toolbar.addGlue();
186 		toolbar.add( new ShowOnlineHelpAction( HelpUrls.REQUEST_ASSERTIONS_HELP_URL ));
187 		
188 		assertionList.addListSelectionListener( new ListSelectionListener() {
189 
190 			public void valueChanged( ListSelectionEvent e )
191 			{
192 				int ix = assertionList.getSelectedIndex();
193 				
194 				configureAssertionAction.setEnabled( ix >= 0 );
195 				removeAssertionAction.setEnabled( ix >= 0 );
196 				
197             if( ix == -1 ) return;
198             TestAssertion assertion = assertionListModel.getAssertionAt( ix );
199 				configureAssertionAction.setEnabled( assertion != null && assertion.isConfigurable() );	
200 			}} );
201 		
202 		return toolbar;
203 	}
204 
205 	protected void addToolbarButtons( JXToolBar toolbar )
206 	{
207 		toolbar.addFixed( UISupport.createToolbarButton( addAssertionAction ));
208 		toolbar.addFixed( UISupport.createToolbarButton( configureAssertionAction ));
209 		toolbar.addFixed( UISupport.createToolbarButton( removeAssertionAction ));
210 	}
211 
212 	public void setEnabled( boolean enabled )
213 	{
214 		assertionList.setEnabled( enabled );
215 	}
216 
217    protected void selectError(AssertionError error)
218 	{
219 	}
220    
221 	private static class AssertionCellRenderer extends JLabel implements ListCellRenderer 
222    {
223       public Component getListCellRendererComponent(
224         JList list,
225         Object value,           
226         int index,               
227         boolean isSelected,      
228         boolean cellHasFocus)    
229       {
230       	setEnabled(list.isEnabled());
231       	
232       	if( value instanceof TestAssertion )
233       	{
234       		TestAssertion assertion = (TestAssertion) value;
235       		setText( assertion.getLabel() + " - " + assertion.getStatus().toString() );
236             setIcon( assertion.getIcon() );
237             
238             if( assertion.isDisabled() && isEnabled() )
239             	setEnabled( false );
240       	}
241       	else if( value instanceof AssertionError )
242       	{
243             AssertionError assertion = (AssertionError) value;
244             setText( " -> " + assertion.toString() );
245             setIcon( null );
246       	}
247       	else if( value instanceof String )
248       	{
249       		setText( value.toString() );
250       	}
251       	
252           if (isSelected) 
253           {
254              setBackground(list.getSelectionBackground());
255              setForeground(list.getSelectionForeground());
256           }
257           else 
258           {
259              setBackground(list.getBackground());
260              setForeground(list.getForeground());
261           }
262           
263           setFont(list.getFont());
264           setOpaque(true);
265           
266           return this;
267       }
268   }
269    
270    private class AssertionListModel extends AbstractListModel implements PropertyChangeListener, 
271        AssertionsListener
272    {
273    	private List<Object> items = new ArrayList<Object>();
274    	
275       public AssertionListModel()
276       {
277       	init();
278       }
279       
280       public int getSize()
281       {
282       	return items.size();
283       }
284 
285       public Object getElementAt(int index)
286       {
287       	return index >= items.size() ? null : items.get( index );
288       }
289 
290       public TestAssertion getAssertionAt( int index )
291       {
292       	Object object = items.get( index );
293       	while( !(object instanceof TestAssertion) && index > 0 )
294       	{
295       		object = items.get( --index );
296       	}
297       	
298       	return (TestAssertion) ((object instanceof TestAssertion) ? object : null);
299       }
300       
301       public void refresh()
302       {
303       	synchronized( this )
304 			{
305 				release();
306 	      	init();
307 	         fireContentsChanged( this, 0, getSize()-1 );
308 			}
309       }
310 
311 		private void init()
312 		{
313       	assertable.addAssertionsListener( this );
314 			
315          for( int c = 0; c < assertable.getAssertionCount(); c++ )
316          {
317          	TestAssertion assertion = assertable.getAssertionAt( c );
318          	addAssertion(assertion);
319          }
320 		}
321 		
322 		public void release()
323 		{
324          items.clear();
325 
326          for( int c = 0; c < assertable.getAssertionCount(); c++ )
327          {
328          	TestAssertion assertion = assertable.getAssertionAt( c );
329          	assertion.removePropertyChangeListener( this );
330          }
331          
332          assertable.removeAssertionsListener( this );
333 		}
334 
335 		public synchronized void propertyChange(PropertyChangeEvent evt)
336 		{
337 			if( SwingUtilities.isEventDispatchThread() )
338 				refresh();
339 			else SwingUtilities.invokeLater( new Runnable() {
340 
341 				public void run()
342 				{
343 					refresh();
344 				}} );			
345 		}
346 
347 		public void assertionAdded(TestAssertion assertion)
348 		{
349 			synchronized( this )
350 			{
351 				int sz = getSize();
352 				addAssertion(assertion);
353       	
354 				fireIntervalAdded( this, sz, items.size()-1 );
355 			}
356 		}
357 
358 		private void addAssertion(TestAssertion assertion)
359 		{
360 			assertion.addPropertyChangeListener( this );
361       	items.add( assertion );
362       	
363       	AssertionError[] errors = assertion.getErrors();
364       	if( errors != null)
365       	{
366       		for( int i = 0; i < errors.length; i++ )
367       		items.add( errors[i] );
368       	}
369 		}
370 
371 		public void assertionRemoved(TestAssertion assertion)
372 		{
373 			synchronized( this )
374 			{
375 				int ix = items.indexOf( assertion );
376 				if( ix == -1 ) return;
377 	
378 				assertion.removePropertyChangeListener( this );
379 				items.remove( ix );
380 				fireIntervalRemoved( this, ix, ix );
381 				
382 				// remove associated errors
383 				while( ix < items.size() && items.get( ix ) instanceof AssertionError )
384 				{
385 					items.remove( ix );
386 					fireIntervalRemoved( this, ix, ix );
387 				}
388 			}
389 		}
390    }
391 
392 	public void release()
393 	{
394 		assertionListModel.release();
395 	}
396 	
397 	public class ConfigureAssertionAction extends AbstractAction
398    {
399       ConfigureAssertionAction()
400       {
401       	super( "Configure" );
402       	putValue( Action.SHORT_DESCRIPTION, "Configures the selection assertion" );
403       	putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/options.gif" ));
404       	setEnabled( false );
405       }
406 
407       public void actionPerformed( ActionEvent e )
408       {
409       	int ix = assertionList.getSelectedIndex();
410          if( ix == -1 ) return;
411          
412          TestAssertion assertion = assertionListModel.getAssertionAt( ix );
413          if( assertion.isConfigurable() )
414          {
415             assertion.configure();
416          }
417 		   else Toolkit.getDefaultToolkit().beep();
418       }
419    }
420 
421    public class RemoveAssertionAction extends AbstractAction
422    {
423       public RemoveAssertionAction()
424       {
425       	super( "Remove Assertion" );
426       	putValue( Action.SHORT_DESCRIPTION, "Removes the selected assertion from this LoadTest" );
427       	putValue( Action.SMALL_ICON, UISupport.createImageIcon( "/remove_assertion.gif" ));
428       	setEnabled( false );
429       }
430 
431       public void actionPerformed( ActionEvent e )
432       {
433       	int ix = assertionList.getSelectedIndex();
434          if( ix == -1 ) return;
435          
436          TestAssertion assertion = assertionListModel.getAssertionAt( ix );
437          if( UISupport.confirm( "Remove assertion [" + assertion.getName() + "]", "Remove Assertion"))
438          {
439          	assertable.removeAssertion( assertion );
440          }
441       }
442    }
443 }